diff -ruN Argyll_V1.6.3.orig/spectro/usbio.c Argyll_V1.6.3/spectro/usbio.c --- Argyll_V1.6.3.orig/spectro/usbio.c 2014-01-31 05:08:57.000000000 +0100 +++ Argyll_V1.6.3/spectro/usbio.c 2015-03-13 09:04:25.067416774 +0100 @@ -353,7 +353,8 @@ static int icoms_usb_ser_write( icoms *p, -char *wbuf, +char *wbuf, /* null terminated unless nch > 0 */ +int nwch, /* if > 0, number of characters to write */ double tout) { int len, wbytes; @@ -385,7 +386,10 @@ else type = icom_usb_trantype_interrutpt; - len = strlen(wbuf); + if (nwch != 0) + len = nwch; + else + len = strlen(wbuf); tout *= 1000.0; /* Timout in msec */ top = (int)(tout + 0.5); /* Timeout period in msecs */ @@ -430,8 +434,9 @@ icoms_usb_ser_read(icoms *p, char *rbuf, /* Buffer to store characters read */ int bsize, /* Buffer size */ -char *tc, /* Terminating characers, NULL if none */ -int ntc, /* Number of terminating characters needed to terminate */ +int *pbread, /* Bytes read (not including forced '\000') */ +char *tc, /* Terminating characers, NULL for none or char count mode */ +int ntc, /* Number of terminating characters or char count needed, if 0 use bsize */ double tout) /* Time out in seconds */ { int j, rbytes; @@ -442,10 +447,6 @@ icom_usb_trantype type; /* bulk or interrupt */ int retrv = ICOM_OK; -#ifdef QUIET_MEMCHECKERS - memset(rbuf, 0, bsize); -#endif - if (!p->is_open) { a1loge(p->log, ICOM_SYS, "icoms_usb_ser_read: device is not open\n"); return ICOM_SYS; @@ -472,7 +473,8 @@ return ICOM_SYS; } - for (j = 0; j < bsize; j++) rbuf[j] = 0; + for (j = 0; j < bsize; j++) + rbuf[j] = 0; bsize -= 1; /* Allow space for null */ bsize -= p->ms_bytes; /* Allow space for modem status bytes */ @@ -487,9 +489,11 @@ a1logd(p->log, 8, "\nicoms_usb_ser_read: ep 0x%x, ttop %d, quant %d\n", p->rd_ep, ttop, p->rd_qa); /* Until data is all read, we time out, or the user aborts */ - stime = msec_time(); + etime = stime = msec_time(); top = ttop; - for (j = 0; top > 0 && bsize > 1 && j < ntc ;) { + j = (tc == NULL && ntc <= 0) ? -1 : 0; + + for (; top > 0 && bsize > 0 && j < ntc ;) { int c, rv; int rsize = p->rd_qa < bsize ? p->rd_qa : bsize; @@ -503,9 +507,10 @@ /* 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; + a1logd(p->log, 8, "icoms_usb_ser_read: discarded %d modem bytes 0x%02x 0x%02x\n",nb,nb >= 1 ? (rbuf[0] & 0xff) : 0, nb >= 2 ? (rbuf[1] & 0xff) : 0); rbytes -= nb; memmove(rbuf, rbuf+nb, rbytes); - a1logd(p->log, 8, "icoms_usb_ser_read: discarded %d modem bytes\n",nb); + rbuf[rbytes] = 0; } a1logd(p->log, 8, "icoms_usb_ser_read: read %d bytes, rbuf = '%s'\n",rbytes,icoms_fix(rrbuf)); @@ -521,7 +526,10 @@ tcp++; } } + a1logd(p->log, 8, "icoms_usb_ser_read: tc count %d\n",j); } else { + if (ntc > 0) + j += rbytes; rbuf += rbytes; } } @@ -534,14 +542,20 @@ } 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'; + a1logd(p->log, 8, "icoms_usb_ser_read: read %d total bytes\n",rbuf - rrbuf); + if (pbread != NULL) + *pbread = (rbuf - rrbuf); + + /* If ran out of time and not completed */ + a1logd(p->log, 8, "icoms_usb_ser_read: took %d msec\n",etime - stime); + if (top <= 0 && bsize > 0 && j < ntc) { + a1logd(p->log, 8, "icoms_usb_ser_read: read ran out of time\n"); + a1logd(p->log, 8, "ttop %d, etime - stime %d\n",ttop,etime - stime); + retrv |= ICOM_TO; + } a1logd(p->log, 8, "icoms_usb_ser_read: returning '%s' ICOM err 0x%x\n",icoms_fix(rrbuf),retrv); diff -ruN Argyll_V1.6.3.orig/spectro/usbio_lx.c Argyll_V1.6.3/spectro/usbio_lx.c --- Argyll_V1.6.3.orig/spectro/usbio_lx.c 2014-01-31 05:08:58.000000000 +0100 +++ Argyll_V1.6.3/spectro/usbio_lx.c 2015-03-13 09:09:46.459415189 +0100 @@ -460,8 +460,11 @@ if ((rv = p->usbd->fd = open(p->usbd->dpath, O_RDWR)) < 0) { a1logd(p->log, 8, "usb_open_port: open '%s' config %d failed (%d) (Permissions ?)\n",p->usbd->dpath,config,rv); if (retries <= 0) { - if (kpc != NULL) - kpc->del(kpc); + if (kpc != NULL) { + if (kpc->th->result < 0) + a1logw(p->log, "usb_open_port: killing competing processes failed\n"); + kpc->del(kpc); + } a1loge(p->log, ICOM_SYS, "usb_open_port: open '%s' config %d failed (%d) (Permissions ?)\n",p->usbd->dpath,config,rv); return ICOM_SYS; } @@ -636,25 +639,53 @@ pa[0].events = POLLIN | POLLOUT; pa[0].revents = 0; + /* Setup to wait for a shutdown signal via the sd_pipe */ pa[1].fd = p->usbd->sd_pipe[0]; pa[1].events = POLLIN; pa[1].revents = 0; - /* Wait for fd to become ready or shutdown */ - if ((rv = poll_x(pa, 2, -1)) < 0 || pa[1].revents || pa[0].revents == 0) { - a1logd(p->log, 6, "urb_reaper: poll returned %d and events %d %d\n",rv,pa[0].revents,pa[1].revents); + /* Wait for fd to become ready or fail */ + rv = poll_x(pa, 2, -1); + + /* Failed */ + if (rv < 0) { + a1logd(p->log, 2, "urb_reaper: poll failed with %d\n",rv); + if (errc++ < 5) { + continue; + } + a1logd(p->log, 2, "urb_reaper: poll failed too many times - shutting down\n"); p->usbd->shutdown = 1; break; } + /* Shutdown event */ + if (pa[1].revents != 0) { + a1logd(p->log, 6, "urb_reaper: poll returned events %d %d - shutting down\n", + pa[0].revents,pa[1].revents); + p->usbd->shutdown = 1; + break; + } + + /* Hmm. poll returned without event from fd. */ + if (pa[0].revents == 0) { + a1logd(p->log, 6, "urb_reaper: poll returned events %d %d - ignoring\n", + pa[0].revents,pa[1].revents); + continue; + } + /* Not sure what this returns if there is nothing there */ rv = ioctl(p->usbd->fd, USBDEVFS_REAPURBNDELAY, &out); + if (rv == EAGAIN) { + a1logd(p->log, 2, "urb_reaper: reap returned EAGAIN - ignored\n"); + continue; + } if (rv < 0) { a1logd(p->log, 2, "urb_reaper: reap failed with %d\n",rv); if (errc++ < 5) { continue; } + a1logd(p->log, 2, "urb_reaper: reap failed too many times - shutting down\n"); p->usbd->shutdown = 1; break; } @@ -662,7 +693,7 @@ errc = 0; if (out == NULL) { - a1logd(p->log, 2, "urb_reaper: reap returned NULL URB\n"); + a1logd(p->log, 2, "urb_reaper: reap returned NULL URB - ignored\n"); continue; } @@ -803,7 +834,7 @@ bp += req.urbs[i].urb.buffer_length; req.urbs[i].urb.status = -EINPROGRESS; } -a1logd(p->log, 8, "icoms_usb_transaction: reset req 0x%p nourbs to %d\n",&req,req.nourbs); +a1logd(p->log, 8, "icoms_usb_transaction: reset req %p nourbs to %d\n",&req,req.nourbs); /* Add our request to the req list so that it can be cancelled on reap failure */ pthread_mutex_lock(&p->usbd->lock);