From c07d0c2d2f6f7b0eb6e92cc6204bf05037957e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 15:43:52 +0200 Subject: Imported Upstream version 1.6.3 --- spectro/usbio.c | 159 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 66 deletions(-) (limited to 'spectro/usbio.c') diff --git a/spectro/usbio.c b/spectro/usbio.c index 3db1535..f8a0529 100644 --- a/spectro/usbio.c +++ b/spectro/usbio.c @@ -14,7 +14,7 @@ * see the License2.txt file for licencing details. */ -/* These routines supliement the class code in ntio.c and unixio.c */ +/* These routines supliement the class code in icoms_nt.c and icoms_ux.c */ /* with common and USB specific routines */ #include @@ -51,35 +51,42 @@ int in_usb_rw = 0; void usb_init_cancel(usb_cancelt *p) { amutex_init(p->cmtx); + amutex_init(p->cond); -#ifdef NATIVE_USB p->hcancel = NULL; -#else -# ifdef USE_LIBUSB1 - p->hcancel = NULL; -# else - p->hcancel = (void *)-1; -# endif -#endif } void usb_uninit_cancel(usb_cancelt *p) { amutex_del(p->cmtx); + amutex_del(p->cond); } -/* Used by implementation */ -static void usb_lock_cancel(usb_cancelt *p) { +/* Used by caller of icoms to re-init for wait_io */ +/* Must be called before icoms_usb_wait_io() */ +void usb_reinit_cancel(usb_cancelt *p) { + amutex_lock(p->cmtx); -} -static void usb_unlock_cancel(usb_cancelt *p) { + p->hcancel = NULL; + p->state = 0; + amutex_lock(p->cond); /* Block until IO is started */ + amutex_unlock(p->cmtx); } +/* Wait for the given transaction to be pending or complete. */ +static int icoms_usb_wait_io( + icoms *p, + usb_cancelt *cancelt +) { + amutex_lock(cancelt->cond); /* Wait for unlock */ + amutex_unlock(cancelt->cond); /* Free it up for next time */ + return ICOM_OK; +} + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Include the USB implementation dependent function implementations */ -#ifdef NATIVE_USB # ifdef NT # include "usbio_nt.c" # endif @@ -87,11 +94,12 @@ static void usb_unlock_cancel(usb_cancelt *p) { # include "usbio_ox.c" # endif # if defined(UNIX_X11) -# include "usbio_lx.c" +# if defined(__FreeBSD__) +# include "usbio_bsd.c" +# else +# include "usbio_lx.c" +# endif # endif -#else /* Using libusb */ -# include "usbio_lusb.c" -#endif /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* I/O routines supported by icoms - uses platform independent */ @@ -415,19 +423,20 @@ double tout) /* Read characters into the buffer */ /* Return string will be terminated with a nul */ -/* Read only in paket sized chunks, and retry if */ +/* Read only in packet sized chunks, and retry if */ /* the bytes requested aren'r read, untill we get a */ /* timeout or a terminating char is read */ static int icoms_usb_ser_read(icoms *p, char *rbuf, /* Buffer to store characters read */ int bsize, /* Buffer size */ -char tc, /* Terminating characer */ -int ntc, /* Number of terminating characters */ +char *tc, /* Terminating characers, NULL if none */ +int ntc, /* Number of terminating characters needed to terminate */ double tout) /* Time out in seconds */ { int j, rbytes; - long toc, i, top; /* Timout count, counter, timeout period */ + long ttop, top; /* Total timeout period, timeout period */ + unsigned int stime, etime; /* Start and end times of USB operation */ char *rrbuf = rbuf; /* Start of return buffer */ int ep = p->rd_ep; /* End point */ icom_usb_trantype type; /* bulk or interrupt */ @@ -463,50 +472,74 @@ double tout) /* Time out in seconds */ return ICOM_SYS; } - for (i = 0; i < bsize; i++) rbuf[i] = 0; + for (j = 0; j < bsize; j++) rbuf[j] = 0; - tout *= 1000.0; /* Timout in msec */ - bsize--; /* Allow space for null */ + bsize -= 1; /* Allow space for null */ + bsize -= p->ms_bytes; /* Allow space for modem status bytes */ - /* Have to do this in one go, because libusb has no way */ - /* of timing out and returning the number of characters read */ - /* up to the timeout, and it looses characters. */ - top = (int)(tout + 0.5); /* Timeout period in msecs */ - toc = (int)(tout/top + 0.5); /* Number of timout periods in timeout */ - if (toc < 1) - toc = 1; + /* The DTP94 doesn't cope with a timeout on OS X, so we need to avoid */ + /* them by giving each read the largest timeout period possible. */ + /* This also reduces the problem of libusb 0.1 not returning the */ + /* number of characters read on a timeou. */ + + ttop = (int)(tout * 1000.0 + 0.5); /* Total timeout period in msecs */ + + a1logd(p->log, 8, "\nicoms_usb_ser_read: ep 0x%x, ttop %d, quant %d\n", p->rd_ep, ttop, p->rd_qa); - a1logd(p->log, 8, "\nicoms_usb_ser_read: end point 0x%x, read quanta %d\n",p->rd_ep,p->rd_qa); /* Until data is all read, we time out, or the user aborts */ - for (i = toc, j = 0; i > 0 && bsize > 1 && j < ntc ;) { + stime = msec_time(); + top = ttop; + for (j = 0; top > 0 && bsize > 1 && j < ntc ;) { int c, rv; int rsize = p->rd_qa < bsize ? p->rd_qa : bsize; - a1logd(p->log, 8, "icoms_usb_ser_read: attempting to read %d bytes from usb, top = %d, i = %d, j = %d\n",bsize > p->rd_qa ? p->rd_qa : bsize,top,i,j); - /* We read one read quanta at a time (usually 8 bytes), to avoid */ - /* problems with libusb loosing characters whenever it times out. */ + a1logd(p->log, 8, "icoms_usb_ser_read: attempting to read %d bytes from usb, top = %d, j = %d\n",bsize > p->rd_qa ? p->rd_qa : bsize,top,j); + rv = icoms_usb_transaction(p, NULL, &rbytes, type, (unsigned char)ep, (unsigned char *)rbuf, rsize, top); - if (rv != 0 && rv != ICOM_SHORT) { - a1logd(p->log, 8, "icoms_usb_ser_read: read failed with 0x%x, rbuf = '%s'\n",rv,icoms_fix(rrbuf)); - if (rv != ICOM_TO) { - retrv |= rv; - break; + etime = msec_time(); + + if (rbytes > 0) { /* Account for bytes read */ + + /* Account for modem status bytes. Modem bytes are per usb read. */ + if (p->ms_bytes) { /* Throw away modem bytes */ + int nb = rbytes < p->ms_bytes ? rbytes : p->ms_bytes; + rbytes -= nb; + memmove(rbuf, rbuf+nb, rbytes); + a1logd(p->log, 8, "icoms_usb_ser_read: discarded %d modem bytes\n",nb); } - i--; /* Timeout */ - } else { /* Account for bytes read */ - a1logd(p->log, 8, "icoms_usb_ser_read: read read %d bytes, rbuf = '%s'\n",rbytes,icoms_fix(rrbuf)); - i = toc; + + a1logd(p->log, 8, "icoms_usb_ser_read: read %d bytes, rbuf = '%s'\n",rbytes,icoms_fix(rrbuf)); + bsize -= rbytes; - while(rbytes) { /* Count termination characters */ - if (*rbuf++ == tc) - j++; - rbytes--; + if (tc != NULL) { + while(rbytes--) { /* Count termination characters */ + char ch = *rbuf++, *tcp = tc; + + while(*tcp != '\000') { + if (ch == *tcp) + j++; + tcp++; + } + } + } else { + rbuf += rbytes; } } - } - if (i <= 0) /* Must have timed out */ - retrv |= ICOM_TO; + /* Deal with any errors */ + if (rv != ICOM_OK && rv != ICOM_SHORT) { + a1logd(p->log, 8, "icoms_usb_ser_read: read failed with 0x%x, rbuf = '%s'\n",rv,icoms_fix(rrbuf)); + retrv |= rv; + break; + } + + top = ttop - (etime - stime); /* Remaining time */ + if (top <= 0) { /* Run out of time */ + a1logd(p->log, 8, "icoms_usb_ser_read: read ran out of time\n"); + retrv |= ICOM_TO; + break; + } + } *rbuf = '\000'; @@ -533,7 +566,8 @@ char **pnames /* List of process names to try and kill before opening */ ) { a1logd(p->log, 8, "icoms_set_usb_port: About to set usb port characteristics\n"); - if (p->port_type(p) == icomt_usb) { + if (p->port_type(p) == icomt_usb + || p->port_type(p) == icomt_usbserial) { int rv; if (p->is_open) @@ -546,21 +580,12 @@ char **pnames /* List of process names to try and kill before opening */ p->write = icoms_usb_ser_write; p->read = icoms_usb_ser_read; + } else { + a1logd(p->log, 8, "icoms_set_usb_port: Not a USB port!\n"); + return ICOM_NOTS; } a1logd(p->log, 6, "icoms_set_usb_port: usb port characteristics set ok\n"); -#ifndef NATIVE_USB - /* libusb doesn't have any facility for re-directing its */ - /* debug messages. Since we're moving away from it, */ - /* ignore the problem. */ - if (p->log->debug >= 8) { /* Could this go inside usb_open_port ? */ -# ifdef USE_LIBUSB1 - libusb_set_debug(NULL, p->log->debug); -# else - usb_set_debug(p->debug); -# endif - } -#endif /* NATIVE_USB */ return ICOM_OK; } @@ -575,6 +600,7 @@ icoms *p p->usb_control = icoms_usb_control; p->usb_read = icoms_usb_rw; p->usb_write = icoms_usb_rw; + p->usb_wait_io = icoms_usb_wait_io; p->usb_cancel_io = icoms_usb_cancel_io; p->usb_resetep = icoms_usb_resetep; p->usb_clearhalt = icoms_usb_clearhalt; @@ -582,4 +608,5 @@ icoms *p /* ---------------------------------------------------------------------------------*/ + #endif /* ENABLE_USB */ -- cgit v1.2.3