25 #define LOG_TAG "usbhost" 42 #include <sys/ioctl.h> 43 #include <sys/types.h> 45 #include <sys/inotify.h> 53 #include <linux/usbdevice_fs.h> 54 #include <asm/byteorder.h> 58 #define DEV_DIR "/dev" 59 #define DEV_BUS_DIR DEV_DIR "/bus" 60 #define USB_FS_DIR DEV_BUS_DIR "/usb" 61 #define USB_FS_ID_SCANNER USB_FS_DIR "/%d/%d" 62 #define USB_FS_ID_FORMAT USB_FS_DIR "/%03d/%03d" 65 #define MAX_STRING_DESCRIPTOR_LENGTH 255 67 #define MAX_USBFS_WD_COUNT 10 79 #define MAX_DESCRIPTORS_LENGTH 4096 92 if(!isdigit(*name++))
return 1;
106 devdir = opendir(busname);
107 if(devdir == 0)
return 0;
109 while ((de = readdir(devdir)) && !done) {
110 if(
badname(de->d_name))
continue;
112 snprintf(devname,
sizeof(devname),
"%s/%s", busname, de->d_name);
113 done = added_cb(devname, client_data);
130 if(busdir == 0)
return 0;
132 while ((de = readdir(busdir)) != 0 && !done) {
133 if(
badname(de->d_name))
continue;
135 snprintf(busname,
sizeof(busname),
USB_FS_DIR "/%s", de->d_name);
145 int *
wds,
int wd_count)
150 wds[0] = inotify_add_watch(context->
fd,
USB_FS_DIR, IN_CREATE | IN_DELETE);
155 for (i = 1; i < wd_count; i++) {
156 snprintf(path,
sizeof(path),
USB_FS_DIR "/%03d", i);
157 ret = inotify_add_watch(context->
fd, path, IN_CREATE | IN_DELETE);
167 fprintf(stderr,
"out of memory in usb_host_context\n");
170 context->
fd = inotify_init();
171 if (context->
fd < 0) {
172 fprintf(stderr,
"inotify_init failed\n");
201 context->
data = client_data;
203 D(
"Created device discovery thread\n");
208 context->
wds[i] = -1;
211 context->
wdd = inotify_add_watch(context->
fd,
DEV_DIR, IN_CREATE | IN_DELETE);
212 if (context->
wdd < 0) {
213 fprintf(stderr,
"inotify_add_watch failed\n");
214 if (discovery_done_cb)
215 discovery_done_cb(client_data);
223 if (discovery_done_cb)
224 done |= discovery_done_cb(client_data);
231 struct inotify_event*
event;
234 int i, ret,
done = 0;
238 ret = read(context->
fd, event_buf,
sizeof(event_buf));
239 if (ret >= (
int)
sizeof(
struct inotify_event)) {
240 while (offset < ret && !done) {
241 event = (
struct inotify_event*)&event_buf[offset];
244 if (wd == context->
wdd) {
245 if ((event->mask & IN_CREATE) && !strcmp(event->name,
"bus")) {
247 if (context->
wddbus < 0) {
254 }
else if (wd == context->
wddbus) {
255 if ((event->mask & IN_CREATE) && !strcmp(event->name,
"usb")) {
258 }
else if ((event->mask & IN_DELETE) && !strcmp(event->name,
"usb")) {
260 if (context->
wds[i] >= 0) {
261 inotify_rm_watch(context->
fd, context->
wds[i]);
262 context->
wds[
i] = -1;
266 }
else if (wd == context->
wds[0]) {
267 i = atoi(event->name);
268 snprintf(path,
sizeof(path),
USB_FS_DIR "/%s", event->name);
269 D(
"%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
270 "new" :
"gone", path, i);
273 if (event->mask & IN_CREATE) {
274 local_ret = inotify_add_watch(context->
fd, path,
275 IN_CREATE | IN_DELETE);
277 context->
wds[
i] = local_ret;
280 }
else if (event->mask & IN_DELETE) {
281 inotify_rm_watch(context->
fd, context->
wds[i]);
282 context->
wds[
i] = -1;
287 if (wd == context->
wds[i]) {
288 snprintf(path,
sizeof(path),
USB_FS_DIR "/%03d/%s", i, event->name);
289 if (event->mask == IN_CREATE) {
290 D(
"new device %s\n", path);
292 }
else if (event->mask == IN_DELETE) {
293 D(
"gone device %s\n", path);
300 offset +=
sizeof(
struct inotify_event) + event->len;
315 done =
usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data);
326 const int SLEEP_BETWEEN_ATTEMPTS_US = 100000;
327 const int64_t MAX_ATTEMPTS = 10;
328 D(
"usb_device_open %s\n", dev_name);
334 for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) {
335 if (
access(dev_name, R_OK | W_OK) == 0) {
339 if (
access(dev_name, R_OK) == 0) {
341 writeable = (
access(dev_name, R_OK | W_OK) == 0);
346 D(
"usb_device_open no access sleeping\n");
347 usleep(SLEEP_BETWEEN_ATTEMPTS_US);
351 fd = open(dev_name, O_RDWR);
353 fd = open(dev_name, O_RDONLY);
355 D(
"usb_device_open open returned %d writeable %d errno %d\n", fd, writeable, errno);
356 if (fd < 0)
return NULL;
375 D(
"usb_device_new %s fd: %d\n", dev_name, fd);
377 if (lseek(fd, 0, SEEK_SET) != 0)
379 length = read(fd, device->
desc,
sizeof(device->
desc));
380 D(
"usb_device_new read returned %d errno %d\n", length, errno);
411 D(
"usb_device_reopen_writeable failed errno %d\n", errno);
429 int bus = 0,
dev = 0;
431 return bus * 1000 +
dev;
436 int bus = 0,
dev = 0;
438 return bus * 1000 +
dev;
452 struct usb_device_descriptor* desc = (
struct usb_device_descriptor*)device->
desc;
453 return __le16_to_cpu(desc->idVendor);
458 struct usb_device_descriptor* desc = (
struct usb_device_descriptor*)device->
desc;
459 return __le16_to_cpu(desc->idProduct);
463 return (
struct usb_device_descriptor*)device->
desc;
489 size_t* response_size) {
493 int languageCount = 0;
495 if (
id == 0)
return -1;
496 if (*ucs2_out !=
NULL)
return -1;
498 memset(languages, 0,
sizeof(languages));
502 USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
506 languageCount = (result - 2) / 2;
508 for (
int i = 1;
i <= languageCount;
i++) {
509 memset(response, 0,
sizeof(response));
512 device, USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
513 (
USB_DT_STRING << 8) |
id, languages[
i], response,
sizeof(response), timeout);
515 int descriptor_len = result - 2;
516 char*
out = malloc(descriptor_len + 3);
520 memcpy(out, response + 2, descriptor_len);
524 memset(out + descriptor_len,
'\0', 3);
525 *ucs2_out = (
void*)out;
526 *response_size = descriptor_len;
538 char* ascii_string =
NULL;
539 size_t raw_string_len = 0;
543 if (ascii_string ==
NULL)
return NULL;
544 for (i = 0; i < raw_string_len / 2; ++
i) {
546 char lower = ascii_string[2 *
i];
547 char upper = ascii_string[2 * i + 1];
548 if (upper || (lower & 0x80)) {
549 ascii_string[
i] =
'?';
551 ascii_string[
i] = lower;
554 ascii_string[
i] =
'\0';
560 struct usb_device_descriptor *desc = (
struct usb_device_descriptor *)device->
desc;
566 struct usb_device_descriptor *desc = (
struct usb_device_descriptor *)device->
desc;
572 struct usb_device_descriptor *desc = (
struct usb_device_descriptor *)device->
desc;
578 struct usb_device_descriptor *desc = (
struct usb_device_descriptor *)device->
desc;
596 struct usb_descriptor_header*
next;
599 next = (
struct usb_descriptor_header*)iter->
curr_desc;
606 return ioctl(device->
fd, USBDEVFS_CLAIMINTERFACE, &interface);
611 return ioctl(device->
fd, USBDEVFS_RELEASEINTERFACE, &interface);
615 unsigned int interface,
int connect)
617 struct usbdevfs_ioctl ctl;
619 ctl.ifno = interface;
620 ctl.ioctl_code = (connect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT);
622 return ioctl(device->
fd, USBDEVFS_IOCTL, &ctl);
627 return ioctl(device->
fd, USBDEVFS_SETCONFIGURATION, &configuration);
631 unsigned int alt_setting)
633 struct usbdevfs_setinterface ctl;
635 ctl.interface = interface;
636 ctl.altsetting = alt_setting;
637 return ioctl(device->
fd, USBDEVFS_SETINTERFACE, &ctl);
649 struct usbdevfs_ctrltransfer ctrl;
655 memset(&ctrl, 0,
sizeof(ctrl));
656 ctrl.bRequestType = requestType;
657 ctrl.bRequest = request;
663 return ioctl(device->
fd, USBDEVFS_CONTROL, &ctrl);
672 struct usbdevfs_bulktransfer ctrl;
674 memset(&ctrl, 0,
sizeof(ctrl));
679 return ioctl(device->
fd, USBDEVFS_BULK, &ctrl);
684 return ioctl(device->
fd, USBDEVFS_RESET);
688 const struct usb_endpoint_descriptor *ep_desc)
690 struct usbdevfs_urb *urb = calloc(1,
sizeof(
struct usbdevfs_urb));
694 if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
695 urb->type = USBDEVFS_URB_TYPE_BULK;
696 else if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
697 urb->type = USBDEVFS_URB_TYPE_INTERRUPT;
699 D(
"Unsupported endpoint type %d", ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
703 urb->endpoint = ep_desc->bEndpointAddress;
715 urb->usercontext = req;
728 struct usbdevfs_urb *urb = (
struct usbdevfs_urb*)req->
private_data;
732 urb->buffer = req->
buffer;
736 res = ioctl(req->
dev->
fd, USBDEVFS_SUBMITURB, urb);
737 }
while((
res < 0) && (errno == EINTR));
745 if (timeoutMillis > 0) {
746 struct pollfd p = {.fd = dev->
fd, .events = POLLOUT, .revents = 0};
748 int res = poll(&p, 1, timeoutMillis);
750 if (res != 1 || p.revents != POLLOUT) {
751 D(
"[ poll - event %d, error %d]\n", p.revents, errno);
758 struct usbdevfs_urb *urb =
NULL;
759 int res = TEMP_FAILURE_RETRY(ioctl(dev->
fd, timeoutMillis == -1 ? USBDEVFS_REAPURB :
760 USBDEVFS_REAPURBNDELAY, &urb));
761 D(
"%s returned %d\n", timeoutMillis == -1 ?
"USBDEVFS_REAPURB" :
"USBDEVFS_REAPURBNDELAY", res);
764 D(
"[ reap urb - error %d]\n", errno);
767 D(
"[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length);
778 struct usbdevfs_urb *urb = ((
struct usbdevfs_urb*)req->
private_data);
779 return ioctl(req->
dev->
fd, USBDEVFS_DISCARDURB, urb);
int usb_device_get_unique_id_from_name(const char *name)
int(* usb_device_removed_cb)(const char *dev_name, void *client_data)
usb_device_added_cb cb_added
#define MAX_DESCRIPTORS_LENGTH
int usb_host_load(struct usb_host_context *context, usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, usb_discovery_done_cb discovery_done_cb, void *client_data)
int usb_device_set_interface(struct usb_device *device, unsigned int interface, unsigned int alt_setting)
GLuint const GLchar * name
static int find_existing_devices(usb_device_added_cb added_cb, void *client_data)
char * usb_device_get_string(struct usb_device *device, int id, int timeout)
const struct usb_device_descriptor * usb_device_get_device_descriptor(struct usb_device *device)
const char * usb_device_get_name(struct usb_device *device)
unsigned char * config_end
size_t usb_device_get_descriptors_length(const struct usb_device *device)
GLsizei const GLchar *const * path
static int badname(const char *name)
#define USB_FS_ID_SCANNER
int usb_device_get_unique_id(struct usb_device *device)
int(* usb_discovery_done_cb)(void *client_data)
unsigned char * curr_desc
void usb_host_cleanup(struct usb_host_context *context)
int usb_device_reset(struct usb_device *device)
int usb_device_set_configuration(struct usb_device *device, int configuration)
static int find_existing_devices_bus(char *busname, usb_device_added_cb added_cb, void *client_data)
void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter)
int usb_device_connect_kernel_driver(struct usb_device *device, unsigned int interface, int connect)
int usb_host_read_event(struct usb_host_context *context)
uint16_t usb_device_get_vendor_id(struct usb_device *device)
#define MAX_STRING_DESCRIPTOR_LENGTH
void usb_request_free(struct usb_request *req)
int usb_device_is_writeable(struct usb_device *device)
uint16_t usb_device_get_product_id(struct usb_device *device)
char * usb_device_get_name_from_unique_id(int id)
int usb_request_queue(struct usb_request *req)
int usb_request_cancel(struct usb_request *req)
int wds[MAX_USBFS_WD_COUNT]
int(* usb_device_added_cb)(const char *dev_name, void *client_data)
struct usb_host_context * usb_host_init()
char * usb_device_get_manufacturer_name(struct usb_device *device, int timeout)
void next(auto_any_t cur, type2type< T, C > *)
int usb_device_get_string_ucs2(struct usb_device *device, int id, int timeout, void **ucs2_out, size_t *response_size)
char * usb_device_get_serial(struct usb_device *device, int timeout)
void usb_host_run(struct usb_host_context *context, usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, usb_discovery_done_cb discovery_done_cb, void *client_data)
GLbitfield GLuint64 timeout
int usb_host_get_fd(struct usb_host_context *context)
struct usb_request * usb_request_new(struct usb_device *dev, const struct usb_endpoint_descriptor *ep_desc)
GLuint GLint GLboolean GLint GLenum access
void usb_device_close(struct usb_device *device)
#define MAX_USBFS_WD_COUNT
struct usb_descriptor_header * usb_descriptor_iter_next(struct usb_descriptor_iter *iter)
usb_device_removed_cb cb_removed
int usb_device_control_transfer(struct usb_device *device, int requestType, int request, int value, int index, void *buffer, int length, unsigned int timeout)
int usb_device_get_version(struct usb_device *device)
GLenum GLuint GLenum GLsizei length
struct usb_device * usb_device_new(const char *dev_name, int fd)
int usb_device_bulk_transfer(struct usb_device *device, int endpoint, void *buffer, unsigned int length, unsigned int timeout)
int usb_device_get_fd(struct usb_device *device)
int usb_device_release_interface(struct usb_device *device, unsigned int interface)
char * usb_device_get_product_name(struct usb_device *device, int timeout)
unsigned char desc[MAX_DESCRIPTORS_LENGTH]
struct usb_device * usb_device_open(const char *dev_name)
int usb_device_claim_interface(struct usb_device *device, unsigned int interface)
const unsigned char * usb_device_get_raw_descriptors(const struct usb_device *device)
struct usb_request * usb_request_wait(struct usb_device *dev, int timeoutMillis)
static void watch_existing_subdirs(struct usb_host_context *context, int *wds, int wd_count)
static int usb_device_reopen_writeable(struct usb_device *device)