summaryrefslogtreecommitdiff
path: root/spectro/usbio.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/usbio.c')
-rw-r--r--spectro/usbio.c159
1 files changed, 93 insertions, 66 deletions
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 <stdio.h>
@@ -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 */