aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_rndis.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_rndis.c')
-rw-r--r--drivers/usb/gadget/f_rndis.c101
1 files changed, 98 insertions, 3 deletions
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index b324efa07733..8f3eae90919f 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -95,10 +95,12 @@ static inline struct f_rndis *func_to_rndis(struct usb_function *f)
95/* peak (theoretical) bulk transfer rate in bits-per-second */ 95/* peak (theoretical) bulk transfer rate in bits-per-second */
96static unsigned int bitrate(struct usb_gadget *g) 96static unsigned int bitrate(struct usb_gadget *g)
97{ 97{
98 if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) 98 if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
99 return 13 * 1024 * 8 * 1000 * 8;
100 else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
99 return 13 * 512 * 8 * 1000 * 8; 101 return 13 * 512 * 8 * 1000 * 8;
100 else 102 else
101 return 19 * 64 * 1 * 1000 * 8; 103 return 19 * 64 * 1 * 1000 * 8;
102} 104}
103 105
104/*-------------------------------------------------------------------------*/ 106/*-------------------------------------------------------------------------*/
@@ -216,6 +218,7 @@ static struct usb_endpoint_descriptor fs_out_desc = {
216 218
217static struct usb_descriptor_header *eth_fs_function[] = { 219static struct usb_descriptor_header *eth_fs_function[] = {
218 (struct usb_descriptor_header *) &rndis_iad_descriptor, 220 (struct usb_descriptor_header *) &rndis_iad_descriptor,
221
219 /* control interface matches ACM, not Ethernet */ 222 /* control interface matches ACM, not Ethernet */
220 (struct usb_descriptor_header *) &rndis_control_intf, 223 (struct usb_descriptor_header *) &rndis_control_intf,
221 (struct usb_descriptor_header *) &header_desc, 224 (struct usb_descriptor_header *) &header_desc,
@@ -223,6 +226,7 @@ static struct usb_descriptor_header *eth_fs_function[] = {
223 (struct usb_descriptor_header *) &rndis_acm_descriptor, 226 (struct usb_descriptor_header *) &rndis_acm_descriptor,
224 (struct usb_descriptor_header *) &rndis_union_desc, 227 (struct usb_descriptor_header *) &rndis_union_desc,
225 (struct usb_descriptor_header *) &fs_notify_desc, 228 (struct usb_descriptor_header *) &fs_notify_desc,
229
226 /* data interface has no altsetting */ 230 /* data interface has no altsetting */
227 (struct usb_descriptor_header *) &rndis_data_intf, 231 (struct usb_descriptor_header *) &rndis_data_intf,
228 (struct usb_descriptor_header *) &fs_in_desc, 232 (struct usb_descriptor_header *) &fs_in_desc,
@@ -241,6 +245,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {
241 .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), 245 .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
242 .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, 246 .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
243}; 247};
248
244static struct usb_endpoint_descriptor hs_in_desc = { 249static struct usb_endpoint_descriptor hs_in_desc = {
245 .bLength = USB_DT_ENDPOINT_SIZE, 250 .bLength = USB_DT_ENDPOINT_SIZE,
246 .bDescriptorType = USB_DT_ENDPOINT, 251 .bDescriptorType = USB_DT_ENDPOINT,
@@ -261,6 +266,7 @@ static struct usb_endpoint_descriptor hs_out_desc = {
261 266
262static struct usb_descriptor_header *eth_hs_function[] = { 267static struct usb_descriptor_header *eth_hs_function[] = {
263 (struct usb_descriptor_header *) &rndis_iad_descriptor, 268 (struct usb_descriptor_header *) &rndis_iad_descriptor,
269
264 /* control interface matches ACM, not Ethernet */ 270 /* control interface matches ACM, not Ethernet */
265 (struct usb_descriptor_header *) &rndis_control_intf, 271 (struct usb_descriptor_header *) &rndis_control_intf,
266 (struct usb_descriptor_header *) &header_desc, 272 (struct usb_descriptor_header *) &header_desc,
@@ -268,6 +274,7 @@ static struct usb_descriptor_header *eth_hs_function[] = {
268 (struct usb_descriptor_header *) &rndis_acm_descriptor, 274 (struct usb_descriptor_header *) &rndis_acm_descriptor,
269 (struct usb_descriptor_header *) &rndis_union_desc, 275 (struct usb_descriptor_header *) &rndis_union_desc,
270 (struct usb_descriptor_header *) &hs_notify_desc, 276 (struct usb_descriptor_header *) &hs_notify_desc,
277
271 /* data interface has no altsetting */ 278 /* data interface has no altsetting */
272 (struct usb_descriptor_header *) &rndis_data_intf, 279 (struct usb_descriptor_header *) &rndis_data_intf,
273 (struct usb_descriptor_header *) &hs_in_desc, 280 (struct usb_descriptor_header *) &hs_in_desc,
@@ -275,6 +282,76 @@ static struct usb_descriptor_header *eth_hs_function[] = {
275 NULL, 282 NULL,
276}; 283};
277 284
285/* super speed support: */
286
287static struct usb_endpoint_descriptor ss_notify_desc = {
288 .bLength = USB_DT_ENDPOINT_SIZE,
289 .bDescriptorType = USB_DT_ENDPOINT,
290
291 .bEndpointAddress = USB_DIR_IN,
292 .bmAttributes = USB_ENDPOINT_XFER_INT,
293 .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
294 .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
295};
296
297static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = {
298 .bLength = sizeof ss_intr_comp_desc,
299 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
300
301 /* the following 3 values can be tweaked if necessary */
302 /* .bMaxBurst = 0, */
303 /* .bmAttributes = 0, */
304 .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT),
305};
306
307static struct usb_endpoint_descriptor ss_in_desc = {
308 .bLength = USB_DT_ENDPOINT_SIZE,
309 .bDescriptorType = USB_DT_ENDPOINT,
310
311 .bEndpointAddress = USB_DIR_IN,
312 .bmAttributes = USB_ENDPOINT_XFER_BULK,
313 .wMaxPacketSize = cpu_to_le16(1024),
314};
315
316static struct usb_endpoint_descriptor ss_out_desc = {
317 .bLength = USB_DT_ENDPOINT_SIZE,
318 .bDescriptorType = USB_DT_ENDPOINT,
319
320 .bEndpointAddress = USB_DIR_OUT,
321 .bmAttributes = USB_ENDPOINT_XFER_BULK,
322 .wMaxPacketSize = cpu_to_le16(1024),
323};
324
325static struct usb_ss_ep_comp_descriptor ss_bulk_comp_desc = {
326 .bLength = sizeof ss_bulk_comp_desc,
327 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
328
329 /* the following 2 values can be tweaked if necessary */
330 /* .bMaxBurst = 0, */
331 /* .bmAttributes = 0, */
332};
333
334static struct usb_descriptor_header *eth_ss_function[] = {
335 (struct usb_descriptor_header *) &rndis_iad_descriptor,
336
337 /* control interface matches ACM, not Ethernet */
338 (struct usb_descriptor_header *) &rndis_control_intf,
339 (struct usb_descriptor_header *) &header_desc,
340 (struct usb_descriptor_header *) &call_mgmt_descriptor,
341 (struct usb_descriptor_header *) &rndis_acm_descriptor,
342 (struct usb_descriptor_header *) &rndis_union_desc,
343 (struct usb_descriptor_header *) &ss_notify_desc,
344 (struct usb_descriptor_header *) &ss_intr_comp_desc,
345
346 /* data interface has no altsetting */
347 (struct usb_descriptor_header *) &rndis_data_intf,
348 (struct usb_descriptor_header *) &ss_in_desc,
349 (struct usb_descriptor_header *) &ss_bulk_comp_desc,
350 (struct usb_descriptor_header *) &ss_out_desc,
351 (struct usb_descriptor_header *) &ss_bulk_comp_desc,
352 NULL,
353};
354
278/* string descriptors: */ 355/* string descriptors: */
279 356
280static struct usb_string rndis_string_defs[] = { 357static struct usb_string rndis_string_defs[] = {
@@ -670,11 +747,24 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
670 747
671 /* copy descriptors, and track endpoint copies */ 748 /* copy descriptors, and track endpoint copies */
672 f->hs_descriptors = usb_copy_descriptors(eth_hs_function); 749 f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
673
674 if (!f->hs_descriptors) 750 if (!f->hs_descriptors)
675 goto fail; 751 goto fail;
676 } 752 }
677 753
754 if (gadget_is_superspeed(c->cdev->gadget)) {
755 ss_in_desc.bEndpointAddress =
756 fs_in_desc.bEndpointAddress;
757 ss_out_desc.bEndpointAddress =
758 fs_out_desc.bEndpointAddress;
759 ss_notify_desc.bEndpointAddress =
760 fs_notify_desc.bEndpointAddress;
761
762 /* copy descriptors, and track endpoint copies */
763 f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
764 if (!f->ss_descriptors)
765 goto fail;
766 }
767
678 rndis->port.open = rndis_open; 768 rndis->port.open = rndis_open;
679 rndis->port.close = rndis_close; 769 rndis->port.close = rndis_close;
680 770
@@ -699,12 +789,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
699 */ 789 */
700 790
701 DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n", 791 DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
792 gadget_is_superspeed(c->cdev->gadget) ? "super" :
702 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 793 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
703 rndis->port.in_ep->name, rndis->port.out_ep->name, 794 rndis->port.in_ep->name, rndis->port.out_ep->name,
704 rndis->notify->name); 795 rndis->notify->name);
705 return 0; 796 return 0;
706 797
707fail: 798fail:
799 if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors)
800 usb_free_descriptors(f->ss_descriptors);
708 if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors) 801 if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
709 usb_free_descriptors(f->hs_descriptors); 802 usb_free_descriptors(f->hs_descriptors);
710 if (f->descriptors) 803 if (f->descriptors)
@@ -736,6 +829,8 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
736 rndis_deregister(rndis->config); 829 rndis_deregister(rndis->config);
737 rndis_exit(); 830 rndis_exit();
738 831
832 if (gadget_is_superspeed(c->cdev->gadget))
833 usb_free_descriptors(f->ss_descriptors);
739 if (gadget_is_dualspeed(c->cdev->gadget)) 834 if (gadget_is_dualspeed(c->cdev->gadget))
740 usb_free_descriptors(f->hs_descriptors); 835 usb_free_descriptors(f->hs_descriptors);
741 usb_free_descriptors(f->descriptors); 836 usb_free_descriptors(f->descriptors);