diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c index cd7bc79..d82da44 100644 --- a/src/suunto_eonsteel.c +++ b/src/suunto_eonsteel.c @@ -35,7 +35,7 @@ typedef struct suunto_eonsteel_device_t { dc_device_t base; - dc_usbhid_t *usbhid; + dc_iostream_t *iostream; unsigned int model; unsigned int magic; unsigned short seq; @@ -141,7 +141,7 @@ static int receive_packet(suunto_eonsteel_device_t *eon, unsigned char *buffer, size_t transferred = 0; int len; - rc = dc_usbhid_read(eon->usbhid, buf, PACKET_SIZE, &transferred); + rc = dc_iostream_read(eon->iostream, buf, PACKET_SIZE, &transferred); if (rc != DC_STATUS_SUCCESS) { ERROR(eon->base.context, "read interrupt transfer failed"); return -1; @@ -207,7 +207,7 @@ static int send_cmd(suunto_eonsteel_device_t *eon, memcpy(buf+14, buffer, len); } - rc = dc_usbhid_write(eon->usbhid, buf, sizeof(buf), &transferred); + rc = dc_iostream_write(eon->iostream, buf, sizeof(buf), &transferred); if (rc != DC_STATUS_SUCCESS) { ERROR(eon->base.context, "write interrupt transfer failed"); return -1; @@ -523,20 +523,20 @@ static int initialize_eonsteel(suunto_eonsteel_device_t *eon) unsigned char buf[64]; struct eon_hdr hdr; - dc_usbhid_set_timeout(eon->usbhid, 10); + dc_iostream_set_timeout(eon->iostream, 10); /* Get rid of any pending stale input first */ for (;;) { size_t transferred = 0; - dc_status_t rc = dc_usbhid_read(eon->usbhid, buf, sizeof(buf), &transferred); + dc_status_t rc = dc_iostream_read(eon->iostream, buf, sizeof(buf), &transferred); if (rc != DC_STATUS_SUCCESS) break; if (!transferred) break; } - dc_usbhid_set_timeout(eon->usbhid, 5000); + dc_iostream_set_timeout(eon->iostream, 5000); if (send_cmd(eon, CMD_INIT, sizeof(init), init)) { ERROR(eon->base.context, "Failed to send initialization command"); @@ -580,7 +580,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, unsigned i } else { pid = 0x0030; } - status = dc_usbhid_open(&eon->usbhid, context, vid, pid); + status = dc_usbhid_open(&eon->iostream, context, vid, pid); if (status != DC_STATUS_SUCCESS) { ERROR(context, "unable to open device"); goto error_free; @@ -597,7 +597,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, unsigned i return DC_STATUS_SUCCESS; error_close: - dc_usbhid_close(eon->usbhid); + dc_iostream_close(eon->iostream); error_free: free(eon); return status; @@ -771,7 +771,7 @@ suunto_eonsteel_device_close(dc_device_t *abstract) { suunto_eonsteel_device_t *eon = (suunto_eonsteel_device_t *) abstract; - dc_usbhid_close(eon->usbhid); + dc_iostream_close(eon->iostream); return DC_STATUS_SUCCESS; } diff --git a/src/usbhid.c b/src/usbhid.c index 0dff237..c9435c8 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -50,8 +50,10 @@ #endif #include "usbhid.h" + #include "common-private.h" #include "context-private.h" +#include "iostream-private.h" #include "platform.h" #ifdef _WIN32 @@ -62,9 +64,17 @@ typedef pthread_mutex_t dc_mutex_t; #define DC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER #endif -struct dc_usbhid_t { - /* Library context. */ - dc_context_t *context; +#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_usbhid_vtable) + +#ifdef USBHID +static dc_status_t dc_usbhid_set_timeout (dc_iostream_t *iostream, int timeout); +static dc_status_t dc_usbhid_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual); +static dc_status_t dc_usbhid_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual); +static dc_status_t dc_usbhid_close (dc_iostream_t *iostream); + +typedef struct dc_usbhid_t { + /* Base class. */ + dc_iostream_t base; /* Internal state. */ #if defined(USE_LIBUSB) libusb_device_handle *handle; @@ -76,6 +86,25 @@ struct dc_usbhid_t { hid_device *handle; int timeout; #endif +} dc_usbhid_t; + +static const dc_iostream_vtable_t dc_usbhid_vtable = { + sizeof(dc_usbhid_t), + dc_usbhid_set_timeout, /* set_timeout */ + NULL, /* set_latency */ + NULL, /* set_halfduplex */ + NULL, /* set_break */ + NULL, /* set_dtr */ + NULL, /* set_rts */ + NULL, /* get_lines */ + NULL, /* get_received */ + NULL, /* configure */ + dc_usbhid_read, /* read */ + dc_usbhid_write, /* write */ + NULL, /* flush */ + NULL, /* purge */ + NULL, /* sleep */ + dc_usbhid_close, /* close */ }; #if defined(USE_LIBUSB) @@ -100,6 +129,7 @@ syserror(int errcode) } } #endif +#endif #ifdef USBHID static dc_mutex_t g_usbhid_mutex = DC_MUTEX_INIT; @@ -184,7 +214,7 @@ dc_usbhid_exit (void) #endif dc_status_t -dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsigned int pid) +dc_usbhid_open (dc_iostream_t **out, dc_context_t *context, unsigned int vid, unsigned int pid) { #ifdef USBHID dc_status_t status = DC_STATUS_SUCCESS; @@ -196,15 +226,12 @@ dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsi INFO (context, "Open: vid=%04x, pid=%04x", vid, pid); // Allocate memory. - usbhid = (dc_usbhid_t *) malloc (sizeof (dc_usbhid_t)); + usbhid = (dc_usbhid_t *) dc_iostream_allocate (context, &dc_usbhid_vtable); if (usbhid == NULL) { ERROR (context, "Out of memory."); return DC_STATUS_NOMEMORY; } - // Library context. - usbhid->context = context; - // Initialize the usb library. status = dc_usbhid_init (context); if (status != DC_STATUS_SUCCESS) { @@ -347,7 +374,7 @@ dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsi usbhid->timeout = -1; #endif - *out = usbhid; + *out = (dc_iostream_t *) usbhid; return DC_STATUS_SUCCESS; @@ -362,21 +389,19 @@ error_usb_free_list: error_usb_exit: dc_usbhid_exit (); error_free: - free (usbhid); + dc_iostream_deallocate ((dc_iostream_t *) usbhid); return status; #else return DC_STATUS_UNSUPPORTED; #endif } -dc_status_t -dc_usbhid_close (dc_usbhid_t *usbhid) -{ #ifdef USBHID +static dc_status_t +dc_usbhid_close (dc_iostream_t *abstract) +{ dc_status_t status = DC_STATUS_SUCCESS; - - if (usbhid == NULL) - return DC_STATUS_SUCCESS; + dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract; #if defined(USE_LIBUSB) libusb_release_interface (usbhid->handle, usbhid->interface); @@ -385,22 +410,14 @@ dc_usbhid_close (dc_usbhid_t *usbhid) hid_close(usbhid->handle); #endif dc_usbhid_exit(); - free (usbhid); return status; -#else - return DC_STATUS_UNSUPPORTED; -#endif } -dc_status_t -dc_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout) +static dc_status_t +dc_usbhid_set_timeout (dc_iostream_t *abstract, int timeout) { -#ifdef USBHID - if (usbhid == NULL) - return DC_STATUS_INVALIDARGS; - - INFO (usbhid->context, "Timeout: value=%i", timeout); + dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract; #if defined(USE_LIBUSB) if (timeout < 0) { @@ -419,27 +436,19 @@ dc_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout) #endif return DC_STATUS_SUCCESS; -#else - return DC_STATUS_UNSUPPORTED; -#endif } -dc_status_t -dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual) +static dc_status_t +dc_usbhid_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual) { -#ifdef USBHID dc_status_t status = DC_STATUS_SUCCESS; + dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract; int nbytes = 0; - if (usbhid == NULL) { - status = DC_STATUS_INVALIDARGS; - goto out_invalidargs; - } - #if defined(USE_LIBUSB) int rc = libusb_interrupt_transfer (usbhid->handle, usbhid->endpoint_in, data, size, &nbytes, usbhid->timeout); if (rc != LIBUSB_SUCCESS) { - ERROR (usbhid->context, "Usb read interrupt transfer failed (%s).", + ERROR (abstract->context, "Usb read interrupt transfer failed (%s).", libusb_error_name (rc)); status = syserror (rc); goto out; @@ -447,7 +456,7 @@ dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual) #elif defined(USE_HIDAPI) nbytes = hid_read_timeout(usbhid->handle, data, size, usbhid->timeout); if (nbytes < 0) { - ERROR (usbhid->context, "Usb read interrupt transfer failed."); + ERROR (abstract->context, "Usb read interrupt transfer failed."); status = DC_STATUS_IO; nbytes = 0; goto out; @@ -455,30 +464,19 @@ dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual) #endif out: - HEXDUMP (usbhid->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes); - -out_invalidargs: if (actual) *actual = nbytes; return status; -#else - return DC_STATUS_UNSUPPORTED; -#endif } -dc_status_t -dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *actual) +static dc_status_t +dc_usbhid_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual) { -#ifdef USBHID dc_status_t status = DC_STATUS_SUCCESS; + dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract; int nbytes = 0; - if (usbhid == NULL) { - status = DC_STATUS_INVALIDARGS; - goto out_invalidargs; - } - if (size == 0) { goto out; } @@ -496,7 +494,7 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act int rc = libusb_interrupt_transfer (usbhid->handle, usbhid->endpoint_out, (void *) buffer, length, &nbytes, 0); if (rc != LIBUSB_SUCCESS) { - ERROR (usbhid->context, "Usb write interrupt transfer failed (%s).", + ERROR (abstract->context, "Usb write interrupt transfer failed (%s).", libusb_error_name (rc)); status = syserror (rc); goto out; @@ -508,7 +506,7 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act #elif defined(USE_HIDAPI) nbytes = hid_write(usbhid->handle, data, size); if (nbytes < 0) { - ERROR (usbhid->context, "Usb write interrupt transfer failed."); + ERROR (abstract->context, "Usb write interrupt transfer failed."); status = DC_STATUS_IO; nbytes = 0; goto out; @@ -518,19 +516,14 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act out: #ifdef _WIN32 if (nbytes > size) { - WARNING (usbhid->context, "Number of bytes exceeds the buffer size (" DC_PRINTF_SIZE " > " DC_PRINTF_SIZE ")!", nbytes, size); + WARNING (abstract->context, "Number of bytes exceeds the buffer size (" DC_PRINTF_SIZE " > " DC_PRINTF_SIZE ")!", nbytes, size); nbytes = size; } #endif - HEXDUMP (usbhid->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, nbytes); - -out_invalidargs: if (actual) *actual = nbytes; return status; -#else - return DC_STATUS_UNSUPPORTED; -#endif } +#endif diff --git a/src/usbhid.h b/src/usbhid.h index 65d98c1..1e85f0a 100644 --- a/src/usbhid.h +++ b/src/usbhid.h @@ -24,20 +24,16 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -/** - * Opaque object representing a USB HID connection. - */ -typedef struct dc_usbhid_t dc_usbhid_t; - /** * Open a USB HID connection. * - * @param[out] usbhid A location to store the USB HID connection. + * @param[out] iostream A location to store the USB HID connection. * @param[in] context A valid context object. * @param[in] vid The USB Vendor ID of the device. * @param[in] pid The USB Product ID of the device. @@ -45,76 +41,7 @@ typedef struct dc_usbhid_t dc_usbhid_t; * on failure. */ dc_status_t -dc_usbhid_open (dc_usbhid_t **usbhid, dc_context_t *context, unsigned int vid, unsigned int pid); - -/** - * Close the connection and free all resources. - * - * @param[in] usbhid A valid USB HID connection. - * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code - * on failure. - */ -dc_status_t -dc_usbhid_close (dc_usbhid_t *usbhid); - -/** - * Set the read timeout. - * - * There are three distinct modes available: - * - * 1. Blocking (timeout < 0): - * - * The read operation is blocked until all the requested bytes have - * been received. If the requested number of bytes does not arrive, - * the operation will block forever. - * - * 2. Non-blocking (timeout == 0): - * - * The read operation returns immediately with the bytes that have - * already been received, even if no bytes have been received. - * - * 3. Timeout (timeout > 0): - * - * The read operation is blocked until all the requested bytes have - * been received. If the requested number of bytes does not arrive - * within the specified amount of time, the operation will return - * with the bytes that have already been received. - * - * @param[in] usbhid A valid USB HID connection. - * @param[in] timeout The timeout in milliseconds. - * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code - * on failure. - */ -dc_status_t -dc_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout); - -/** - * Read data from the USB HID connection. - * - * @param[in] usbhid A valid USB HID connection. - * @param[out] data The memory buffer to read the data into. - * @param[in] size The number of bytes to read. - * @param[out] actual An (optional) location to store the actual - * number of bytes transferred. - * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code - * on failure. - */ -dc_status_t -dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual); - -/** - * Write data to the USB HID connection. - * - * @param[in] usbhid A valid USB HID connection. - * @param[in] data The memory buffer to write the data from. - * @param[in] size The number of bytes to write. - * @param[out] actual An (optional) location to store the actual - * number of bytes transferred. - * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code - * on failure. - */ -dc_status_t -dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *actual); +dc_usbhid_open (dc_iostream_t **iostream, dc_context_t *context, unsigned int vid, unsigned int pid); #ifdef __cplusplus } diff --git a/src/uwatec_g2.c b/src/uwatec_g2.c index 5f62f4b..5031055 100644 --- a/src/uwatec_g2.c +++ b/src/uwatec_g2.c @@ -39,7 +39,7 @@ typedef struct uwatec_g2_device_t { dc_device_t base; - dc_usbhid_t *usbhid; + dc_iostream_t *iostream; unsigned int timestamp; unsigned int devtime; dc_ticks_t systime; @@ -74,7 +74,7 @@ receive_data (uwatec_g2_device_t *device, dc_event_progress_t *progress, unsigne dc_status_t rc = DC_STATUS_SUCCESS; unsigned int len = 0; - rc = dc_usbhid_read (device->usbhid, buf, sizeof(buf), &transferred); + rc = dc_iostream_read (device->iostream, buf, sizeof(buf), &transferred); if (rc != DC_STATUS_SUCCESS) { ERROR (device->base.context, "read interrupt transfer failed"); return rc; @@ -126,7 +126,7 @@ uwatec_g2_transfer (uwatec_g2_device_t *device, const unsigned char command[], u buf[1] = csize; memcpy(buf + 2, command, csize); memset(buf + 2 + csize, 0, sizeof(buf) - (csize + 2)); - status = dc_usbhid_write (device->usbhid, buf, sizeof(buf), &transferred); + status = dc_iostream_write (device->iostream, buf, sizeof(buf), &transferred); if (status != DC_STATUS_SUCCESS) { ERROR (device->base.context, "Failed to send the command."); return status; @@ -196,7 +196,7 @@ uwatec_g2_device_open (dc_device_t **out, dc_context_t *context, unsigned int mo } // Set the default values. - device->usbhid = NULL; + device->iostream = NULL; device->timestamp = 0; device->systime = (dc_ticks_t) -1; device->devtime = 0; @@ -210,7 +210,7 @@ uwatec_g2_device_open (dc_device_t **out, dc_context_t *context, unsigned int mo vid = 0x2e6c; pid = 0x3201; } - status = dc_usbhid_open (&device->usbhid, context, vid, pid); + status = dc_usbhid_open (&device->iostream, context, vid, pid); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to open USB device"); goto error_free; @@ -228,7 +228,7 @@ uwatec_g2_device_open (dc_device_t **out, dc_context_t *context, unsigned int mo return DC_STATUS_SUCCESS; error_close: - dc_usbhid_close (device->usbhid); + dc_iostream_close (device->iostream); error_free: dc_device_deallocate ((dc_device_t *) device); return status; @@ -243,7 +243,7 @@ uwatec_g2_device_close (dc_device_t *abstract) dc_status_t rc = DC_STATUS_SUCCESS; // Close the device. - rc = dc_usbhid_close (device->usbhid); + rc = dc_iostream_close (device->iostream); if (status != DC_STATUS_SUCCESS) { dc_status_set_error(&status, rc); }