cdc-acm modem fails to get recognized as ttyACM*

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);
}


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux