2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
30 #include <linux/usbdevice_fs.h>
31 #include <linux/version.h>
32 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
33 #include <linux/usb/ch9.h>
35 #include <linux/usb_ch9.h>
37 #include <asm/byteorder.h>
41 //#define TRACE_TAG TRACE_USB
42 #define LOG_TAG "SDBD_TRACE_USB"
48 /* usb scan debugging is waaaay too verbose */
51 SDB_MUTEX_DEFINE( usb_lock );
66 struct usbdevfs_urb urb_in;
67 struct usbdevfs_urb urb_out;
76 // for garbage collecting disconnected devices
79 // ID of thread currently in REAPURB
80 pthread_t reaper_thread;
83 static usb_handle handle_list = {
88 static int known_device(const char *dev_name)
92 sdb_mutex_lock(&usb_lock);
93 for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
94 if(!strcmp(usb->fname, dev_name)) {
95 // set mark flag to indicate this device is still alive
97 sdb_mutex_unlock(&usb_lock);
101 sdb_mutex_unlock(&usb_lock);
105 static void kick_disconnected_devices()
109 sdb_mutex_lock(&usb_lock);
110 // kick any devices in the device list that were not found in the device scan
111 for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
112 if (usb->mark == 0) {
118 sdb_mutex_unlock(&usb_lock);
122 static void register_device(const char *dev_name, unsigned char ep_in, unsigned char ep_out,
123 int ifc, int serial_index, unsigned zero_mask);
125 static inline int badname(const char *name)
128 if(!isdigit(*name++)) return 1;
133 static void find_usb_device(const char *base,
134 void (*register_device_callback)
135 (const char *, unsigned char, unsigned char, int, int, unsigned))
137 char busname[32], devname[32];
138 unsigned char local_ep_in, local_ep_out;
139 DIR *busdir , *devdir ;
143 busdir = opendir(base);
144 if(busdir == 0) return;
146 while((de = readdir(busdir)) != 0) {
147 if(badname(de->d_name)) continue;
149 snprintf(busname, sizeof busname, "%s/%s", base, de->d_name);
150 devdir = opendir(busname);
151 if(devdir == 0) continue;
153 // DBGX("[ scanning %s ]\n", busname);
154 while((de = readdir(devdir))) {
155 unsigned char devdesc[4096];
156 unsigned char* bufptr = devdesc;
157 unsigned char* bufend;
158 struct usb_device_descriptor* device;
159 struct usb_config_descriptor* config;
160 struct usb_interface_descriptor* interface;
161 struct usb_endpoint_descriptor *ep1, *ep2;
162 unsigned zero_mask = 0;
164 unsigned int desclength;
166 if(badname(de->d_name)) continue;
167 snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
169 if(known_device(devname)) {
170 DBGX("skipping %s\n", devname);
174 // DBGX("[ scanning %s ]\n", devname);
175 if((fd = unix_open(devname, O_RDONLY)) < 0) {
179 desclength = sdb_read(fd, devdesc, sizeof(devdesc));
180 bufend = bufptr + desclength;
182 // should have device and configuration descriptors, and atleast two endpoints
183 if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
184 E("desclength %d is too small\n", desclength);
189 device = (struct usb_device_descriptor*)bufptr;
190 bufptr += USB_DT_DEVICE_SIZE;
192 if((device->bLength != USB_DT_DEVICE_SIZE) || (device->bDescriptorType != USB_DT_DEVICE)) {
197 vid = device->idVendor;
198 pid = device->idProduct;
199 DBGX("[ %s is V:%04x P:%04x ]\n", devname, vid, pid);
201 // should have config descriptor next
202 config = (struct usb_config_descriptor *)bufptr;
205 if (device->bNumConfigurations > 1) {
206 bufptr += config->wTotalLength;
207 config = (struct usb_config_descriptor *)bufptr;
208 bufend = bufptr + config->wTotalLength;
211 bufptr += USB_DT_CONFIG_SIZE;
212 if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
213 E("usb_config_descriptor not found\n");
218 // loop through all the descriptors and look for the SDB interface
219 while (bufptr < bufend) {
220 unsigned char length = bufptr[0];
221 unsigned char type = bufptr[1];
223 if (type == USB_DT_INTERFACE) {
224 interface = (struct usb_interface_descriptor *)bufptr;
227 if (length != USB_DT_INTERFACE_SIZE) {
228 E("interface descriptor has wrong size\n");
232 DBGX("bInterfaceClass: %d, bInterfaceSubClass: %d,"
233 "bInterfaceProtocol: %d, bNumEndpoints: %d\n",
234 interface->bInterfaceClass, interface->bInterfaceSubClass,
235 interface->bInterfaceProtocol, interface->bNumEndpoints);
237 if (interface->bNumEndpoints == 2 &&
238 is_sdb_interface(vid, pid, interface->bInterfaceClass,
239 interface->bInterfaceSubClass, interface->bInterfaceProtocol)) {
241 I("looking for bulk endpoints\n");
243 ep1 = (struct usb_endpoint_descriptor *)bufptr;
244 bufptr += USB_DT_ENDPOINT_SIZE;
245 ep2 = (struct usb_endpoint_descriptor *)bufptr;
246 bufptr += USB_DT_ENDPOINT_SIZE;
248 if (bufptr > devdesc + desclength ||
249 ep1->bLength != USB_DT_ENDPOINT_SIZE ||
250 ep1->bDescriptorType != USB_DT_ENDPOINT ||
251 ep2->bLength != USB_DT_ENDPOINT_SIZE ||
252 ep2->bDescriptorType != USB_DT_ENDPOINT) {
253 I("endpoints not found\n");
257 // both endpoints should be bulk
258 if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
259 ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
260 I("bulk endpoints not found\n");
263 /* aproto 01 needs 0 termination */
264 if(interface->bInterfaceProtocol == 0x01) {
265 zero_mask = ep1->wMaxPacketSize - 1;
268 // we have a match. now we just need to figure out which is in and which is out.
269 if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
270 local_ep_in = ep1->bEndpointAddress;
271 local_ep_out = ep2->bEndpointAddress;
273 local_ep_in = ep2->bEndpointAddress;
274 local_ep_out = ep1->bEndpointAddress;
277 register_device_callback(devname, local_ep_in, local_ep_out,
278 interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
287 } // end of devdir while
289 } //end of busdir while
297 static int usb_bulk_write(usb_handle *h, const void *data, int len)
299 struct usbdevfs_urb *urb = &h->urb_out;
304 memset(urb, 0, sizeof(*urb));
305 urb->type = USBDEVFS_URB_TYPE_BULK;
306 urb->endpoint = h->ep_out;
308 urb->buffer = (void*) data;
309 urb->buffer_length = len;
313 sdb_mutex_lock(&h->lock);
319 res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
320 } while((res < 0) && (errno == EINTR));
329 /* time out after five seconds */
330 gettimeofday(&tv, NULL);
331 ts.tv_sec = tv.tv_sec + 5;
332 ts.tv_nsec = tv.tv_usec * 1000L;
333 res = pthread_cond_timedwait(&h->notify, &h->lock, &ts);
334 if(res < 0 || h->dead) {
337 if(h->urb_out_busy == 0) {
338 if(urb->status == 0) {
339 res = urb->actual_length;
345 sdb_mutex_unlock(&h->lock);
350 static int usb_bulk_read(usb_handle *h, void *data, int len)
352 struct usbdevfs_urb *urb = &h->urb_in;
353 struct usbdevfs_urb *out = NULL;
356 memset(urb, 0, sizeof(*urb));
357 urb->type = USBDEVFS_URB_TYPE_BULK;
358 urb->endpoint = h->ep_in;
361 urb->buffer_length = len;
364 sdb_mutex_lock(&h->lock);
370 res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
371 } while((res < 0) && (errno == EINTR));
379 I("[ reap urb - wait ]\n");
380 h->reaper_thread = pthread_self();
381 sdb_mutex_unlock(&h->lock);
382 res = ioctl(h->desc, USBDEVFS_REAPURB, &out);
383 int saved_errno = errno;
384 sdb_mutex_lock(&h->lock);
385 h->reaper_thread = 0;
391 if(saved_errno == EINTR) {
394 E("[ reap urb - error ]\n");
397 D("[ urb @%p status = %d, actual = %d ]\n",
398 out, out->status, out->actual_length);
400 if(out == &h->urb_in) {
401 D("[ reap urb - IN complete ]\n");
403 if(urb->status == 0) {
404 res = urb->actual_length;
410 if(out == &h->urb_out) {
411 I("[ reap urb - OUT compelete ]\n");
413 sdb_cond_broadcast(&h->notify);
417 sdb_mutex_unlock(&h->lock);
422 int usb_write(usb_handle *h, const void *_data, int len)
424 unsigned char *data = (unsigned char*) _data;
429 /* if we need 0-markers and our transfer
430 ** is an even multiple of the packet size,
431 ** we make note of it
433 if(!(len & h->zero_mask)) {
439 int xfer = (len > 4096) ? 4096 : len;
441 n = usb_bulk_write(h, data, xfer);
443 E("ERROR: n = %d, errno = %d\n",
453 n = usb_bulk_write(h, _data, 0);
460 int usb_read(usb_handle *h, void *_data, size_t len)
462 unsigned char *data = (unsigned char*) _data;
465 I("++ usb_read ++\n");
467 int xfer = (len > 4096) ? 4096 : len;
469 D("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
470 n = usb_bulk_read(h, data, xfer);
471 D("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname);
473 if((errno == ETIMEDOUT) && (h->desc != -1)) {
481 E("ERROR: n = %d, errno = %d \n",
490 I("-- usb_read --\n");
494 void usb_kick(usb_handle *h)
496 D("[ kicking %p (fd = %d) ]\n", h, h->desc);
497 sdb_mutex_lock(&h->lock);
503 ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB).
504 ** This is a workaround for that problem.
506 if (h->reaper_thread) {
507 pthread_kill(h->reaper_thread, SIGALRM);
510 /* cancel any pending transactions
511 ** these will quietly fail if the txns are not active,
512 ** but this ensures that a reader blocked on REAPURB
513 ** will get unblocked
515 ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_in);
516 ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_out);
517 h->urb_in.status = -ENODEV;
518 h->urb_out.status = -ENODEV;
521 sdb_cond_broadcast(&h->notify);
523 unregister_usb_transport(h);
526 sdb_mutex_unlock(&h->lock);
529 int usb_close(usb_handle *h)
531 I("[ usb close ... ]\n");
532 sdb_mutex_lock(&usb_lock);
533 h->next->prev = h->prev;
534 h->prev->next = h->next;
539 D("[ usb closed %p (fd = %d) ]\n", h, h->desc);
540 sdb_mutex_unlock(&usb_lock);
546 static void register_device(const char *dev_name,
547 unsigned char ep_in, unsigned char ep_out,
548 int interface, int serial_index, unsigned zero_mask)
553 int bConfigurationValue = 2; /* tizen specific : sdb needs 2nd configruation */
555 /* Since Linux will not reassign the device ID (and dev_name)
556 ** as long as the device is open, we can add to the list here
557 ** once we open it and remove from the list when we're finally
558 ** closed and everything will work out fine.
560 ** If we have a usb_handle on the list 'o handles with a matching
561 ** name, we have no further work to do.
563 sdb_mutex_lock(&usb_lock);
564 for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
565 if(!strcmp(usb->fname, dev_name)) {
566 sdb_mutex_unlock(&usb_lock);
570 sdb_mutex_unlock(&usb_lock);
572 D("[ usb located new device %s (%d/%d/%d) ]\n",
573 dev_name, ep_in, ep_out, interface);
574 usb = calloc(1, sizeof(usb_handle));
575 strncpy(usb->fname, dev_name, sizeof(usb->fname) - 1);
577 usb->ep_out = ep_out;
578 usb->zero_mask = zero_mask;
581 sdb_cond_init(&usb->notify, 0);
582 sdb_mutex_init(&usb->lock, 0);
583 /* initialize mark to 1 so we don't get garbage collected after the device scan */
585 usb->reaper_thread = 0;
587 usb->desc = unix_open(usb->fname, O_RDWR);
589 /* if we fail, see if have read-only access */
590 usb->desc = unix_open(usb->fname, O_RDONLY);
591 if(usb->desc < 0) goto fail;
593 D("[ usb open read-only %s fd = %d]\n", usb->fname, usb->desc);
595 D("[ usb open %s fd = %d]\n", usb->fname, usb->desc);
597 n = ioctl(usb->desc, USBDEVFS_RESET);
599 E("[ usb reset failed %s fd = %d]\n", usb->fname, usb->desc);
602 n = ioctl(usb->desc, USBDEVFS_SETCONFIGURATION, &bConfigurationValue);
604 D("[ usb set %d configuration failed %s fd = %d]\n", bConfigurationValue, usb->fname, usb->desc);
605 D("check kernel is supporting %dth configuration\n", bConfigurationValue);
608 n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface);
610 E("[ usb claim failed %s fd = %d]\n", usb->fname, usb->desc);
615 /* read the device's serial number */
617 memset(serial, 0, sizeof(serial));
619 struct usbdevfs_ctrltransfer ctrl;
621 __u16 languages[128];
623 int languageCount = 0;
625 memset(languages, 0, sizeof(languages));
626 memset(&ctrl, 0, sizeof(ctrl));
628 // read list of supported languages
629 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
630 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
631 ctrl.wValue = (USB_DT_STRING << 8) | 0;
633 ctrl.wLength = sizeof(languages);
634 ctrl.data = languages;
637 result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
639 languageCount = (result - 2) / 2;
641 for (i = 1; i <= languageCount; i++) {
642 memset(buffer, 0, sizeof(buffer));
643 memset(&ctrl, 0, sizeof(ctrl));
645 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
646 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
647 ctrl.wValue = (USB_DT_STRING << 8) | serial_index;
648 ctrl.wIndex = __le16_to_cpu(languages[i]);
649 ctrl.wLength = sizeof(buffer);
653 result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
656 // skip first word, and copy the rest to the serial string, changing shorts to bytes.
658 for (i = 1; i < result; i++)
659 serial[i - 1] = __le16_to_cpu(buffer[i]);
666 /* add to the end of the active handles */
667 sdb_mutex_lock(&usb_lock);
668 usb->next = &handle_list;
669 usb->prev = handle_list.prev;
670 usb->prev->next = usb;
671 usb->next->prev = usb;
672 sdb_mutex_unlock(&usb_lock);
674 register_usb_transport(usb, serial, usb->writeable);
678 E("[ usb open %s error=%d]\n",
681 sdb_close(usb->desc);
686 void* device_poll_thread(void* unused)
688 I("Created device thread\n");
690 /* XXX use inotify */
691 find_usb_device("/dev/bus/usb", register_device);
692 kick_disconnected_devices();
698 static void sigalrm_handler(int signo)
700 // don't need to do anything here
706 struct sigaction actions;
708 memset(&actions, 0, sizeof(actions));
709 sigemptyset(&actions.sa_mask);
710 actions.sa_flags = 0;
711 actions.sa_handler = sigalrm_handler;
712 sigaction(SIGALRM,& actions, NULL);
714 if(sdb_thread_create(&tid, device_poll_thread, NULL)){
715 fatal_errno("cannot create input thread");