xref: /rk3399_rockchip-uboot/drivers/serial/usbtty.c (revision b2caefbb3344ff5eece7d4b1f3d8e583951d2a20)
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