12731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 22731b9a8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2003 32731b9a8SJean-Christophe PLAGNIOL-VILLARD * Gerry Hamel, geh@ti.com, Texas Instruments 42731b9a8SJean-Christophe PLAGNIOL-VILLARD * 52731b9a8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2006 62731b9a8SJean-Christophe PLAGNIOL-VILLARD * Bryan O'Donoghue, deckard@CodeHermit.ie 72731b9a8SJean-Christophe PLAGNIOL-VILLARD * 82731b9a8SJean-Christophe PLAGNIOL-VILLARD * Based on 92731b9a8SJean-Christophe PLAGNIOL-VILLARD * linux/drivers/usbd/ep0.c 102731b9a8SJean-Christophe PLAGNIOL-VILLARD * 112731b9a8SJean-Christophe PLAGNIOL-VILLARD * Copyright (c) 2000, 2001, 2002 Lineo 122731b9a8SJean-Christophe PLAGNIOL-VILLARD * Copyright (c) 2001 Hewlett Packard 132731b9a8SJean-Christophe PLAGNIOL-VILLARD * 142731b9a8SJean-Christophe PLAGNIOL-VILLARD * By: 152731b9a8SJean-Christophe PLAGNIOL-VILLARD * Stuart Lynne <sl@lineo.com>, 162731b9a8SJean-Christophe PLAGNIOL-VILLARD * Tom Rushworth <tbr@lineo.com>, 172731b9a8SJean-Christophe PLAGNIOL-VILLARD * Bruce Balden <balden@lineo.com> 182731b9a8SJean-Christophe PLAGNIOL-VILLARD * 191a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 202731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 212731b9a8SJean-Christophe PLAGNIOL-VILLARD 222731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 232731b9a8SJean-Christophe PLAGNIOL-VILLARD * This is the builtin ep0 control function. It implements all required functionality 242731b9a8SJean-Christophe PLAGNIOL-VILLARD * for responding to control requests (SETUP packets). 252731b9a8SJean-Christophe PLAGNIOL-VILLARD * 262731b9a8SJean-Christophe PLAGNIOL-VILLARD * XXX 272731b9a8SJean-Christophe PLAGNIOL-VILLARD * 282731b9a8SJean-Christophe PLAGNIOL-VILLARD * Currently we do not pass any SETUP packets (or other) to the configured 292731b9a8SJean-Christophe PLAGNIOL-VILLARD * function driver. This may need to change. 302731b9a8SJean-Christophe PLAGNIOL-VILLARD * 312731b9a8SJean-Christophe PLAGNIOL-VILLARD * XXX 322731b9a8SJean-Christophe PLAGNIOL-VILLARD * 332731b9a8SJean-Christophe PLAGNIOL-VILLARD * As alluded to above, a simple callback cdc_recv_setup has been implemented 342731b9a8SJean-Christophe PLAGNIOL-VILLARD * in the usb_device data structure to facilicate passing 352731b9a8SJean-Christophe PLAGNIOL-VILLARD * Common Device Class packets to a function driver. 362731b9a8SJean-Christophe PLAGNIOL-VILLARD * 372731b9a8SJean-Christophe PLAGNIOL-VILLARD * XXX 382731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 392731b9a8SJean-Christophe PLAGNIOL-VILLARD 402731b9a8SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 412731b9a8SJean-Christophe PLAGNIOL-VILLARD #include <usbdevice.h> 422731b9a8SJean-Christophe PLAGNIOL-VILLARD 432731b9a8SJean-Christophe PLAGNIOL-VILLARD #if 0 442731b9a8SJean-Christophe PLAGNIOL-VILLARD #define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args) 452731b9a8SJean-Christophe PLAGNIOL-VILLARD #else 462731b9a8SJean-Christophe PLAGNIOL-VILLARD #define dbg_ep0(lvl,fmt,args...) 472731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif 482731b9a8SJean-Christophe PLAGNIOL-VILLARD 492731b9a8SJean-Christophe PLAGNIOL-VILLARD /* EP0 Configuration Set ********************************************************************* */ 502731b9a8SJean-Christophe PLAGNIOL-VILLARD 512731b9a8SJean-Christophe PLAGNIOL-VILLARD 522731b9a8SJean-Christophe PLAGNIOL-VILLARD /** 532731b9a8SJean-Christophe PLAGNIOL-VILLARD * ep0_get_status - fill in URB data with appropriate status 542731b9a8SJean-Christophe PLAGNIOL-VILLARD * @device: 552731b9a8SJean-Christophe PLAGNIOL-VILLARD * @urb: 562731b9a8SJean-Christophe PLAGNIOL-VILLARD * @index: 572731b9a8SJean-Christophe PLAGNIOL-VILLARD * @requesttype: 582731b9a8SJean-Christophe PLAGNIOL-VILLARD * 592731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 602731b9a8SJean-Christophe PLAGNIOL-VILLARD static int ep0_get_status (struct usb_device_instance *device, 612731b9a8SJean-Christophe PLAGNIOL-VILLARD struct urb *urb, int index, int requesttype) 622731b9a8SJean-Christophe PLAGNIOL-VILLARD { 632731b9a8SJean-Christophe PLAGNIOL-VILLARD char *cp; 642731b9a8SJean-Christophe PLAGNIOL-VILLARD 652731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->actual_length = 2; 662731b9a8SJean-Christophe PLAGNIOL-VILLARD cp = (char*)urb->buffer; 672731b9a8SJean-Christophe PLAGNIOL-VILLARD cp[0] = cp[1] = 0; 682731b9a8SJean-Christophe PLAGNIOL-VILLARD 692731b9a8SJean-Christophe PLAGNIOL-VILLARD switch (requesttype) { 702731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_DEVICE: 712731b9a8SJean-Christophe PLAGNIOL-VILLARD cp[0] = USB_STATUS_SELFPOWERED; 722731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 732731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_INTERFACE: 742731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 752731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_ENDPOINT: 762731b9a8SJean-Christophe PLAGNIOL-VILLARD cp[0] = usbd_endpoint_halted (device, index); 772731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 782731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_OTHER: 792731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->actual_length = 0; 802731b9a8SJean-Christophe PLAGNIOL-VILLARD default: 812731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 822731b9a8SJean-Christophe PLAGNIOL-VILLARD } 832731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (2, "%02x %02x", cp[0], cp[1]); 842731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 852731b9a8SJean-Christophe PLAGNIOL-VILLARD } 862731b9a8SJean-Christophe PLAGNIOL-VILLARD 872731b9a8SJean-Christophe PLAGNIOL-VILLARD /** 882731b9a8SJean-Christophe PLAGNIOL-VILLARD * ep0_get_one 892731b9a8SJean-Christophe PLAGNIOL-VILLARD * @device: 902731b9a8SJean-Christophe PLAGNIOL-VILLARD * @urb: 912731b9a8SJean-Christophe PLAGNIOL-VILLARD * @result: 922731b9a8SJean-Christophe PLAGNIOL-VILLARD * 932731b9a8SJean-Christophe PLAGNIOL-VILLARD * Set a single byte value in the urb send buffer. Return non-zero to signal 942731b9a8SJean-Christophe PLAGNIOL-VILLARD * a request error. 952731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 962731b9a8SJean-Christophe PLAGNIOL-VILLARD static int ep0_get_one (struct usb_device_instance *device, struct urb *urb, 972731b9a8SJean-Christophe PLAGNIOL-VILLARD __u8 result) 982731b9a8SJean-Christophe PLAGNIOL-VILLARD { 992731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->actual_length = 1; /* XXX 2? */ 1002731b9a8SJean-Christophe PLAGNIOL-VILLARD ((char *) urb->buffer)[0] = result; 1012731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 1022731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1032731b9a8SJean-Christophe PLAGNIOL-VILLARD 1042731b9a8SJean-Christophe PLAGNIOL-VILLARD /** 1052731b9a8SJean-Christophe PLAGNIOL-VILLARD * copy_config 1062731b9a8SJean-Christophe PLAGNIOL-VILLARD * @urb: pointer to urb 1072731b9a8SJean-Christophe PLAGNIOL-VILLARD * @data: pointer to configuration data 1082731b9a8SJean-Christophe PLAGNIOL-VILLARD * @length: length of data 1092731b9a8SJean-Christophe PLAGNIOL-VILLARD * 1102731b9a8SJean-Christophe PLAGNIOL-VILLARD * Copy configuration data to urb transfer buffer if there is room for it. 1112731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 1122731b9a8SJean-Christophe PLAGNIOL-VILLARD void copy_config (struct urb *urb, void *data, int max_length, 1132731b9a8SJean-Christophe PLAGNIOL-VILLARD int max_buf) 1142731b9a8SJean-Christophe PLAGNIOL-VILLARD { 1152731b9a8SJean-Christophe PLAGNIOL-VILLARD int available; 1162731b9a8SJean-Christophe PLAGNIOL-VILLARD int length; 1172731b9a8SJean-Christophe PLAGNIOL-VILLARD 1182731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */ 1192731b9a8SJean-Christophe PLAGNIOL-VILLARD /* urb->actual_length, urb->buffer_length, max_buf, max_length, data); */ 1202731b9a8SJean-Christophe PLAGNIOL-VILLARD 1212731b9a8SJean-Christophe PLAGNIOL-VILLARD if (!data) { 1222731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "data is NULL"); 1232731b9a8SJean-Christophe PLAGNIOL-VILLARD return; 1242731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1252731b9a8SJean-Christophe PLAGNIOL-VILLARD length = max_length; 1262731b9a8SJean-Christophe PLAGNIOL-VILLARD 1272731b9a8SJean-Christophe PLAGNIOL-VILLARD if (length > max_length) { 1282731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "length: %d >= max_length: %d", length, 1292731b9a8SJean-Christophe PLAGNIOL-VILLARD max_length); 1302731b9a8SJean-Christophe PLAGNIOL-VILLARD return; 1312731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1322731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(1, " actual: %d buf: %d max_buf: %d max_length: %d length: %d", */ 1332731b9a8SJean-Christophe PLAGNIOL-VILLARD /* urb->actual_length, urb->buffer_length, max_buf, max_length, length); */ 1342731b9a8SJean-Christophe PLAGNIOL-VILLARD 1352731b9a8SJean-Christophe PLAGNIOL-VILLARD if ((available = 1362731b9a8SJean-Christophe PLAGNIOL-VILLARD /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) { 1372731b9a8SJean-Christophe PLAGNIOL-VILLARD return; 1382731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1392731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ 1402731b9a8SJean-Christophe PLAGNIOL-VILLARD /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ 1412731b9a8SJean-Christophe PLAGNIOL-VILLARD 1422731b9a8SJean-Christophe PLAGNIOL-VILLARD if (length > available) { 1432731b9a8SJean-Christophe PLAGNIOL-VILLARD length = available; 1442731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1452731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ 1462731b9a8SJean-Christophe PLAGNIOL-VILLARD /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ 1472731b9a8SJean-Christophe PLAGNIOL-VILLARD 1482731b9a8SJean-Christophe PLAGNIOL-VILLARD memcpy (urb->buffer + urb->actual_length, data, length); 1492731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->actual_length += length; 1502731b9a8SJean-Christophe PLAGNIOL-VILLARD 1512731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (3, 1522731b9a8SJean-Christophe PLAGNIOL-VILLARD "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d", 1532731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->actual_length, urb->buffer_length, max_buf, max_length, 1542731b9a8SJean-Christophe PLAGNIOL-VILLARD available); 1552731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1562731b9a8SJean-Christophe PLAGNIOL-VILLARD 1572731b9a8SJean-Christophe PLAGNIOL-VILLARD /** 1582731b9a8SJean-Christophe PLAGNIOL-VILLARD * ep0_get_descriptor 1592731b9a8SJean-Christophe PLAGNIOL-VILLARD * @device: 1602731b9a8SJean-Christophe PLAGNIOL-VILLARD * @urb: 1612731b9a8SJean-Christophe PLAGNIOL-VILLARD * @max: 1622731b9a8SJean-Christophe PLAGNIOL-VILLARD * @descriptor_type: 1632731b9a8SJean-Christophe PLAGNIOL-VILLARD * @index: 1642731b9a8SJean-Christophe PLAGNIOL-VILLARD * 1652731b9a8SJean-Christophe PLAGNIOL-VILLARD * Called by ep0_rx_process for a get descriptor device command. Determine what 1662731b9a8SJean-Christophe PLAGNIOL-VILLARD * descriptor is being requested, copy to send buffer. Return zero if ok to send, 1672731b9a8SJean-Christophe PLAGNIOL-VILLARD * return non-zero to signal a request error. 1682731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 1692731b9a8SJean-Christophe PLAGNIOL-VILLARD static int ep0_get_descriptor (struct usb_device_instance *device, 1702731b9a8SJean-Christophe PLAGNIOL-VILLARD struct urb *urb, int max, int descriptor_type, 1712731b9a8SJean-Christophe PLAGNIOL-VILLARD int index) 1722731b9a8SJean-Christophe PLAGNIOL-VILLARD { 1732731b9a8SJean-Christophe PLAGNIOL-VILLARD int port = 0; /* XXX compound device */ 1742731b9a8SJean-Christophe PLAGNIOL-VILLARD 1752731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */ 1762731b9a8SJean-Christophe PLAGNIOL-VILLARD 1772731b9a8SJean-Christophe PLAGNIOL-VILLARD if (!urb || !urb->buffer || !urb->buffer_length 1782731b9a8SJean-Christophe PLAGNIOL-VILLARD || (urb->buffer_length < 255)) { 1792731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (2, "invalid urb %p", urb); 1802731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1L; 1812731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1822731b9a8SJean-Christophe PLAGNIOL-VILLARD 1832731b9a8SJean-Christophe PLAGNIOL-VILLARD /* setup tx urb */ 1842731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->actual_length = 0; 1852731b9a8SJean-Christophe PLAGNIOL-VILLARD 1862731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type)); 1872731b9a8SJean-Christophe PLAGNIOL-VILLARD 1882731b9a8SJean-Christophe PLAGNIOL-VILLARD switch (descriptor_type) { 1892731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_DEVICE: 1902731b9a8SJean-Christophe PLAGNIOL-VILLARD { 1912731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device_descriptor *device_descriptor; 1922731b9a8SJean-Christophe PLAGNIOL-VILLARD if (! 1932731b9a8SJean-Christophe PLAGNIOL-VILLARD (device_descriptor = 1942731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_device_descriptor (device, port))) { 1952731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 1962731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1972731b9a8SJean-Christophe PLAGNIOL-VILLARD /* copy descriptor for this device */ 1982731b9a8SJean-Christophe PLAGNIOL-VILLARD copy_config (urb, device_descriptor, 1992731b9a8SJean-Christophe PLAGNIOL-VILLARD sizeof (struct usb_device_descriptor), 2002731b9a8SJean-Christophe PLAGNIOL-VILLARD max); 2012731b9a8SJean-Christophe PLAGNIOL-VILLARD 2022731b9a8SJean-Christophe PLAGNIOL-VILLARD /* correct the correct control endpoint 0 max packet size into the descriptor */ 2032731b9a8SJean-Christophe PLAGNIOL-VILLARD device_descriptor = 2042731b9a8SJean-Christophe PLAGNIOL-VILLARD (struct usb_device_descriptor *) urb->buffer; 2052731b9a8SJean-Christophe PLAGNIOL-VILLARD 2062731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2072731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length); 2082731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 2092731b9a8SJean-Christophe PLAGNIOL-VILLARD 2102731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_CONFIGURATION: 2112731b9a8SJean-Christophe PLAGNIOL-VILLARD { 2122731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_configuration_descriptor 2132731b9a8SJean-Christophe PLAGNIOL-VILLARD *configuration_descriptor; 2142731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device_descriptor *device_descriptor; 2152731b9a8SJean-Christophe PLAGNIOL-VILLARD if (! 2162731b9a8SJean-Christophe PLAGNIOL-VILLARD (device_descriptor = 2172731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_device_descriptor (device, port))) { 2182731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 2192731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2202731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */ 2212731b9a8SJean-Christophe PLAGNIOL-VILLARD if (index >= device_descriptor->bNumConfigurations) { 2222731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (0, "index too large: %d >= %d", index, 2232731b9a8SJean-Christophe PLAGNIOL-VILLARD device_descriptor-> 2242731b9a8SJean-Christophe PLAGNIOL-VILLARD bNumConfigurations); 2252731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 2262731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2272731b9a8SJean-Christophe PLAGNIOL-VILLARD 2282731b9a8SJean-Christophe PLAGNIOL-VILLARD if (! 2292731b9a8SJean-Christophe PLAGNIOL-VILLARD (configuration_descriptor = 2302731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_configuration_descriptor (device, 2312731b9a8SJean-Christophe PLAGNIOL-VILLARD port, 2322731b9a8SJean-Christophe PLAGNIOL-VILLARD index))) { 2332731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (0, 2342731b9a8SJean-Christophe PLAGNIOL-VILLARD "usbd_device_configuration_descriptor failed: %d", 2352731b9a8SJean-Christophe PLAGNIOL-VILLARD index); 2362731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 2372731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2382731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength)); 2392731b9a8SJean-Christophe PLAGNIOL-VILLARD copy_config (urb, configuration_descriptor, 2402731b9a8SJean-Christophe PLAGNIOL-VILLARD 2412731b9a8SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(configuration_descriptor->wTotalLength), 2422731b9a8SJean-Christophe PLAGNIOL-VILLARD max); 2432731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2442731b9a8SJean-Christophe PLAGNIOL-VILLARD 2452731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 2462731b9a8SJean-Christophe PLAGNIOL-VILLARD 2472731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_STRING: 2482731b9a8SJean-Christophe PLAGNIOL-VILLARD { 2492731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_string_descriptor *string_descriptor; 2502731b9a8SJean-Christophe PLAGNIOL-VILLARD if (!(string_descriptor = usbd_get_string (index))) { 2512731b9a8SJean-Christophe PLAGNIOL-VILLARD serial_printf("Invalid string index %d\n", index); 2522731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 2532731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2542731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength); 2552731b9a8SJean-Christophe PLAGNIOL-VILLARD copy_config (urb, string_descriptor, string_descriptor->bLength, max); 2562731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2572731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 2582731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_INTERFACE: 2592731b9a8SJean-Christophe PLAGNIOL-VILLARD serial_printf("USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n"); 2602731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 2612731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_ENDPOINT: 2622731b9a8SJean-Christophe PLAGNIOL-VILLARD serial_printf("USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n"); 2632731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 2642731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_HID: 2652731b9a8SJean-Christophe PLAGNIOL-VILLARD { 2662731b9a8SJean-Christophe PLAGNIOL-VILLARD serial_printf("USB_DESCRIPTOR_TYPE_HID - error not implemented\n"); 2672731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; /* unsupported at this time */ 2682731b9a8SJean-Christophe PLAGNIOL-VILLARD #if 0 2692731b9a8SJean-Christophe PLAGNIOL-VILLARD int bNumInterface = 2702731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (urb->device_request.wIndex); 2712731b9a8SJean-Christophe PLAGNIOL-VILLARD int bAlternateSetting = 0; 2722731b9a8SJean-Christophe PLAGNIOL-VILLARD int class = 0; 2732731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_class_descriptor *class_descriptor; 2742731b9a8SJean-Christophe PLAGNIOL-VILLARD 2752731b9a8SJean-Christophe PLAGNIOL-VILLARD if (!(class_descriptor = 2762731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_class_descriptor_index (device, 2772731b9a8SJean-Christophe PLAGNIOL-VILLARD port, 0, 2782731b9a8SJean-Christophe PLAGNIOL-VILLARD bNumInterface, 2792731b9a8SJean-Christophe PLAGNIOL-VILLARD bAlternateSetting, 2802731b9a8SJean-Christophe PLAGNIOL-VILLARD class)) 2812731b9a8SJean-Christophe PLAGNIOL-VILLARD || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) { 2822731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (3, "[%d] interface is not HID", 2832731b9a8SJean-Christophe PLAGNIOL-VILLARD bNumInterface); 2842731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 2852731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2862731b9a8SJean-Christophe PLAGNIOL-VILLARD /* copy descriptor for this class */ 2872731b9a8SJean-Christophe PLAGNIOL-VILLARD copy_config (urb, class_descriptor, 2882731b9a8SJean-Christophe PLAGNIOL-VILLARD class_descriptor->descriptor.hid.bLength, 2892731b9a8SJean-Christophe PLAGNIOL-VILLARD max); 2902731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif 2912731b9a8SJean-Christophe PLAGNIOL-VILLARD } 2922731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 2932731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_REPORT: 2942731b9a8SJean-Christophe PLAGNIOL-VILLARD { 2952731b9a8SJean-Christophe PLAGNIOL-VILLARD serial_printf("USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n"); 2962731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; /* unsupported at this time */ 2972731b9a8SJean-Christophe PLAGNIOL-VILLARD #if 0 2982731b9a8SJean-Christophe PLAGNIOL-VILLARD int bNumInterface = 2992731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (urb->device_request.wIndex); 3002731b9a8SJean-Christophe PLAGNIOL-VILLARD int bAlternateSetting = 0; 3012731b9a8SJean-Christophe PLAGNIOL-VILLARD int class = 0; 3022731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_class_report_descriptor *report_descriptor; 3032731b9a8SJean-Christophe PLAGNIOL-VILLARD 3042731b9a8SJean-Christophe PLAGNIOL-VILLARD if (!(report_descriptor = 3052731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_class_report_descriptor_index 3062731b9a8SJean-Christophe PLAGNIOL-VILLARD (device, port, 0, bNumInterface, 3072731b9a8SJean-Christophe PLAGNIOL-VILLARD bAlternateSetting, class)) 3082731b9a8SJean-Christophe PLAGNIOL-VILLARD || report_descriptor->bDescriptorType != 3092731b9a8SJean-Christophe PLAGNIOL-VILLARD USB_DT_REPORT) { 3102731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (3, "[%d] descriptor is not REPORT", 3112731b9a8SJean-Christophe PLAGNIOL-VILLARD bNumInterface); 3122731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 3132731b9a8SJean-Christophe PLAGNIOL-VILLARD } 3142731b9a8SJean-Christophe PLAGNIOL-VILLARD /* copy report descriptor for this class */ 3152731b9a8SJean-Christophe PLAGNIOL-VILLARD /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */ 3162731b9a8SJean-Christophe PLAGNIOL-VILLARD if (max - urb->actual_length > 0) { 3172731b9a8SJean-Christophe PLAGNIOL-VILLARD int length = 318*c79cba37SMasahiro Yamada min(report_descriptor->wLength, 3192731b9a8SJean-Christophe PLAGNIOL-VILLARD max - urb->actual_length); 3202731b9a8SJean-Christophe PLAGNIOL-VILLARD memcpy (urb->buffer + urb->actual_length, 3212731b9a8SJean-Christophe PLAGNIOL-VILLARD &report_descriptor->bData[0], length); 3222731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->actual_length += length; 3232731b9a8SJean-Christophe PLAGNIOL-VILLARD } 3242731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif 3252731b9a8SJean-Christophe PLAGNIOL-VILLARD } 3262731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 3272731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: 328f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS) 3292731b9a8SJean-Christophe PLAGNIOL-VILLARD { 330f9da0f89SVipin KUMAR struct usb_qualifier_descriptor *qualifier_descriptor = 331f9da0f89SVipin KUMAR device->qualifier_descriptor; 332f9da0f89SVipin KUMAR 333f9da0f89SVipin KUMAR if (!qualifier_descriptor) 3342731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 335f9da0f89SVipin KUMAR 336f9da0f89SVipin KUMAR /* copy descriptor for this device */ 337f9da0f89SVipin KUMAR copy_config(urb, qualifier_descriptor, 338f9da0f89SVipin KUMAR sizeof(struct usb_qualifier_descriptor), 339f9da0f89SVipin KUMAR max); 340f9da0f89SVipin KUMAR 3412731b9a8SJean-Christophe PLAGNIOL-VILLARD } 342f9da0f89SVipin KUMAR dbg_ep0(3, "copied qualifier descriptor, actual_length: 0x%x", 343f9da0f89SVipin KUMAR urb->actual_length); 344f9da0f89SVipin KUMAR #else 345f9da0f89SVipin KUMAR return -1; 346f9da0f89SVipin KUMAR #endif 347f9da0f89SVipin KUMAR break; 348f9da0f89SVipin KUMAR 3492731b9a8SJean-Christophe PLAGNIOL-VILLARD default: 3502731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 3512731b9a8SJean-Christophe PLAGNIOL-VILLARD } 3522731b9a8SJean-Christophe PLAGNIOL-VILLARD 3532731b9a8SJean-Christophe PLAGNIOL-VILLARD 3542731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d", 3552731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->buffer, urb->buffer_length, urb->actual_length, 3562731b9a8SJean-Christophe PLAGNIOL-VILLARD device->bus->endpoint_array[0].tx_packetSize); 3572731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 3582731b9a8SJean-Christophe PLAGNIOL-VILLARD if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) { 3592731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0(0, "adding null byte"); 3602731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->buffer[urb->actual_length++] = 0; 3612731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d", 3622731b9a8SJean-Christophe PLAGNIOL-VILLARD urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize); 3632731b9a8SJean-Christophe PLAGNIOL-VILLARD } 3642731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 3652731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 3662731b9a8SJean-Christophe PLAGNIOL-VILLARD 3672731b9a8SJean-Christophe PLAGNIOL-VILLARD } 3682731b9a8SJean-Christophe PLAGNIOL-VILLARD 3692731b9a8SJean-Christophe PLAGNIOL-VILLARD /** 3702731b9a8SJean-Christophe PLAGNIOL-VILLARD * ep0_recv_setup - called to indicate URB has been received 3712731b9a8SJean-Christophe PLAGNIOL-VILLARD * @urb: pointer to struct urb 3722731b9a8SJean-Christophe PLAGNIOL-VILLARD * 3732731b9a8SJean-Christophe PLAGNIOL-VILLARD * Check if this is a setup packet, process the device request, put results 3742731b9a8SJean-Christophe PLAGNIOL-VILLARD * back into the urb and return zero or non-zero to indicate success (DATA) 3752731b9a8SJean-Christophe PLAGNIOL-VILLARD * or failure (STALL). 3762731b9a8SJean-Christophe PLAGNIOL-VILLARD * 3772731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 3782731b9a8SJean-Christophe PLAGNIOL-VILLARD int ep0_recv_setup (struct urb *urb) 3792731b9a8SJean-Christophe PLAGNIOL-VILLARD { 3802731b9a8SJean-Christophe PLAGNIOL-VILLARD /*struct usb_device_request *request = urb->buffer; */ 3812731b9a8SJean-Christophe PLAGNIOL-VILLARD /*struct usb_device_instance *device = urb->device; */ 3822731b9a8SJean-Christophe PLAGNIOL-VILLARD 3832731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device_request *request; 3842731b9a8SJean-Christophe PLAGNIOL-VILLARD struct usb_device_instance *device; 3852731b9a8SJean-Christophe PLAGNIOL-VILLARD int address; 3862731b9a8SJean-Christophe PLAGNIOL-VILLARD 3872731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (0, "entering ep0_recv_setup()"); 3882731b9a8SJean-Christophe PLAGNIOL-VILLARD if (!urb || !urb->device) { 3892731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (3, "invalid URB %p", urb); 3902731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 3912731b9a8SJean-Christophe PLAGNIOL-VILLARD } 3922731b9a8SJean-Christophe PLAGNIOL-VILLARD 3932731b9a8SJean-Christophe PLAGNIOL-VILLARD request = &urb->device_request; 3942731b9a8SJean-Christophe PLAGNIOL-VILLARD device = urb->device; 3952731b9a8SJean-Christophe PLAGNIOL-VILLARD 3962731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (3, "urb: %p device: %p", urb, urb->device); 3972731b9a8SJean-Christophe PLAGNIOL-VILLARD 3982731b9a8SJean-Christophe PLAGNIOL-VILLARD 3992731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(2, "- - - - - - - - - -"); */ 4002731b9a8SJean-Christophe PLAGNIOL-VILLARD 4012731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (2, 4022731b9a8SJean-Christophe PLAGNIOL-VILLARD "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s", 4032731b9a8SJean-Christophe PLAGNIOL-VILLARD request->bmRequestType, request->bRequest, 4042731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex), 4052731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (request->wLength), 4062731b9a8SJean-Christophe PLAGNIOL-VILLARD USBD_DEVICE_REQUESTS (request->bRequest)); 4072731b9a8SJean-Christophe PLAGNIOL-VILLARD 4082731b9a8SJean-Christophe PLAGNIOL-VILLARD /* handle USB Standard Request (c.f. USB Spec table 9-2) */ 4092731b9a8SJean-Christophe PLAGNIOL-VILLARD if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) { 4102731b9a8SJean-Christophe PLAGNIOL-VILLARD if(device->device_state <= STATE_CONFIGURED){ 4112731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Attempt to handle a CDC specific request if we are 4122731b9a8SJean-Christophe PLAGNIOL-VILLARD * in the configured state. 4132731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 4142731b9a8SJean-Christophe PLAGNIOL-VILLARD return device->cdc_recv_setup(request,urb); 4152731b9a8SJean-Christophe PLAGNIOL-VILLARD } 4162731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "non standard request: %x", 4172731b9a8SJean-Christophe PLAGNIOL-VILLARD request->bmRequestType & USB_REQ_TYPE_MASK); 4182731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; /* Stall here */ 4192731b9a8SJean-Christophe PLAGNIOL-VILLARD } 4202731b9a8SJean-Christophe PLAGNIOL-VILLARD 4212731b9a8SJean-Christophe PLAGNIOL-VILLARD switch (device->device_state) { 4222731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_CREATED: 4232731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_ATTACHED: 4242731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_POWERED: 4252731b9a8SJean-Christophe PLAGNIOL-VILLARD /* It actually is important to allow requests in these states, 4262731b9a8SJean-Christophe PLAGNIOL-VILLARD * Windows will request descriptors before assigning an 4272731b9a8SJean-Christophe PLAGNIOL-VILLARD * address to the client. 4282731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 4292731b9a8SJean-Christophe PLAGNIOL-VILLARD 4302731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0 (1, "request %s not allowed in this state: %s", */ 4312731b9a8SJean-Christophe PLAGNIOL-VILLARD /* USBD_DEVICE_REQUESTS(request->bRequest), */ 4322731b9a8SJean-Christophe PLAGNIOL-VILLARD /* usbd_device_states[device->device_state]); */ 4332731b9a8SJean-Christophe PLAGNIOL-VILLARD /*return -1; */ 4342731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 4352731b9a8SJean-Christophe PLAGNIOL-VILLARD 4362731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_INIT: 4372731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_DEFAULT: 4382731b9a8SJean-Christophe PLAGNIOL-VILLARD switch (request->bRequest) { 4392731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_STATUS: 4402731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_INTERFACE: 4412731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ 4422731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_CLEAR_FEATURE: 4432731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_FEATURE: 4442731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_DESCRIPTOR: 4452731b9a8SJean-Christophe PLAGNIOL-VILLARD /* case USB_REQ_SET_CONFIGURATION: */ 4462731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_INTERFACE: 4472731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, 4482731b9a8SJean-Christophe PLAGNIOL-VILLARD "request %s not allowed in DEFAULT state: %s", 4492731b9a8SJean-Christophe PLAGNIOL-VILLARD USBD_DEVICE_REQUESTS (request->bRequest), 4502731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_states[device->device_state]); 4512731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 4522731b9a8SJean-Christophe PLAGNIOL-VILLARD 4532731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_CONFIGURATION: 4542731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_ADDRESS: 4552731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_DESCRIPTOR: 4562731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_CONFIGURATION: 4572731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 4582731b9a8SJean-Christophe PLAGNIOL-VILLARD } 4592731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_ADDRESSED: 4602731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_CONFIGURED: 4612731b9a8SJean-Christophe PLAGNIOL-VILLARD break; 4622731b9a8SJean-Christophe PLAGNIOL-VILLARD case STATE_UNKNOWN: 4632731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s", 4642731b9a8SJean-Christophe PLAGNIOL-VILLARD USBD_DEVICE_REQUESTS (request->bRequest), 4652731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_states[device->device_state]); 4662731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 4672731b9a8SJean-Christophe PLAGNIOL-VILLARD } 4682731b9a8SJean-Christophe PLAGNIOL-VILLARD 4692731b9a8SJean-Christophe PLAGNIOL-VILLARD /* handle all requests that return data (direction bit set on bm RequestType) */ 4702731b9a8SJean-Christophe PLAGNIOL-VILLARD if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) { 4712731b9a8SJean-Christophe PLAGNIOL-VILLARD 4722731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (3, "Device-to-Host"); 4732731b9a8SJean-Christophe PLAGNIOL-VILLARD 4742731b9a8SJean-Christophe PLAGNIOL-VILLARD switch (request->bRequest) { 4752731b9a8SJean-Christophe PLAGNIOL-VILLARD 4762731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_STATUS: 4772731b9a8SJean-Christophe PLAGNIOL-VILLARD return ep0_get_status (device, urb, request->wIndex, 4782731b9a8SJean-Christophe PLAGNIOL-VILLARD request->bmRequestType & 4792731b9a8SJean-Christophe PLAGNIOL-VILLARD USB_REQ_RECIPIENT_MASK); 4802731b9a8SJean-Christophe PLAGNIOL-VILLARD 4812731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_DESCRIPTOR: 4822731b9a8SJean-Christophe PLAGNIOL-VILLARD return ep0_get_descriptor (device, urb, 4832731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (request->wLength), 4842731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (request->wValue) >> 8, 4852731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (request->wValue) & 0xff); 4862731b9a8SJean-Christophe PLAGNIOL-VILLARD 4872731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_CONFIGURATION: 4882731b9a8SJean-Christophe PLAGNIOL-VILLARD serial_printf("get config %d\n", device->configuration); 4892731b9a8SJean-Christophe PLAGNIOL-VILLARD return ep0_get_one (device, urb, 4902731b9a8SJean-Christophe PLAGNIOL-VILLARD device->configuration); 4912731b9a8SJean-Christophe PLAGNIOL-VILLARD 4922731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_INTERFACE: 4932731b9a8SJean-Christophe PLAGNIOL-VILLARD return ep0_get_one (device, urb, device->alternate); 4942731b9a8SJean-Christophe PLAGNIOL-VILLARD 4952731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ 4962731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 4972731b9a8SJean-Christophe PLAGNIOL-VILLARD 4982731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_CLEAR_FEATURE: 4992731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_FEATURE: 5002731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_ADDRESS: 5012731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_DESCRIPTOR: 5022731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_CONFIGURATION: 5032731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_INTERFACE: 5042731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5052731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5062731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5072731b9a8SJean-Christophe PLAGNIOL-VILLARD /* handle the requests that do not return data */ 5082731b9a8SJean-Christophe PLAGNIOL-VILLARD else { 5092731b9a8SJean-Christophe PLAGNIOL-VILLARD 5102731b9a8SJean-Christophe PLAGNIOL-VILLARD 5112731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(3, "Host-to-Device"); */ 5122731b9a8SJean-Christophe PLAGNIOL-VILLARD switch (request->bRequest) { 5132731b9a8SJean-Christophe PLAGNIOL-VILLARD 5142731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_CLEAR_FEATURE: 5152731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_FEATURE: 5162731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (0, "Host-to-Device"); 5172731b9a8SJean-Christophe PLAGNIOL-VILLARD switch (request-> 5182731b9a8SJean-Christophe PLAGNIOL-VILLARD bmRequestType & USB_REQ_RECIPIENT_MASK) { 5192731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_DEVICE: 5202731b9a8SJean-Christophe PLAGNIOL-VILLARD /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */ 5212731b9a8SJean-Christophe PLAGNIOL-VILLARD /* XXX fall through for now as we do not support either */ 5222731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_INTERFACE: 5232731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_OTHER: 5242731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (0, "request %s not", 5252731b9a8SJean-Christophe PLAGNIOL-VILLARD USBD_DEVICE_REQUESTS (request->bRequest)); 5262731b9a8SJean-Christophe PLAGNIOL-VILLARD default: 5272731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5282731b9a8SJean-Christophe PLAGNIOL-VILLARD 5292731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_RECIPIENT_ENDPOINT: 5302731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue)); 5312731b9a8SJean-Christophe PLAGNIOL-VILLARD if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) { 5322731b9a8SJean-Christophe PLAGNIOL-VILLARD /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */ 5332731b9a8SJean-Christophe PLAGNIOL-VILLARD /* request->bRequest == USB_REQ_SET_FEATURE); */ 5342731b9a8SJean-Christophe PLAGNIOL-VILLARD /* NEED TO IMPLEMENT THIS!!! */ 5352731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5362731b9a8SJean-Christophe PLAGNIOL-VILLARD } else { 5372731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "request %s bad wValue: %04x", 5382731b9a8SJean-Christophe PLAGNIOL-VILLARD USBD_DEVICE_REQUESTS 5392731b9a8SJean-Christophe PLAGNIOL-VILLARD (request->bRequest), 5402731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (request->wValue)); 5412731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5422731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5432731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5442731b9a8SJean-Christophe PLAGNIOL-VILLARD 5452731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_ADDRESS: 5462731b9a8SJean-Christophe PLAGNIOL-VILLARD /* check if this is a re-address, reset first if it is (this shouldn't be possible) */ 5472731b9a8SJean-Christophe PLAGNIOL-VILLARD if (device->device_state != STATE_DEFAULT) { 5482731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "set_address: %02x state: %s", 5492731b9a8SJean-Christophe PLAGNIOL-VILLARD le16_to_cpu (request->wValue), 5502731b9a8SJean-Christophe PLAGNIOL-VILLARD usbd_device_states[device->device_state]); 5512731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5522731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5532731b9a8SJean-Christophe PLAGNIOL-VILLARD address = le16_to_cpu (request->wValue); 5542731b9a8SJean-Christophe PLAGNIOL-VILLARD if ((address & 0x7f) != address) { 5552731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (1, "invalid address %04x %04x", 5562731b9a8SJean-Christophe PLAGNIOL-VILLARD address, address & 0x7f); 5572731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5582731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5592731b9a8SJean-Christophe PLAGNIOL-VILLARD device->address = address; 5602731b9a8SJean-Christophe PLAGNIOL-VILLARD 5612731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(2, "address: %d %d %d", */ 5622731b9a8SJean-Christophe PLAGNIOL-VILLARD /* request->wValue, le16_to_cpu(request->wValue), device->address); */ 5632731b9a8SJean-Christophe PLAGNIOL-VILLARD 5642731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 5652731b9a8SJean-Christophe PLAGNIOL-VILLARD 5662731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */ 5672731b9a8SJean-Christophe PLAGNIOL-VILLARD dbg_ep0 (0, "set descriptor: NOT SUPPORTED"); 5682731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5692731b9a8SJean-Christophe PLAGNIOL-VILLARD 5702731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_CONFIGURATION: 5712731b9a8SJean-Christophe PLAGNIOL-VILLARD /* c.f. 9.4.7 - the top half of wValue is reserved */ 5722731b9a8SJean-Christophe PLAGNIOL-VILLARD device->configuration = le16_to_cpu(request->wValue) & 0xff; 5732731b9a8SJean-Christophe PLAGNIOL-VILLARD 5742731b9a8SJean-Christophe PLAGNIOL-VILLARD /* reset interface and alternate settings */ 5752731b9a8SJean-Christophe PLAGNIOL-VILLARD device->interface = device->alternate = 0; 5762731b9a8SJean-Christophe PLAGNIOL-VILLARD 5772731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(2, "set configuration: %d", device->configuration); */ 5782731b9a8SJean-Christophe PLAGNIOL-VILLARD /*serial_printf("DEVICE_CONFIGURED.. event?\n"); */ 5792731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 5802731b9a8SJean-Christophe PLAGNIOL-VILLARD 5812731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SET_INTERFACE: 5822731b9a8SJean-Christophe PLAGNIOL-VILLARD device->interface = le16_to_cpu (request->wIndex); 5832731b9a8SJean-Christophe PLAGNIOL-VILLARD device->alternate = le16_to_cpu (request->wValue); 5842731b9a8SJean-Christophe PLAGNIOL-VILLARD /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */ 5852731b9a8SJean-Christophe PLAGNIOL-VILLARD serial_printf ("DEVICE_SET_INTERFACE.. event?\n"); 5862731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 5872731b9a8SJean-Christophe PLAGNIOL-VILLARD 5882731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_STATUS: 5892731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_DESCRIPTOR: 5902731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_CONFIGURATION: 5912731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_GET_INTERFACE: 5922731b9a8SJean-Christophe PLAGNIOL-VILLARD case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ 5932731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5942731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5952731b9a8SJean-Christophe PLAGNIOL-VILLARD } 5962731b9a8SJean-Christophe PLAGNIOL-VILLARD return -1; 5972731b9a8SJean-Christophe PLAGNIOL-VILLARD } 598