@@ -243,22 +243,38 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
243243 int status = req -> status ;
244244
245245 switch (status ) {
246-
247246 case 0 : /* normal completion? */
248247 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 ;
251265 }
252266
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 */
255268 status = usb_ep_queue (ep , req , GFP_ATOMIC );
256- if (status == 0 )
269+ if (status == 0 ) {
257270 return ;
271+ } else {
272+ ERROR (cdev , "Unable to loop back buffer to %s: %d\n" ,
273+ ep -> name , status );
274+ goto free_req ;
275+ }
258276
259277 /* "should never get here" */
260- /* FALLTHROUGH */
261-
262278 default :
263279 ERROR (cdev , "%s loop complete --> %d, %d/%d\n" , ep -> name ,
264280 status , req -> actual , req -> length );
@@ -272,6 +288,10 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
272288 case - ECONNABORTED : /* hardware forced ep reset */
273289 case - ECONNRESET : /* request dequeued */
274290 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 );
275295 free_ep_req (ep , req );
276296 return ;
277297 }
@@ -293,50 +313,72 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
293313 return alloc_ep_req (ep , len , loop -> buflen );
294314}
295315
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 )
298318{
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 ;
314322
315323 /*
316324 * 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
319328 */
320329 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 ;
324347
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 );
327349 if (result ) {
328350 ERROR (cdev , "%s queue req --> %d\n" ,
329- ep -> name , result );
330- goto fail1 ;
351+ loop -> out_ep -> name , result );
352+ goto fail_out ;
331353 }
332354 }
333355
334356 return 0 ;
335357
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 ;
338374
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 :
340382 return result ;
341383}
342384
@@ -347,13 +389,24 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
347389
348390 result = enable_endpoint (cdev , loop , loop -> in_ep );
349391 if (result )
350- return result ;
392+ goto out ;
351393
352394 result = enable_endpoint (cdev , loop , loop -> out_ep );
353395 if (result )
354- return result ;
396+ goto disable_in ;
397+
398+ result = alloc_requests (cdev , loop );
399+ if (result )
400+ goto disable_out ;
355401
356402 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 :
357410 return result ;
358411}
359412
0 commit comments