@@ -26,6 +26,12 @@ static struct class *hidg_class;
26
26
/*-------------------------------------------------------------------------*/
27
27
/* HID gadget struct */
28
28
29
+ struct f_hidg_req_list {
30
+ struct usb_request * req ;
31
+ unsigned int pos ;
32
+ struct list_head list ;
33
+ };
34
+
29
35
struct f_hidg {
30
36
/* configuration */
31
37
unsigned char bInterfaceSubClass ;
@@ -35,10 +41,10 @@ struct f_hidg {
35
41
unsigned short report_length ;
36
42
37
43
/* recv report */
38
- char * set_report_buff ;
39
- unsigned short set_report_length ;
44
+ struct list_head completed_out_req ;
40
45
spinlock_t spinlock ;
41
46
wait_queue_head_t read_queue ;
47
+ unsigned int qlen ;
42
48
43
49
/* send report */
44
50
struct mutex lock ;
@@ -49,7 +55,9 @@ struct f_hidg {
49
55
int minor ;
50
56
struct cdev cdev ;
51
57
struct usb_function func ;
58
+
52
59
struct usb_ep * in_ep ;
60
+ struct usb_ep * out_ep ;
53
61
};
54
62
55
63
static inline struct f_hidg * func_to_hidg (struct usb_function * f )
@@ -65,7 +73,7 @@ static struct usb_interface_descriptor hidg_interface_desc = {
65
73
.bDescriptorType = USB_DT_INTERFACE ,
66
74
/* .bInterfaceNumber = DYNAMIC */
67
75
.bAlternateSetting = 0 ,
68
- .bNumEndpoints = 1 ,
76
+ .bNumEndpoints = 2 ,
69
77
.bInterfaceClass = USB_CLASS_HID ,
70
78
/* .bInterfaceSubClass = DYNAMIC */
71
79
/* .bInterfaceProtocol = DYNAMIC */
@@ -96,10 +104,23 @@ static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = {
96
104
*/
97
105
};
98
106
107
+ static 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
+
99
119
static struct usb_descriptor_header * hidg_hs_descriptors [] = {
100
120
(struct usb_descriptor_header * )& hidg_interface_desc ,
101
121
(struct usb_descriptor_header * )& hidg_desc ,
102
122
(struct usb_descriptor_header * )& hidg_hs_in_ep_desc ,
123
+ (struct usb_descriptor_header * )& hidg_hs_out_ep_desc ,
103
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
141
+ static 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
+
120
153
static struct usb_descriptor_header * hidg_fs_descriptors [] = {
121
154
(struct usb_descriptor_header * )& hidg_interface_desc ,
122
155
(struct usb_descriptor_header * )& hidg_desc ,
123
156
(struct usb_descriptor_header * )& hidg_fs_in_ep_desc ,
157
+ (struct usb_descriptor_header * )& hidg_fs_out_ep_desc ,
124
158
NULL ,
125
159
};
126
160
@@ -130,9 +164,11 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = {
130
164
static ssize_t f_hidg_read (struct file * file , char __user * buffer ,
131
165
size_t count , loff_t * ptr )
132
166
{
133
- struct f_hidg * hidg = file -> private_data ;
134
- char * tmp_buff = NULL ;
135
- unsigned long flags ;
167
+ struct f_hidg * hidg = file -> private_data ;
168
+ struct f_hidg_req_list * list ;
169
+ struct usb_request * req ;
170
+ unsigned long flags ;
171
+ int ret ;
136
172
137
173
if (!count )
138
174
return 0 ;
@@ -142,8 +178,9 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
142
178
143
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
184
while (!READ_COND ) {
148
185
spin_unlock_irqrestore (& hidg -> spinlock , flags );
149
186
if (file -> f_flags & O_NONBLOCK )
@@ -155,19 +192,34 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
155
192
spin_lock_irqsave (& hidg -> spinlock , flags );
156
193
}
157
194
158
-
159
- count = min_t ( unsigned , count , hidg -> set_report_length );
160
- tmp_buff = hidg -> set_report_buff ;
161
- hidg -> set_report_buff = NULL ;
162
-
195
+ /* pick the first one */
196
+ list = list_first_entry ( & hidg -> completed_out_req ,
197
+ struct f_hidg_req_list , list ) ;
198
+ req = list -> req ;
199
+ count = min_t ( unsigned int , count , req -> actual - list -> pos );
163
200
spin_unlock_irqrestore (& hidg -> spinlock , flags );
164
201
165
- if (tmp_buff != NULL ) {
166
- /* copy to user outside spinlock */
167
- count -= copy_to_user (buffer , tmp_buff , count );
168
- kfree (tmp_buff );
169
- } else
170
- count = - ENOMEM ;
202
+ /* copy to user outside spinlock */
203
+ count -= copy_to_user (buffer , req -> buf + list -> pos , count );
204
+ list -> pos += count ;
205
+
206
+ /*
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
224
return count ;
173
225
}
@@ -282,28 +334,37 @@ static int f_hidg_open(struct inode *inode, struct file *fd)
282
334
/*-------------------------------------------------------------------------*/
283
335
/* usb_function */
284
336
285
- static void hidg_set_report_complete (struct usb_ep * ep , struct usb_request * req )
337
+ static 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 ;
288
-
289
- if (req -> status != 0 || req -> buf == NULL || req -> actual == 0 ) {
290
- ERROR (hidg -> func .config -> cdev , "%s FAILED\n" , __func__ );
291
- return ;
339
+ struct usb_request * req ;
340
+
341
+ req = usb_ep_alloc_request (ep , GFP_ATOMIC );
342
+ if (req ) {
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 );
295
-
296
- hidg -> set_report_buff = krealloc (hidg -> set_report_buff ,
297
- req -> actual , GFP_ATOMIC );
353
+ static void hidg_set_report_complete (struct usb_ep * ep , struct usb_request * req )
354
+ {
355
+ struct f_hidg * hidg = (struct f_hidg * ) req -> context ;
356
+ struct f_hidg_req_list * req_list ;
357
+ unsigned long flags ;
298
358
299
- if ( hidg -> set_report_buff == NULL ) {
300
- spin_unlock ( & hidg -> spinlock );
359
+ req_list = kzalloc ( sizeof ( * req_list ), GFP_ATOMIC );
360
+ if (! req_list )
301
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
369
wake_up (& hidg -> read_queue );
309
370
}
@@ -344,9 +405,7 @@ static int hidg_setup(struct usb_function *f,
344
405
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE ) << 8
345
406
| HID_REQ_SET_REPORT ):
346
407
VDBG (cdev , "set_report | wLenght=%d\n" , ctrl -> wLength );
347
- req -> context = hidg ;
348
- req -> complete = hidg_set_report_complete ;
349
- goto respond ;
408
+ goto stall ;
350
409
break ;
351
410
352
411
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE ) << 8
@@ -403,16 +462,25 @@ static int hidg_setup(struct usb_function *f,
403
462
static void hidg_disable (struct usb_function * f )
404
463
{
405
464
struct f_hidg * hidg = func_to_hidg (f );
465
+ struct f_hidg_req_list * list , * next ;
406
466
407
467
usb_ep_disable (hidg -> in_ep );
408
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
411
479
static int hidg_set_alt (struct usb_function * f , unsigned intf , unsigned alt )
412
480
{
413
481
struct usb_composite_dev * cdev = f -> config -> cdev ;
414
482
struct f_hidg * hidg = func_to_hidg (f );
415
- int status = 0 ;
483
+ int i , status = 0 ;
416
484
417
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
498
status = usb_ep_enable (hidg -> in_ep );
431
499
if (status < 0 ) {
432
- ERROR (cdev , "Enable endpoint FAILED!\n" );
500
+ ERROR (cdev , "Enable IN endpoint FAILED!\n" );
433
501
goto fail ;
434
502
}
435
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
+
437
549
fail :
438
550
return status ;
439
551
}
@@ -470,13 +582,18 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
470
582
ep -> driver_data = c -> cdev ; /* claim */
471
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
591
/* preallocate request and buffer */
474
592
status = - ENOMEM ;
475
593
hidg -> req = usb_ep_alloc_request (hidg -> in_ep , GFP_KERNEL );
476
594
if (!hidg -> req )
477
595
goto fail ;
478
596
479
-
480
597
hidg -> req -> buf = kmalloc (hidg -> report_length , GFP_KERNEL );
481
598
if (!hidg -> req -> buf )
482
599
goto fail ;
@@ -486,12 +603,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
486
603
hidg_interface_desc .bInterfaceProtocol = hidg -> bInterfaceProtocol ;
487
604
hidg_hs_in_ep_desc .wMaxPacketSize = cpu_to_le16 (hidg -> report_length );
488
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
608
hidg_desc .desc [0 ].bDescriptorType = HID_DT_REPORT ;
490
609
hidg_desc .desc [0 ].wDescriptorLength =
491
610
cpu_to_le16 (hidg -> report_desc_length );
492
611
493
- hidg -> set_report_buff = NULL ;
494
-
495
612
/* copy descriptors */
496
613
f -> descriptors = usb_copy_descriptors (hidg_fs_descriptors );
497
614
if (!f -> descriptors )
@@ -500,6 +617,8 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
500
617
if (gadget_is_dualspeed (c -> cdev -> gadget )) {
501
618
hidg_hs_in_ep_desc .bEndpointAddress =
502
619
hidg_fs_in_ep_desc .bEndpointAddress ;
620
+ hidg_hs_out_ep_desc .bEndpointAddress =
621
+ hidg_fs_out_ep_desc .bEndpointAddress ;
503
622
f -> hs_descriptors = usb_copy_descriptors (hidg_hs_descriptors );
504
623
if (!f -> hs_descriptors )
505
624
goto fail ;
@@ -509,6 +628,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
509
628
spin_lock_init (& hidg -> spinlock );
510
629
init_waitqueue_head (& hidg -> write_queue );
511
630
init_waitqueue_head (& hidg -> read_queue );
631
+ INIT_LIST_HEAD (& hidg -> completed_out_req );
512
632
513
633
/* create char device */
514
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
673
usb_free_descriptors (f -> descriptors );
554
674
555
675
kfree (hidg -> report_desc );
556
- kfree (hidg -> set_report_buff );
557
676
kfree (hidg );
558
677
}
559
678
@@ -624,6 +743,9 @@ int __init hidg_bind_config(struct usb_configuration *c,
624
743
hidg -> func .disable = hidg_disable ;
625
744
hidg -> func .setup = hidg_setup ;
626
745
746
+ /* this could me made configurable at some point */
747
+ hidg -> qlen = 4 ;
748
+
627
749
status = usb_add_function (c , & hidg -> func );
628
750
if (status )
629
751
kfree (hidg );
0 commit comments