2
/* General USB I/O support, MSWin native libusb0.sys implementation. */
3
/* This file is conditionaly #included into usbio.c */
6
* Argyll Color Correction System
8
* Author: Graeme W. Gill
11
* Copyright 2006 - 2013 Graeme W. Gill
12
* All rights reserved.
14
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
15
* see the License2.txt file for licencing details.
26
#include <driver_api.h>
28
#define DEBUG /* Turn on debug messages */
30
#define LIBUSBW1_MAX_DEVICES 255
31
#define LIBUSBW1_PATH_MAX 512
32
#define LIBUSBW1_DEFAULT_TIMEOUT 5000
34
/* USB descriptors are little endian */
36
/* Take a word sized return buffer, and convert it to an unsigned int */
37
static unsigned int buf2uint(unsigned char *buf) {
40
val = ((val << 8) + (0xff & buf[2]));
41
val = ((val << 8) + (0xff & buf[1]));
42
val = ((val << 8) + (0xff & buf[0]));
46
/* Take a short sized return buffer, and convert it to an int */
47
static unsigned int buf2ushort(unsigned char *buf) {
50
val = ((val << 8) + (0xff & buf[0]));
54
/* Take an int, and convert it into a byte buffer */
55
static void int2buf(unsigned char *buf, int inv) {
56
buf[0] = (inv >> 0) & 0xff;
57
buf[1] = (inv >> 8) & 0xff;
58
buf[2] = (inv >> 16) & 0xff;
59
buf[3] = (inv >> 24) & 0xff;
62
/* Take a short, and convert it into a byte buffer */
63
static void short2buf(unsigned char *buf, int inv) {
64
buf[0] = (inv >> 0) & 0xff;
65
buf[1] = (inv >> 8) & 0xff;
68
/* Do a synchronous request. Return an ICOM error */
69
static int do_sync_io(
78
memset(&olaps, 0, sizeof(OVERLAPPED));
82
if ((olaps.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
85
if (!DeviceIoControl(handle, ioctl, out, outsz, in, insz, &xlength, &olaps)) {
86
if (GetLastError() != ERROR_IO_PENDING) {
87
CloseHandle(olaps.hEvent);
90
if (!GetOverlappedResult(handle, &olaps, &xlength, TRUE)) {
91
CloseHandle(olaps.hEvent);
95
CloseHandle(olaps.hEvent);
97
*retsz = (int)xlength;
102
/* Add paths to USB connected instruments */
103
/* Return an icom error */
107
unsigned int vid, pid, nep10 = 0xffff;
108
unsigned int configix, nconfig, nifce;
110
struct usb_idevice *usbd = NULL;
113
for (i = 0; i < LIBUSBW1_MAX_DEVICES; i++) {
115
char dpath[LIBUSBW1_PATH_MAX];
117
unsigned char buf[IUSB_DESC_TYPE_DEVICE_SIZE];
119
_snprintf(dpath, LIBUSBW1_PATH_MAX - 1,"\\\\.\\libusb0-%04d", i+1);
120
a1logd(p->log, 6, "usb_get_paths opening device '%s'\n",dpath);
122
if ((handle = CreateFile(dpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
123
NULL)) == INVALID_HANDLE_VALUE) {
125
a1logd(p->log, 8, "usb_get_paths failed to open device '%s'\n",dpath);
130
/* Set kernel message debug */
131
if (p->log->debug >= 6) {
132
req.debug.level = LIBUSB_DEBUG_MAX;
133
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
134
if (do_sync_io(handle, LIBUSB_IOCTL_SET_DEBUG_LEVEL,
135
&req, sizeof(libusb_request), NULL, 0, NULL)) {
136
a1logd(p->log, 1, "usb_get_paths: failed to set driver log leve\n");
138
a1logd(p->log, 1, "usb_get_paths: turned on kernel debug messages\n");
142
/* Read the device descriptor */
143
req.descriptor.type = IUSB_DESC_TYPE_DEVICE;
144
req.descriptor.recipient = IUSB_REQ_RECIP_DEVICE;
145
req.descriptor.index = 0;
146
req.descriptor.language_id = 0;
147
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
149
if (do_sync_io(handle, LIBUSB_IOCTL_GET_DESCRIPTOR,
150
&req, sizeof(libusb_request),
151
buf, IUSB_DESC_TYPE_DEVICE_SIZE, &retsz) != ICOM_OK
152
|| retsz != IUSB_DESC_TYPE_DEVICE_SIZE) {
153
a1logd(p->log, 1, "usb_get_paths: failed to read device descriptor '%s'\n",dpath);
158
/* Extract the vid and pid */
159
vid = buf2ushort(buf + 8);
160
pid = buf2ushort(buf + 10);
163
a1logd(p->log, 6, "usb_get_paths: checking vid 0x%04x, pid 0x%04x\n",vid,pid);
165
/* Do a preliminary match */
166
if ((itype = inst_usb_match(vid, pid, 0)) == instUnknown) {
167
a1logd(p->log, 6 , "usb_get_paths: instrument not reconized\n");
172
/* Allocate an idevice so that we can fill in the end point information */
173
if ((usbd = (struct usb_idevice *) calloc(sizeof(struct usb_idevice), 1)) == NULL) {
174
a1loge(p->log, ICOM_SYS, "usb_get_paths: calloc failed!\n");
179
usbd->nconfig = nconfig;
181
/* Read the configuration descriptors looking for the first configuration, first interface, */
182
/* and extract the number of end points for each configuration */
183
for (configix = 0; configix < nconfig; configix++) {
184
int configno, totlen;
185
unsigned char *buf2, *bp, *zp;
186
unsigned int ninfaces, inface, nep;
188
/* Read the configuration descriptor */
189
req.descriptor.type = IUSB_DESC_TYPE_CONFIG;
190
req.descriptor.recipient = IUSB_REQ_RECIP_DEVICE;
191
req.descriptor.index = configix;
192
req.descriptor.language_id = 0;
193
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
195
if ((rv = do_sync_io(handle, LIBUSB_IOCTL_GET_DESCRIPTOR,
196
&req, sizeof(libusb_request),
197
buf, IUSB_DESC_TYPE_CONFIG_SIZE, &retsz)) != ICOM_OK
198
|| retsz != IUSB_DESC_TYPE_CONFIG_SIZE) {
199
a1logd(p->log, 1, "usb_get_paths: failed to read configix %d descriptor\n",configix);
204
nifce = buf[4]; /* number of interfaces */
205
configno = buf[5]; /* Configuration number */
210
if ((totlen = buf2ushort(buf + 2)) < 6) {
211
a1logd(p->log, 1, "usb_get_paths: '%s' config desc size strange\n",dpath);
216
if ((buf2 = calloc(1, totlen)) == NULL) {
217
a1loge(p->log, ICOM_SYS, "usb_get_paths: calloc of descriptor failed!\n");
223
/* Read the whole configuration descriptor */
224
req.descriptor.type = IUSB_DESC_TYPE_CONFIG;
225
req.descriptor.recipient = IUSB_REQ_RECIP_DEVICE;
226
req.descriptor.index = configix;
227
req.descriptor.language_id = 0;
228
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
230
if (do_sync_io(handle, LIBUSB_IOCTL_GET_DESCRIPTOR,
231
&req, sizeof(libusb_request),
232
buf2, totlen, &retsz) != ICOM_OK
233
|| retsz != totlen) {
234
a1logd(p->log, 1, "usb_get_paths: failed to read all configix %d descriptor\n",configix);
241
bp = buf2 + buf2[0]; /* Skip coniguration tag */
242
zp = buf2 + totlen; /* Past last bytes */
244
/* We are at the first configuration. */
245
/* Just read tags and keep track of where we are */
248
usbd->nifce = buf2[4]; /* number of interfaces */
249
usbd->config = configno = buf2[5]; /* this configuration */
250
for (;bp < zp; bp += bp[0]) {
253
break; /* Hmm - bodgy, give up */
254
if (bp[1] == IUSB_DESC_TYPE_INTERFACE) {
257
break; /* Hmm - bodgy, give up */
258
ifaceno = bp[2]; /* Get bInterfaceNumber */
259
} else if (bp[1] == IUSB_DESC_TYPE_ENDPOINT) {
262
break; /* Hmm - bodgy */
263
/* At first config - */
264
/* record current nep and end point details */
268
usbd->EPINFO(ad).valid = 1;
269
usbd->EPINFO(ad).addr = ad;
270
usbd->EPINFO(ad).packetsize = buf2ushort(bp + 4);
271
usbd->EPINFO(ad).type = bp[3] & IUSB_ENDPOINT_TYPE_MASK;
272
usbd->EPINFO(ad).interface = ifaceno;
273
a1logd(p->log, 6, "set ep ad 0x%x packetsize %d type %d\n",ad,usbd->EPINFO(ad).packetsize,usbd->EPINFO(ad).type);
276
/* Ignore other tags */
280
if (nep10 == 0xffff) { /* Hmm. Failed to find number of end points */
281
a1logd(p->log, 1, "usb_get_paths: failed to find number of end points\n");
287
/* Check that we have an up to date kernel driver */
288
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
289
if (do_sync_io(handle, LIBUSB_IOCTL_GET_VERSION,
290
&req, sizeof(libusb_request),
291
&req, sizeof(libusb_request), &retsz) != ICOM_OK
292
|| retsz != sizeof(libusb_request)) {
293
a1logd(p->log, 1, "usb_get_paths: failed to read driver version info\n");
298
if (req.version.major < 1
299
|| req.version.major == 1 && (req.version.minor < 2
300
|| req.version.minor == 2 && req.version.micro < 6)) {
301
a1loge(p->log, ICOM_VER, "usb_get_paths: Must update %s System Driver to latest version!\n",inst_name(itype));
308
/* Found a known instrument ? */
309
if ((itype = inst_usb_match(vid, pid, nep10)) != instUnknown) {
312
a1logd(p->log, 1, "usb_get_paths: found instrument vid 0x%04x, pid 0x%04x\n",vid,pid);
314
/* Create a path/identification */
315
sprintf(pname,"%s (%s)", dpath + 4, inst_name(itype));
317
if ((usbd->dpath = strdup(dpath)) == NULL) {
318
a1loge(p->log, ICOM_SYS, "usb_check_and_add: strdup path failed!\n");
323
/* Add the path and ep info to the list */
324
if ((rv = p->add_usb(p, pname, vid, pid, nep10, usbd, itype)) != ICOM_OK)
335
/* Copy usb_idevice contents from icompaths to icom */
336
/* return icom error */
337
int usb_copy_usb_idevice(icoms *d, icompath *s) {
339
if (s->usbd == NULL) {
343
if ((d->usbd = calloc(sizeof(struct usb_idevice), 1)) == NULL) {
344
a1loge(d->log, ICOM_SYS, "usb_copy_usb_idevice: malloc\n");
347
if ((d->usbd->dpath = strdup(s->usbd->dpath)) == NULL) {
348
a1loge(d->log, ICOM_SYS, "usb_copy_usb_idevice: malloc\n");
351
/* Copy the current state & ep info */
352
d->nconfig = s->usbd->nconfig;
353
d->config = s->usbd->config;
354
d->nifce = s->usbd->nifce;
355
for (i = 0; i < 32; i++)
356
d->ep[i] = s->usbd->ep[i]; /* Struct copy */
360
/* Cleanup and then free a usb dev entry */
361
void usb_del_usb_idevice(struct usb_idevice *usbd) {
366
if (usbd->dpath != NULL)
371
/* Cleanup any USB specific icoms state */
372
void usb_del_usb(icoms *p) {
374
usb_del_usb_idevice(p->usbd);
377
/* Close an open USB port */
378
/* If we don't do this, the port and/or the device may be left in an unusable state. */
379
void usb_close_port(icoms *p) {
381
a1logd(p->log, 6, "usb_close_port: called\n");
383
if (p->is_open && p->usbd != NULL) {
386
/* Release all the interfaces */
387
for (iface = 0; iface < p->nifce; iface++) {
390
memset(&req, 0, sizeof(req));
391
req.intf.interface_number = iface;
392
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
394
do_sync_io(p->usbd->handle, LIBUSB_IOCTL_RELEASE_INTERFACE,
395
&req, sizeof(libusb_request), NULL, 0, NULL);
398
/* Workaround for some bugs - reset device on close */
399
if (p->uflags & icomuf_reset_before_close) {
402
memset(&req, 0, sizeof(req));
403
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
405
if ((rv = do_sync_io(p->usbd->handle, LIBUSB_IOCTL_RESET_DEVICE,
406
&req, sizeof(libusb_request), NULL, 0, NULL)) != ICOM_OK) {
407
a1logd(p->log, 1, "usb_close_port: reset returned %d\n",rv);
410
CloseHandle(p->usbd->handle);
412
free(p->usbd->dpath);
416
a1logd(p->log, 6, "usb_close_port: usb port has been released and closed\n");
420
/* Find it and delete it from our static cleanup list */
421
usb_delete_from_cleanup_list(p);
424
static void *urb_reaper(void *context); /* Declare */
426
/* Open a USB port for all our uses. */
427
/* This always re-opens the port */
428
/* return icom error */
429
static int usb_open_port(
431
int config, /* Configuration number */
432
int wr_ep, /* Write end point */
433
int rd_ep, /* Read end point */
434
icomuflags usbflags,/* Any special handling flags */
435
int retries, /* > 0 if we should retry set_configuration (100msec) */
436
char **pnames /* List of process names to try and kill before opening */
439
a1logd(p->log, 8, "usb_open_port: Make sure USB port is open, tries %d\n",retries);
444
/* Make sure the port is open */
447
kkill_nproc_ctx *kpc = NULL;
451
/* Nothing currently needs it, so we haven't implemented it yet... */
452
a1loge(p->log, ICOM_NOTS, "usb_open_port: native driver cant handle config %d\n",config);
456
/* Do open retries */
457
for (tries = 0; retries >= 0; retries--, tries++) {
459
a1logd(p->log, 8, "usb_open_port: About to open USB port '%s'\n",p->usbd->dpath);
462
//msec_sleep(i_rand(50,100));
466
if ((p->usbd->handle = CreateFile(p->usbd->dpath, 0, 0, NULL, OPEN_EXISTING,
467
FILE_FLAG_OVERLAPPED, NULL)) == INVALID_HANDLE_VALUE) {
468
a1logd(p->log, 8, "usb_open_port: open '%s' config %d failed (%d) (Device being used ?)\n",p->usbd->dpath,config,GetLastError());
472
a1loge(p->log, ICOM_SYS, "usb_open_port: open '%s' config %d failed (%d) (Device being used ?)\n",p->usbd->dpath,config,GetLastError());
477
a1logd(p->log, 2, "usb_open_port: open port '%s' succeeded\n",p->usbd->dpath);
479
p->uflags = usbflags;
488
/* We should only do a set configuration if the device has more than one */
489
/* possible configuration and it is currently not the desired configuration, */
490
/* but we should avoid doing a set configuration if the OS has already */
491
/* selected the configuration we want, since two set configs seem to */
492
/* mess up the Spyder2, BUT we can't do a get config because this */
493
/* messes up the i1pro-D. */
495
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
496
osver.dwMajorVersion = 5;
497
GetVersionEx(&osver);
498
if (osver.dwMajorVersion >= 6 && osver.dwMinorVersion >= 2) {
499
p->cconfig = 0; /* Need to do set_congfig(1) on Win8 */
501
p->cconfig = 1; /* Set by default to config 1 */
504
if (p->cconfig != config) {
507
memset(&req, 0, sizeof(libusb_request));
508
req.configuration.configuration = config;
509
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
511
if ((rv = do_sync_io(p->usbd->handle, LIBUSB_IOCTL_SET_CONFIGURATION,
512
&req, sizeof(libusb_request), NULL, 0, NULL)) != ICOM_OK) {
514
a1loge(p->log, rv, "usb_open_port: Setting port '%s' to config %d failed with %d\n",p->usbd->dpath,config,rv);
518
a1logd(p->log, 6, "usb_open_port: set config %d OK\n",config);
521
/* Claim all the interfaces */
522
for (iface = 0; iface < p->nifce; iface++) {
525
memset(&req, 0, sizeof(libusb_request));
526
req.intf.interface_number = iface;
527
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
529
if ((rv = do_sync_io(p->usbd->handle, LIBUSB_IOCTL_CLAIM_INTERFACE,
530
&req, sizeof(libusb_request), NULL, 0, NULL)) != ICOM_OK) {
532
a1loge(p->log, rv, "usb_open_port: Claiming USB port '%s' interface %d failed with %d\n",p->usbd->dpath,iface,rv);
537
/* Clear any errors */
538
/* (Some I/F seem to hang if we do this, some seem to hang if we don't !) */
539
if (!(p->uflags & icomuf_no_open_clear)) {
540
for (i = 0; i < 32; i++) {
543
p->usb_clearhalt(p, p->ep[i].addr);
547
/* Set "serial" coms values */
550
p->rd_qa = p->EPINFO(rd_ep).packetsize;
553
a1logd(p->log, 8, "usb_open_port: 'serial' read quanta = packet size = %d\n",p->rd_qa);
556
a1logd(p->log, 8, "usb_open_port: USB port is now open\n");
559
/* Install the cleanup signal handlers, and add to our cleanup list */
560
usb_install_signal_handlers(p);
565
/* -------------------------------------------------------------- */
567
/* Our universal USB transfer function */
568
static int icoms_usb_transaction(
570
usb_cancelt *cancelt,
572
icom_usb_trantype ttype, /* transfer type */
573
unsigned char endpoint, /* 0x80 for control write, 0x00 for control read */
574
unsigned char *buffer,
576
unsigned int timeout /* In msec */
579
int dirw = (endpoint & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT ? 1 : 0;
586
a1logd(p->log, 8, "icoms_usb_transaction: req type 0x%x ep 0x%x size %d\n",ttype,endpoint,length);
588
if (ttype != icom_usb_trantype_interrutpt
589
&& ttype != icom_usb_trantype_bulk) {
590
/* We only handle interrupt & bulk, not control */
594
memset(&olaps, 0, sizeof(olaps));
596
if ((olaps.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
599
if (cancelt != NULL) {
600
usb_lock_cancel(cancelt);
601
cancelt->hcancel = (void *)&endpoint;
602
usb_unlock_cancel(cancelt);
605
memset(&req, 0, sizeof(libusb_request));
606
req.endpoint.endpoint = endpoint;
608
if (!DeviceIoControl(p->usbd->handle,
609
dirw ? LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE
610
: LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ,
611
&req, sizeof(libusb_request),
613
length, &xlength, &olaps)) {
614
if (GetLastError() != ERROR_IO_PENDING) {
615
rv = dirw ? ICOM_USBW : ICOM_USBR;
619
if (WaitForSingleObject(olaps.hEvent, timeout) == WAIT_TIMEOUT) {
621
/* Cancel the operation */
622
memset(&req, 0, sizeof(libusb_request));
623
req.endpoint.endpoint = endpoint;
624
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
625
do_sync_io(p->usbd->handle, LIBUSB_IOCTL_ABORT_ENDPOINT,
626
&req, sizeof(libusb_request), NULL, 0, NULL);
630
if (!GetOverlappedResult(p->usbd->handle, &olaps, &xlength, TRUE)) {
632
if (GetLastError() == ERROR_OPERATION_ABORTED)
635
rv = dirw ? ICOM_USBW : ICOM_USBR;
640
if (cancelt != NULL) {
641
usb_lock_cancel(cancelt);
642
cancelt->hcancel = (void *)NULL;
643
usb_unlock_cancel(cancelt);
646
CloseHandle(olaps.hEvent);
648
if (transferred != NULL)
649
*transferred = (int)xlength;
651
/* The requested size wasn't transferred */
652
if (rv == ICOM_OK && xlength != length)
660
a1logd(p->log, 8, "coms_usb_transaction: returning err 0x%x and %d bytes\n",rv, xlength);
666
/* Our control message routine */
667
/* Return error icom error code */
668
static int icoms_usb_control_msg(
671
int requesttype, int request,
672
int value, int index, unsigned char *bytes, int size,
675
int dirw = (requesttype & IUSB_REQ_DIR_MASK) == IUSB_REQ_HOST_TO_DEV ? 1 : 0;
677
unsigned char *obuf = (unsigned char *)&req;
678
int osize = sizeof(libusb_request);
679
unsigned char *ibuf = bytes;
684
a1logd(p->log, 8, "icoms_usb_control_msg: type 0x%x req 0x%x size %d\n",requesttype,request,size);
686
memset(&req, 0, sizeof(libusb_request));
687
req.timeout = timeout;
689
/* We need to treat each request type as a different IOCTL */
690
switch (requesttype & IUSB_REQ_TYPE_MASK) {
692
case IUSB_REQ_TYPE_STANDARD:
695
case IUSB_REQ_GET_STATUS:
696
req.status.recipient = requesttype & IUSB_REQ_RECIP_MASK;
697
req.status.index = index;
698
ioctl = LIBUSB_IOCTL_GET_STATUS;
701
case IUSB_REQ_CLEAR_FEATURE:
702
req.feature.recipient = requesttype & IUSB_REQ_RECIP_MASK;
703
req.feature.feature = value;
704
req.feature.index = index;
705
ioctl = LIBUSB_IOCTL_CLEAR_FEATURE;
708
case IUSB_REQ_SET_FEATURE:
709
req.feature.recipient = requesttype & IUSB_REQ_RECIP_MASK;
710
req.feature.feature = value;
711
req.feature.index = index;
712
ioctl = LIBUSB_IOCTL_SET_FEATURE;
715
case IUSB_REQ_GET_DESCRIPTOR:
716
req.descriptor.recipient = requesttype & IUSB_REQ_RECIP_MASK;
717
req.descriptor.type = (value >> 8) & 0xFF;
718
req.descriptor.index = value & 0xFF;
719
req.descriptor.language_id = index;
720
ioctl = LIBUSB_IOCTL_GET_DESCRIPTOR;
723
case IUSB_REQ_SET_DESCRIPTOR:
724
req.descriptor.recipient = requesttype & IUSB_REQ_RECIP_MASK;
725
req.descriptor.type = (value >> 8) & 0xFF;
726
req.descriptor.index = value & 0xFF;
727
req.descriptor.language_id = index;
728
ioctl = LIBUSB_IOCTL_SET_DESCRIPTOR;
731
case IUSB_REQ_GET_CONFIGURATION:
732
ioctl = LIBUSB_IOCTL_GET_CONFIGURATION;
735
case IUSB_REQ_SET_CONFIGURATION:
736
req.configuration.configuration = value;
737
ioctl = LIBUSB_IOCTL_SET_CONFIGURATION;
740
case IUSB_REQ_GET_INTERFACE:
741
req.intf.interface_number = index;
742
ioctl = LIBUSB_IOCTL_GET_INTERFACE;
745
case IUSB_REQ_SET_INTERFACE:
746
req.intf.interface_number = index;
747
req.intf.altsetting_number = value;
748
ioctl = LIBUSB_IOCTL_SET_INTERFACE;
756
case IUSB_REQ_TYPE_VENDOR:
757
case IUSB_REQ_TYPE_CLASS:
759
req.vendor.type = (requesttype & IUSB_REQ_TYPE_MASK) >> IUSB_REQ_TYPE_SHIFT;
760
req.vendor.recipient = requesttype & IUSB_REQ_RECIP_MASK;
761
req.vendor.request = request;
762
req.vendor.value = value;
763
req.vendor.index = index;
766
ioctl = LIBUSB_IOCTL_VENDOR_WRITE;
768
ioctl = LIBUSB_IOCTL_VENDOR_READ;
771
case IUSB_REQ_TYPE_RESERVED:
776
/* If we're writing the data, append it to the req */
778
osize = sizeof(libusb_request) + size;
779
if ((obuf = calloc(1, osize)) == NULL) {
780
a1loge(p->log, ICOM_SYS, "icoms_usb_control_msg: calloc failed\n");
784
memcpy(obuf, &req, sizeof(libusb_request));
785
memcpy(obuf + sizeof(libusb_request), bytes, size);
790
if ((rv = do_sync_io(p->usbd->handle, ioctl, obuf, osize, ibuf, isize, &retsz))
802
if (transferred != NULL) /* Adjust for header size requested */
803
*transferred = retsz;
805
a1logd(p->log, 8, "icoms_usb_control_msg: returning err 0x%x and %d bytes\n",rv, *transferred);
809
/* Cancel i/o operation in another thread. */
810
/* Only Vista has CancelIoEx that can cancel a single operation, */
811
/* so we cancel the io to the end point, which will */
812
/* acheive what we want. */
813
int icoms_usb_cancel_io(
818
usb_lock_cancel(cancelt);
819
if (cancelt->hcancel != NULL) {
822
memset(&req, 0, sizeof(libusb_request));
823
req.endpoint.endpoint = *((unsigned char *)cancelt->hcancel);
824
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
826
if ((rv = do_sync_io(p->usbd->handle, LIBUSB_IOCTL_ABORT_ENDPOINT,
827
&req, sizeof(libusb_request), NULL, 0, NULL)) != ICOM_OK) {
828
a1logd(p->log, 1, "icoms_usb_cancel_io: failed with 0x%x\n",rv);
831
usb_unlock_cancel(cancelt);
836
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
837
/* Reset and end point data toggle to 0 */
838
int icoms_usb_resetep(
840
int ep /* End point address */
845
memset(&req, 0, sizeof(libusb_request));
846
req.endpoint.endpoint = ep;
847
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
849
if ((rv = do_sync_io(p->usbd->handle, LIBUSB_IOCTL_RESET_ENDPOINT, &req,
850
sizeof(libusb_request), NULL, 0, NULL)) != ICOM_OK) {
851
a1logd(p->log, 1, "icoms_usb_resetep failed with %d\n",rv);
857
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
858
/* Clear a halt on an end point */
859
/* (Actually does a resetep) */
860
int icoms_usb_clearhalt(
862
int ep /* End point address */
867
memset(&req, 0, sizeof(libusb_request));
868
req.endpoint.endpoint = ep;
869
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
871
if ((rv = do_sync_io(p->usbd->handle, LIBUSB_IOCTL_RESET_ENDPOINT, &req,
872
sizeof(libusb_request), NULL, 0, NULL)) != ICOM_OK) {
873
a1logd(p->log, 1, "icoms_usb_resetep failed with %d\n",rv);
879
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
883
unsigned char buf[1] = { 0xff };
885
memset(&req, 0, sizeof(libusb_request));
886
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
888
if ((rv = do_sync_io(p->usbd->handle, LIBUSB_IOCTL_GET_CONFIGURATION,
889
&req, sizeof(libusb_request), buf, 1, NULL)) != ICOM_OK) {
891
a1logd(p->log, 1, "usb_open_port: Getting port '%s' configuration failed with %d\n",p->usbd->dpath,rv);
894
a1logd(p->log, 1, "usb_open_port: current config = %d\n",(int)buf[0]);