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