diff options
Diffstat (limited to 'spectro/usbio_lx.c')
-rw-r--r-- | spectro/usbio_lx.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/spectro/usbio_lx.c b/spectro/usbio_lx.c index 44307fd..7cc37e6 100644 --- a/spectro/usbio_lx.c +++ b/spectro/usbio_lx.c @@ -460,8 +460,11 @@ char **pnames /* List of process names to try and kill before opening */ 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) + 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 @@ static void *urb_reaper(void *context) { 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 @@ static void *urb_reaper(void *context) { 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; } @@ -710,7 +741,7 @@ static void *urb_reaper(void *context) { pthread_mutex_lock(&req->lock); for (i = req->nourbs-1; i >= 0; i--) { - req->urbs[i].urb.status = ICOM_SYS; + req->urbs[i].urb.status = -ENOMSG; /* Use ENOMSG as error marker */ } req->nourbs = 0; pthread_cond_signal(&req->cond); @@ -803,7 +834,7 @@ static int icoms_usb_transaction( 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); @@ -815,7 +846,7 @@ a1logd(p->log, 8, "icoms_usb_transaction: reset req 0x%p nourbs to %d\n",&req,re for (i = 0; i < req.nurbs; i++) { if ((rv = ioctl(p->usbd->fd, USBDEVFS_SUBMITURB, &req.urbs[i].urb)) < 0) { a1logd(p->log, 1, "coms_usb_transaction: Submitting urb to fd %d failed with %d\n",p->usbd->fd, rv); - req.urbs[i].urb.status = ICOM_SYS; /* Mark it as failed to submit */ + req.urbs[i].urb.status = -ENOMSG; /* Mark it as failed to submit */ req.nourbs--; } } @@ -824,7 +855,7 @@ a1logd(p->log, 8, "icoms_usb_transaction: reset req 0x%p nourbs to %d\n",&req,re amutex_lock(cancelt->cmtx); cancelt->hcancel = (void *)&req; cancelt->state = 1; - amutex_unlock(cancelt->cond); /* Signal any thread waiting for IO start */ + amutex_unlock(cancelt->condx); /* Signal any thread waiting for IO start */ amutex_unlock(cancelt->cmtx); } @@ -887,7 +918,7 @@ a1logd(p->log, 8, "icoms_usb_transaction: reset req 0x%p nourbs to %d\n",&req,re int stat = req.urbs[i].urb.status; xlength += req.urbs[i].urb.actual_length; - if (stat == ICOM_SYS) { /* Submit or cancel failed */ + if (stat == -ENOMSG) { /* Submit or cancel failed */ reqrv = ICOM_SYS; } else if (reqrv == ICOM_OK && stat < 0 && stat != -ECONNRESET) { /* Error result */ if ((endpoint & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT) @@ -919,7 +950,7 @@ done:; amutex_lock(cancelt->cmtx); cancelt->hcancel = (void *)NULL; if (cancelt->state == 0) - amutex_unlock(cancelt->cond); + amutex_unlock(cancelt->condx); cancelt->state = 2; amutex_unlock(cancelt->cmtx); } |