diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c index d33229c35282..84396f2023f1 100644 --- a/drivers/usb/gadget/function/f_accessory.c +++ b/drivers/usb/gadget/function/f_accessory.c @@ -117,6 +117,12 @@ struct acc_dev { /* delayed work for handling ACCESSORY_START */ struct delayed_work start_work; + /* work for handling ACCESSORY GET PROTOCOL */ + struct work_struct getprotocol_work; + + /* work for handling ACCESSORY SEND STRING */ + struct work_struct sendstring_work; + /* worker for registering and unregistering hid devices */ struct work_struct hid_work; @@ -854,6 +860,7 @@ int acc_ctrlrequest(struct usb_composite_dev *cdev, value = 0; cdev->req->complete = acc_complete_setup_noop; } else if (b_request == ACCESSORY_SEND_STRING) { + schedule_work(&dev->sendstring_work); dev->string_index = w_index; cdev->gadget->ep0->driver_data = dev; cdev->req->complete = acc_complete_set_string; @@ -900,6 +907,7 @@ int acc_ctrlrequest(struct usb_composite_dev *cdev, } } else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) { if (b_request == ACCESSORY_GET_PROTOCOL) { + schedule_work(&dev->getprotocol_work); *((u16 *)cdev->req->buf) = PROTOCOL_VERSION; value = sizeof(u16); cdev->req->complete = acc_complete_setup_noop; @@ -1047,6 +1055,20 @@ acc_function_unbind(struct usb_configuration *c, struct usb_function *f) acc_hid_unbind(dev); } +static void acc_getprotocol_work(struct work_struct *data) +{ + char *envp[2] = { "ACCESSORY=GETPROTOCOL", NULL }; + + kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp); +} + +static void acc_sendstring_work(struct work_struct *data) +{ + char *envp[2] = { "ACCESSORY=SENDSTRING", NULL }; + + kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp); +} + static void acc_start_work(struct work_struct *data) { char *envp[2] = { "ACCESSORY=START", NULL }; @@ -1213,6 +1235,8 @@ static int acc_setup(void) INIT_LIST_HEAD(&dev->dead_hid_list); INIT_DELAYED_WORK(&dev->start_work, acc_start_work); INIT_WORK(&dev->hid_work, acc_hid_work); + INIT_WORK(&dev->getprotocol_work, acc_getprotocol_work); + INIT_WORK(&dev->sendstring_work, acc_sendstring_work); /* _acc_dev must be set before calling usb_gadget_register_driver */ _acc_dev = dev;