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:
parent
e590739260
commit
b7699b6985
@ -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));
|
rc = suunto_d9_device_open (&device, context, name, dc_descriptor_get_model (descriptor));
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SUUNTO_EONSTEEL:
|
case DC_FAMILY_SUUNTO_EONSTEEL:
|
||||||
rc = suunto_eonsteel_device_open (&device, context);
|
rc = suunto_eonsteel_device_open (&device, context, name);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SCUBAPRO_G2:
|
case DC_FAMILY_SCUBAPRO_G2:
|
||||||
rc = scubapro_g2_device_open (&device, context);
|
rc = scubapro_g2_device_open (&device, context, name);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_UWATEC_ALADIN:
|
case DC_FAMILY_UWATEC_ALADIN:
|
||||||
rc = uwatec_aladin_device_open (&device, context, name);
|
rc = uwatec_aladin_device_open (&device, context, name);
|
||||||
|
|||||||
@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
typedef struct scubapro_g2_device_t {
|
typedef struct scubapro_g2_device_t {
|
||||||
dc_device_t base;
|
dc_device_t base;
|
||||||
dc_usbhid_t *usbhid;
|
|
||||||
unsigned int timestamp;
|
unsigned int timestamp;
|
||||||
unsigned int devtime;
|
unsigned int devtime;
|
||||||
dc_ticks_t systime;
|
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
|
#define PACKET_SIZE 64
|
||||||
static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int size)
|
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) {
|
while (size) {
|
||||||
unsigned char buf[PACKET_SIZE];
|
unsigned char buf[PACKET_SIZE];
|
||||||
size_t transferred = 0;
|
size_t transferred = 0;
|
||||||
dc_status_t rc;
|
dc_status_t rc;
|
||||||
int len;
|
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) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR(g2->base.context, "read interrupt transfer failed");
|
ERROR(g2->base.context, "read interrupt transfer failed");
|
||||||
return -1;
|
return -1;
|
||||||
@ -96,6 +96,7 @@ static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int siz
|
|||||||
static dc_status_t
|
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)
|
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];
|
unsigned char buf[PACKET_SIZE];
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
size_t transferred = 0;
|
size_t transferred = 0;
|
||||||
@ -109,7 +110,7 @@ scubapro_g2_transfer(scubapro_g2_device_t *g2, const unsigned char command[], un
|
|||||||
|
|
||||||
buf[0] = csize;
|
buf[0] = csize;
|
||||||
memcpy(buf+1, command, 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) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR(g2->base.context, "Failed to send the command.");
|
ERROR(g2->base.context, "Failed to send the command.");
|
||||||
return status;
|
return status;
|
||||||
@ -162,7 +163,7 @@ scubapro_g2_handshake (scubapro_g2_device_t *device)
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
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;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
scubapro_g2_device_t *device = NULL;
|
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;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set the default values.
|
// Set the default values.
|
||||||
device->usbhid = NULL;
|
|
||||||
device->timestamp = 0;
|
device->timestamp = 0;
|
||||||
device->systime = (dc_ticks_t) -1;
|
device->systime = (dc_ticks_t) -1;
|
||||||
device->devtime = 0;
|
device->devtime = 0;
|
||||||
|
|
||||||
// Open the irda socket.
|
dc_custom_io_t *io = _dc_context_custom_io(context);
|
||||||
status = dc_usbhid_open(&device->usbhid, context, 0x2e6c, 0x3201);
|
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) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (context, "Failed to open USB device");
|
ERROR (context, "Failed to open Scubapro G2 device");
|
||||||
goto error_free;
|
goto error_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +207,7 @@ scubapro_g2_device_open(dc_device_t **out, dc_context_t *context)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
error_close:
|
error_close:
|
||||||
dc_usbhid_close(device->usbhid);
|
scubapro_g2_device_close((dc_device_t *) device);
|
||||||
error_free:
|
error_free:
|
||||||
dc_device_deallocate ((dc_device_t *) device);
|
dc_device_deallocate ((dc_device_t *) device);
|
||||||
return status;
|
return status;
|
||||||
@ -212,11 +217,9 @@ error_free:
|
|||||||
static dc_status_t
|
static dc_status_t
|
||||||
scubapro_g2_device_close (dc_device_t *abstract)
|
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 io->packet_close(io);
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ extern "C" {
|
|||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
dc_status_t
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,6 @@
|
|||||||
|
|
||||||
typedef struct suunto_eonsteel_device_t {
|
typedef struct suunto_eonsteel_device_t {
|
||||||
dc_device_t base;
|
dc_device_t base;
|
||||||
dc_usbhid_t *usbhid;
|
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
unsigned short seq;
|
unsigned short seq;
|
||||||
unsigned char version[0x30];
|
unsigned char version[0x30];
|
||||||
@ -130,10 +129,11 @@ static int receive_packet(suunto_eonsteel_device_t *eon, unsigned char *buffer,
|
|||||||
{
|
{
|
||||||
unsigned char buf[64];
|
unsigned char buf[64];
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
|
dc_custom_io_t *io = _dc_context_custom_io(eon->base.context);
|
||||||
size_t transferred = 0;
|
size_t transferred = 0;
|
||||||
int len;
|
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) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR(eon->base.context, "read interrupt transfer failed");
|
ERROR(eon->base.context, "read interrupt transfer failed");
|
||||||
return -1;
|
return -1;
|
||||||
@ -168,6 +168,7 @@ static int send_cmd(suunto_eonsteel_device_t *eon,
|
|||||||
unsigned char buf[64];
|
unsigned char buf[64];
|
||||||
unsigned short seq = eon->seq;
|
unsigned short seq = eon->seq;
|
||||||
unsigned int magic = eon->magic;
|
unsigned int magic = eon->magic;
|
||||||
|
dc_custom_io_t *io = _dc_context_custom_io(eon->base.context);
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
size_t transferred = 0;
|
size_t transferred = 0;
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ static int send_cmd(suunto_eonsteel_device_t *eon,
|
|||||||
memcpy(buf+14, buffer, len);
|
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) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR(eon->base.context, "write interrupt transfer failed");
|
ERROR(eon->base.context, "write interrupt transfer failed");
|
||||||
return -1;
|
return -1;
|
||||||
@ -462,7 +463,6 @@ static int get_file_list(suunto_eonsteel_device_t *eon, struct directory_entry *
|
|||||||
unsigned char result[2048];
|
unsigned char result[2048];
|
||||||
int rc, cmdlen;
|
int rc, cmdlen;
|
||||||
|
|
||||||
|
|
||||||
*res = NULL;
|
*res = NULL;
|
||||||
put_le32(0, cmd);
|
put_le32(0, cmd);
|
||||||
memcpy(cmd + 4, dive_directory, sizeof(dive_directory));
|
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)
|
static int initialize_eonsteel(suunto_eonsteel_device_t *eon)
|
||||||
{
|
{
|
||||||
const unsigned char init[] = {0x02, 0x00, 0x2a, 0x00};
|
const unsigned char init[] = {0x02, 0x00, 0x2a, 0x00};
|
||||||
unsigned char buf[64];
|
|
||||||
struct eon_hdr hdr;
|
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)) {
|
if (send_cmd(eon, INIT_CMD, sizeof(init), init)) {
|
||||||
ERROR(eon->base.context, "Failed to send initialization command");
|
ERROR(eon->base.context, "Failed to send initialization command");
|
||||||
return -1;
|
return -1;
|
||||||
@ -548,7 +531,7 @@ static int initialize_eonsteel(suunto_eonsteel_device_t *eon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
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;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
suunto_eonsteel_device_t *eon = NULL;
|
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->version, 0, sizeof (eon->version));
|
||||||
memset (eon->fingerprint, 0, sizeof (eon->fingerprint));
|
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) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR(context, "unable to open device");
|
ERROR(context, "unable to open device");
|
||||||
goto error_free;
|
goto error_free;
|
||||||
@ -583,7 +571,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
error_close:
|
error_close:
|
||||||
dc_usbhid_close(eon->usbhid);
|
io->packet_close(io);
|
||||||
error_free:
|
error_free:
|
||||||
free(eon);
|
free(eon);
|
||||||
return status;
|
return status;
|
||||||
@ -705,9 +693,7 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac
|
|||||||
static dc_status_t
|
static dc_status_t
|
||||||
suunto_eonsteel_device_close(dc_device_t *abstract)
|
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 io->packet_close(io);
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ extern "C" {
|
|||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
dc_status_t
|
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
|
dc_status_t
|
||||||
suunto_eonsteel_parser_create(dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
suunto_eonsteel_parser_create(dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user