diff options
| -rw-r--r-- | openpcd/opcd_test/Makefile | 10 | ||||
| -rw-r--r-- | openpcd/opcd_test/ausb/Makefile | 21 | ||||
| -rw-r--r-- | openpcd/opcd_test/ausb/ausb.c | 331 | ||||
| -rw-r--r-- | openpcd/opcd_test/ausb/ausb.h | 68 | ||||
| -rw-r--r-- | openpcd/opcd_test/ausb/ausb_test.c | 95 | ||||
| -rw-r--r-- | openpcd/opcd_test/ausb/usb.c | 86 | ||||
| -rw-r--r-- | openpcd/opcd_test/ausb/usb.h | 8 | ||||
| -rw-r--r-- | openpcd/opcd_test/opcd_test.c | 147 | ||||
| -rw-r--r-- | openpcd/opcd_test/opcd_usb.c | 185 | ||||
| -rw-r--r-- | openpcd/opcd_test/opcd_usb.h | 23 | 
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  | 
