Add 'usbstorage' iostream

This ends up being just a file interface for dive computers that expose
their data as a filesystem that can be mounted.

Right now that's only the Garmin Descent Mk1, although technically the
Uemis Zurich also did that (but oddly, and the backend was never merged
into libdivecomputer).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2020-05-07 12:42:14 -07:00
parent cf104bb8de
commit 99c2ca7205
7 changed files with 124 additions and 1 deletions

View File

@ -99,6 +99,7 @@ static const transport_table_t g_transports[] = {
{"irda", DC_TRANSPORT_IRDA}, {"irda", DC_TRANSPORT_IRDA},
{"bluetooth", DC_TRANSPORT_BLUETOOTH}, {"bluetooth", DC_TRANSPORT_BLUETOOTH},
{"ble", DC_TRANSPORT_BLE}, {"ble", DC_TRANSPORT_BLE},
{"usbstorage",DC_TRANSPORT_USBSTORAGE},
}; };
const char * const char *
@ -537,6 +538,8 @@ dctool_iostream_open (dc_iostream_t **iostream, dc_context_t *context, dc_descri
return dctool_irda_open (iostream, context, descriptor, devname); return dctool_irda_open (iostream, context, descriptor, devname);
case DC_TRANSPORT_BLUETOOTH: case DC_TRANSPORT_BLUETOOTH:
return dctool_bluetooth_open (iostream, context, descriptor, devname); return dctool_bluetooth_open (iostream, context, descriptor, devname);
case DC_TRANSPORT_USBSTORAGE:
return dc_usb_storage_open (iostream, context, devname);
default: default:
return DC_STATUS_UNSUPPORTED; return DC_STATUS_UNSUPPORTED;
} }

View File

@ -48,9 +48,13 @@ typedef enum dc_transport_t {
DC_TRANSPORT_USBHID = (1 << 2), DC_TRANSPORT_USBHID = (1 << 2),
DC_TRANSPORT_IRDA = (1 << 3), DC_TRANSPORT_IRDA = (1 << 3),
DC_TRANSPORT_BLUETOOTH = (1 << 4), DC_TRANSPORT_BLUETOOTH = (1 << 4),
DC_TRANSPORT_BLE = (1 << 5) DC_TRANSPORT_BLE = (1 << 5),
DC_TRANSPORT_USBSTORAGE= (1 << 6),
} dc_transport_t; } dc_transport_t;
// Idiotic enums can't be queried
#define DC_TRANSPORT_USBSTORAGE DC_TRANSPORT_USBSTORAGE
typedef enum dc_family_t { typedef enum dc_family_t {
DC_FAMILY_NULL = 0, DC_FAMILY_NULL = 0,
/* Suunto */ /* Suunto */

View File

@ -310,6 +310,9 @@ dc_iostream_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
dc_status_t dc_status_t
dc_iostream_close (dc_iostream_t *iostream); dc_iostream_close (dc_iostream_t *iostream);
dc_status_t
dc_usb_storage_open (dc_iostream_t **out, dc_context_t *context, const char *name);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@ -77,6 +77,7 @@ libdivecomputer_la_SOURCES = \
irda.c \ irda.c \
usbhid.c \ usbhid.c \
bluetooth.c \ bluetooth.c \
usb_storage.c \
custom.c custom.c
if OS_WIN32 if OS_WIN32

View File

@ -334,6 +334,7 @@ dc_context_get_transports (dc_context_t *context)
#elif defined(HAVE_LIBUSB) && !defined(__APPLE__) #elif defined(HAVE_LIBUSB) && !defined(__APPLE__)
| DC_TRANSPORT_USBHID | DC_TRANSPORT_USBHID
#endif #endif
| DC_TRANSPORT_USBSTORAGE
#ifdef _WIN32 #ifdef _WIN32
#ifdef HAVE_AF_IRDA_H #ifdef HAVE_AF_IRDA_H
| DC_TRANSPORT_IRDA | DC_TRANSPORT_IRDA

View File

@ -76,6 +76,8 @@ dc_usbhid_device_free
dc_usbhid_iterator_new dc_usbhid_iterator_new
dc_usbhid_open dc_usbhid_open
dc_usb_storage_open
dc_custom_open dc_custom_open
dc_parser_new dc_parser_new

109
src/usb_storage.c Normal file
View File

@ -0,0 +1,109 @@
/*
* Dummy "stream" operations for USB storage
*
* Copyright (C) 2018 Linus Torvalds
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "common-private.h"
#include "context-private.h"
#include "iostream-private.h"
#include "iterator-private.h"
#include "descriptor-private.h"
#include "timer.h"
// Fake "device" that just contains the directory name that
// you can read out of the iostream. All the actual IO is
// up to you.
typedef struct dc_usbstorage_t {
dc_iostream_t base;
char pathname[PATH_MAX];
} dc_usbstorage_t;
static dc_status_t
dc_usb_storage_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
static const dc_iostream_vtable_t dc_usbstorage_vtable = {
sizeof(dc_usbstorage_t),
NULL, /* set_timeout */
NULL, /* set_latency */
NULL, /* set_break */
NULL, /* set_dtr */
NULL, /* set_rts */
NULL, /* get_lines */
NULL, /* get_available */
NULL, /* configure */
dc_usb_storage_read, /* read */
NULL, /* write */
NULL, /* flush */
NULL, /* purge */
NULL, /* sleep */
NULL, /* close */
};
dc_status_t
dc_usb_storage_open (dc_iostream_t **out, dc_context_t *context, const char *name)
{
dc_usbstorage_t *device = NULL;
struct stat st;
if (out == NULL || name == NULL)
return DC_STATUS_INVALIDARGS;
INFO (context, "Open: name=%s", name);
if (stat(name, &st) < 0 || !S_ISDIR(st.st_mode))
return DC_STATUS_NODEVICE;
// Allocate memory.
device = (dc_usbstorage_t *) dc_iostream_allocate (context, &dc_usbstorage_vtable, DC_TRANSPORT_USBSTORAGE);
if (device == NULL) {
SYSERROR (context, ENOMEM);
return DC_STATUS_NOMEMORY;
}
strncpy(device->pathname, name, PATH_MAX);
device->pathname[PATH_MAX-1] = 0;
*out = (dc_iostream_t *) device;
return DC_STATUS_SUCCESS;
}
static dc_status_t
dc_usb_storage_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual)
{
dc_usbstorage_t *device = (dc_usbstorage_t *) iostream;
size_t len = strlen(device->pathname);
if (size <= len)
return DC_STATUS_IO;
memcpy(data, device->pathname, len+1);
if (actual)
*actual = len;
return DC_STATUS_SUCCESS;
}