Convert Suunto EON Steel and Scubapro G2 to dc_usbhid_custom_io helper

This means that they still default to their respective USB devices, but
you can now set custom IO structure to pass in your own data.

Not only will we hopefully have some kind of BLE support, you could also
use this to simply emulate packets from a log-file by having a packet
replay (or by actually emulating a device).  Of course, you can already
do this by actually emulating the device in a virtual environment, but
it might be useful for some kind of libdivecomputer testing environment.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2017-06-18 15:19:22 +09:00
parent e590739260
commit b7699b6985
5 changed files with 34 additions and 45 deletions

View File

@ -125,10 +125,10 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
rc = suunto_d9_device_open (&device, context, name, dc_descriptor_get_model (descriptor));
break;
case DC_FAMILY_SUUNTO_EONSTEEL:
rc = suunto_eonsteel_device_open (&device, context);
rc = suunto_eonsteel_device_open (&device, context, name);
break;
case DC_FAMILY_SCUBAPRO_G2:
rc = scubapro_g2_device_open (&device, context);
rc = scubapro_g2_device_open (&device, context, name);
break;
case DC_FAMILY_UWATEC_ALADIN:
rc = uwatec_aladin_device_open (&device, context, name);

View File

@ -33,7 +33,6 @@
typedef struct scubapro_g2_device_t {
dc_device_t base;
dc_usbhid_t *usbhid;
unsigned int timestamp;
unsigned int devtime;
dc_ticks_t systime;
@ -61,13 +60,14 @@ scubapro_g2_extract_dives (dc_device_t *device, const unsigned char data[], unsi
#define PACKET_SIZE 64
static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int size)
{
dc_custom_io_t *io = _dc_context_custom_io(g2->base.context);
while (size) {
unsigned char buf[PACKET_SIZE];
size_t transferred = 0;
dc_status_t rc;
int len;
rc = dc_usbhid_read(g2->usbhid, buf, PACKET_SIZE, &transferred);
rc = io->packet_read(io, buf, PACKET_SIZE, &transferred);
if (rc != DC_STATUS_SUCCESS) {
ERROR(g2->base.context, "read interrupt transfer failed");
return -1;
@ -96,6 +96,7 @@ static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int siz
static dc_status_t
scubapro_g2_transfer(scubapro_g2_device_t *g2, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
{
dc_custom_io_t *io = _dc_context_custom_io(g2->base.context);
unsigned char buf[PACKET_SIZE];
dc_status_t status = DC_STATUS_SUCCESS;
size_t transferred = 0;
@ -109,7 +110,7 @@ scubapro_g2_transfer(scubapro_g2_device_t *g2, const unsigned char command[], un
buf[0] = csize;
memcpy(buf+1, command, csize);
status = dc_usbhid_write(g2->usbhid, buf, csize+1, &transferred);
status = io->packet_write(io, buf, csize+1, &transferred);
if (status != DC_STATUS_SUCCESS) {
ERROR(g2->base.context, "Failed to send the command.");
return status;
@ -162,7 +163,7 @@ scubapro_g2_handshake (scubapro_g2_device_t *device)
dc_status_t
scubapro_g2_device_open(dc_device_t **out, dc_context_t *context)
scubapro_g2_device_open(dc_device_t **out, dc_context_t *context, const char *name)
{
dc_status_t status = DC_STATUS_SUCCESS;
scubapro_g2_device_t *device = NULL;
@ -177,16 +178,20 @@ scubapro_g2_device_open(dc_device_t **out, dc_context_t *context)
return DC_STATUS_NOMEMORY;
}
// Set the default values.
device->usbhid = NULL;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
device->devtime = 0;
// Open the irda socket.
status = dc_usbhid_open(&device->usbhid, context, 0x2e6c, 0x3201);
dc_custom_io_t *io = _dc_context_custom_io(context);
if (io && io->packet_open)
status = io->packet_open(io, context, name);
else
status = dc_usbhid_custom_io(context, 0x2e6c, 0x3201);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open USB device");
ERROR (context, "Failed to open Scubapro G2 device");
goto error_free;
}
@ -202,7 +207,7 @@ scubapro_g2_device_open(dc_device_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
error_close:
dc_usbhid_close(device->usbhid);
scubapro_g2_device_close((dc_device_t *) device);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@ -212,11 +217,9 @@ error_free:
static dc_status_t
scubapro_g2_device_close (dc_device_t *abstract)
{
scubapro_g2_device_t *device = (scubapro_g2_device_t*) abstract;
dc_custom_io_t *io = _dc_context_custom_io(abstract->context);
dc_usbhid_close(device->usbhid);
return DC_STATUS_SUCCESS;
return io->packet_close(io);
}

View File

@ -31,7 +31,7 @@ extern "C" {
#endif /* __cplusplus */
dc_status_t
scubapro_g2_device_open (dc_device_t **device, dc_context_t *context);
scubapro_g2_device_open (dc_device_t **device, dc_context_t *context, const char *name);
#ifdef __cplusplus
}

View File

@ -35,7 +35,6 @@
typedef struct suunto_eonsteel_device_t {
dc_device_t base;
dc_usbhid_t *usbhid;
unsigned int magic;
unsigned short seq;
unsigned char version[0x30];
@ -130,10 +129,11 @@ static int receive_packet(suunto_eonsteel_device_t *eon, unsigned char *buffer,
{
unsigned char buf[64];
dc_status_t rc = DC_STATUS_SUCCESS;
dc_custom_io_t *io = _dc_context_custom_io(eon->base.context);
size_t transferred = 0;
int len;
rc = dc_usbhid_read(eon->usbhid, buf, PACKET_SIZE, &transferred);
rc = io->packet_read(io, buf, PACKET_SIZE, &transferred);
if (rc != DC_STATUS_SUCCESS) {
ERROR(eon->base.context, "read interrupt transfer failed");
return -1;
@ -168,6 +168,7 @@ static int send_cmd(suunto_eonsteel_device_t *eon,
unsigned char buf[64];
unsigned short seq = eon->seq;
unsigned int magic = eon->magic;
dc_custom_io_t *io = _dc_context_custom_io(eon->base.context);
dc_status_t rc = DC_STATUS_SUCCESS;
size_t transferred = 0;
@ -199,7 +200,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 = io->packet_write(io, buf, sizeof(buf), &transferred);
if (rc != DC_STATUS_SUCCESS) {
ERROR(eon->base.context, "write interrupt transfer failed");
return -1;
@ -462,7 +463,6 @@ static int get_file_list(suunto_eonsteel_device_t *eon, struct directory_entry *
unsigned char result[2048];
int rc, cmdlen;
*res = NULL;
put_le32(0, cmd);
memcpy(cmd + 4, dive_directory, sizeof(dive_directory));
@ -512,25 +512,8 @@ static int get_file_list(suunto_eonsteel_device_t *eon, struct directory_entry *
static int initialize_eonsteel(suunto_eonsteel_device_t *eon)
{
const unsigned char init[] = {0x02, 0x00, 0x2a, 0x00};
unsigned char buf[64];
struct eon_hdr hdr;
dc_usbhid_set_timeout(eon->usbhid, 10);
/* Get rid of any pending stale input first */
/* NOTE! This will cause an annoying warning from dc_usbhid_read() */
for (;;) {
size_t transferred = 0;
dc_status_t rc = dc_usbhid_read(eon->usbhid, buf, sizeof(buf), &transferred);
if (rc != DC_STATUS_SUCCESS)
break;
if (!transferred)
break;
}
dc_usbhid_set_timeout(eon->usbhid, 5000);
if (send_cmd(eon, INIT_CMD, sizeof(init), init)) {
ERROR(eon->base.context, "Failed to send initialization command");
return -1;
@ -548,7 +531,7 @@ static int initialize_eonsteel(suunto_eonsteel_device_t *eon)
}
dc_status_t
suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context)
suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, const char *name)
{
dc_status_t status = DC_STATUS_SUCCESS;
suunto_eonsteel_device_t *eon = NULL;
@ -566,7 +549,12 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context)
memset (eon->version, 0, sizeof (eon->version));
memset (eon->fingerprint, 0, sizeof (eon->fingerprint));
status = dc_usbhid_open(&eon->usbhid, context, 0x1493, 0x0030);
dc_custom_io_t *io = _dc_context_custom_io(eon->base.context);
if (io && io->packet_open)
status = io->packet_open(io, context, name);
else
status = dc_usbhid_custom_io(context, 0x1493, 0x0030);
if (status != DC_STATUS_SUCCESS) {
ERROR(context, "unable to open device");
goto error_free;
@ -583,7 +571,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
error_close:
dc_usbhid_close(eon->usbhid);
io->packet_close(io);
error_free:
free(eon);
return status;
@ -705,9 +693,7 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac
static dc_status_t
suunto_eonsteel_device_close(dc_device_t *abstract)
{
suunto_eonsteel_device_t *eon = (suunto_eonsteel_device_t *) abstract;
dc_custom_io_t *io = _dc_context_custom_io(abstract->context);
dc_usbhid_close(eon->usbhid);
return DC_STATUS_SUCCESS;
return io->packet_close(io);
}

View File

@ -31,7 +31,7 @@ extern "C" {
#endif /* __cplusplus */
dc_status_t
suunto_eonsteel_device_open(dc_device_t **device, dc_context_t *context);
suunto_eonsteel_device_open(dc_device_t **device, dc_context_t *context, const char *name);
dc_status_t
suunto_eonsteel_parser_create(dc_parser_t **parser, dc_context_t *context, unsigned int model);