diff --git a/examples/common.c b/examples/common.c index d8c7262..ba22eaf 100644 --- a/examples/common.c +++ b/examples/common.c @@ -99,6 +99,7 @@ static const transport_table_t g_transports[] = { {"irda", DC_TRANSPORT_IRDA}, {"bluetooth", DC_TRANSPORT_BLUETOOTH}, {"ble", DC_TRANSPORT_BLE}, + {"usbstorage",DC_TRANSPORT_USBSTORAGE}, }; 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); case DC_TRANSPORT_BLUETOOTH: return dctool_bluetooth_open (iostream, context, descriptor, devname); + case DC_TRANSPORT_USBSTORAGE: + return dc_usb_storage_open (iostream, context, devname); default: return DC_STATUS_UNSUPPORTED; } diff --git a/include/libdivecomputer/common.h b/include/libdivecomputer/common.h index 7f94f14..154bf12 100644 --- a/include/libdivecomputer/common.h +++ b/include/libdivecomputer/common.h @@ -48,9 +48,13 @@ typedef enum dc_transport_t { DC_TRANSPORT_USBHID = (1 << 2), DC_TRANSPORT_IRDA = (1 << 3), DC_TRANSPORT_BLUETOOTH = (1 << 4), - DC_TRANSPORT_BLE = (1 << 5) + DC_TRANSPORT_BLE = (1 << 5), + DC_TRANSPORT_USBSTORAGE= (1 << 6), } dc_transport_t; +// Idiotic enums can't be queried +#define DC_TRANSPORT_USBSTORAGE DC_TRANSPORT_USBSTORAGE + typedef enum dc_family_t { DC_FAMILY_NULL = 0, /* Suunto */ diff --git a/include/libdivecomputer/iostream.h b/include/libdivecomputer/iostream.h index b09cba1..7e60a73 100644 --- a/include/libdivecomputer/iostream.h +++ b/include/libdivecomputer/iostream.h @@ -310,6 +310,9 @@ dc_iostream_sleep (dc_iostream_t *iostream, unsigned int milliseconds); dc_status_t 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 } #endif /* __cplusplus */ diff --git a/src/Makefile.am b/src/Makefile.am index b21ef3b..cc71d1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,7 @@ libdivecomputer_la_SOURCES = \ irda.c \ usbhid.c \ bluetooth.c \ + usb_storage.c \ custom.c if OS_WIN32 diff --git a/src/context.c b/src/context.c index 63824a5..1e77d83 100644 --- a/src/context.c +++ b/src/context.c @@ -334,6 +334,7 @@ dc_context_get_transports (dc_context_t *context) #elif defined(HAVE_LIBUSB) && !defined(__APPLE__) | DC_TRANSPORT_USBHID #endif + | DC_TRANSPORT_USBSTORAGE #ifdef _WIN32 #ifdef HAVE_AF_IRDA_H | DC_TRANSPORT_IRDA diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index b17d60b..96fe6fe 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -76,6 +76,8 @@ dc_usbhid_device_free dc_usbhid_iterator_new dc_usbhid_open +dc_usb_storage_open + dc_custom_open dc_parser_new diff --git a/src/usb_storage.c b/src/usb_storage.c new file mode 100644 index 0000000..c667673 --- /dev/null +++ b/src/usb_storage.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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; +}