aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r--drivers/usb/gadget/composite.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 82314ed22506..5cbb1a41c223 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -461,12 +461,23 @@ static int set_config(struct usb_composite_dev *cdev,
461 reset_config(cdev); 461 reset_config(cdev);
462 goto done; 462 goto done;
463 } 463 }
464
465 if (result == USB_GADGET_DELAYED_STATUS) {
466 DBG(cdev,
467 "%s: interface %d (%s) requested delayed status\n",
468 __func__, tmp, f->name);
469 cdev->delayed_status++;
470 DBG(cdev, "delayed_status count %d\n",
471 cdev->delayed_status);
472 }
464 } 473 }
465 474
466 /* when we return, be sure our power usage is valid */ 475 /* when we return, be sure our power usage is valid */
467 power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW; 476 power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
468done: 477done:
469 usb_gadget_vbus_draw(gadget, power); 478 usb_gadget_vbus_draw(gadget, power);
479 if (result >= 0 && cdev->delayed_status)
480 result = USB_GADGET_DELAYED_STATUS;
470 return result; 481 return result;
471} 482}
472 483
@@ -895,6 +906,14 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
895 if (w_value && !f->set_alt) 906 if (w_value && !f->set_alt)
896 break; 907 break;
897 value = f->set_alt(f, w_index, w_value); 908 value = f->set_alt(f, w_index, w_value);
909 if (value == USB_GADGET_DELAYED_STATUS) {
910 DBG(cdev,
911 "%s: interface %d (%s) requested delayed status\n",
912 __func__, intf, f->name);
913 cdev->delayed_status++;
914 DBG(cdev, "delayed_status count %d\n",
915 cdev->delayed_status);
916 }
898 break; 917 break;
899 case USB_REQ_GET_INTERFACE: 918 case USB_REQ_GET_INTERFACE:
900 if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) 919 if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
@@ -958,7 +977,7 @@ unknown:
958 } 977 }
959 978
960 /* respond with data transfer before status phase? */ 979 /* respond with data transfer before status phase? */
961 if (value >= 0) { 980 if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
962 req->length = value; 981 req->length = value;
963 req->zero = value < w_length; 982 req->zero = value < w_length;
964 value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); 983 value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
@@ -967,6 +986,10 @@ unknown:
967 req->status = 0; 986 req->status = 0;
968 composite_setup_complete(gadget->ep0, req); 987 composite_setup_complete(gadget->ep0, req);
969 } 988 }
989 } else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) {
990 WARN(cdev,
991 "%s: Delayed status not supported for w_length != 0",
992 __func__);
970 } 993 }
971 994
972done: 995done:
@@ -1289,3 +1312,40 @@ void usb_composite_unregister(struct usb_composite_driver *driver)
1289 return; 1312 return;
1290 usb_gadget_unregister_driver(&composite_driver); 1313 usb_gadget_unregister_driver(&composite_driver);
1291} 1314}
1315
1316/**
1317 * usb_composite_setup_continue() - Continue with the control transfer
1318 * @cdev: the composite device who's control transfer was kept waiting
1319 *
1320 * This function must be called by the USB function driver to continue
1321 * with the control transfer's data/status stage in case it had requested to
1322 * delay the data/status stages. A USB function's setup handler (e.g. set_alt())
1323 * can request the composite framework to delay the setup request's data/status
1324 * stages by returning USB_GADGET_DELAYED_STATUS.
1325 */
1326void usb_composite_setup_continue(struct usb_composite_dev *cdev)
1327{
1328 int value;
1329 struct usb_request *req = cdev->req;
1330 unsigned long flags;
1331
1332 DBG(cdev, "%s\n", __func__);
1333 spin_lock_irqsave(&cdev->lock, flags);
1334
1335 if (cdev->delayed_status == 0) {
1336 WARN(cdev, "%s: Unexpected call\n", __func__);
1337
1338 } else if (--cdev->delayed_status == 0) {
1339 DBG(cdev, "%s: Completing delayed status\n", __func__);
1340 req->length = 0;
1341 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
1342 if (value < 0) {
1343 DBG(cdev, "ep_queue --> %d\n", value);
1344 req->status = 0;
1345 composite_setup_complete(cdev->gadget->ep0, req);
1346 }
1347 }
1348
1349 spin_unlock_irqrestore(&cdev->lock, flags);
1350}
1351