Lines Matching +full:composite +full:- +full:in

1 // SPDX-License-Identifier: GPL-2.0+
3 * composite.c - infrastructure for Composite USB Gadgets
5 * Copyright (C) 2006-2008 David Brownell
6 * U-Boot porting: Lukasz Majewski <l.majewski@samsung.com>
11 #include <linux/usb/composite.h>
15 static struct usb_composite_driver *composite; variable
18 * usb_add_function() - add a function to a configuration
34 int value = -EINVAL; in usb_add_function()
37 function->name, function, in usb_add_function()
38 config->label, config); in usb_add_function()
40 if (!function->set_alt || !function->disable) in usb_add_function()
43 function->config = config; in usb_add_function()
44 list_add_tail(&function->list, &config->functions); in usb_add_function()
46 if (function->bind) { in usb_add_function()
47 value = function->bind(config, function); in usb_add_function()
49 list_del(&function->list); in usb_add_function()
50 function->config = NULL; in usb_add_function()
55 if (!config->fullspeed && function->descriptors) in usb_add_function()
56 config->fullspeed = 1; in usb_add_function()
57 if (!config->highspeed && function->hs_descriptors) in usb_add_function()
58 config->highspeed = 1; in usb_add_function()
62 debug("adding '%s'/%p --> %d\n", in usb_add_function()
63 function->name, function, value); in usb_add_function()
68 * usb_function_deactivate - prevent function and gadget enumeration
88 struct usb_composite_dev *cdev = function->config->cdev; in usb_function_deactivate()
91 if (cdev->deactivations == 0) in usb_function_deactivate()
92 status = usb_gadget_disconnect(cdev->gadget); in usb_function_deactivate()
94 cdev->deactivations++; in usb_function_deactivate()
100 * usb_function_activate - allow function and gadget enumeration
111 struct usb_composite_dev *cdev = function->config->cdev; in usb_function_activate()
114 if (cdev->deactivations == 0) in usb_function_activate()
115 status = -EINVAL; in usb_function_activate()
117 cdev->deactivations--; in usb_function_activate()
118 if (cdev->deactivations == 0) in usb_function_activate()
119 status = usb_gadget_connect(cdev->gadget); in usb_function_activate()
126 * usb_interface_id() - allocate an unused interface ID
133 * ID in interface, association, CDC union, and other descriptors. It
136 * also be class-specific or vendor-specific requests to handle.
141 * identifers are configuration-specific, functions used in more than
142 * one configuration (or more than once in a given configuration) need
145 * Returns the interface ID which was allocated; or -ENODEV if no
151 unsigned char id = config->next_interface_id; in usb_interface_id()
154 config->interface[id] = function; in usb_interface_id()
155 config->next_interface_id = id + 1; in usb_interface_id()
158 return -ENODEV; in usb_interface_id()
164 int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE; in config_buf()
173 c->bLength = USB_DT_CONFIG_SIZE; in config_buf()
174 c->bDescriptorType = type; in config_buf()
176 c->bNumInterfaces = config->next_interface_id; in config_buf()
177 c->bConfigurationValue = config->bConfigurationValue; in config_buf()
178 c->iConfiguration = config->iConfiguration; in config_buf()
179 c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; in config_buf()
180 c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2); in config_buf()
183 if (config->descriptors) { in config_buf()
185 config->descriptors); in config_buf()
188 len -= status; in config_buf()
193 list_for_each_entry(f, &config->functions, list) { in config_buf()
195 descriptors = f->hs_descriptors; in config_buf()
197 descriptors = f->descriptors; in config_buf()
204 len -= status; in config_buf()
208 len = next - buf; in config_buf()
209 c->wTotalLength = cpu_to_le16(len); in config_buf()
216 struct usb_gadget *gadget = cdev->gadget; in config_desc()
222 if (gadget->speed == USB_SPEED_HIGH) in config_desc()
231 list_for_each_entry(c, &cdev->configs, list) { in config_desc()
233 if (!c->highspeed) in config_desc()
236 if (!c->fullspeed) in config_desc()
240 return config_buf(c, speed, cdev->req->buf, type); in config_desc()
241 w_value--; in config_desc()
243 return -EINVAL; in config_desc()
248 struct usb_gadget *gadget = cdev->gadget; in count_configs()
254 if (gadget->speed == USB_SPEED_HIGH) in count_configs()
259 list_for_each_entry(c, &cdev->configs, list) { in count_configs()
262 if (!c->highspeed) in count_configs()
265 if (!c->fullspeed) in count_configs()
275 struct usb_qualifier_descriptor *qual = cdev->req->buf; in device_qual()
277 qual->bLength = sizeof(*qual); in device_qual()
278 qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER; in device_qual()
280 qual->bcdUSB = cdev->desc.bcdUSB; in device_qual()
281 qual->bDeviceClass = cdev->desc.bDeviceClass; in device_qual()
282 qual->bDeviceSubClass = cdev->desc.bDeviceSubClass; in device_qual()
283 qual->bDeviceProtocol = cdev->desc.bDeviceProtocol; in device_qual()
285 qual->bMaxPacketSize0 = cdev->gadget->ep0->maxpacket; in device_qual()
286 qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER); in device_qual()
287 qual->bRESERVED = 0; in device_qual()
296 list_for_each_entry(f, &cdev->config->functions, list) { in reset_config()
297 if (f->disable) in reset_config()
298 f->disable(f); in reset_config()
300 bitmap_zero(f->endpoints, 32); in reset_config()
302 cdev->config = NULL; in reset_config()
308 struct usb_gadget *gadget = cdev->gadget; in set_config()
311 int result = -EINVAL; in set_config()
318 if (cdev->config) in set_config()
322 list_for_each_entry(c, &cdev->configs, list) { in set_config()
323 if (c->bConfigurationValue == number) { in set_config()
335 switch (gadget->speed) { in set_config()
350 }), number, c ? c->label : "unconfigured"); in set_config()
355 cdev->config = c; in set_config()
359 f = c->interface[tmp]; in set_config()
369 if (gadget->speed == USB_SPEED_HIGH) in set_config()
370 descriptors = f->hs_descriptors; in set_config()
372 descriptors = f->descriptors; in set_config()
375 if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT) in set_config()
379 addr = ((ep->bEndpointAddress & 0x80) >> 3) in set_config()
380 | (ep->bEndpointAddress & 0x0f); in set_config()
381 generic_set_bit(addr, f->endpoints); in set_config()
384 result = f->set_alt(f, tmp, 0); in set_config()
386 debug("interface %d (%s/%p) alt 0 --> %d\n", in set_config()
387 tmp, f->name, f, result); in set_config()
395 power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW; in set_config()
402 * usb_add_config() - add a configuration to a device.
407 * One of the main tasks of a composite driver's bind() routine is to
412 * assigns global resources including string IDs, and per-configuration
418 int status = -EINVAL; in usb_add_config()
424 config->bConfigurationValue, in usb_add_config()
425 config->label, config); in usb_add_config()
427 if (!config->bConfigurationValue || !config->bind) in usb_add_config()
431 list_for_each_entry(c, &cdev->configs, list) { in usb_add_config()
432 if (c->bConfigurationValue == config->bConfigurationValue) { in usb_add_config()
433 status = -EBUSY; in usb_add_config()
438 config->cdev = cdev; in usb_add_config()
439 list_add_tail(&config->list, &cdev->configs); in usb_add_config()
441 INIT_LIST_HEAD(&config->functions); in usb_add_config()
442 config->next_interface_id = 0; in usb_add_config()
444 status = config->bind(config); in usb_add_config()
446 list_del(&config->list); in usb_add_config()
447 config->cdev = NULL; in usb_add_config()
450 config->bConfigurationValue, config, in usb_add_config()
451 config->highspeed ? " high" : "", in usb_add_config()
452 config->fullspeed in usb_add_config()
453 ? (gadget_is_dualspeed(cdev->gadget) in usb_add_config()
459 f = config->interface[i]; in usb_add_config()
463 __func__, i, f->name, f); in usb_add_config()
467 usb_ep_autoconfig_reset(cdev->gadget); in usb_add_config()
471 debug("added config '%s'/%u --> %d\n", config->label, in usb_add_config()
472 config->bConfigurationValue, status); in usb_add_config()
477 * We support strings in multiple languages ... string descriptor zero
491 language = cpu_to_le16(s->language); in collect_langs()
514 if (s->language != language) in lookup_string()
520 return -EINVAL; in lookup_string()
541 s->bDescriptorType = USB_DT_STRING; in get_string()
543 sp = composite->strings; in get_string()
545 collect_langs(sp, s->wData); in get_string()
547 list_for_each_entry(c, &cdev->configs, list) { in get_string()
548 sp = c->strings; in get_string()
550 collect_langs(sp, s->wData); in get_string()
552 list_for_each_entry(f, &c->functions, list) { in get_string()
553 sp = f->strings; in get_string()
555 collect_langs(sp, s->wData); in get_string()
559 for (len = 0; len <= 126 && s->wData[len]; len++) in get_string()
562 return -EINVAL; in get_string()
564 s->bLength = 2 * (len + 1); in get_string()
565 return s->bLength; in get_string()
570 * are device-scoped, so we look up each string table we're told in get_string()
571 * about. These lookups are infrequent; simpler-is-better here. in get_string()
573 if (composite->strings) { in get_string()
574 len = lookup_string(composite->strings, buf, language, id); in get_string()
578 list_for_each_entry(c, &cdev->configs, list) { in get_string()
579 if (c->strings) { in get_string()
580 len = lookup_string(c->strings, buf, language, id); in get_string()
584 list_for_each_entry(f, &c->functions, list) { in get_string()
585 if (!f->strings) in get_string()
587 len = lookup_string(f->strings, buf, language, id); in get_string()
592 return -EINVAL; in get_string()
596 * usb_string_id() - allocate an unused string ID
602 * then store that ID in the appropriate descriptors and string table.
611 if (cdev->next_string_id < 254) { in usb_string_id()
615 * 255 reserved as well? -- mina86 in usb_string_id()
617 cdev->next_string_id++; in usb_string_id()
618 return cdev->next_string_id; in usb_string_id()
620 return -ENODEV; in usb_string_id()
624 * usb_string_ids() - allocate unused string IDs in batch
641 u8 next = cdev->next_string_id; in usb_string_ids_tab()
643 for (; str->s; ++str) { in usb_string_ids_tab()
645 return -ENODEV; in usb_string_ids_tab()
646 str->id = ++next; in usb_string_ids_tab()
649 cdev->next_string_id = next; in usb_string_ids_tab()
655 * usb_string_ids_n() - allocate unused string IDs in batch
660 * Returns the first requested ID. This ID and next @n-1 IDs are now
661 * valid IDs. At least provided that @n is non-zero because if it
666 * then store that ID in the appropriate descriptors and string table.
675 u8 next = c->next_string_id; in usb_string_ids_n()
678 return -ENODEV; in usb_string_ids_n()
680 c->next_string_id += n; in usb_string_ids_n()
686 if (req->status || req->actual != req->length) in composite_setup_complete()
687 debug("%s: setup complete --> %d, %d/%d\n", __func__, in composite_setup_complete()
688 req->status, req->actual, req->length); in composite_setup_complete()
693 * not handled lower down, in hardware or the hardware driver(like
696 * the work is in config and function specific setup.
701 u16 w_length = le16_to_cpu(ctrl->wLength); in composite_setup()
702 u16 w_index = le16_to_cpu(ctrl->wIndex); in composite_setup()
703 u16 w_value = le16_to_cpu(ctrl->wValue); in composite_setup()
706 int value = -EOPNOTSUPP; in composite_setup()
707 struct usb_request *req = cdev->req; in composite_setup()
714 * partial re-init of the response message; the function or the in composite_setup()
715 * gadget might need to intercept e.g. a control-OUT completion in composite_setup()
718 req->zero = 0; in composite_setup()
719 req->complete = composite_setup_complete; in composite_setup()
720 req->length = USB_BUFSIZ; in composite_setup()
721 gadget->ep0->driver_data = cdev; in composite_setup()
722 standard = (ctrl->bRequestType & USB_TYPE_MASK) in composite_setup()
727 switch (ctrl->bRequest) { in composite_setup()
731 if (ctrl->bRequestType != USB_DIR_IN) in composite_setup()
736 cdev->desc.bNumConfigurations = in composite_setup()
742 * exponent of 2. So, 9(2^9=512) should be filled in in composite_setup()
746 if (cdev->gadget->speed == USB_SPEED_SUPER) { in composite_setup()
747 cdev->desc.bMaxPacketSize0 = 9; in composite_setup()
748 cdev->desc.bcdUSB = cpu_to_le16(0x0300); in composite_setup()
750 cdev->desc.bMaxPacketSize0 = in composite_setup()
751 cdev->gadget->ep0->maxpacket; in composite_setup()
753 value = min(w_length, (u16) sizeof cdev->desc); in composite_setup()
754 memcpy(req->buf, &cdev->desc, value); in composite_setup()
773 value = get_string(cdev, req->buf, in composite_setup()
793 if (ctrl->bRequestType != 0) in composite_setup()
796 if (gadget->a_hnp_support) in composite_setup()
798 else if (gadget->a_alt_hnp_support) in composite_setup()
807 if (ctrl->bRequestType != USB_DIR_IN) in composite_setup()
809 if (cdev->config) in composite_setup()
810 *(u8 *)req->buf = cdev->config->bConfigurationValue; in composite_setup()
812 *(u8 *)req->buf = 0; in composite_setup()
821 if (ctrl->bRequestType != USB_RECIP_INTERFACE) in composite_setup()
823 if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) in composite_setup()
825 f = cdev->config->interface[intf]; in composite_setup()
828 if (w_value && !f->set_alt) in composite_setup()
830 value = f->set_alt(f, w_index, w_value); in composite_setup()
833 if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) in composite_setup()
835 if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) in composite_setup()
837 f = cdev->config->interface[intf]; in composite_setup()
841 value = f->get_alt ? f->get_alt(f, w_index) : 0; in composite_setup()
844 *((u8 *)req->buf) = value; in composite_setup()
849 debug("non-core control req%02x.%02x v%04x i%04x l%d\n", in composite_setup()
850 ctrl->bRequestType, ctrl->bRequest, in composite_setup()
853 if (!cdev->config) in composite_setup()
861 switch (ctrl->bRequestType & USB_RECIP_MASK) { in composite_setup()
863 f = cdev->config->interface[intf]; in composite_setup()
868 list_for_each_entry(f, &cdev->config->functions, list) { in composite_setup()
869 if (test_bit(endp, f->endpoints)) in composite_setup()
872 if (&f->list == &cdev->config->functions) in composite_setup()
876 * dfu-util (version 0.5) sets bmRequestType.Receipent = Device in composite_setup()
877 * for non-standard request (w_value = 0x21, in composite_setup()
878 * bRequest = GET_DESCRIPTOR in this case). in composite_setup()
883 * In the below code it is checked if only one interface is in composite_setup()
885 * function's setup (f->setup) is called to handle this in composite_setup()
886 * special non-standard request. in composite_setup()
889 debug("cdev->config->next_interface_id: %d intf: %d\n", in composite_setup()
890 cdev->config->next_interface_id, intf); in composite_setup()
891 if (cdev->config->next_interface_id == 1) in composite_setup()
892 f = cdev->config->interface[intf]; in composite_setup()
896 if (f && f->setup) in composite_setup()
897 value = f->setup(f, ctrl); in composite_setup()
899 c = cdev->config; in composite_setup()
900 if (c->setup) in composite_setup()
901 value = c->setup(c, ctrl); in composite_setup()
909 req->length = value; in composite_setup()
910 req->zero = value < w_length; in composite_setup()
911 value = usb_ep_queue(gadget->ep0, req, GFP_KERNEL); in composite_setup()
913 debug("ep_queue --> %d\n", value); in composite_setup()
914 req->status = 0; in composite_setup()
915 composite_setup_complete(gadget->ep0, req); in composite_setup()
928 if (cdev->config) in composite_disconnect()
930 if (composite->disconnect) in composite_disconnect()
931 composite->disconnect(cdev); in composite_disconnect()
944 * state protected by cdev->lock. in composite_unbind()
946 BUG_ON(cdev->config); in composite_unbind()
948 while (!list_empty(&cdev->configs)) { in composite_unbind()
949 c = list_first_entry(&cdev->configs, in composite_unbind()
951 while (!list_empty(&c->functions)) { in composite_unbind()
952 f = list_first_entry(&c->functions, in composite_unbind()
954 list_del(&f->list); in composite_unbind()
955 if (f->unbind) { in composite_unbind()
957 f->name, f); in composite_unbind()
958 f->unbind(c, f); in composite_unbind()
961 list_del(&c->list); in composite_unbind()
962 if (c->unbind) { in composite_unbind()
963 debug("unbind config '%s'/%p\n", c->label, c); in composite_unbind()
964 c->unbind(c); in composite_unbind()
968 if (composite->unbind) in composite_unbind()
969 composite->unbind(cdev); in composite_unbind()
971 if (cdev->req) { in composite_unbind()
972 kfree(cdev->req->buf); in composite_unbind()
973 usb_ep_free_request(gadget->ep0, cdev->req); in composite_unbind()
978 composite = NULL; in composite_unbind()
983 int status = -ENOMEM; in composite_bind()
990 cdev->gadget = gadget; in composite_bind()
992 INIT_LIST_HEAD(&cdev->configs); in composite_bind()
995 cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); in composite_bind()
996 if (!cdev->req) in composite_bind()
998 cdev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, USB_BUFSIZ); in composite_bind()
999 if (!cdev->req->buf) in composite_bind()
1001 cdev->req->complete = composite_setup_complete; in composite_bind()
1002 gadget->ep0->driver_data = cdev; in composite_bind()
1004 cdev->bufsiz = USB_BUFSIZ; in composite_bind()
1005 cdev->driver = composite; in composite_bind()
1008 usb_ep_autoconfig_reset(cdev->gadget); in composite_bind()
1010 status = composite->bind(cdev); in composite_bind()
1014 memcpy(&cdev->desc, composite->dev, in composite_bind()
1016 cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; in composite_bind()
1018 debug("%s: ready\n", composite->name); in composite_bind()
1033 if (cdev->config) { in composite_suspend()
1034 list_for_each_entry(f, &cdev->config->functions, list) { in composite_suspend()
1035 if (f->suspend) in composite_suspend()
1036 f->suspend(f); in composite_suspend()
1039 if (composite->suspend) in composite_suspend()
1040 composite->suspend(cdev); in composite_suspend()
1042 cdev->suspended = 1; in composite_suspend()
1052 if (composite->resume) in composite_resume()
1053 composite->resume(cdev); in composite_resume()
1054 if (cdev->config) { in composite_resume()
1055 list_for_each_entry(f, &cdev->config->functions, list) { in composite_resume()
1056 if (f->resume) in composite_resume()
1057 f->resume(f); in composite_resume()
1061 cdev->suspended = 0; in composite_resume()
1079 * usb_composite_register() - register a composite driver
1083 * This function is used to register drivers using the composite driver
1090 * while it was binding. That would usually be done in order to wait for
1097 if (!driver || !driver->dev || !driver->bind || composite) in usb_composite_register()
1098 return -EINVAL; in usb_composite_register()
1100 if (!driver->name) in usb_composite_register()
1101 driver->name = "composite"; in usb_composite_register()
1102 composite = driver; in usb_composite_register()
1106 composite = NULL; in usb_composite_register()
1112 * usb_composite_unregister() - unregister a composite driver
1115 * This function is used to unregister drivers using the composite
1120 if (composite != driver) in usb_composite_unregister()
1123 composite = NULL; in usb_composite_unregister()