1
2 /* General USB I/O support */
3
4 /*
5 * Argyll Color Correction System
6 *
7 * Author: Graeme W. Gill
8 * Date: 2006/22/4
9 *
10 * Copyright 2006 - 2013 Graeme W. Gill
11 * All rights reserved.
12 *
13 * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
14 * see the License2.txt file for licencing details.
15 */
16
17 /* These routines supliement the class code in icoms_nt.c and icoms_ux.c */
18 /* with common and USB specific routines */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <time.h>
23 #include <signal.h>
24 #if defined(UNIX)
25 #include <termios.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #endif
29 #ifndef SALONEINSTLIB
30 #include "copyright.h"
31 #include "aconfig.h"
32 #else
33 #include "sa_config.h"
34 #endif
35 #include "numsup.h"
36 #include "xspect.h"
37 #include "insttypes.h"
38 #include "conv.h"
39 #include "icoms.h"
40
41 #ifdef ENABLE_USB
42
43 /* Counter set when we're in a USB read or write */
44 /* Note - this isn't perfectly thread safe */
45 int in_usb_rw = 0;
46
47 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
48 /* Cancel token utility functions */
49
50 /* Used by caller of icoms to init and uninit token */
usb_init_cancel(usb_cancelt * p)51 void usb_init_cancel(usb_cancelt *p) {
52
53 amutex_init(p->cmtx);
54 amutex_init(p->condx);
55
56 p->hcancel = NULL;
57 }
58
usb_uninit_cancel(usb_cancelt * p)59 void usb_uninit_cancel(usb_cancelt *p) {
60 amutex_del(p->cmtx);
61 amutex_del(p->condx);
62 }
63
64 /* Used by caller of icoms to re-init for wait_io */
65 /* Must be called before icoms_usb_wait_io() */
usb_reinit_cancel(usb_cancelt * p)66 void usb_reinit_cancel(usb_cancelt *p) {
67
68 amutex_lock(p->cmtx);
69
70 p->hcancel = NULL;
71 p->state = 0;
72 amutex_lock(p->condx); /* Block until IO is started */
73
74 amutex_unlock(p->cmtx);
75 }
76
77 /* Wait for the given transaction to be pending or complete. */
icoms_usb_wait_io(icoms * p,usb_cancelt * cancelt)78 static int icoms_usb_wait_io(
79 icoms *p,
80 usb_cancelt *cancelt
81 ) {
82 amutex_lock(cancelt->condx); /* Wait for unlock */
83 amutex_unlock(cancelt->condx); /* Free it up for next time */
84 return ICOM_OK;
85 }
86
87 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
88
89 /* Include the USB implementation dependent function implementations */
90 # ifdef NT
91 # include "usbio_nt.c"
92 # endif
93 # if defined(UNIX_APPLE)
94 # include "usbio_ox.c"
95 # endif
96 # if defined(UNIX_X11)
97 # if defined(__FreeBSD__) || defined(__OpenBSD__)
98 # include "usbio_bsd.c"
99 # else
100 # include "usbio_lx.c"
101 # endif
102 # endif
103
104 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
105 /* I/O routines supported by icoms - uses platform independent */
106 /* USB routines implemented by code in usbio_*.c above */
107
108 /* USB control message */
109 static int
icoms_usb_control(icoms * p,int requesttype,int request,int value,int index,unsigned char * rwbuf,int rwsize,double tout)110 icoms_usb_control(
111 icoms *p,
112 int requesttype, /* 8 bit request type (USB bmRequestType) */
113 int request, /* 8 bit request code (USB bRequest) */
114 int value, /* 16 bit value (USB wValue) */
115 int index, /* 16 bit index (USB wIndex) */
116 unsigned char *rwbuf, /* Write or read buffer */
117 int rwsize, /* Bytes to read or write */
118 double tout /* Timeout in seconds */
119 ) {
120 int rv = 0; /* Return value */
121 int rwbytes; /* Data bytes read or written */
122 long top; /* timeout in msec */
123
124 if (p->log->debug >= 8) {
125 a1logd(p->log, 8, "icoms_usb_control: message %02x, %02x %04x %04x %04x\n",
126 requesttype, request, value, index, rwsize);
127 if ((requesttype & IUSB_ENDPOINT_IN) == 0)
128 a1logd(p->log, 8, " writing data %s\n",icoms_tohex(rwbuf, rwsize));
129 }
130
131 if (!p->is_open) {
132 a1loge(p->log, ICOM_SYS, "icoms_usb_control: device not open\n");
133 return ICOM_SYS;
134 }
135
136 top = (int)(tout * 1000.0 + 0.5); /* Timout in msec */
137
138 #ifdef QUIET_MEMCHECKERS
139 if (requesttype & IUSB_ENDPOINT_IN)
140 memset(rwbuf, 0, rwsize);
141 #endif
142
143 /* Call back end implementation */
144 rv = icoms_usb_control_msg(p, &rwbytes, requesttype, request, value, index,
145 rwbuf, rwsize, top);
146 a1logd(p->log, 8, "icoms_usb_control: returning ICOM err 0x%x\n",rv);
147
148 if (p->log->debug >= 8 && (requesttype & IUSB_ENDPOINT_IN))
149 a1logd(p->log, 8, " read data %s\n",icoms_tohex(rwbuf, rwsize));
150
151 return rv;
152 }
153
154 /* - - - - - - - - - - - - - */
155 /* USB Read/Write. Direction is set by ep. */
156 /* Don't retry on a short read, return ICOM_SHORT. */
157 static int
icoms_usb_rw(icoms * p,usb_cancelt * cancelt,int ep,unsigned char * rbuf,int bsize,int * breadp,double tout)158 icoms_usb_rw(icoms *p,
159 usb_cancelt *cancelt, /* Cancel handle */
160 int ep, /* End point address */
161 unsigned char *rbuf, /* Read/Write buffer */
162 int bsize, /* Bytes to read */
163 int *breadp, /* Bytes read/written */
164 double tout /* Timeout in seconds */
165 ) {
166 int lerr; /* Last error */
167 int bread, qa;
168 long top; /* Timeout period */
169 icom_usb_trantype type; /* bulk or interrupt */
170
171 #ifdef QUIET_MEMCHECKERS
172 memset(rbuf, 0, bsize);
173 #endif
174
175 if (!p->is_open) {
176 a1loge(p->log, ICOM_SYS, "icoms_usb_rw: device not initialised\n");
177 return ICOM_SYS;
178 }
179
180 if (p->EPINFO(ep).valid == 0) {
181 a1loge(p->log, ICOM_SYS, "icoms_usb_rw: invalid end point 0x%02x\n",ep);
182 return ICOM_SYS;
183 }
184
185 if (p->EPINFO(ep).type != ICOM_EP_TYPE_BULK
186 && p->EPINFO(ep).type != ICOM_EP_TYPE_INTERRUPT) {
187 a1loge(p->log, ICOM_SYS, "icoms_usb_rw: unhandled end point type %d\n",p->EPINFO(ep).type);
188 return ICOM_SYS;
189 }
190
191 if (p->EPINFO(ep).type == ICOM_EP_TYPE_BULK)
192 type = icom_usb_trantype_bulk;
193 else
194 type = icom_usb_trantype_interrutpt;
195
196 qa = bsize; /* For simpler tracing */
197
198 lerr = 0;
199 bread = 0;
200
201 top = (int)(tout * 1000 + 0.5); /* Timeout period in msecs */
202
203 /* Bug workaround - on some OS's for some devices */
204 if (p->uflags & icomuf_resetep_before_read
205 && (ep & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_IN) {
206 msec_sleep(1); /* Let device recover ? */
207 p->usb_resetep(p, ep);
208 msec_sleep(1); /* Let device recover (ie. Spyder 3) */
209 }
210
211 /* Until data is all read/written, we get a short read/write, we time out, or the user aborts */
212 // a1logd(p->log, 8, "icoms_usb_rw: read/write of %d bytes, timout %f\n",bsize,tout);
213 while (bsize > 0) {
214 int rv, rbytes;
215 int rsize = bsize > qa ? qa : bsize;
216
217 // a1logd(p->log, 8, "icoms_usb_rw: read/write %d bytes this time\n",rsize);
218 rv = icoms_usb_transaction(p, cancelt, &rbytes, type, (unsigned char)ep, rbuf, rsize, top);
219 if (rv != 0 && rv != ICOM_SHORT) {
220 lerr = rv;
221 break;
222 } else { /* Account for bytes read/written */
223 bsize -= rbytes;
224 rbuf += rbytes;
225 bread += rbytes;
226 }
227 if (rbytes != rsize) {
228 lerr |= ICOM_SHORT;
229 break;
230 }
231 }
232
233 if (breadp != NULL)
234 *breadp = bread;
235
236 a1logd(p->log, 8, "icoms_usb_rw: returning %d bytes, ICOM err 0x%x\n",bread, lerr);
237
238 return lerr;
239 }
240
241 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
242
243 /* Static list so that all open USB/HID connections can be closed on a SIGKILL */
244 static icoms *icoms_list = NULL;
245
246 /* Clean up any open USB ports ready for exit on signal */
icoms_cleanup()247 static void icoms_cleanup() {
248 icoms *pp, *np;
249
250 #if defined(UNIX)
251 /* This is a bit of a hack to compensate for the fact */
252 /* that a ^C will kill the program while ICANON is off. */
253 /* It's really better to restore the original attributes, */
254 /* even when USB is not compiled in. */
255 struct termios news;
256 if (tcgetattr(STDIN_FILENO, &news) >= 0) {
257 news.c_lflag |= (ICANON | ECHO);
258 tcsetattr(STDIN_FILENO,TCSANOW, &news);
259 }
260 #endif
261
262 for (pp = icoms_list; pp != NULL; pp = np) {
263 np = pp->next;
264 a1logd(pp->log, 6, "icoms_cleanup: closing usb port 0x%x\n",pp);
265 /* There's a problem here if have more than one USB port */
266 /* open - win32 doesn't return from the system call. */
267 /* Should we depend on usb read/write routines to call cleanup ? */
268 pp->close_port(pp);
269 }
270 }
271
272 #ifdef NT
273 void (__cdecl *usbio_int)(int sig) = SIG_DFL;
274 void (__cdecl *usbio_term)(int sig) = SIG_DFL;
275 #endif
276 #ifdef UNIX
277 void (*usbio_hup)(int sig) = SIG_DFL;
278 void (*usbio_int)(int sig) = SIG_DFL;
279 void (*usbio_term)(int sig) = SIG_DFL;
280 #endif
281
282 /* On something killing our process, deal with USB cleanup */
icoms_sighandler(int arg)283 static void icoms_sighandler(int arg) {
284 static amutex_static(lock);
285
286 a1logd(g_log, 6, "icoms_sighandler: invoked with arg = %d\n",arg);
287
288 /* Make sure we don't re-enter */
289 if (amutex_trylock(lock)) {
290 return;
291 }
292
293 if (in_usb_rw != 0)
294 in_usb_rw = -1;
295 icoms_cleanup();
296
297 /* Call the existing handlers */
298 #ifdef UNIX
299 if (arg == SIGHUP && usbio_hup != SIG_DFL && usbio_hup != SIG_IGN)
300 usbio_hup(arg);
301 #endif /* UNIX */
302 if (arg == SIGINT && usbio_int != SIG_DFL && usbio_int != SIG_IGN)
303 usbio_int(arg);
304 if (arg == SIGTERM && usbio_term != SIG_DFL && usbio_term != SIG_IGN)
305 usbio_term(arg);
306
307 a1logd(g_log, 6, "icoms_sighandler: calling exit()\n");
308
309 amutex_unlock(lock);
310 exit(0);
311 }
312
313 /* - - - - - - - - - - - - - - - - - - - */
314
315 /* Install the cleanup signal handlers */
usb_install_signal_handlers(icoms * p)316 void usb_install_signal_handlers(icoms *p) {
317 if (icoms_list == NULL) {
318 a1logd(g_log, 6, "usb_install_signal_handlers: called\n");
319 #if defined(UNIX)
320 usbio_hup = signal(SIGHUP, icoms_sighandler);
321 #endif /* UNIX */
322 usbio_int = signal(SIGINT, icoms_sighandler);
323 usbio_term = signal(SIGTERM, icoms_sighandler);
324 }
325
326 /* Add it to our static list, to allow automatic cleanup on signal */
327 p->next = icoms_list;
328 icoms_list = p;
329 a1logd(g_log, 6, "usb_install_signal_handlers: done\n");
330 }
331
332 /* Delete an icoms from our static signal cleanup list */
usb_delete_from_cleanup_list(icoms * p)333 void usb_delete_from_cleanup_list(icoms *p) {
334
335 /* Find it and delete it from our static cleanup list */
336 if (icoms_list != NULL) {
337 if (icoms_list == p) {
338 icoms_list = p->next;
339 if (icoms_list == NULL) {
340 #if defined(UNIX)
341 signal(SIGHUP, usbio_hup);
342 #endif /* UNIX */
343 signal(SIGINT, usbio_int);
344 signal(SIGTERM, usbio_term);
345 }
346 } else {
347 icoms *pp;
348 for (pp = icoms_list; pp != NULL; pp = pp->next) {
349 if (pp->next == p) {
350 pp->next = p->next;
351 break;
352 }
353 }
354 }
355 }
356 }
357
358 /* ========================================================= */
359 /* USB write/read "serial" imitation */
360
361 /* Write the characters in the buffer out */
362 /* Data will be written up to the terminating nul */
363 /* Return relevant error status bits */
364 static int
icoms_usb_ser_write(icoms * p,char * wbuf,int nwch,double tout)365 icoms_usb_ser_write(
366 icoms *p,
367 char *wbuf, /* null terminated unless nch > 0 */
368 int nwch, /* if > 0, number of characters to write */
369 double tout)
370 {
371 int len, wbytes;
372 long ttop, top; /* Total timeout period, timeout period */
373 unsigned int stime, etime; /* Start and end times of USB operation */
374 int ep = p->wr_ep; /* End point */
375 icom_usb_trantype type; /* bulk or interrupt */
376 int retrv = ICOM_OK;
377
378 a1logd(p->log, 8, "\nicoms_usb_ser_write: writing '%s'\n",
379 nwch > 0 ? icoms_tohex((unsigned char *)wbuf, nwch) : icoms_fix(wbuf));
380
381 if (!p->is_open) {
382 a1loge(p->log, ICOM_SYS, "icoms_usb_ser_write: device is not open\n");
383 return ICOM_SYS;
384 }
385
386 if (p->EPINFO(ep).valid == 0) {
387 a1loge(p->log, ICOM_SYS, "icoms_usb_ser_write: invalid end point 0x%02x\n",ep);
388 return ICOM_SYS;
389 }
390
391 if (p->EPINFO(ep).type != ICOM_EP_TYPE_BULK
392 && p->EPINFO(ep).type != ICOM_EP_TYPE_INTERRUPT) {
393 a1loge(p->log, ICOM_SYS, "icoms_usb_ser_write: unhandled end point type %d",p->EPINFO(ep).type);
394 return ICOM_SYS;
395 }
396
397 if (p->EPINFO(ep).type == ICOM_EP_TYPE_BULK)
398 type = icom_usb_trantype_bulk;
399 else
400 type = icom_usb_trantype_interrutpt;
401
402 if (nwch != 0)
403 len = nwch;
404 else
405 len = strlen(wbuf);
406
407 ttop = (int)(tout * 1000.0 + 0.5); /* Total timeout period in msecs */
408
409 a1logd(p->log, 8, "\nicoms_usb_ser_write: ep 0x%x, bytes %d, ttop %d, quant %d\n", p->rd_ep, len, ttop, p->rd_qa);
410
411 etime = stime = msec_time();
412
413 /* Until data is all written, we time out, or the user aborts */
414 for (top = ttop; top > 0 && len > 0;) {
415 int rv;
416 a1logd(p->log, 8, "icoms_usb_ser_write: attempting to write %d bytes to usb top = %d\n",len,top);
417
418 rv = icoms_usb_transaction(p, NULL, &wbytes, type, (unsigned char)ep, (unsigned char *)wbuf, len, top);
419 etime = msec_time();
420 if (rv != ICOM_OK) {
421 if (rv != ICOM_TO) {
422 retrv |= rv;
423 break;
424 }
425 } else { /* Account for bytes written */
426 a1logd(p->log, 8, "icoms_usb_ser_write: wrote %d bytes\n",wbytes);
427 wbuf += wbytes;
428 len -= wbytes;
429 }
430 top = ttop - (etime - stime); /* Remaining time */
431 }
432
433 if (top <= 0) { /* Must have timed out */
434 a1logd(p->log, 8, "icoms_usb_ser_write: timeout, took %d msec out of %d\n",etime - stime,ttop);
435 retrv |= ICOM_TO;
436 }
437
438 a1logd(p->log, 8, "icoms_usb_ser_write: took %d msec, returning ICOM err 0x%x\n",etime - stime,retrv);
439
440 return retrv;
441 }
442
443
444 /* Read characters into the buffer */
445 /* Return string will be terminated with a nul */
446 /* Read only in packet sized chunks, and retry if */
447 /* the bytes requested aren't read, untill we get a */
448 /* timeout or a terminating char is read */
449 static int
icoms_usb_ser_read(icoms * p,char * rbuf,int bsize,int * pbread,char * tc,int ntc,double tout)450 icoms_usb_ser_read(icoms *p,
451 char *rbuf, /* Buffer to store characters read */
452 int bsize, /* Buffer size */
453 int *pbread, /* Bytes read (not including forced '\000') */
454 char *tc, /* Terminating characers, NULL for none or char count mode */
455 int ntc, /* Number of terminating characters or char count needed */
456 double tout) /* Time out in seconds */
457 {
458 int j, rbytes;
459 long ttop, top; /* Total timeout period, timeout period */
460 unsigned int stime, etime; /* Start and end times of USB operation */
461 char *rrbuf = rbuf; /* Start of return buffer */
462 int ep = p->rd_ep; /* End point */
463 icom_usb_trantype type; /* bulk or interrupt */
464 int retrv = ICOM_OK;
465 int nreads; /* Number of reads performed */
466 int fastserial = 0; /* If fast serial type */
467
468 if (!p->is_open) {
469 a1loge(p->log, ICOM_SYS, "icoms_usb_ser_read: device is not open\n");
470 return ICOM_SYS;
471 }
472
473 if (p->EPINFO(ep).valid == 0) {
474 a1loge(p->log, ICOM_SYS, "icoms_usb_ser_read: invalid end point 0x%02x\n",ep);
475 return ICOM_SYS;
476 }
477
478 if (p->EPINFO(ep).type != ICOM_EP_TYPE_BULK
479 && p->EPINFO(ep).type != ICOM_EP_TYPE_INTERRUPT) {
480 a1loge(p->log, ICOM_SYS, "icoms_usb_ser_read: unhandled end point type %d",p->EPINFO(ep).type);
481 return ICOM_SYS;
482 }
483
484 if (p->EPINFO(ep).type == ICOM_EP_TYPE_BULK)
485 type = icom_usb_trantype_bulk;
486 else
487 type = icom_usb_trantype_interrutpt;
488
489 if (bsize < 3) {
490 a1loge(p->log, ICOM_SYS, "icoms_usb_ser_read given too small a buffer (%d)", bsize);
491 return ICOM_SYS;
492 }
493
494 if (p->dctype & icomt_fastserial)
495 fastserial = 1;
496
497 for (j = 0; j < bsize; j++)
498 rbuf[j] = 0;
499
500 /* The DTP94 doesn't cope with a timeout on OS X, so we need to avoid */
501 /* them by giving each read the largest timeout period possible. */
502 /* This also reduces the problem of libusb 0.1 not returning the */
503 /* number of characters read on a timeout. */
504
505 ttop = (int)(tout * 1000.0 + 0.5); /* Total timeout period in msecs */
506
507 a1logd(p->log, 8, "\nicoms_usb_ser_read: ep 0x%x, bytes %d, ttop %d, ntc %d, quant %d\n", p->rd_ep, bsize, ttop, ntc, p->rd_qa);
508
509 bsize -= 1; /* Allow space for null */
510 bsize -= p->ms_bytes; /* Allow space for modem status bytes */
511
512 j = (tc == NULL && ntc <= 0) ? -1 : 0;
513 etime = stime = msec_time();
514
515 /* Until data is all read, we time out, or the user aborts */
516 for (top = ttop, nreads = 0; top > 0 && bsize > 0 && j < ntc ;) {
517 int c, rv;
518 int rsize = bsize;
519
520 /* If not a fast USB/BT serial port, read in quanta size chunks */
521 if (!fastserial && rsize > p->rd_qa)
522 rsize = p->rd_qa;
523
524 a1logd(p->log, 8, "icoms_usb_ser_read: attempting to read %d bytes from usb, top = %d, j = %d\n",rsize,top,j);
525
526 rv = icoms_usb_transaction(p, NULL, &rbytes, type, (unsigned char)ep, (unsigned char *)rbuf, rsize, top);
527 etime = msec_time();
528 nreads++;
529
530 if (rbytes > 0) { /* Account for bytes read */
531
532 /* Account for modem status bytes. Modem bytes are per usb read, */
533 /* or every p->rd_qa bytes. */
534 if (p->ms_bytes) { /* Throw away modem bytes */
535 char *bp = rbuf;
536 int rb = rbytes;
537 for (; rb > 0; ) {
538 int nb = rb < p->ms_bytes ? rb : p->ms_bytes; /* Bytes to shift */
539 if (p->interp_ms != NULL && nb >= p->ms_bytes)
540 retrv |= p->interp_ms(p, (unsigned char *)bp); /* Deal with error flags in ms bytes */
541 a1logd(p->log, 8, "icoms_usb_ser_read: discarded %d modem bytes 0x%02x 0x%02x\n",nb,nb >= 1 ? (bp[0] & 0xff) : 0, nb >= 2 ? (bp[1] & 0xff) : 0);
542 rb -= nb;
543 rbytes -= nb;
544 memmove(bp, bp+nb, rb);
545 bp += p->rd_qa - p->ms_bytes;
546 rb -= p->rd_qa - p->ms_bytes;
547 }
548 rbuf[rbytes] = 0;
549 }
550
551 a1logd(p->log, 8, "icoms_usb_ser_read: read %d bytes, rbuf = '%s'\n",rbytes,icoms_fix(rrbuf));
552
553 bsize -= rbytes;
554 if (tc != NULL) {
555 while(rbytes--) { /* Count termination characters */
556 char ch = *rbuf++, *tcp = tc;
557
558 while(*tcp != '\000') {
559 if (ch == *tcp)
560 j++;
561 tcp++;
562 }
563 }
564 a1logd(p->log, 8, "icoms_usb_ser_read: tc count %d\n",j);
565 } else {
566 if (ntc > 0)
567 j += rbytes;
568 rbuf += rbytes;
569 }
570 }
571
572 /* Deal with any errors */
573 if (rv != ICOM_OK && rv != ICOM_SHORT) {
574 a1logd(p->log, 8, "icoms_usb_ser_read: read failed with 0x%x, rbuf = '%s'\n",rv,icoms_fix(rrbuf));
575 retrv |= rv;
576 break;
577 }
578 top = ttop - (etime - stime); /* Remaining time */
579 }
580
581 *rbuf = '\000';
582 a1logd(p->log, 8, "icoms_usb_ser_read: read %d total bytes with %d reads\n",rbuf - rrbuf, nreads);
583 if (pbread != NULL)
584 *pbread = (rbuf - rrbuf);
585
586 /* If ran out of time and not completed */
587 a1logd(p->log, 8, "icoms_usb_ser_read: took %d msec\n",etime - stime);
588 if (top <= 0 && bsize > 0 && j < ntc) {
589 a1logd(p->log, 8, "icoms_usb_ser_read: timeout, took %d msec out of %d\n",etime - stime,ttop);
590 retrv |= ICOM_TO;
591 }
592
593 a1logd(p->log, 8, "icoms_usb_ser_read: took %d msec, returning '%s' ICOM err 0x%x\n",
594 etime - stime, tc == NULL && ntc > 0 ? icoms_tohex((unsigned char*)rrbuf, rbuf - rrbuf) : icoms_fix(rrbuf), retrv);
595
596 return retrv;
597 }
598
599
600 /* ------------------------------------------------- */
601
602 /* Set the usb port number and characteristics. */
603 /* This may be called to re-establish a connection that has failed */
604 /* return an icom error */
605 static int
icoms_set_usb_port(icoms * p,int config,int wr_ep,int rd_ep,icomuflags usbflags,int retries,char ** pnames)606 icoms_set_usb_port(
607 icoms *p,
608 int config, /* Configuration */
609 int wr_ep, /* "Serial" Write end point */
610 int rd_ep, /* "Serial" Read end point */
611 icomuflags usbflags, /* Any special handling flags */
612 int retries, /* > 0 if we should retry set_configuration (100msec) */
613 char **pnames /* List of process names to try and kill before opening */
614 ) {
615 a1logd(p->log, 8, "icoms_set_usb_port: About to set usb port characteristics\n");
616
617 if (p->port_type(p) & icomt_usb) {
618 int rv;
619
620 if (p->is_open)
621 p->close_port(p);
622
623 if ((rv = usb_open_port(p, config, wr_ep, rd_ep, usbflags, retries, pnames)) != ICOM_OK) {
624 return rv;
625 }
626
627 p->write = icoms_usb_ser_write;
628 p->read = icoms_usb_ser_read;
629
630 } else {
631 a1logd(p->log, 8, "icoms_set_usb_port: Not a USB port!\n");
632 return ICOM_NOTS;
633 }
634 a1logd(p->log, 6, "icoms_set_usb_port: usb port characteristics set ok\n");
635
636
637 return ICOM_OK;
638 }
639
640 /* ---------------------------------------------------------------------------------*/
641
642 /* Set the USB specific icoms methods */
usb_set_usb_methods(icoms * p)643 void usb_set_usb_methods(
644 icoms *p
645 ) {
646 p->set_usb_port = icoms_set_usb_port;
647 p->usb_control = icoms_usb_control;
648 p->usb_read = icoms_usb_rw;
649 p->usb_write = icoms_usb_rw;
650 p->usb_wait_io = icoms_usb_wait_io;
651 p->usb_cancel_io = icoms_usb_cancel_io;
652 p->usb_resetep = icoms_usb_resetep;
653 p->usb_clearhalt = icoms_usb_clearhalt;
654 }
655
656 /* ---------------------------------------------------------------------------------*/
657
658
659 #endif /* ENABLE_USB */
660