diff options
| author | Harald Welte <laforge@gnumonks.org> | 2011-07-31 22:36:10 +0200 | 
|---|---|---|
| committer | Harald Welte <laforge@gnumonks.org> | 2011-07-31 22:36:10 +0200 | 
| commit | db0ddc6ee6c5e9d3dec919465dcb1c068123922d (patch) | |
| tree | 7aedd43863b0bf548c2a73c7f7427c99cc81f56e | |
| parent | 29745a4febe20b8e0f229e248197bb1faeec4d0c (diff) | |
This is in anticipation of the future SIMtrace firmware,
where we will have a single device with three configurations.
| -rw-r--r-- | at91lib/usb/device/multiconf/MULTIDriver.c | 180 | ||||
| -rw-r--r-- | at91lib/usb/device/multiconf/MULTIDriver.h | 15 | ||||
| -rw-r--r-- | at91lib/usb/device/multiconf/MULTIDriverDescriptors.c | 506 | ||||
| -rw-r--r-- | at91lib/usb/device/multiconf/MULTIDriverDescriptors.h | 5 | ||||
| -rw-r--r-- | usb-device-multi-project/Makefile | 173 | ||||
| -rw-r--r-- | usb-device-multi-project/main.c | 406 | 
6 files changed, 1285 insertions, 0 deletions
| diff --git a/at91lib/usb/device/multiconf/MULTIDriver.c b/at91lib/usb/device/multiconf/MULTIDriver.c new file mode 100644 index 0000000..01a023e --- /dev/null +++ b/at91lib/usb/device/multiconf/MULTIDriver.c @@ -0,0 +1,180 @@ +/* ----------------------------------------------------------------------------
 + *         ATMEL Microcontroller Software Support 
 + * ----------------------------------------------------------------------------
 + * Copyright (c) 2008, Atmel Corporation
 + *
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions are met:
 + *
 + * - Redistributions of source code must retain the above copyright notice,
 + * this list of conditions and the disclaimer below.
 + *
 + * Atmel's name may not be used to endorse or promote products derived from
 + * this software without specific prior written permission.
 + *
 + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + * ----------------------------------------------------------------------------
 + */
 +
 +//-----------------------------------------------------------------------------
 +//      Headers
 +//-----------------------------------------------------------------------------
 +
 +// GENERAL
 +#include <utility/trace.h>
 +#include <utility/assert.h>
 +#include <utility/led.h>
 +
 +// USB
 +#include <usb/device/core/USBD.h>
 +#include <usb/device/core/USBDDriver.h>
 +
 +//- MULTI
 +#include "MULTIDriver.h"
 +#include "MULTIDriverDescriptors.h"
 +
 +//-----------------------------------------------------------------------------
 +//         Defines
 +//-----------------------------------------------------------------------------
 +
 +/// Interface setting spaces (4 byte aligned)
 +#define NUM_INTERFACES  ((2+3)&0xFC)
 +
 +//-----------------------------------------------------------------------------
 +//         Types
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +//         Internal variables
 +//-----------------------------------------------------------------------------
 +
 +/// USBDDriver instance
 +static USBDDriver usbdDriver;
 +
 +/// Array for storing the current setting of each interface
 +static unsigned char multiDriverInterfaces[NUM_INTERFACES];
 +
 +//-----------------------------------------------------------------------------
 +//         Internal functions
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +//         Optional RequestReceived() callback re-implementation
 +//-----------------------------------------------------------------------------
 +#if !defined(NOAUTOCALLBACK)
 +void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
 +{
 +    MULTIDriver_RequestHandler(request);
 +}
 +#endif
 +
 +//-----------------------------------------------------------------------------
 +/// Invoked whenever the active setting of an interface is changed by the
 +/// host. Changes the status of the third LED accordingly.
 +/// \param interface Interface number.
 +/// \param setting Newly active setting.
 +//-----------------------------------------------------------------------------
 +void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
 +                                                 unsigned char setting)
 +{
 +	TRACE_DEBUG("Callback_IntfChg(%u, %u)\n\r", interface, setting);
 +}
 +
 +//-----------------------------------------------------------------------------
 +//         ConfigurationChanged() callback re-implementation
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +/// Invoked whenever the configuration value of a device is changed by the host
 +/// \param cfgnum Configuration number.
 +//-----------------------------------------------------------------------------
 +void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
 +{
 +	TRACE_DEBUG("Callback_ConfigChg(%u)\n\r", cfgnum);
 +}
 +
 +//-----------------------------------------------------------------------------
 +//         Exported functions
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +/// Initializes the USB device composite device driver.
 +//-----------------------------------------------------------------------------
 +void MULTIDriver_Initialize(void)
 +{
 +
 +    CDCDFunctionDriver_Initialize();
 +
 +	/* CCID nees no initialization */
 +
 +    // Initialize the standard USB driver
 +    USBDDriver_Initialize(&usbdDriver,
 +                          &multiDriverDescriptors,
 +                          multiDriverInterfaces);
 +
 +    // Initialize the USB driver
 +    USBD_Init();
 +}
 +
 +//-----------------------------------------------------------------------------
 +/// Handles composite-specific USB requests sent by the host, and forwards
 +/// standard ones to the USB device driver.
 +/// \param request Pointer to a USBGenericRequest instance.
 +//-----------------------------------------------------------------------------
 +void MULTIDriver_RequestHandler(const USBGenericRequest *request)
 +{
 +    // Check if this is a class request
 +    if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
 +
 +        unsigned char rc = 0;
 +
 +        //rc = CCID_RequestHandler(request);
 +        if (!rc) {
 +            TRACE_WARNING(
 +              "MULTIDriver_RequestHandler: Unsupported request (%d)\n\r",
 +              USBGenericRequest_GetRequest(request));
 +            USBD_Stall(0);
 +        }
 +
 +    }
 +    // Check if this is a standard request
 +    else if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
 +
 +        unsigned char rc = 0;
 +
 +        // Forward request to the standard handler
 +        if (rc == 0)
 +            USBDDriver_RequestHandler(&(usbdDriver), request);
 +    }
 +    // Unsupported request type
 +    else {
 +        TRACE_WARNING(
 +          "MULTIDriver_RequestHandler: Unsupported request type (%d)\n\r",
 +          USBGenericRequest_GetType(request));
 +        USBD_Stall(0);
 +    }
 +}
 +
 +//-----------------------------------------------------------------------------
 +/// Starts a remote wake-up sequence if the host has explicitely enabled it
 +/// by sending the appropriate SET_FEATURE request.
 +//-----------------------------------------------------------------------------
 +void MULTIDriver_RemoteWakeUp(void)
 +{
 +    // Remote wake-up has been enabled
 +    if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver))
 +        USBD_RemoteWakeUp();
 +    else
 +        TRACE_WARNING("MULTIriver_RemoteWakeUp: not enabled\n\r");
 +}
 diff --git a/at91lib/usb/device/multiconf/MULTIDriver.h b/at91lib/usb/device/multiconf/MULTIDriver.h new file mode 100644 index 0000000..49a8fbc --- /dev/null +++ b/at91lib/usb/device/multiconf/MULTIDriver.h @@ -0,0 +1,15 @@ +#ifndef MULTIDRIVER_H +#define MULTIDRIVER_H + +#include <usb/common/core/USBGenericRequest.h> +#include <usb/device/core/USBD.h> + +#include "../composite/CDCDFunctionDriver.h" + +extern void MULTIDriver_RequestHandler(const USBGenericRequest *request); + +extern void MULTIDriver_RemoteWakeUp(void); + +extern void MULTIDriver_Initialize(void); + +#endif //#ifndef MULTIDDRIVER_H diff --git a/at91lib/usb/device/multiconf/MULTIDriverDescriptors.c b/at91lib/usb/device/multiconf/MULTIDriverDescriptors.c new file mode 100644 index 0000000..384d72f --- /dev/null +++ b/at91lib/usb/device/multiconf/MULTIDriverDescriptors.c @@ -0,0 +1,506 @@ +/* ----------------------------------------------------------------------------
 + *         ATMEL Microcontroller Software Support 
 + * ----------------------------------------------------------------------------
 + * Copyright (c) 2008, Atmel Corporation
 + *
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions are met:
 + *
 + * - Redistributions of source code must retain the above copyright notice,
 + * this list of conditions and the disclaimer below.
 + *
 + * Atmel's name may not be used to endorse or promote products derived from
 + * this software without specific prior written permission.
 + *
 + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + * ----------------------------------------------------------------------------
 + */
 +
 +//------------------------------------------------------------------------------
 +//      Headers
 +//------------------------------------------------------------------------------
 +
 +#include "MULTIDriver.h"
 +#include "MULTIDriverDescriptors.h"
 +#include <board.h>
 +
 +//- USB Generic
 +#include <usb/common/core/USBGenericDescriptor.h>
 +#include <usb/common/core/USBConfigurationDescriptor.h>
 +#include <usb/common/core/USBInterfaceAssociationDescriptor.h>
 +#include <usb/common/core/USBEndpointDescriptor.h>
 +#include <usb/common/core/USBStringDescriptor.h>
 +#include <usb/common/core/USBGenericRequest.h>
 +
 +//- CDC
 +#include <usb/common/cdc/CDCGenericDescriptor.h>
 +#include <usb/common/cdc/CDCDeviceDescriptor.h>
 +#include <usb/common/cdc/CDCCommunicationInterfaceDescriptor.h>
 +#include <usb/common/cdc/CDCDataInterfaceDescriptor.h>
 +#include <usb/common/cdc/CDCHeaderDescriptor.h>
 +#include <usb/common/cdc/CDCCallManagementDescriptor.h>
 +#include <usb/common/cdc/CDCAbstractControlManagementDescriptor.h>
 +#include <usb/common/cdc/CDCUnionDescriptor.h>
 +#include "../composite/CDCDFunctionDriverDescriptors.h"
 +
 +//CCID
 +#include <usb/device/ccid/cciddriver.h>
 +#include <usb/device/ccid/cciddriverdescriptors.h>
 +
 +//-----------------------------------------------------------------------------
 +//         Definitions
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +//         Macros
 +//-----------------------------------------------------------------------------
 +
 +/// Returns the minimum between two values.
 +#define MIN(a, b)       ((a < b) ? a : b)
 +
 +//-----------------------------------------------------------------------------
 +//         Internal structures
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +/// Audio control header descriptor with one slave interface.
 +//-----------------------------------------------------------------------------
 +#ifdef __ICCARM__          // IAR
 +#pragma pack(1)            // IAR
 +#define __attribute__(...) // IAR
 +#endif                     // IAR
 +
 +//-----------------------------------------------------------------------------
 +/// Configuration descriptor list for a device implementing a composite driver.
 +//-----------------------------------------------------------------------------
 +struct multi_cdc_conf_desc {
 +	/// Standard configuration descriptor.
 +	USBConfigurationDescriptor configuration;
 +
 +	/// IAD 0
 +	USBInterfaceAssociationDescriptor cdcIAD0;
 +	/// Communication interface descriptor
 +	USBInterfaceDescriptor cdcCommunication0;
 +	/// CDC header functional descriptor.
 +	CDCHeaderDescriptor cdcHeader0;
 +	/// CDC call management functional descriptor.
 +	CDCCallManagementDescriptor cdcCallManagement0;
 +	/// CDC abstract control management functional descriptor.
 +	CDCAbstractControlManagementDescriptor cdcAbstractControlManagement0;
 +	/// CDC union functional descriptor (with one slave interface).
 +	CDCUnionDescriptor cdcUnion0;
 +	/// Notification endpoint descriptor.
 +	USBEndpointDescriptor cdcNotification0;
 +	/// Data interface descriptor.
 +	USBInterfaceDescriptor cdcData0;
 +	/// Data OUT endpoint descriptor.
 +	USBEndpointDescriptor cdcDataOut0;
 +	/// Data IN endpoint descriptor.
 +	USBEndpointDescriptor cdcDataIn0;
 +} __attribute__ ((packed));
 +
 +struct multi_ccid_conf_desc {
 +	USBConfigurationDescriptor configuration;
 +	USBInterfaceDescriptor interface;
 +	CCIDDescriptor ccid;
 +	USBEndpointDescriptor endpoint[3];
 +} __attribute__ ((packed));
 +
 +#ifdef __ICCARM__          // IAR
 +#pragma pack()             // IAR
 +#endif                     // IAR
 +
 +//------------------------------------------------------------------------------
 +//         Exported variables
 +//------------------------------------------------------------------------------
 +
 +/// Standard USB device descriptor for the composite device driver
 +const USBDeviceDescriptor deviceDescriptor = {
 +	.bLength		= sizeof(USBDeviceDescriptor),
 +	.bDescriptorType	= USBGenericDescriptor_DEVICE,
 +	.bcdUSB			= USBDeviceDescriptor_USB2_00,
 +	.bDeviceClass		= 0x00,
 +	.bDeviceSubClass	= 0x00,
 +	.bDeviceProtocol	= 0x00,
 +	.bMaxPacketSize0	= BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
 +	.idVendor		= 0x16c0,
 +	.idProduct		= 0x0762,
 +	.bcdDevice		= 0x0090,
 +    	.iManufacturer		= 1,
 +	.iProduct		= 2,
 +	.iSerialNumber		= 0,
 +    	.bNumConfigurations	= 3,
 +};
 +
 +#if defined(BOARD_USB_UDPHS)
 +
 +/// USB device qualifier descriptor.
 +const USBDeviceQualifierDescriptor qualifierDescriptor = {
 +
 +    sizeof(USBDeviceQualifierDescriptor),
 +    USBGenericDescriptor_DEVICEQUALIFIER,
 +    USBDeviceDescriptor_USB2_00,
 +  #if defined(usb_HIDMSD)
 +    0x00,
 +    0x00,
 +    0x00,
 +  #else
 +    0xEF,// MI
 +    0x02,//
 +    0x01,//
 +  #endif
 +    BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
 +    3, // Device has one possible configuration
 +    0 // Reserved
 +};
 +
 +#endif
 +
 +/* Configuration Descriptor for config #0 (SNIFFER) */
 +const struct multi_cdc_conf_desc sniffer_configurationDescriptors = {
 +	.configuration = {
 +		.bLength 		= sizeof(USBConfigurationDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_CONFIGURATION,
 +		.wTotalLength		= sizeof(struct multi_cdc_conf_desc),
 +		.bNumInterfaces		= 2,
 +		.bConfigurationValue	= 1,
 +		.iConfiguration		= 0,
 +		.bmAttributes		= BOARD_USB_BMATTRIBUTES,
 +		.bMaxPower		= USBConfigurationDescriptor_POWER(100),
 +	},
 +	.cdcIAD0 = {
 +		.bLength		= sizeof(USBInterfaceAssociationDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_INTERFACEASSOCIATION,
 +		.bFirstInterface	= 0,
 +		.bInterfaceCount	= 2,
 +		.bFunctionClass		= CDCCommunicationInterfaceDescriptor_CLASS,
 +		.bFunctionSubClass	= CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
 +		.bFunctionProtocol	= CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
 +		.iFunction		= 0,
 +	},
 +	.cdcCommunication0 = {
 +		.bLength		= sizeof(USBInterfaceDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_INTERFACE,
 +		.bInterfaceNumber	= 0,
 +		.bAlternateSetting	= 0,
 +		.bNumEndpoints		= 1,
 +		.bInterfaceClass	= CDCCommunicationInterfaceDescriptor_CLASS,
 +		.bInterfaceSubClass	= CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
 +		.bInterfaceProtocol	= CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
 +		.iInterface		= 0,
 +	},
 +	.cdcHeader0 = {
 +		.bFunctionLength	= sizeof(CDCHeaderDescriptor),
 +		.bDescriptorType	= CDCGenericDescriptor_INTERFACE,
 +		.bDescriptorSubtype	= CDCGenericDescriptor_HEADER,
 +		.bcdCDC			= CDCGenericDescriptor_CDC1_10,
 +	},
 +	.cdcCallManagement0 = {
 +		.bFunctionLength	= sizeof(CDCCallManagementDescriptor),
 +		.bDescriptorType	= CDCGenericDescriptor_INTERFACE,
 +		.bDescriptorSubtype	= CDCGenericDescriptor_CALLMANAGEMENT,
 +		.bmCapabilities		= CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
 +		.bDataInterface		= 1,
 +	},
 +	.cdcAbstractControlManagement0 = {
 +		.bFunctionLength	= sizeof(CDCAbstractControlManagementDescriptor),
 +		.bDescriptorType	= CDCGenericDescriptor_INTERFACE,
 +		.bDescriptorSubtype	= CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
 +		.bmCapabilities		= CDCAbstractControlManagementDescriptor_LINE,
 +	},
 +	.cdcUnion0 = {
 +		.bFunctionLength	= sizeof(CDCUnionDescriptor),
 +		.bDescriptorType	= CDCGenericDescriptor_INTERFACE,
 +		.bDescriptorSubtype	= CDCGenericDescriptor_UNION,
 +		.bMasterInterface	= 0,
 +		.bSlaveInterface0	= 1,
 +	},
 +	.cdcNotification0 = {
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
 +									CDCD_Descriptors_NOTIFICATION0),
 +		.bmAttributes		= USBEndpointDescriptor_INTERRUPT,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
 +					      USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
 +		.bInterval		= 10,
 +	},
 +	.cdcData0 = {
 +		.bLength		= sizeof(USBInterfaceDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_INTERFACE,
 +		.bInterfaceNumber	= 1,
 +		.bAlternateSetting	= 0,
 +		.bNumEndpoints		= 2,
 +		.bInterfaceClass	= CDCDataInterfaceDescriptor_CLASS,
 +		.bInterfaceSubClass	= CDCDataInterfaceDescriptor_SUBCLASS,
 +		.bInterfaceProtocol	= CDCDataInterfaceDescriptor_NOPROTOCOL,
 +		.iInterface		= 0,
 +	},
 +	.cdcDataOut0 = {
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
 +									CDCD_Descriptors_DATAOUT0),
 +		.bmAttributes		= USBEndpointDescriptor_BULK,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
 +					      USBEndpointDescriptor_MAXBULKSIZE_FS),
 +		.bInterval		= 0,
 +	},
 +	.cdcDataIn0 = {
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
 +									CDCD_Descriptors_DATAIN0),
 +		.bmAttributes		= USBEndpointDescriptor_BULK,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
 +					      USBEndpointDescriptor_MAXBULKSIZE_FS),
 +		.bInterval		= 0,
 +	},
 +};
 +
 +const struct multi_ccid_conf_desc reader_configurationDescriptors = {
 +	.configuration = {
 +		.bLength 		= sizeof(USBConfigurationDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_CONFIGURATION,
 +		.wTotalLength		= sizeof(struct multi_ccid_conf_desc),
 +		.bNumInterfaces		= 1,
 +		.bConfigurationValue	= 2,
 +		.iConfiguration		= 0,
 +		.bmAttributes		= BOARD_USB_BMATTRIBUTES,
 +		.bMaxPower		= USBConfigurationDescriptor_POWER(100),
 +	},
 +	.interface = {
 +		.bLength		= sizeof(USBInterfaceDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_INTERFACE,
 +		.bInterfaceNumber	= 0,
 +		.bAlternateSetting	= 0,
 +		.bNumEndpoints		= 3,
 +		.bInterfaceClass	= SMART_CARD_DEVICE_CLASS,
 +		.bInterfaceSubClass	= 0,
 +		.bInterfaceProtocol	= 0,
 +		.iInterface		= 0,
 +	},
 +	.ccid = {
 +		.bLength		= sizeof(CCIDDescriptor),
 +		.bDescriptorType	= CCID_DECRIPTOR_TYPE,
 +		.bcdCCID		= CCID1_10,
 +		.bMaxSlotIndex		= 0,
 +		.bVoltageSupport	= VOLTS_3_0,
 +		.dwProtocols		= (1 << PROTOCOL_TO),
 +		.dwDefaultClock		= 3580,
 +		.dwMaximumClock		= 3580,
 +		.bNumClockSupported	= 0,
 +		.dwDataRate		= 9600,
 +		.dwMaxDataRate		= 9600,
 +		.bNumDataRatesSupported	= 0,
 +		.dwMaxIFSD		= 0xfe,
 +		.dwSynchProtocols	= 0,
 +		.dwMechanical		= 0,
 +		.dwFeatures		= CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
 +					  CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO |
 +					  CCID_FEATURES_EXC_TPDU,
 +		.dwMaxCCIDMessageLength	= 0x10f,
 +		.bClassGetResponse	= 0xff,
 +		.bClassEnvelope		= 0xff,
 +		.wLcdLayout		= 0,
 +		.bPINSupport		= 0,
 +		.bMaxCCIDBusySlots	= 1,
 +	},
 +	.endpoint = {
 +		{
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
 +									CCID_EPT_DATA_OUT),
 +		.bmAttributes		= USBEndpointDescriptor_BULK,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
 +					      USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
 +		.bInterval		= 0,
 +		},
 +		{
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
 +									CCID_EPT_DATA_IN),
 +		.bmAttributes		= USBEndpointDescriptor_BULK,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
 +					      USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
 +		.bInterval		= 0,
 +		},
 +		{
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
 +									CCID_EPT_NOTIFICATION),
 +		.bmAttributes		= USBEndpointDescriptor_INTERRUPT,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
 +					      USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
 +		.bInterval		= 0x10,
 +		},
 +	},
 +};
 +
 +const struct multi_ccid_conf_desc mitm_configurationDescriptors = {
 +	.configuration = {
 +		.bLength 		= sizeof(USBConfigurationDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_CONFIGURATION,
 +		.wTotalLength		= sizeof(struct multi_ccid_conf_desc),
 +		.bNumInterfaces		= 1,
 +		.bConfigurationValue	= 3,
 +		.iConfiguration		= 0,
 +		.bmAttributes		= BOARD_USB_BMATTRIBUTES,
 +		.bMaxPower		= USBConfigurationDescriptor_POWER(100),
 +	},
 +	.interface = {
 +		.bLength		= sizeof(USBInterfaceDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_INTERFACE,
 +		.bInterfaceNumber	= 0,
 +		.bAlternateSetting	= 0,
 +		.bNumEndpoints		= 3,
 +		.bInterfaceClass	= SMART_CARD_DEVICE_CLASS,
 +		.bInterfaceSubClass	= 0,
 +		.bInterfaceProtocol	= 0,
 +		.iInterface		= 0,
 +	},
 +	.ccid = {
 +		.bLength		= sizeof(CCIDDescriptor),
 +		.bDescriptorType	= CCID_DECRIPTOR_TYPE,
 +		.bcdCCID		= CCID1_10,
 +		.bMaxSlotIndex		= 0,
 +		.bVoltageSupport	= VOLTS_3_0,
 +		.dwProtocols		= (1 << PROTOCOL_TO),
 +		.dwDefaultClock		= 3580,
 +		.dwMaximumClock		= 3580,
 +		.bNumClockSupported	= 0,
 +		.dwDataRate		= 9600,
 +		.dwMaxDataRate		= 9600,
 +		.bNumDataRatesSupported	= 0,
 +		.dwMaxIFSD		= 0xfe,
 +		.dwSynchProtocols	= 0,
 +		.dwMechanical		= 0,
 +		.dwFeatures		= CCID_FEATURES_AUTO_CLOCK | CCID_FEATURES_AUTO_BAUD |
 +					  CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO |
 +					  CCID_FEATURES_EXC_TPDU,
 +		.dwMaxCCIDMessageLength	= 0x10f,
 +		.bClassGetResponse	= 0xff,
 +		.bClassEnvelope		= 0xff,
 +		.wLcdLayout		= 0,
 +		.bPINSupport		= 0,
 +		.bMaxCCIDBusySlots	= 1,
 +	},
 +	.endpoint = {
 +		{
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
 +									CCID_EPT_DATA_OUT),
 +		.bmAttributes		= USBEndpointDescriptor_BULK,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
 +					      USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
 +		.bInterval		= 0,
 +		},
 +		{
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
 +									CCID_EPT_DATA_IN),
 +		.bmAttributes		= USBEndpointDescriptor_BULK,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
 +					      USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
 +		.bInterval		= 0,
 +		},
 +		{
 +		.bLength		= sizeof(USBEndpointDescriptor),
 +		.bDescriptorType	= USBGenericDescriptor_ENDPOINT,
 +		.bEndpointAddress	= USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
 +									CCID_EPT_NOTIFICATION),
 +		.bmAttributes		= USBEndpointDescriptor_INTERRUPT,
 +		.wMaxPacketSize		= MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
 +					      USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
 +		.bInterval		= 0x10,
 +		},
 +	},
 +};
 +
 +
 +/// String descriptor with the supported languages.
 +const unsigned char languageIdDescriptor[] = {
 +
 +    USBStringDescriptor_LENGTH(1),
 +    USBGenericDescriptor_STRING,
 +    USBStringDescriptor_ENGLISH_US
 +};
 +
 +/// Manufacturer name.
 +const unsigned char manufacturerDescriptor[] = {
 +
 +    USBStringDescriptor_LENGTH(5),
 +    USBGenericDescriptor_STRING,
 +    USBStringDescriptor_UNICODE('A'),
 +    USBStringDescriptor_UNICODE('t'),
 +    USBStringDescriptor_UNICODE('m'),
 +    USBStringDescriptor_UNICODE('e'),
 +    USBStringDescriptor_UNICODE('l')
 +};
 +
 +/// Product name.
 +const unsigned char productDescriptor[] = {
 +
 +    USBStringDescriptor_LENGTH(10),
 +    USBGenericDescriptor_STRING,
 +    USBStringDescriptor_UNICODE('M'),
 +    USBStringDescriptor_UNICODE('u'),
 +    USBStringDescriptor_UNICODE('l'),
 +    USBStringDescriptor_UNICODE('t'),
 +    USBStringDescriptor_UNICODE('i'),
 +    USBStringDescriptor_UNICODE(' '),
 +    USBStringDescriptor_UNICODE('D'),
 +    USBStringDescriptor_UNICODE('e'),
 +    USBStringDescriptor_UNICODE('m'),
 +    USBStringDescriptor_UNICODE('o')
 +};
 +
 +/// Array of pointers to the four string descriptors.
 +const unsigned char *stringDescriptors[] = {
 +
 +    languageIdDescriptor,
 +    manufacturerDescriptor,
 +    productDescriptor,
 +};
 +
 +//------------------------------------------------------------------------------
 +//         Exported variables
 +//------------------------------------------------------------------------------
 +
 +/// List of descriptors required by an USB audio speaker device driver.
 +const USBDDriverDescriptors multiDriverDescriptors = {
 +
 +    &deviceDescriptor,
 +    { (const USBConfigurationDescriptor *) &sniffer_configurationDescriptors,
 +      (const USBConfigurationDescriptor *) &reader_configurationDescriptors,
 +      (const USBConfigurationDescriptor *) &mitm_configurationDescriptors },
 +#ifdef BOARD_USB_UDPHS
 +    &qualifierDescriptor,
 +    { (const USBConfigurationDescriptor *) &sniffer_configurationDescriptors },
 +    &deviceDescriptor,
 +    { (const USBConfigurationDescriptor *) &sniffer_configurationDescriptors },
 +    &qualifierDescriptor,
 +    { (const USBConfigurationDescriptor *) &sniffer_configurationDescriptors },
 +#else
 +    0, { 0 }, 0, { 0 }, 0, { 0 },
 +#endif
 +    stringDescriptors,
 +    3 // Number of string descriptors
 +};
 +
 diff --git a/at91lib/usb/device/multiconf/MULTIDriverDescriptors.h b/at91lib/usb/device/multiconf/MULTIDriverDescriptors.h new file mode 100644 index 0000000..b0eaa28 --- /dev/null +++ b/at91lib/usb/device/multiconf/MULTIDriverDescriptors.h @@ -0,0 +1,5 @@ + +#include <board.h> +#include <usb/device/core/USBDDriverDescriptors.h> + +extern const USBDDriverDescriptors multiDriverDescriptors; diff --git a/usb-device-multi-project/Makefile b/usb-device-multi-project/Makefile new file mode 100644 index 0000000..797b520 --- /dev/null +++ b/usb-device-multi-project/Makefile @@ -0,0 +1,173 @@ +# ----------------------------------------------------------------------------
 +#         ATMEL Microcontroller Software Support 
 +# ----------------------------------------------------------------------------
 +# Copyright (c) 2008, Atmel Corporation
 +#
 +# All rights reserved.
 +#
 +# Redistribution and use in source and binary forms, with or without
 +# modification, are permitted provided that the following conditions are met:
 +#
 +# - Redistributions of source code must retain the above copyright notice,
 +# this list of conditions and the disclaimer below.
 +#
 +# Atmel's name may not be used to endorse or promote products derived from
 +# this software without specific prior written permission.
 +#
 +# DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 +# DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 +# ----------------------------------------------------------------------------
 +
 +# 	Makefile for compiling the USB COMPOSITE project
 +
 +#-------------------------------------------------------------------------------
 +#		User-modifiable options
 +#-------------------------------------------------------------------------------
 +
 +# Chip & board used for compilation
 +# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
 +CHIP  = at91sam7s128
 +BOARD = simtrace
 +
 +# Trace level used for compilation
 +# (can be overriden by adding TRACE_LEVEL=#number to the command-line)
 +# TRACE_LEVEL_DEBUG      5
 +# TRACE_LEVEL_INFO       4
 +# TRACE_LEVEL_WARNING    3
 +# TRACE_LEVEL_ERROR      2
 +# TRACE_LEVEL_FATAL      1
 +# TRACE_LEVEL_NO_TRACE   0
 +TRACE_LEVEL = 5
 +
 +# Optimization level, put in comment for debugging
 +OPTIMIZATION = -Os
 +
 +# AT91 library directory
 +AT91LIB = ../at91lib
 +
 +# Output file basename
 +OUTPUT = usb-device-multi-project-$(BOARD)-$(CHIP)
 +
 +# Compile for all memories available on the board (this sets $(MEMORIES))
 +include $(AT91LIB)/boards/$(BOARD)/board.mak
 +
 +# Output directories
 +BIN = bin
 +OBJ = obj
 +
 +#-------------------------------------------------------------------------------
 +#		Tools
 +#-------------------------------------------------------------------------------
 +
 +# Tool suffix when cross-compiling
 +CROSS_COMPILE = arm-elf-
 +
 +# Compilation tools
 +CC = $(CROSS_COMPILE)gcc
 +SIZE = $(CROSS_COMPILE)size
 +OBJCOPY = $(CROSS_COMPILE)objcopy
 +
 +# Flags
 +INCLUDES = -I$(AT91LIB)/boards/$(BOARD) -I$(AT91LIB)/peripherals 
 +INCLUDES += -I$(AT91LIB)/components -I$(AT91LIB)/usb/device -I$(AT91LIB)
 +
 +CFLAGS = -Wall -mlong-calls -ffunction-sections
 +CFLAGS += -Dusb_CDCHID
 +CFLAGS += -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL)
 +ASFLAGS = -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__
 +LDFLAGS = -g $(OPTIMIZATION) -nostartfiles -Wl,--gc-sections
 +
 +#-------------------------------------------------------------------------------
 +#		Files
 +#-------------------------------------------------------------------------------
 +
 +# Directories where source files can be found
 +USB = $(AT91LIB)/usb
 +UTILITY = $(AT91LIB)/utility
 +PERIPH = $(AT91LIB)/peripherals
 +BOARDS = $(AT91LIB)/boards
 +COMP = $(AT91LIB)/components
 +MEM = $(AT91LIB)/memories
 +
 +VPATH += $(MEM)
 +VPATH += $(USB)/device/hid-keyboard $(USB)/common/hid
 +VPATH += $(USB)/device/multiconf $(USB)/device/composite
 +VPATH += $(USB)/device/core $(USB)/common/core
 +VPATH += $(USB)/common/cdc
 +VPATH += $(UTILITY)
 +VPATH += $(PERIPH)/dbgu $(PERIPH)/aic $(PERIPH)/usart $(PERIPH)/pio $(PERIPH)/pmc
 +VPATH += $(PERIPH)/cp15 $(PERIPH)/pit
 +VPATH += $(BOARDS)/$(BOARD) $(BOARDS)/$(BOARD)/$(CHIP)
 +
 +# Objects built from C source files
 +C_OBJECTS = main.o
 +C_OBJECTS += MULTIDriver.o MULTIDriverDescriptors.o
 +C_OBJECTS += CDCSetControlLineStateRequest.o CDCLineCoding.o
 +C_OBJECTS += CDCDFunctionDriver.o
 +#C_OBJECTS += HIDIdleRequest.o HIDReportRequest.o HIDKeypad.o
 +#C_OBJECTS += HIDDKeyboardInputReport.o HIDDKeyboardOutputReport.o
 +#C_OBJECTS += HIDDFunctionDriver.o
 +C_OBJECTS += USBD_OTGHS.o USBD_UDP.o USBD_UDPHS.o USBDDriver.o
 +C_OBJECTS += USBDCallbacks_Initialized.o
 +C_OBJECTS += USBDCallbacks_Reset.o
 +#C_OBJECTS += USBDCallbacks_Resumed.o
 +#C_OBJECTS += USBDCallbacks_Suspended.o
 +#C_OBJECTS += USBDDriverCb_CfgChanged.o
 +#C_OBJECTS += USBDDriverCb_IfSettingChanged.o
 +C_OBJECTS += USBSetAddressRequest.o USBGenericDescriptor.o USBInterfaceRequest.o
 +C_OBJECTS += USBGenericRequest.o USBGetDescriptorRequest.o 
 +C_OBJECTS += USBSetConfigurationRequest.o USBFeatureRequest.o
 +C_OBJECTS += USBEndpointDescriptor.o USBConfigurationDescriptor.o
 +C_OBJECTS += led.o string.o stdio.o
 +C_OBJECTS += aic.o dbgu.o usart.o pio.o pio_it.o pmc.o cp15.o pit.o
 +C_OBJECTS += board_memories.o board_lowlevel.o
 +
 +# Objects built from Assembly source files
 +ASM_OBJECTS = board_cstartup.o
 +ASM_OBJECTS += cp15_asm.o
 +
 +# Append OBJ and BIN directories to output filename
 +OUTPUT := $(BIN)/$(OUTPUT)
 +
 +#-------------------------------------------------------------------------------
 +#		Rules
 +#-------------------------------------------------------------------------------
 +
 +all: $(BIN) $(OBJ) $(MEMORIES)
 +
 +$(BIN) $(OBJ):
 +	mkdir $@
 +
 +define RULES
 +C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS))
 +ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS))
 +
 +$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1))
 +	$(CC) $(LDFLAGS) -T"$(AT91LIB)/boards/$(BOARD)/$(CHIP)/$$@.lds" -o $(OUTPUT)-$$@.elf $$^
 +	$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin
 +	$(SIZE) $$^ $(OUTPUT)-$$@.elf
 +
 +$$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN)
 +	$(CC) $(CFLAGS) -D$(1) -c -o $$@ $$<
 +
 +$$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN)
 +	$(CC) $(ASFLAGS) -D$(1) -c -o $$@ $$<
 +
 +debug_$(1): $(1)
 +	perl ../resources/gdb/debug.pl $(OUTPUT)-$(1).elf
 +
 +endef
 +
 +$(foreach MEMORY, $(MEMORIES), $(eval $(call RULES,$(MEMORY))))
 +
 +clean:
 +	-rm -f $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf
 +
 diff --git a/usb-device-multi-project/main.c b/usb-device-multi-project/main.c new file mode 100644 index 0000000..b211770 --- /dev/null +++ b/usb-device-multi-project/main.c @@ -0,0 +1,406 @@ +#include <board.h>
 +#include <pio/pio.h>
 +#include <pio/pio_it.h>
 +#include <aic/aic.h>
 +#include <usart/usart.h>
 +#include <utility/trace.h>
 +#include <pit/pit.h>
 +#include <usb/common/core/USBConfigurationDescriptor.h>
 +#include <usb/device/core/USBD.h>
 +#include <utility/led.h>
 +#include <pmc/pmc.h>
 +
 +#include <usb/device/multiconf/MULTIDriver.h>
 +
 +#include <string.h>
 +
 +//-----------------------------------------------------------------------------
 +//      Definitions
 +//-----------------------------------------------------------------------------
 +#ifndef AT91C_ID_TC0
 +#if defined(AT91C_ID_TC012)
 +    #define AT91C_ID_TC0 AT91C_ID_TC012
 +#elif defined(AT91C_ID_TC)
 +    #define AT91C_ID_TC0 AT91C_ID_TC
 +#else
 +    #error Pb define ID_TC
 +#endif
 +#endif
 +
 +/// Master clock frequency in Hz
 +#define MCK             BOARD_MCK
 +
 +/// Number of keys used in the example.
 +#define NUM_KEYS                    4
 +
 +/// Number of non-modifiers keys.
 +#define NUM_NORMAL_KEYS             3
 +
 +/// Number of modifier keys.
 +#define NUM_MODIFIER_KEYS           (NUM_KEYS - NUM_NORMAL_KEYS)
 +
 +/// Num lock LED index.
 +#define LED_NUMLOCK                 USBD_LEDOTHER
 +
 +/// Delay for pushbutton debouncing (ms)
 +#define DEBOUNCE_TIME      10
 +
 +/// PIT period value (useconds)
 +#define PIT_PERIOD        1000
 +
 +/// Size in bytes of the buffer used for reading data from the USB & USART
 +#define DATABUFFERSIZE    BOARD_USB_ENDPOINTS_MAXPACKETSIZE(2)
 +
 +/// Use for power management
 +#define STATE_IDLE    0
 +/// The USB device is in suspend state
 +#define STATE_SUSPEND 4
 +/// The USB device is in resume state
 +#define STATE_RESUME  5
 +
 +//-----------------------------------------------------------------------------
 +//      Internal variables
 +//-----------------------------------------------------------------------------
 +/// State of USB, for suspend and resume
 +unsigned char USBState = STATE_IDLE;
 +
 +//- CDC
 +/// List of pins that must be configured for use by the application.
 +static const Pin pinsUsart[] = {PIN_USART0_TXD, PIN_USART0_RXD};
 +
 +/// Double-buffer for storing incoming USART data.
 +static unsigned char usartBuffers[2][DATABUFFERSIZE];
 +
 +/// Current USART buffer index.
 +static unsigned char usartCurrentBuffer = 0;
 +
 +/// Buffer for storing incoming USB data.
 +static unsigned char usbSerialBuffer0[DATABUFFERSIZE];
 +//static unsigned char usbSerialBuffer1[DATABUFFERSIZE];
 +
 +#define WAKEUP_CONFIGURE()
 +#define VBUS_CONFIGURE()    USBD_Connect()
 +
 +//------------------------------------------------------------------------------
 +/// Put the CPU in 32kHz, disable PLL, main oscillator
 +/// Put voltage regulator in standby mode
 +//------------------------------------------------------------------------------
 +void LowPowerMode(void)
 +{
 +    // MCK=48MHz to MCK=32kHz
 +    // MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M
 +    AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
 +    while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
 +    // MCK=SLCK : then change prescaler
 +    AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK;
 +    while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
 +    // disable PLL
 +    AT91C_BASE_PMC->PMC_PLLR = 0;
 +    // Disable Main Oscillator
 +    AT91C_BASE_PMC->PMC_MOR = 0;
 +
 +    // Voltage regulator in standby mode : Enable VREG Low Power Mode
 +    AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY;
 +
 +    PMC_DisableProcessorClock();
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Put voltage regulator in normal mode
 +/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
 +//------------------------------------------------------------------------------
 +void NormalPowerMode(void)
 +{
 +    // Voltage regulator in normal mode : Disable VREG Low Power Mode
 +    AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY;
 +
 +    // MCK=32kHz to MCK=48MHz
 +    // enable Main Oscillator
 +    AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN ));
 +    while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) );
 +
 +    // enable PLL@96MHz
 +    AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) |
 +         (AT91C_CKGR_PLLCOUNT & (28<<8)) |
 +         (AT91C_CKGR_MUL & (0x48<<16)));
 +    while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) );
 +    while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
 +    AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
 +    // MCK=SLCK/2 : change prescaler first
 +    AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
 +    while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
 +    // MCK=PLLCK/2 : then change source
 +    AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK  ;
 +    while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
 +
 +}
 +
 +//------------------------------------------------------------------------------
 +//         Callbacks re-implementation
 +//------------------------------------------------------------------------------
 +//------------------------------------------------------------------------------
 +/// Invoked when the USB device leaves the Suspended state. By default,
 +/// configures the LEDs.
 +//------------------------------------------------------------------------------
 +void USBDCallbacks_Resumed(void)
 +{
 +    // Initialize LEDs
 +    LED_Configure(USBD_LEDPOWER);
 +    LED_Set(USBD_LEDPOWER);
 +    LED_Configure(USBD_LEDUSB);
 +    LED_Clear(USBD_LEDUSB);
 +    USBState = STATE_RESUME;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Invoked when the USB device gets suspended. By default, turns off all LEDs.
 +//------------------------------------------------------------------------------
 +void USBDCallbacks_Suspended(void)
 +{
 +    // Turn off LEDs
 +    LED_Clear(USBD_LEDPOWER);
 +    LED_Clear(USBD_LEDUSB);
 +    USBState = STATE_SUSPEND;
 +}
 +
 +
 +
 +//-----------------------------------------------------------------------------
 +//         Internal functions
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +/// Handles interrupts coming from Timer #0.
 +//-----------------------------------------------------------------------------
 +static void ISR_Timer0()
 +{
 +    unsigned char size;
 +    unsigned int status = AT91C_BASE_TC0->TC_SR;
 +
 +    if ((status & AT91C_TC_CPCS) != 0) {
 +    
 +        // Flush PDC buffer
 +        size = DATABUFFERSIZE - AT91C_BASE_US0->US_RCR;
 +        if (size == 0) {
 +
 +            AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
 +            return;
 +        }
 +        AT91C_BASE_US0->US_RCR = 0;
 +    
 +        // Send current buffer through the USB
 +        while (CDCDSerialDriver_Write(0, usartBuffers[usartCurrentBuffer],
 +                                      size, 0, 0) != USBD_STATUS_SUCCESS);
 +    
 +        // Restart read on buffer
 +        USART_ReadBuffer(AT91C_BASE_US0,
 +                         usartBuffers[usartCurrentBuffer],
 +                         DATABUFFERSIZE);
 +        usartCurrentBuffer = 1 - usartCurrentBuffer;
 +        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
 +    }
 +}
 +
 +//-----------------------------------------------------------------------------
 +/// Callback invoked when data has been received on the USB.
 +//-----------------------------------------------------------------------------
 +static void UsbDataReceived0(unsigned int unused,
 +                             unsigned char status,
 +                             unsigned int received,
 +                             unsigned int remaining)
 +{
 +    // Check that data has been received successfully
 +    if (status == USBD_STATUS_SUCCESS) {
 +
 +        // Send data through USART
 +        while (!USART_WriteBuffer(AT91C_BASE_US0, usbSerialBuffer0, received));
 +        AT91C_BASE_US0->US_IER = AT91C_US_TXBUFE;
 +
 +        // Check if bytes have been discarded
 +        if ((received == DATABUFFERSIZE) && (remaining > 0)) {
 +
 +            TRACE_WARNING(
 +                      "UsbDataReceived: %u bytes discarded\n\r",
 +                      remaining);
 +        }
 +    }
 +    else {
 +
 +        TRACE_WARNING("UsbDataReceived: Transfer error\n\r");
 +    }
 +}
 +
 +//-----------------------------------------------------------------------------
 +/// Handles interrupts coming from USART #0.
 +//-----------------------------------------------------------------------------
 +static void ISR_Usart0()
 +{
 +    unsigned int status = AT91C_BASE_US0->US_CSR;
 +    unsigned short serialState;
 +
 +    // If USB device is not configured, do nothing
 +    if (USBD_GetState() != USBD_STATE_CONFIGURED) {
 +
 +        AT91C_BASE_US0->US_IDR = 0xFFFFFFFF;
 +        return;
 +    }
 +
 +    // Buffer has been read successfully
 +    if ((status & AT91C_US_ENDRX) != 0) {
 +
 +        // Disable timer
 +        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
 +
 +        // Send buffer through the USBSerial0
 +        while (CDCDSerialDriver_Write(0, usartBuffers[usartCurrentBuffer],
 +                                 DATABUFFERSIZE, 0, 0) != USBD_STATUS_SUCCESS);
 +
 +        // Restart read on buffer
 +        USART_ReadBuffer(AT91C_BASE_US0,
 +                         usartBuffers[usartCurrentBuffer],
 +                         DATABUFFERSIZE);
 +        usartCurrentBuffer = 1 - usartCurrentBuffer;
 +
 +        // Restart timer
 +        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
 +    }
 +
 +    // Buffer has been sent
 +    if ((status & AT91C_US_TXBUFE) != 0) {
 +
 +        // Restart USB read
 +        CDCDSerialDriver_Read(0, usbSerialBuffer0,
 +                              DATABUFFERSIZE,
 +                              (TransferCallback) UsbDataReceived0,
 +                              0);
 +        AT91C_BASE_US0->US_IDR = AT91C_US_TXBUFE;
 +    }
 +
 +    // Errors
 +    serialState = CDCDSerialDriver_GetSerialState(0);
 +
 +    // Overrun
 +    if ((status & AT91C_US_OVER) != 0) {
 +
 +        TRACE_WARNING("ISR_Usart0: Overrun\n\r");
 +        serialState |= CDCD_STATE_OVERRUN;
 +    }
 +
 +    // Framing error
 +    if ((status & AT91C_US_FRAME) != 0) {
 +
 +        TRACE_WARNING("ISR_Usart0: Framing error\n\r");
 +        serialState |= CDCD_STATE_FRAMING;
 +    }
 +
 +    CDCDSerialDriver_SetSerialState(0, serialState);
 +}
 +
 +//-----------------------------------------------------------------------------
 +//          Main
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +/// Initializes drivers and start the USB composite device.
 +//-----------------------------------------------------------------------------
 +int main()
 +{
 +    TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
 +    printf("-- USB Multi Device Project %s --\n\r", SOFTPACK_VERSION);
 +    printf("-- %s\n\r", BOARD_NAME);
 +    printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
 +
 +    // If they are present, configure Vbus & Wake-up pins
 +    PIO_InitializeInterrupts(0);
 +#if 0
 +    // ----- HID Function Initialize
 +    // Initialize key statuses and configure push buttons
 +    PIO_Configure(pinsPushButtons, PIO_LISTSIZE(pinsPushButtons));
 +    memset(keyStatus, 1, NUM_KEYS);
 +
 +    // Configure LEDs
 +    LED_Configure(LED_NUMLOCK);
 +
 +    // ----- CDC Function Initialize
 +    // Configure USART
 +    PIO_Configure(pinsUsart, PIO_LISTSIZE(pinsUsart));
 +    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_US0;
 +    AT91C_BASE_US0->US_IDR = 0xFFFFFFFF;
 +    USART_Configure(AT91C_BASE_US0,
 +                    USART_MODE_ASYNCHRONOUS,
 +                    115200,
 +                    MCK);
 +    USART_SetTransmitterEnabled(AT91C_BASE_US0, 1);
 +    USART_SetReceiverEnabled(AT91C_BASE_US0, 1);
 +    AIC_ConfigureIT(AT91C_ID_US0, 0, ISR_Usart0);
 +    AIC_EnableIT(AT91C_ID_US0);
 +
 +    // Configure timer 0
 +    AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
 +    AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
 +    AT91C_BASE_TC0->TC_IDR = 0xFFFFFFFF;
 +    AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK
 +                             | AT91C_TC_CPCSTOP
 +                             | AT91C_TC_CPCDIS
 +                             | AT91C_TC_WAVESEL_UP_AUTO
 +                             | AT91C_TC_WAVE;
 +    AT91C_BASE_TC0->TC_RC = 0x00FF;
 +    AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;
 +    AIC_ConfigureIT(AT91C_ID_TC0, 0, ISR_Timer0);
 +    AIC_EnableIT(AT91C_ID_TC0);
 +#endif
 +
 +    // USB COMPOSITE driver initialization
 +    MULTIDriver_Initialize();
 +
 +    WAKEUP_CONFIGURE();
 +
 +    // connect if needed
 +    VBUS_CONFIGURE();
 +
 +    // Driver loop
 +    while (1) {
 +
 +        // Device is not configured
 +        if (USBD_GetState() < USBD_STATE_CONFIGURED) {
 +
 +            // Connect pull-up, wait for configuration
 +            USBD_Connect();
 +            while (USBD_GetState() < USBD_STATE_CONFIGURED);
 +
 +#if 0
 +            // Start receiving data on the USART
 +            usartCurrentBuffer = 0;
 +            USART_ReadBuffer(AT91C_BASE_US0, usartBuffers[0], DATABUFFERSIZE);
 +            USART_ReadBuffer(AT91C_BASE_US0, usartBuffers[1], DATABUFFERSIZE);
 +            AT91C_BASE_US0->US_IER = AT91C_US_ENDRX
 +                                     | AT91C_US_FRAME
 +                                     | AT91C_US_OVER;
 +            AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
 +
 +            // Start receiving data on the USB
 +            CDCDSerialDriver_Read(0, usbSerialBuffer0,
 +                                  DATABUFFERSIZE,
 +                                  (TransferCallback) UsbDataReceived0,
 +                                  0);
 +        }
 +        else {
 +
 +            HIDDKeyboardProcessKeys();
 +#endif
 +        }
 +
 +        if( USBState == STATE_SUSPEND ) {
 +            TRACE_DEBUG("suspend  !\n\r");
 +            //LowPowerMode();
 +            USBState = STATE_IDLE;
 +        }
 +        if( USBState == STATE_RESUME ) {
 +            // Return in normal MODE
 +            TRACE_DEBUG("resume !\n\r");
 +            //NormalPowerMode();
 +            USBState = STATE_IDLE;
 +        }
 +    }
 +}
 +
 | 
