xref: /rk3399_rockchip-uboot/drivers/serial/usbtty.c (revision 02234e49dea4c9ca3f58eb0cc13ab9ad9e3d1363)
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  *
81a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
91378df79SJean-Christophe PLAGNIOL-VILLARD  */
101378df79SJean-Christophe PLAGNIOL-VILLARD 
111378df79SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
12dedacc18SJean-Christophe PLAGNIOL-VILLARD #include <config.h>
131378df79SJean-Christophe PLAGNIOL-VILLARD #include <circbuf.h>
1452cb4d4fSJean-Christophe PLAGNIOL-VILLARD #include <stdio_dev.h>
15b2fb47f1STom Rini #include <asm/unaligned.h>
161378df79SJean-Christophe PLAGNIOL-VILLARD #include "usbtty.h"
171378df79SJean-Christophe PLAGNIOL-VILLARD #include "usb_cdc_acm.h"
181378df79SJean-Christophe PLAGNIOL-VILLARD #include "usbdescriptors.h"
191378df79SJean-Christophe PLAGNIOL-VILLARD 
20dedacc18SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
211378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYDBG(fmt,args...)\
221378df79SJean-Christophe PLAGNIOL-VILLARD 	serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
231378df79SJean-Christophe PLAGNIOL-VILLARD #else
241378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYDBG(fmt,args...) do{}while(0)
251378df79SJean-Christophe PLAGNIOL-VILLARD #endif
261378df79SJean-Christophe PLAGNIOL-VILLARD 
271378df79SJean-Christophe PLAGNIOL-VILLARD #if 1
281378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYERR(fmt,args...)\
291378df79SJean-Christophe PLAGNIOL-VILLARD 	serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\
301378df79SJean-Christophe PLAGNIOL-VILLARD 	__LINE__,##args)
311378df79SJean-Christophe PLAGNIOL-VILLARD #else
321378df79SJean-Christophe PLAGNIOL-VILLARD #define TTYERR(fmt,args...) do{}while(0)
331378df79SJean-Christophe PLAGNIOL-VILLARD #endif
341378df79SJean-Christophe PLAGNIOL-VILLARD 
351378df79SJean-Christophe PLAGNIOL-VILLARD /*
361378df79SJean-Christophe PLAGNIOL-VILLARD  * Defines
371378df79SJean-Christophe PLAGNIOL-VILLARD  */
381378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_CONFIGS    1
391378df79SJean-Christophe PLAGNIOL-VILLARD #define MAX_INTERFACES 2
401378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_ENDPOINTS  3
411378df79SJean-Christophe PLAGNIOL-VILLARD #define ACM_TX_ENDPOINT 3
421378df79SJean-Christophe PLAGNIOL-VILLARD #define ACM_RX_ENDPOINT 2
431378df79SJean-Christophe PLAGNIOL-VILLARD #define GSERIAL_TX_ENDPOINT 2
441378df79SJean-Christophe PLAGNIOL-VILLARD #define GSERIAL_RX_ENDPOINT 1
451378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_ACM_INTERFACES 2
461378df79SJean-Christophe PLAGNIOL-VILLARD #define NUM_GSERIAL_INTERFACES 1
471378df79SJean-Christophe PLAGNIOL-VILLARD #define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface"
481378df79SJean-Christophe PLAGNIOL-VILLARD #define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface"
491378df79SJean-Christophe PLAGNIOL-VILLARD 
501378df79SJean-Christophe PLAGNIOL-VILLARD /*
511378df79SJean-Christophe PLAGNIOL-VILLARD  * Buffers to hold input and output data
521378df79SJean-Christophe PLAGNIOL-VILLARD  */
53b2caefbbSShiraz Hashim #define USBTTY_BUFFER_SIZE 2048
541378df79SJean-Christophe PLAGNIOL-VILLARD static circbuf_t usbtty_input;
551378df79SJean-Christophe PLAGNIOL-VILLARD static circbuf_t usbtty_output;
561378df79SJean-Christophe PLAGNIOL-VILLARD 
571378df79SJean-Christophe PLAGNIOL-VILLARD 
581378df79SJean-Christophe PLAGNIOL-VILLARD /*
591378df79SJean-Christophe PLAGNIOL-VILLARD  * Instance variables
601378df79SJean-Christophe PLAGNIOL-VILLARD  */
6152cb4d4fSJean-Christophe PLAGNIOL-VILLARD static struct stdio_dev usbttydev;
621378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_device_instance device_instance[1];
631378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_bus_instance bus_instance[1];
641378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_configuration_instance config_instance[NUM_CONFIGS];
651378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_interface_instance interface_instance[MAX_INTERFACES];
661378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_alternate_instance alternate_instance[MAX_INTERFACES];
671378df79SJean-Christophe PLAGNIOL-VILLARD /* one extra for control endpoint */
681378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1];
691378df79SJean-Christophe PLAGNIOL-VILLARD 
701378df79SJean-Christophe PLAGNIOL-VILLARD /*
711378df79SJean-Christophe PLAGNIOL-VILLARD  * Global flag
721378df79SJean-Christophe PLAGNIOL-VILLARD  */
731378df79SJean-Christophe PLAGNIOL-VILLARD int usbtty_configured_flag = 0;
741378df79SJean-Christophe PLAGNIOL-VILLARD 
751378df79SJean-Christophe PLAGNIOL-VILLARD /*
761378df79SJean-Christophe PLAGNIOL-VILLARD  * Serial number
771378df79SJean-Christophe PLAGNIOL-VILLARD  */
781378df79SJean-Christophe PLAGNIOL-VILLARD static char serial_number[16];
791378df79SJean-Christophe PLAGNIOL-VILLARD 
801378df79SJean-Christophe PLAGNIOL-VILLARD 
811378df79SJean-Christophe PLAGNIOL-VILLARD /*
821378df79SJean-Christophe PLAGNIOL-VILLARD  * Descriptors, Strings, Local variables.
831378df79SJean-Christophe PLAGNIOL-VILLARD  */
841378df79SJean-Christophe PLAGNIOL-VILLARD 
852731b9a8SJean-Christophe PLAGNIOL-VILLARD /* defined and used by gadget/ep0.c */
861378df79SJean-Christophe PLAGNIOL-VILLARD extern struct usb_string_descriptor **usb_strings;
871378df79SJean-Christophe PLAGNIOL-VILLARD 
881378df79SJean-Christophe PLAGNIOL-VILLARD /* Indicies, References */
891378df79SJean-Christophe PLAGNIOL-VILLARD static unsigned short rx_endpoint = 0;
901378df79SJean-Christophe PLAGNIOL-VILLARD static unsigned short tx_endpoint = 0;
911378df79SJean-Christophe PLAGNIOL-VILLARD static unsigned short interface_count = 0;
921378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_string_descriptor *usbtty_string_table[STR_COUNT];
931378df79SJean-Christophe PLAGNIOL-VILLARD 
941378df79SJean-Christophe PLAGNIOL-VILLARD /* USB Descriptor Strings */
951378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4};
961378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];
971378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)];
981378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)];
991378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)];
1001378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
1011378df79SJean-Christophe PLAGNIOL-VILLARD static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
1021378df79SJean-Christophe PLAGNIOL-VILLARD 
1031378df79SJean-Christophe PLAGNIOL-VILLARD /* Standard USB Data Structures */
1041378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES];
1051378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS];
1061378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_configuration_descriptor	*configuration_descriptor = 0;
1071378df79SJean-Christophe PLAGNIOL-VILLARD static struct usb_device_descriptor device_descriptor = {
1081378df79SJean-Christophe PLAGNIOL-VILLARD 	.bLength = sizeof(struct usb_device_descriptor),
1091378df79SJean-Christophe PLAGNIOL-VILLARD 	.bDescriptorType =	USB_DT_DEVICE,
1101378df79SJean-Christophe PLAGNIOL-VILLARD 	.bcdUSB =		cpu_to_le16(USB_BCD_VERSION),
1111378df79SJean-Christophe PLAGNIOL-VILLARD 	.bDeviceSubClass =	0x00,
1121378df79SJean-Christophe PLAGNIOL-VILLARD 	.bDeviceProtocol =	0x00,
1131378df79SJean-Christophe PLAGNIOL-VILLARD 	.bMaxPacketSize0 =	EP0_MAX_PACKET_SIZE,
1141378df79SJean-Christophe PLAGNIOL-VILLARD 	.idVendor =		cpu_to_le16(CONFIG_USBD_VENDORID),
1151378df79SJean-Christophe PLAGNIOL-VILLARD 	.bcdDevice =		cpu_to_le16(USBTTY_BCD_DEVICE),
1161378df79SJean-Christophe PLAGNIOL-VILLARD 	.iManufacturer =	STR_MANUFACTURER,
1171378df79SJean-Christophe PLAGNIOL-VILLARD 	.iProduct =		STR_PRODUCT,
1181378df79SJean-Christophe PLAGNIOL-VILLARD 	.iSerialNumber =	STR_SERIAL,
1191378df79SJean-Christophe PLAGNIOL-VILLARD 	.bNumConfigurations =	NUM_CONFIGS
1201378df79SJean-Christophe PLAGNIOL-VILLARD };
1211378df79SJean-Christophe PLAGNIOL-VILLARD 
1221378df79SJean-Christophe PLAGNIOL-VILLARD 
123f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS)
124f9da0f89SVipin KUMAR static struct usb_qualifier_descriptor qualifier_descriptor = {
125f9da0f89SVipin KUMAR 	.bLength = sizeof(struct usb_qualifier_descriptor),
126f9da0f89SVipin KUMAR 	.bDescriptorType =	USB_DT_QUAL,
127f9da0f89SVipin KUMAR 	.bcdUSB =		cpu_to_le16(USB_BCD_VERSION),
128f9da0f89SVipin KUMAR 	.bDeviceClass =		COMMUNICATIONS_DEVICE_CLASS,
129f9da0f89SVipin KUMAR 	.bDeviceSubClass =	0x00,
130f9da0f89SVipin KUMAR 	.bDeviceProtocol =	0x00,
131f9da0f89SVipin KUMAR 	.bMaxPacketSize0 =	EP0_MAX_PACKET_SIZE,
132f9da0f89SVipin KUMAR 	.bNumConfigurations =	NUM_CONFIGS
133f9da0f89SVipin KUMAR };
134f9da0f89SVipin KUMAR #endif
135f9da0f89SVipin KUMAR 
1361378df79SJean-Christophe PLAGNIOL-VILLARD /*
1371378df79SJean-Christophe PLAGNIOL-VILLARD  * Static CDC ACM specific descriptors
1381378df79SJean-Christophe PLAGNIOL-VILLARD  */
1391378df79SJean-Christophe PLAGNIOL-VILLARD 
1401378df79SJean-Christophe PLAGNIOL-VILLARD struct acm_config_desc {
1411378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_configuration_descriptor configuration_desc;
1421378df79SJean-Christophe PLAGNIOL-VILLARD 
1431378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Master Interface */
1441378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_interface_descriptor interface_desc;
1451378df79SJean-Christophe PLAGNIOL-VILLARD 
1461378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_class_header_function_descriptor usb_class_header;
1471378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_class_call_management_descriptor usb_class_call_mgt;
1481378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_class_abstract_control_descriptor usb_class_acm;
1491378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_class_union_function_descriptor usb_class_union;
1501378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_endpoint_descriptor notification_endpoint;
1511378df79SJean-Christophe PLAGNIOL-VILLARD 
1521378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Slave Interface */
1531378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_interface_descriptor data_class_interface;
154f3c0de63SAtin Malaviya 	struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS-1];
1551378df79SJean-Christophe PLAGNIOL-VILLARD } __attribute__((packed));
1561378df79SJean-Christophe PLAGNIOL-VILLARD 
1571378df79SJean-Christophe PLAGNIOL-VILLARD static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = {
1581378df79SJean-Christophe PLAGNIOL-VILLARD 	{
1591378df79SJean-Christophe PLAGNIOL-VILLARD 		.configuration_desc ={
1601378df79SJean-Christophe PLAGNIOL-VILLARD 			.bLength =
1611378df79SJean-Christophe PLAGNIOL-VILLARD 				sizeof(struct usb_configuration_descriptor),
1621378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType = USB_DT_CONFIG,
1631378df79SJean-Christophe PLAGNIOL-VILLARD 			.wTotalLength =
1641378df79SJean-Christophe PLAGNIOL-VILLARD 				cpu_to_le16(sizeof(struct acm_config_desc)),
1651378df79SJean-Christophe PLAGNIOL-VILLARD 			.bNumInterfaces = NUM_ACM_INTERFACES,
1661378df79SJean-Christophe PLAGNIOL-VILLARD 			.bConfigurationValue = 1,
1671378df79SJean-Christophe PLAGNIOL-VILLARD 			.iConfiguration = STR_CONFIG,
1681378df79SJean-Christophe PLAGNIOL-VILLARD 			.bmAttributes =
1691378df79SJean-Christophe PLAGNIOL-VILLARD 				BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
1701378df79SJean-Christophe PLAGNIOL-VILLARD 			.bMaxPower = USBTTY_MAXPOWER
1711378df79SJean-Christophe PLAGNIOL-VILLARD 		},
1721378df79SJean-Christophe PLAGNIOL-VILLARD 		/* Interface 1 */
1731378df79SJean-Christophe PLAGNIOL-VILLARD 		.interface_desc = {
1741378df79SJean-Christophe PLAGNIOL-VILLARD 			.bLength  = sizeof(struct usb_interface_descriptor),
1751378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType = USB_DT_INTERFACE,
1761378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceNumber = 0,
1771378df79SJean-Christophe PLAGNIOL-VILLARD 			.bAlternateSetting = 0,
1781378df79SJean-Christophe PLAGNIOL-VILLARD 			.bNumEndpoints = 0x01,
1791378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceClass =
1801378df79SJean-Christophe PLAGNIOL-VILLARD 				COMMUNICATIONS_INTERFACE_CLASS_CONTROL,
1811378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS,
1821378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL,
1831378df79SJean-Christophe PLAGNIOL-VILLARD 			.iInterface = STR_CTRL_INTERFACE,
1841378df79SJean-Christophe PLAGNIOL-VILLARD 		},
1851378df79SJean-Christophe PLAGNIOL-VILLARD 		.usb_class_header = {
1861378df79SJean-Christophe PLAGNIOL-VILLARD 			.bFunctionLength	=
1871378df79SJean-Christophe PLAGNIOL-VILLARD 				sizeof(struct usb_class_header_function_descriptor),
1881378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType	= CS_INTERFACE,
1891378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorSubtype	= USB_ST_HEADER,
1901378df79SJean-Christophe PLAGNIOL-VILLARD 			.bcdCDC	= cpu_to_le16(110),
1911378df79SJean-Christophe PLAGNIOL-VILLARD 		},
1921378df79SJean-Christophe PLAGNIOL-VILLARD 		.usb_class_call_mgt = {
1931378df79SJean-Christophe PLAGNIOL-VILLARD 			.bFunctionLength	=
1941378df79SJean-Christophe PLAGNIOL-VILLARD 				sizeof(struct usb_class_call_management_descriptor),
1951378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType	= CS_INTERFACE,
1961378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorSubtype	= USB_ST_CMF,
1971378df79SJean-Christophe PLAGNIOL-VILLARD 			.bmCapabilities		= 0x00,
1981378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDataInterface		= 0x01,
1991378df79SJean-Christophe PLAGNIOL-VILLARD 		},
2001378df79SJean-Christophe PLAGNIOL-VILLARD 		.usb_class_acm = {
2011378df79SJean-Christophe PLAGNIOL-VILLARD 			.bFunctionLength	=
2021378df79SJean-Christophe PLAGNIOL-VILLARD 				sizeof(struct usb_class_abstract_control_descriptor),
2031378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType	= CS_INTERFACE,
2041378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorSubtype	= USB_ST_ACMF,
2051378df79SJean-Christophe PLAGNIOL-VILLARD 			.bmCapabilities		= 0x00,
2061378df79SJean-Christophe PLAGNIOL-VILLARD 		},
2071378df79SJean-Christophe PLAGNIOL-VILLARD 		.usb_class_union = {
2081378df79SJean-Christophe PLAGNIOL-VILLARD 			.bFunctionLength	=
2091378df79SJean-Christophe PLAGNIOL-VILLARD 				sizeof(struct usb_class_union_function_descriptor),
2101378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType	= CS_INTERFACE,
2111378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorSubtype	= USB_ST_UF,
2121378df79SJean-Christophe PLAGNIOL-VILLARD 			.bMasterInterface	= 0x00,
2131378df79SJean-Christophe PLAGNIOL-VILLARD 			.bSlaveInterface0	= 0x01,
2141378df79SJean-Christophe PLAGNIOL-VILLARD 		},
2151378df79SJean-Christophe PLAGNIOL-VILLARD 		.notification_endpoint = {
2161378df79SJean-Christophe PLAGNIOL-VILLARD 			.bLength =
2171378df79SJean-Christophe PLAGNIOL-VILLARD 				sizeof(struct usb_endpoint_descriptor),
2181378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType	= USB_DT_ENDPOINT,
2199e78dae2SVivek Kutal 			.bEndpointAddress	= UDC_INT_ENDPOINT | USB_DIR_IN,
2201378df79SJean-Christophe PLAGNIOL-VILLARD 			.bmAttributes		= USB_ENDPOINT_XFER_INT,
2211378df79SJean-Christophe PLAGNIOL-VILLARD 			.wMaxPacketSize
2221378df79SJean-Christophe PLAGNIOL-VILLARD 				= cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
2231378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterval		= 0xFF,
2241378df79SJean-Christophe PLAGNIOL-VILLARD 		},
2251378df79SJean-Christophe PLAGNIOL-VILLARD 
2261378df79SJean-Christophe PLAGNIOL-VILLARD 		/* Interface 2 */
2271378df79SJean-Christophe PLAGNIOL-VILLARD 		.data_class_interface = {
2281378df79SJean-Christophe PLAGNIOL-VILLARD 			.bLength		=
2291378df79SJean-Christophe PLAGNIOL-VILLARD 				sizeof(struct usb_interface_descriptor),
2301378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType	= USB_DT_INTERFACE,
2311378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceNumber	= 0x01,
2321378df79SJean-Christophe PLAGNIOL-VILLARD 			.bAlternateSetting	= 0x00,
2331378df79SJean-Christophe PLAGNIOL-VILLARD 			.bNumEndpoints		= 0x02,
2341378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceClass	=
2351378df79SJean-Christophe PLAGNIOL-VILLARD 				COMMUNICATIONS_INTERFACE_CLASS_DATA,
2361378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceSubClass	= DATA_INTERFACE_SUBCLASS_NONE,
2371378df79SJean-Christophe PLAGNIOL-VILLARD 			.bInterfaceProtocol	= DATA_INTERFACE_PROTOCOL_NONE,
2381378df79SJean-Christophe PLAGNIOL-VILLARD 			.iInterface		= STR_DATA_INTERFACE,
2391378df79SJean-Christophe PLAGNIOL-VILLARD 		},
2401378df79SJean-Christophe PLAGNIOL-VILLARD 		.data_endpoints = {
2411378df79SJean-Christophe PLAGNIOL-VILLARD 			{
2421378df79SJean-Christophe PLAGNIOL-VILLARD 				.bLength		=
2431378df79SJean-Christophe PLAGNIOL-VILLARD 					sizeof(struct usb_endpoint_descriptor),
2441378df79SJean-Christophe PLAGNIOL-VILLARD 				.bDescriptorType	= USB_DT_ENDPOINT,
2459e78dae2SVivek Kutal 				.bEndpointAddress	= UDC_OUT_ENDPOINT | USB_DIR_OUT,
2461378df79SJean-Christophe PLAGNIOL-VILLARD 				.bmAttributes		=
2471378df79SJean-Christophe PLAGNIOL-VILLARD 					USB_ENDPOINT_XFER_BULK,
2481378df79SJean-Christophe PLAGNIOL-VILLARD 				.wMaxPacketSize		=
2491378df79SJean-Christophe PLAGNIOL-VILLARD 					cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
2501378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterval		= 0xFF,
2511378df79SJean-Christophe PLAGNIOL-VILLARD 			},
2521378df79SJean-Christophe PLAGNIOL-VILLARD 			{
2531378df79SJean-Christophe PLAGNIOL-VILLARD 				.bLength		=
2541378df79SJean-Christophe PLAGNIOL-VILLARD 					sizeof(struct usb_endpoint_descriptor),
2551378df79SJean-Christophe PLAGNIOL-VILLARD 				.bDescriptorType	= USB_DT_ENDPOINT,
2569e78dae2SVivek Kutal 				.bEndpointAddress	= UDC_IN_ENDPOINT | USB_DIR_IN,
2571378df79SJean-Christophe PLAGNIOL-VILLARD 				.bmAttributes		=
2581378df79SJean-Christophe PLAGNIOL-VILLARD 					USB_ENDPOINT_XFER_BULK,
2591378df79SJean-Christophe PLAGNIOL-VILLARD 				.wMaxPacketSize		=
2601378df79SJean-Christophe PLAGNIOL-VILLARD 					cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
2611378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterval		= 0xFF,
2621378df79SJean-Christophe PLAGNIOL-VILLARD 			},
2631378df79SJean-Christophe PLAGNIOL-VILLARD 		},
2641378df79SJean-Christophe PLAGNIOL-VILLARD 	},
2651378df79SJean-Christophe PLAGNIOL-VILLARD };
2661378df79SJean-Christophe PLAGNIOL-VILLARD 
2671378df79SJean-Christophe PLAGNIOL-VILLARD static struct rs232_emu rs232_desc={
2681378df79SJean-Christophe PLAGNIOL-VILLARD 		.dter		=	115200,
2691378df79SJean-Christophe PLAGNIOL-VILLARD 		.stop_bits	=	0x00,
2701378df79SJean-Christophe PLAGNIOL-VILLARD 		.parity		=	0x00,
2711378df79SJean-Christophe PLAGNIOL-VILLARD 		.data_bits	=	0x08
2721378df79SJean-Christophe PLAGNIOL-VILLARD };
2731378df79SJean-Christophe PLAGNIOL-VILLARD 
2741378df79SJean-Christophe PLAGNIOL-VILLARD 
2751378df79SJean-Christophe PLAGNIOL-VILLARD /*
2761378df79SJean-Christophe PLAGNIOL-VILLARD  * Static Generic Serial specific data
2771378df79SJean-Christophe PLAGNIOL-VILLARD  */
2781378df79SJean-Christophe PLAGNIOL-VILLARD 
2791378df79SJean-Christophe PLAGNIOL-VILLARD 
2801378df79SJean-Christophe PLAGNIOL-VILLARD struct gserial_config_desc {
2811378df79SJean-Christophe PLAGNIOL-VILLARD 
2821378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_configuration_descriptor configuration_desc;
283f3c0de63SAtin Malaviya 	struct usb_interface_descriptor	interface_desc[NUM_GSERIAL_INTERFACES];
284f3c0de63SAtin Malaviya 	struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS];
2851378df79SJean-Christophe PLAGNIOL-VILLARD 
2861378df79SJean-Christophe PLAGNIOL-VILLARD } __attribute__((packed));
2871378df79SJean-Christophe PLAGNIOL-VILLARD 
2881378df79SJean-Christophe PLAGNIOL-VILLARD static struct gserial_config_desc
2891378df79SJean-Christophe PLAGNIOL-VILLARD gserial_configuration_descriptors[NUM_CONFIGS] ={
2901378df79SJean-Christophe PLAGNIOL-VILLARD 	{
2911378df79SJean-Christophe PLAGNIOL-VILLARD 		.configuration_desc ={
2921378df79SJean-Christophe PLAGNIOL-VILLARD 			.bLength = sizeof(struct usb_configuration_descriptor),
2931378df79SJean-Christophe PLAGNIOL-VILLARD 			.bDescriptorType = USB_DT_CONFIG,
2941378df79SJean-Christophe PLAGNIOL-VILLARD 			.wTotalLength =
2951378df79SJean-Christophe PLAGNIOL-VILLARD 				cpu_to_le16(sizeof(struct gserial_config_desc)),
2961378df79SJean-Christophe PLAGNIOL-VILLARD 			.bNumInterfaces = NUM_GSERIAL_INTERFACES,
2971378df79SJean-Christophe PLAGNIOL-VILLARD 			.bConfigurationValue = 1,
2981378df79SJean-Christophe PLAGNIOL-VILLARD 			.iConfiguration = STR_CONFIG,
2991378df79SJean-Christophe PLAGNIOL-VILLARD 			.bmAttributes =
3001378df79SJean-Christophe PLAGNIOL-VILLARD 				BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
3011378df79SJean-Christophe PLAGNIOL-VILLARD 			.bMaxPower = USBTTY_MAXPOWER
3021378df79SJean-Christophe PLAGNIOL-VILLARD 		},
3031378df79SJean-Christophe PLAGNIOL-VILLARD 		.interface_desc = {
3041378df79SJean-Christophe PLAGNIOL-VILLARD 			{
3051378df79SJean-Christophe PLAGNIOL-VILLARD 				.bLength  =
3061378df79SJean-Christophe PLAGNIOL-VILLARD 					sizeof(struct usb_interface_descriptor),
3071378df79SJean-Christophe PLAGNIOL-VILLARD 				.bDescriptorType = USB_DT_INTERFACE,
3081378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterfaceNumber = 0,
3091378df79SJean-Christophe PLAGNIOL-VILLARD 				.bAlternateSetting = 0,
3101378df79SJean-Christophe PLAGNIOL-VILLARD 				.bNumEndpoints = NUM_ENDPOINTS,
3111378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterfaceClass =
3121378df79SJean-Christophe PLAGNIOL-VILLARD 					COMMUNICATIONS_INTERFACE_CLASS_VENDOR,
3131378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterfaceSubClass =
3141378df79SJean-Christophe PLAGNIOL-VILLARD 					COMMUNICATIONS_NO_SUBCLASS,
3151378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterfaceProtocol =
3161378df79SJean-Christophe PLAGNIOL-VILLARD 					COMMUNICATIONS_NO_PROTOCOL,
3171378df79SJean-Christophe PLAGNIOL-VILLARD 				.iInterface = STR_DATA_INTERFACE
3181378df79SJean-Christophe PLAGNIOL-VILLARD 			},
3191378df79SJean-Christophe PLAGNIOL-VILLARD 		},
3201378df79SJean-Christophe PLAGNIOL-VILLARD 		.data_endpoints  = {
3211378df79SJean-Christophe PLAGNIOL-VILLARD 			{
3221378df79SJean-Christophe PLAGNIOL-VILLARD 				.bLength =
3231378df79SJean-Christophe PLAGNIOL-VILLARD 					sizeof(struct usb_endpoint_descriptor),
3241378df79SJean-Christophe PLAGNIOL-VILLARD 				.bDescriptorType =	USB_DT_ENDPOINT,
3259e78dae2SVivek Kutal 				.bEndpointAddress =	UDC_OUT_ENDPOINT | USB_DIR_OUT,
3261378df79SJean-Christophe PLAGNIOL-VILLARD 				.bmAttributes =		USB_ENDPOINT_XFER_BULK,
3271378df79SJean-Christophe PLAGNIOL-VILLARD 				.wMaxPacketSize =
3281378df79SJean-Christophe PLAGNIOL-VILLARD 					cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE),
3291378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterval=		0xFF,
3301378df79SJean-Christophe PLAGNIOL-VILLARD 			},
3311378df79SJean-Christophe PLAGNIOL-VILLARD 			{
3321378df79SJean-Christophe PLAGNIOL-VILLARD 				.bLength =
3331378df79SJean-Christophe PLAGNIOL-VILLARD 					sizeof(struct usb_endpoint_descriptor),
3341378df79SJean-Christophe PLAGNIOL-VILLARD 				.bDescriptorType =	USB_DT_ENDPOINT,
3359e78dae2SVivek Kutal 				.bEndpointAddress =	UDC_IN_ENDPOINT | USB_DIR_IN,
3361378df79SJean-Christophe PLAGNIOL-VILLARD 				.bmAttributes =		USB_ENDPOINT_XFER_BULK,
3371378df79SJean-Christophe PLAGNIOL-VILLARD 				.wMaxPacketSize =
3381378df79SJean-Christophe PLAGNIOL-VILLARD 					cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE),
3391378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterval =		0xFF,
3401378df79SJean-Christophe PLAGNIOL-VILLARD 			},
3411378df79SJean-Christophe PLAGNIOL-VILLARD 			{
3421378df79SJean-Christophe PLAGNIOL-VILLARD 				.bLength =
3431378df79SJean-Christophe PLAGNIOL-VILLARD 					sizeof(struct usb_endpoint_descriptor),
3441378df79SJean-Christophe PLAGNIOL-VILLARD 				.bDescriptorType =	USB_DT_ENDPOINT,
3459e78dae2SVivek Kutal 				.bEndpointAddress =	UDC_INT_ENDPOINT | USB_DIR_IN,
3461378df79SJean-Christophe PLAGNIOL-VILLARD 				.bmAttributes =		USB_ENDPOINT_XFER_INT,
3471378df79SJean-Christophe PLAGNIOL-VILLARD 				.wMaxPacketSize =
3481378df79SJean-Christophe PLAGNIOL-VILLARD 					cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
3491378df79SJean-Christophe PLAGNIOL-VILLARD 				.bInterval =		0xFF,
3501378df79SJean-Christophe PLAGNIOL-VILLARD 			},
3511378df79SJean-Christophe PLAGNIOL-VILLARD 		},
3521378df79SJean-Christophe PLAGNIOL-VILLARD 	},
3531378df79SJean-Christophe PLAGNIOL-VILLARD };
3541378df79SJean-Christophe PLAGNIOL-VILLARD 
3551378df79SJean-Christophe PLAGNIOL-VILLARD /*
3561378df79SJean-Christophe PLAGNIOL-VILLARD  * Static Function Prototypes
3571378df79SJean-Christophe PLAGNIOL-VILLARD  */
3581378df79SJean-Christophe PLAGNIOL-VILLARD 
3591378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_strings (void);
3601378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_instances (void);
3611378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_endpoints (void);
3621378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_terminal_type(short type);
3631378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_event_handler (struct usb_device_instance *device,
3641378df79SJean-Christophe PLAGNIOL-VILLARD 				usb_device_event_t event, int data);
3651378df79SJean-Christophe PLAGNIOL-VILLARD static int usbtty_cdc_setup(struct usb_device_request *request,
3661378df79SJean-Christophe PLAGNIOL-VILLARD 				struct urb *urb);
3671378df79SJean-Christophe PLAGNIOL-VILLARD static int usbtty_configured (void);
3681378df79SJean-Christophe PLAGNIOL-VILLARD static int write_buffer (circbuf_t * buf);
3691378df79SJean-Christophe PLAGNIOL-VILLARD static int fill_buffer (circbuf_t * buf);
3701378df79SJean-Christophe PLAGNIOL-VILLARD 
3711378df79SJean-Christophe PLAGNIOL-VILLARD void usbtty_poll (void);
3721378df79SJean-Christophe PLAGNIOL-VILLARD 
3731378df79SJean-Christophe PLAGNIOL-VILLARD /* utility function for converting char* to wide string used by USB */
str2wide(char * str,u16 * wide)3741378df79SJean-Christophe PLAGNIOL-VILLARD static void str2wide (char *str, u16 * wide)
3751378df79SJean-Christophe PLAGNIOL-VILLARD {
3761378df79SJean-Christophe PLAGNIOL-VILLARD 	int i;
3771378df79SJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < strlen (str) && str[i]; i++){
3781378df79SJean-Christophe PLAGNIOL-VILLARD 		#if defined(__LITTLE_ENDIAN)
3791378df79SJean-Christophe PLAGNIOL-VILLARD 			wide[i] = (u16) str[i];
3801378df79SJean-Christophe PLAGNIOL-VILLARD 		#elif defined(__BIG_ENDIAN)
3811378df79SJean-Christophe PLAGNIOL-VILLARD 			wide[i] = ((u16)(str[i])<<8);
3821378df79SJean-Christophe PLAGNIOL-VILLARD 		#else
3831378df79SJean-Christophe PLAGNIOL-VILLARD 			#error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined"
3841378df79SJean-Christophe PLAGNIOL-VILLARD 		#endif
3851378df79SJean-Christophe PLAGNIOL-VILLARD 	}
3861378df79SJean-Christophe PLAGNIOL-VILLARD }
3871378df79SJean-Christophe PLAGNIOL-VILLARD 
3881378df79SJean-Christophe PLAGNIOL-VILLARD /*
3891378df79SJean-Christophe PLAGNIOL-VILLARD  * Test whether a character is in the RX buffer
3901378df79SJean-Christophe PLAGNIOL-VILLARD  */
3911378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_tstc(struct stdio_dev * dev)392709ea543SSimon Glass int usbtty_tstc(struct stdio_dev *dev)
3931378df79SJean-Christophe PLAGNIOL-VILLARD {
3941378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_endpoint_instance *endpoint =
3951378df79SJean-Christophe PLAGNIOL-VILLARD 		&endpoint_instance[rx_endpoint];
3961378df79SJean-Christophe PLAGNIOL-VILLARD 
3971378df79SJean-Christophe PLAGNIOL-VILLARD 	/* If no input data exists, allow more RX to be accepted */
3981378df79SJean-Christophe PLAGNIOL-VILLARD 	if(usbtty_input.size <= 0){
3991378df79SJean-Christophe PLAGNIOL-VILLARD 		udc_unset_nak(endpoint->endpoint_address&0x03);
4001378df79SJean-Christophe PLAGNIOL-VILLARD 	}
4011378df79SJean-Christophe PLAGNIOL-VILLARD 
4021378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_poll ();
4031378df79SJean-Christophe PLAGNIOL-VILLARD 	return (usbtty_input.size > 0);
4041378df79SJean-Christophe PLAGNIOL-VILLARD }
4051378df79SJean-Christophe PLAGNIOL-VILLARD 
4061378df79SJean-Christophe PLAGNIOL-VILLARD /*
4071378df79SJean-Christophe PLAGNIOL-VILLARD  * Read a single byte from the usb client port. Returns 1 on success, 0
4081378df79SJean-Christophe PLAGNIOL-VILLARD  * otherwise. When the function is succesfull, the character read is
4091378df79SJean-Christophe PLAGNIOL-VILLARD  * written into its argument c.
4101378df79SJean-Christophe PLAGNIOL-VILLARD  */
4111378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_getc(struct stdio_dev * dev)412709ea543SSimon Glass int usbtty_getc(struct stdio_dev *dev)
4131378df79SJean-Christophe PLAGNIOL-VILLARD {
4141378df79SJean-Christophe PLAGNIOL-VILLARD 	char c;
4151378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_endpoint_instance *endpoint =
4161378df79SJean-Christophe PLAGNIOL-VILLARD 		&endpoint_instance[rx_endpoint];
4171378df79SJean-Christophe PLAGNIOL-VILLARD 
4181378df79SJean-Christophe PLAGNIOL-VILLARD 	while (usbtty_input.size <= 0) {
4191378df79SJean-Christophe PLAGNIOL-VILLARD 		udc_unset_nak(endpoint->endpoint_address&0x03);
4201378df79SJean-Christophe PLAGNIOL-VILLARD 		usbtty_poll ();
4211378df79SJean-Christophe PLAGNIOL-VILLARD 	}
4221378df79SJean-Christophe PLAGNIOL-VILLARD 
4231378df79SJean-Christophe PLAGNIOL-VILLARD 	buf_pop (&usbtty_input, &c, 1);
4241378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_set_nak(endpoint->endpoint_address&0x03);
4251378df79SJean-Christophe PLAGNIOL-VILLARD 
4261378df79SJean-Christophe PLAGNIOL-VILLARD 	return c;
4271378df79SJean-Christophe PLAGNIOL-VILLARD }
4281378df79SJean-Christophe PLAGNIOL-VILLARD 
4291378df79SJean-Christophe PLAGNIOL-VILLARD /*
4301378df79SJean-Christophe PLAGNIOL-VILLARD  * Output a single byte to the usb client port.
4311378df79SJean-Christophe PLAGNIOL-VILLARD  */
usbtty_putc(struct stdio_dev * dev,const char c)432709ea543SSimon Glass void usbtty_putc(struct stdio_dev *dev, const char c)
4331378df79SJean-Christophe PLAGNIOL-VILLARD {
434f3c0de63SAtin Malaviya 	if (!usbtty_configured ())
435f3c0de63SAtin Malaviya 		return;
436f3c0de63SAtin Malaviya 
4371378df79SJean-Christophe PLAGNIOL-VILLARD 	/* If \n, also do \r */
4381378df79SJean-Christophe PLAGNIOL-VILLARD 	if (c == '\n')
4391378df79SJean-Christophe PLAGNIOL-VILLARD 		buf_push (&usbtty_output, "\r", 1);
4401378df79SJean-Christophe PLAGNIOL-VILLARD 
441055457efSAlison Wang 	buf_push(&usbtty_output, &c, 1);
442055457efSAlison Wang 
4431378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Poll at end to handle new data... */
4441378df79SJean-Christophe PLAGNIOL-VILLARD 	if ((usbtty_output.size + 2) >= usbtty_output.totalsize) {
4451378df79SJean-Christophe PLAGNIOL-VILLARD 		usbtty_poll ();
4461378df79SJean-Christophe PLAGNIOL-VILLARD 	}
4471378df79SJean-Christophe PLAGNIOL-VILLARD }
4481378df79SJean-Christophe PLAGNIOL-VILLARD 
4491378df79SJean-Christophe PLAGNIOL-VILLARD /* usbtty_puts() helper function for finding the next '\n' in a string */
next_nl_pos(const char * s)4501378df79SJean-Christophe PLAGNIOL-VILLARD static int next_nl_pos (const char *s)
4511378df79SJean-Christophe PLAGNIOL-VILLARD {
4521378df79SJean-Christophe PLAGNIOL-VILLARD 	int i;
4531378df79SJean-Christophe PLAGNIOL-VILLARD 
4541378df79SJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; s[i] != '\0'; i++) {
4551378df79SJean-Christophe PLAGNIOL-VILLARD 		if (s[i] == '\n')
4561378df79SJean-Christophe PLAGNIOL-VILLARD 			return i;
4571378df79SJean-Christophe PLAGNIOL-VILLARD 	}
4581378df79SJean-Christophe PLAGNIOL-VILLARD 	return i;
4591378df79SJean-Christophe PLAGNIOL-VILLARD }
4601378df79SJean-Christophe PLAGNIOL-VILLARD 
4611378df79SJean-Christophe PLAGNIOL-VILLARD /*
4621378df79SJean-Christophe PLAGNIOL-VILLARD  * Output a string to the usb client port - implementing flow control
4631378df79SJean-Christophe PLAGNIOL-VILLARD  */
4641378df79SJean-Christophe PLAGNIOL-VILLARD 
__usbtty_puts(const char * str,int len)4651378df79SJean-Christophe PLAGNIOL-VILLARD static void __usbtty_puts (const char *str, int len)
4661378df79SJean-Christophe PLAGNIOL-VILLARD {
4671378df79SJean-Christophe PLAGNIOL-VILLARD 	int maxlen = usbtty_output.totalsize;
4681378df79SJean-Christophe PLAGNIOL-VILLARD 	int space, n;
4691378df79SJean-Christophe PLAGNIOL-VILLARD 
4701378df79SJean-Christophe PLAGNIOL-VILLARD 	/* break str into chunks < buffer size, if needed */
4711378df79SJean-Christophe PLAGNIOL-VILLARD 	while (len > 0) {
4721378df79SJean-Christophe PLAGNIOL-VILLARD 		usbtty_poll ();
4731378df79SJean-Christophe PLAGNIOL-VILLARD 
4741378df79SJean-Christophe PLAGNIOL-VILLARD 		space = maxlen - usbtty_output.size;
4751378df79SJean-Christophe PLAGNIOL-VILLARD 		/* Empty buffer here, if needed, to ensure space... */
4761378df79SJean-Christophe PLAGNIOL-VILLARD 		if (space) {
4771378df79SJean-Christophe PLAGNIOL-VILLARD 			write_buffer (&usbtty_output);
4781378df79SJean-Christophe PLAGNIOL-VILLARD 
479c79cba37SMasahiro Yamada 			n = min(space, min(len, maxlen));
4801378df79SJean-Christophe PLAGNIOL-VILLARD 			buf_push (&usbtty_output, str, n);
4811378df79SJean-Christophe PLAGNIOL-VILLARD 
4821378df79SJean-Christophe PLAGNIOL-VILLARD 			str += n;
4831378df79SJean-Christophe PLAGNIOL-VILLARD 			len -= n;
4841378df79SJean-Christophe PLAGNIOL-VILLARD 		}
4851378df79SJean-Christophe PLAGNIOL-VILLARD 	}
4861378df79SJean-Christophe PLAGNIOL-VILLARD }
4871378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_puts(struct stdio_dev * dev,const char * str)488709ea543SSimon Glass void usbtty_puts(struct stdio_dev *dev, const char *str)
4891378df79SJean-Christophe PLAGNIOL-VILLARD {
4901378df79SJean-Christophe PLAGNIOL-VILLARD 	int n;
491f3c0de63SAtin Malaviya 	int len;
4921378df79SJean-Christophe PLAGNIOL-VILLARD 
493f3c0de63SAtin Malaviya 	if (!usbtty_configured ())
494f3c0de63SAtin Malaviya 		return;
495f3c0de63SAtin Malaviya 
496f3c0de63SAtin Malaviya 	len = strlen (str);
4971378df79SJean-Christophe PLAGNIOL-VILLARD 	/* add '\r' for each '\n' */
4981378df79SJean-Christophe PLAGNIOL-VILLARD 	while (len > 0) {
4991378df79SJean-Christophe PLAGNIOL-VILLARD 		n = next_nl_pos (str);
5001378df79SJean-Christophe PLAGNIOL-VILLARD 
5011378df79SJean-Christophe PLAGNIOL-VILLARD 		if (str[n] == '\n') {
5021378df79SJean-Christophe PLAGNIOL-VILLARD 			__usbtty_puts("\r", 1);
503055457efSAlison Wang 			__usbtty_puts(str, n + 1);
5041378df79SJean-Christophe PLAGNIOL-VILLARD 			str += (n + 1);
5051378df79SJean-Christophe PLAGNIOL-VILLARD 			len -= (n + 1);
5061378df79SJean-Christophe PLAGNIOL-VILLARD 		} else {
5071378df79SJean-Christophe PLAGNIOL-VILLARD 			/* No \n found.	 All done. */
5081378df79SJean-Christophe PLAGNIOL-VILLARD 			__usbtty_puts (str, n);
5091378df79SJean-Christophe PLAGNIOL-VILLARD 			break;
5101378df79SJean-Christophe PLAGNIOL-VILLARD 		}
5111378df79SJean-Christophe PLAGNIOL-VILLARD 	}
5121378df79SJean-Christophe PLAGNIOL-VILLARD 
5131378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Poll at end to handle new data... */
5141378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_poll ();
5151378df79SJean-Christophe PLAGNIOL-VILLARD }
5161378df79SJean-Christophe PLAGNIOL-VILLARD 
5171378df79SJean-Christophe PLAGNIOL-VILLARD /*
5181378df79SJean-Christophe PLAGNIOL-VILLARD  * Initialize the usb client port.
5191378df79SJean-Christophe PLAGNIOL-VILLARD  *
5201378df79SJean-Christophe PLAGNIOL-VILLARD  */
drv_usbtty_init(void)5211378df79SJean-Christophe PLAGNIOL-VILLARD int drv_usbtty_init (void)
5221378df79SJean-Christophe PLAGNIOL-VILLARD {
5231378df79SJean-Christophe PLAGNIOL-VILLARD 	int rc;
5241378df79SJean-Christophe PLAGNIOL-VILLARD 	char * sn;
5251378df79SJean-Christophe PLAGNIOL-VILLARD 	char * tt;
5261378df79SJean-Christophe PLAGNIOL-VILLARD 	int snlen;
5271378df79SJean-Christophe PLAGNIOL-VILLARD 
528*02234e49SHeinrich Schuchardt 	/* Get serial number */
52900caae6dSSimon Glass 	sn = env_get("serial#");
53000caae6dSSimon Glass 	if (!sn)
5311378df79SJean-Christophe PLAGNIOL-VILLARD 		sn = "000000000000";
5321378df79SJean-Christophe PLAGNIOL-VILLARD 	snlen = strlen(sn);
5331378df79SJean-Christophe PLAGNIOL-VILLARD 	if (snlen > sizeof(serial_number) - 1) {
534b64f190bSWolfgang Denk 		printf ("Warning: serial number %s is too long (%d > %lu)\n",
535b64f190bSWolfgang Denk 			sn, snlen, (ulong)(sizeof(serial_number) - 1));
5361378df79SJean-Christophe PLAGNIOL-VILLARD 		snlen = sizeof(serial_number) - 1;
5371378df79SJean-Christophe PLAGNIOL-VILLARD 	}
5381378df79SJean-Christophe PLAGNIOL-VILLARD 	memcpy (serial_number, sn, snlen);
5391378df79SJean-Christophe PLAGNIOL-VILLARD 	serial_number[snlen] = '\0';
5401378df79SJean-Christophe PLAGNIOL-VILLARD 
5411378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Decide on which type of UDC device to be.
5421378df79SJean-Christophe PLAGNIOL-VILLARD 	 */
54300caae6dSSimon Glass 	tt = env_get("usbtty");
54400caae6dSSimon Glass 	if (!tt)
5451378df79SJean-Christophe PLAGNIOL-VILLARD 		tt = "generic";
5461378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_init_terminal_type(strcmp(tt,"cdc_acm"));
5471378df79SJean-Christophe PLAGNIOL-VILLARD 
5481378df79SJean-Christophe PLAGNIOL-VILLARD 	/* prepare buffers... */
5491378df79SJean-Christophe PLAGNIOL-VILLARD 	buf_init (&usbtty_input, USBTTY_BUFFER_SIZE);
5501378df79SJean-Christophe PLAGNIOL-VILLARD 	buf_init (&usbtty_output, USBTTY_BUFFER_SIZE);
5511378df79SJean-Christophe PLAGNIOL-VILLARD 
5521378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Now, set up USB controller and infrastructure */
5531378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_init ();		/* Basic USB initialization */
5541378df79SJean-Christophe PLAGNIOL-VILLARD 
5551378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_init_strings ();
5561378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_init_instances ();
5571378df79SJean-Christophe PLAGNIOL-VILLARD 
558241d9a61SStefan Herbrechtsmeier 	usbtty_init_endpoints ();
559241d9a61SStefan Herbrechtsmeier 
5601378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_startup_events (device_instance);/* Enable dev, init udc pointers */
5611378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_connect ();		/* Enable pullup for host detection */
5621378df79SJean-Christophe PLAGNIOL-VILLARD 
5631378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Device initialization */
5641378df79SJean-Christophe PLAGNIOL-VILLARD 	memset (&usbttydev, 0, sizeof (usbttydev));
5651378df79SJean-Christophe PLAGNIOL-VILLARD 
5661378df79SJean-Christophe PLAGNIOL-VILLARD 	strcpy (usbttydev.name, "usbtty");
5671378df79SJean-Christophe PLAGNIOL-VILLARD 	usbttydev.ext = 0;	/* No extensions */
5681378df79SJean-Christophe PLAGNIOL-VILLARD 	usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT;
5691378df79SJean-Christophe PLAGNIOL-VILLARD 	usbttydev.tstc = usbtty_tstc;	/* 'tstc' function */
5701378df79SJean-Christophe PLAGNIOL-VILLARD 	usbttydev.getc = usbtty_getc;	/* 'getc' function */
5711378df79SJean-Christophe PLAGNIOL-VILLARD 	usbttydev.putc = usbtty_putc;	/* 'putc' function */
5721378df79SJean-Christophe PLAGNIOL-VILLARD 	usbttydev.puts = usbtty_puts;	/* 'puts' function */
5731378df79SJean-Christophe PLAGNIOL-VILLARD 
57452cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	rc = stdio_register (&usbttydev);
5751378df79SJean-Christophe PLAGNIOL-VILLARD 
5761378df79SJean-Christophe PLAGNIOL-VILLARD 	return (rc == 0) ? 1 : rc;
5771378df79SJean-Christophe PLAGNIOL-VILLARD }
5781378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_init_strings(void)5791378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_strings (void)
5801378df79SJean-Christophe PLAGNIOL-VILLARD {
5811378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_string_descriptor *string;
5821378df79SJean-Christophe PLAGNIOL-VILLARD 
5831378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_string_table[STR_LANG] =
5841378df79SJean-Christophe PLAGNIOL-VILLARD 		(struct usb_string_descriptor*)wstrLang;
5851378df79SJean-Christophe PLAGNIOL-VILLARD 
5861378df79SJean-Christophe PLAGNIOL-VILLARD 	string = (struct usb_string_descriptor *) wstrManufacturer;
5871378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bLength = sizeof(wstrManufacturer);
5881378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bDescriptorType = USB_DT_STRING;
5891378df79SJean-Christophe PLAGNIOL-VILLARD 	str2wide (CONFIG_USBD_MANUFACTURER, string->wData);
5901378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_string_table[STR_MANUFACTURER]=string;
5911378df79SJean-Christophe PLAGNIOL-VILLARD 
5921378df79SJean-Christophe PLAGNIOL-VILLARD 
5931378df79SJean-Christophe PLAGNIOL-VILLARD 	string = (struct usb_string_descriptor *) wstrProduct;
5941378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bLength = sizeof(wstrProduct);
5951378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bDescriptorType = USB_DT_STRING;
5961378df79SJean-Christophe PLAGNIOL-VILLARD 	str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData);
5971378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_string_table[STR_PRODUCT]=string;
5981378df79SJean-Christophe PLAGNIOL-VILLARD 
5991378df79SJean-Christophe PLAGNIOL-VILLARD 
6001378df79SJean-Christophe PLAGNIOL-VILLARD 	string = (struct usb_string_descriptor *) wstrSerial;
6011378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bLength = sizeof(serial_number);
6021378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bDescriptorType = USB_DT_STRING;
6031378df79SJean-Christophe PLAGNIOL-VILLARD 	str2wide (serial_number, string->wData);
6041378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_string_table[STR_SERIAL]=string;
6051378df79SJean-Christophe PLAGNIOL-VILLARD 
6061378df79SJean-Christophe PLAGNIOL-VILLARD 
6071378df79SJean-Christophe PLAGNIOL-VILLARD 	string = (struct usb_string_descriptor *) wstrConfiguration;
6081378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bLength = sizeof(wstrConfiguration);
6091378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bDescriptorType = USB_DT_STRING;
6101378df79SJean-Christophe PLAGNIOL-VILLARD 	str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData);
6111378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_string_table[STR_CONFIG]=string;
6121378df79SJean-Christophe PLAGNIOL-VILLARD 
6131378df79SJean-Christophe PLAGNIOL-VILLARD 
6141378df79SJean-Christophe PLAGNIOL-VILLARD 	string = (struct usb_string_descriptor *) wstrDataInterface;
6151378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bLength = sizeof(wstrDataInterface);
6161378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bDescriptorType = USB_DT_STRING;
6171378df79SJean-Christophe PLAGNIOL-VILLARD 	str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData);
6181378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_string_table[STR_DATA_INTERFACE]=string;
6191378df79SJean-Christophe PLAGNIOL-VILLARD 
6201378df79SJean-Christophe PLAGNIOL-VILLARD 	string = (struct usb_string_descriptor *) wstrCtrlInterface;
6211378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bLength = sizeof(wstrCtrlInterface);
6221378df79SJean-Christophe PLAGNIOL-VILLARD 	string->bDescriptorType = USB_DT_STRING;
6231378df79SJean-Christophe PLAGNIOL-VILLARD 	str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData);
6241378df79SJean-Christophe PLAGNIOL-VILLARD 	usbtty_string_table[STR_CTRL_INTERFACE]=string;
6251378df79SJean-Christophe PLAGNIOL-VILLARD 
6261378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Now, initialize the string table for ep0 handling */
6271378df79SJean-Christophe PLAGNIOL-VILLARD 	usb_strings = usbtty_string_table;
6281378df79SJean-Christophe PLAGNIOL-VILLARD }
6291378df79SJean-Christophe PLAGNIOL-VILLARD 
630b2fb47f1STom Rini #define init_wMaxPacketSize(x)	le16_to_cpu(get_unaligned(\
631b2fb47f1STom Rini 			&ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize));
632b2fb47f1STom Rini 
usbtty_init_instances(void)6331378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_instances (void)
6341378df79SJean-Christophe PLAGNIOL-VILLARD {
6351378df79SJean-Christophe PLAGNIOL-VILLARD 	int i;
6361378df79SJean-Christophe PLAGNIOL-VILLARD 
6371378df79SJean-Christophe PLAGNIOL-VILLARD 	/* initialize device instance */
6381378df79SJean-Christophe PLAGNIOL-VILLARD 	memset (device_instance, 0, sizeof (struct usb_device_instance));
6391378df79SJean-Christophe PLAGNIOL-VILLARD 	device_instance->device_state = STATE_INIT;
6401378df79SJean-Christophe PLAGNIOL-VILLARD 	device_instance->device_descriptor = &device_descriptor;
641f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS)
642f9da0f89SVipin KUMAR 	device_instance->qualifier_descriptor = &qualifier_descriptor;
643f9da0f89SVipin KUMAR #endif
6441378df79SJean-Christophe PLAGNIOL-VILLARD 	device_instance->event = usbtty_event_handler;
6451378df79SJean-Christophe PLAGNIOL-VILLARD 	device_instance->cdc_recv_setup = usbtty_cdc_setup;
6461378df79SJean-Christophe PLAGNIOL-VILLARD 	device_instance->bus = bus_instance;
6471378df79SJean-Christophe PLAGNIOL-VILLARD 	device_instance->configurations = NUM_CONFIGS;
6481378df79SJean-Christophe PLAGNIOL-VILLARD 	device_instance->configuration_instance_array = config_instance;
6491378df79SJean-Christophe PLAGNIOL-VILLARD 
6501378df79SJean-Christophe PLAGNIOL-VILLARD 	/* initialize bus instance */
6511378df79SJean-Christophe PLAGNIOL-VILLARD 	memset (bus_instance, 0, sizeof (struct usb_bus_instance));
6521378df79SJean-Christophe PLAGNIOL-VILLARD 	bus_instance->device = device_instance;
6531378df79SJean-Christophe PLAGNIOL-VILLARD 	bus_instance->endpoint_array = endpoint_instance;
6541378df79SJean-Christophe PLAGNIOL-VILLARD 	bus_instance->max_endpoints = 1;
6551378df79SJean-Christophe PLAGNIOL-VILLARD 	bus_instance->maxpacketsize = 64;
6561378df79SJean-Christophe PLAGNIOL-VILLARD 	bus_instance->serial_number_str = serial_number;
6571378df79SJean-Christophe PLAGNIOL-VILLARD 
6581378df79SJean-Christophe PLAGNIOL-VILLARD 	/* configuration instance */
6591378df79SJean-Christophe PLAGNIOL-VILLARD 	memset (config_instance, 0,
6601378df79SJean-Christophe PLAGNIOL-VILLARD 		sizeof (struct usb_configuration_instance));
6611378df79SJean-Christophe PLAGNIOL-VILLARD 	config_instance->interfaces = interface_count;
6621378df79SJean-Christophe PLAGNIOL-VILLARD 	config_instance->configuration_descriptor = configuration_descriptor;
6631378df79SJean-Christophe PLAGNIOL-VILLARD 	config_instance->interface_instance_array = interface_instance;
6641378df79SJean-Christophe PLAGNIOL-VILLARD 
6651378df79SJean-Christophe PLAGNIOL-VILLARD 	/* interface instance */
6661378df79SJean-Christophe PLAGNIOL-VILLARD 	memset (interface_instance, 0,
6671378df79SJean-Christophe PLAGNIOL-VILLARD 		sizeof (struct usb_interface_instance));
6681378df79SJean-Christophe PLAGNIOL-VILLARD 	interface_instance->alternates = 1;
6691378df79SJean-Christophe PLAGNIOL-VILLARD 	interface_instance->alternates_instance_array = alternate_instance;
6701378df79SJean-Christophe PLAGNIOL-VILLARD 
6711378df79SJean-Christophe PLAGNIOL-VILLARD 	/* alternates instance */
6721378df79SJean-Christophe PLAGNIOL-VILLARD 	memset (alternate_instance, 0,
6731378df79SJean-Christophe PLAGNIOL-VILLARD 		sizeof (struct usb_alternate_instance));
6741378df79SJean-Christophe PLAGNIOL-VILLARD 	alternate_instance->interface_descriptor = interface_descriptors;
6751378df79SJean-Christophe PLAGNIOL-VILLARD 	alternate_instance->endpoints = NUM_ENDPOINTS;
6761378df79SJean-Christophe PLAGNIOL-VILLARD 	alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs;
6771378df79SJean-Christophe PLAGNIOL-VILLARD 
6781378df79SJean-Christophe PLAGNIOL-VILLARD 	/* endpoint instances */
6791378df79SJean-Christophe PLAGNIOL-VILLARD 	memset (&endpoint_instance[0], 0,
6801378df79SJean-Christophe PLAGNIOL-VILLARD 		sizeof (struct usb_endpoint_instance));
6811378df79SJean-Christophe PLAGNIOL-VILLARD 	endpoint_instance[0].endpoint_address = 0;
6821378df79SJean-Christophe PLAGNIOL-VILLARD 	endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE;
6831378df79SJean-Christophe PLAGNIOL-VILLARD 	endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL;
6841378df79SJean-Christophe PLAGNIOL-VILLARD 	endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE;
6851378df79SJean-Christophe PLAGNIOL-VILLARD 	endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL;
6861378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_setup_ep (device_instance, 0, &endpoint_instance[0]);
6871378df79SJean-Christophe PLAGNIOL-VILLARD 
6881378df79SJean-Christophe PLAGNIOL-VILLARD 	for (i = 1; i <= NUM_ENDPOINTS; i++) {
6891378df79SJean-Christophe PLAGNIOL-VILLARD 		memset (&endpoint_instance[i], 0,
6901378df79SJean-Christophe PLAGNIOL-VILLARD 			sizeof (struct usb_endpoint_instance));
6911378df79SJean-Christophe PLAGNIOL-VILLARD 
6921378df79SJean-Christophe PLAGNIOL-VILLARD 		endpoint_instance[i].endpoint_address =
6931378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[i - 1]->bEndpointAddress;
6941378df79SJean-Christophe PLAGNIOL-VILLARD 
6951378df79SJean-Christophe PLAGNIOL-VILLARD 		endpoint_instance[i].rcv_attributes =
6961378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[i - 1]->bmAttributes;
6971378df79SJean-Christophe PLAGNIOL-VILLARD 
698b2fb47f1STom Rini 		endpoint_instance[i].rcv_packetSize = init_wMaxPacketSize(i);
6991378df79SJean-Christophe PLAGNIOL-VILLARD 
7001378df79SJean-Christophe PLAGNIOL-VILLARD 		endpoint_instance[i].tx_attributes =
7011378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[i - 1]->bmAttributes;
7021378df79SJean-Christophe PLAGNIOL-VILLARD 
703b2fb47f1STom Rini 		endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i);
7041378df79SJean-Christophe PLAGNIOL-VILLARD 
7051378df79SJean-Christophe PLAGNIOL-VILLARD 		endpoint_instance[i].tx_attributes =
7061378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[i - 1]->bmAttributes;
7071378df79SJean-Christophe PLAGNIOL-VILLARD 
7081378df79SJean-Christophe PLAGNIOL-VILLARD 		urb_link_init (&endpoint_instance[i].rcv);
7091378df79SJean-Christophe PLAGNIOL-VILLARD 		urb_link_init (&endpoint_instance[i].rdy);
7101378df79SJean-Christophe PLAGNIOL-VILLARD 		urb_link_init (&endpoint_instance[i].tx);
7111378df79SJean-Christophe PLAGNIOL-VILLARD 		urb_link_init (&endpoint_instance[i].done);
7121378df79SJean-Christophe PLAGNIOL-VILLARD 
7131378df79SJean-Christophe PLAGNIOL-VILLARD 		if (endpoint_instance[i].endpoint_address & USB_DIR_IN)
7141378df79SJean-Christophe PLAGNIOL-VILLARD 			endpoint_instance[i].tx_urb =
7151378df79SJean-Christophe PLAGNIOL-VILLARD 				usbd_alloc_urb (device_instance,
7161378df79SJean-Christophe PLAGNIOL-VILLARD 						&endpoint_instance[i]);
7171378df79SJean-Christophe PLAGNIOL-VILLARD 		else
7181378df79SJean-Christophe PLAGNIOL-VILLARD 			endpoint_instance[i].rcv_urb =
7191378df79SJean-Christophe PLAGNIOL-VILLARD 				usbd_alloc_urb (device_instance,
7201378df79SJean-Christophe PLAGNIOL-VILLARD 						&endpoint_instance[i]);
7211378df79SJean-Christophe PLAGNIOL-VILLARD 	}
7221378df79SJean-Christophe PLAGNIOL-VILLARD }
7231378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_init_endpoints(void)7241378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_endpoints (void)
7251378df79SJean-Christophe PLAGNIOL-VILLARD {
7261378df79SJean-Christophe PLAGNIOL-VILLARD 	int i;
7271378df79SJean-Christophe PLAGNIOL-VILLARD 
7281378df79SJean-Christophe PLAGNIOL-VILLARD 	bus_instance->max_endpoints = NUM_ENDPOINTS + 1;
7291378df79SJean-Christophe PLAGNIOL-VILLARD 	for (i = 1; i <= NUM_ENDPOINTS; i++) {
7301378df79SJean-Christophe PLAGNIOL-VILLARD 		udc_setup_ep (device_instance, i, &endpoint_instance[i]);
7311378df79SJean-Christophe PLAGNIOL-VILLARD 	}
7321378df79SJean-Christophe PLAGNIOL-VILLARD }
7331378df79SJean-Christophe PLAGNIOL-VILLARD 
7341378df79SJean-Christophe PLAGNIOL-VILLARD /* usbtty_init_terminal_type
7351378df79SJean-Christophe PLAGNIOL-VILLARD  *
7361378df79SJean-Christophe PLAGNIOL-VILLARD  * Do some late binding for our device type.
7371378df79SJean-Christophe PLAGNIOL-VILLARD  */
usbtty_init_terminal_type(short type)7381378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_init_terminal_type(short type)
7391378df79SJean-Christophe PLAGNIOL-VILLARD {
7401378df79SJean-Christophe PLAGNIOL-VILLARD 	switch(type){
7411378df79SJean-Christophe PLAGNIOL-VILLARD 		/* CDC ACM */
7421378df79SJean-Christophe PLAGNIOL-VILLARD 		case 0:
7431378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Assign endpoint descriptors */
7441378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[0] =
7451378df79SJean-Christophe PLAGNIOL-VILLARD 				&acm_configuration_descriptors[0].notification_endpoint;
7461378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[1] =
7471378df79SJean-Christophe PLAGNIOL-VILLARD 				&acm_configuration_descriptors[0].data_endpoints[0];
7481378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[2] =
7491378df79SJean-Christophe PLAGNIOL-VILLARD 				&acm_configuration_descriptors[0].data_endpoints[1];
7501378df79SJean-Christophe PLAGNIOL-VILLARD 
7511378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Enumerate Device Descriptor */
7521378df79SJean-Christophe PLAGNIOL-VILLARD 			device_descriptor.bDeviceClass =
7531378df79SJean-Christophe PLAGNIOL-VILLARD 				COMMUNICATIONS_DEVICE_CLASS;
7541378df79SJean-Christophe PLAGNIOL-VILLARD 			device_descriptor.idProduct =
7551378df79SJean-Christophe PLAGNIOL-VILLARD 				cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM);
7561378df79SJean-Christophe PLAGNIOL-VILLARD 
757f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS)
758f9da0f89SVipin KUMAR 			qualifier_descriptor.bDeviceClass =
759f9da0f89SVipin KUMAR 				COMMUNICATIONS_DEVICE_CLASS;
760f9da0f89SVipin KUMAR #endif
7611378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Assign endpoint indices */
7621378df79SJean-Christophe PLAGNIOL-VILLARD 			tx_endpoint = ACM_TX_ENDPOINT;
7631378df79SJean-Christophe PLAGNIOL-VILLARD 			rx_endpoint = ACM_RX_ENDPOINT;
7641378df79SJean-Christophe PLAGNIOL-VILLARD 
7651378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Configuration Descriptor */
7661378df79SJean-Christophe PLAGNIOL-VILLARD 			configuration_descriptor =
7671378df79SJean-Christophe PLAGNIOL-VILLARD 				(struct usb_configuration_descriptor*)
7681378df79SJean-Christophe PLAGNIOL-VILLARD 				&acm_configuration_descriptors;
7691378df79SJean-Christophe PLAGNIOL-VILLARD 
7701378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Interface count */
7711378df79SJean-Christophe PLAGNIOL-VILLARD 			interface_count = NUM_ACM_INTERFACES;
7721378df79SJean-Christophe PLAGNIOL-VILLARD 		break;
7731378df79SJean-Christophe PLAGNIOL-VILLARD 
7741378df79SJean-Christophe PLAGNIOL-VILLARD 		/* BULK IN/OUT & Default */
7751378df79SJean-Christophe PLAGNIOL-VILLARD 		case 1:
7761378df79SJean-Christophe PLAGNIOL-VILLARD 		default:
7771378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Assign endpoint descriptors */
7781378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[0] =
7791378df79SJean-Christophe PLAGNIOL-VILLARD 				&gserial_configuration_descriptors[0].data_endpoints[0];
7801378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[1] =
7811378df79SJean-Christophe PLAGNIOL-VILLARD 				&gserial_configuration_descriptors[0].data_endpoints[1];
7821378df79SJean-Christophe PLAGNIOL-VILLARD 			ep_descriptor_ptrs[2] =
7831378df79SJean-Christophe PLAGNIOL-VILLARD 				&gserial_configuration_descriptors[0].data_endpoints[2];
7841378df79SJean-Christophe PLAGNIOL-VILLARD 
7851378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Enumerate Device Descriptor */
7861378df79SJean-Christophe PLAGNIOL-VILLARD 			device_descriptor.bDeviceClass = 0xFF;
7871378df79SJean-Christophe PLAGNIOL-VILLARD 			device_descriptor.idProduct =
7881378df79SJean-Christophe PLAGNIOL-VILLARD 				cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL);
789f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS)
790f9da0f89SVipin KUMAR 			qualifier_descriptor.bDeviceClass = 0xFF;
791f9da0f89SVipin KUMAR #endif
7921378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Assign endpoint indices */
7931378df79SJean-Christophe PLAGNIOL-VILLARD 			tx_endpoint = GSERIAL_TX_ENDPOINT;
7941378df79SJean-Christophe PLAGNIOL-VILLARD 			rx_endpoint = GSERIAL_RX_ENDPOINT;
7951378df79SJean-Christophe PLAGNIOL-VILLARD 
7961378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Configuration Descriptor */
7971378df79SJean-Christophe PLAGNIOL-VILLARD 			configuration_descriptor =
7981378df79SJean-Christophe PLAGNIOL-VILLARD 				(struct usb_configuration_descriptor*)
7991378df79SJean-Christophe PLAGNIOL-VILLARD 				&gserial_configuration_descriptors;
8001378df79SJean-Christophe PLAGNIOL-VILLARD 
8011378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Interface count */
8021378df79SJean-Christophe PLAGNIOL-VILLARD 			interface_count = NUM_GSERIAL_INTERFACES;
8031378df79SJean-Christophe PLAGNIOL-VILLARD 		break;
8041378df79SJean-Christophe PLAGNIOL-VILLARD 	}
8051378df79SJean-Christophe PLAGNIOL-VILLARD }
8061378df79SJean-Christophe PLAGNIOL-VILLARD 
8071378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/
8081378df79SJean-Christophe PLAGNIOL-VILLARD 
next_urb(struct usb_device_instance * device,struct usb_endpoint_instance * endpoint)8091378df79SJean-Christophe PLAGNIOL-VILLARD static struct urb *next_urb (struct usb_device_instance *device,
8101378df79SJean-Christophe PLAGNIOL-VILLARD 			     struct usb_endpoint_instance *endpoint)
8111378df79SJean-Christophe PLAGNIOL-VILLARD {
8121378df79SJean-Christophe PLAGNIOL-VILLARD 	struct urb *current_urb = NULL;
8131378df79SJean-Christophe PLAGNIOL-VILLARD 	int space;
8141378df79SJean-Christophe PLAGNIOL-VILLARD 
8151378df79SJean-Christophe PLAGNIOL-VILLARD 	/* If there's a queue, then we should add to the last urb */
8161378df79SJean-Christophe PLAGNIOL-VILLARD 	if (!endpoint->tx_queue) {
8171378df79SJean-Christophe PLAGNIOL-VILLARD 		current_urb = endpoint->tx_urb;
8181378df79SJean-Christophe PLAGNIOL-VILLARD 	} else {
8191378df79SJean-Christophe PLAGNIOL-VILLARD 		/* Last urb from tx chain */
8201378df79SJean-Christophe PLAGNIOL-VILLARD 		current_urb =
8211378df79SJean-Christophe PLAGNIOL-VILLARD 			p2surround (struct urb, link, endpoint->tx.prev);
8221378df79SJean-Christophe PLAGNIOL-VILLARD 	}
8231378df79SJean-Christophe PLAGNIOL-VILLARD 
8241378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Make sure this one has enough room */
8251378df79SJean-Christophe PLAGNIOL-VILLARD 	space = current_urb->buffer_length - current_urb->actual_length;
8261378df79SJean-Christophe PLAGNIOL-VILLARD 	if (space > 0) {
8271378df79SJean-Christophe PLAGNIOL-VILLARD 		return current_urb;
8281378df79SJean-Christophe PLAGNIOL-VILLARD 	} else {		/* No space here */
8291378df79SJean-Christophe PLAGNIOL-VILLARD 		/* First look at done list */
8301378df79SJean-Christophe PLAGNIOL-VILLARD 		current_urb = first_urb_detached (&endpoint->done);
8311378df79SJean-Christophe PLAGNIOL-VILLARD 		if (!current_urb) {
8321378df79SJean-Christophe PLAGNIOL-VILLARD 			current_urb = usbd_alloc_urb (device, endpoint);
8331378df79SJean-Christophe PLAGNIOL-VILLARD 		}
8341378df79SJean-Christophe PLAGNIOL-VILLARD 
8351378df79SJean-Christophe PLAGNIOL-VILLARD 		urb_append (&endpoint->tx, current_urb);
8361378df79SJean-Christophe PLAGNIOL-VILLARD 		endpoint->tx_queue++;
8371378df79SJean-Christophe PLAGNIOL-VILLARD 	}
8381378df79SJean-Christophe PLAGNIOL-VILLARD 	return current_urb;
8391378df79SJean-Christophe PLAGNIOL-VILLARD }
8401378df79SJean-Christophe PLAGNIOL-VILLARD 
write_buffer(circbuf_t * buf)8411378df79SJean-Christophe PLAGNIOL-VILLARD static int write_buffer (circbuf_t * buf)
8421378df79SJean-Christophe PLAGNIOL-VILLARD {
8431378df79SJean-Christophe PLAGNIOL-VILLARD 	if (!usbtty_configured ()) {
8441378df79SJean-Christophe PLAGNIOL-VILLARD 		return 0;
8451378df79SJean-Christophe PLAGNIOL-VILLARD 	}
8461378df79SJean-Christophe PLAGNIOL-VILLARD 
8471378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_endpoint_instance *endpoint =
8481378df79SJean-Christophe PLAGNIOL-VILLARD 			&endpoint_instance[tx_endpoint];
8491378df79SJean-Christophe PLAGNIOL-VILLARD 	struct urb *current_urb = NULL;
8501378df79SJean-Christophe PLAGNIOL-VILLARD 
8511378df79SJean-Christophe PLAGNIOL-VILLARD 	current_urb = next_urb (device_instance, endpoint);
85273be5b3fSxypron.glpk@gmx.de 
85373be5b3fSxypron.glpk@gmx.de 	if (!current_urb) {
85473be5b3fSxypron.glpk@gmx.de 		TTYERR ("current_urb is NULL, buf->size %d\n",
85573be5b3fSxypron.glpk@gmx.de 		buf->size);
85673be5b3fSxypron.glpk@gmx.de 		return 0;
85773be5b3fSxypron.glpk@gmx.de 	}
85873be5b3fSxypron.glpk@gmx.de 
8591378df79SJean-Christophe PLAGNIOL-VILLARD 	/* TX data still exists - send it now
8601378df79SJean-Christophe PLAGNIOL-VILLARD 	 */
8611378df79SJean-Christophe PLAGNIOL-VILLARD 	if(endpoint->sent < current_urb->actual_length){
8621378df79SJean-Christophe PLAGNIOL-VILLARD 		if(udc_endpoint_write (endpoint)){
8631378df79SJean-Christophe PLAGNIOL-VILLARD 			/* Write pre-empted by RX */
8641378df79SJean-Christophe PLAGNIOL-VILLARD 			return -1;
8651378df79SJean-Christophe PLAGNIOL-VILLARD 		}
8661378df79SJean-Christophe PLAGNIOL-VILLARD 	}
8671378df79SJean-Christophe PLAGNIOL-VILLARD 
8681378df79SJean-Christophe PLAGNIOL-VILLARD 	if (buf->size) {
8691378df79SJean-Christophe PLAGNIOL-VILLARD 		char *dest;
8701378df79SJean-Christophe PLAGNIOL-VILLARD 
8711378df79SJean-Christophe PLAGNIOL-VILLARD 		int space_avail;
8721378df79SJean-Christophe PLAGNIOL-VILLARD 		int popnum, popped;
8731378df79SJean-Christophe PLAGNIOL-VILLARD 		int total = 0;
8741378df79SJean-Christophe PLAGNIOL-VILLARD 
8751378df79SJean-Christophe PLAGNIOL-VILLARD 		/* Break buffer into urb sized pieces,
8761378df79SJean-Christophe PLAGNIOL-VILLARD 		 * and link each to the endpoint
8771378df79SJean-Christophe PLAGNIOL-VILLARD 		 */
8781378df79SJean-Christophe PLAGNIOL-VILLARD 		while (buf->size > 0) {
8791378df79SJean-Christophe PLAGNIOL-VILLARD 
8801378df79SJean-Christophe PLAGNIOL-VILLARD 			dest = (char*)current_urb->buffer +
8811378df79SJean-Christophe PLAGNIOL-VILLARD 				current_urb->actual_length;
8821378df79SJean-Christophe PLAGNIOL-VILLARD 
8831378df79SJean-Christophe PLAGNIOL-VILLARD 			space_avail =
8841378df79SJean-Christophe PLAGNIOL-VILLARD 				current_urb->buffer_length -
8851378df79SJean-Christophe PLAGNIOL-VILLARD 				current_urb->actual_length;
886b4141195SMasahiro Yamada 			popnum = min(space_avail, (int)buf->size);
8871378df79SJean-Christophe PLAGNIOL-VILLARD 			if (popnum == 0)
8881378df79SJean-Christophe PLAGNIOL-VILLARD 				break;
8891378df79SJean-Christophe PLAGNIOL-VILLARD 
8901378df79SJean-Christophe PLAGNIOL-VILLARD 			popped = buf_pop (buf, dest, popnum);
8911378df79SJean-Christophe PLAGNIOL-VILLARD 			if (popped == 0)
8921378df79SJean-Christophe PLAGNIOL-VILLARD 				break;
8931378df79SJean-Christophe PLAGNIOL-VILLARD 			current_urb->actual_length += popped;
8941378df79SJean-Christophe PLAGNIOL-VILLARD 			total += popped;
8951378df79SJean-Christophe PLAGNIOL-VILLARD 
8961378df79SJean-Christophe PLAGNIOL-VILLARD 			/* If endpoint->last == 0, then transfers have
8971378df79SJean-Christophe PLAGNIOL-VILLARD 			 * not started on this endpoint
8981378df79SJean-Christophe PLAGNIOL-VILLARD 			 */
8991378df79SJean-Christophe PLAGNIOL-VILLARD 			if (endpoint->last == 0) {
9001378df79SJean-Christophe PLAGNIOL-VILLARD 				if(udc_endpoint_write (endpoint)){
9011378df79SJean-Christophe PLAGNIOL-VILLARD 					/* Write pre-empted by RX */
9021378df79SJean-Christophe PLAGNIOL-VILLARD 					return -1;
9031378df79SJean-Christophe PLAGNIOL-VILLARD 				}
9041378df79SJean-Christophe PLAGNIOL-VILLARD 			}
9051378df79SJean-Christophe PLAGNIOL-VILLARD 
9061378df79SJean-Christophe PLAGNIOL-VILLARD 		}/* end while */
9071378df79SJean-Christophe PLAGNIOL-VILLARD 		return total;
9081378df79SJean-Christophe PLAGNIOL-VILLARD 	}
9091378df79SJean-Christophe PLAGNIOL-VILLARD 
9101378df79SJean-Christophe PLAGNIOL-VILLARD 	return 0;
9111378df79SJean-Christophe PLAGNIOL-VILLARD }
9121378df79SJean-Christophe PLAGNIOL-VILLARD 
fill_buffer(circbuf_t * buf)9131378df79SJean-Christophe PLAGNIOL-VILLARD static int fill_buffer (circbuf_t * buf)
9141378df79SJean-Christophe PLAGNIOL-VILLARD {
9151378df79SJean-Christophe PLAGNIOL-VILLARD 	struct usb_endpoint_instance *endpoint =
9161378df79SJean-Christophe PLAGNIOL-VILLARD 		&endpoint_instance[rx_endpoint];
9171378df79SJean-Christophe PLAGNIOL-VILLARD 
9181378df79SJean-Christophe PLAGNIOL-VILLARD 	if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) {
9191378df79SJean-Christophe PLAGNIOL-VILLARD 		unsigned int nb = 0;
9201378df79SJean-Christophe PLAGNIOL-VILLARD 		char *src = (char *) endpoint->rcv_urb->buffer;
9211378df79SJean-Christophe PLAGNIOL-VILLARD 		unsigned int rx_avail = buf->totalsize - buf->size;
9221378df79SJean-Christophe PLAGNIOL-VILLARD 
9231378df79SJean-Christophe PLAGNIOL-VILLARD 		if(rx_avail >= endpoint->rcv_urb->actual_length){
9241378df79SJean-Christophe PLAGNIOL-VILLARD 
9251378df79SJean-Christophe PLAGNIOL-VILLARD 			nb = endpoint->rcv_urb->actual_length;
9261378df79SJean-Christophe PLAGNIOL-VILLARD 			buf_push (buf, src, nb);
9271378df79SJean-Christophe PLAGNIOL-VILLARD 			endpoint->rcv_urb->actual_length = 0;
9281378df79SJean-Christophe PLAGNIOL-VILLARD 
9291378df79SJean-Christophe PLAGNIOL-VILLARD 		}
9301378df79SJean-Christophe PLAGNIOL-VILLARD 		return nb;
9311378df79SJean-Christophe PLAGNIOL-VILLARD 	}
9321378df79SJean-Christophe PLAGNIOL-VILLARD 	return 0;
9331378df79SJean-Christophe PLAGNIOL-VILLARD }
9341378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_configured(void)9351378df79SJean-Christophe PLAGNIOL-VILLARD static int usbtty_configured (void)
9361378df79SJean-Christophe PLAGNIOL-VILLARD {
9371378df79SJean-Christophe PLAGNIOL-VILLARD 	return usbtty_configured_flag;
9381378df79SJean-Christophe PLAGNIOL-VILLARD }
9391378df79SJean-Christophe PLAGNIOL-VILLARD 
9401378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/
9411378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_event_handler(struct usb_device_instance * device,usb_device_event_t event,int data)9421378df79SJean-Christophe PLAGNIOL-VILLARD static void usbtty_event_handler (struct usb_device_instance *device,
9431378df79SJean-Christophe PLAGNIOL-VILLARD 				  usb_device_event_t event, int data)
9441378df79SJean-Christophe PLAGNIOL-VILLARD {
945f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS)
946f9da0f89SVipin KUMAR 	int i;
947f9da0f89SVipin KUMAR #endif
9481378df79SJean-Christophe PLAGNIOL-VILLARD 	switch (event) {
9491378df79SJean-Christophe PLAGNIOL-VILLARD 	case DEVICE_RESET:
9501378df79SJean-Christophe PLAGNIOL-VILLARD 	case DEVICE_BUS_INACTIVE:
9511378df79SJean-Christophe PLAGNIOL-VILLARD 		usbtty_configured_flag = 0;
9521378df79SJean-Christophe PLAGNIOL-VILLARD 		break;
9531378df79SJean-Christophe PLAGNIOL-VILLARD 	case DEVICE_CONFIGURED:
9541378df79SJean-Christophe PLAGNIOL-VILLARD 		usbtty_configured_flag = 1;
9551378df79SJean-Christophe PLAGNIOL-VILLARD 		break;
9561378df79SJean-Christophe PLAGNIOL-VILLARD 
9571378df79SJean-Christophe PLAGNIOL-VILLARD 	case DEVICE_ADDRESS_ASSIGNED:
958f9da0f89SVipin KUMAR #if defined(CONFIG_USBD_HS)
959f9da0f89SVipin KUMAR 		/*
960f9da0f89SVipin KUMAR 		 * is_usbd_high_speed routine needs to be defined by
961f9da0f89SVipin KUMAR 		 * specific gadget driver
962472d5460SYork Sun 		 * It returns true if device enumerates at High speed
963472d5460SYork Sun 		 * Retuns false otherwise
964f9da0f89SVipin KUMAR 		 */
965f9da0f89SVipin KUMAR 		for (i = 0; i < NUM_ENDPOINTS; i++) {
966f9da0f89SVipin KUMAR 			if (((ep_descriptor_ptrs[i]->bmAttributes &
967f9da0f89SVipin KUMAR 			      USB_ENDPOINT_XFERTYPE_MASK) ==
968f9da0f89SVipin KUMAR 			      USB_ENDPOINT_XFER_BULK)
969f9da0f89SVipin KUMAR 			    && is_usbd_high_speed()) {
970f9da0f89SVipin KUMAR 
971f9da0f89SVipin KUMAR 				ep_descriptor_ptrs[i]->wMaxPacketSize =
972f9da0f89SVipin KUMAR 					CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE;
973f9da0f89SVipin KUMAR 			}
974f9da0f89SVipin KUMAR 
975f9da0f89SVipin KUMAR 			endpoint_instance[i + 1].tx_packetSize =
976f9da0f89SVipin KUMAR 				ep_descriptor_ptrs[i]->wMaxPacketSize;
977f9da0f89SVipin KUMAR 			endpoint_instance[i + 1].rcv_packetSize =
978f9da0f89SVipin KUMAR 				ep_descriptor_ptrs[i]->wMaxPacketSize;
979f9da0f89SVipin KUMAR 		}
980f9da0f89SVipin KUMAR #endif
9811378df79SJean-Christophe PLAGNIOL-VILLARD 		usbtty_init_endpoints ();
9821378df79SJean-Christophe PLAGNIOL-VILLARD 
9831378df79SJean-Christophe PLAGNIOL-VILLARD 	default:
9841378df79SJean-Christophe PLAGNIOL-VILLARD 		break;
9851378df79SJean-Christophe PLAGNIOL-VILLARD 	}
9861378df79SJean-Christophe PLAGNIOL-VILLARD }
9871378df79SJean-Christophe PLAGNIOL-VILLARD 
9881378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/
9891378df79SJean-Christophe PLAGNIOL-VILLARD 
usbtty_cdc_setup(struct usb_device_request * request,struct urb * urb)9901378df79SJean-Christophe PLAGNIOL-VILLARD int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb)
9911378df79SJean-Christophe PLAGNIOL-VILLARD {
9921378df79SJean-Christophe PLAGNIOL-VILLARD 	switch (request->bRequest){
9931378df79SJean-Christophe PLAGNIOL-VILLARD 
9941378df79SJean-Christophe PLAGNIOL-VILLARD 		case ACM_SET_CONTROL_LINE_STATE:	/* Implies DTE ready */
9951378df79SJean-Christophe PLAGNIOL-VILLARD 			break;
9961378df79SJean-Christophe PLAGNIOL-VILLARD 		case ACM_SEND_ENCAPSULATED_COMMAND :	/* Required */
9971378df79SJean-Christophe PLAGNIOL-VILLARD 			break;
9981378df79SJean-Christophe PLAGNIOL-VILLARD 		case ACM_SET_LINE_ENCODING :		/* DTE stop/parity bits
9991378df79SJean-Christophe PLAGNIOL-VILLARD 							 * per character */
10001378df79SJean-Christophe PLAGNIOL-VILLARD 			break;
10011378df79SJean-Christophe PLAGNIOL-VILLARD 		case ACM_GET_ENCAPSULATED_RESPONSE :	/* request response */
10021378df79SJean-Christophe PLAGNIOL-VILLARD 			break;
10031378df79SJean-Christophe PLAGNIOL-VILLARD 		case ACM_GET_LINE_ENCODING :		/* request DTE rate,
10041378df79SJean-Christophe PLAGNIOL-VILLARD 							 * stop/parity bits */
10051378df79SJean-Christophe PLAGNIOL-VILLARD 			memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc));
10061378df79SJean-Christophe PLAGNIOL-VILLARD 			urb->actual_length = sizeof(rs232_desc);
10071378df79SJean-Christophe PLAGNIOL-VILLARD 
10081378df79SJean-Christophe PLAGNIOL-VILLARD 			break;
10091378df79SJean-Christophe PLAGNIOL-VILLARD 		default:
10101378df79SJean-Christophe PLAGNIOL-VILLARD 			return 1;
10111378df79SJean-Christophe PLAGNIOL-VILLARD 	}
10121378df79SJean-Christophe PLAGNIOL-VILLARD 	return 0;
10131378df79SJean-Christophe PLAGNIOL-VILLARD }
10141378df79SJean-Christophe PLAGNIOL-VILLARD 
10151378df79SJean-Christophe PLAGNIOL-VILLARD /******************************************************************************/
10161378df79SJean-Christophe PLAGNIOL-VILLARD 
10171378df79SJean-Christophe PLAGNIOL-VILLARD /*
10181378df79SJean-Christophe PLAGNIOL-VILLARD  * Since interrupt handling has not yet been implemented, we use this function
10191378df79SJean-Christophe PLAGNIOL-VILLARD  * to handle polling.  This is called by the tstc,getc,putc,puts routines to
10201378df79SJean-Christophe PLAGNIOL-VILLARD  * update the USB state.
10211378df79SJean-Christophe PLAGNIOL-VILLARD  */
usbtty_poll(void)10221378df79SJean-Christophe PLAGNIOL-VILLARD void usbtty_poll (void)
10231378df79SJean-Christophe PLAGNIOL-VILLARD {
10241378df79SJean-Christophe PLAGNIOL-VILLARD 	/* New interrupts? */
10251378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_irq();
10261378df79SJean-Christophe PLAGNIOL-VILLARD 
10271378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Write any output data to host buffer
10281378df79SJean-Christophe PLAGNIOL-VILLARD 	 * (do this before checking interrupts to avoid missing one)
10291378df79SJean-Christophe PLAGNIOL-VILLARD 	 */
10301378df79SJean-Christophe PLAGNIOL-VILLARD 	if (usbtty_configured ()) {
10311378df79SJean-Christophe PLAGNIOL-VILLARD 		write_buffer (&usbtty_output);
10321378df79SJean-Christophe PLAGNIOL-VILLARD 	}
10331378df79SJean-Christophe PLAGNIOL-VILLARD 
10341378df79SJean-Christophe PLAGNIOL-VILLARD 	/* New interrupts? */
10351378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_irq();
10361378df79SJean-Christophe PLAGNIOL-VILLARD 
10371378df79SJean-Christophe PLAGNIOL-VILLARD 	/* Check for new data from host..
10381378df79SJean-Christophe PLAGNIOL-VILLARD 	 * (do this after checking interrupts to get latest data)
10391378df79SJean-Christophe PLAGNIOL-VILLARD 	 */
10401378df79SJean-Christophe PLAGNIOL-VILLARD 	if (usbtty_configured ()) {
10411378df79SJean-Christophe PLAGNIOL-VILLARD 		fill_buffer (&usbtty_input);
10421378df79SJean-Christophe PLAGNIOL-VILLARD 	}
10431378df79SJean-Christophe PLAGNIOL-VILLARD 
10441378df79SJean-Christophe PLAGNIOL-VILLARD 	/* New interrupts? */
10451378df79SJean-Christophe PLAGNIOL-VILLARD 	udc_irq();
10461378df79SJean-Christophe PLAGNIOL-VILLARD 
10471378df79SJean-Christophe PLAGNIOL-VILLARD }
1048