@@ -243,22 +243,38 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
243
243
int status = req -> status ;
244
244
245
245
switch (status ) {
246
-
247
246
case 0 : /* normal completion? */
248
247
if (ep == loop -> out_ep ) {
249
- req -> zero = (req -> actual < req -> length );
250
- req -> length = req -> actual ;
248
+ /*
249
+ * We received some data from the host so let's
250
+ * queue it so host can read the from our in ep
251
+ */
252
+ struct usb_request * in_req = req -> context ;
253
+
254
+ in_req -> zero = (req -> actual < req -> length );
255
+ in_req -> length = req -> actual ;
256
+ ep = loop -> in_ep ;
257
+ req = in_req ;
258
+ } else {
259
+ /*
260
+ * We have just looped back a bunch of data
261
+ * to host. Now let's wait for some more data.
262
+ */
263
+ req = req -> context ;
264
+ ep = loop -> out_ep ;
251
265
}
252
266
253
- /* queue the buffer for some later OUT packet */
254
- req -> length = loop -> buflen ;
267
+ /* queue the buffer back to host or for next bunch of data */
255
268
status = usb_ep_queue (ep , req , GFP_ATOMIC );
256
- if (status == 0 )
269
+ if (status == 0 ) {
257
270
return ;
271
+ } else {
272
+ ERROR (cdev , "Unable to loop back buffer to %s: %d\n" ,
273
+ ep -> name , status );
274
+ goto free_req ;
275
+ }
258
276
259
277
/* "should never get here" */
260
- /* FALLTHROUGH */
261
-
262
278
default :
263
279
ERROR (cdev , "%s loop complete --> %d, %d/%d\n" , ep -> name ,
264
280
status , req -> actual , req -> length );
@@ -272,6 +288,10 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
272
288
case - ECONNABORTED : /* hardware forced ep reset */
273
289
case - ECONNRESET : /* request dequeued */
274
290
case - ESHUTDOWN : /* disconnect from host */
291
+ free_req :
292
+ usb_ep_free_request (ep == loop -> in_ep ?
293
+ loop -> out_ep : loop -> in_ep ,
294
+ req -> context );
275
295
free_ep_req (ep , req );
276
296
return ;
277
297
}
@@ -293,50 +313,72 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
293
313
return alloc_ep_req (ep , len , loop -> buflen );
294
314
}
295
315
296
- static int enable_endpoint (struct usb_composite_dev * cdev , struct f_loopback * loop ,
297
- struct usb_ep * ep )
316
+ static int alloc_requests (struct usb_composite_dev * cdev ,
317
+ struct f_loopback * loop )
298
318
{
299
- struct usb_request * req ;
300
- unsigned i ;
301
- int result ;
302
-
303
- /*
304
- * one endpoint writes data back IN to the host while another endpoint
305
- * just reads OUT packets
306
- */
307
- result = config_ep_by_speed (cdev -> gadget , & (loop -> function ), ep );
308
- if (result )
309
- goto fail0 ;
310
- result = usb_ep_enable (ep );
311
- if (result < 0 )
312
- goto fail0 ;
313
- ep -> driver_data = loop ;
319
+ struct usb_request * in_req , * out_req ;
320
+ int i ;
321
+ int result = 0 ;
314
322
315
323
/*
316
324
* allocate a bunch of read buffers and queue them all at once.
317
- * we buffer at most 'qlen' transfers; fewer if any need more
318
- * than 'buflen' bytes each.
325
+ * we buffer at most 'qlen' transfers; We allocate buffers only
326
+ * for out transfer and reuse them in IN transfers to implement
327
+ * our loopback functionality
319
328
*/
320
329
for (i = 0 ; i < loop -> qlen && result == 0 ; i ++ ) {
321
- req = lb_alloc_ep_req (ep , 0 );
322
- if (!req )
323
- goto fail1 ;
330
+ result = - ENOMEM ;
331
+
332
+ in_req = usb_ep_alloc_request (loop -> in_ep , GFP_KERNEL );
333
+ if (!in_req )
334
+ goto fail ;
335
+
336
+ out_req = lb_alloc_ep_req (loop -> out_ep , 0 );
337
+ if (!out_req )
338
+ goto fail_in ;
339
+
340
+ in_req -> complete = loopback_complete ;
341
+ out_req -> complete = loopback_complete ;
342
+
343
+ in_req -> buf = out_req -> buf ;
344
+ /* length will be set in complete routine */
345
+ in_req -> context = out_req ;
346
+ out_req -> context = in_req ;
324
347
325
- req -> complete = loopback_complete ;
326
- result = usb_ep_queue (ep , req , GFP_ATOMIC );
348
+ result = usb_ep_queue (loop -> out_ep , out_req , GFP_ATOMIC );
327
349
if (result ) {
328
350
ERROR (cdev , "%s queue req --> %d\n" ,
329
- ep -> name , result );
330
- goto fail1 ;
351
+ loop -> out_ep -> name , result );
352
+ goto fail_out ;
331
353
}
332
354
}
333
355
334
356
return 0 ;
335
357
336
- fail1 :
337
- usb_ep_disable (ep );
358
+ fail_out :
359
+ free_ep_req (loop -> out_ep , out_req );
360
+ fail_in :
361
+ usb_ep_free_request (loop -> in_ep , in_req );
362
+ fail :
363
+ return result ;
364
+ }
365
+
366
+ static int enable_endpoint (struct usb_composite_dev * cdev ,
367
+ struct f_loopback * loop , struct usb_ep * ep )
368
+ {
369
+ int result ;
370
+
371
+ result = config_ep_by_speed (cdev -> gadget , & (loop -> function ), ep );
372
+ if (result )
373
+ goto out ;
338
374
339
- fail0 :
375
+ result = usb_ep_enable (ep );
376
+ if (result < 0 )
377
+ goto out ;
378
+ ep -> driver_data = loop ;
379
+ result = 0 ;
380
+
381
+ out :
340
382
return result ;
341
383
}
342
384
@@ -347,13 +389,24 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
347
389
348
390
result = enable_endpoint (cdev , loop , loop -> in_ep );
349
391
if (result )
350
- return result ;
392
+ goto out ;
351
393
352
394
result = enable_endpoint (cdev , loop , loop -> out_ep );
353
395
if (result )
354
- return result ;
396
+ goto disable_in ;
397
+
398
+ result = alloc_requests (cdev , loop );
399
+ if (result )
400
+ goto disable_out ;
355
401
356
402
DBG (cdev , "%s enabled\n" , loop -> function .name );
403
+ return 0 ;
404
+
405
+ disable_out :
406
+ usb_ep_disable (loop -> out_ep );
407
+ disable_in :
408
+ usb_ep_disable (loop -> in_ep );
409
+ out :
357
410
return result ;
358
411
}
359
412
0 commit comments