summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author(no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-08-10 21:27:01 +0000
committer(no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-08-10 21:27:01 +0000
commit4c1c0deb058ff8781362fb17fa3f5d5ac7c440d9 (patch)
tree1a9bf21b96e7ac0e5ef2352754ca834b12234328
parentf3adbdb793a66092b527f1a8232636c19f76fe58 (diff)
- add my ausb library code for async usb handling
- separate opcd_test code from core openpcd usb protocol handling routines git-svn-id: https://svn.openpcd.org:2342/trunk@99 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
-rw-r--r--openpcd/opcd_test/Makefile10
-rw-r--r--openpcd/opcd_test/ausb/Makefile21
-rw-r--r--openpcd/opcd_test/ausb/ausb.c331
-rw-r--r--openpcd/opcd_test/ausb/ausb.h68
-rw-r--r--openpcd/opcd_test/ausb/ausb_test.c95
-rw-r--r--openpcd/opcd_test/ausb/usb.c86
-rw-r--r--openpcd/opcd_test/ausb/usb.h8
-rw-r--r--openpcd/opcd_test/opcd_test.c147
-rw-r--r--openpcd/opcd_test/opcd_usb.c185
-rw-r--r--openpcd/opcd_test/opcd_usb.h23
10 files changed, 838 insertions, 136 deletions
diff --git a/openpcd/opcd_test/Makefile b/openpcd/opcd_test/Makefile
index 580e3a9..edae90f 100644
--- a/openpcd/opcd_test/Makefile
+++ b/openpcd/opcd_test/Makefile
@@ -5,11 +5,15 @@ all: opcd_test
clean:
-rm -f *.o opcd_test
+ $(MAKE) -C ausb clean
-opcd_test: opcd_test.o
- $(CC) $(LDFLAGS) -o $@ $<
+ausb/libausb.a:
+ $(MAKE) -C ausb libausb.a
-opcd_test.o: opcd_test.c
+opcd_test: opcd_test.o opcd_usb.o ausb/libausb.a
+ $(CC) $(LDFLAGS) -o $@ $^
+
+%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
.PHONEY: all clean
diff --git a/openpcd/opcd_test/ausb/Makefile b/openpcd/opcd_test/ausb/Makefile
new file mode 100644
index 0000000..6269739
--- /dev/null
+++ b/openpcd/opcd_test/ausb/Makefile
@@ -0,0 +1,21 @@
+#include ../../makevars
+
+OBJS=ausb.o usb.o
+CFLAGS+=-fPIC
+
+all: libausb.a libausb.so
+
+libausb.a: $(OBJS)
+ $(AR) r $@ $^
+
+libausb.so: $(OBJS)
+ $(LD) -x --shared -o $@ $^
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ -c $^
+
+ausb_test: ausb_test.o ausb.o
+ $(CC) $(CFLAGS) -lusb -o $@ $^
+
+clean:
+ @rm -f *.o ausb_test libusb.a libausb.a libausb.so
diff --git a/openpcd/opcd_test/ausb/ausb.c b/openpcd/opcd_test/ausb/ausb.c
new file mode 100644
index 0000000..8b0117f
--- /dev/null
+++ b/openpcd/opcd_test/ausb/ausb.c
@@ -0,0 +1,331 @@
+/* Wrapper/Extension code to libusb-0.1 to support asynchronous requests
+ * on Linux platforns
+ *
+ * (C) 2004-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Distributed and licensed under the terms of GNU LGPL, Version 2.1
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+
+#include "ausb.h"
+#include "usb.h"
+
+#ifdef DEBUG_AUSB
+#define DEBUGP(x, args...) fprintf(stderr, "%s:%s():%u " x, __FILE__, \
+ __FUNCTION__, __LINE__, ## args)
+#else
+#define DEBUGP(x, args...);
+#endif
+
+#define SIGAUSB (SIGRTMIN+1)
+
+static int ausb_get_fd(ausb_dev_handle *ah)
+{
+ return *((int *)ah->uh);
+}
+
+
+static int kernel_2_5;
+
+/* FIXME: this has to go */
+static struct ausb_dev_handle *last_handle = NULL;
+
+static int is_kernel_2_5()
+{
+ struct utsname uts;
+ int ret;
+
+ uname(&uts);
+
+ ret = (strncmp(uts.release, "2.5.", 4) == 0) ||
+ (strncmp(uts.release, "2.6.", 4) == 0);
+
+ return ret;
+}
+
+void ausb_dump_urb(struct usbdevfs_urb *uurb)
+{
+ DEBUGP("urb(%p): type=%u, endpoint=0x%x, status=%d, flags=0x%x, number_of_packets=%d, error_count=%d\n", uurb, uurb->type, uurb->endpoint, uurb->status, uurb->flags, uurb->number_of_packets, uurb->error_count);
+}
+
+void ausb_fill_int_urb(struct usbdevfs_urb *uurb, unsigned char endpoint,
+ void *buffer, int buffer_length)
+
+{
+ uurb->type = kernel_2_5 ? USBDEVFS_URB_TYPE_INTERRUPT : USBDEVFS_URB_TYPE_BULK;
+ uurb->endpoint = endpoint; /* | USB_DIR_IN; */
+ uurb->flags = kernel_2_5 ? 0 : 1 ; /* USBDEVFS_URB_QUEUE_BULK; */
+ uurb->buffer = buffer;
+ uurb->buffer_length = buffer_length;
+ uurb->signr = SIGAUSB;
+ uurb->start_frame = -1;
+}
+
+int ausb_submit_urb(ausb_dev_handle *ah, struct usbdevfs_urb *uurb)
+{
+ int ret;
+
+ DEBUGP("ah=%p\n", ah);
+ ausb_dump_urb(uurb);
+
+ /* save ausb_dev_handle in opaque usercontext field */
+ uurb->usercontext = ah;
+
+ do {
+ ret = ioctl(ausb_get_fd(ah), USBDEVFS_SUBMITURB, uurb);
+ } while (ret < 0 && errno == EINTR);
+
+ return ret;
+}
+
+int ausb_discard_urb(ausb_dev_handle *ah, struct usbdevfs_urb *uurb)
+{
+ int ret;
+
+ DEBUGP("ah=%p, uurb=%p\n");
+ ausb_dump_urb(uurb);
+
+ do {
+ ret = ioctl(ausb_get_fd(ah), USBDEVFS_DISCARDURB, uurb);
+ } while (ret < 0 && errno == EINTR);
+
+ return ret;
+}
+
+struct usbdevfs_urb *ausb_get_urb(ausb_dev_handle *ah)
+{
+ int ret;
+ struct usbdevfs_urb *uurb;
+
+ DEBUGP("entering\n");
+
+ do {
+ ret = ioctl(ausb_get_fd(ah), USBDEVFS_REAPURBNDELAY, &uurb);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0 && errno == EAGAIN) {
+ DEBUGP("ioctl returned %d (errno=%s)\n", ret,
+ strerror(errno));
+ return NULL;
+ }
+
+ DEBUGP("returning %p\n", uurb);
+ return uurb;
+}
+
+static void handle_urb(struct usbdevfs_urb *uurb)
+{
+ struct ausb_dev_handle *ah = uurb->usercontext;
+
+ DEBUGP("called, ah=%p\n", ah);
+
+ if (uurb->type >= AUSB_USBDEVFS_URB_TYPES) {
+ DEBUGP("unknown uurb type %u\n", uurb->type);
+ return;
+ }
+
+ if (!ah) {
+ DEBUGP("cant't call handler because missing ah ptr\n");
+ return;
+ }
+
+ if (!ah->cb[uurb->type].handler) {
+ DEBUGP("received URB type %u, but no handler\n", uurb->type);
+ return;
+ }
+ ah->cb[uurb->type].handler(uurb, ah->cb[uurb->type].userdata);
+}
+
+static void sigact_rtmin(int sig, siginfo_t *siginfo, void *v)
+{
+ int count;
+ struct usbdevfs_urb *urb;
+
+ if (sig != SIGAUSB)
+ return;
+
+ //DEBUGP("errno=%d, si_addr=%p\n", siginfo->errno, siginfo->si_addr);
+
+ DEBUGP("last_handle=%p\n", last_handle);
+
+ if (!last_handle)
+ return;
+
+ for (count = 0; ; count++) {
+ urb = ausb_get_urb(last_handle);
+
+ if (urb == NULL) {
+ DEBUGP("ausb_get_urb() returned urb==NULL\n");
+ break;
+ }
+
+ DEBUGP("calling handle_urb(%p)\n", urb);
+ handle_urb(urb);
+ }
+}
+
+
+int ausb_init(void)
+{
+ struct sigaction act;
+
+ DEBUGP("entering\n");
+
+ memset(&act, 0, sizeof(act));
+ act.sa_sigaction = sigact_rtmin;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+
+ sigaction(SIGAUSB, &act, NULL);
+
+ kernel_2_5 = is_kernel_2_5();
+
+ DEBUGP("kernel 2.5+ = %d\n", kernel_2_5);
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ return 1;
+}
+
+ausb_dev_handle *ausb_open(struct usb_device *dev)
+{
+ ausb_dev_handle *dh = malloc(sizeof *dh);
+
+ DEBUGP("entering, dh=%p\n", dh);
+
+ memset(dh, 0, sizeof(*dh));
+
+ dh->uh = usb_open(dev);
+
+ if (!dh->uh) {
+ DEBUGP("usb_open() failed\n");
+ free(dh);
+ return NULL;
+ }
+
+ last_handle = dh;
+ DEBUGP("last_handle = %p\n", last_handle);
+
+ return dh;
+}
+
+int ausb_register_callback(ausb_dev_handle *ah, unsigned char type,
+ void (*callback)(struct usbdevfs_urb *uurb,
+ void *userdata),
+ void *userdata)
+{
+ DEBUGP("registering callback for type %u:%p\n", type, callback);
+
+ if (type >= AUSB_USBDEVFS_URB_TYPES) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!kernel_2_5 && type == USBDEVFS_URB_TYPE_INTERRUPT)
+ type = USBDEVFS_URB_TYPE_BULK;
+
+ ah->cb[type].handler = callback;
+ ah->cb[type].userdata = userdata;
+
+ return 0;
+}
+
+int ausb_claim_interface(ausb_dev_handle *ah, int interface)
+{
+ DEBUGP("entering\n");
+ return usb_claim_interface(ah->uh, interface);
+}
+
+int ausb_release_interface(ausb_dev_handle *ah, int interface)
+{
+ DEBUGP("entering\n");
+ /* what the hell? */
+ if (ah == last_handle)
+ last_handle = NULL;
+ return usb_release_interface(ah->uh, interface);
+}
+
+int ausb_set_configuration(ausb_dev_handle *ah, int configuration)
+{
+ DEBUGP("entering\n");
+ return usb_set_configuration(ah->uh, configuration);
+}
+
+int ausb_bulk_write(ausb_dev_handle *ah, int ep, char *bytes, int size, int timeout)
+{
+ DEBUGP("entering (ah=%p, ep=0x%x, bytes=%p, size=%d, timeout=%d\n",
+ ah, ep, bytes, size, timeout);
+ return __usb_bulk_write(ah->uh, ep, bytes, size, timeout);
+}
+
+int ausb_bulk_read(ausb_dev_handle *ah, int ep, char *bytes, int size, int timeout)
+{
+ DEBUGP("entering (ah=%p, ep=0x%x, bytes=%p, size=%d, timeout=%d\n",
+ ah, ep, bytes, size, timeout);
+ return __usb_bulk_read(ah->uh, ep, bytes, size, timeout);
+}
+
+int ausb_clear_halt(ausb_dev_handle *ah, unsigned int ep)
+{
+ DEBUGP("entering (ah=%p, ep=0x%x)\n", ah, ep);
+ return usb_clear_halt(ah->uh, ep);
+}
+
+int ausb_reset(ausb_dev_handle *ah)
+{
+ DEBUGP("entering (ah=%p)\n", ah);
+ return usb_reset(ah->uh);
+}
+
+int ausb_resetep(ausb_dev_handle *ah, int ep)
+{
+ DEBUGP("entering (ah=%pm ep=0x%x)\n", ah, ep);
+ return usb_resetep(ah->uh, ep);
+}
+
+#ifdef LIBUSB_HAS_GET_DRIVER_NP
+int ausb_get_driver_np(ausb_dev_handle *ah, int interface, char *name,
+ unsigned int namelen)
+{
+ DEBUGP("entering\n");
+ return usb_get_driver_np(ah->uh, interface, name, namelen);
+}
+#endif
+
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+int ausb_detach_kernel_driver_np(ausb_dev_handle *ah, int interface)
+{
+ DEBUGP("entering\n");
+ return usb_detach_kernel_driver_np(ah->uh, interface);
+}
+int ausb_reattach_kernel_driver_np(ausb_dev_handle *ah, int interface)
+{
+ DEBUGP("entering\n");
+ return __usb_reattach_kernel_driver_np(ah->uh, interface);
+}
+#endif
+
+int ausb_close(struct ausb_dev_handle *ah)
+{
+ DEBUGP("entering\n");
+
+ if (ah == last_handle)
+ last_handle = NULL;
+
+ return usb_close(ah->uh);
+}
+
+void ausb_fini(void)
+{
+ DEBUGP("entering\n");
+ sigaction(SIGAUSB, NULL, NULL);
+}
diff --git a/openpcd/opcd_test/ausb/ausb.h b/openpcd/opcd_test/ausb/ausb.h
new file mode 100644
index 0000000..4d62cac
--- /dev/null
+++ b/openpcd/opcd_test/ausb/ausb.h
@@ -0,0 +1,68 @@
+#ifndef _AUSB_H
+#define _AUSB_H
+
+/* Wrapper/Extension code to libusb-0.1 to support asynchronous requests
+ * on Linux platforns
+ *
+ * (C) 2004 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Distributed under the terms of GNU LGPL, Version 2.1
+ */
+
+
+#include <usb.h>
+#include <linux/usbdevice_fs.h>
+
+#define AUSB_USBDEVFS_URB_TYPES 4
+
+/* structures */
+struct ausb_callback {
+ void (*handler)(struct usbdevfs_urb *uurb, void *userdata);
+ void *userdata;
+};
+
+struct ausb_dev_handle {
+ usb_dev_handle *uh;
+ struct ausb_callback cb[AUSB_USBDEVFS_URB_TYPES];
+};
+
+typedef struct ausb_dev_handle ausb_dev_handle;
+
+/* intitialization */
+int ausb_init(void);
+ausb_dev_handle *ausb_open(struct usb_device *dev);
+int ausb_close(ausb_dev_handle *ah);
+int ausb_register_callback(ausb_dev_handle *ah, unsigned char type,
+ void (*callback)(struct usbdevfs_urb *uurb,
+ void *userdata),
+ void *userdata);
+
+/* asynchronous URB related functions */
+void ausb_dump_urb(struct usbdevfs_urb *uurb);
+void ausb_fill_int_urb(struct usbdevfs_urb *uurb, unsigned char endpoint,
+ void *buffer, int buffer_length);
+int ausb_submit_urb(ausb_dev_handle *ah, struct usbdevfs_urb *uurb);
+int ausb_discard_urb(ausb_dev_handle *ah, struct usbdevfs_urb *uurb);
+struct usbdevfs_urb *ausb_get_urb(ausb_dev_handle *ah);
+
+/* synchronous functions, mostly wrappers for libusb */
+int ausb_claim_interface(ausb_dev_handle *ah, int interface);
+int ausb_release_interface(ausb_dev_handle *ah, int interface);
+int ausb_set_configuration(ausb_dev_handle *dev, int configuration);
+int ausb_clear_halt(ausb_dev_handle *dev, unsigned int ep);
+int ausb_reset(ausb_dev_handle *dev);
+int ausb_resetep(ausb_dev_handle *dev, int ep);
+int ausb_bulk_write(ausb_dev_handle *ah, int ep, char *bytes, int size,
+ int timeout);
+int ausb_bulk_read(ausb_dev_handle *ah, int ep, char *bytes, int size,
+ int timeout);
+#ifdef LIBUSB_HAS_GET_DRIVER_NP
+int ausb_get_driver_np(ausb_dev_handle *ah, int interface, char *name,
+ unsigned int namelen);
+#endif
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+int ausb_detach_kernel_driver_np(ausb_dev_handle *dev, int interface);
+int ausb_reattach_kernel_driver_np(ausb_dev_handle *dev, int interface);
+#endif
+
+#endif /* _AUSB_H */
diff --git a/openpcd/opcd_test/ausb/ausb_test.c b/openpcd/opcd_test/ausb/ausb_test.c
new file mode 100644
index 0000000..f7bfdee
--- /dev/null
+++ b/openpcd/opcd_test/ausb/ausb_test.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "ausb.h"
+
+#define CJPPA_USB_VENDOR_ID 0x0c4b
+#define CJPPA_USB_DEVICE_ID 0x0100
+
+static struct usb_device *find_cj_usbdev(int num)
+{
+ struct usb_bus *busses, *bus;
+ struct usb_device *dev;
+ int found = 0;
+
+ busses = usb_get_busses();
+
+ for (bus = busses; bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+ if (dev->descriptor.idVendor == CJPPA_USB_VENDOR_ID &&
+ dev->descriptor.idProduct == CJPPA_USB_DEVICE_ID) {
+ found++;
+ if (found == num)
+ return dev;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void int_cb(struct usbdevfs_urb *uurb)
+{
+ struct ausb_dev_handle *ah = uurb->usercontext;
+
+ fprintf(stdout, __FUNCTION__ " called, ");
+
+ ausb_dump_urb(uurb);
+
+ if (ausb_submit_urb(ah, uurb))
+ fprintf(stderr, "unable to resubmit urb\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct usb_device *dev;
+ struct ausb_dev_handle *ah;
+ struct usbdevfs_urb *uurb;
+ char buffer[280];
+ ausb_init();
+
+ uurb = malloc(sizeof(*uurb));
+
+ dev = find_cj_usbdev(1);
+
+ if (!dev) {
+ fprintf(stderr, "unable to find matching usb device\n");
+ exit(1);
+ }
+
+ ah = ausb_open(dev);
+ if (!ah) {
+ fprintf(stderr, "error while opening usb device\n");
+ exit(1);
+ }
+
+ if (ausb_claim_interface(ah, 0)) {
+ fprintf(stderr, "unable to claim interface\n");
+ ausb_close(ah);
+ exit(1);
+ }
+
+ if (usb_set_configuration(ah->uh, 1)) {
+ fprintf(stderr, "unable to set configuration 1\n");
+ ausb_close(ah);
+ exit(1);
+ }
+
+#if 1
+ ausb_fill_int_urb(uurb, 0x81, buffer, sizeof(buffer));
+ if (ausb_submit_urb(ah, uurb)) {
+ fprintf(stderr, "unable to submit urb\n");
+ ausb_close(ah);
+ exit(1);
+ }
+
+ while (1) {
+ sleep(10);
+ }
+#endif
+
+ ausb_close(ah);
+
+ exit(0);
+}
diff --git a/openpcd/opcd_test/ausb/usb.c b/openpcd/opcd_test/ausb/usb.c
new file mode 100644
index 0000000..1f1078d
--- /dev/null
+++ b/openpcd/opcd_test/ausb/usb.c
@@ -0,0 +1,86 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <usb.h>
+#include <sys/ioctl.h>
+#include <linux/usbdevice_fs.h>
+
+#define MAX_READ_WRITE 4096
+
+#define USB_ERROR_STR(ret, x, args...) return ret
+
+static int usb_get_fd(usb_dev_handle *uh)
+{
+ return *((int *)uh);
+}
+
+int __usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int length,
+ int timeout)
+{
+ struct usbdevfs_bulktransfer bulk;
+ int ret, sent = 0;
+
+ /* Ensure the endpoint address is correct */
+ ep &= ~USB_ENDPOINT_IN;
+
+ do {
+ bulk.ep = ep;
+ bulk.len = length - sent;
+ if (bulk.len > MAX_READ_WRITE)
+ bulk.len = MAX_READ_WRITE;
+ bulk.timeout = timeout;
+ bulk.data = (unsigned char *)bytes + sent;
+
+ ret = ioctl(usb_get_fd(dev), USBDEVFS_BULK, &bulk);
+ if (ret < 0)
+ USB_ERROR_STR(ret,
+ "error writing to bulk endpoint %d: %s",
+ ep, strerror(errno));
+
+ sent += ret;
+ } while (ret > 0 && sent < length);
+
+ return sent;
+}
+
+int __usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
+ int timeout)
+{
+ struct usbdevfs_bulktransfer bulk;
+ int ret, retrieved = 0, requested;
+
+ /* Ensure the endpoint address is correct */
+ ep |= USB_ENDPOINT_IN;
+
+ do {
+ bulk.ep = ep;
+ requested = size - retrieved;
+ if (requested > MAX_READ_WRITE)
+ requested = MAX_READ_WRITE;
+ bulk.len = requested;
+ bulk.timeout = timeout;
+ bulk.data = (unsigned char *)bytes + retrieved;
+
+ ret = ioctl(usb_get_fd(dev), USBDEVFS_BULK, &bulk);
+ if (ret < 0)
+ USB_ERROR_STR(ret,
+ "error reading from bulk endpoint 0x%x: %s",
+ ep, strerror(errno));
+
+ retrieved += ret;
+ } while (ret > 0 && retrieved < size && ret == requested);
+
+ return retrieved;
+}
+
+int __usb_reattach_kernel_driver_np(usb_dev_handle *dev, int interface)
+{
+ struct usbdevfs_ioctl command;
+
+ command.ifno = interface;
+ command.ioctl_code = USBDEVFS_CONNECT;
+ command.data = NULL;
+
+ return ioctl(usb_get_fd(dev), USBDEVFS_IOCTL, &command);
+}
diff --git a/openpcd/opcd_test/ausb/usb.h b/openpcd/opcd_test/ausb/usb.h
new file mode 100644
index 0000000..66be0ee
--- /dev/null
+++ b/openpcd/opcd_test/ausb/usb.h
@@ -0,0 +1,8 @@
+#ifndef _AUSB_USB_H
+#define _AUSB_USB_H
+int __usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int length,
+ int timeout);
+int __usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int length,
+ int timeout);
+int __usb_reattach_kernel_driver_np(usb_dev_handle *dev, int interface);
+#endif
diff --git a/openpcd/opcd_test/opcd_test.c b/openpcd/opcd_test/opcd_test.c
index 6b99792..c9faa92 100644
--- a/openpcd/opcd_test/opcd_test.c
+++ b/openpcd/opcd_test/opcd_test.c
@@ -31,109 +31,8 @@
#include <usb.h>
#include "openpcd.h"
+#include "opcd_usb.h"
-const char *
-hexdump(const void *data, unsigned int len)
-{
- static char string[65535];
- unsigned char *d = (unsigned char *) data;
- unsigned int i, left, ofs;
-
- string[0] = '\0';
- ofs = snprintf(string, sizeof(string)-1, "(%u): ", len);
-
- left = sizeof(string) - ofs;
- for (i = 0; len--; i += 3) {
- if (i >= sizeof(string) -4)
- break;
- snprintf(string+ofs+i, 4, " %02x", *d++);
- }
- string[sizeof(string)-1] = '\0';
- return string;
-}
-
-#define OPCD_VENDOR_ID 0x2342
-#define OPCD_PRODUCT_ID 0x0001
-#define OPCD_OUT_EP 0x01
-#define OPCD_IN_EP 0x82
-
-static struct usb_dev_handle *hdl;
-static struct usb_device *find_opcd_device(void)
-{
- struct usb_bus *bus;
-
- for (bus = usb_busses; bus; bus = bus->next) {
- struct usb_device *dev;
- for (dev = bus->devices; dev; dev = dev->next) {
- if (dev->descriptor.idVendor == OPCD_VENDOR_ID
- && dev->descriptor.idProduct == OPCD_PRODUCT_ID
- && dev->descriptor.iManufacturer == 0
- && dev->descriptor.iProduct == 0
- && dev->descriptor.bNumConfigurations == 1
- && dev->config->bNumInterfaces == 1
- && dev->config->iConfiguration == 0)
- return dev;
- }
- }
- return NULL;
-}
-
-static int opcd_recv_reply(void)
-{
- char buf[8192];
- int ret, i;
-
- memset(buf, 0, sizeof(buf));
-
- ret = usb_bulk_read(hdl, OPCD_IN_EP, buf, sizeof(buf), 1000);
-
- if (ret < 0) {
- fprintf(stderr, "bulk_read returns %d(%s)\n", ret,
- usb_strerror());
- return ret;
- }
-
- printf("RX: %s\n", hexdump(buf, ret));
-
- return ret;
-}
-
-
-static int opcd_send_command(u_int8_t cmd, u_int8_t reg, u_int8_t val, u_int16_t len,
- const unsigned char *data)
-{
- unsigned char buf[8192];
- struct openpcd_hdr *ohdr = (struct openpcd_hdr *)buf;
- int cur = 0;
- int ret;
-
- memset(buf, 0, sizeof(buf));
-
- ohdr->cmd = cmd;
- ohdr->reg = reg;
- ohdr->val = val;
- ohdr->len = len;
- if (data && len)
- memcpy(ohdr->data, data, len);
-
- cur = sizeof(*ohdr) + len;
-
- printf("TX: %s\n", hexdump(buf, cur));
-
- ret = usb_bulk_write(hdl, OPCD_OUT_EP, buf, cur, 0);
- if (ret < 0) {
- fprintf(stderr, "bulk_write returns %d(%s)\n", ret,
- usb_strerror());
- return ret;
- }
-
- /* this usleep is required in order to make the process work.
- * apparently some race condition in the bootloader if we feed
- * data too fast */
- usleep(5000);
-
- //return ezx_blob_recv_reply();
-}
static int get_number(const char *optarg, unsigned int min,
unsigned int max, unsigned int *num)
{
@@ -166,6 +65,7 @@ static void print_help(void)
"\t-c\t--clear-bits\treg\tmask\n");
}
+
static struct option opts[] = {
{ "led-set", 1, 0, 'l' },
{ "reg-write", 1, 0, 'w' },
@@ -179,33 +79,14 @@ static struct option opts[] = {
int main(int argc, char **argv)
{
- struct usb_device *dev;
+ struct opcd_handle *od;
int c;
+ static char buf[8192];
+ int buf_len = sizeof(buf);
print_welcome();
- usb_init();
- if (!usb_find_busses())
- exit(1);
- if (!usb_find_devices())
- exit(1);
-
- dev = find_opcd_device();
- if (!dev) {
- printf("Cannot find OpenPCD device. Are you sure it is connected?\n");
- exit(1);
- }
-
- hdl = usb_open(dev);
- if (!hdl) {
- printf("Unable to open usb device: %s\n", usb_strerror());
- exit(1);
- }
-
- if (usb_claim_interface(hdl, 0) < 0) {
- printf("Unable to claim usb interface 1 of device: %s\n", usb_strerror());
- exit(1);
- }
+ od = opcd_init();
while (1) {
int option_index = 0;
@@ -224,14 +105,14 @@ int main(int argc, char **argv)
if (get_number(argv[optind], 0, 1, &j) < 0)
exit(2);
printf("setting LED %d to %s\n", i, j ? "on" : "off");
- opcd_send_command(OPENPCD_CMD_SET_LED, i, j, 0, NULL);
+ opcd_send_command(od, OPENPCD_CMD_SET_LED, i, j, 0, NULL);
break;
case 'r':
if (get_number(optarg, 0x00, OPENPCD_REG_MAX, &i) < 0)
exit(2);
printf("reading register 0x%02x: ");
- opcd_send_command(OPENPCD_CMD_READ_REG, i, 0, 0, NULL);
- opcd_recv_reply();
+ opcd_send_command(od, OPENPCD_CMD_READ_REG, i, 0, 0, NULL);
+ opcd_recv_reply(od, buf, buf_len);
break;
case 'w':
if (get_number(optarg, 0x00, OPENPCD_REG_MAX, &i) < 0) {
@@ -243,13 +124,13 @@ int main(int argc, char **argv)
exit(2);
}
fprintf(stdout, "setting register 0x%02x to 0x%02x\n", i, j);
- opcd_send_command(OPENPCD_CMD_WRITE_REG, i, j, 0, NULL);
+ opcd_send_command(od, OPENPCD_CMD_WRITE_REG, i, j, 0, NULL);
break;
case 'R':
if (get_number(optarg, 0x00, OPENPCD_REG_MAX, &i) < 0)
exit(2);
- opcd_send_command(OPENPCD_CMD_READ_FIFO, 0, i, 0, NULL);
- opcd_recv_reply();
+ opcd_send_command(od, OPENPCD_CMD_READ_FIFO, 0, i, 0, NULL);
+ opcd_recv_reply(od, buf, buf_len);
break;
case 'W':
fprintf(stderr, "FIFO write not implemented yet\n");
@@ -259,14 +140,14 @@ int main(int argc, char **argv)
exit(2);
if (get_number(argv[optind], 0x00, 0xff, &j) < 0)
exit(2);
- opcd_send_command(OPENPCD_CMD_REG_BITS_SET, i, j, 0, NULL);
+ opcd_send_command(od, OPENPCD_CMD_REG_BITS_SET, i, j, 0, NULL);
break;
case 'c':
if (get_number(optarg, 0x00, OPENPCD_REG_MAX, &i) < 0)
exit(2);
if (get_number(argv[optind], 0x00, 0xff, &j) < 0)
exit(2);
- opcd_send_command(OPENPCD_CMD_REG_BITS_CLEAR, i, j, 0, NULL);
+ opcd_send_command(od, OPENPCD_CMD_REG_BITS_CLEAR, i, j, 0, NULL);
break;
case 'h':
case '?':
diff --git a/openpcd/opcd_test/opcd_usb.c b/openpcd/opcd_test/opcd_usb.c
new file mode 100644
index 0000000..70b40a0
--- /dev/null
+++ b/openpcd/opcd_test/opcd_usb.c
@@ -0,0 +1,185 @@
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "ausb/ausb.h"
+#include "openpcd.h"
+
+#include "opcd_usb.h"
+
+const char *
+opcd_hexdump(const void *data, unsigned int len)
+{
+ static char string[65535];
+ unsigned char *d = (unsigned char *) data;
+ unsigned int i, left, ofs;
+
+ string[0] = '\0';
+ ofs = snprintf(string, sizeof(string)-1, "(%u): ", len);
+
+ left = sizeof(string) - ofs;
+ for (i = 0; len--; i += 3) {
+ if (i >= sizeof(string) -4)
+ break;
+ snprintf(string+ofs+i, 4, " %02x", *d++);
+ }
+ string[sizeof(string)-1] = '\0';
+ return string;
+}
+
+#define OPCD_VENDOR_ID 0x2342
+#define OPCD_PRODUCT_ID 0x0001
+#define OPCD_OUT_EP 0x01
+#define OPCD_IN_EP 0x82
+#define OPCD_INT_EP 0x83
+
+static struct usb_device *find_opcd_handle(void)
+{
+ struct usb_bus *bus;
+
+ for (bus = usb_busses; bus; bus = bus->next) {
+ struct usb_device *dev;
+ for (dev = bus->devices; dev; dev = dev->next) {
+ if (dev->descriptor.idVendor == OPCD_VENDOR_ID
+ && dev->descriptor.idProduct == OPCD_PRODUCT_ID
+ && dev->descriptor.iManufacturer == 0
+ && dev->descriptor.iProduct == 0
+ && dev->descriptor.bNumConfigurations == 1
+ && dev->config->bNumInterfaces == 1
+ && dev->config->iConfiguration == 0)
+ return dev;
+ }
+ }
+ return NULL;
+}
+
+static void opcd_dump_hdr(struct openpcd_hdr *hdr)
+{
+ printf("IRQ: cmd=0x%02x, flags=0x%02x, reg=0x%02x, val=0x%02x "
+ "len=%d, res=%d\n", hdr->cmd, hdr->flags, hdr->reg,
+ hdr->val, hdr->len);
+}
+
+static void handle_interrupt(struct usbdevfs_urb *uurb, void *userdata)
+{
+ struct opcd_handle *od = userdata;
+ ausb_dev_handle *ah;
+ struct openpcd_hdr *opcdh;
+
+ if (!uurb) {
+ fprintf(stderr, "interrupt with no URB?!?\n");
+ return;
+ }
+
+ ah = uurb->usercontext;
+
+ opcdh = (struct openpcd_hdr *)uurb->buffer;
+ opcd_dump_hdr(opcdh);
+
+ if (ausb_submit_urb(ah, uurb))
+ fprintf(stderr, "unable to resubmit interupt urb\n");
+}
+
+struct opcd_handle *opcd_init(void)
+{
+ struct opcd_handle *oh;
+ struct usb_device *dev;
+
+ oh = malloc(sizeof(*oh));
+ if (!oh)
+ return NULL;
+
+ memset(oh, 0, sizeof(*oh));
+
+ ausb_init();
+
+ dev = find_opcd_handle();
+ if (!dev) {
+ fprintf(stderr, "Cannot find OpenPCD device. "
+ "Are you sure it is connected?\n");
+ exit(1);
+ }
+
+ oh->hdl = ausb_open(dev);
+ if (!oh->hdl) {
+ fprintf(stderr, "Unable to open usb device: %s\n",
+ usb_strerror());
+ exit(1);
+ }
+
+ if (ausb_claim_interface(oh->hdl, 0) < 0) {
+ fprintf(stderr, "Unable to claim usb interface "
+ "1 of device: %s\n", usb_strerror());
+ exit(1);
+ }
+
+ ausb_fill_int_urb(&oh->int_urb, OPCD_INT_EP, oh->int_buf,
+ sizeof(oh->int_buf));
+ if (ausb_register_callback(oh->hdl, USBDEVFS_URB_TYPE_INTERRUPT,
+ handle_interrupt, oh)) {
+ fprintf(stderr, "unable to submit interrupt urb");
+ exit(1);
+ }
+
+ return oh;
+}
+
+void opcd_fini(struct opcd_handle *od)
+{
+ ausb_discard_urb(od->hdl, &od->int_urb);
+ ausb_close(od->hdl);
+}
+
+int opcd_recv_reply(struct opcd_handle *od, char *buf, int len)
+{
+ int ret, i;
+
+ memset(buf, 0, sizeof(buf));
+
+ ret = ausb_bulk_read(od->hdl, OPCD_IN_EP, buf, len, 1000);
+
+ if (ret < 0) {
+ fprintf(stderr, "bulk_read returns %d(%s)\n", ret,
+ usb_strerror());
+ return ret;
+ }
+
+ printf("RX: %s\n", opcd_hexdump(buf, ret));
+ opcd_dump_hdr((struct openpcd_hdr *)buf);
+
+ return ret;
+}
+
+
+int opcd_send_command(struct opcd_handle *od, u_int8_t cmd,
+ u_int8_t reg, u_int8_t val, u_int16_t len,
+ const unsigned char *data)
+{
+ unsigned char buf[128];
+ struct openpcd_hdr *ohdr = (struct openpcd_hdr *)buf;
+ int cur = 0;
+ int ret;
+
+ memset(buf, 0, sizeof(buf));
+
+ ohdr->cmd = cmd;
+ ohdr->reg = reg;
+ ohdr->val = val;
+ ohdr->len = len;
+ if (data && len)
+ memcpy(ohdr->data, data, len);
+
+ cur = sizeof(*ohdr) + len;
+
+ printf("TX: %s\n", opcd_hexdump(buf, cur));
+
+ ret = ausb_bulk_write(od->hdl, OPCD_OUT_EP, buf, cur, 0);
+ if (ret < 0) {
+ fprintf(stderr, "bulk_write returns %d(%s)\n", ret,
+ usb_strerror());
+ return ret;
+ }
+}
diff --git a/openpcd/opcd_test/opcd_usb.h b/openpcd/opcd_test/opcd_usb.h
new file mode 100644
index 0000000..953f983
--- /dev/null
+++ b/openpcd/opcd_test/opcd_usb.h
@@ -0,0 +1,23 @@
+#ifndef _OPCD_USB_H
+#define _OPCD_USB_H
+
+#include "ausb/ausb.h"
+
+#define OPCD_INTBUF_SIZE 64
+struct opcd_handle {
+ struct ausb_dev_handle *hdl;
+ struct usbdevfs_urb int_urb;
+ u_int8_t int_buf[OPCD_INTBUF_SIZE];
+};
+
+extern const char *opcd_hexdump(const void *data, unsigned int len);
+
+extern struct opcd_handle *opcd_init(void);
+extern void opcd_fini(struct opcd_handle *od);
+
+extern int opcd_recv_reply(struct opcd_handle *od, char *buf, int len);
+extern int opcd_send_command(struct opcd_handle *od, u_int8_t cmd,
+ u_int8_t reg, u_int8_t val, u_int16_t len,
+ const unsigned char *data);
+
+#endif
personal git repositories of Harald Welte. Your mileage may vary