summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2013-08-28 13:21:02 -0700
committerMarcel Holtmann <marcel@holtmann.org>2013-08-28 13:21:02 -0700
commitfd087d91a0ccbf2376e8e4124c23c3a2f31d6887 (patch)
tree21cfaf554c01cdd3198132dc34fb4a935363147e
parentbd8f10e71dbbe5f0cc70e107d9218bb319cb5362 (diff)
downloadbluez-fd087d91a0ccbf2376e8e4124c23c3a2f31d6887.tar.gz
tools: Access USB device directly from bccmd without libusb
-rw-r--r--tools/bccmd.c8
-rw-r--r--tools/csr_usb.c215
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;
}