aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_hid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_hid.c')
-rw-r--r--drivers/usb/gadget/f_hid.c208
1 files changed, 165 insertions, 43 deletions
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 3b3932c55361..16a8b1c15c62 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -26,6 +26,12 @@ static struct class *hidg_class;
26/*-------------------------------------------------------------------------*/ 26/*-------------------------------------------------------------------------*/
27/* HID gadget struct */ 27/* HID gadget struct */
28 28
29struct f_hidg_req_list {
30 struct usb_request *req;
31 unsigned int pos;
32 struct list_head list;
33};
34
29struct f_hidg { 35struct f_hidg {
30 /* configuration */ 36 /* configuration */
31 unsigned char bInterfaceSubClass; 37 unsigned char bInterfaceSubClass;
@@ -35,10 +41,10 @@ struct f_hidg {
35 unsigned short report_length; 41 unsigned short report_length;
36 42
37 /* recv report */ 43 /* recv report */
38 char *set_report_buff; 44 struct list_head completed_out_req;
39 unsigned short set_report_length;
40 spinlock_t spinlock; 45 spinlock_t spinlock;
41 wait_queue_head_t read_queue; 46 wait_queue_head_t read_queue;
47 unsigned int qlen;
42 48
43 /* send report */ 49 /* send report */
44 struct mutex lock; 50 struct mutex lock;
@@ -49,7 +55,9 @@ struct f_hidg {
49 int minor; 55 int minor;
50 struct cdev cdev; 56 struct cdev cdev;
51 struct usb_function func; 57 struct usb_function func;
58
52 struct usb_ep *in_ep; 59 struct usb_ep *in_ep;
60 struct usb_ep *out_ep;
53}; 61};
54 62
55static inline struct f_hidg *func_to_hidg(struct usb_function *f) 63static inline struct f_hidg *func_to_hidg(struct usb_function *f)
@@ -65,7 +73,7 @@ static struct usb_interface_descriptor hidg_interface_desc = {
65 .bDescriptorType = USB_DT_INTERFACE, 73 .bDescriptorType = USB_DT_INTERFACE,
66 /* .bInterfaceNumber = DYNAMIC */ 74 /* .bInterfaceNumber = DYNAMIC */
67 .bAlternateSetting = 0, 75 .bAlternateSetting = 0,
68 .bNumEndpoints = 1, 76 .bNumEndpoints = 2,
69 .bInterfaceClass = USB_CLASS_HID, 77 .bInterfaceClass = USB_CLASS_HID,
70 /* .bInterfaceSubClass = DYNAMIC */ 78 /* .bInterfaceSubClass = DYNAMIC */
71 /* .bInterfaceProtocol = DYNAMIC */ 79 /* .bInterfaceProtocol = DYNAMIC */
@@ -96,10 +104,23 @@ static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = {
96 */ 104 */
97}; 105};
98 106
107static struct usb_endpoint_descriptor hidg_hs_out_ep_desc = {
108 .bLength = USB_DT_ENDPOINT_SIZE,
109 .bDescriptorType = USB_DT_ENDPOINT,
110 .bEndpointAddress = USB_DIR_OUT,
111 .bmAttributes = USB_ENDPOINT_XFER_INT,
112 /*.wMaxPacketSize = DYNAMIC */
113 .bInterval = 4, /* FIXME: Add this field in the
114 * HID gadget configuration?
115 * (struct hidg_func_descriptor)
116 */
117};
118
99static struct usb_descriptor_header *hidg_hs_descriptors[] = { 119static struct usb_descriptor_header *hidg_hs_descriptors[] = {
100 (struct usb_descriptor_header *)&hidg_interface_desc, 120 (struct usb_descriptor_header *)&hidg_interface_desc,
101 (struct usb_descriptor_header *)&hidg_desc, 121 (struct usb_descriptor_header *)&hidg_desc,
102 (struct usb_descriptor_header *)&hidg_hs_in_ep_desc, 122 (struct usb_descriptor_header *)&hidg_hs_in_ep_desc,
123 (struct usb_descriptor_header *)&hidg_hs_out_ep_desc,
103 NULL, 124 NULL,
104}; 125};
105 126
@@ -117,10 +138,23 @@ static struct usb_endpoint_descriptor hidg_fs_in_ep_desc = {
117 */ 138 */
118}; 139};
119 140
141static struct usb_endpoint_descriptor hidg_fs_out_ep_desc = {
142 .bLength = USB_DT_ENDPOINT_SIZE,
143 .bDescriptorType = USB_DT_ENDPOINT,
144 .bEndpointAddress = USB_DIR_OUT,
145 .bmAttributes = USB_ENDPOINT_XFER_INT,
146 /*.wMaxPacketSize = DYNAMIC */
147 .bInterval = 10, /* FIXME: Add this field in the
148 * HID gadget configuration?
149 * (struct hidg_func_descriptor)
150 */
151};
152
120static struct usb_descriptor_header *hidg_fs_descriptors[] = { 153static struct usb_descriptor_header *hidg_fs_descriptors[] = {
121 (struct usb_descriptor_header *)&hidg_interface_desc, 154 (struct usb_descriptor_header *)&hidg_interface_desc,
122 (struct usb_descriptor_header *)&hidg_desc, 155 (struct usb_descriptor_header *)&hidg_desc,
123 (struct usb_descriptor_header *)&hidg_fs_in_ep_desc, 156 (struct usb_descriptor_header *)&hidg_fs_in_ep_desc,
157 (struct usb_descriptor_header *)&hidg_fs_out_ep_desc,
124 NULL, 158 NULL,
125}; 159};
126 160
@@ -130,9 +164,11 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = {
130static ssize_t f_hidg_read(struct file *file, char __user *buffer, 164static ssize_t f_hidg_read(struct file *file, char __user *buffer,
131 size_t count, loff_t *ptr) 165 size_t count, loff_t *ptr)
132{ 166{
133 struct f_hidg *hidg = file->private_data; 167 struct f_hidg *hidg = file->private_data;
134 char *tmp_buff = NULL; 168 struct f_hidg_req_list *list;
135 unsigned long flags; 169 struct usb_request *req;
170 unsigned long flags;
171 int ret;
136 172
137 if (!count) 173 if (!count)
138 return 0; 174 return 0;
@@ -142,8 +178,9 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
142 178
143 spin_lock_irqsave(&hidg->spinlock, flags); 179 spin_lock_irqsave(&hidg->spinlock, flags);
144 180
145#define READ_COND (hidg->set_report_buff != NULL) 181#define READ_COND (!list_empty(&hidg->completed_out_req))
146 182
183 /* wait for at least one buffer to complete */
147 while (!READ_COND) { 184 while (!READ_COND) {
148 spin_unlock_irqrestore(&hidg->spinlock, flags); 185 spin_unlock_irqrestore(&hidg->spinlock, flags);
149 if (file->f_flags & O_NONBLOCK) 186 if (file->f_flags & O_NONBLOCK)
@@ -155,19 +192,34 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
155 spin_lock_irqsave(&hidg->spinlock, flags); 192 spin_lock_irqsave(&hidg->spinlock, flags);
156 } 193 }
157 194
158 195 /* pick the first one */
159 count = min_t(unsigned, count, hidg->set_report_length); 196 list = list_first_entry(&hidg->completed_out_req,
160 tmp_buff = hidg->set_report_buff; 197 struct f_hidg_req_list, list);
161 hidg->set_report_buff = NULL; 198 req = list->req;
162 199 count = min_t(unsigned int, count, req->actual - list->pos);
163 spin_unlock_irqrestore(&hidg->spinlock, flags); 200 spin_unlock_irqrestore(&hidg->spinlock, flags);
164 201
165 if (tmp_buff != NULL) { 202 /* copy to user outside spinlock */
166 /* copy to user outside spinlock */ 203 count -= copy_to_user(buffer, req->buf + list->pos, count);
167 count -= copy_to_user(buffer, tmp_buff, count); 204 list->pos += count;
168 kfree(tmp_buff); 205
169 } else 206 /*
170 count = -ENOMEM; 207 * if this request is completely handled and transfered to
208 * userspace, remove its entry from the list and requeue it
209 * again. Otherwise, we will revisit it again upon the next
210 * call, taking into account its current read position.
211 */
212 if (list->pos == req->actual) {
213 spin_lock_irqsave(&hidg->spinlock, flags);
214 list_del(&list->list);
215 kfree(list);
216 spin_unlock_irqrestore(&hidg->spinlock, flags);
217
218 req->length = hidg->report_length;
219 ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL);
220 if (ret < 0)
221 return ret;
222 }
171 223
172 return count; 224 return count;
173} 225}
@@ -282,28 +334,37 @@ static int f_hidg_open(struct inode *inode, struct file *fd)
282/*-------------------------------------------------------------------------*/ 334/*-------------------------------------------------------------------------*/
283/* usb_function */ 335/* usb_function */
284 336
285static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) 337static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length)
286{ 338{
287 struct f_hidg *hidg = (struct f_hidg *)req->context; 339 struct usb_request *req;
288 340
289 if (req->status != 0 || req->buf == NULL || req->actual == 0) { 341 req = usb_ep_alloc_request(ep, GFP_ATOMIC);
290 ERROR(hidg->func.config->cdev, "%s FAILED\n", __func__); 342 if (req) {
291 return; 343 req->length = length;
344 req->buf = kmalloc(length, GFP_ATOMIC);
345 if (!req->buf) {
346 usb_ep_free_request(ep, req);
347 req = NULL;
348 }
292 } 349 }
350 return req;
351}
293 352
294 spin_lock(&hidg->spinlock); 353static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
295 354{
296 hidg->set_report_buff = krealloc(hidg->set_report_buff, 355 struct f_hidg *hidg = (struct f_hidg *) req->context;
297 req->actual, GFP_ATOMIC); 356 struct f_hidg_req_list *req_list;
357 unsigned long flags;
298 358
299 if (hidg->set_report_buff == NULL) { 359 req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
300 spin_unlock(&hidg->spinlock); 360 if (!req_list)
301 return; 361 return;
302 }
303 hidg->set_report_length = req->actual;
304 memcpy(hidg->set_report_buff, req->buf, req->actual);
305 362
306 spin_unlock(&hidg->spinlock); 363 req_list->req = req;
364
365 spin_lock_irqsave(&hidg->spinlock, flags);
366 list_add_tail(&req_list->list, &hidg->completed_out_req);
367 spin_unlock_irqrestore(&hidg->spinlock, flags);
307 368
308 wake_up(&hidg->read_queue); 369 wake_up(&hidg->read_queue);
309} 370}
@@ -344,9 +405,7 @@ static int hidg_setup(struct usb_function *f,
344 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 405 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
345 | HID_REQ_SET_REPORT): 406 | HID_REQ_SET_REPORT):
346 VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength); 407 VDBG(cdev, "set_report | wLenght=%d\n", ctrl->wLength);
347 req->context = hidg; 408 goto stall;
348 req->complete = hidg_set_report_complete;
349 goto respond;
350 break; 409 break;
351 410
352 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 411 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@@ -403,16 +462,25 @@ respond:
403static void hidg_disable(struct usb_function *f) 462static void hidg_disable(struct usb_function *f)
404{ 463{
405 struct f_hidg *hidg = func_to_hidg(f); 464 struct f_hidg *hidg = func_to_hidg(f);
465 struct f_hidg_req_list *list, *next;
406 466
407 usb_ep_disable(hidg->in_ep); 467 usb_ep_disable(hidg->in_ep);
408 hidg->in_ep->driver_data = NULL; 468 hidg->in_ep->driver_data = NULL;
469
470 usb_ep_disable(hidg->out_ep);
471 hidg->out_ep->driver_data = NULL;
472
473 list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
474 list_del(&list->list);
475 kfree(list);
476 }
409} 477}
410 478
411static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) 479static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
412{ 480{
413 struct usb_composite_dev *cdev = f->config->cdev; 481 struct usb_composite_dev *cdev = f->config->cdev;
414 struct f_hidg *hidg = func_to_hidg(f); 482 struct f_hidg *hidg = func_to_hidg(f);
415 int status = 0; 483 int i, status = 0;
416 484
417 VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt); 485 VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
418 486
@@ -429,11 +497,55 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
429 } 497 }
430 status = usb_ep_enable(hidg->in_ep); 498 status = usb_ep_enable(hidg->in_ep);
431 if (status < 0) { 499 if (status < 0) {
432 ERROR(cdev, "Enable endpoint FAILED!\n"); 500 ERROR(cdev, "Enable IN endpoint FAILED!\n");
433 goto fail; 501 goto fail;
434 } 502 }
435 hidg->in_ep->driver_data = hidg; 503 hidg->in_ep->driver_data = hidg;
436 } 504 }
505
506
507 if (hidg->out_ep != NULL) {
508 /* restart endpoint */
509 if (hidg->out_ep->driver_data != NULL)
510 usb_ep_disable(hidg->out_ep);
511
512 status = config_ep_by_speed(f->config->cdev->gadget, f,
513 hidg->out_ep);
514 if (status) {
515 ERROR(cdev, "config_ep_by_speed FAILED!\n");
516 goto fail;
517 }
518 status = usb_ep_enable(hidg->out_ep);
519 if (status < 0) {
520 ERROR(cdev, "Enable IN endpoint FAILED!\n");
521 goto fail;
522 }
523 hidg->out_ep->driver_data = hidg;
524
525 /*
526 * allocate a bunch of read buffers and queue them all at once.
527 */
528 for (i = 0; i < hidg->qlen && status == 0; i++) {
529 struct usb_request *req =
530 hidg_alloc_ep_req(hidg->out_ep,
531 hidg->report_length);
532 if (req) {
533 req->complete = hidg_set_report_complete;
534 req->context = hidg;
535 status = usb_ep_queue(hidg->out_ep, req,
536 GFP_ATOMIC);
537 if (status)
538 ERROR(cdev, "%s queue req --> %d\n",
539 hidg->out_ep->name, status);
540 } else {
541 usb_ep_disable(hidg->out_ep);
542 hidg->out_ep->driver_data = NULL;
543 status = -ENOMEM;
544 goto fail;
545 }
546 }
547 }
548
437fail: 549fail:
438 return status; 550 return status;
439} 551}
@@ -470,13 +582,18 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
470 ep->driver_data = c->cdev; /* claim */ 582 ep->driver_data = c->cdev; /* claim */
471 hidg->in_ep = ep; 583 hidg->in_ep = ep;
472 584
585 ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
586 if (!ep)
587 goto fail;
588 ep->driver_data = c->cdev; /* claim */
589 hidg->out_ep = ep;
590
473 /* preallocate request and buffer */ 591 /* preallocate request and buffer */
474 status = -ENOMEM; 592 status = -ENOMEM;
475 hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL); 593 hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL);
476 if (!hidg->req) 594 if (!hidg->req)
477 goto fail; 595 goto fail;
478 596
479
480 hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL); 597 hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL);
481 if (!hidg->req->buf) 598 if (!hidg->req->buf)
482 goto fail; 599 goto fail;
@@ -486,12 +603,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
486 hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; 603 hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
487 hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); 604 hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
488 hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); 605 hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
606 hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
607 hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
489 hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT; 608 hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT;
490 hidg_desc.desc[0].wDescriptorLength = 609 hidg_desc.desc[0].wDescriptorLength =
491 cpu_to_le16(hidg->report_desc_length); 610 cpu_to_le16(hidg->report_desc_length);
492 611
493 hidg->set_report_buff = NULL;
494
495 /* copy descriptors */ 612 /* copy descriptors */
496 f->descriptors = usb_copy_descriptors(hidg_fs_descriptors); 613 f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
497 if (!f->descriptors) 614 if (!f->descriptors)
@@ -500,6 +617,8 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
500 if (gadget_is_dualspeed(c->cdev->gadget)) { 617 if (gadget_is_dualspeed(c->cdev->gadget)) {
501 hidg_hs_in_ep_desc.bEndpointAddress = 618 hidg_hs_in_ep_desc.bEndpointAddress =
502 hidg_fs_in_ep_desc.bEndpointAddress; 619 hidg_fs_in_ep_desc.bEndpointAddress;
620 hidg_hs_out_ep_desc.bEndpointAddress =
621 hidg_fs_out_ep_desc.bEndpointAddress;
503 f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors); 622 f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
504 if (!f->hs_descriptors) 623 if (!f->hs_descriptors)
505 goto fail; 624 goto fail;
@@ -509,6 +628,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
509 spin_lock_init(&hidg->spinlock); 628 spin_lock_init(&hidg->spinlock);
510 init_waitqueue_head(&hidg->write_queue); 629 init_waitqueue_head(&hidg->write_queue);
511 init_waitqueue_head(&hidg->read_queue); 630 init_waitqueue_head(&hidg->read_queue);
631 INIT_LIST_HEAD(&hidg->completed_out_req);
512 632
513 /* create char device */ 633 /* create char device */
514 cdev_init(&hidg->cdev, &f_hidg_fops); 634 cdev_init(&hidg->cdev, &f_hidg_fops);
@@ -553,7 +673,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
553 usb_free_descriptors(f->descriptors); 673 usb_free_descriptors(f->descriptors);
554 674
555 kfree(hidg->report_desc); 675 kfree(hidg->report_desc);
556 kfree(hidg->set_report_buff);
557 kfree(hidg); 676 kfree(hidg);
558} 677}
559 678
@@ -624,6 +743,9 @@ int __init hidg_bind_config(struct usb_configuration *c,
624 hidg->func.disable = hidg_disable; 743 hidg->func.disable = hidg_disable;
625 hidg->func.setup = hidg_setup; 744 hidg->func.setup = hidg_setup;
626 745
746 /* this could me made configurable at some point */
747 hidg->qlen = 4;
748
627 status = usb_add_function(c, &hidg->func); 749 status = usb_add_function(c, &hidg->func);
628 if (status) 750 if (status)
629 kfree(hidg); 751 kfree(hidg);