11378df79SJean-Christophe PLAGNIOL-VILLARD /* 21378df79SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2003 31378df79SJean-Christophe PLAGNIOL-VILLARD * Gerry Hamel, geh@ti.com, Texas Instruments 41378df79SJean-Christophe PLAGNIOL-VILLARD * 51378df79SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2006 61378df79SJean-Christophe PLAGNIOL-VILLARD * Bryan O'Donoghue, bodonoghue@codehermit.ie 71378df79SJean-Christophe PLAGNIOL-VILLARD * 81378df79SJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or modify 91378df79SJean-Christophe PLAGNIOL-VILLARD * it under the terms of the GNU General Public License as published by 101378df79SJean-Christophe PLAGNIOL-VILLARD * the Free Software Foundation; either version 2 of the License, or 111378df79SJean-Christophe PLAGNIOL-VILLARD * (at your option) any later version. 121378df79SJean-Christophe PLAGNIOL-VILLARD * 131378df79SJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 141378df79SJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 151378df79SJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 161378df79SJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 171378df79SJean-Christophe PLAGNIOL-VILLARD * 181378df79SJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 191378df79SJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 201378df79SJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 211378df79SJean-Christophe PLAGNIOL-VILLARD * 221378df79SJean-Christophe PLAGNIOL-VILLARD */ 231378df79SJean-Christophe PLAGNIOL-VILLARD 241378df79SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 25dedacc18SJean-Christophe PLAGNIOL-VILLARD #include <config.h> 261378df79SJean-Christophe PLAGNIOL-VILLARD #include <circbuf.h> 2752cb4d4fSJean-Christophe PLAGNIOL-VILLARD #include <stdio_dev.h> 28b2fb47f1STom Rini #include <asm/unaligned.h> 291378df79SJean-Christophe PLAGNIOL-VILLARD #include "usbtty.h" 301378df79SJean-Christophe PLAGNIOL-VILLARD #include "usb_cdc_acm.h" 311378df79SJean-Christophe PLAGNIOL-VILLARD #include "usbdescriptors.h" 321378df79SJean-Christophe PLAGNIOL-VILLARD 33dedacc18SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 341378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYDBG(fmt,args...)\ 351378df79SJean-Christophe PLAGNIOL-VILLARD serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args) 361378df79SJean-Christophe PLAGNIOL-VILLARD #else 371378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYDBG(fmt,args...) do{}while(0) 381378df79SJean-Christophe PLAGNIOL-VILLARD #endif 391378df79SJean-Christophe PLAGNIOL-VILLARD 401378df79SJean-Christophe PLAGNIOL-VILLARD #if 1 411378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYERR(fmt,args...)\ 421378df79SJean-Christophe PLAGNIOL-VILLARD serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\ 431378df79SJean-Christophe PLAGNIOL-VILLARD __LINE__,##args) 441378df79SJean-Christophe PLAGNIOL-VILLARD #else 451378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYERR(fmt,args...) do{}while(0) 461378df79SJean-Christophe PLAGNIOL-VILLARD #endif 471378df79SJean-Christophe PLAGNIOL-VILLARD 481378df79SJean-Christophe PLAGNIOL-VILLARD /* 491378df79SJean-Christophe PLAGNIOL-VILLARD * Defines 501378df79SJean-Christophe PLAGNIOL-VILLARD */ 511378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_CONFIGS 1 521378df79SJean-Christophe PLAGNIOL-VILLARD #define MAX_INTERFACES 2 531378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_ENDPOINTS 3 541378df79SJean-Christophe PLAGNIOL-VILLARD #define ACM_TX_ENDPOINT 3 551378df79SJean-Christophe PLAGNIOL-VILLARD #define ACM_RX_ENDPOINT 2 561378df79SJean-Christophe PLAGNIOL-VILLARD #define GSERIAL_TX_ENDPOINT 2 571378df79SJean-Christophe PLAGNIOL-VILLARD #define GSERIAL_RX_ENDPOINT 1 581378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_ACM_INTERFACES 2 591378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_GSERIAL_INTERFACES 1 601378df79SJean-Christophe PLAGNIOL-VILLARD #define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface" 611378df79SJean-Christophe PLAGNIOL-VILLARD #define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface" 621378df79SJean-Christophe PLAGNIOL-VILLARD 631378df79SJean-Christophe PLAGNIOL-VILLARD /* 641378df79SJean-Christophe PLAGNIOL-VILLARD * Buffers to hold input and output data 651378df79SJean-Christophe PLAGNIOL-VILLARD */ 66*b2caefbbSShiraz Hashim #define USBTTY_BUFFER_SIZE 2048 671378df79SJean-Christophe PLAGNIOL-VILLARD static circbuf_t usbtty_input; 681378df79SJean-Christophe PLAGNIOL-VILLARD static circbuf_t usbtty_output; 691378df79SJean-Christophe PLAGNIOL-VILLARD 701378df79SJean-Christophe PLAGNIOL-VILLARD 711378df79SJean-Christophe PLAGNIOL-VILLARD /* 721378df79SJean-Christophe PLAGNIOL-VILLARD * Instance variables 731378df79SJean-Christophe PLAGNIOL-VILLARD */ 7452cb4d4fSJean-Christophe PLAGNIOL-VILLARD static struct stdio_dev usbttydev; 751378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_device_instance device_instance[1]; 761378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_bus_instance bus_instance[1]; 771378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_configuration_instance config_instance[NUM_CONFIGS]; 781378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_interface_instance interface_instance[MAX_INTERFACES]; 791378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_alternate_instance alternate_instance[MAX_INTERFACES]; 801378df79SJean-Christophe PLAGNIOL-VILLARD /* one extra for control endpoint */ 811378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1]; 821378df79SJean-Christophe PLAGNIOL-VILLARD 831378df79SJean-Christophe PLAGNIOL-VILLARD /* 841378df79SJean-Christophe PLAGNIOL-VILLARD * Global flag 851378df79SJean-Christophe PLAGNIOL-VILLARD */ 861378df79SJean-Christophe PLAGNIOL-VILLARD int usbtty_configured_flag = 0; 871378df79SJean-Christophe PLAGNIOL-VILLARD 881378df79SJean-Christophe PLAGNIOL-VILLARD /* 891378df79SJean-Christophe PLAGNIOL-VILLARD * Serial number 901378df79SJean-Christophe PLAGNIOL-VILLARD */ 911378df79SJean-Christophe PLAGNIOL-VILLARD static char serial_number[16]; 921378df79SJean-Christophe PLAGNIOL-VILLARD 931378df79SJean-Christophe PLAGNIOL-VILLARD 941378df79SJean-Christophe PLAGNIOL-VILLARD /* 951378df79SJean-Christophe PLAGNIOL-VILLARD * Descriptors, Strings, Local variables. 961378df79SJean-Christophe PLAGNIOL-VILLARD */ 971378df79SJean-Christophe PLAGNIOL-VILLARD 982731b9a8SJean-Christophe PLAGNIOL-VILLARD /* defined and used by gadget/ep0.c */ 991378df79SJean-Christophe PLAGNIOL-VILLARD extern struct usb_string_descriptor **usb_strings; 1001378df79SJean-Christophe PLAGNIOL-VILLARD 1011378df79SJean-Christophe PLAGNIOL-VILLARD /* Indicies, References */ 1021378df79SJean-Christophe PLAGNIOL-VILLARD static unsigned short rx_endpoint = 0; 1031378df79SJean-Christophe PLAGNIOL-VILLARD static unsigned short tx_endpoint = 0; 1041378df79SJean-Christophe PLAGNIOL-VILLARD static unsigned short interface_count = 0; 1051378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_string_descriptor *usbtty_string_table[STR_COUNT]; 1061378df79SJean-Christophe PLAGNIOL-VILLARD 1071378df79SJean-Christophe PLAGNIOL-VILLARD /* USB Descriptor Strings */ 1081378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4}; 1091378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)]; 1101378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)]; 1111378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)]; 1121378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)]; 1131378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)]; 1141378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)]; 1151378df79SJean-Christophe PLAGNIOL-VILLARD 1161378df79SJean-Christophe PLAGNIOL-VILLARD /* Standard USB Data Structures */ 1171378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES]; 1181378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS]; 1191378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_configuration_descriptor *configuration_descriptor = 0; 1201378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_device_descriptor device_descriptor = { 1211378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = sizeof(struct usb_device_descriptor), 1221378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_DEVICE, 1231378df79SJean-Christophe PLAGNIOL-VILLARD .bcdUSB = cpu_to_le16(USB_BCD_VERSION), 1241378df79SJean-Christophe PLAGNIOL-VILLARD .bDeviceSubClass = 0x00, 1251378df79SJean-Christophe PLAGNIOL-VILLARD .bDeviceProtocol = 0x00, 1261378df79SJean-Christophe PLAGNIOL-VILLARD .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE, 1271378df79SJean-Christophe PLAGNIOL-VILLARD .idVendor = cpu_to_le16(CONFIG_USBD_VENDORID), 1281378df79SJean-Christophe PLAGNIOL-VILLARD .bcdDevice = cpu_to_le16(USBTTY_BCD_DEVICE), 1291378df79SJean-Christophe PLAGNIOL-VILLARD .iManufacturer = STR_MANUFACTURER, 1301378df79SJean-Christophe PLAGNIOL-VILLARD .iProduct = STR_PRODUCT, 1311378df79SJean-Christophe PLAGNIOL-VILLARD .iSerialNumber = STR_SERIAL, 1321378df79SJean-Christophe PLAGNIOL-VILLARD .bNumConfigurations = NUM_CONFIGS 1331378df79SJean-Christophe PLAGNIOL-VILLARD }; 1341378df79SJean-Christophe PLAGNIOL-VILLARD 1351378df79SJean-Christophe PLAGNIOL-VILLARD 136f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS) 137f9da0f89SVipin KUMAR static struct usb_qualifier_descriptor qualifier_descriptor = { 138f9da0f89SVipin KUMAR .bLength = sizeof(struct usb_qualifier_descriptor), 139f9da0f89SVipin KUMAR .bDescriptorType = USB_DT_QUAL, 140f9da0f89SVipin KUMAR .bcdUSB = cpu_to_le16(USB_BCD_VERSION), 141f9da0f89SVipin KUMAR .bDeviceClass = COMMUNICATIONS_DEVICE_CLASS, 142f9da0f89SVipin KUMAR .bDeviceSubClass = 0x00, 143f9da0f89SVipin KUMAR .bDeviceProtocol = 0x00, 144f9da0f89SVipin KUMAR .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE, 145f9da0f89SVipin KUMAR .bNumConfigurations = NUM_CONFIGS 146f9da0f89SVipin KUMAR }; 147f9da0f89SVipin KUMAR #endif 148f9da0f89SVipin KUMAR 1491378df79SJean-Christophe PLAGNIOL-VILLARD /* 1501378df79SJean-Christophe PLAGNIOL-VILLARD * Static CDC ACM specific descriptors 1511378df79SJean-Christophe PLAGNIOL-VILLARD */ 1521378df79SJean-Christophe PLAGNIOL-VILLARD 1531378df79SJean-Christophe PLAGNIOL-VILLARD struct acm_config_desc { 1541378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_configuration_descriptor configuration_desc; 1551378df79SJean-Christophe PLAGNIOL-VILLARD 1561378df79SJean-Christophe PLAGNIOL-VILLARD /* Master Interface */ 1571378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_interface_descriptor interface_desc; 1581378df79SJean-Christophe PLAGNIOL-VILLARD 1591378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_class_header_function_descriptor usb_class_header; 1601378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_class_call_management_descriptor usb_class_call_mgt; 1611378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_class_abstract_control_descriptor usb_class_acm; 1621378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_class_union_function_descriptor usb_class_union; 1631378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_endpoint_descriptor notification_endpoint; 1641378df79SJean-Christophe PLAGNIOL-VILLARD 1651378df79SJean-Christophe PLAGNIOL-VILLARD /* Slave Interface */ 1661378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_interface_descriptor data_class_interface; 167f3c0de63SAtin Malaviya struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS-1]; 1681378df79SJean-Christophe PLAGNIOL-VILLARD } __attribute__((packed)); 1691378df79SJean-Christophe PLAGNIOL-VILLARD 1701378df79SJean-Christophe PLAGNIOL-VILLARD static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = { 1711378df79SJean-Christophe PLAGNIOL-VILLARD { 1721378df79SJean-Christophe PLAGNIOL-VILLARD .configuration_desc ={ 1731378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 1741378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_configuration_descriptor), 1751378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_CONFIG, 1761378df79SJean-Christophe PLAGNIOL-VILLARD .wTotalLength = 1771378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(sizeof(struct acm_config_desc)), 1781378df79SJean-Christophe PLAGNIOL-VILLARD .bNumInterfaces = NUM_ACM_INTERFACES, 1791378df79SJean-Christophe PLAGNIOL-VILLARD .bConfigurationValue = 1, 1801378df79SJean-Christophe PLAGNIOL-VILLARD .iConfiguration = STR_CONFIG, 1811378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = 1821378df79SJean-Christophe PLAGNIOL-VILLARD BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, 1831378df79SJean-Christophe PLAGNIOL-VILLARD .bMaxPower = USBTTY_MAXPOWER 1841378df79SJean-Christophe PLAGNIOL-VILLARD }, 1851378df79SJean-Christophe PLAGNIOL-VILLARD /* Interface 1 */ 1861378df79SJean-Christophe PLAGNIOL-VILLARD .interface_desc = { 1871378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = sizeof(struct usb_interface_descriptor), 1881378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_INTERFACE, 1891378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceNumber = 0, 1901378df79SJean-Christophe PLAGNIOL-VILLARD .bAlternateSetting = 0, 1911378df79SJean-Christophe PLAGNIOL-VILLARD .bNumEndpoints = 0x01, 1921378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceClass = 1931378df79SJean-Christophe PLAGNIOL-VILLARD COMMUNICATIONS_INTERFACE_CLASS_CONTROL, 1941378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS, 1951378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL, 1961378df79SJean-Christophe PLAGNIOL-VILLARD .iInterface = STR_CTRL_INTERFACE, 1971378df79SJean-Christophe PLAGNIOL-VILLARD }, 1981378df79SJean-Christophe PLAGNIOL-VILLARD .usb_class_header = { 1991378df79SJean-Christophe PLAGNIOL-VILLARD .bFunctionLength = 2001378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_class_header_function_descriptor), 2011378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = CS_INTERFACE, 2021378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorSubtype = USB_ST_HEADER, 2031378df79SJean-Christophe PLAGNIOL-VILLARD .bcdCDC = cpu_to_le16(110), 2041378df79SJean-Christophe PLAGNIOL-VILLARD }, 2051378df79SJean-Christophe PLAGNIOL-VILLARD .usb_class_call_mgt = { 2061378df79SJean-Christophe PLAGNIOL-VILLARD .bFunctionLength = 2071378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_class_call_management_descriptor), 2081378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = CS_INTERFACE, 2091378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorSubtype = USB_ST_CMF, 2101378df79SJean-Christophe PLAGNIOL-VILLARD .bmCapabilities = 0x00, 2111378df79SJean-Christophe PLAGNIOL-VILLARD .bDataInterface = 0x01, 2121378df79SJean-Christophe PLAGNIOL-VILLARD }, 2131378df79SJean-Christophe PLAGNIOL-VILLARD .usb_class_acm = { 2141378df79SJean-Christophe PLAGNIOL-VILLARD .bFunctionLength = 2151378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_class_abstract_control_descriptor), 2161378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = CS_INTERFACE, 2171378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorSubtype = USB_ST_ACMF, 2181378df79SJean-Christophe PLAGNIOL-VILLARD .bmCapabilities = 0x00, 2191378df79SJean-Christophe PLAGNIOL-VILLARD }, 2201378df79SJean-Christophe PLAGNIOL-VILLARD .usb_class_union = { 2211378df79SJean-Christophe PLAGNIOL-VILLARD .bFunctionLength = 2221378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_class_union_function_descriptor), 2231378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = CS_INTERFACE, 2241378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorSubtype = USB_ST_UF, 2251378df79SJean-Christophe PLAGNIOL-VILLARD .bMasterInterface = 0x00, 2261378df79SJean-Christophe PLAGNIOL-VILLARD .bSlaveInterface0 = 0x01, 2271378df79SJean-Christophe PLAGNIOL-VILLARD }, 2281378df79SJean-Christophe PLAGNIOL-VILLARD .notification_endpoint = { 2291378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 2301378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_endpoint_descriptor), 2311378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_ENDPOINT, 2329e78dae2SVivek Kutal .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, 2331378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = USB_ENDPOINT_XFER_INT, 2341378df79SJean-Christophe PLAGNIOL-VILLARD .wMaxPacketSize 2351378df79SJean-Christophe PLAGNIOL-VILLARD = cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE), 2361378df79SJean-Christophe PLAGNIOL-VILLARD .bInterval = 0xFF, 2371378df79SJean-Christophe PLAGNIOL-VILLARD }, 2381378df79SJean-Christophe PLAGNIOL-VILLARD 2391378df79SJean-Christophe PLAGNIOL-VILLARD /* Interface 2 */ 2401378df79SJean-Christophe PLAGNIOL-VILLARD .data_class_interface = { 2411378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 2421378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_interface_descriptor), 2431378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_INTERFACE, 2441378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceNumber = 0x01, 2451378df79SJean-Christophe PLAGNIOL-VILLARD .bAlternateSetting = 0x00, 2461378df79SJean-Christophe PLAGNIOL-VILLARD .bNumEndpoints = 0x02, 2471378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceClass = 2481378df79SJean-Christophe PLAGNIOL-VILLARD COMMUNICATIONS_INTERFACE_CLASS_DATA, 2491378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceSubClass = DATA_INTERFACE_SUBCLASS_NONE, 2501378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceProtocol = DATA_INTERFACE_PROTOCOL_NONE, 2511378df79SJean-Christophe PLAGNIOL-VILLARD .iInterface = STR_DATA_INTERFACE, 2521378df79SJean-Christophe PLAGNIOL-VILLARD }, 2531378df79SJean-Christophe PLAGNIOL-VILLARD .data_endpoints = { 2541378df79SJean-Christophe PLAGNIOL-VILLARD { 2551378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 2561378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_endpoint_descriptor), 2571378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_ENDPOINT, 2589e78dae2SVivek Kutal .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, 2591378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = 2601378df79SJean-Christophe PLAGNIOL-VILLARD USB_ENDPOINT_XFER_BULK, 2611378df79SJean-Christophe PLAGNIOL-VILLARD .wMaxPacketSize = 2621378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE), 2631378df79SJean-Christophe PLAGNIOL-VILLARD .bInterval = 0xFF, 2641378df79SJean-Christophe PLAGNIOL-VILLARD }, 2651378df79SJean-Christophe PLAGNIOL-VILLARD { 2661378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 2671378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_endpoint_descriptor), 2681378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_ENDPOINT, 2699e78dae2SVivek Kutal .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, 2701378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = 2711378df79SJean-Christophe PLAGNIOL-VILLARD USB_ENDPOINT_XFER_BULK, 2721378df79SJean-Christophe PLAGNIOL-VILLARD .wMaxPacketSize = 2731378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE), 2741378df79SJean-Christophe PLAGNIOL-VILLARD .bInterval = 0xFF, 2751378df79SJean-Christophe PLAGNIOL-VILLARD }, 2761378df79SJean-Christophe PLAGNIOL-VILLARD }, 2771378df79SJean-Christophe PLAGNIOL-VILLARD }, 2781378df79SJean-Christophe PLAGNIOL-VILLARD }; 2791378df79SJean-Christophe PLAGNIOL-VILLARD 2801378df79SJean-Christophe PLAGNIOL-VILLARD static struct rs232_emu rs232_desc={ 2811378df79SJean-Christophe PLAGNIOL-VILLARD .dter = 115200, 2821378df79SJean-Christophe PLAGNIOL-VILLARD .stop_bits = 0x00, 2831378df79SJean-Christophe PLAGNIOL-VILLARD .parity = 0x00, 2841378df79SJean-Christophe PLAGNIOL-VILLARD .data_bits = 0x08 2851378df79SJean-Christophe PLAGNIOL-VILLARD }; 2861378df79SJean-Christophe PLAGNIOL-VILLARD 2871378df79SJean-Christophe PLAGNIOL-VILLARD 2881378df79SJean-Christophe PLAGNIOL-VILLARD /* 2891378df79SJean-Christophe PLAGNIOL-VILLARD * Static Generic Serial specific data 2901378df79SJean-Christophe PLAGNIOL-VILLARD */ 2911378df79SJean-Christophe PLAGNIOL-VILLARD 2921378df79SJean-Christophe PLAGNIOL-VILLARD 2931378df79SJean-Christophe PLAGNIOL-VILLARD struct gserial_config_desc { 2941378df79SJean-Christophe PLAGNIOL-VILLARD 2951378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_configuration_descriptor configuration_desc; 296f3c0de63SAtin Malaviya struct usb_interface_descriptor interface_desc[NUM_GSERIAL_INTERFACES]; 297f3c0de63SAtin Malaviya struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS]; 2981378df79SJean-Christophe PLAGNIOL-VILLARD 2991378df79SJean-Christophe PLAGNIOL-VILLARD } __attribute__((packed)); 3001378df79SJean-Christophe PLAGNIOL-VILLARD 3011378df79SJean-Christophe PLAGNIOL-VILLARD static struct gserial_config_desc 3021378df79SJean-Christophe PLAGNIOL-VILLARD gserial_configuration_descriptors[NUM_CONFIGS] ={ 3031378df79SJean-Christophe PLAGNIOL-VILLARD { 3041378df79SJean-Christophe PLAGNIOL-VILLARD .configuration_desc ={ 3051378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = sizeof(struct usb_configuration_descriptor), 3061378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_CONFIG, 3071378df79SJean-Christophe PLAGNIOL-VILLARD .wTotalLength = 3081378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(sizeof(struct gserial_config_desc)), 3091378df79SJean-Christophe PLAGNIOL-VILLARD .bNumInterfaces = NUM_GSERIAL_INTERFACES, 3101378df79SJean-Christophe PLAGNIOL-VILLARD .bConfigurationValue = 1, 3111378df79SJean-Christophe PLAGNIOL-VILLARD .iConfiguration = STR_CONFIG, 3121378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = 3131378df79SJean-Christophe PLAGNIOL-VILLARD BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, 3141378df79SJean-Christophe PLAGNIOL-VILLARD .bMaxPower = USBTTY_MAXPOWER 3151378df79SJean-Christophe PLAGNIOL-VILLARD }, 3161378df79SJean-Christophe PLAGNIOL-VILLARD .interface_desc = { 3171378df79SJean-Christophe PLAGNIOL-VILLARD { 3181378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 3191378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_interface_descriptor), 3201378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_INTERFACE, 3211378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceNumber = 0, 3221378df79SJean-Christophe PLAGNIOL-VILLARD .bAlternateSetting = 0, 3231378df79SJean-Christophe PLAGNIOL-VILLARD .bNumEndpoints = NUM_ENDPOINTS, 3241378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceClass = 3251378df79SJean-Christophe PLAGNIOL-VILLARD COMMUNICATIONS_INTERFACE_CLASS_VENDOR, 3261378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceSubClass = 3271378df79SJean-Christophe PLAGNIOL-VILLARD COMMUNICATIONS_NO_SUBCLASS, 3281378df79SJean-Christophe PLAGNIOL-VILLARD .bInterfaceProtocol = 3291378df79SJean-Christophe PLAGNIOL-VILLARD COMMUNICATIONS_NO_PROTOCOL, 3301378df79SJean-Christophe PLAGNIOL-VILLARD .iInterface = STR_DATA_INTERFACE 3311378df79SJean-Christophe PLAGNIOL-VILLARD }, 3321378df79SJean-Christophe PLAGNIOL-VILLARD }, 3331378df79SJean-Christophe PLAGNIOL-VILLARD .data_endpoints = { 3341378df79SJean-Christophe PLAGNIOL-VILLARD { 3351378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 3361378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_endpoint_descriptor), 3371378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_ENDPOINT, 3389e78dae2SVivek Kutal .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, 3391378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = USB_ENDPOINT_XFER_BULK, 3401378df79SJean-Christophe PLAGNIOL-VILLARD .wMaxPacketSize = 3411378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE), 3421378df79SJean-Christophe PLAGNIOL-VILLARD .bInterval= 0xFF, 3431378df79SJean-Christophe PLAGNIOL-VILLARD }, 3441378df79SJean-Christophe PLAGNIOL-VILLARD { 3451378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 3461378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_endpoint_descriptor), 3471378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_ENDPOINT, 3489e78dae2SVivek Kutal .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, 3491378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = USB_ENDPOINT_XFER_BULK, 3501378df79SJean-Christophe PLAGNIOL-VILLARD .wMaxPacketSize = 3511378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE), 3521378df79SJean-Christophe PLAGNIOL-VILLARD .bInterval = 0xFF, 3531378df79SJean-Christophe PLAGNIOL-VILLARD }, 3541378df79SJean-Christophe PLAGNIOL-VILLARD { 3551378df79SJean-Christophe PLAGNIOL-VILLARD .bLength = 3561378df79SJean-Christophe PLAGNIOL-VILLARD sizeof(struct usb_endpoint_descriptor), 3571378df79SJean-Christophe PLAGNIOL-VILLARD .bDescriptorType = USB_DT_ENDPOINT, 3589e78dae2SVivek Kutal .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, 3591378df79SJean-Christophe PLAGNIOL-VILLARD .bmAttributes = USB_ENDPOINT_XFER_INT, 3601378df79SJean-Christophe PLAGNIOL-VILLARD .wMaxPacketSize = 3611378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE), 3621378df79SJean-Christophe PLAGNIOL-VILLARD .bInterval = 0xFF, 3631378df79SJean-Christophe PLAGNIOL-VILLARD }, 3641378df79SJean-Christophe PLAGNIOL-VILLARD }, 3651378df79SJean-Christophe PLAGNIOL-VILLARD }, 3661378df79SJean-Christophe PLAGNIOL-VILLARD }; 3671378df79SJean-Christophe PLAGNIOL-VILLARD 3681378df79SJean-Christophe PLAGNIOL-VILLARD /* 3691378df79SJean-Christophe PLAGNIOL-VILLARD * Static Function Prototypes 3701378df79SJean-Christophe PLAGNIOL-VILLARD */ 3711378df79SJean-Christophe PLAGNIOL-VILLARD 3721378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_strings (void); 3731378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_instances (void); 3741378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_endpoints (void); 3751378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_terminal_type(short type); 3761378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_event_handler (struct usb_device_instance *device, 3771378df79SJean-Christophe PLAGNIOL-VILLARD usb_device_event_t event, int data); 3781378df79SJean-Christophe PLAGNIOL-VILLARD static int usbtty_cdc_setup(struct usb_device_request *request, 3791378df79SJean-Christophe PLAGNIOL-VILLARD struct urb *urb); 3801378df79SJean-Christophe PLAGNIOL-VILLARD static int usbtty_configured (void); 3811378df79SJean-Christophe PLAGNIOL-VILLARD static int write_buffer (circbuf_t * buf); 3821378df79SJean-Christophe PLAGNIOL-VILLARD static int fill_buffer (circbuf_t * buf); 3831378df79SJean-Christophe PLAGNIOL-VILLARD 3841378df79SJean-Christophe PLAGNIOL-VILLARD void usbtty_poll (void); 3851378df79SJean-Christophe PLAGNIOL-VILLARD 3861378df79SJean-Christophe PLAGNIOL-VILLARD /* utility function for converting char* to wide string used by USB */ 3871378df79SJean-Christophe PLAGNIOL-VILLARD static void str2wide (char *str, u16 * wide) 3881378df79SJean-Christophe PLAGNIOL-VILLARD { 3891378df79SJean-Christophe PLAGNIOL-VILLARD int i; 3901378df79SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < strlen (str) && str[i]; i++){ 3911378df79SJean-Christophe PLAGNIOL-VILLARD #if defined(__LITTLE_ENDIAN) 3921378df79SJean-Christophe PLAGNIOL-VILLARD wide[i] = (u16) str[i]; 3931378df79SJean-Christophe PLAGNIOL-VILLARD #elif defined(__BIG_ENDIAN) 3941378df79SJean-Christophe PLAGNIOL-VILLARD wide[i] = ((u16)(str[i])<<8); 3951378df79SJean-Christophe PLAGNIOL-VILLARD #else 3961378df79SJean-Christophe PLAGNIOL-VILLARD #error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined" 3971378df79SJean-Christophe PLAGNIOL-VILLARD #endif 3981378df79SJean-Christophe PLAGNIOL-VILLARD } 3991378df79SJean-Christophe PLAGNIOL-VILLARD } 4001378df79SJean-Christophe PLAGNIOL-VILLARD 4011378df79SJean-Christophe PLAGNIOL-VILLARD /* 4021378df79SJean-Christophe PLAGNIOL-VILLARD * Test whether a character is in the RX buffer 4031378df79SJean-Christophe PLAGNIOL-VILLARD */ 4041378df79SJean-Christophe PLAGNIOL-VILLARD 4051378df79SJean-Christophe PLAGNIOL-VILLARD int usbtty_tstc (void) 4061378df79SJean-Christophe PLAGNIOL-VILLARD { 4071378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_endpoint_instance *endpoint = 4081378df79SJean-Christophe PLAGNIOL-VILLARD &endpoint_instance[rx_endpoint]; 4091378df79SJean-Christophe PLAGNIOL-VILLARD 4101378df79SJean-Christophe PLAGNIOL-VILLARD /* If no input data exists, allow more RX to be accepted */ 4111378df79SJean-Christophe PLAGNIOL-VILLARD if(usbtty_input.size <= 0){ 4121378df79SJean-Christophe PLAGNIOL-VILLARD udc_unset_nak(endpoint->endpoint_address&0x03); 4131378df79SJean-Christophe PLAGNIOL-VILLARD } 4141378df79SJean-Christophe PLAGNIOL-VILLARD 4151378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_poll (); 4161378df79SJean-Christophe PLAGNIOL-VILLARD return (usbtty_input.size > 0); 4171378df79SJean-Christophe PLAGNIOL-VILLARD } 4181378df79SJean-Christophe PLAGNIOL-VILLARD 4191378df79SJean-Christophe PLAGNIOL-VILLARD /* 4201378df79SJean-Christophe PLAGNIOL-VILLARD * Read a single byte from the usb client port. Returns 1 on success, 0 4211378df79SJean-Christophe PLAGNIOL-VILLARD * otherwise. When the function is succesfull, the character read is 4221378df79SJean-Christophe PLAGNIOL-VILLARD * written into its argument c. 4231378df79SJean-Christophe PLAGNIOL-VILLARD */ 4241378df79SJean-Christophe PLAGNIOL-VILLARD 4251378df79SJean-Christophe PLAGNIOL-VILLARD int usbtty_getc (void) 4261378df79SJean-Christophe PLAGNIOL-VILLARD { 4271378df79SJean-Christophe PLAGNIOL-VILLARD char c; 4281378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_endpoint_instance *endpoint = 4291378df79SJean-Christophe PLAGNIOL-VILLARD &endpoint_instance[rx_endpoint]; 4301378df79SJean-Christophe PLAGNIOL-VILLARD 4311378df79SJean-Christophe PLAGNIOL-VILLARD while (usbtty_input.size <= 0) { 4321378df79SJean-Christophe PLAGNIOL-VILLARD udc_unset_nak(endpoint->endpoint_address&0x03); 4331378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_poll (); 4341378df79SJean-Christophe PLAGNIOL-VILLARD } 4351378df79SJean-Christophe PLAGNIOL-VILLARD 4361378df79SJean-Christophe PLAGNIOL-VILLARD buf_pop (&usbtty_input, &c, 1); 4371378df79SJean-Christophe PLAGNIOL-VILLARD udc_set_nak(endpoint->endpoint_address&0x03); 4381378df79SJean-Christophe PLAGNIOL-VILLARD 4391378df79SJean-Christophe PLAGNIOL-VILLARD return c; 4401378df79SJean-Christophe PLAGNIOL-VILLARD } 4411378df79SJean-Christophe PLAGNIOL-VILLARD 4421378df79SJean-Christophe PLAGNIOL-VILLARD /* 4431378df79SJean-Christophe PLAGNIOL-VILLARD * Output a single byte to the usb client port. 4441378df79SJean-Christophe PLAGNIOL-VILLARD */ 4451378df79SJean-Christophe PLAGNIOL-VILLARD void usbtty_putc (const char c) 4461378df79SJean-Christophe PLAGNIOL-VILLARD { 447f3c0de63SAtin Malaviya if (!usbtty_configured ()) 448f3c0de63SAtin Malaviya return; 449f3c0de63SAtin Malaviya 4501378df79SJean-Christophe PLAGNIOL-VILLARD buf_push (&usbtty_output, &c, 1); 4511378df79SJean-Christophe PLAGNIOL-VILLARD /* If \n, also do \r */ 4521378df79SJean-Christophe PLAGNIOL-VILLARD if (c == '\n') 4531378df79SJean-Christophe PLAGNIOL-VILLARD buf_push (&usbtty_output, "\r", 1); 4541378df79SJean-Christophe PLAGNIOL-VILLARD 4551378df79SJean-Christophe PLAGNIOL-VILLARD /* Poll at end to handle new data... */ 4561378df79SJean-Christophe PLAGNIOL-VILLARD if ((usbtty_output.size + 2) >= usbtty_output.totalsize) { 4571378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_poll (); 4581378df79SJean-Christophe PLAGNIOL-VILLARD } 4591378df79SJean-Christophe PLAGNIOL-VILLARD } 4601378df79SJean-Christophe PLAGNIOL-VILLARD 4611378df79SJean-Christophe PLAGNIOL-VILLARD /* usbtty_puts() helper function for finding the next '\n' in a string */ 4621378df79SJean-Christophe PLAGNIOL-VILLARD static int next_nl_pos (const char *s) 4631378df79SJean-Christophe PLAGNIOL-VILLARD { 4641378df79SJean-Christophe PLAGNIOL-VILLARD int i; 4651378df79SJean-Christophe PLAGNIOL-VILLARD 4661378df79SJean-Christophe PLAGNIOL-VILLARD for (i = 0; s[i] != '\0'; i++) { 4671378df79SJean-Christophe PLAGNIOL-VILLARD if (s[i] == '\n') 4681378df79SJean-Christophe PLAGNIOL-VILLARD return i; 4691378df79SJean-Christophe PLAGNIOL-VILLARD } 4701378df79SJean-Christophe PLAGNIOL-VILLARD return i; 4711378df79SJean-Christophe PLAGNIOL-VILLARD } 4721378df79SJean-Christophe PLAGNIOL-VILLARD 4731378df79SJean-Christophe PLAGNIOL-VILLARD /* 4741378df79SJean-Christophe PLAGNIOL-VILLARD * Output a string to the usb client port - implementing flow control 4751378df79SJean-Christophe PLAGNIOL-VILLARD */ 4761378df79SJean-Christophe PLAGNIOL-VILLARD 4771378df79SJean-Christophe PLAGNIOL-VILLARD static void __usbtty_puts (const char *str, int len) 4781378df79SJean-Christophe PLAGNIOL-VILLARD { 4791378df79SJean-Christophe PLAGNIOL-VILLARD int maxlen = usbtty_output.totalsize; 4801378df79SJean-Christophe PLAGNIOL-VILLARD int space, n; 4811378df79SJean-Christophe PLAGNIOL-VILLARD 4821378df79SJean-Christophe PLAGNIOL-VILLARD /* break str into chunks < buffer size, if needed */ 4831378df79SJean-Christophe PLAGNIOL-VILLARD while (len > 0) { 4841378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_poll (); 4851378df79SJean-Christophe PLAGNIOL-VILLARD 4861378df79SJean-Christophe PLAGNIOL-VILLARD space = maxlen - usbtty_output.size; 4871378df79SJean-Christophe PLAGNIOL-VILLARD /* Empty buffer here, if needed, to ensure space... */ 4881378df79SJean-Christophe PLAGNIOL-VILLARD if (space) { 4891378df79SJean-Christophe PLAGNIOL-VILLARD write_buffer (&usbtty_output); 4901378df79SJean-Christophe PLAGNIOL-VILLARD 4911378df79SJean-Christophe PLAGNIOL-VILLARD n = MIN (space, MIN (len, maxlen)); 4921378df79SJean-Christophe PLAGNIOL-VILLARD buf_push (&usbtty_output, str, n); 4931378df79SJean-Christophe PLAGNIOL-VILLARD 4941378df79SJean-Christophe PLAGNIOL-VILLARD str += n; 4951378df79SJean-Christophe PLAGNIOL-VILLARD len -= n; 4961378df79SJean-Christophe PLAGNIOL-VILLARD } 4971378df79SJean-Christophe PLAGNIOL-VILLARD } 4981378df79SJean-Christophe PLAGNIOL-VILLARD } 4991378df79SJean-Christophe PLAGNIOL-VILLARD 5001378df79SJean-Christophe PLAGNIOL-VILLARD void usbtty_puts (const char *str) 5011378df79SJean-Christophe PLAGNIOL-VILLARD { 5021378df79SJean-Christophe PLAGNIOL-VILLARD int n; 503f3c0de63SAtin Malaviya int len; 5041378df79SJean-Christophe PLAGNIOL-VILLARD 505f3c0de63SAtin Malaviya if (!usbtty_configured ()) 506f3c0de63SAtin Malaviya return; 507f3c0de63SAtin Malaviya 508f3c0de63SAtin Malaviya len = strlen (str); 5091378df79SJean-Christophe PLAGNIOL-VILLARD /* add '\r' for each '\n' */ 5101378df79SJean-Christophe PLAGNIOL-VILLARD while (len > 0) { 5111378df79SJean-Christophe PLAGNIOL-VILLARD n = next_nl_pos (str); 5121378df79SJean-Christophe PLAGNIOL-VILLARD 5131378df79SJean-Christophe PLAGNIOL-VILLARD if (str[n] == '\n') { 5141378df79SJean-Christophe PLAGNIOL-VILLARD __usbtty_puts (str, n + 1); 5151378df79SJean-Christophe PLAGNIOL-VILLARD __usbtty_puts ("\r", 1); 5161378df79SJean-Christophe PLAGNIOL-VILLARD str += (n + 1); 5171378df79SJean-Christophe PLAGNIOL-VILLARD len -= (n + 1); 5181378df79SJean-Christophe PLAGNIOL-VILLARD } else { 5191378df79SJean-Christophe PLAGNIOL-VILLARD /* No \n found. All done. */ 5201378df79SJean-Christophe PLAGNIOL-VILLARD __usbtty_puts (str, n); 5211378df79SJean-Christophe PLAGNIOL-VILLARD break; 5221378df79SJean-Christophe PLAGNIOL-VILLARD } 5231378df79SJean-Christophe PLAGNIOL-VILLARD } 5241378df79SJean-Christophe PLAGNIOL-VILLARD 5251378df79SJean-Christophe PLAGNIOL-VILLARD /* Poll at end to handle new data... */ 5261378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_poll (); 5271378df79SJean-Christophe PLAGNIOL-VILLARD } 5281378df79SJean-Christophe PLAGNIOL-VILLARD 5291378df79SJean-Christophe PLAGNIOL-VILLARD /* 5301378df79SJean-Christophe PLAGNIOL-VILLARD * Initialize the usb client port. 5311378df79SJean-Christophe PLAGNIOL-VILLARD * 5321378df79SJean-Christophe PLAGNIOL-VILLARD */ 5331378df79SJean-Christophe PLAGNIOL-VILLARD int drv_usbtty_init (void) 5341378df79SJean-Christophe PLAGNIOL-VILLARD { 5351378df79SJean-Christophe PLAGNIOL-VILLARD int rc; 5361378df79SJean-Christophe PLAGNIOL-VILLARD char * sn; 5371378df79SJean-Christophe PLAGNIOL-VILLARD char * tt; 5381378df79SJean-Christophe PLAGNIOL-VILLARD int snlen; 5391378df79SJean-Christophe PLAGNIOL-VILLARD 5401378df79SJean-Christophe PLAGNIOL-VILLARD /* Ger seiral number */ 5411378df79SJean-Christophe PLAGNIOL-VILLARD if (!(sn = getenv("serial#"))) { 5421378df79SJean-Christophe PLAGNIOL-VILLARD sn = "000000000000"; 5431378df79SJean-Christophe PLAGNIOL-VILLARD } 5441378df79SJean-Christophe PLAGNIOL-VILLARD snlen = strlen(sn); 5451378df79SJean-Christophe PLAGNIOL-VILLARD if (snlen > sizeof(serial_number) - 1) { 546b64f190bSWolfgang Denk printf ("Warning: serial number %s is too long (%d > %lu)\n", 547b64f190bSWolfgang Denk sn, snlen, (ulong)(sizeof(serial_number) - 1)); 5481378df79SJean-Christophe PLAGNIOL-VILLARD snlen = sizeof(serial_number) - 1; 5491378df79SJean-Christophe PLAGNIOL-VILLARD } 5501378df79SJean-Christophe PLAGNIOL-VILLARD memcpy (serial_number, sn, snlen); 5511378df79SJean-Christophe PLAGNIOL-VILLARD serial_number[snlen] = '\0'; 5521378df79SJean-Christophe PLAGNIOL-VILLARD 5531378df79SJean-Christophe PLAGNIOL-VILLARD /* Decide on which type of UDC device to be. 5541378df79SJean-Christophe PLAGNIOL-VILLARD */ 5551378df79SJean-Christophe PLAGNIOL-VILLARD 5561378df79SJean-Christophe PLAGNIOL-VILLARD if(!(tt = getenv("usbtty"))) { 5571378df79SJean-Christophe PLAGNIOL-VILLARD tt = "generic"; 5581378df79SJean-Christophe PLAGNIOL-VILLARD } 5591378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_init_terminal_type(strcmp(tt,"cdc_acm")); 5601378df79SJean-Christophe PLAGNIOL-VILLARD 5611378df79SJean-Christophe PLAGNIOL-VILLARD /* prepare buffers... */ 5621378df79SJean-Christophe PLAGNIOL-VILLARD buf_init (&usbtty_input, USBTTY_BUFFER_SIZE); 5631378df79SJean-Christophe PLAGNIOL-VILLARD buf_init (&usbtty_output, USBTTY_BUFFER_SIZE); 5641378df79SJean-Christophe PLAGNIOL-VILLARD 5651378df79SJean-Christophe PLAGNIOL-VILLARD /* Now, set up USB controller and infrastructure */ 5661378df79SJean-Christophe PLAGNIOL-VILLARD udc_init (); /* Basic USB initialization */ 5671378df79SJean-Christophe PLAGNIOL-VILLARD 5681378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_init_strings (); 5691378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_init_instances (); 5701378df79SJean-Christophe PLAGNIOL-VILLARD 571241d9a61SStefan Herbrechtsmeier usbtty_init_endpoints (); 572241d9a61SStefan Herbrechtsmeier 5731378df79SJean-Christophe PLAGNIOL-VILLARD udc_startup_events (device_instance);/* Enable dev, init udc pointers */ 5741378df79SJean-Christophe PLAGNIOL-VILLARD udc_connect (); /* Enable pullup for host detection */ 5751378df79SJean-Christophe PLAGNIOL-VILLARD 5761378df79SJean-Christophe PLAGNIOL-VILLARD /* Device initialization */ 5771378df79SJean-Christophe PLAGNIOL-VILLARD memset (&usbttydev, 0, sizeof (usbttydev)); 5781378df79SJean-Christophe PLAGNIOL-VILLARD 5791378df79SJean-Christophe PLAGNIOL-VILLARD strcpy (usbttydev.name, "usbtty"); 5801378df79SJean-Christophe PLAGNIOL-VILLARD usbttydev.ext = 0; /* No extensions */ 5811378df79SJean-Christophe PLAGNIOL-VILLARD usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT; 5821378df79SJean-Christophe PLAGNIOL-VILLARD usbttydev.tstc = usbtty_tstc; /* 'tstc' function */ 5831378df79SJean-Christophe PLAGNIOL-VILLARD usbttydev.getc = usbtty_getc; /* 'getc' function */ 5841378df79SJean-Christophe PLAGNIOL-VILLARD usbttydev.putc = usbtty_putc; /* 'putc' function */ 5851378df79SJean-Christophe PLAGNIOL-VILLARD usbttydev.puts = usbtty_puts; /* 'puts' function */ 5861378df79SJean-Christophe PLAGNIOL-VILLARD 58752cb4d4fSJean-Christophe PLAGNIOL-VILLARD rc = stdio_register (&usbttydev); 5881378df79SJean-Christophe PLAGNIOL-VILLARD 5891378df79SJean-Christophe PLAGNIOL-VILLARD return (rc == 0) ? 1 : rc; 5901378df79SJean-Christophe PLAGNIOL-VILLARD } 5911378df79SJean-Christophe PLAGNIOL-VILLARD 5921378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_strings (void) 5931378df79SJean-Christophe PLAGNIOL-VILLARD { 5941378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_string_descriptor *string; 5951378df79SJean-Christophe PLAGNIOL-VILLARD 5961378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_string_table[STR_LANG] = 5971378df79SJean-Christophe PLAGNIOL-VILLARD (struct usb_string_descriptor*)wstrLang; 5981378df79SJean-Christophe PLAGNIOL-VILLARD 5991378df79SJean-Christophe PLAGNIOL-VILLARD string = (struct usb_string_descriptor *) wstrManufacturer; 6001378df79SJean-Christophe PLAGNIOL-VILLARD string->bLength = sizeof(wstrManufacturer); 6011378df79SJean-Christophe PLAGNIOL-VILLARD string->bDescriptorType = USB_DT_STRING; 6021378df79SJean-Christophe PLAGNIOL-VILLARD str2wide (CONFIG_USBD_MANUFACTURER, string->wData); 6031378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_string_table[STR_MANUFACTURER]=string; 6041378df79SJean-Christophe PLAGNIOL-VILLARD 6051378df79SJean-Christophe PLAGNIOL-VILLARD 6061378df79SJean-Christophe PLAGNIOL-VILLARD string = (struct usb_string_descriptor *) wstrProduct; 6071378df79SJean-Christophe PLAGNIOL-VILLARD string->bLength = sizeof(wstrProduct); 6081378df79SJean-Christophe PLAGNIOL-VILLARD string->bDescriptorType = USB_DT_STRING; 6091378df79SJean-Christophe PLAGNIOL-VILLARD str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData); 6101378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_string_table[STR_PRODUCT]=string; 6111378df79SJean-Christophe PLAGNIOL-VILLARD 6121378df79SJean-Christophe PLAGNIOL-VILLARD 6131378df79SJean-Christophe PLAGNIOL-VILLARD string = (struct usb_string_descriptor *) wstrSerial; 6141378df79SJean-Christophe PLAGNIOL-VILLARD string->bLength = sizeof(serial_number); 6151378df79SJean-Christophe PLAGNIOL-VILLARD string->bDescriptorType = USB_DT_STRING; 6161378df79SJean-Christophe PLAGNIOL-VILLARD str2wide (serial_number, string->wData); 6171378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_string_table[STR_SERIAL]=string; 6181378df79SJean-Christophe PLAGNIOL-VILLARD 6191378df79SJean-Christophe PLAGNIOL-VILLARD 6201378df79SJean-Christophe PLAGNIOL-VILLARD string = (struct usb_string_descriptor *) wstrConfiguration; 6211378df79SJean-Christophe PLAGNIOL-VILLARD string->bLength = sizeof(wstrConfiguration); 6221378df79SJean-Christophe PLAGNIOL-VILLARD string->bDescriptorType = USB_DT_STRING; 6231378df79SJean-Christophe PLAGNIOL-VILLARD str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData); 6241378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_string_table[STR_CONFIG]=string; 6251378df79SJean-Christophe PLAGNIOL-VILLARD 6261378df79SJean-Christophe PLAGNIOL-VILLARD 6271378df79SJean-Christophe PLAGNIOL-VILLARD string = (struct usb_string_descriptor *) wstrDataInterface; 6281378df79SJean-Christophe PLAGNIOL-VILLARD string->bLength = sizeof(wstrDataInterface); 6291378df79SJean-Christophe PLAGNIOL-VILLARD string->bDescriptorType = USB_DT_STRING; 6301378df79SJean-Christophe PLAGNIOL-VILLARD str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData); 6311378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_string_table[STR_DATA_INTERFACE]=string; 6321378df79SJean-Christophe PLAGNIOL-VILLARD 6331378df79SJean-Christophe PLAGNIOL-VILLARD string = (struct usb_string_descriptor *) wstrCtrlInterface; 6341378df79SJean-Christophe PLAGNIOL-VILLARD string->bLength = sizeof(wstrCtrlInterface); 6351378df79SJean-Christophe PLAGNIOL-VILLARD string->bDescriptorType = USB_DT_STRING; 6361378df79SJean-Christophe PLAGNIOL-VILLARD str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData); 6371378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_string_table[STR_CTRL_INTERFACE]=string; 6381378df79SJean-Christophe PLAGNIOL-VILLARD 6391378df79SJean-Christophe PLAGNIOL-VILLARD /* Now, initialize the string table for ep0 handling */ 6401378df79SJean-Christophe PLAGNIOL-VILLARD usb_strings = usbtty_string_table; 6411378df79SJean-Christophe PLAGNIOL-VILLARD } 6421378df79SJean-Christophe PLAGNIOL-VILLARD 643b2fb47f1STom Rini #define init_wMaxPacketSize(x) le16_to_cpu(get_unaligned(\ 644b2fb47f1STom Rini &ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize)); 645b2fb47f1STom Rini 6461378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_instances (void) 6471378df79SJean-Christophe PLAGNIOL-VILLARD { 6481378df79SJean-Christophe PLAGNIOL-VILLARD int i; 6491378df79SJean-Christophe PLAGNIOL-VILLARD 6501378df79SJean-Christophe PLAGNIOL-VILLARD /* initialize device instance */ 6511378df79SJean-Christophe PLAGNIOL-VILLARD memset (device_instance, 0, sizeof (struct usb_device_instance)); 6521378df79SJean-Christophe PLAGNIOL-VILLARD device_instance->device_state = STATE_INIT; 6531378df79SJean-Christophe PLAGNIOL-VILLARD device_instance->device_descriptor = &device_descriptor; 654f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS) 655f9da0f89SVipin KUMAR device_instance->qualifier_descriptor = &qualifier_descriptor; 656f9da0f89SVipin KUMAR #endif 6571378df79SJean-Christophe PLAGNIOL-VILLARD device_instance->event = usbtty_event_handler; 6581378df79SJean-Christophe PLAGNIOL-VILLARD device_instance->cdc_recv_setup = usbtty_cdc_setup; 6591378df79SJean-Christophe PLAGNIOL-VILLARD device_instance->bus = bus_instance; 6601378df79SJean-Christophe PLAGNIOL-VILLARD device_instance->configurations = NUM_CONFIGS; 6611378df79SJean-Christophe PLAGNIOL-VILLARD device_instance->configuration_instance_array = config_instance; 6621378df79SJean-Christophe PLAGNIOL-VILLARD 6631378df79SJean-Christophe PLAGNIOL-VILLARD /* initialize bus instance */ 6641378df79SJean-Christophe PLAGNIOL-VILLARD memset (bus_instance, 0, sizeof (struct usb_bus_instance)); 6651378df79SJean-Christophe PLAGNIOL-VILLARD bus_instance->device = device_instance; 6661378df79SJean-Christophe PLAGNIOL-VILLARD bus_instance->endpoint_array = endpoint_instance; 6671378df79SJean-Christophe PLAGNIOL-VILLARD bus_instance->max_endpoints = 1; 6681378df79SJean-Christophe PLAGNIOL-VILLARD bus_instance->maxpacketsize = 64; 6691378df79SJean-Christophe PLAGNIOL-VILLARD bus_instance->serial_number_str = serial_number; 6701378df79SJean-Christophe PLAGNIOL-VILLARD 6711378df79SJean-Christophe PLAGNIOL-VILLARD /* configuration instance */ 6721378df79SJean-Christophe PLAGNIOL-VILLARD memset (config_instance, 0, 6731378df79SJean-Christophe PLAGNIOL-VILLARD sizeof (struct usb_configuration_instance)); 6741378df79SJean-Christophe PLAGNIOL-VILLARD config_instance->interfaces = interface_count; 6751378df79SJean-Christophe PLAGNIOL-VILLARD config_instance->configuration_descriptor = configuration_descriptor; 6761378df79SJean-Christophe PLAGNIOL-VILLARD config_instance->interface_instance_array = interface_instance; 6771378df79SJean-Christophe PLAGNIOL-VILLARD 6781378df79SJean-Christophe PLAGNIOL-VILLARD /* interface instance */ 6791378df79SJean-Christophe PLAGNIOL-VILLARD memset (interface_instance, 0, 6801378df79SJean-Christophe PLAGNIOL-VILLARD sizeof (struct usb_interface_instance)); 6811378df79SJean-Christophe PLAGNIOL-VILLARD interface_instance->alternates = 1; 6821378df79SJean-Christophe PLAGNIOL-VILLARD interface_instance->alternates_instance_array = alternate_instance; 6831378df79SJean-Christophe PLAGNIOL-VILLARD 6841378df79SJean-Christophe PLAGNIOL-VILLARD /* alternates instance */ 6851378df79SJean-Christophe PLAGNIOL-VILLARD memset (alternate_instance, 0, 6861378df79SJean-Christophe PLAGNIOL-VILLARD sizeof (struct usb_alternate_instance)); 6871378df79SJean-Christophe PLAGNIOL-VILLARD alternate_instance->interface_descriptor = interface_descriptors; 6881378df79SJean-Christophe PLAGNIOL-VILLARD alternate_instance->endpoints = NUM_ENDPOINTS; 6891378df79SJean-Christophe PLAGNIOL-VILLARD alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs; 6901378df79SJean-Christophe PLAGNIOL-VILLARD 6911378df79SJean-Christophe PLAGNIOL-VILLARD /* endpoint instances */ 6921378df79SJean-Christophe PLAGNIOL-VILLARD memset (&endpoint_instance[0], 0, 6931378df79SJean-Christophe PLAGNIOL-VILLARD sizeof (struct usb_endpoint_instance)); 6941378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[0].endpoint_address = 0; 6951378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE; 6961378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL; 6971378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE; 6981378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL; 6991378df79SJean-Christophe PLAGNIOL-VILLARD udc_setup_ep (device_instance, 0, &endpoint_instance[0]); 7001378df79SJean-Christophe PLAGNIOL-VILLARD 7011378df79SJean-Christophe PLAGNIOL-VILLARD for (i = 1; i <= NUM_ENDPOINTS; i++) { 7021378df79SJean-Christophe PLAGNIOL-VILLARD memset (&endpoint_instance[i], 0, 7031378df79SJean-Christophe PLAGNIOL-VILLARD sizeof (struct usb_endpoint_instance)); 7041378df79SJean-Christophe PLAGNIOL-VILLARD 7051378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[i].endpoint_address = 7061378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[i - 1]->bEndpointAddress; 7071378df79SJean-Christophe PLAGNIOL-VILLARD 7081378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[i].rcv_attributes = 7091378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[i - 1]->bmAttributes; 7101378df79SJean-Christophe PLAGNIOL-VILLARD 711b2fb47f1STom Rini endpoint_instance[i].rcv_packetSize = init_wMaxPacketSize(i); 7121378df79SJean-Christophe PLAGNIOL-VILLARD 7131378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[i].tx_attributes = 7141378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[i - 1]->bmAttributes; 7151378df79SJean-Christophe PLAGNIOL-VILLARD 716b2fb47f1STom Rini endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i); 7171378df79SJean-Christophe PLAGNIOL-VILLARD 7181378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[i].tx_attributes = 7191378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[i - 1]->bmAttributes; 7201378df79SJean-Christophe PLAGNIOL-VILLARD 7211378df79SJean-Christophe PLAGNIOL-VILLARD urb_link_init (&endpoint_instance[i].rcv); 7221378df79SJean-Christophe PLAGNIOL-VILLARD urb_link_init (&endpoint_instance[i].rdy); 7231378df79SJean-Christophe PLAGNIOL-VILLARD urb_link_init (&endpoint_instance[i].tx); 7241378df79SJean-Christophe PLAGNIOL-VILLARD urb_link_init (&endpoint_instance[i].done); 7251378df79SJean-Christophe PLAGNIOL-VILLARD 7261378df79SJean-Christophe PLAGNIOL-VILLARD if (endpoint_instance[i].endpoint_address & USB_DIR_IN) 7271378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[i].tx_urb = 7281378df79SJean-Christophe PLAGNIOL-VILLARD usbd_alloc_urb (device_instance, 7291378df79SJean-Christophe PLAGNIOL-VILLARD &endpoint_instance[i]); 7301378df79SJean-Christophe PLAGNIOL-VILLARD else 7311378df79SJean-Christophe PLAGNIOL-VILLARD endpoint_instance[i].rcv_urb = 7321378df79SJean-Christophe PLAGNIOL-VILLARD usbd_alloc_urb (device_instance, 7331378df79SJean-Christophe PLAGNIOL-VILLARD &endpoint_instance[i]); 7341378df79SJean-Christophe PLAGNIOL-VILLARD } 7351378df79SJean-Christophe PLAGNIOL-VILLARD } 7361378df79SJean-Christophe PLAGNIOL-VILLARD 7371378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_endpoints (void) 7381378df79SJean-Christophe PLAGNIOL-VILLARD { 7391378df79SJean-Christophe PLAGNIOL-VILLARD int i; 7401378df79SJean-Christophe PLAGNIOL-VILLARD 7411378df79SJean-Christophe PLAGNIOL-VILLARD bus_instance->max_endpoints = NUM_ENDPOINTS + 1; 7421378df79SJean-Christophe PLAGNIOL-VILLARD for (i = 1; i <= NUM_ENDPOINTS; i++) { 7431378df79SJean-Christophe PLAGNIOL-VILLARD udc_setup_ep (device_instance, i, &endpoint_instance[i]); 7441378df79SJean-Christophe PLAGNIOL-VILLARD } 7451378df79SJean-Christophe PLAGNIOL-VILLARD } 7461378df79SJean-Christophe PLAGNIOL-VILLARD 7471378df79SJean-Christophe PLAGNIOL-VILLARD /* usbtty_init_terminal_type 7481378df79SJean-Christophe PLAGNIOL-VILLARD * 7491378df79SJean-Christophe PLAGNIOL-VILLARD * Do some late binding for our device type. 7501378df79SJean-Christophe PLAGNIOL-VILLARD */ 7511378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_terminal_type(short type) 7521378df79SJean-Christophe PLAGNIOL-VILLARD { 7531378df79SJean-Christophe PLAGNIOL-VILLARD switch(type){ 7541378df79SJean-Christophe PLAGNIOL-VILLARD /* CDC ACM */ 7551378df79SJean-Christophe PLAGNIOL-VILLARD case 0: 7561378df79SJean-Christophe PLAGNIOL-VILLARD /* Assign endpoint descriptors */ 7571378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[0] = 7581378df79SJean-Christophe PLAGNIOL-VILLARD &acm_configuration_descriptors[0].notification_endpoint; 7591378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[1] = 7601378df79SJean-Christophe PLAGNIOL-VILLARD &acm_configuration_descriptors[0].data_endpoints[0]; 7611378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[2] = 7621378df79SJean-Christophe PLAGNIOL-VILLARD &acm_configuration_descriptors[0].data_endpoints[1]; 7631378df79SJean-Christophe PLAGNIOL-VILLARD 7641378df79SJean-Christophe PLAGNIOL-VILLARD /* Enumerate Device Descriptor */ 7651378df79SJean-Christophe PLAGNIOL-VILLARD device_descriptor.bDeviceClass = 7661378df79SJean-Christophe PLAGNIOL-VILLARD COMMUNICATIONS_DEVICE_CLASS; 7671378df79SJean-Christophe PLAGNIOL-VILLARD device_descriptor.idProduct = 7681378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM); 7691378df79SJean-Christophe PLAGNIOL-VILLARD 770f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS) 771f9da0f89SVipin KUMAR qualifier_descriptor.bDeviceClass = 772f9da0f89SVipin KUMAR COMMUNICATIONS_DEVICE_CLASS; 773f9da0f89SVipin KUMAR #endif 7741378df79SJean-Christophe PLAGNIOL-VILLARD /* Assign endpoint indices */ 7751378df79SJean-Christophe PLAGNIOL-VILLARD tx_endpoint = ACM_TX_ENDPOINT; 7761378df79SJean-Christophe PLAGNIOL-VILLARD rx_endpoint = ACM_RX_ENDPOINT; 7771378df79SJean-Christophe PLAGNIOL-VILLARD 7781378df79SJean-Christophe PLAGNIOL-VILLARD /* Configuration Descriptor */ 7791378df79SJean-Christophe PLAGNIOL-VILLARD configuration_descriptor = 7801378df79SJean-Christophe PLAGNIOL-VILLARD (struct usb_configuration_descriptor*) 7811378df79SJean-Christophe PLAGNIOL-VILLARD &acm_configuration_descriptors; 7821378df79SJean-Christophe PLAGNIOL-VILLARD 7831378df79SJean-Christophe PLAGNIOL-VILLARD /* Interface count */ 7841378df79SJean-Christophe PLAGNIOL-VILLARD interface_count = NUM_ACM_INTERFACES; 7851378df79SJean-Christophe PLAGNIOL-VILLARD break; 7861378df79SJean-Christophe PLAGNIOL-VILLARD 7871378df79SJean-Christophe PLAGNIOL-VILLARD /* BULK IN/OUT & Default */ 7881378df79SJean-Christophe PLAGNIOL-VILLARD case 1: 7891378df79SJean-Christophe PLAGNIOL-VILLARD default: 7901378df79SJean-Christophe PLAGNIOL-VILLARD /* Assign endpoint descriptors */ 7911378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[0] = 7921378df79SJean-Christophe PLAGNIOL-VILLARD &gserial_configuration_descriptors[0].data_endpoints[0]; 7931378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[1] = 7941378df79SJean-Christophe PLAGNIOL-VILLARD &gserial_configuration_descriptors[0].data_endpoints[1]; 7951378df79SJean-Christophe PLAGNIOL-VILLARD ep_descriptor_ptrs[2] = 7961378df79SJean-Christophe PLAGNIOL-VILLARD &gserial_configuration_descriptors[0].data_endpoints[2]; 7971378df79SJean-Christophe PLAGNIOL-VILLARD 7981378df79SJean-Christophe PLAGNIOL-VILLARD /* Enumerate Device Descriptor */ 7991378df79SJean-Christophe PLAGNIOL-VILLARD device_descriptor.bDeviceClass = 0xFF; 8001378df79SJean-Christophe PLAGNIOL-VILLARD device_descriptor.idProduct = 8011378df79SJean-Christophe PLAGNIOL-VILLARD cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL); 802f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS) 803f9da0f89SVipin KUMAR qualifier_descriptor.bDeviceClass = 0xFF; 804f9da0f89SVipin KUMAR #endif 8051378df79SJean-Christophe PLAGNIOL-VILLARD /* Assign endpoint indices */ 8061378df79SJean-Christophe PLAGNIOL-VILLARD tx_endpoint = GSERIAL_TX_ENDPOINT; 8071378df79SJean-Christophe PLAGNIOL-VILLARD rx_endpoint = GSERIAL_RX_ENDPOINT; 8081378df79SJean-Christophe PLAGNIOL-VILLARD 8091378df79SJean-Christophe PLAGNIOL-VILLARD /* Configuration Descriptor */ 8101378df79SJean-Christophe PLAGNIOL-VILLARD configuration_descriptor = 8111378df79SJean-Christophe PLAGNIOL-VILLARD (struct usb_configuration_descriptor*) 8121378df79SJean-Christophe PLAGNIOL-VILLARD &gserial_configuration_descriptors; 8131378df79SJean-Christophe PLAGNIOL-VILLARD 8141378df79SJean-Christophe PLAGNIOL-VILLARD /* Interface count */ 8151378df79SJean-Christophe PLAGNIOL-VILLARD interface_count = NUM_GSERIAL_INTERFACES; 8161378df79SJean-Christophe PLAGNIOL-VILLARD break; 8171378df79SJean-Christophe PLAGNIOL-VILLARD } 8181378df79SJean-Christophe PLAGNIOL-VILLARD } 8191378df79SJean-Christophe PLAGNIOL-VILLARD 8201378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/ 8211378df79SJean-Christophe PLAGNIOL-VILLARD 8221378df79SJean-Christophe PLAGNIOL-VILLARD static struct urb *next_urb (struct usb_device_instance *device, 8231378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_endpoint_instance *endpoint) 8241378df79SJean-Christophe PLAGNIOL-VILLARD { 8251378df79SJean-Christophe PLAGNIOL-VILLARD struct urb *current_urb = NULL; 8261378df79SJean-Christophe PLAGNIOL-VILLARD int space; 8271378df79SJean-Christophe PLAGNIOL-VILLARD 8281378df79SJean-Christophe PLAGNIOL-VILLARD /* If there's a queue, then we should add to the last urb */ 8291378df79SJean-Christophe PLAGNIOL-VILLARD if (!endpoint->tx_queue) { 8301378df79SJean-Christophe PLAGNIOL-VILLARD current_urb = endpoint->tx_urb; 8311378df79SJean-Christophe PLAGNIOL-VILLARD } else { 8321378df79SJean-Christophe PLAGNIOL-VILLARD /* Last urb from tx chain */ 8331378df79SJean-Christophe PLAGNIOL-VILLARD current_urb = 8341378df79SJean-Christophe PLAGNIOL-VILLARD p2surround (struct urb, link, endpoint->tx.prev); 8351378df79SJean-Christophe PLAGNIOL-VILLARD } 8361378df79SJean-Christophe PLAGNIOL-VILLARD 8371378df79SJean-Christophe PLAGNIOL-VILLARD /* Make sure this one has enough room */ 8381378df79SJean-Christophe PLAGNIOL-VILLARD space = current_urb->buffer_length - current_urb->actual_length; 8391378df79SJean-Christophe PLAGNIOL-VILLARD if (space > 0) { 8401378df79SJean-Christophe PLAGNIOL-VILLARD return current_urb; 8411378df79SJean-Christophe PLAGNIOL-VILLARD } else { /* No space here */ 8421378df79SJean-Christophe PLAGNIOL-VILLARD /* First look at done list */ 8431378df79SJean-Christophe PLAGNIOL-VILLARD current_urb = first_urb_detached (&endpoint->done); 8441378df79SJean-Christophe PLAGNIOL-VILLARD if (!current_urb) { 8451378df79SJean-Christophe PLAGNIOL-VILLARD current_urb = usbd_alloc_urb (device, endpoint); 8461378df79SJean-Christophe PLAGNIOL-VILLARD } 8471378df79SJean-Christophe PLAGNIOL-VILLARD 8481378df79SJean-Christophe PLAGNIOL-VILLARD urb_append (&endpoint->tx, current_urb); 8491378df79SJean-Christophe PLAGNIOL-VILLARD endpoint->tx_queue++; 8501378df79SJean-Christophe PLAGNIOL-VILLARD } 8511378df79SJean-Christophe PLAGNIOL-VILLARD return current_urb; 8521378df79SJean-Christophe PLAGNIOL-VILLARD } 8531378df79SJean-Christophe PLAGNIOL-VILLARD 8541378df79SJean-Christophe PLAGNIOL-VILLARD static int write_buffer (circbuf_t * buf) 8551378df79SJean-Christophe PLAGNIOL-VILLARD { 8561378df79SJean-Christophe PLAGNIOL-VILLARD if (!usbtty_configured ()) { 8571378df79SJean-Christophe PLAGNIOL-VILLARD return 0; 8581378df79SJean-Christophe PLAGNIOL-VILLARD } 8591378df79SJean-Christophe PLAGNIOL-VILLARD 8601378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_endpoint_instance *endpoint = 8611378df79SJean-Christophe PLAGNIOL-VILLARD &endpoint_instance[tx_endpoint]; 8621378df79SJean-Christophe PLAGNIOL-VILLARD struct urb *current_urb = NULL; 8631378df79SJean-Christophe PLAGNIOL-VILLARD 8641378df79SJean-Christophe PLAGNIOL-VILLARD current_urb = next_urb (device_instance, endpoint); 8651378df79SJean-Christophe PLAGNIOL-VILLARD /* TX data still exists - send it now 8661378df79SJean-Christophe PLAGNIOL-VILLARD */ 8671378df79SJean-Christophe PLAGNIOL-VILLARD if(endpoint->sent < current_urb->actual_length){ 8681378df79SJean-Christophe PLAGNIOL-VILLARD if(udc_endpoint_write (endpoint)){ 8691378df79SJean-Christophe PLAGNIOL-VILLARD /* Write pre-empted by RX */ 8701378df79SJean-Christophe PLAGNIOL-VILLARD return -1; 8711378df79SJean-Christophe PLAGNIOL-VILLARD } 8721378df79SJean-Christophe PLAGNIOL-VILLARD } 8731378df79SJean-Christophe PLAGNIOL-VILLARD 8741378df79SJean-Christophe PLAGNIOL-VILLARD if (buf->size) { 8751378df79SJean-Christophe PLAGNIOL-VILLARD char *dest; 8761378df79SJean-Christophe PLAGNIOL-VILLARD 8771378df79SJean-Christophe PLAGNIOL-VILLARD int space_avail; 8781378df79SJean-Christophe PLAGNIOL-VILLARD int popnum, popped; 8791378df79SJean-Christophe PLAGNIOL-VILLARD int total = 0; 8801378df79SJean-Christophe PLAGNIOL-VILLARD 8811378df79SJean-Christophe PLAGNIOL-VILLARD /* Break buffer into urb sized pieces, 8821378df79SJean-Christophe PLAGNIOL-VILLARD * and link each to the endpoint 8831378df79SJean-Christophe PLAGNIOL-VILLARD */ 8841378df79SJean-Christophe PLAGNIOL-VILLARD while (buf->size > 0) { 8851378df79SJean-Christophe PLAGNIOL-VILLARD 8861378df79SJean-Christophe PLAGNIOL-VILLARD if (!current_urb) { 8871378df79SJean-Christophe PLAGNIOL-VILLARD TTYERR ("current_urb is NULL, buf->size %d\n", 8881378df79SJean-Christophe PLAGNIOL-VILLARD buf->size); 8891378df79SJean-Christophe PLAGNIOL-VILLARD return total; 8901378df79SJean-Christophe PLAGNIOL-VILLARD } 8911378df79SJean-Christophe PLAGNIOL-VILLARD 8921378df79SJean-Christophe PLAGNIOL-VILLARD dest = (char*)current_urb->buffer + 8931378df79SJean-Christophe PLAGNIOL-VILLARD current_urb->actual_length; 8941378df79SJean-Christophe PLAGNIOL-VILLARD 8951378df79SJean-Christophe PLAGNIOL-VILLARD space_avail = 8961378df79SJean-Christophe PLAGNIOL-VILLARD current_urb->buffer_length - 8971378df79SJean-Christophe PLAGNIOL-VILLARD current_urb->actual_length; 8981378df79SJean-Christophe PLAGNIOL-VILLARD popnum = MIN (space_avail, buf->size); 8991378df79SJean-Christophe PLAGNIOL-VILLARD if (popnum == 0) 9001378df79SJean-Christophe PLAGNIOL-VILLARD break; 9011378df79SJean-Christophe PLAGNIOL-VILLARD 9021378df79SJean-Christophe PLAGNIOL-VILLARD popped = buf_pop (buf, dest, popnum); 9031378df79SJean-Christophe PLAGNIOL-VILLARD if (popped == 0) 9041378df79SJean-Christophe PLAGNIOL-VILLARD break; 9051378df79SJean-Christophe PLAGNIOL-VILLARD current_urb->actual_length += popped; 9061378df79SJean-Christophe PLAGNIOL-VILLARD total += popped; 9071378df79SJean-Christophe PLAGNIOL-VILLARD 9081378df79SJean-Christophe PLAGNIOL-VILLARD /* If endpoint->last == 0, then transfers have 9091378df79SJean-Christophe PLAGNIOL-VILLARD * not started on this endpoint 9101378df79SJean-Christophe PLAGNIOL-VILLARD */ 9111378df79SJean-Christophe PLAGNIOL-VILLARD if (endpoint->last == 0) { 9121378df79SJean-Christophe PLAGNIOL-VILLARD if(udc_endpoint_write (endpoint)){ 9131378df79SJean-Christophe PLAGNIOL-VILLARD /* Write pre-empted by RX */ 9141378df79SJean-Christophe PLAGNIOL-VILLARD return -1; 9151378df79SJean-Christophe PLAGNIOL-VILLARD } 9161378df79SJean-Christophe PLAGNIOL-VILLARD } 9171378df79SJean-Christophe PLAGNIOL-VILLARD 9181378df79SJean-Christophe PLAGNIOL-VILLARD }/* end while */ 9191378df79SJean-Christophe PLAGNIOL-VILLARD return total; 9201378df79SJean-Christophe PLAGNIOL-VILLARD } 9211378df79SJean-Christophe PLAGNIOL-VILLARD 9221378df79SJean-Christophe PLAGNIOL-VILLARD return 0; 9231378df79SJean-Christophe PLAGNIOL-VILLARD } 9241378df79SJean-Christophe PLAGNIOL-VILLARD 9251378df79SJean-Christophe PLAGNIOL-VILLARD static int fill_buffer (circbuf_t * buf) 9261378df79SJean-Christophe PLAGNIOL-VILLARD { 9271378df79SJean-Christophe PLAGNIOL-VILLARD struct usb_endpoint_instance *endpoint = 9281378df79SJean-Christophe PLAGNIOL-VILLARD &endpoint_instance[rx_endpoint]; 9291378df79SJean-Christophe PLAGNIOL-VILLARD 9301378df79SJean-Christophe PLAGNIOL-VILLARD if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) { 9311378df79SJean-Christophe PLAGNIOL-VILLARD unsigned int nb = 0; 9321378df79SJean-Christophe PLAGNIOL-VILLARD char *src = (char *) endpoint->rcv_urb->buffer; 9331378df79SJean-Christophe PLAGNIOL-VILLARD unsigned int rx_avail = buf->totalsize - buf->size; 9341378df79SJean-Christophe PLAGNIOL-VILLARD 9351378df79SJean-Christophe PLAGNIOL-VILLARD if(rx_avail >= endpoint->rcv_urb->actual_length){ 9361378df79SJean-Christophe PLAGNIOL-VILLARD 9371378df79SJean-Christophe PLAGNIOL-VILLARD nb = endpoint->rcv_urb->actual_length; 9381378df79SJean-Christophe PLAGNIOL-VILLARD buf_push (buf, src, nb); 9391378df79SJean-Christophe PLAGNIOL-VILLARD endpoint->rcv_urb->actual_length = 0; 9401378df79SJean-Christophe PLAGNIOL-VILLARD 9411378df79SJean-Christophe PLAGNIOL-VILLARD } 9421378df79SJean-Christophe PLAGNIOL-VILLARD return nb; 9431378df79SJean-Christophe PLAGNIOL-VILLARD } 9441378df79SJean-Christophe PLAGNIOL-VILLARD return 0; 9451378df79SJean-Christophe PLAGNIOL-VILLARD } 9461378df79SJean-Christophe PLAGNIOL-VILLARD 9471378df79SJean-Christophe PLAGNIOL-VILLARD static int usbtty_configured (void) 9481378df79SJean-Christophe PLAGNIOL-VILLARD { 9491378df79SJean-Christophe PLAGNIOL-VILLARD return usbtty_configured_flag; 9501378df79SJean-Christophe PLAGNIOL-VILLARD } 9511378df79SJean-Christophe PLAGNIOL-VILLARD 9521378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/ 9531378df79SJean-Christophe PLAGNIOL-VILLARD 9541378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_event_handler (struct usb_device_instance *device, 9551378df79SJean-Christophe PLAGNIOL-VILLARD usb_device_event_t event, int data) 9561378df79SJean-Christophe PLAGNIOL-VILLARD { 957f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS) 958f9da0f89SVipin KUMAR int i; 959f9da0f89SVipin KUMAR #endif 9601378df79SJean-Christophe PLAGNIOL-VILLARD switch (event) { 9611378df79SJean-Christophe PLAGNIOL-VILLARD case DEVICE_RESET: 9621378df79SJean-Christophe PLAGNIOL-VILLARD case DEVICE_BUS_INACTIVE: 9631378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_configured_flag = 0; 9641378df79SJean-Christophe PLAGNIOL-VILLARD break; 9651378df79SJean-Christophe PLAGNIOL-VILLARD case DEVICE_CONFIGURED: 9661378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_configured_flag = 1; 9671378df79SJean-Christophe PLAGNIOL-VILLARD break; 9681378df79SJean-Christophe PLAGNIOL-VILLARD 9691378df79SJean-Christophe PLAGNIOL-VILLARD case DEVICE_ADDRESS_ASSIGNED: 970f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS) 971f9da0f89SVipin KUMAR /* 972f9da0f89SVipin KUMAR * is_usbd_high_speed routine needs to be defined by 973f9da0f89SVipin KUMAR * specific gadget driver 974f9da0f89SVipin KUMAR * It returns TRUE if device enumerates at High speed 975f9da0f89SVipin KUMAR * Retuns FALSE otherwise 976f9da0f89SVipin KUMAR */ 977f9da0f89SVipin KUMAR for (i = 0; i < NUM_ENDPOINTS; i++) { 978f9da0f89SVipin KUMAR if (((ep_descriptor_ptrs[i]->bmAttributes & 979f9da0f89SVipin KUMAR USB_ENDPOINT_XFERTYPE_MASK) == 980f9da0f89SVipin KUMAR USB_ENDPOINT_XFER_BULK) 981f9da0f89SVipin KUMAR && is_usbd_high_speed()) { 982f9da0f89SVipin KUMAR 983f9da0f89SVipin KUMAR ep_descriptor_ptrs[i]->wMaxPacketSize = 984f9da0f89SVipin KUMAR CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE; 985f9da0f89SVipin KUMAR } 986f9da0f89SVipin KUMAR 987f9da0f89SVipin KUMAR endpoint_instance[i + 1].tx_packetSize = 988f9da0f89SVipin KUMAR ep_descriptor_ptrs[i]->wMaxPacketSize; 989f9da0f89SVipin KUMAR endpoint_instance[i + 1].rcv_packetSize = 990f9da0f89SVipin KUMAR ep_descriptor_ptrs[i]->wMaxPacketSize; 991f9da0f89SVipin KUMAR } 992f9da0f89SVipin KUMAR #endif 9931378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_init_endpoints (); 9941378df79SJean-Christophe PLAGNIOL-VILLARD 9951378df79SJean-Christophe PLAGNIOL-VILLARD default: 9961378df79SJean-Christophe PLAGNIOL-VILLARD break; 9971378df79SJean-Christophe PLAGNIOL-VILLARD } 9981378df79SJean-Christophe PLAGNIOL-VILLARD } 9991378df79SJean-Christophe PLAGNIOL-VILLARD 10001378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/ 10011378df79SJean-Christophe PLAGNIOL-VILLARD 10021378df79SJean-Christophe PLAGNIOL-VILLARD int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb) 10031378df79SJean-Christophe PLAGNIOL-VILLARD { 10041378df79SJean-Christophe PLAGNIOL-VILLARD switch (request->bRequest){ 10051378df79SJean-Christophe PLAGNIOL-VILLARD 10061378df79SJean-Christophe PLAGNIOL-VILLARD case ACM_SET_CONTROL_LINE_STATE: /* Implies DTE ready */ 10071378df79SJean-Christophe PLAGNIOL-VILLARD break; 10081378df79SJean-Christophe PLAGNIOL-VILLARD case ACM_SEND_ENCAPSULATED_COMMAND : /* Required */ 10091378df79SJean-Christophe PLAGNIOL-VILLARD break; 10101378df79SJean-Christophe PLAGNIOL-VILLARD case ACM_SET_LINE_ENCODING : /* DTE stop/parity bits 10111378df79SJean-Christophe PLAGNIOL-VILLARD * per character */ 10121378df79SJean-Christophe PLAGNIOL-VILLARD break; 10131378df79SJean-Christophe PLAGNIOL-VILLARD case ACM_GET_ENCAPSULATED_RESPONSE : /* request response */ 10141378df79SJean-Christophe PLAGNIOL-VILLARD break; 10151378df79SJean-Christophe PLAGNIOL-VILLARD case ACM_GET_LINE_ENCODING : /* request DTE rate, 10161378df79SJean-Christophe PLAGNIOL-VILLARD * stop/parity bits */ 10171378df79SJean-Christophe PLAGNIOL-VILLARD memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc)); 10181378df79SJean-Christophe PLAGNIOL-VILLARD urb->actual_length = sizeof(rs232_desc); 10191378df79SJean-Christophe PLAGNIOL-VILLARD 10201378df79SJean-Christophe PLAGNIOL-VILLARD break; 10211378df79SJean-Christophe PLAGNIOL-VILLARD default: 10221378df79SJean-Christophe PLAGNIOL-VILLARD return 1; 10231378df79SJean-Christophe PLAGNIOL-VILLARD } 10241378df79SJean-Christophe PLAGNIOL-VILLARD return 0; 10251378df79SJean-Christophe PLAGNIOL-VILLARD } 10261378df79SJean-Christophe PLAGNIOL-VILLARD 10271378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/ 10281378df79SJean-Christophe PLAGNIOL-VILLARD 10291378df79SJean-Christophe PLAGNIOL-VILLARD /* 10301378df79SJean-Christophe PLAGNIOL-VILLARD * Since interrupt handling has not yet been implemented, we use this function 10311378df79SJean-Christophe PLAGNIOL-VILLARD * to handle polling. This is called by the tstc,getc,putc,puts routines to 10321378df79SJean-Christophe PLAGNIOL-VILLARD * update the USB state. 10331378df79SJean-Christophe PLAGNIOL-VILLARD */ 10341378df79SJean-Christophe PLAGNIOL-VILLARD void usbtty_poll (void) 10351378df79SJean-Christophe PLAGNIOL-VILLARD { 10361378df79SJean-Christophe PLAGNIOL-VILLARD /* New interrupts? */ 10371378df79SJean-Christophe PLAGNIOL-VILLARD udc_irq(); 10381378df79SJean-Christophe PLAGNIOL-VILLARD 10391378df79SJean-Christophe PLAGNIOL-VILLARD /* Write any output data to host buffer 10401378df79SJean-Christophe PLAGNIOL-VILLARD * (do this before checking interrupts to avoid missing one) 10411378df79SJean-Christophe PLAGNIOL-VILLARD */ 10421378df79SJean-Christophe PLAGNIOL-VILLARD if (usbtty_configured ()) { 10431378df79SJean-Christophe PLAGNIOL-VILLARD write_buffer (&usbtty_output); 10441378df79SJean-Christophe PLAGNIOL-VILLARD } 10451378df79SJean-Christophe PLAGNIOL-VILLARD 10461378df79SJean-Christophe PLAGNIOL-VILLARD /* New interrupts? */ 10471378df79SJean-Christophe PLAGNIOL-VILLARD udc_irq(); 10481378df79SJean-Christophe PLAGNIOL-VILLARD 10491378df79SJean-Christophe PLAGNIOL-VILLARD /* Check for new data from host.. 10501378df79SJean-Christophe PLAGNIOL-VILLARD * (do this after checking interrupts to get latest data) 10511378df79SJean-Christophe PLAGNIOL-VILLARD */ 10521378df79SJean-Christophe PLAGNIOL-VILLARD if (usbtty_configured ()) { 10531378df79SJean-Christophe PLAGNIOL-VILLARD fill_buffer (&usbtty_input); 10541378df79SJean-Christophe PLAGNIOL-VILLARD } 10551378df79SJean-Christophe PLAGNIOL-VILLARD 10561378df79SJean-Christophe PLAGNIOL-VILLARD /* New interrupts? */ 10571378df79SJean-Christophe PLAGNIOL-VILLARD udc_irq(); 10581378df79SJean-Christophe PLAGNIOL-VILLARD 10591378df79SJean-Christophe PLAGNIOL-VILLARD } 1060