diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2013-08-28 13:21:02 -0700 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2013-08-28 13:21:02 -0700 |
commit | fd087d91a0ccbf2376e8e4124c23c3a2f31d6887 (patch) | |
tree | 21cfaf554c01cdd3198132dc34fb4a935363147e | |
parent | bd8f10e71dbbe5f0cc70e107d9218bb319cb5362 (diff) | |
download | bluez-fd087d91a0ccbf2376e8e4124c23c3a2f31d6887.tar.gz |
tools: Access USB device directly from bccmd without libusb
-rw-r--r-- | tools/bccmd.c | 8 | ||||
-rw-r--r-- | tools/csr_usb.c | 215 |
2 files changed, 168 insertions, 55 deletions
diff --git a/tools/bccmd.c b/tools/bccmd.c index 952bf131d..ff1b30763 100644 --- a/tools/bccmd.c +++ b/tools/bccmd.c @@ -64,10 +64,8 @@ static inline int transport_open(int transport, char *device, speed_t bcsp_rate) switch (transport) { case CSR_TRANSPORT_HCI: return csr_open_hci(device); -#ifdef HAVE_LIBUSB case CSR_TRANSPORT_USB: return csr_open_usb(device); -#endif case CSR_TRANSPORT_BCSP: return csr_open_bcsp(device, bcsp_rate); case CSR_TRANSPORT_H4: @@ -85,10 +83,8 @@ static inline int transport_read(int transport, uint16_t varid, uint8_t *value, switch (transport) { case CSR_TRANSPORT_HCI: return csr_read_hci(varid, value, length); -#ifdef HAVE_LIBUSB case CSR_TRANSPORT_USB: return csr_read_usb(varid, value, length); -#endif case CSR_TRANSPORT_BCSP: return csr_read_bcsp(varid, value, length); case CSR_TRANSPORT_H4: @@ -106,10 +102,8 @@ static inline int transport_write(int transport, uint16_t varid, uint8_t *value, switch (transport) { case CSR_TRANSPORT_HCI: return csr_write_hci(varid, value, length); -#ifdef HAVE_LIBUSB case CSR_TRANSPORT_USB: return csr_write_usb(varid, value, length); -#endif case CSR_TRANSPORT_BCSP: return csr_write_bcsp(varid, value, length); case CSR_TRANSPORT_H4: @@ -128,11 +122,9 @@ static inline void transport_close(int transport) case CSR_TRANSPORT_HCI: csr_close_hci(); break; -#ifdef HAVE_LIBUSB case CSR_TRANSPORT_USB: csr_close_usb(); break; -#endif case CSR_TRANSPORT_BCSP: csr_close_bcsp(); break; diff --git a/tools/csr_usb.c b/tools/csr_usb.c index 19903b0c3..88181e9d1 100644 --- a/tools/csr_usb.c +++ b/tools/csr_usb.c @@ -27,80 +27,197 @@ #include <stdio.h> #include <errno.h> +#include <ctype.h> +#include <fcntl.h> +#include <unistd.h> #include <string.h> - -#include <usb.h> +#include <dirent.h> +#include <sys/ioctl.h> #include "csr.h" -#ifdef NEED_USB_GET_BUSSES -static inline struct usb_bus *usb_get_busses(void) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +#define USB_ENDPOINT_IN 0x80 +#define USB_ENDPOINT_OUT 0x00 + +struct usbfs_ctrltransfer { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint32_t timeout; /* in milliseconds */ + void *data; /* pointer to data */ +}; + +struct usbfs_bulktransfer { + unsigned int ep; + unsigned int len; + unsigned int timeout; /* in milliseconds */ + void *data; /* pointer to data */ +}; + +#define USBFS_IOCTL_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer) +#define USBFS_IOCTL_BULK _IOWR('U', 2, struct usbfs_bulktransfer) +#define USBFS_IOCTL_CLAIMINTF _IOR('U', 15, unsigned int) +#define USBFS_IOCTL_RELEASEINTF _IOR('U', 16, unsigned int) + +static int read_value(const char *name, const char *attr, const char *format) { - return usb_busses; + char path[PATH_MAX]; + FILE *file; + int n, value; + + snprintf(path, sizeof(path), "/sys/bus/usb/devices/%s/%s", name, attr); + + file = fopen(path, "r"); + if (!file) + return -1; + + n = fscanf(file, format, &value); + if (n != 1) + return -1; + + return value; } -#endif -#ifdef NEED_USB_INTERRUPT_READ -static inline int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) +static char *check_device(const char *name) { - return usb_bulk_read(dev, ep, bytes, size, timeout); -} -#endif + char path[PATH_MAX]; + int busnum, devnum, vendor, product; -#ifndef USB_DIR_OUT -#define USB_DIR_OUT 0x00 -#endif + busnum = read_value(name, "busnum", "%d"); + if (busnum < 0) + return NULL; -static uint16_t seqnum = 0x0000; + devnum = read_value(name, "devnum", "%d"); + if (devnum < 0) + return NULL; -static struct usb_dev_handle *udev = NULL; + snprintf(path, sizeof(path), "/dev/bus/usb/%03u/%03u", busnum, devnum); -int csr_open_usb(char *device) + vendor = read_value(name, "idVendor", "%04x"); + if (vendor < 0) + return NULL; + + product = read_value(name, "idProduct", "%04x"); + if (product < 0) + return NULL; + + if (vendor != 0x0a12 || product != 0x0001) + return NULL; + + return strdup(path); +} + +static char *find_device(void) { - struct usb_bus *bus; - struct usb_device *dev; + char *path = NULL; + DIR *dir; - usb_init(); + dir = opendir("/sys/bus/usb/devices"); + if (!dir) + return NULL; - usb_find_busses(); - usb_find_devices(); + while (1) { + struct dirent *d; - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - if (dev->descriptor.bDeviceClass == USB_CLASS_HUB) - continue; + d = readdir(dir); + if (!d) + break; - if (dev->descriptor.idVendor != 0x0a12 || - dev->descriptor.idProduct != 0x0001) - continue; + if ((!isdigit(d->d_name[0]) && strncmp(d->d_name, "usb", 3)) + || strchr(d->d_name, ':')) + continue; - goto found; - } + path = check_device(d->d_name); + if (path) + break; } - fprintf(stderr, "Device not available\n"); + closedir(dir); - return -1; + return path; +} -found: - udev = usb_open(dev); - if (!udev) { +static uint16_t seqnum = 0x0000; +static int handle = -1; + +int csr_open_usb(char *device) +{ + int interface = 0; + char *path; + + path = find_device(); + if (!path) { + fprintf(stderr, "Device not available\n"); + return -1; + } + + handle = open(path, O_RDWR, O_CLOEXEC | O_NONBLOCK); + if (handle < 0) { fprintf(stderr, "Can't open device: %s (%d)\n", strerror(errno), errno); return -1; } - if (usb_claim_interface(udev, 0) < 0) { + if (ioctl(handle, USBFS_IOCTL_CLAIMINTF, &interface) < 0) { fprintf(stderr, "Can't claim interface: %s (%d)\n", strerror(errno), errno); - usb_close(udev); + close(handle); + handle = -1; return -1; } return 0; } -static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length) +static int control_write(int fd, void *data, unsigned short size) +{ + struct usbfs_ctrltransfer transfer; + + transfer.bmRequestType = USB_TYPE_CLASS | USB_ENDPOINT_OUT | + USB_RECIP_DEVICE; + transfer.bRequest = 0; + transfer.wValue = 0; + transfer.wIndex = 0; + transfer.wLength = size, + transfer.timeout = 2000; + transfer.data = data; + + if (ioctl(fd, USBFS_IOCTL_CONTROL, &transfer) < 0) { + fprintf(stderr, "Control transfer failed: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + return 0; +} + +static int interrupt_read(int fd, unsigned char endpoint, + void *data, unsigned short size) +{ + struct usbfs_bulktransfer transfer; + + transfer.ep = endpoint; + transfer.len = size, + transfer.timeout = 20; + transfer.data = data; + + return ioctl(fd, USBFS_IOCTL_BULK, &transfer); +} + +static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, + uint8_t *value, uint16_t length) { unsigned char cp[254], rp[254]; uint8_t cmd[10]; @@ -128,11 +245,9 @@ static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t memcpy(cp + 4, cmd, sizeof(cmd)); memcpy(cp + 14, value, length); - usb_interrupt_read(udev, 0x81, (void *) rp, sizeof(rp), 2); + interrupt_read(handle, 0x81, rp, sizeof(rp)); - if (usb_control_msg(udev, USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_DEVICE, - 0, 0, 0, (void *) cp, (size * 2) + 4, 1000) < 0) - return -1; + control_write(handle, cp, (size * 2) + 4); switch (varid) { case CSR_VARID_COLD_RESET: @@ -143,8 +258,10 @@ static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t } do { - len = usb_interrupt_read(udev, 0x81, - (void *) (rp + offset), sizeof(rp) - offset, 10); + len = interrupt_read(handle, 0x81, + rp + offset, sizeof(rp) - offset); + if (len < 0) + break; offset += len; } while (len > 0); @@ -175,6 +292,10 @@ int csr_write_usb(uint16_t varid, uint8_t *value, uint16_t length) void csr_close_usb(void) { - usb_release_interface(udev, 0); - usb_close(udev); + int interface = 0; + + ioctl(handle, USBFS_IOCTL_RELEASEINTF, &interface); + + close(handle); + handle = -1; } |