Loading arch/arm64/configs/msm-auto-perf_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -461,6 +461,7 @@ CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_UEVENT=y CONFIG_USB_CONFIGFS_F_UAC1=y CONFIG_USB_CONFIGFS_F_MIDI=y CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_USB_CONFIGFS_F_QDSS=y Loading arch/arm64/configs/msm-auto_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,7 @@ CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_UEVENT=y CONFIG_USB_CONFIGFS_F_UAC1=y CONFIG_USB_CONFIGFS_F_MIDI=y CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_USB_CONFIGFS_F_QDSS=y Loading drivers/usb/gadget/function/f_hid.c +168 −29 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ struct f_hidg { /* configuration */ unsigned char bInterfaceSubClass; unsigned char bInterfaceProtocol; unsigned char protocol; unsigned short report_desc_length; char *report_desc; unsigned short report_length; Loading Loading @@ -98,6 +99,60 @@ static struct hid_descriptor hidg_desc = { /*.desc[0].wDescriptorLenght = DYNAMIC */ }; /* Super-Speed Support */ static struct usb_endpoint_descriptor hidg_ss_in_ep_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, /*.wMaxPacketSize = DYNAMIC */ .bInterval = 4, /* FIXME: Add this field in the * HID gadget configuration? * (struct hidg_func_descriptor) */ }; static struct usb_ss_ep_comp_descriptor hidg_ss_in_comp_desc = { .bLength = sizeof(hidg_ss_in_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /* .bMaxBurst = 0, */ /* .bmAttributes = 0, */ /* .wBytesPerInterval = DYNAMIC */ }; static struct usb_endpoint_descriptor hidg_ss_out_ep_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_INT, /*.wMaxPacketSize = DYNAMIC */ .bInterval = 4, /* FIXME: Add this field in the * HID gadget configuration? * (struct hidg_func_descriptor) */ }; static struct usb_ss_ep_comp_descriptor hidg_ss_out_comp_desc = { .bLength = sizeof(hidg_ss_out_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /* .bMaxBurst = 0, */ /* .bmAttributes = 0, */ /* .wBytesPerInterval = DYNAMIC */ }; static struct usb_descriptor_header *hidg_ss_descriptors[] = { (struct usb_descriptor_header *)&hidg_interface_desc, (struct usb_descriptor_header *)&hidg_desc, (struct usb_descriptor_header *)&hidg_ss_in_ep_desc, (struct usb_descriptor_header *)&hidg_ss_in_comp_desc, (struct usb_descriptor_header *)&hidg_ss_out_ep_desc, (struct usb_descriptor_header *)&hidg_ss_out_comp_desc, NULL, }; /* High-Speed Support */ static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = { Loading Loading @@ -284,6 +339,7 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, size_t count, loff_t *offp) { struct f_hidg *hidg = file->private_data; struct usb_request *req; unsigned long flags; ssize_t status = -ENOMEM; Loading @@ -293,7 +349,7 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, spin_lock_irqsave(&hidg->write_spinlock, flags); #define WRITE_COND (!hidg->write_pending) try_again: /* write queue */ while (!WRITE_COND) { spin_unlock_irqrestore(&hidg->write_spinlock, flags); Loading @@ -308,10 +364,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, } hidg->write_pending = 1; req = hidg->req; count = min_t(unsigned, count, hidg->report_length); spin_unlock_irqrestore(&hidg->write_spinlock, flags); status = copy_from_user(hidg->req->buf, buffer, count); status = copy_from_user(req->buf, buffer, count); if (status != 0) { ERROR(hidg->func.config->cdev, Loading @@ -320,24 +377,38 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, goto release_write_pending; } hidg->req->status = 0; hidg->req->zero = 0; hidg->req->length = count; hidg->req->complete = f_hidg_req_complete; hidg->req->context = hidg; spin_lock_irqsave(&hidg->write_spinlock, flags); status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); /* when our function has been disabled by host */ if (!hidg->req) { free_ep_req(hidg->in_ep, req); /* * TODO * Should we fail with error here? */ goto try_again; } req->status = 0; req->zero = 0; req->length = count; req->complete = f_hidg_req_complete; req->context = hidg; status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC); if (status < 0) { ERROR(hidg->func.config->cdev, "usb_ep_queue error on int endpoint %zd\n", status); goto release_write_pending; goto release_write_pending_unlocked; } else { status = count; } spin_unlock_irqrestore(&hidg->write_spinlock, flags); return status; release_write_pending: spin_lock_irqsave(&hidg->write_spinlock, flags); release_write_pending_unlocked: hidg->write_pending = 0; spin_unlock_irqrestore(&hidg->write_spinlock, flags); Loading Loading @@ -457,7 +528,9 @@ static int hidg_setup(struct usb_function *f, case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 | HID_REQ_GET_PROTOCOL): VDBG(cdev, "get_protocol\n"); goto stall; length = min_t(unsigned int, length, 1); ((u8 *) req->buf)[0] = hidg->protocol; goto respond; break; case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 Loading @@ -469,6 +542,17 @@ static int hidg_setup(struct usb_function *f, case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 | HID_REQ_SET_PROTOCOL): VDBG(cdev, "set_protocol\n"); if (value > HID_REPORT_PROTOCOL) goto stall; length = 0; /* * We assume that programs implementing the Boot protocol * are also compatible with the Report Protocol */ if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { hidg->protocol = value; goto respond; } goto stall; break; Loading Loading @@ -541,12 +625,23 @@ static void hidg_disable(struct usb_function *f) kfree(list); } spin_unlock_irqrestore(&hidg->read_spinlock, flags); spin_lock_irqsave(&hidg->write_spinlock, flags); if (!hidg->write_pending) { free_ep_req(hidg->in_ep, hidg->req); hidg->write_pending = 1; } hidg->req = NULL; spin_unlock_irqrestore(&hidg->write_spinlock, flags); } static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct usb_composite_dev *cdev = f->config->cdev; struct f_hidg *hidg = func_to_hidg(f); struct usb_request *req_in = NULL; unsigned long flags; int i, status = 0; VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt); Loading @@ -567,6 +662,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) goto fail; } hidg->in_ep->driver_data = hidg; req_in = hidg_alloc_ep_req(hidg->in_ep, hidg->report_length); if (!req_in) { status = -ENOMEM; goto disable_ep_in; } } Loading @@ -578,12 +679,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) hidg->out_ep); if (status) { ERROR(cdev, "config_ep_by_speed FAILED!\n"); goto fail; goto free_req_in; } status = usb_ep_enable(hidg->out_ep); if (status < 0) { ERROR(cdev, "Enable OUT endpoint FAILED!\n"); goto fail; goto free_req_in; } hidg->out_ep->driver_data = hidg; Loading @@ -599,17 +700,37 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) req->context = hidg; status = usb_ep_queue(hidg->out_ep, req, GFP_ATOMIC); if (status) if (status) { ERROR(cdev, "%s queue req --> %d\n", hidg->out_ep->name, status); free_ep_req(hidg->out_ep, req); } } else { usb_ep_disable(hidg->out_ep); status = -ENOMEM; goto fail; goto disable_out_ep; } } } if (hidg->in_ep != NULL) { spin_lock_irqsave(&hidg->write_spinlock, flags); hidg->req = req_in; hidg->write_pending = 0; spin_unlock_irqrestore(&hidg->write_spinlock, flags); wake_up(&hidg->write_queue); } return 0; disable_out_ep: usb_ep_disable(hidg->out_ep); free_req_in: if (req_in) free_ep_req(hidg->in_ep, req_in); disable_ep_in: if (hidg->in_ep) usb_ep_disable(hidg->in_ep); fail: return status; } Loading Loading @@ -658,17 +779,18 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) goto fail; hidg->out_ep = ep; /* preallocate request and buffer */ status = -ENOMEM; hidg->req = alloc_ep_req(hidg->in_ep, hidg->report_length); if (!hidg->req) goto fail; /* set descriptor dynamic values */ hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass; hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; hidg->protocol = HID_REPORT_PROTOCOL; hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_ss_in_comp_desc.wBytesPerInterval = cpu_to_le16(hidg->report_length); hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_ss_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_ss_out_comp_desc.wBytesPerInterval = cpu_to_le16(hidg->report_length); hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); /* Loading @@ -684,12 +806,19 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) hidg_hs_out_ep_desc.bEndpointAddress = hidg_fs_out_ep_desc.bEndpointAddress; hidg_ss_in_ep_desc.bEndpointAddress = hidg_fs_in_ep_desc.bEndpointAddress; hidg_ss_out_ep_desc.bEndpointAddress = hidg_fs_out_ep_desc.bEndpointAddress; status = usb_assign_descriptors(f, hidg_fs_descriptors, hidg_hs_descriptors, NULL); hidg_hs_descriptors, hidg_ss_descriptors); if (status) goto fail; spin_lock_init(&hidg->write_spinlock); hidg->write_pending = 1; hidg->req = NULL; spin_lock_init(&hidg->read_spinlock); init_waitqueue_head(&hidg->write_queue); init_waitqueue_head(&hidg->read_queue); Loading Loading @@ -883,7 +1012,7 @@ static void hidg_free_inst(struct usb_function_instance *f) mutex_lock(&hidg_ida_lock); hidg_put_minor(opts->minor); if (idr_is_empty(&hidg_ida.idr)) if (ida_is_empty(&hidg_ida)) ghid_cleanup(); mutex_unlock(&hidg_ida_lock); Loading @@ -909,7 +1038,7 @@ static struct usb_function_instance *hidg_alloc_inst(void) mutex_lock(&hidg_ida_lock); if (idr_is_empty(&hidg_ida.idr)) { if (ida_is_empty(&hidg_ida)) { status = ghid_setup(NULL, HIDG_MINORS); if (status) { ret = ERR_PTR(status); Loading @@ -922,7 +1051,7 @@ static struct usb_function_instance *hidg_alloc_inst(void) if (opts->minor < 0) { ret = ERR_PTR(opts->minor); kfree(opts); if (idr_is_empty(&hidg_ida.idr)) if (ida_is_empty(&hidg_ida)) ghid_cleanup(); goto unlock; } Loading Loading @@ -954,10 +1083,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) device_destroy(hidg_class, MKDEV(major, hidg->minor)); cdev_del(&hidg->cdev); /* disable/free request and end point */ usb_ep_disable(hidg->in_ep); free_ep_req(hidg->in_ep, hidg->req); usb_free_all_descriptors(f); } Loading Loading @@ -1009,6 +1134,20 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(hid, hidg_alloc_inst, hidg_alloc); static int __init afunc_init(void) { return usb_function_register(&hidusb_func); } static void __exit afunc_exit(void) { usb_function_unregister(&hidusb_func); } module_init(afunc_init); module_exit(afunc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Fabien Chouteau"); Loading drivers/usb/gadget/function/f_printer.c +3 −3 Original line number Diff line number Diff line Loading @@ -1269,7 +1269,7 @@ static void gprinter_free_inst(struct usb_function_instance *f) mutex_lock(&printer_ida_lock); gprinter_put_minor(opts->minor); if (idr_is_empty(&printer_ida.idr)) if (ida_is_empty(&printer_ida)) gprinter_cleanup(); mutex_unlock(&printer_ida_lock); Loading @@ -1293,7 +1293,7 @@ static struct usb_function_instance *gprinter_alloc_inst(void) mutex_lock(&printer_ida_lock); if (idr_is_empty(&printer_ida.idr)) { if (ida_is_empty(&printer_ida)) { status = gprinter_setup(PRINTER_MINORS); if (status) { ret = ERR_PTR(status); Loading @@ -1306,7 +1306,7 @@ static struct usb_function_instance *gprinter_alloc_inst(void) if (opts->minor < 0) { ret = ERR_PTR(opts->minor); kfree(opts); if (idr_is_empty(&printer_ida.idr)) if (ida_is_empty(&printer_ida)) gprinter_cleanup(); goto unlock; } Loading include/linux/hid.h +6 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,12 @@ struct hid_item { #define HID_GROUP_WACOM 0x0101 #define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102 /* * HID protocol status */ #define HID_REPORT_PROTOCOL 1 #define HID_BOOT_PROTOCOL 0 /* * This is the global environment of the parser. This information is * persistent for main-items. The global environment can be saved and Loading Loading
arch/arm64/configs/msm-auto-perf_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -461,6 +461,7 @@ CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_UEVENT=y CONFIG_USB_CONFIGFS_F_UAC1=y CONFIG_USB_CONFIGFS_F_MIDI=y CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_USB_CONFIGFS_F_QDSS=y Loading
arch/arm64/configs/msm-auto_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,7 @@ CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_UEVENT=y CONFIG_USB_CONFIGFS_F_UAC1=y CONFIG_USB_CONFIGFS_F_MIDI=y CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_USB_CONFIGFS_F_QDSS=y Loading
drivers/usb/gadget/function/f_hid.c +168 −29 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ struct f_hidg { /* configuration */ unsigned char bInterfaceSubClass; unsigned char bInterfaceProtocol; unsigned char protocol; unsigned short report_desc_length; char *report_desc; unsigned short report_length; Loading Loading @@ -98,6 +99,60 @@ static struct hid_descriptor hidg_desc = { /*.desc[0].wDescriptorLenght = DYNAMIC */ }; /* Super-Speed Support */ static struct usb_endpoint_descriptor hidg_ss_in_ep_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, /*.wMaxPacketSize = DYNAMIC */ .bInterval = 4, /* FIXME: Add this field in the * HID gadget configuration? * (struct hidg_func_descriptor) */ }; static struct usb_ss_ep_comp_descriptor hidg_ss_in_comp_desc = { .bLength = sizeof(hidg_ss_in_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /* .bMaxBurst = 0, */ /* .bmAttributes = 0, */ /* .wBytesPerInterval = DYNAMIC */ }; static struct usb_endpoint_descriptor hidg_ss_out_ep_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_INT, /*.wMaxPacketSize = DYNAMIC */ .bInterval = 4, /* FIXME: Add this field in the * HID gadget configuration? * (struct hidg_func_descriptor) */ }; static struct usb_ss_ep_comp_descriptor hidg_ss_out_comp_desc = { .bLength = sizeof(hidg_ss_out_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /* .bMaxBurst = 0, */ /* .bmAttributes = 0, */ /* .wBytesPerInterval = DYNAMIC */ }; static struct usb_descriptor_header *hidg_ss_descriptors[] = { (struct usb_descriptor_header *)&hidg_interface_desc, (struct usb_descriptor_header *)&hidg_desc, (struct usb_descriptor_header *)&hidg_ss_in_ep_desc, (struct usb_descriptor_header *)&hidg_ss_in_comp_desc, (struct usb_descriptor_header *)&hidg_ss_out_ep_desc, (struct usb_descriptor_header *)&hidg_ss_out_comp_desc, NULL, }; /* High-Speed Support */ static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = { Loading Loading @@ -284,6 +339,7 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, size_t count, loff_t *offp) { struct f_hidg *hidg = file->private_data; struct usb_request *req; unsigned long flags; ssize_t status = -ENOMEM; Loading @@ -293,7 +349,7 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, spin_lock_irqsave(&hidg->write_spinlock, flags); #define WRITE_COND (!hidg->write_pending) try_again: /* write queue */ while (!WRITE_COND) { spin_unlock_irqrestore(&hidg->write_spinlock, flags); Loading @@ -308,10 +364,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, } hidg->write_pending = 1; req = hidg->req; count = min_t(unsigned, count, hidg->report_length); spin_unlock_irqrestore(&hidg->write_spinlock, flags); status = copy_from_user(hidg->req->buf, buffer, count); status = copy_from_user(req->buf, buffer, count); if (status != 0) { ERROR(hidg->func.config->cdev, Loading @@ -320,24 +377,38 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, goto release_write_pending; } hidg->req->status = 0; hidg->req->zero = 0; hidg->req->length = count; hidg->req->complete = f_hidg_req_complete; hidg->req->context = hidg; spin_lock_irqsave(&hidg->write_spinlock, flags); status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); /* when our function has been disabled by host */ if (!hidg->req) { free_ep_req(hidg->in_ep, req); /* * TODO * Should we fail with error here? */ goto try_again; } req->status = 0; req->zero = 0; req->length = count; req->complete = f_hidg_req_complete; req->context = hidg; status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC); if (status < 0) { ERROR(hidg->func.config->cdev, "usb_ep_queue error on int endpoint %zd\n", status); goto release_write_pending; goto release_write_pending_unlocked; } else { status = count; } spin_unlock_irqrestore(&hidg->write_spinlock, flags); return status; release_write_pending: spin_lock_irqsave(&hidg->write_spinlock, flags); release_write_pending_unlocked: hidg->write_pending = 0; spin_unlock_irqrestore(&hidg->write_spinlock, flags); Loading Loading @@ -457,7 +528,9 @@ static int hidg_setup(struct usb_function *f, case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 | HID_REQ_GET_PROTOCOL): VDBG(cdev, "get_protocol\n"); goto stall; length = min_t(unsigned int, length, 1); ((u8 *) req->buf)[0] = hidg->protocol; goto respond; break; case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 Loading @@ -469,6 +542,17 @@ static int hidg_setup(struct usb_function *f, case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 | HID_REQ_SET_PROTOCOL): VDBG(cdev, "set_protocol\n"); if (value > HID_REPORT_PROTOCOL) goto stall; length = 0; /* * We assume that programs implementing the Boot protocol * are also compatible with the Report Protocol */ if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { hidg->protocol = value; goto respond; } goto stall; break; Loading Loading @@ -541,12 +625,23 @@ static void hidg_disable(struct usb_function *f) kfree(list); } spin_unlock_irqrestore(&hidg->read_spinlock, flags); spin_lock_irqsave(&hidg->write_spinlock, flags); if (!hidg->write_pending) { free_ep_req(hidg->in_ep, hidg->req); hidg->write_pending = 1; } hidg->req = NULL; spin_unlock_irqrestore(&hidg->write_spinlock, flags); } static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct usb_composite_dev *cdev = f->config->cdev; struct f_hidg *hidg = func_to_hidg(f); struct usb_request *req_in = NULL; unsigned long flags; int i, status = 0; VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt); Loading @@ -567,6 +662,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) goto fail; } hidg->in_ep->driver_data = hidg; req_in = hidg_alloc_ep_req(hidg->in_ep, hidg->report_length); if (!req_in) { status = -ENOMEM; goto disable_ep_in; } } Loading @@ -578,12 +679,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) hidg->out_ep); if (status) { ERROR(cdev, "config_ep_by_speed FAILED!\n"); goto fail; goto free_req_in; } status = usb_ep_enable(hidg->out_ep); if (status < 0) { ERROR(cdev, "Enable OUT endpoint FAILED!\n"); goto fail; goto free_req_in; } hidg->out_ep->driver_data = hidg; Loading @@ -599,17 +700,37 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) req->context = hidg; status = usb_ep_queue(hidg->out_ep, req, GFP_ATOMIC); if (status) if (status) { ERROR(cdev, "%s queue req --> %d\n", hidg->out_ep->name, status); free_ep_req(hidg->out_ep, req); } } else { usb_ep_disable(hidg->out_ep); status = -ENOMEM; goto fail; goto disable_out_ep; } } } if (hidg->in_ep != NULL) { spin_lock_irqsave(&hidg->write_spinlock, flags); hidg->req = req_in; hidg->write_pending = 0; spin_unlock_irqrestore(&hidg->write_spinlock, flags); wake_up(&hidg->write_queue); } return 0; disable_out_ep: usb_ep_disable(hidg->out_ep); free_req_in: if (req_in) free_ep_req(hidg->in_ep, req_in); disable_ep_in: if (hidg->in_ep) usb_ep_disable(hidg->in_ep); fail: return status; } Loading Loading @@ -658,17 +779,18 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) goto fail; hidg->out_ep = ep; /* preallocate request and buffer */ status = -ENOMEM; hidg->req = alloc_ep_req(hidg->in_ep, hidg->report_length); if (!hidg->req) goto fail; /* set descriptor dynamic values */ hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass; hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; hidg->protocol = HID_REPORT_PROTOCOL; hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_ss_in_comp_desc.wBytesPerInterval = cpu_to_le16(hidg->report_length); hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_ss_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_ss_out_comp_desc.wBytesPerInterval = cpu_to_le16(hidg->report_length); hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); /* Loading @@ -684,12 +806,19 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) hidg_hs_out_ep_desc.bEndpointAddress = hidg_fs_out_ep_desc.bEndpointAddress; hidg_ss_in_ep_desc.bEndpointAddress = hidg_fs_in_ep_desc.bEndpointAddress; hidg_ss_out_ep_desc.bEndpointAddress = hidg_fs_out_ep_desc.bEndpointAddress; status = usb_assign_descriptors(f, hidg_fs_descriptors, hidg_hs_descriptors, NULL); hidg_hs_descriptors, hidg_ss_descriptors); if (status) goto fail; spin_lock_init(&hidg->write_spinlock); hidg->write_pending = 1; hidg->req = NULL; spin_lock_init(&hidg->read_spinlock); init_waitqueue_head(&hidg->write_queue); init_waitqueue_head(&hidg->read_queue); Loading Loading @@ -883,7 +1012,7 @@ static void hidg_free_inst(struct usb_function_instance *f) mutex_lock(&hidg_ida_lock); hidg_put_minor(opts->minor); if (idr_is_empty(&hidg_ida.idr)) if (ida_is_empty(&hidg_ida)) ghid_cleanup(); mutex_unlock(&hidg_ida_lock); Loading @@ -909,7 +1038,7 @@ static struct usb_function_instance *hidg_alloc_inst(void) mutex_lock(&hidg_ida_lock); if (idr_is_empty(&hidg_ida.idr)) { if (ida_is_empty(&hidg_ida)) { status = ghid_setup(NULL, HIDG_MINORS); if (status) { ret = ERR_PTR(status); Loading @@ -922,7 +1051,7 @@ static struct usb_function_instance *hidg_alloc_inst(void) if (opts->minor < 0) { ret = ERR_PTR(opts->minor); kfree(opts); if (idr_is_empty(&hidg_ida.idr)) if (ida_is_empty(&hidg_ida)) ghid_cleanup(); goto unlock; } Loading Loading @@ -954,10 +1083,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) device_destroy(hidg_class, MKDEV(major, hidg->minor)); cdev_del(&hidg->cdev); /* disable/free request and end point */ usb_ep_disable(hidg->in_ep); free_ep_req(hidg->in_ep, hidg->req); usb_free_all_descriptors(f); } Loading Loading @@ -1009,6 +1134,20 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) } DECLARE_USB_FUNCTION_INIT(hid, hidg_alloc_inst, hidg_alloc); static int __init afunc_init(void) { return usb_function_register(&hidusb_func); } static void __exit afunc_exit(void) { usb_function_unregister(&hidusb_func); } module_init(afunc_init); module_exit(afunc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Fabien Chouteau"); Loading
drivers/usb/gadget/function/f_printer.c +3 −3 Original line number Diff line number Diff line Loading @@ -1269,7 +1269,7 @@ static void gprinter_free_inst(struct usb_function_instance *f) mutex_lock(&printer_ida_lock); gprinter_put_minor(opts->minor); if (idr_is_empty(&printer_ida.idr)) if (ida_is_empty(&printer_ida)) gprinter_cleanup(); mutex_unlock(&printer_ida_lock); Loading @@ -1293,7 +1293,7 @@ static struct usb_function_instance *gprinter_alloc_inst(void) mutex_lock(&printer_ida_lock); if (idr_is_empty(&printer_ida.idr)) { if (ida_is_empty(&printer_ida)) { status = gprinter_setup(PRINTER_MINORS); if (status) { ret = ERR_PTR(status); Loading @@ -1306,7 +1306,7 @@ static struct usb_function_instance *gprinter_alloc_inst(void) if (opts->minor < 0) { ret = ERR_PTR(opts->minor); kfree(opts); if (idr_is_empty(&printer_ida.idr)) if (ida_is_empty(&printer_ida)) gprinter_cleanup(); goto unlock; } Loading
include/linux/hid.h +6 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,12 @@ struct hid_item { #define HID_GROUP_WACOM 0x0101 #define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102 /* * HID protocol status */ #define HID_REPORT_PROTOCOL 1 #define HID_BOOT_PROTOCOL 0 /* * This is the global environment of the parser. This information is * persistent for main-items. The global environment can be saved and Loading