Hi three. I have some cdc-acm class device code running on a AT91RM9200 that I would like to connect to a Debian Linux (2.6.26) machine. The code is based on Atmel's AT91RM9200-EK Basicusb example (ported to gcc) and is validated to work as intended on a Windows XP host. Central parts of the used code is show in the appended file usb_enumerate.c. When the device is connected to the Debian machine it becomes enumerated but it never gets recognized as a new ttyACM* char device. The appended file lsusb-output.txt shows the result of the enumeration process. The Debian machine has been validated to recognise other ACM devices (my mobile phone) automatically when plugged in. Using modprob with increased verbosity shows nothing of interest nor does the syslog reveal any problems but the absense of the creation a ttyACM*. Know I am more or less out of ideas to understand what the problem is and how to fix it. I guess it could be som defect in the device descriptor or that some mechanism in the usb-core or above blocks the cdc-acm module from probing the usb bus for my device. Can anyone help me progress further? Regards Olof Tångrot
user@debian:~$ uname -a Linux debian 2.6.26-2-486 #1 Fri Aug 14 01:02:21 UTC 2009 i586 GNU/Linux user@debian:~$ sudo lsusb -v -d 03eb:6119 Bus 002 Device 006: ID 03eb:6119 Atmel Corp. Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 2 Communications bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x03eb Atmel Corp. idProduct 0x6119 bcdDevice 1.10 iManufacturer 0 iProduct 0 iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 67 bNumInterfaces 2 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xc0 Self Powered MaxPower 0mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 2 Communications bInterfaceSubClass 2 Abstract (modem) bInterfaceProtocol 0 None iInterface 0 CDC Header: bcdCDC 1.10 CDC ACM: bmCapabilities 0x00 CDC Union: bMasterInterface 0 bSlaveInterface 1 CDC Call Management: bmCapabilities 0x00 bDataInterface 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x83 EP 3 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 255 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 10 CDC Data bInterfaceSubClass 0 Unused bInterfaceProtocol 0 iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x01 EP 1 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Device Status: 0x0000 (Bus Powered) user@debian:~$
//*---------------------------------------------------------------------------- //* ATMEL Microcontroller Software Support - ROUSSET - //*---------------------------------------------------------------------------- //* The software is delivered "AS IS" without warranty or condition of any //* kind, either express, implied or statutory. This includes without //* limitation any warranty or condition with respect to merchantability or //* fitness for any particular purpose, or against the infringements of //* intellectual property rights of others. //*---------------------------------------------------------------------------- //* File Name : descriptor.c //* Object : USB monitor aplication. //* //* 1.0 Jul 31 2002 : ODi Creation //*---------------------------------------------------------------------------- #include "AT91_SVC_USBCTL.h" #include "AT91_SVC_USBIN.h" #include "lib_AT91RM9200.h" #include "main.h" #include <stdio.h> /* ================================================================ */ /* ===================== Device configuration ===================== */ /* ================================================================ */ // This is the current configuration. unsigned char currentConfiguration = 0; unsigned char currentConnection = 0; #define __align(d) __attribute__ ((aligned (d))) // Removed by OT __align(32) const char deviceDescriptor[] = { /* Device descriptor */ 0x12, // bLength 0x01, // bDescriptorType 0x10, // bcdUSBL 0x01, // 0x02, // bDeviceClass: CDC class code 0x00, // bDeviceSubclass: CDC class sub code 0x00, // bDeviceProtocol: CDC Device protocol 0x08, // bMaxPacketSize0 0xEB, // idVendorL 0x03, // 0x19, // idProductL 0x61, // 0x10, // bcdDeviceL 0x01, // 0x00, // iManufacturer // 0x01 0x00, // iProduct 0x00, // SerialNumber 0x01 // bNumConfigs }; __align(32) const char configurationDescriptor[] = { /* ============== CONFIGURATION 1 =========== */ /* Configuration 1 descriptor */ 0x09, // CbLength 0x02, // CbDescriptorType 0x43, // CwTotalLength 2 EP + Control 0x00, 0x02, // CbNumInterfaces 0x01, // CbConfigurationValue 0x00, // CiConfiguration 0xC0, // CbmAttributes 0xA0 0x00, // CMaxPower /* Communication Class Interface Descriptor Requirement */ 0x09, // bLength 0x04, // bDescriptorType 0x00, // bInterfaceNumber 0x00, // bAlternateSetting 0x01, // bNumEndpoints 0x02, // bInterfaceClass 0x02, // bInterfaceSubclass 0x00, // bInterfaceProtocol 0x00, // iInterface /* Header Functional Descriptor */ 0x05, // bFunction Length 0x24, // bDescriptor type: CS_INTERFACE 0x00, // bDescriptor subtype: Header Func Desc 0x10, // bcdCDC:1.1 +++ OT 0x10 0x01, // +++ OT 0x01 /* ACM Functional Descriptor */ 0x04, // bFunctionLength 0x24, // bDescriptor Type: CS_INTERFACE 0x02, // bDescriptor Subtype: ACM Func Desc 0x00, // bmCapabilities /* Union Functional Descriptor */ 0x05, // bFunctionLength 0x24, // bDescriptorType: CS_INTERFACE 0x06, // bDescriptor Subtype: Union Func Desc 0x00, // bMasterInterface: Communication Class Interface 0x01, // bSlaveInterface0: Data Class Interface /* Call Management Functional Descriptor */ 0x05, // bFunctionLength 0x24, // bDescriptor Type: CS_INTERFACE 0x01, // bDescriptor Subtype: Call Management Func Desc 0x00, // bmCapabilities: D1 + D0 0x01, // bDataInterface: Data Class Interface 1 /* Endpoint 1 descriptor */ 0x07, // bLength 0x05, // bDescriptorType 0x83, // bEndpointAddress, Endpoint 03 - IN 0x03, // bmAttributes INT 0x08, // wMaxPacketSize 0x00, 0xFF, // bInterval /* Data Class Interface Descriptor Requirement */ 0x09, // bLength 0x04, // bDescriptorType 0x01, // bInterfaceNumber 0x00, // bAlternateSetting 0x02, // bNumEndpoints 0x0A, // bInterfaceClass 0x00, // bInterfaceSubclass 0x00, // bInterfaceProtocol 0x00, // iInterface /* First alternate setting */ /* Endpoint 1 descriptor */ 0x07, // bLength 0x05, // bDescriptorType 0x01, // bEndpointAddress, Endpoint 01 - OUT 0x02, // bmAttributes BULK 0x40, // wMaxPacketSize 0x00, 0x00, // bInterval /* Endpoint 2 descriptor */ 0x07, // bLength 0x05, // bDescriptorType 0x82, // bEndpointAddress, Endpoint 02 - IN 0x02, // bmAttributes BULK 0x40, // wMaxPacketSize 0x00, 0x00 // bInterval }; /* USB standard request code */ #define STD_GET_STATUS_ZERO 0x0080 #define STD_GET_STATUS_INTERFACE 0x0081 #define STD_GET_STATUS_ENDPOINT 0x0082 #define STD_CLEAR_FEATURE_ZERO 0x0100 #define STD_CLEAR_FEATURE_INTERFACE 0x0101 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102 #define STD_SET_FEATURE_ZERO 0x0300 #define STD_SET_FEATURE_INTERFACE 0x0301 #define STD_SET_FEATURE_ENDPOINT 0x0302 #define STD_SET_ADDRESS 0x0500 #define STD_GET_DESCRIPTOR 0x0680 #define STD_SET_DESCRIPTOR 0x0700 #define STD_GET_CONFIGURATION 0x0880 #define STD_SET_CONFIGURATION 0x0900 #define STD_GET_INTERFACE 0x0A81 #define STD_SET_INTERFACE 0x0B01 #define STD_SYNCH_FRAME 0x0C82 /* CDC Class Specific Request Code */ #define GET_LINE_CODING 0x21A1 #define SET_LINE_CODING 0x2021 #define SET_CONTROL_LINE_STATE 0x2221 //*---------------------------------------------------------------------------- //* \fn AT91F_USB_GetDescriptorDevice //* \brief Answer to a standard GET DESCRIPTOR request //*---------------------------------------------------------------------------- #define MIN(a, b) (((a) < (b)) ? (a) : (b)) __inline void AT91F_USB_GetDescriptorDevice( AT91PS_SVC_USBCTL pUSBCTL) { unsigned short wLength = *((unsigned short *) &(pUSBCTL->pSetup[6])); pUSBCTL->Write(pUSBCTL, deviceDescriptor, MIN(sizeof(deviceDescriptor), wLength), (AT91PF_SVC_USBCTL_RWComplete) 0); // No callback } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_GetDescriptorConfiguration //* \brief Answer to a standard GET DESCRIPTOR request //*---------------------------------------------------------------------------- __inline void AT91F_USB_GetDescriptorConfiguration( AT91PS_SVC_USBCTL pUSBCTL) { unsigned short wLength = *((unsigned short *) &(pUSBCTL->pSetup[6])); pUSBCTL->Write(pUSBCTL, configurationDescriptor, MIN(sizeof(configurationDescriptor), wLength), (AT91PF_SVC_USBCTL_RWComplete) 0); // No callback } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_SetAddress //* \brief Answer to a standard SET ADDRESS request //*---------------------------------------------------------------------------- void AT91F_USB_SetAddressComplete( AT91PS_SVC_USBCTL pUSBCTL) { unsigned char address = pUSBCTL->pSetup[2]; // Set Address AT91F_UDP_SetAddress(pUSBCTL->pUdp, address); if (address) // Move the UDP function to the addressed state AT91F_UDP_SetState(pUSBCTL->pUdp, AT91C_UDP_FADDEN); else // Move the UDP function to the default state AT91F_UDP_SetState(pUSBCTL->pUdp, 0); } __inline void AT91F_USB_SetAddress( AT91PS_SVC_USBCTL pUSBCTL) { // UDP address change must be done once STATUS IN is achieved pUSBCTL->Write(pUSBCTL, (char *) 0, 0, AT91F_USB_SetAddressComplete); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_SetConfiguration //* \brief Answer to a standard SET CONFIGURATION request //*---------------------------------------------------------------------------- void AT91F_USB_SetConfigurationComplete( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers // Move the UDP function to the configured state AT91F_UDP_SetState(pUdp, AT91C_UDP_CONFG); // Enable endpoints AT91F_UDP_EpSet(pUdp, 1, AT91C_UDP_EPEDS); AT91F_UDP_EpSet(pUdp, 2, AT91C_UDP_EPEDS); AT91F_UDP_EpSet(pUdp, 3, AT91C_UDP_EPEDS); } __inline void AT91F_USB_SetConfiguration( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers AT91PF_SVC_USBCTL_RWComplete RWComplete = (AT91PF_SVC_USBCTL_RWComplete) 0; // Callback // Store the current configuration currentConfiguration = pUSBCTL->pSetup[2]; // Move to the Configured State if (currentConfiguration) { // Reset endpoints AT91F_UDP_ResetEp(pUdp, (AT91C_UDP_EPINT1 | AT91C_UDP_EPINT2 | AT91C_UDP_EPINT3)); AT91F_UDP_ResetEp(pUdp, 0); //AT91F_UDP_EnableEp(pUdp, (AT91C_UDP_EPINT1 | AT91C_UDP_EPINT2)); // Configure endpoints and enable them AT91F_UDP_EpSet(pUdp, 1, (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT)); // Endpoint 1 is a bulk in AT91F_UDP_EpSet(pUdp, 2, (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN)); // Endpoint 2 is a bulk out // AT91F_UDP_EpSet(pUdp, 3, (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN)); // Endpoint 3 is a INT in AT91F_UDP_EpSet(pUdp, 3, (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN)); // Endpoint 3 is a INT in // Init the Callback after STATUS IN RWComplete = AT91F_USB_SetConfigurationComplete; } // Move back to the Address State else { // Move the UDP function to the addressed state AT91F_UDP_SetState(pUdp, AT91C_UDP_FADDEN); // Enable endpoints AT91F_UDP_EpClear(pUdp, 1, AT91C_UDP_EPEDS); AT91F_UDP_EpClear(pUdp, 2, AT91C_UDP_EPEDS); } // Send a STATUS IN pUSBCTL->Write(pUSBCTL, (char *) 0, 0, RWComplete); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_GetConfiguration //* \brief Answer to a standard GET CONFIGURATION request //*---------------------------------------------------------------------------- __inline void AT91F_USB_GetConfiguration( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers // Send the current configuration AT91F_UDP_EpWrite(pUdp, 0, currentConfiguration); AT91F_UDP_EpEndOfWr(pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_GetStatusZero //* \brief Answer to a standard GET STATUS ZERO request //*---------------------------------------------------------------------------- __inline void AT91F_USB_GetStatusZero( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers // Return no Remote wakeup, not self powered (Cf. Fig 9.4 in USB Spec Rev 1.1) AT91F_UDP_EpWrite(pUdp, 0, 0); AT91F_UDP_EpWrite(pUdp, 0, 0); AT91F_UDP_EpEndOfWr(pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_GetStatusInterface //* \brief Answer to a standard GET STATUS INTERFACE request //*---------------------------------------------------------------------------- __inline void AT91F_USB_GetStatusInterface( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers // Return 0 (Cf. Fig 9.5 in USB Spec Rev 1.1) AT91F_UDP_EpWrite(pUdp, 0, 0); AT91F_UDP_EpWrite(pUdp, 0, 0); AT91F_UDP_EpEndOfWr(pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_GetStatusEndpoint //* \brief Answer to a standard GET STATUS ENDPOINT request //*---------------------------------------------------------------------------- __inline void AT91F_USB_GetStatusEndpoint( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers unsigned char endpoint = (pUSBCTL->pSetup[4] & 0x7F); // Return halt or not (Cf. Fig 9.6 in USB Spec Rev 1.1) if ((AT91F_UDP_GetState(pUdp) != AT91C_UDP_CONFG) || (endpoint > 3)) AT91F_UDP_EpStall(pUdp, 0); else { if (AT91F_UDP_EpStatus(pUdp, endpoint) & AT91C_UDP_EPEDS) AT91F_UDP_EpWrite(pUdp, 0, 1); else AT91F_UDP_EpWrite(pUdp, 0, 0); AT91F_UDP_EpWrite(pUdp, 0, 0); AT91F_UDP_EpEndOfWr(pUdp, 0); } } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_SetFeatureZero //* \brief Answer to a standard SET FEATURE ZERO request //*---------------------------------------------------------------------------- __inline void AT91F_USB_SetFeatureZero( AT91PS_SVC_USBCTL pUSBCTL) { // Device feature RWUp is not supported STALL it AT91F_UDP_EpStall(pUSBCTL->pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_SetFeatureInterface //* \brief Answer to a standard SET FEATURE INTERFACE request //*---------------------------------------------------------------------------- __inline void AT91F_USB_SetFeatureInterface( AT91PS_SVC_USBCTL pUSBCTL) { // Assumed RFU... // Send a zero length packet AT91F_UDP_EpEndOfWr(pUSBCTL->pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_SetFeatureEndpoint //* \brief Answer to a standard SET FEATURE ENDPOINT request //*---------------------------------------------------------------------------- __inline void AT91F_USB_SetFeatureEndpoint( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers unsigned char endpoint = (pUSBCTL->pSetup[4] & 0x7F); // If Feature different from ENDPOINT_HALT, Stall the request !!! (Cf table 9.6 in USB Spec. ) if (pUSBCTL->pSetup[2]) AT91F_UDP_EpStall(pUdp, 0); if ((AT91F_UDP_GetState(pUdp) != AT91C_UDP_CONFG) || (endpoint < 1) || (endpoint > 3)) AT91F_UDP_EpStall(pUdp, 0); else { // Disable the endpoint AT91F_UDP_DisableEp(pUdp, endpoint); // Send a zero length packet AT91F_UDP_EpEndOfWr(pUdp, 0); } } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_ClrFeatureZero //* \brief Answer to a standard CLEAR FEATURE ZERO request //*---------------------------------------------------------------------------- __inline void AT91F_USB_ClrFeatureZero( AT91PS_SVC_USBCTL pUSBCTL) { // Device feature RWUp is not supported STALL it AT91F_UDP_EpStall(pUSBCTL->pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_ClrFeatureInterface //* \brief Answer to a standard CLEAR FEATURE INTERFACE request //*---------------------------------------------------------------------------- __inline void AT91F_USB_ClrFeatureInterface( AT91PS_SVC_USBCTL pUSBCTL) { // Assumed RFU... // Send a zero length packet AT91F_UDP_EpEndOfWr(pUSBCTL->pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_ClrFeatureEndpoint //* \brief Answer to a standard CLEAR FEATURE ENDPOINT request //*---------------------------------------------------------------------------- __inline void AT91F_USB_ClrFeatureEndpoint( AT91PS_SVC_USBCTL pUSBCTL) { AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers unsigned char endpoint = (pUSBCTL->pSetup[4] & 0x7F); // If Feature different from ENDPOINT_HALT, Stall the request !!! (Cf table 9.6 in USB Spec. ) if (pUSBCTL->pSetup[2]) AT91F_UDP_EpStall(pUdp, 0); if ((AT91F_UDP_GetState(pUdp) != AT91C_UDP_CONFG) || (endpoint < 1) || (endpoint > 3)) AT91F_UDP_EpStall(pUdp, 0); else { // Disable the endpoint AT91F_UDP_EnableEp(pUdp, endpoint); // Send a zero length packet AT91F_UDP_EpEndOfWr(pUdp, 0); } } /* +++ OT removed since they where no longer used.... __align(32) char serialState[] = { 0xA1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; __align(32) char networkConnection[] = { 0xA1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00 }; */ typedef struct { unsigned int dwDTERRate; char bCharFormat; char bParityType; char bDataBits; } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING; __align(32) AT91S_CDC_LINE_CODING lineCoding = { // 115200, // baudrate 9600, 0, // 1 Stop Bit 0, // None Parity 8}; // 8 Data bits //*---------------------------------------------------------------------------- //* \fn AT91F_CDC_GetLineCoding //* \brief This request allows the host to find out the currently configured line coding //*---------------------------------------------------------------------------- __inline void AT91F_CDC_GetLineCoding( AT91PS_SVC_USBCTL pUSBCTL) { unsigned short wLength = *((unsigned short *) &(pUSBCTL->pSetup[6])); pUSBCTL->Write(pUSBCTL, (const char *) &lineCoding, MIN(sizeof(lineCoding), wLength), (AT91PF_SVC_USBCTL_RWComplete) 0); // No callback } //*---------------------------------------------------------------------------- //* \fn AT91F_CDC_SetLineCodingComplete //* \brief AT91F_CDC_SetLineCodingComplete once AT91F_CDC_SetLineCoding is achieved //*---------------------------------------------------------------------------- __inline void AT91F_CDC_SetLineCodingComplete( AT91PS_SVC_USBCTL pUSBCTL) { // Send a STATUS IN pUSBCTL->Write(pUSBCTL, (const char *) 0, 0, (AT91PF_SVC_USBCTL_RWComplete)0); } //*---------------------------------------------------------------------------- //* \fn AT91F_CDC_SetLineCoding //* \brief This request allows the host to specify typical asynchronous line-characterformatting properties //*---------------------------------------------------------------------------- __inline void AT91F_CDC_SetLineCoding( AT91PS_SVC_USBCTL pUSBCTL) { unsigned short wLength = *((unsigned short *) &(pUSBCTL->pSetup[6])); pUSBCTL->Read(pUSBCTL, (char *) &lineCoding, MIN(sizeof(lineCoding), wLength), (AT91PF_SVC_USBCTL_RWComplete) AT91F_CDC_SetLineCodingComplete); // No callback } //*---------------------------------------------------------------------------- //* \fn AT91F_CDC_NotificationComplete //* \brief //*---------------------------------------------------------------------------- void AT91F_CDC_NotificationComplete( AT91PS_SVC_USBIN pUSBIN) { #if 1 // +++ OT removed comment.... and activated in design... // usbEpInt.Write(&usbEpInt, networkConnection, sizeof(networkConnection), (AT91PF_SVC_SVCUSBIN_TxComplete) 0); #endif } void AT91F_CDC_SetControlLineStateComplete( AT91PS_SVC_USBCTL pUSBCTL) { currentConnection = pUSBCTL->pSetup[2]; #if 1 // +++ OT removed comment.... and activated in design... // if (currentConnection == 3) // usbEpInt.Write(&usbEpInt, serialState, sizeof(serialState), (AT91PF_SVC_SVCUSBIN_TxComplete) 0); #endif } //*---------------------------------------------------------------------------- //* \fn AT91F_CDC_SetControlLineState //* \brief This request allows the host to specify typical asynchronous line-characterformatting properties //*---------------------------------------------------------------------------- __inline void AT91F_CDC_SetControlLineState( AT91PS_SVC_USBCTL pUSBCTL) { //AT91PS_UDP pUdp = pUSBCTL->pUdp; // Pointer to UDP registers // Send a STATUS IN pUSBCTL->Write(pUSBCTL, (char *) 0, 0, AT91F_CDC_SetControlLineStateComplete); //AT91F_UDP_EpEndOfWr(pUdp, 0); } //*---------------------------------------------------------------------------- //* \fn AT91F_USB_DispatchRequest //* \brief This function is a callback invoked when a SETUP packet is received //*---------------------------------------------------------------------------- void AT91F_USB_DispatchRequest( AT91PS_SVC_USBCTL pUSBCTL) { unsigned short request = *((unsigned short *) pUSBCTL->pSetup); #if 0 unsigned short wValue = *((unsigned short *)(&pUSBCTL->pSetup[2])); unsigned short wIndex = *((unsigned short *)(&pUSBCTL->pSetup[4])); unsigned short wLength = *((unsigned short *)(&pUSBCTL->pSetup[6])); char str[64]; sprintf( str, "0x%x 0x%x 0x%x 0x%x\n\r", request, wValue, wIndex, wLength ); HAL_ASCDBG_SendString( (uint8_t*) str ); #endif // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 if ((request == STD_GET_DESCRIPTOR) && (pUSBCTL->pSetup[3] == 1)) AT91F_USB_GetDescriptorDevice(pUSBCTL); else if ((request == STD_GET_DESCRIPTOR) && (pUSBCTL->pSetup[3] == 2)) AT91F_USB_GetDescriptorConfiguration(pUSBCTL); else if (request == STD_SET_ADDRESS) AT91F_USB_SetAddress(pUSBCTL); else if (request == STD_SET_CONFIGURATION) AT91F_USB_SetConfiguration(pUSBCTL); else if (request == STD_GET_CONFIGURATION) AT91F_USB_GetConfiguration(pUSBCTL); else if (request == STD_GET_STATUS_ZERO) AT91F_USB_GetStatusZero(pUSBCTL); else if (request == STD_GET_STATUS_INTERFACE) AT91F_USB_GetStatusInterface(pUSBCTL); else if (request == STD_GET_STATUS_ENDPOINT) AT91F_USB_GetStatusEndpoint(pUSBCTL); else if (request == STD_SET_FEATURE_ZERO) AT91F_USB_SetFeatureZero(pUSBCTL); else if (request == STD_SET_FEATURE_INTERFACE) AT91F_USB_SetFeatureInterface(pUSBCTL); else if (request == STD_SET_FEATURE_ENDPOINT) AT91F_USB_SetFeatureEndpoint(pUSBCTL); else if (request == STD_CLEAR_FEATURE_ZERO) AT91F_USB_ClrFeatureZero(pUSBCTL); else if (request == STD_CLEAR_FEATURE_INTERFACE) AT91F_USB_ClrFeatureInterface(pUSBCTL); else if (request == STD_CLEAR_FEATURE_ENDPOINT) AT91F_USB_ClrFeatureEndpoint(pUSBCTL); // handle CDC class requests else if (request == SET_LINE_CODING) AT91F_CDC_SetLineCoding(pUSBCTL); else if (request == GET_LINE_CODING) AT91F_CDC_GetLineCoding(pUSBCTL); else if (request == SET_CONTROL_LINE_STATE) AT91F_CDC_SetControlLineState(pUSBCTL); // Unsupported requests else AT91F_UDP_EpStall(pUSBCTL->pUdp, 0); }