diff options
Diffstat (limited to 'usb')
226 files changed, 52617 insertions, 0 deletions
diff --git a/usb/USBFrameworkArchitecture.png b/usb/USBFrameworkArchitecture.png Binary files differnew file mode 100644 index 0000000..83e77eb --- /dev/null +++ b/usb/USBFrameworkArchitecture.png diff --git a/usb/common/audio/AUDControlInterfaceDescriptor.h b/usb/common/audio/AUDControlInterfaceDescriptor.h new file mode 100644 index 0000000..ada2f1e --- /dev/null +++ b/usb/common/audio/AUDControlInterfaceDescriptor.h @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definitions for using USB %audio control interfaces.
+///
+/// !!!Usage
+///
+/// -# When declaring a standard USB interface descriptor for an %audio control
+/// interface, use the "USB Audio control interface codes" constants.
+//------------------------------------------------------------------------------
+
+#ifndef AUDCONTROLINTERFACEDESCRIPTOR_H
+#define AUDCONTROLINTERFACEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio control interface codes"
+///
+/// This page lists the class, subclass and protocol codes that a USB Audio
+/// Control interface descriptor should display.
+///
+/// !Codes
+/// - AUDControlInterfaceDescriptor_CLASS
+/// - AUDControlInterfaceDescriptor_SUBCLASS
+/// - AUDControlInterfaceDescriptor_PROTOCOL
+
+/// Class code for an audio control interface.
+#define AUDControlInterfaceDescriptor_CLASS 0x01
+
+/// Subclass code for an audio control interface.
+#define AUDControlInterfaceDescriptor_SUBCLASS 0x01
+
+/// Protocol code for an audio control interface.
+#define AUDControlInterfaceDescriptor_PROTOCOL 0x00
+//------------------------------------------------------------------------------
+
+#endif //#ifndef AUDCONTROLINTERFACEDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDDataEndpointDescriptor.h b/usb/common/audio/AUDDataEndpointDescriptor.h new file mode 100644 index 0000000..5963546 --- /dev/null +++ b/usb/common/audio/AUDDataEndpointDescriptor.h @@ -0,0 +1,104 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definition of the USB audio-specific data endpoint descriptor.
+///
+/// !!!Usage
+///
+/// -# Declare an AUDDataEndpointDescriptor instance as part of the
+/// configuration descriptors of a USB %audio %device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDDATAENDPOINTDESCRIPTOR_H
+#define AUDDATAENDPOINTDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Descriptor subtype for an Audio data endpoint.
+#define AUDDataEndpointDescriptor_SUBTYPE 0x01
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio Lock delay units"
+///
+/// This page lists the valid lock delay unit types.
+///
+/// !Units
+/// - AUDDataEndpointDescriptor_MILLISECONDS
+/// - AUDDataEndpointDescriptor_PCMSAMPLES
+
+/// Lock delay is expressed in milliseconds.
+#define AUDDataEndpointDescriptor_MILLISECONDS 1
+
+/// Lock delay is expressed in decoded PCM samples.
+#define AUDDataEndpointDescriptor_PCMSAMPLES 2
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Gives additional information about an USB endpoint used to transmit audio
+/// data to or from the host.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (AUDGenericDescriptor_ENDPOINT).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (AUDDataEndpointDescriptor_SUBTYPE).
+ unsigned char bDescriptorSubType;
+ /// Indicates available controls and requirement on packet sizes.
+ unsigned char bmAttributes;
+ /// Indicates the units of the wLockDelay fields.
+ /// \sa "USB Audio Lock delay units"
+ unsigned char bLockDelayUnits;
+ /// Time it takes for the endpoint to lock its internal clock circuitry.
+ unsigned short wLockDelay;
+
+} __attribute__ ((packed)) AUDDataEndpointDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDDATAENDPOINTDESCRIPTOR_H
diff --git a/usb/common/audio/AUDDeviceDescriptor.h b/usb/common/audio/AUDDeviceDescriptor.h new file mode 100644 index 0000000..f33523a --- /dev/null +++ b/usb/common/audio/AUDDeviceDescriptor.h @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Fields values for an USB Audio %device descriptor.
+///
+/// !!!Usage
+///
+/// -# When declaring the %device descriptor of a USB %audio %device, use
+/// "USB Audio device descriptor values" defined here.
+//------------------------------------------------------------------------------
+
+#ifndef AUDDEVICEDESCRIPTOR_H
+#define AUDDEVICEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio device descriptor values"
+///
+/// This page lists the class, subclass & protocol codes that a USB audio
+/// device should display in its device descriptor.
+///
+/// !Codes
+/// - AUDDeviceDescriptor_CLASS
+/// - AUDDeviceDescriptor_SUBCLASS
+/// - AUDDeviceDescriptor_PROTOCOL
+
+/// Class code for a USB audio device.
+#define AUDDeviceDescriptor_CLASS 0x00
+
+/// Subclass code for a USB audio device.
+#define AUDDeviceDescriptor_SUBCLASS 0x00
+
+/// Protocol code for a USB audio device.
+#define AUDDeviceDescriptor_PROTOCOL 0x00
+//------------------------------------------------------------------------------
+
+#endif //#ifndef AUDDEVICEDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDEndpointDescriptor.h b/usb/common/audio/AUDEndpointDescriptor.h new file mode 100644 index 0000000..9dce6ab --- /dev/null +++ b/usb/common/audio/AUDEndpointDescriptor.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Re-definition of the standard USB endpoint descriptor with two additional
+/// fields. This is required by the USB audio 1.00 specification.
+///
+/// !!!Usage
+///
+/// -# Declare an AUDEndpointDescriptor instance as part of the configuration
+/// descriptors of an USB %audio %device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDENDPOINTDESCRIPTOR_H
+#define AUDENDPOINTDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Modified endpoint descriptor with two additional fields, with are
+/// USB audio specific.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of the descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (USBGenericDescriptor_ENDPOINT).
+ unsigned char bDescriptorType;
+ /// Address and direction of the endpoint.
+ unsigned char bEndpointAddress;
+ /// Endpoint type and additional characteristics (for isochronous endpoints).
+ unsigned char bmAttributes;
+ /// Maximum packet size (in bytes) of the endpoint.
+ unsigned short wMaxPacketSize;
+ /// Polling rate of the endpoint.
+ unsigned char bInterval;
+ /// Refresh rate for a feedback endpoint.
+ unsigned char bRefresh;
+ /// Address of the associated feedback endpoint if any.
+ unsigned char bSyncAddress;
+
+} __attribute__ ((packed)) AUDEndpointDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDENDPOINTDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDFeatureUnitDescriptor.h b/usb/common/audio/AUDFeatureUnitDescriptor.h new file mode 100644 index 0000000..a1ba45f --- /dev/null +++ b/usb/common/audio/AUDFeatureUnitDescriptor.h @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Class for manipulating USB %audio feature unit descriptor.
+///
+/// !!!Usage
+///
+/// -# Declare an AUDFeatureUnitDescriptor instance as part of the
+/// configuration descriptors returned by a USB %audio %device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDFEATUREUNITDESCRIPTOR_H
+#define AUDFEATUREUNITDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio Channel controls"
+///
+/// This page lists the available controls for each channel of the audio
+/// interface. Each channel can have any control combination; simply perform
+/// a bitwise OR ('|') to combine several values.
+///
+/// !Controls
+/// -# AUDFeatureUnitDescriptor_MUTE
+/// -# AUDFeatureUnitDescriptor_VOLUME
+/// -# AUDFeatureUnitDescriptor_BASS
+/// -# AUDFeatureUnitDescriptor_MID
+/// -# AUDFeatureUnitDescriptor_TREBLE
+
+/// Channel mute control.
+#define AUDFeatureUnitDescriptor_MUTE (1 << 0)
+
+/// Channel volume control.
+#define AUDFeatureUnitDescriptor_VOLUME (1 << 1)
+
+/// Channel bass control.
+#define AUDFeatureUnitDescriptor_BASS (1 << 2)
+
+/// Channel middle control.
+#define AUDFeatureUnitDescriptor_MID (1 << 3)
+
+/// Channel treble control.
+#define AUDFeatureUnitDescriptor_TREBLE (1 << 4)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Describes available controls for each channel of the unit or terminal
+/// it is connected to. This type must be augmented with the relevant number
+/// of bmaControls fields and the iFeature field.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (AUDGenericDescriptor_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (AUDGenericDescriptor_FEATURE).
+ unsigned char bDescriptorSubType;
+ /// Identifier of this feature unit.
+ unsigned char bUnitID;
+ /// Identifier of the unit or terminal this feature unit is connected to.
+ unsigned char bSourceID;
+ /// Size in bytes of a channel controls field.
+ unsigned char bControlSize;
+
+} __attribute__ ((packed)) AUDFeatureUnitDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDFEATUREUNITDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDFeatureUnitRequest.c b/usb/common/audio/AUDFeatureUnitRequest.c new file mode 100644 index 0000000..bc6c642 --- /dev/null +++ b/usb/common/audio/AUDFeatureUnitRequest.c @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------
+ * 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 "AUDFeatureUnitRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the control selector value indicating the target of a Feature Unit
+/// request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \sa "USB Audio Control selector values"
+//------------------------------------------------------------------------------
+unsigned char AUDFeatureUnitRequest_GetControl(const USBGenericRequest *request)
+{
+ return ((USBGenericRequest_GetValue(request) >> 8) & 0xFF);
+}
+
+//------------------------------------------------------------------------------
+/// Returns the channel number of a Feature unit which should be altered by the
+/// given request.
+/// \param request Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+unsigned char AUDFeatureUnitRequest_GetChannel(const USBGenericRequest *request)
+{
+ return (USBGenericRequest_GetValue(request) & 0xFF);
+}
+
diff --git a/usb/common/audio/AUDFeatureUnitRequest.h b/usb/common/audio/AUDFeatureUnitRequest.h new file mode 100644 index 0000000..289f598 --- /dev/null +++ b/usb/common/audio/AUDFeatureUnitRequest.h @@ -0,0 +1,81 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definitions of constants and methods for using USB %audio requests
+/// targetted at a Feature unit.
+///
+/// !!!Usage
+///
+/// - For a USB %device:
+/// -# Use AUDFeatureUnitRequest_GetControl to determine which control
+/// shall be tweaked following a host request.
+// -# Use AUDFeatureUnitRequest_GetChannel to identify the channel which
+// will have its control altered.
+//------------------------------------------------------------------------------
+
+#ifndef AUDFEATUREUNITREQUEST_H
+#define AUDFEATUREUNITREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio Control selector values"
+///
+/// This page lists the available control selectors for a Feature Unit request.
+///
+/// !Controls
+/// - AUDFeatureUnitRequest_MUTE
+
+/// Mute control selector.
+#define AUDFeatureUnitRequest_MUTE 0x01
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+extern unsigned char AUDFeatureUnitRequest_GetControl(
+ const USBGenericRequest *request);
+extern unsigned char AUDFeatureUnitRequest_GetChannel(
+ const USBGenericRequest *request);
+
+#endif //#ifndef AUDFEATUREUNITREQUEST_H
+
diff --git a/usb/common/audio/AUDFormatTypeOneDescriptor.h b/usb/common/audio/AUDFormatTypeOneDescriptor.h new file mode 100644 index 0000000..0aa6b63 --- /dev/null +++ b/usb/common/audio/AUDFormatTypeOneDescriptor.h @@ -0,0 +1,101 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definitions for using USB %audio format type I descriptors.
+///
+/// !!!Usage
+///
+/// -# Declare an instance of AUDFormatTypeOneDescriptor as part of the
+/// configuration descriptors of an audio device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDFORMATTYPEONEDESCRIPTOR_H
+#define AUDFORMATTYPEONEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Format type for a format type I descriptor.
+#define AUDFormatTypeOneDescriptor_FORMATTYPEONE 0x01
+
+/// AUDFormatTypeOneDescriptor_PCM - PCM format.
+#define AUDFormatTypeOneDescriptor_PCM 0x0001
+
+/// Indicates the sampling frequency can have any value in the provided range.
+#define AUDFormatTypeOneDescriptor_CONTINUOUS 0
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Describes an audio data stream that is constructed on a sample-by-sample
+/// basis. This type must be augmented with either the continuous sampling
+/// frequency range (if bSamFreqType = <AUDFormatTypeOneDescriptor_CONTINUOUS>)
+/// or with an array containing the possible discrete frequencies.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (AUDGenericDescriptor_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (AUDStreamingInterfaceDescriptor_FORMATTYPE).
+ unsigned char bDescriptorSubType;
+ /// Format type (AUDFormatTypeOneDescriptor_FORMATTYPEONE).
+ unsigned char bFormatType;
+ /// Number of physical channels in the audio stream.
+ unsigned char bNrChannels;
+ /// Number of bytes occupied by one audio subframe.
+ unsigned char bSubFrameSize;
+ /// Number of bits effectively used in an audio subframe.
+ unsigned char bBitResolution;
+ /// Number of supported discrete sampling frequencies, or
+ /// AUDFormatTypeOneDescriptor_CONTINUOUS.
+ unsigned char bSamFreqType;
+
+} __attribute__ ((packed)) AUDFormatTypeOneDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDFORMATTYPEONEDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDGenericDescriptor.h b/usb/common/audio/AUDGenericDescriptor.h new file mode 100644 index 0000000..8758a92 --- /dev/null +++ b/usb/common/audio/AUDGenericDescriptor.h @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Constants for manipulating USB audio-specific descriptors.
+///
+/// !!!Usage
+///
+/// - For a USB %device:
+/// -# When declaring an Audio-specific descriptor, use the descriptor types
+/// and subtypes defined in this unit (see "USB Audio descriptor types"
+/// and "USB Audio descriptor subtypes").
+//------------------------------------------------------------------------------
+
+#ifndef AUDGENERICDESCRIPTOR_H
+#define AUDGENERICDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio descriptor types"
+///
+/// This page lists the available types for USB audio-specific descriptors.
+///
+/// !Types
+/// - AUDGenericDescriptor_DEVICE
+/// - AUDGenericDescriptor_CONFIGURATION
+/// - AUDGenericDescriptor_STRING
+/// - AUDGenericDescriptor_INTERFACE
+/// - AUDGenericDescriptor_ENDPOINT
+
+/// Descriptor gives detail about the whole device.
+#define AUDGenericDescriptor_DEVICE 0x21
+
+/// Descriptor gives detail about a configuration.
+#define AUDGenericDescriptor_CONFIGURATION 0x22
+
+/// Descriptor gives detail about a string.
+#define AUDGenericDescriptor_STRING 0x23
+
+/// Descriptor gives detail about an interface.
+#define AUDGenericDescriptor_INTERFACE 0x24
+
+/// Descriptor gives detail about an endpoint.
+#define AUDGenericDescriptor_ENDPOINT 0x25
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio descriptor subtypes"
+///
+/// This page lists the possible subtypes for USB audio-specific descriptors.
+///
+/// !Subtypes
+/// - AUDGenericDescriptor_HEADER
+/// - AUDGenericDescriptor_INPUTTERMINAL
+/// - AUDGenericDescriptor_OUTPUTTERMINAL
+/// - AUDGenericDescriptor_MIXERUNIT
+/// - AUDGenericDescriptor_SELECTORUNIT
+/// - AUDGenericDescriptor_FEATUREUNIT
+/// - AUDGenericDescriptor_PROCESSINGUNIT
+/// - AUDGenericDescriptor_EXTENSIONUNIT
+
+/// Header descriptor subtype.
+#define AUDGenericDescriptor_HEADER 0x01
+
+/// Input terminal descriptor subtype.
+#define AUDGenericDescriptor_INPUTTERMINAL 0x02
+
+/// Output terminal descriptor subtype.
+#define AUDGenericDescriptor_OUTPUTTERMINAL 0x03
+
+/// Mixer unit descriptor subtype.
+#define AUDGenericDescriptor_MIXERUNIT 0x04
+
+/// Selector unit descriptor subtype.
+#define AUDGenericDescriptor_SELECTORUNIT 0x05
+
+/// Feature unit descriptor subtype.
+#define AUDGenericDescriptor_FEATUREUNIT 0x06
+
+/// Processing unit descriptor subtype.
+#define AUDGenericDescriptor_PROCESSINGUNIT 0x07
+
+///Extension unit descriptor subtype.
+#define AUDGenericDescriptor_EXTENSIONUNIT 0x08
+//------------------------------------------------------------------------------
+
+#endif //#ifndef AUDGENERICDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDGenericRequest.c b/usb/common/audio/AUDGenericRequest.c new file mode 100644 index 0000000..c9c6e87 --- /dev/null +++ b/usb/common/audio/AUDGenericRequest.c @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------
+ * 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 "AUDGenericRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the ID of the unit or terminal targetted by an USB audio request.
+/// \param request Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+unsigned char AUDGenericRequest_GetEntity(const USBGenericRequest *request)
+{
+ return ((USBGenericRequest_GetIndex(request) >> 8) & 0xFF);
+}
+
+//------------------------------------------------------------------------------
+/// Returns the ID of the interface targetted by an USB audio request.
+/// \param request Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+unsigned char AUDGenericRequest_GetInterface(const USBGenericRequest *request)
+{
+ return (USBGenericRequest_GetIndex(request) & 0xFF);
+}
+
diff --git a/usb/common/audio/AUDGenericRequest.h b/usb/common/audio/AUDGenericRequest.h new file mode 100644 index 0000000..b0b8527 --- /dev/null +++ b/usb/common/audio/AUDGenericRequest.h @@ -0,0 +1,94 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Constants for using USB %audio SETUP requests.
+///
+/// !!!Usage
+///
+/// - For a USB %device:
+/// -# After receiving an Audio request from the host, use
+/// AUDGenericRequest_GetEntity to determine the target Unit or Terminal.
+/// -# After receiving an Audio request from the host, use
+/// AUDGenericRequest_GetInterface to know which interface is referenced.
+//------------------------------------------------------------------------------
+
+#ifndef AUDGENERICREQUEST_H
+#define AUDGENERICREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio request codes"
+///
+/// This page lists the codes of the existing Audio requests.
+///
+/// !Requests
+/// - AUDGenericRequest_SETCUR
+/// - AUDGenericRequest_GETCUR
+
+/// SET_CUR request code.
+#define AUDGenericRequest_SETCUR 0x01
+
+/// GET_CUR request code.
+#define AUDGenericRequest_GETCUR 0x81
+
+/// GET_MIN request code.
+#define AUDGenericRequest_GETMIN 0x82
+
+/// GET_MAX request code.
+#define AUDGenericRequest_GETMAX 0x83
+
+/// GET_RES request code.
+#define AUDGenericRequest_GETRES 0x84
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char AUDGenericRequest_GetEntity(
+ const USBGenericRequest *request);
+extern unsigned char AUDGenericRequest_GetInterface(
+ const USBGenericRequest *request);
+
+#endif //#ifndef AUDGENERICREQUEST_H
+
diff --git a/usb/common/audio/AUDHeaderDescriptor.h b/usb/common/audio/AUDHeaderDescriptor.h new file mode 100644 index 0000000..ca30a0b --- /dev/null +++ b/usb/common/audio/AUDHeaderDescriptor.h @@ -0,0 +1,100 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Class for manipulating USB %audio header descriptors.
+///
+/// !!!Usage
+///
+/// - For a USB %device:
+/// -# Declare a AUDHeaderDescriptor as part of the configuration
+/// descriptors of the %device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDHEADERDESCRIPTOR_H
+#define AUDHEADERDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio class releases"
+/// This page lists the existing versions of the Audio class specification.
+///
+///
+/// !Versions
+/// - AUDHeaderDescriptor_AUD1_00
+
+/// Indentifies the USB audio specification release 1.00.
+#define AUDHeaderDescriptor_AUD1_00 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Groups the various audio interfaces to display one single function to
+/// the USB host. Subclass this structure to add a particular number of
+/// slave interface descriptors.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (AUDGenericDescriptor_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (AUDGenericDescriptor_HEADER).
+ unsigned char bDescriptorSubType;
+ /// Audio class release number in BCD format
+ /// \sa "USB Audio class releases"
+ unsigned short bcdADC;
+ /// Length of all descriptors used to qualify the Audio Control interface.
+ unsigned short wTotalLength;
+ /// Number of Streaming interfaces contained in this collection.
+ unsigned char bInCollection;
+
+} __attribute__ ((packed)) AUDHeaderDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDHEADERDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDInputTerminalDescriptor.h b/usb/common/audio/AUDInputTerminalDescriptor.h new file mode 100644 index 0000000..e0895fb --- /dev/null +++ b/usb/common/audio/AUDInputTerminalDescriptor.h @@ -0,0 +1,139 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Class for manipulating input terminal descriptors.
+///
+/// !!!Usage
+///
+/// - For a USB %device:
+/// -# Declare an AUDInputTerminalDescriptor instance as part of the
+/// configuration of the %device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDINPUTTERMINALDESCRIPTOR_H
+#define AUDINPUTTERMINALDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio Input terminal types"
+///
+/// This page lists the available types for an Input terminal.
+///
+/// !Types
+///
+/// - AUDInputTerminalDescriptor_USBSTREAMING
+/// - AUDInputTerminalDescriptor_MICROPHONE
+/// - AUDInputTerminalDescriptor_SPEAKERPHONE
+/// - AUDInputTerminalDescriptor_LINEIN
+
+/// A terminal receiving its data from a USB isochronous endpoint.
+#define AUDInputTerminalDescriptor_USBSTREAMING 0x0101
+/// A terminal sampling data from a microphone.
+#define AUDInputTerminalDescriptor_MICROPHONE 0x0201
+/// A terminal sampling data from a Handset In.
+#define AUDInputTerminalDescriptor_HANDSETIN 0x0401
+/// A terminal sampling data from a speakerphone
+#define AUDInputTerminalDescriptor_SPEAKERPHONE 0x0403
+/// A terminal sampling data from a Phone Line In.
+#define AUDInputTerminalDescriptor_LINEIN 0x0501
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio Channel spatial locations"
+///
+/// This page lists the possible spatial locations for audio channels.
+///
+/// !Locations
+///
+/// - AUDInputTerminalDescriptor_LEFTFRONT
+/// - AUDInputTerminalDescriptor_RIGHTFRONT
+/// - AUDInputTerminalDescriptor_CENTERFRONT
+
+/// Front left channel.
+#define AUDInputTerminalDescriptor_LEFTFRONT (1 << 0)
+
+/// Front right channel.
+#define AUDInputTerminalDescriptor_RIGHTFRONT (1 << 1)
+
+/// Front center channel.
+#define AUDInputTerminalDescriptor_CENTERFRONT (1 << 2)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Describes an input of a USB audio device.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (AUDGenericDescriptor_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (AUDGenericDescriptor_INPUTTERMINAL).
+ unsigned char bDescriptorSubType;
+ /// ID of the terminal in the audio function.
+ unsigned char bTerminalID;
+ /// Terminal type.
+ /// \sa "USB Audio Input terminal types"
+ unsigned short wTerminalType;
+ /// ID of the output terminal to which this input terminal is associated.
+ unsigned char bAssocTerminal;
+ /// Number of logical output channels in this terminal.
+ unsigned char bNrChannels;
+ /// Spatial configuration of the logical channels.
+ unsigned short wChannelConfig;
+ /// Index of a string descriptor for the first logical channel.
+ unsigned char iChannelNames;
+ /// Index of a string descriptor for this terminal.
+ unsigned char iTerminal;
+
+} __attribute__ ((packed)) AUDInputTerminalDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDINPUTTERMINALDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDOutputTerminalDescriptor.h b/usb/common/audio/AUDOutputTerminalDescriptor.h new file mode 100644 index 0000000..6ba3156 --- /dev/null +++ b/usb/common/audio/AUDOutputTerminalDescriptor.h @@ -0,0 +1,112 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definition of a class for using USB %audio output terminal descriptors.
+///
+/// !!!Usage
+///
+/// - For a USB %device:
+/// -# Declare a AUDOutputTerminalDescriptor instance as part of the
+/// configuration descriptors of a USB %audio %device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDOUTPUTTERMINALDESCRIPTOR_H
+#define AUDOUTPUTTERMINALDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio Output terminal types"
+///
+/// This page lists the available types for an output terminal.
+///
+/// !Types
+/// - AUDOutputTerminalDescriptor_USBTREAMING
+/// - AUDOutputTerminalDescriptor_SPEAKER
+/// - AUDOutputTerminalDescriptor_HANDSETOUT
+/// - AUDOutputTerminalDescriptor_LINEOUT
+
+/// A terminal sending data through USB isochronous endpoint.
+#define AUDOutputTerminalDescriptor_USBTREAMING 0x0101
+/// A terminal sending data to a USB host through an Isochronous endpoint.
+#define AUDOutputTerminalDescriptor_SPEAKER 0x0301
+/// A terminal sending data to Handset Out.
+#define AUDOutputTerminalDescriptor_HANDSETOUT 0x0401
+/// A terminal sending data to Phone Line Out.
+#define AUDOutputTerminalDescriptor_LINEOUT 0x0501
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// \typedef AUDOutputTerminalDescriptor
+/// Describes an output of the USB audio function.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (AUDGenericDescriptor_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (AUDGenericDescriptor_OUTPUTTERMINAL).
+ unsigned char bDescriptorSubType;
+ /// Identifier for this terminal.
+ unsigned char bTerminalID;
+ /// Terminal type.
+ /// \sa "USB Audio Output terminal types"
+ unsigned short wTerminalType;
+ /// Identifier of the associated input terminal.
+ unsigned char bAssocTerminal;
+ /// Identifier of the unit or terminal to which this terminal is connected.
+ unsigned char bSourceID;
+ /// Index of a string descriptor for this terminal.
+ unsigned char iTerminal;
+
+} __attribute__ ((packed)) AUDOutputTerminalDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDOUTPUTTERMINALDESCRIPTOR_H
+
diff --git a/usb/common/audio/AUDStreamingInterfaceDescriptor.h b/usb/common/audio/AUDStreamingInterfaceDescriptor.h new file mode 100644 index 0000000..80c9cfd --- /dev/null +++ b/usb/common/audio/AUDStreamingInterfaceDescriptor.h @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definition of a class for manipulating USB %audio streaming interface
+/// descriptors.
+///
+/// !!!Usage
+///
+/// - For a USB %device:
+/// -# Declare an AUDStreamingInterfaceDescriptor instance as part of the
+/// configuration descriptors returned by a USB %audio %device.
+//------------------------------------------------------------------------------
+
+#ifndef AUDSTREAMINGINTERFACEDESCRIPTOR_H
+#define AUDSTREAMINGINTERFACEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio streaming interface codes"
+///
+/// This page lists the class, subclass and protocol codes that an Audio
+/// Streaming interface should display in its descriptor.
+///
+/// !Codes
+/// - AUDStreamingInterfaceDescriptor_CLASS
+/// - AUDStreamingInterfaceDescriptor_SUBCLASS
+/// - AUDStreamingInterfaceDescriptor_PROTOCOL
+
+/// Class code for an USB audio streaming interface.
+#define AUDStreamingInterfaceDescriptor_CLASS 0x01
+
+/// Subclass code for an audio streaming interface.
+#define AUDStreamingInterfaceDescriptor_SUBCLASS 0x02
+
+/// Protocol code for an audio streaming interface.
+#define AUDStreamingInterfaceDescriptor_PROTOCOL 0x00
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Audio streaming descriptor subtypes"
+///
+/// This page lists the possible subtypes for audio-specific descriptor appended
+/// to an Audio Streaming interface.
+///
+/// !Subtypes
+/// - AUDStreamingInterfaceDescriptor_GENERAL
+/// - AUDStreamingInterfaceDescriptor_FORMATTYPE
+/// - AUDStreamingInterfaceDescriptor_FORMATSPECIFIC
+
+/// General descriptor subtype.
+#define AUDStreamingInterfaceDescriptor_GENERAL 0x01
+
+/// Format type descriptor subtype.
+#define AUDStreamingInterfaceDescriptor_FORMATTYPE 0x02
+
+/// Format specific descriptor subtype.
+#define AUDStreamingInterfaceDescriptor_FORMATSPECIFIC 0x03
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Provides additional information about an audio streaming interface to
+/// the USB host.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (AUDGenericDescriptor_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (AUDStreamingInterfaceDescriptor_GENERAL).
+ unsigned char bDescriptorSubType;
+ /// Terminal ID to which the interface is connected.
+ unsigned char bTerminalLink;
+ /// Delay introduced by the data path, in number of frames.
+ unsigned char bDelay;
+ /// Audio data format used by this interface.
+ unsigned short wFormatTag;
+
+} __attribute__ ((packed)) AUDStreamingInterfaceDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef AUDSTREAMINGINTERFACEDESCRIPTOR_H
+
diff --git a/usb/common/audio/audio.dir b/usb/common/audio/audio.dir new file mode 100644 index 0000000..2bc574f --- /dev/null +++ b/usb/common/audio/audio.dir @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !!!Purpose
+///
+/// This directory contains definitions, structures and funcions related to the
+/// USB Audio Class specification. They can be divided into two groups:
+/// - Audio-specific descriptors, prefixed with AUD and suffixed with
+/// Descriptor.
+/// - Audio-specific requests, prefixed with AUD and suffixed with Request.
+//------------------------------------------------------------------------------
+
diff --git a/usb/common/cdc/CDCAbstractControlManagementDescriptor.h b/usb/common/cdc/CDCAbstractControlManagementDescriptor.h new file mode 100644 index 0000000..943204c --- /dev/null +++ b/usb/common/cdc/CDCAbstractControlManagementDescriptor.h @@ -0,0 +1,104 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for manipulating CDC abstract control management
+ descriptors.
+
+ !!!Usage
+
+ Should be included in a list of USB configuration descriptors.
+*/
+
+#ifndef CDCABSTRACTCONTROLMANAGEMENTDESCRIPTOR_H
+#define CDCABSTRACTCONTROLMANAGEMENTDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC ACM Capabilities"
+/// This page lists the capabilities of the CDC ACM.
+///
+/// !Capabilities
+/// - CDCAbstractControlManagementDescriptor_COMMFEATURE
+/// - CDCAbstractControlManagementDescriptor_LINE
+/// - CDCAbstractControlManagementDescriptor_SENDBREAK
+/// - CDCAbstractControlManagementDescriptor_NETWORKCONNECTION
+
+/// Device supports the request combination of SetCommFeature, ClearCommFeature
+/// and GetCommFeature.
+#define CDCAbstractControlManagementDescriptor_COMMFEATURE (1 << 0)
+/// Device supports the request combination of SetLineCoding, GetLineCoding and
+/// SetControlLineState.
+#define CDCAbstractControlManagementDescriptor_LINE (1 << 1)
+/// Device supports the SendBreak request.
+#define CDCAbstractControlManagementDescriptor_SENDBREAK (1 << 2)
+/// Device supports the NetworkConnection notification.
+#define CDCAbstractControlManagementDescriptor_NETWORKCONNECTION (1 << 3)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Describes the command supported by the communication interface class
+/// with the Abstract Control Model subclass code.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of this descriptor in bytes.
+ unsigned char bFunctionLength;
+ /// Descriptor type (CDCDescriptors_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (CDCDescriptors_ABSTRACTCONTROLMANAGEMENT).
+ unsigned char bDescriptorSubtype;
+ /// Configuration capabilities.
+ /// \sa "CDC ACM Capabilities".
+ unsigned char bmCapabilities;
+
+} __attribute__ ((packed)) CDCAbstractControlManagementDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef CDCABSTRACTCONTROLMANAGEMENTDESCRIPTOR_H
+
diff --git a/usb/common/cdc/CDCCallManagementDescriptor.h b/usb/common/cdc/CDCCallManagementDescriptor.h new file mode 100644 index 0000000..191ff61 --- /dev/null +++ b/usb/common/cdc/CDCCallManagementDescriptor.h @@ -0,0 +1,97 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for managing CDC call management descriptors.
+
+ !!!Usage
+
+ Should be included in a list of configuration descriptors for a USB
+ device.
+*/
+
+#ifndef CDCCALLMANAGEMENTDESCRIPTOR_H
+#define CDCCALLMANAGEMENTDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC CallManagement Capabilities"
+/// This page lists CDC CallManagement Capabilities.
+///
+/// !Capabilities
+/// - CDCCallManagementDescriptor_SELFCALLMANAGEMENT
+/// - CDCCallManagementDescriptor_DATACALLMANAGEMENT
+
+/// Device handles call management itself.
+#define CDCCallManagementDescriptor_SELFCALLMANAGEMENT (1 << 0)
+/// Device can exchange call management information over a Data class interface.
+#define CDCCallManagementDescriptor_DATACALLMANAGEMENT (1 << 1)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Describes the processing of calls for the communication class interface.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of this descriptor in bytes.
+ unsigned char bFunctionLength;
+ /// Descriptor type (CDCDescriptors_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor sub-type (CDCDescriptors_CALLMANAGEMENT).
+ unsigned char bDescriptorSubtype;
+ /// Configuration capabilities ("CDC CallManagement Capabilities").
+ unsigned char bmCapabilities;
+ /// Interface number of the data class interface used for call management
+ /// (optional).
+ unsigned char bDataInterface;
+
+} __attribute__ ((packed)) CDCCallManagementDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef CDCCALLMANAGEMENTDESCRIPTOR_H
+
diff --git a/usb/common/cdc/CDCCommunicationInterfaceDescriptor.h b/usb/common/cdc/CDCCommunicationInterfaceDescriptor.h new file mode 100644 index 0000000..aa13915 --- /dev/null +++ b/usb/common/cdc/CDCCommunicationInterfaceDescriptor.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of several constants used when declaring a CDC communication
+ class interface descriptor.
+*/
+
+#ifndef CDCCOMMUNICATIONINTERFACEDESCRIPTOR_H
+#define CDCCOMMUNICATIONINTERFACEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Communication Interface Values"
+/// This page lists the values for CDC Communication Interface Descriptor.
+///
+/// !Values
+/// - CDCCommunicationInterfaceDescriptor_CLASS
+/// - CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL
+/// - CDCCommunicationInterfaceDescriptor_NOPROTOCOL
+
+/// Interface class code for a CDC communication class interface.
+#define CDCCommunicationInterfaceDescriptor_CLASS 0x02
+/// Interface subclass code for an Abstract Control Model interface descriptor.
+#define CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL 0x02
+/// Interface protocol code when a CDC communication interface does not
+/// implemenent any particular protocol.
+#define CDCCommunicationInterfaceDescriptor_NOPROTOCOL 0x00
+//------------------------------------------------------------------------------
+
+#endif //#ifndef CDCCOMMUNICATIONINTERFACEDESCRIPTOR_H
+
diff --git a/usb/common/cdc/CDCDataInterfaceDescriptor.h b/usb/common/cdc/CDCDataInterfaceDescriptor.h new file mode 100644 index 0000000..640f8dc --- /dev/null +++ b/usb/common/cdc/CDCDataInterfaceDescriptor.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions of constants used when declaring a CDC data class interface
+ descriptor.
+*/
+
+#ifndef CDCDATAINTERFACEDESCRIPTOR_H
+#define CDCDATAINTERFACEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Data Interface Values"
+/// This page lists the values for CDC Data Interface Descriptor.
+///
+/// !Values
+/// - CDCDataInterfaceDescriptor_CLASS
+/// - CDCDataInterfaceDescriptor_SUBCLASS
+/// - CDCDataInterfaceDescriptor_NOPROTOCOL
+
+/// Interface class code for a data class interface.
+#define CDCDataInterfaceDescriptor_CLASS 0x0A
+/// Interface subclass code for a data class interface.
+#define CDCDataInterfaceDescriptor_SUBCLASS 0x00
+/// Protocol code for a data class interface which does not implement any
+/// particular protocol.
+#define CDCDataInterfaceDescriptor_NOPROTOCOL 0x00
+//------------------------------------------------------------------------------
+
+#endif //#ifndef CDCDATAINTERFACEDESCRIPTOR_H
+
diff --git a/usb/common/cdc/CDCDeviceDescriptor.h b/usb/common/cdc/CDCDeviceDescriptor.h new file mode 100644 index 0000000..b1bc177 --- /dev/null +++ b/usb/common/cdc/CDCDeviceDescriptor.h @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of several constants used when declaring USB CDC device
+ descriptors.
+*/
+
+#ifndef CDCDEVICEDESCRIPTOR_H
+#define CDCDEVICEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Device Descriptor Values"
+/// This page lists the values for CDC Device Descriptor.
+///
+/// !Values
+/// - CDCDeviceDescriptor_CLASS
+/// - CDCDeviceDescriptor_SUBCLASS
+/// - CDCDeviceDescriptor_PROTOCOL
+
+/// Device class code when using the CDC class.
+#define CDCDeviceDescriptor_CLASS 0x02
+/// Device subclass code when using the CDC class.
+#define CDCDeviceDescriptor_SUBCLASS 0x00
+/// Device protocol code when using the CDC class.
+#define CDCDeviceDescriptor_PROTOCOL 0x00
+//------------------------------------------------------------------------------
+
+#endif //#ifndef CDCDEVICEDESCRIPTOR_H
+
diff --git a/usb/common/cdc/CDCGenericDescriptor.h b/usb/common/cdc/CDCGenericDescriptor.h new file mode 100644 index 0000000..3d93656 --- /dev/null +++ b/usb/common/cdc/CDCGenericDescriptor.h @@ -0,0 +1,91 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of several constants for declaring CDC descriptors.
+*/
+
+#ifndef CDCGENERICDESCRIPTOR_H
+#define CDCGENERICDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Specification Release Numbers"
+/// This page list the CDC Spec. Release Numbers.
+///
+/// !Numbers
+/// - CDCGenericDescriptor_CDC1_10
+
+/// Identify CDC specification version 1.10.
+#define CDCGenericDescriptor_CDC1_10 0x0110
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Descriptro Types"
+/// This page lists CDC descriptor types.
+///
+/// !Types
+/// - CDCGenericDescriptor_INTERFACE
+/// - CDCGenericDescriptor_ENDPOINT
+
+///Indicates that a CDC descriptor applies to an interface.
+#define CDCGenericDescriptor_INTERFACE 0x24
+/// Indicates that a CDC descriptor applies to an endpoint.
+#define CDCGenericDescriptor_ENDPOINT 0x25
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Descriptor Subtypes"
+/// This page lists CDC descriptor sub types
+///
+/// !Types
+/// - CDCGenericDescriptor_HEADER
+/// - CDCGenericDescriptor_CALLMANAGEMENT
+/// - CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT
+/// - CDCGenericDescriptor_UNION
+
+/// Header functional descriptor subtype.
+#define CDCGenericDescriptor_HEADER 0x00
+/// Call management functional descriptor subtype.
+#define CDCGenericDescriptor_CALLMANAGEMENT 0x01
+/// Abstract control management descriptor subtype.
+#define CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT 0x02
+/// Union descriptor subtype.
+#define CDCGenericDescriptor_UNION 0x06
+//------------------------------------------------------------------------------
+
+#endif //#ifndef CDCGENERICDESCRIPTOR_H
+
diff --git a/usb/common/cdc/CDCGenericRequest.h b/usb/common/cdc/CDCGenericRequest.h new file mode 100644 index 0000000..d6abd0b --- /dev/null +++ b/usb/common/cdc/CDCGenericRequest.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Various definitions used for characterizing USB CDC requests.
+*/
+
+#ifndef CDCGENERICREQUEST_H
+#define CDCGENERICREQUEST_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Request Codes"
+/// This page lists USB CDC Request Codes.
+///
+/// !Codes
+/// - CDCGenericRequest_SETLINECODING
+/// - CDCGenericRequest_GETLINECODING
+/// - CDCGenericRequest_SETCONTROLLINESTATE
+
+/// SetLineCoding request code.
+#define CDCGenericRequest_SETLINECODING 0x20
+/// GetLineCoding request code.
+#define CDCGenericRequest_GETLINECODING 0x21
+/// SetControlLineState request code.
+#define CDCGenericRequest_SETCONTROLLINESTATE 0x22
+//------------------------------------------------------------------------------
+
+#endif //#ifndef CDCGENERICREQUEST_H
+
diff --git a/usb/common/cdc/CDCHeaderDescriptor.h b/usb/common/cdc/CDCHeaderDescriptor.h new file mode 100644 index 0000000..b04926f --- /dev/null +++ b/usb/common/cdc/CDCHeaderDescriptor.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of the CDCHeaderDescriptor class.
+
+ !!!Usage
+
+ Should be included in a USB configuration descriptor.
+*/
+
+#ifndef CDCHEADERDESCRIPTOR_H
+#define CDCHEADERDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Marks the beginning of the concatenated set of functional descriptors
+/// for the interface.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of this descriptor in bytes.
+ unsigned char bFunctionLength;
+ /// Descriptor type (CDCDescriptors_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor sub-type (CDCDescriptors_HEADER).
+ unsigned char bDescriptorSubtype;
+ /// USB CDC specification release number.
+ unsigned short bcdCDC;
+
+} __attribute__ ((packed)) CDCHeaderDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef CDCHEADERDESCRIPTOR_H
+
+
diff --git a/usb/common/cdc/CDCLineCoding.c b/usb/common/cdc/CDCLineCoding.c new file mode 100644 index 0000000..4223fec --- /dev/null +++ b/usb/common/cdc/CDCLineCoding.c @@ -0,0 +1,78 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: CDCLineCoding
+
+ About: Purpose
+ Implementation of the CDCLineCoding class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "CDCLineCoding.h"
+#include <utility/assert.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the bitrate, number of stop bits, parity checking and
+/// number of data bits of a CDCLineCoding object.
+/// \param lineCoding Pointer to a CDCLineCoding instance.
+/// \param bitrate Bitrate of the virtual COM connection.
+/// \param stopbits Number of stop bits ("CDC LineCoding StopBits").
+/// \param parity Parity check type ("CDC LineCoding ParityChecking").
+/// \param databits Number of data bits.
+//------------------------------------------------------------------------------
+void CDCLineCoding_Initialize(CDCLineCoding *lineCoding,
+ unsigned int bitrate,
+ unsigned char stopbits,
+ unsigned char parity,
+ unsigned char databits)
+{
+ ASSERT(stopbits <= CDCLineCoding_TWOSTOPBITS,
+ "CDCLineCoding_Initialize: Invalid stopbits value (%d)\n\r",
+ stopbits);
+ ASSERT(parity <= CDCLineCoding_SPACEPARITY,
+ "CDCLineCoding_Initialize: Invalid parity value (%d)\n\r",
+ parity);
+ ASSERT(((databits >= 5) && (databits <= 8)) || (databits == 16),
+ "CDCLineCoding_Initialize: Invalid databits value (%d)\n\r",
+ databits);
+
+ lineCoding->dwDTERate = bitrate;
+ lineCoding->bCharFormat = stopbits;
+ lineCoding->bParityType = parity;
+ lineCoding->bDataBits = databits;
+}
+
diff --git a/usb/common/cdc/CDCLineCoding.h b/usb/common/cdc/CDCLineCoding.h new file mode 100644 index 0000000..dfe3c10 --- /dev/null +++ b/usb/common/cdc/CDCLineCoding.h @@ -0,0 +1,136 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Line coding structure used for by the CDC GetLineCoding and SetLineCoding
+ requests.
+
+ !!!Usage
+
+ -# Initialize a CDCLineCoding instance using CDCLineCoding_Initialize.
+ -# Send a CDCLineCoding object to the host in response to a GetLineCoding
+ request.
+ -# Receive a CDCLineCoding object from the host after a SetLineCoding
+ request.
+*/
+
+#ifndef CDCLINECODING_H
+#define CDCLINECODING_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC LineCoding StopBits"
+/// This page lists Stop Bits for CDC Line Coding.
+///
+/// !Stop bits
+/// - CDCLineCoding_ONESTOPBIT
+/// - CDCLineCoding_ONE5STOPBIT
+/// - CDCLineCoding_TWOSTOPBITS
+
+/// The transmission protocol uses one stop bit.
+#define CDCLineCoding_ONESTOPBIT 0
+/// The transmission protocol uses 1.5 stop bit.
+#define CDCLineCoding_ONE5STOPBIT 1
+/// The transmissin protocol uses two stop bits.
+#define CDCLineCoding_TWOSTOPBITS 2
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC LineCoding ParityCheckings"
+/// This page lists Parity checkings for CDC Line Coding.
+///
+/// !Parity checking
+/// - CDCLineCoding_NOPARITY
+/// - CDCLineCoding_ODDPARITY
+/// - CDCLineCoding_EVENPARITY
+/// - CDCLineCoding_MARKPARITY
+/// - CDCLineCoding_SPACEPARITY
+
+/// No parity checking.
+#define CDCLineCoding_NOPARITY 0
+/// Odd parity checking.
+#define CDCLineCoding_ODDPARITY 1
+/// Even parity checking.
+#define CDCLineCoding_EVENPARITY 2
+/// Mark parity checking.
+#define CDCLineCoding_MARKPARITY 3
+/// Space parity checking.
+#define CDCLineCoding_SPACEPARITY 4
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Format of the data returned when a GetLineCoding request is received.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Data terminal rate in bits per second.
+ unsigned int dwDTERate;
+ /// Number of stop bits.
+ /// \sa "CDC LineCoding StopBits".
+ char bCharFormat;
+ /// Type of parity checking used.
+ /// \sa "CDC LineCoding ParityCheckings".
+ char bParityType;
+ /// Number of data bits (5, 6, 7, 8 or 16).
+ char bDataBits;
+
+} __attribute__ ((packed)) CDCLineCoding; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void CDCLineCoding_Initialize(CDCLineCoding *lineCoding,
+ unsigned int bitrate,
+ unsigned char stopbits,
+ unsigned char parity,
+ unsigned char databits);
+
+#endif //#ifndef CDCLINECODING_H
+
diff --git a/usb/common/cdc/CDCSetControlLineStateRequest.c b/usb/common/cdc/CDCSetControlLineStateRequest.c new file mode 100644 index 0000000..43079ca --- /dev/null +++ b/usb/common/cdc/CDCSetControlLineStateRequest.c @@ -0,0 +1,84 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ CDCSetControlLineStateRequest.c
+
+ !!!Purpose
+
+ Implementation of the CDCSetControlLineStateRequest class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "CDCSetControlLineStateRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Notifies if the given request indicates that the DTE signal is present.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return 1 if the DTE signal is present, otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char CDCSetControlLineStateRequest_IsDtePresent(
+ const USBGenericRequest *request)
+{
+ if ((USBGenericRequest_GetValue(request) & 0x0001) != 0) {
+
+ return 1;
+ }
+ else {
+
+ return 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Notifies if the given request indicates that the device carrier should
+/// be activated.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return 1 is the device should activate its carrier, 0 otherwise.
+//------------------------------------------------------------------------------
+unsigned char CDCSetControlLineStateRequest_ActivateCarrier(
+ const USBGenericRequest *request)
+{
+ if ((USBGenericRequest_GetValue(request) & 0x0002) != 0) {
+
+ return 1;
+ }
+ else {
+
+ return 0;
+ }
+}
+
diff --git a/usb/common/cdc/CDCSetControlLineStateRequest.h b/usb/common/cdc/CDCSetControlLineStateRequest.h new file mode 100644 index 0000000..5d6c661 --- /dev/null +++ b/usb/common/cdc/CDCSetControlLineStateRequest.h @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for manipulating SetControlLineState requests.
+*/
+
+#ifndef CDCSETCONTROLLINESTATE_H
+#define CDCSETCONTROLLINESTATE_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char CDCSetControlLineStateRequest_IsDtePresent(
+ const USBGenericRequest *request);
+
+
+extern unsigned char CDCSetControlLineStateRequest_ActivateCarrier(
+ const USBGenericRequest *request);
+
+#endif //#ifndef CDCSETCONTROLLINESTATE_H
+
diff --git a/usb/common/cdc/CDCUnionDescriptor.h b/usb/common/cdc/CDCUnionDescriptor.h new file mode 100644 index 0000000..0ba9eaa --- /dev/null +++ b/usb/common/cdc/CDCUnionDescriptor.h @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for manipulating CDC union descriptors.
+
+ !!!Usage
+
+ Should be included in the list of USB descriptor used for a device
+ configuration.
+*/
+
+#ifndef CDCUNIONDESCRIPTOR_H
+#define CDCUNIONDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Describes the relationship between a group of interfaces that can
+/// be considered to form a functional unit.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of the descriptor in bytes.
+ unsigned char bFunctionLength;
+ /// Descriptor type (CDCDescriptors_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Descriptor subtype (CDCDescriptors_UNION).
+ unsigned char bDescriptorSubtype;
+ /// Number of the master interface for this union.
+ unsigned char bMasterInterface;
+ /// Number of the first slave interface for this union.
+ unsigned char bSlaveInterface0;
+
+} __attribute__ ((packed)) CDCUnionDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef CDCUNIONDESCRIPTOR_H
+
diff --git a/usb/common/cdc/cdc.dir b/usb/common/cdc/cdc.dir new file mode 100644 index 0000000..8d9e99b --- /dev/null +++ b/usb/common/cdc/cdc.dir @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !Purpose
+///
+/// This directory contains structures and definitions related to the USB CDC
+/// specification. They can be divided into two groups:
+/// - CDC-specific descriptors, prefixed with CDC and suffixed with Descriptor.
+/// - CDC-specific requests, prefixed with CDC and suffixed with Request.
+//------------------------------------------------------------------------------
+
diff --git a/usb/common/common.dir b/usb/common/common.dir new file mode 100644 index 0000000..239696c --- /dev/null +++ b/usb/common/common.dir @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !!!Purpose
+///
+/// This directory containes highly re-usable code from USB standard and some
+/// classes specifications for general use.
+///
+/// !!!Contents
+/// This dircetory provides two sections of definitions:
+/// -# Definitions, structures and functions from USB specification,
+/// commonly used for all USB classes and projects.
+/// - core: for USB specification
+/// -# Definitions, structures and functions from class-specific
+/// specification commonly used for class related project ONLY.
+/// - cdc: for USB Communication Devie Class (CDC)
+/// - hid: for USB Humen Interface Device Class (HID)
+/// - massstorage: for USB Mass Storage Class (MS)
+/// - audio: for USB Audio Class (AUD)
+///
+/// For more information about what a particular group contains, please refer to
+/// its documentation page.
+///
+/// \note
+/// Depending on the project, not all the subdirectories will be available
+/// (i.e. the #cdc# directory will not be in non-CDC projects).
+//------------------------------------------------------------------------------
\ No newline at end of file diff --git a/usb/common/core/USBConfigurationDescriptor.c b/usb/common/core/USBConfigurationDescriptor.c new file mode 100644 index 0000000..503dceb --- /dev/null +++ b/usb/common/core/USBConfigurationDescriptor.c @@ -0,0 +1,162 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBConfigurationDescriptor implementation
+
+ About: Purpose
+ Implementation of the USBConfigurationDescriptor class.
+*/
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include "USBConfigurationDescriptor.h"
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Returns the total length of a configuration, i.e. including the
+/// descriptors following it.
+/// \param configuration Pointer to a USBConfigurationDescriptor instance.
+/// \return Total length (in bytes) of the configuration.
+//-----------------------------------------------------------------------------
+unsigned int USBConfigurationDescriptor_GetTotalLength(
+ const USBConfigurationDescriptor *configuration)
+{
+ return configuration->wTotalLength;
+}
+
+//-----------------------------------------------------------------------------
+/// Returns the number of interfaces in a configuration.
+/// \param configuration Pointer to a USBConfigurationDescriptor instance.
+/// \return Number of interfaces in configuration.
+//-----------------------------------------------------------------------------
+unsigned char USBConfigurationDescriptor_GetNumInterfaces(
+ const USBConfigurationDescriptor *configuration)
+{
+ return configuration->bNumInterfaces;
+}
+
+//-----------------------------------------------------------------------------
+/// Indicates if the device is self-powered when in a given configuration.
+/// \param configuration Pointer to a USBConfigurationDescriptor instance.
+/// \return 1 if the device is self-powered when in the given configuration;
+/// otherwise 0.
+//-----------------------------------------------------------------------------
+unsigned char USBConfigurationDescriptor_IsSelfPowered(
+ const USBConfigurationDescriptor *configuration)
+{
+ if ((configuration->bmAttributes & (1 << 6)) != 0) {
+
+ return 1;
+ }
+ else {
+
+ return 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Parses the given Configuration descriptor (followed by relevant
+/// interface, endpoint and class-specific descriptors) into three arrays.
+/// *Each array must have its size equal or greater to the number of
+/// descriptors it stores plus one*. A null-value is inserted after the last
+/// descriptor of each type to indicate the array end.
+///
+/// Note that if the pointer to an array is null (0), nothing is stored in
+/// it.
+/// \param configuration Pointer to the start of the whole Configuration
+/// descriptor.
+/// \param interfaces Pointer to the Interface descriptor array.
+/// \param endpoints Pointer to the Endpoint descriptor array.
+/// \param others Pointer to the class-specific descriptor array.
+//-----------------------------------------------------------------------------
+void USBConfigurationDescriptor_Parse(
+ const USBConfigurationDescriptor *configuration,
+ USBInterfaceDescriptor **interfaces,
+ USBEndpointDescriptor **endpoints,
+ USBGenericDescriptor **others)
+{
+ // Get size of configuration to parse
+ int size = USBConfigurationDescriptor_GetTotalLength(configuration);
+ size -= sizeof(USBConfigurationDescriptor);
+
+ // Start parsing descriptors
+ USBGenericDescriptor *descriptor = (USBGenericDescriptor *) configuration;
+ while (size > 0) {
+
+ // Get next descriptor
+ descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor);
+ size -= USBGenericDescriptor_GetLength(descriptor);
+
+ // Store descriptor in correponding array
+ if (USBGenericDescriptor_GetType(descriptor)
+ == USBGenericDescriptor_INTERFACE) {
+
+ if (interfaces) {
+
+ *interfaces = (USBInterfaceDescriptor *) descriptor;
+ interfaces++;
+ }
+ }
+ else if (USBGenericDescriptor_GetType(descriptor)
+ == USBGenericDescriptor_ENDPOINT) {
+
+ if (endpoints) {
+
+ *endpoints = (USBEndpointDescriptor *) descriptor;
+ endpoints++;
+ }
+ }
+ else if (others) {
+
+ *others = descriptor;
+ others++;
+ }
+ }
+
+ // Null-terminate arrays
+ if (interfaces) {
+
+ *interfaces = 0;
+ }
+ if (endpoints) {
+
+ *endpoints = 0;
+ }
+ if (others) {
+
+ *others = 0;
+ }
+}
+
diff --git a/usb/common/core/USBConfigurationDescriptor.h b/usb/common/core/USBConfigurationDescriptor.h new file mode 100644 index 0000000..150e656 --- /dev/null +++ b/usb/common/core/USBConfigurationDescriptor.h @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+ !!!Purpose
+
+ Definitions and methods for USB configuration descriptor structures
+ described by the USB specification.
+
+ !!!Usage
+
+ -# Declare USBConfigurationDescriptor instance as a part
+ of the configuration descriptors of a USB device.
+ -# To get useful information (field values) from the defined USB device
+ configuration descriptor, use
+ - USBConfigurationDescriptor_GetTotalLength
+ - USBConfigurationDescriptor_GetNumInterfaces
+ - USBConfigurationDescriptor_IsSelfPowered
+ -# To pase the defined USB device configuration descriptor, use
+ - USBConfigurationDescriptor_Parse
+*/
+
+#ifndef USBCONFIGURATIONDESCRIPTOR_H
+#define USBCONFIGURATIONDESCRIPTOR_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include "USBGenericDescriptor.h"
+#include "USBInterfaceDescriptor.h"
+#include "USBEndpointDescriptor.h"
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// \page "USB device Attributes"
+///
+/// This page lists the codes of the usb attributes.
+///
+/// !Attributes
+/// - USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
+/// - USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
+/// - USBConfigurationDescriptor_BUSPOWERED_RWAKEUP
+/// - USBConfigurationDescriptor_SELFPOWERED_RWAKEUP
+/// - USBConfigurationDescriptor_POWER
+
+/// Device is bus-powered and not support remote wake-up.
+#define USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP 0x80
+/// Device is self-powered and not support remote wake-up.
+#define USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP 0xC0
+/// Device is bus-powered and supports remote wake-up.
+#define USBConfigurationDescriptor_BUSPOWERED_RWAKEUP 0xA0
+/// Device is self-powered and supports remote wake-up.
+#define USBConfigurationDescriptor_SELFPOWERED_RWAKEUP 0xE0
+
+/// Calculates the value of the power consumption field given the value in mA.
+/// \param power The power consumption value in mA
+/// \return The value that should be set to the field in descriptor
+#define USBConfigurationDescriptor_POWER(power) (power / 2)
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//-----------------------------------------------------------------------------
+/// USB standard configuration descriptor structure.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of the descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (USBDESC_CONFIGURATION of "USB Descriptor types").
+ unsigned char bDescriptorType;
+ /// Length of all descriptors returned along with this configuration
+ /// descriptor.
+ unsigned short wTotalLength;
+ /// Number of interfaces in this configuration.
+ unsigned char bNumInterfaces;
+ /// Value for selecting this configuration.
+ unsigned char bConfigurationValue;
+ /// Index of the configuration string descriptor.
+ unsigned char iConfiguration;
+ /// Configuration characteristics.
+ unsigned char bmAttributes;
+ /// Maximum power consumption of the device when in this configuration.
+ unsigned char bMaxPower;
+
+} __attribute__ ((packed)) USBConfigurationDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+extern unsigned int USBConfigurationDescriptor_GetTotalLength(
+ const USBConfigurationDescriptor *configuration);
+
+extern unsigned char USBConfigurationDescriptor_GetNumInterfaces(
+ const USBConfigurationDescriptor *configuration);
+
+extern unsigned char USBConfigurationDescriptor_IsSelfPowered(
+ const USBConfigurationDescriptor *configuration);
+
+extern void USBConfigurationDescriptor_Parse(
+ const USBConfigurationDescriptor *configuration,
+ USBInterfaceDescriptor **interfaces,
+ USBEndpointDescriptor **endpoints,
+ USBGenericDescriptor **others);
+
+#endif //#ifndef USBCONFIGURATIONDESCRIPTOR_H
+
diff --git a/usb/common/core/USBConfigurationOTG.c b/usb/common/core/USBConfigurationOTG.c new file mode 100644 index 0000000..c875790 --- /dev/null +++ b/usb/common/core/USBConfigurationOTG.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+
+#include "USBConfigurationOTG.h"
+
+
+USBGenericOTGDescriptor *pOTGDescriptor;
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// External functions
+//-----------------------------------------------------------------------------
+void OTG_Initialize(USBGenericOTGDescriptor *pOTGDesc)
+{
+ pOTGDescriptor = pOTGDesc;
+}
+
+
diff --git a/usb/common/core/USBConfigurationOTG.h b/usb/common/core/USBConfigurationOTG.h new file mode 100644 index 0000000..d0d3b05 --- /dev/null +++ b/usb/common/core/USBConfigurationOTG.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Methods and definitions for configuring OTG.
+///
+/// !Usage
+///
+/// -#
+/// -#
+///
+//------------------------------------------------------------------------------
+
+#ifndef USBCONFIGURATIONOTG_H
+#define USBCONFIGURATIONOTG_H
+
+#include <usb/otg/compiler.h>
+
+
+/// OTG specific configuration
+typedef struct {
+
+ /// USB MODE CONFIGURATION
+
+ /// ENABLE to activate the host software library support
+ /// Possible values ENABLE or DISABLE
+ unsigned char bOTGUsbHostFeature;
+
+ /// ENABLE to activate the device software library support
+ /// Possible values ENABLE or DISABLE
+ unsigned char bOTGUsbDeviceFeature;
+ /// OTG MODE CONFIGURATION
+ /// ENABLE to enable OTG module (support A- and B- Device roles)
+ /// Possible values ENABLE or DISABLE
+ unsigned char bOTGFeature;
+
+ /// For reduced host only allows to control VBUS generator with PIO PE.7
+ unsigned char bOTGSoftwareVbusCtrl;
+
+ /// Selects the messaging method for OTG No Silent Failure spec.
+ ///
+ /// A compliant OTG device must at least handle 3 Failure messages :
+ /// "Device No Response", "Unsupported Device" and "Unsupported Hub"
+ /// Functions must be defined for communicating messages to user (LCD display,
+ /// LEDs...)
+ /// The values available for this parameter are :
+ /// - OTGMSG_ALL : all messages (events and failures) are displayed
+ /// In this case, the following functions must be defined in user application firmware :
+ /// # "void Otg_messaging_init(void)", this function is called at start up to initialize the messaging peripheral
+ /// # "void Otg_output_failure_msg(U8)", displays the failure message choosen by ID number (see "usb_task.h")
+ /// # "void Otg_output_failure_clear(void)", clears the current failure message
+ /// # "void Otg_output_event_msg(U8)", displays the event message choosen by ID number
+ /// # "void Otg_output_event_clear(void)", clears the current event message
+ /// - OTGMSG_FAIL : only failure messages are displayed
+ /// In this case, the following functions must be defined in user application firmware :
+ /// # "void Otg_messaging_init(void)", this function is called at start up to initialize the messaging peripheral
+ /// # "void Otg_output_failure_msg(U8)", displays the failure message choosen by ID number (see "usb_task.h")
+ /// # "void Otg_output_failure_clear(void)", clears the current failure message
+ /// - OTGMSG_NONE : messages are not displayed (not OTG compliant device)
+ unsigned char bOTGMessagingOutput;
+
+ /// ENABLE to make the A-Device send a SetFeature(b_hnp_enable) just after a SRP
+ /// has been received
+ /// This feature must be ENABLE to pass the OTG compliance program
+ /// Possible values ENABLE or DISABLE
+ unsigned char bOTGEnableHNPAfterSRP;
+
+ /// Selects the SRP pulse for which the A Device will react and rise Vbus
+ /// The value is VBUS_PULSE or DATA_PULSE
+ unsigned char bOTGADevSRPReaction;
+
+} USBGenericOTGDescriptor;
+
+#define OTGMSG_NONE 0 // no messages displayed
+#define OTGMSG_FAIL 1 // only failure messages displayed
+#define OTGMSG_ALL 2 // all messages displayed
+
+#define VBUS_PULSE 1 // no more used
+#define DATA_PULSE 0
+
+
+extern USBGenericOTGDescriptor *pOTGDescriptor;
+
+extern void OTG_Initialize(USBGenericOTGDescriptor *pOTGDesc);
+
+
+#endif //#ifndef USBCONFIGURATIONOTG_H
+
diff --git a/usb/common/core/USBDeviceDescriptor.h b/usb/common/core/USBDeviceDescriptor.h new file mode 100644 index 0000000..ce8d199 --- /dev/null +++ b/usb/common/core/USBDeviceDescriptor.h @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+ !!!Purpose
+
+ Class for manipulating USB device descriptors.
+
+ !!!Usage
+
+ - Declare a USBDeviceDescriptor instance as the device descriptor of a
+ USB device.
+*/
+
+#ifndef USBDEVICEDESCRIPTOR_H
+#define USBDEVICEDESCRIPTOR_H
+
+#include <board.h>
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB release numbers"
+///
+/// This page lists the codes of USB release numbers.
+///
+/// !Code
+/// - USBDeviceDescriptor_USB2_00
+
+/// The device supports USB 2.00.
+#define USBDeviceDescriptor_USB2_00 0x0200
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// USB standard device descriptor structure.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of this descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (USBGenericDescriptor_DEVICE).
+ unsigned char bDescriptorType;
+ /// USB specification release number in BCD format.
+ unsigned short bcdUSB;
+ /// Device class code.
+ unsigned char bDeviceClass;
+ /// Device subclass code.
+ unsigned char bDeviceSubClass;
+ /// Device protocol code.
+ unsigned char bDeviceProtocol;
+ /// Maximum packet size of endpoint 0 (in bytes).
+ unsigned char bMaxPacketSize0;
+ /// Vendor ID.
+ unsigned short idVendor;
+ /// Product ID.
+ unsigned short idProduct;
+ /// Device release number in BCD format.
+ unsigned short bcdDevice;
+ /// Index of the manufacturer string descriptor.
+ unsigned char iManufacturer;
+ /// Index of the product string descriptor.
+ unsigned char iProduct;
+ /// Index of the serial number string descriptor.
+ unsigned char iSerialNumber;
+ /// Number of possible configurations for the device.
+ unsigned char bNumConfigurations;
+
+} __attribute__ ((packed)) USBDeviceDescriptor; // GCC
+
+#if defined(CHIP_USB_OTGHS)
+typedef struct {
+
+ /// Size of this descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (USBGenericDescriptor_OTG).
+ unsigned char bDescriptorType;
+ /// Attribute Fields D7…2: Reserved D1: HNP support D0: SRP support
+ unsigned char bmAttributes;
+
+} __attribute__ ((packed)) USBOtgDescriptor; // GCC
+#endif
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef USBDEVICEDESCRIPTOR_H
+
diff --git a/usb/common/core/USBDeviceQualifierDescriptor.h b/usb/common/core/USBDeviceQualifierDescriptor.h new file mode 100644 index 0000000..3728865 --- /dev/null +++ b/usb/common/core/USBDeviceQualifierDescriptor.h @@ -0,0 +1,89 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Class for manipulating USB device qualifier descriptors.
+
+ !!!Usage
+
+ - Declare a USBDeviceQualifierDescriptor instance as the device qualifier
+ descriptor of a USB device.
+*/
+
+#ifndef USBDEVICEQUALIFIERDESCRIPTOR_H
+#define USBDEVICEQUALIFIERDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Alternate device descriptor indicating the capabilities of the device
+/// in full-speed, if currently in high-speed; or in high-speed, if it is
+/// currently in full-speed. Only relevant for devices supporting the
+/// high-speed mode.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of the descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (USBDESC_DEVICE_QUALIFIER or "USB device types").
+ unsigned char bDescriptorType;
+ /// USB specification release number (in BCD format).
+ unsigned short bcdUSB;
+ /// Device class code.
+ unsigned char bDeviceClass;
+ /// Device subclass code.
+ unsigned char bDeviceSubClass;
+ /// Device protocol code.
+ unsigned char bDeviceProtocol;
+ /// Maximum packet size of endpoint 0.
+ unsigned char bMaxPacketSize0;
+ /// Number of possible configurations for the device.
+ unsigned char bNumConfigurations;
+ /// Reserved.
+ unsigned char bReserved;
+
+} __attribute__ ((packed)) USBDeviceQualifierDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef USBDEVICEQUALIFIERDESCRIPTOR_H
+
diff --git a/usb/common/core/USBEndpointDescriptor.c b/usb/common/core/USBEndpointDescriptor.c new file mode 100644 index 0000000..6300ade --- /dev/null +++ b/usb/common/core/USBEndpointDescriptor.c @@ -0,0 +1,109 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBEndpointDescriptor implementation
+
+ About: Purpose
+ Implementation of the USBEndpointDescriptor class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBEndpointDescriptor.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the number of an endpoint given its descriptor.
+/// \param endpoint Pointer to a USBEndpointDescriptor instance.
+/// \return Endpoint number.
+//------------------------------------------------------------------------------
+unsigned char USBEndpointDescriptor_GetNumber(
+ const USBEndpointDescriptor *endpoint)
+{
+ return endpoint->bEndpointAddress & 0xF;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the direction of an endpoint given its descriptor.
+/// \param endpoint Pointer to a USBEndpointDescriptor instance.
+/// \return Endpoint direction (see <Endpoint directions>).
+//------------------------------------------------------------------------------
+unsigned char USBEndpointDescriptor_GetDirection(
+ const USBEndpointDescriptor *endpoint)
+{
+ if ((endpoint->bEndpointAddress & 0x80) != 0) {
+
+ return USBEndpointDescriptor_IN;
+ }
+ else {
+
+ return USBEndpointDescriptor_OUT;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Returns the type of an endpoint given its descriptor.
+/// \param endpoint Pointer to a USBEndpointDescriptor instance.
+/// \return Endpoint type (see <Endpoint types>).
+//------------------------------------------------------------------------------
+unsigned char USBEndpointDescriptor_GetType(
+ const USBEndpointDescriptor *endpoint)
+{
+ return endpoint->bmAttributes & 0x3;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the maximum size of a packet (in bytes) on an endpoint given
+/// its descriptor.
+/// \param endpoint - Pointer to a USBEndpointDescriptor instance.
+/// \return Maximum packet size of endpoint.
+//------------------------------------------------------------------------------
+unsigned short USBEndpointDescriptor_GetMaxPacketSize(
+ const USBEndpointDescriptor *endpoint)
+{
+ return endpoint->wMaxPacketSize;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the polling interval on an endpoint given its descriptor.
+/// \param endpoint - Pointer to a USBEndpointDescriptor instance.
+/// \return Polling interval of endpoint.
+//------------------------------------------------------------------------------
+unsigned char USBEndpointDescriptor_GetInterval(
+ const USBEndpointDescriptor *endpoint)
+{
+ return endpoint->bInterval;
+}
+
diff --git a/usb/common/core/USBEndpointDescriptor.h b/usb/common/core/USBEndpointDescriptor.h new file mode 100644 index 0000000..d49e028 --- /dev/null +++ b/usb/common/core/USBEndpointDescriptor.h @@ -0,0 +1,224 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for handling USB endpoint descriptors.
+
+ !!!Usage
+
+ -# Declare USBEndpointDescriptor instance as a part of the
+ configuration descriptors of a USB device.
+ -# To get useful information (field values) from the defined USB device
+ endpoint descriptor (to configure hardware for endpoints, etc), use
+ - USBEndpointDescriptor_GetNumber
+ - USBEndpointDescriptor_GetDirection
+ - USBEndpointDescriptor_GetType
+ - USBEndpointDescriptor_GetMaxPacketSize
+*/
+
+#ifndef USBENDPOINTDESCRIPTOR_H
+#define USBENDPOINTDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Endpoint definitions"
+///
+/// This page lists definitions and macro for endpoint descriptors.
+///
+/// - USB Endpoint directions
+/// - USBEndpointDescriptor_OUT
+/// - USBEndpointDescriptor_IN
+///
+/// - USB Endpoint types
+/// - USBEndpointDescriptor_CONTROL
+/// - USBEndpointDescriptor_ISOCHRONOUS
+/// - USBEndpointDescriptor_BULK
+/// - USBEndpointDescriptor_INTERRUPT
+///
+/// - USB Endpoint maximun sizes
+/// - USBEndpointDescriptor_MAXCTRLSIZE_FS
+/// - USBEndpointDescriptor_MAXCTRLSIZE_HS
+/// - USBEndpointDescriptor_MAXBULKSIZE_FS
+/// - USBEndpointDescriptor_MAXBULKSIZE_HS
+/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_FS
+/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_HS
+/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS
+/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_HS
+///
+/// - USB Endpoint address define
+/// - USBEndpointDescriptor_ADDRESS
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Endpoint directions"
+///
+/// This page lists definitions of USB endpoint directions.
+///
+/// !Directions
+/// - USBEndpointDescriptor_OUT
+/// - USBEndpointDescriptor_IN
+
+/// Endpoint receives data from the host.
+#define USBEndpointDescriptor_OUT 0
+/// Endpoint sends data to the host.
+#define USBEndpointDescriptor_IN 1
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Endpoint types"
+///
+/// This page lists definitions of USB endpoint types.
+///
+/// !Types
+/// - USBEndpointDescriptor_CONTROL
+/// - USBEndpointDescriptor_ISOCHRONOUS
+/// - USBEndpointDescriptor_BULK
+/// - USBEndpointDescriptor_INTERRUPT
+
+/// Control endpoint type.
+#define USBEndpointDescriptor_CONTROL 0
+/// Isochronous endpoint type.
+#define USBEndpointDescriptor_ISOCHRONOUS 1
+/// Bulk endpoint type.
+#define USBEndpointDescriptor_BULK 2
+/// Interrupt endpoint type.
+#define USBEndpointDescriptor_INTERRUPT 3
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Endpoint maximun sizes"
+///
+/// This page lists definitions of USB endpoint maximun sizes.
+///
+/// !Sizes
+/// - USBEndpointDescriptor_MAXCTRLSIZE_FS
+/// - USBEndpointDescriptor_MAXCTRLSIZE_HS
+/// - USBEndpointDescriptor_MAXBULKSIZE_FS
+/// - USBEndpointDescriptor_MAXBULKSIZE_HS
+/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_FS
+/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_HS
+/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS
+/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_HS
+
+/// Maximum size for a full-speed control endpoint.
+#define USBEndpointDescriptor_MAXCTRLSIZE_FS 64
+/// Maximum size for a high-speed control endpoint.
+#define USBEndpointDescriptor_MAXCTRLSIZE_HS 64
+/// Maximum size for a full-speed bulk endpoint.
+#define USBEndpointDescriptor_MAXBULKSIZE_FS 64
+/// Maximum size for a high-speed bulk endpoint.
+#define USBEndpointDescriptor_MAXBULKSIZE_HS 512
+/// Maximum size for a full-speed interrupt endpoint.
+#define USBEndpointDescriptor_MAXINTERRUPTSIZE_FS 64
+/// Maximum size for a high-speed interrupt endpoint.
+#define USBEndpointDescriptor_MAXINTERRUPTSIZE_HS 1024
+/// Maximum size for a full-speed isochronous endpoint.
+#define USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS 1023
+/// Maximum size for a high-speed isochronous endpoint.
+#define USBEndpointDescriptor_MAXISOCHRONOUSSIZE_HS 1024
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Endpoint address define"
+///
+/// This page lists macro for USB endpoint address definition.
+///
+/// !Macro
+/// - USBEndpointDescriptor_ADDRESS
+
+/// Calculates the address of an endpoint given its number and direction
+/// \param direction USB endpoint direction definition
+/// \param number USB endpoint number
+/// \return The value used to set the endpoint descriptor based on input number
+/// and direction
+#define USBEndpointDescriptor_ADDRESS(direction, number) \
+ (((direction & 0x01) << 7) | (number & 0xF))
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// USB standard endpoint descriptor structure.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of the descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (<USBGenericDescriptor_ENDPOINT>).
+ unsigned char bDescriptorType;
+ /// Address and direction of the endpoint.
+ unsigned char bEndpointAddress;
+ /// Endpoint type and additional characteristics (for isochronous endpoints).
+ unsigned char bmAttributes;
+ /// Maximum packet size (in bytes) of the endpoint.
+ unsigned short wMaxPacketSize;
+ /// Polling rate of the endpoint.
+ unsigned char bInterval;
+
+} __attribute__ ((packed)) USBEndpointDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char USBEndpointDescriptor_GetNumber(
+ const USBEndpointDescriptor *endpoint);
+
+extern unsigned char USBEndpointDescriptor_GetDirection(
+ const USBEndpointDescriptor *endpoint);
+
+extern unsigned char USBEndpointDescriptor_GetType(
+ const USBEndpointDescriptor *endpoint);
+
+extern unsigned short USBEndpointDescriptor_GetMaxPacketSize(
+ const USBEndpointDescriptor *endpoint);
+
+extern unsigned char USBEndpointDescriptor_GetInterval(
+ const USBEndpointDescriptor *endpoint);
+
+#endif //#ifndef USBENDPOINTDESCRIPTOR_H
+
diff --git a/usb/common/core/USBFeatureRequest.c b/usb/common/core/USBFeatureRequest.c new file mode 100644 index 0000000..1e0422a --- /dev/null +++ b/usb/common/core/USBFeatureRequest.c @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBFeatureRequest implementation
+
+ About: Purpose
+ Implementation of the USBFeatureRequest class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBFeatureRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the feature selector of a given CLEAR_FEATURE or SET_FEATURE
+/// request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Feature selector.
+//------------------------------------------------------------------------------
+unsigned char USBFeatureRequest_GetFeatureSelector(
+ const USBGenericRequest *request)
+{
+ return USBGenericRequest_GetValue(request);
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the test that the device must undertake following a
+/// SET_FEATURE request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Test selector.
+//------------------------------------------------------------------------------
+unsigned char USBFeatureRequest_GetTestSelector(
+ const USBGenericRequest *request)
+{
+ return (USBGenericRequest_GetIndex(request) >> 8) & 0xFF;
+}
+
diff --git a/usb/common/core/USBFeatureRequest.h b/usb/common/core/USBFeatureRequest.h new file mode 100644 index 0000000..0454ffb --- /dev/null +++ b/usb/common/core/USBFeatureRequest.h @@ -0,0 +1,146 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for manipulating CLEAR_FEATURE and SET_FEATURE
+ requests.
+
+ !!!Usage
+
+ - To get USB feature request information (field values) from the
+ USBGenericRequest instance, use
+ - USBFeatureRequest_GetFeatureSelector
+ - USBFeatureRequest_GetTestSelector
+*/
+
+#ifndef USBFEATUREREQUEST_H
+#define USBFEATUREREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGenericRequest.h"
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Feature Request definitions"
+///
+/// This page lists codes of USB Feature Request
+///
+/// - USB Feature selectors
+/// - USBFeatureRequest_ENDPOINTHALT
+/// - USBFeatureRequest_DEVICEREMOTEWAKEUP
+/// - USBFeatureRequest_TESTMODE
+///
+/// - USB Test mode selectors
+/// - USBFeatureRequest_TESTJ
+/// - USBFeatureRequest_TESTK
+/// - USBFeatureRequest_TESTSE0NAK
+/// - USBFeatureRequest_TESTPACKET
+/// - USBFeatureRequest_TESTFORCEENABLE
+/// - USBFeatureRequest_TESTSENDZLP
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Feature selectors"
+///
+/// This page lists codes of USB feature selectors.
+///
+/// !Selectors
+/// - USBFeatureRequest_ENDPOINTHALT
+/// - USBFeatureRequest_DEVICEREMOTEWAKEUP
+/// - USBFeatureRequest_TESTMODE
+
+/// Halt feature of an endpoint.
+#define USBFeatureRequest_ENDPOINTHALT 0
+/// Remote wake-up feature of the device.
+#define USBFeatureRequest_DEVICEREMOTEWAKEUP 1
+/// Test mode of the device.
+#define USBFeatureRequest_TESTMODE 2
+/// OTG set feature
+#define USBFeatureRequest_OTG 0x0B
+//------------------------------------------------------------------------------
+
+/// On The Go Feature Selectors
+/// b_hnp_enable 3
+/// a_hnp_support 4
+/// a_alt_hnp_support 5
+#define USBFeatureRequest_OTG_B_HNP_ENABLE 3
+#define USBFeatureRequest_OTG_A_HNP_SUPPORT 4
+#define USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT 5
+
+//------------------------------------------------------------------------------
+/// \page "USB Test mode selectors"
+///
+/// This page lists codes of USB high speed test mode selectors.
+///
+/// !Selectors
+/// - USBFeatureRequest_TESTJ
+/// - USBFeatureRequest_TESTK
+/// - USBFeatureRequest_TESTSE0NAK
+/// - USBFeatureRequest_TESTPACKET
+/// - USBFeatureRequest_TESTFORCEENABLE
+/// - USBFeatureRequest_TESTSENDZLP
+
+/// Tests the high-output drive level on the D+ line.
+#define USBFeatureRequest_TESTJ 1
+/// Tests the high-output drive level on the D- line.
+#define USBFeatureRequest_TESTK 2
+/// Tests the output impedance, low-level output voltage and loading
+/// characteristics.
+#define USBFeatureRequest_TESTSE0NAK 3
+/// Tests rise and fall times, eye patterns and jitter.
+#define USBFeatureRequest_TESTPACKET 4
+/// Tests the hub disconnect detection.
+#define USBFeatureRequest_TESTFORCEENABLE 5
+/// Send a ZLP in Test Mode.
+#define USBFeatureRequest_TESTSENDZLP 6
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char USBFeatureRequest_GetFeatureSelector(
+ const USBGenericRequest *request);
+
+
+extern unsigned char USBFeatureRequest_GetTestSelector(
+ const USBGenericRequest *request);
+
+#endif //#ifndef USBFEATUREREQUEST_H
+
diff --git a/usb/common/core/USBGenericDescriptor.c b/usb/common/core/USBGenericDescriptor.c new file mode 100644 index 0000000..99ed6f9 --- /dev/null +++ b/usb/common/core/USBGenericDescriptor.c @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBGenericDescriptor implementation
+
+ About: Purpose
+ Implementation of the USBGenericDescriptor class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGenericDescriptor.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the length of a descriptor.
+/// \param descriptor Pointer to a USBGenericDescriptor instance.
+/// \return Length of descriptor in bytes.
+//------------------------------------------------------------------------------
+unsigned int USBGenericDescriptor_GetLength(
+ const USBGenericDescriptor *descriptor)
+{
+ return descriptor->bLength;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the type of a descriptor.
+/// \param descriptor Pointer to a USBGenericDescriptor instance.
+/// \return Type of descriptor.
+//------------------------------------------------------------------------------
+unsigned char USBGenericDescriptor_GetType(
+ const USBGenericDescriptor *descriptor)
+{
+ return descriptor->bDescriptorType;
+}
+
+//------------------------------------------------------------------------------
+/// Returns a pointer to the descriptor right after the given one, when
+/// parsing a Configuration descriptor.
+/// \param descriptor - Pointer to a USBGenericDescriptor instance.
+/// \return Pointer to the next descriptor.
+//------------------------------------------------------------------------------
+USBGenericDescriptor *USBGenericDescriptor_GetNextDescriptor(
+ const USBGenericDescriptor *descriptor)
+{
+ return (USBGenericDescriptor *)
+ (((char *) descriptor) + USBGenericDescriptor_GetLength(descriptor));
+}
diff --git a/usb/common/core/USBGenericDescriptor.h b/usb/common/core/USBGenericDescriptor.h new file mode 100644 index 0000000..b1237ae --- /dev/null +++ b/usb/common/core/USBGenericDescriptor.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definition of a generic USB descriptor class.
+///
+/// !!!Usage
+///
+/// -# Declare or access USB descriptors by USBGenericDescriptor instance.
+/// -# To get usful information (field values) from the USB descriptors, use
+/// - USBGenericDescriptor_GetLength
+/// - USBGenericDescriptor_GetType
+/// -# To scan the descriptors, use
+/// - USBGenericDescriptor_GetNextDescriptor
+//------------------------------------------------------------------------------
+
+#ifndef USBGENERICDESCRIPTOR_H
+#define USBGENERICDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Descriptor types"
+///
+/// This page lists the codes of the usb descriptor types
+///
+/// !Types
+/// - USBGenericDescriptor_DEVICE
+/// - USBGenericDescriptor_CONFIGURATION
+/// - USBGenericDescriptor_STRING
+/// - USBGenericDescriptor_INTERFACE
+/// - USBGenericDescriptor_ENDPOINT
+/// - USBGenericDescriptor_DEVICEQUALIFIER
+/// - USBGenericDescriptor_OTHERSPEEDCONFIGURATION
+/// - USBGenericDescriptor_INTERFACEPOWER
+/// - USBGenericDescriptor_OTG
+/// - USBGenericDescriptor_DEBUG
+/// - USBGenericDescriptor_INTERFACEASSOCIATION
+
+/// Device descriptor type.
+#define USBGenericDescriptor_DEVICE 1
+/// Configuration descriptor type.
+#define USBGenericDescriptor_CONFIGURATION 2
+/// String descriptor type.
+#define USBGenericDescriptor_STRING 3
+/// Interface descriptor type.
+#define USBGenericDescriptor_INTERFACE 4
+/// Endpoint descriptor type.
+#define USBGenericDescriptor_ENDPOINT 5
+/// Device qualifier descriptor type.
+#define USBGenericDescriptor_DEVICEQUALIFIER 6
+/// Other speed configuration descriptor type.
+#define USBGenericDescriptor_OTHERSPEEDCONFIGURATION 7
+/// Interface power descriptor type.
+#define USBGenericDescriptor_INTERFACEPOWER 8
+/// On-The-Go descriptor type.
+#define USBGenericDescriptor_OTG 9
+/// Debug descriptor type.
+#define USBGenericDescriptor_DEBUG 10
+/// Interface association descriptor type.
+#define USBGenericDescriptor_INTERFACEASSOCIATION 11
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+/// Holds the few fields shared by all USB descriptors.
+typedef struct {
+
+ /// Length of the descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type.
+ unsigned char bDescriptorType;
+
+} __attribute__ ((packed)) USBGenericDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned int USBGenericDescriptor_GetLength(
+ const USBGenericDescriptor *descriptor);
+
+extern unsigned char USBGenericDescriptor_GetType(
+ const USBGenericDescriptor *descriptor);
+
+extern USBGenericDescriptor *USBGenericDescriptor_GetNextDescriptor(
+ const USBGenericDescriptor *descriptor);
+
+#endif //#ifndef USBGENERICDESCRIPTOR_H
+
diff --git a/usb/common/core/USBGenericRequest.c b/usb/common/core/USBGenericRequest.c new file mode 100644 index 0000000..a3bbbfd --- /dev/null +++ b/usb/common/core/USBGenericRequest.c @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBGenericRequest implementation
+
+ About: Purpose
+ Implementation of the USBGenericRequest class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGenericRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// Returns the type of the given request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return "USB Request Types"
+//------------------------------------------------------------------------------
+extern unsigned char USBGenericRequest_GetType(const USBGenericRequest *request)
+{
+ return ((request->bmRequestType >> 5) & 0x3);
+}
+
+//------------------------------------------------------------------------------
+/// Returns the request code of the given request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Request code.
+/// \sa "USB Request Codes"
+//------------------------------------------------------------------------------
+unsigned char USBGenericRequest_GetRequest(const USBGenericRequest *request)
+{
+ return request->bRequest;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the wValue field of the given request.
+/// \param request - Pointer to a USBGenericRequest instance.
+/// \return Request value.
+//------------------------------------------------------------------------------
+unsigned short USBGenericRequest_GetValue(const USBGenericRequest *request)
+{
+ return request->wValue;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the wIndex field of the given request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Request index;
+//------------------------------------------------------------------------------
+unsigned short USBGenericRequest_GetIndex(const USBGenericRequest *request)
+{
+ return request->wIndex;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the expected length of the data phase following a request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Length of data phase.
+//------------------------------------------------------------------------------
+unsigned short USBGenericRequest_GetLength(const USBGenericRequest *request)
+{
+ return request->wLength;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the endpoint number targetted by a given request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Endpoint number.
+//------------------------------------------------------------------------------
+unsigned char USBGenericRequest_GetEndpointNumber(
+ const USBGenericRequest *request)
+{
+ return USBGenericRequest_GetIndex(request) & 0xF;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the intended recipient of a given request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Request recipient.
+/// \sa "USB Request Recipients"
+//------------------------------------------------------------------------------
+unsigned char USBGenericRequest_GetRecipient(const USBGenericRequest *request)
+{
+ // Recipient is in bits [0..4] of the bmRequestType field
+ return request->bmRequestType & 0xF;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the direction of the data transfer following the given request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Transfer direction.
+/// \sa "USB Request Directions"
+//------------------------------------------------------------------------------
+unsigned char USBGenericRequest_GetDirection(const USBGenericRequest *request)
+{
+ // Transfer direction is located in bit D7 of the bmRequestType field
+ if ((request->bmRequestType & 0x80) != 0) {
+
+ return USBGenericRequest_IN;
+ }
+ else {
+
+ return USBGenericRequest_OUT;
+ }
+}
+
diff --git a/usb/common/core/USBGenericRequest.h b/usb/common/core/USBGenericRequest.h new file mode 100644 index 0000000..77f8ca5 --- /dev/null +++ b/usb/common/core/USBGenericRequest.h @@ -0,0 +1,244 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of the USBGenericRequest class and its methods.
+
+ !!!Usage
+
+ -# Declare or access USB requests by USBGenericRequest instance.
+ -# To get usful information (field values) from the USB requests, use
+ - USBGenericRequest_GetType
+ - USBGenericRequest_GetRequest
+ - USBGenericRequest_GetValue
+ - USBGenericRequest_GetIndex
+ - USBGenericRequest_GetLength
+ - USBGenericRequest_GetEndpointNumber
+ - USBGenericRequest_GetRecipient
+ - USBGenericRequest_GetDirection
+*/
+
+#ifndef USBGENERICREQUEST_H
+#define USBGENERICREQUEST_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Generic Request definitions"
+///
+/// This page lists the codes of USB generic request.
+///
+/// - USB Request codes
+/// - USBGenericRequest_GETSTATUS
+/// - USBGenericRequest_CLEARFEATURE
+/// - USBGenericRequest_SETFEATURE
+/// - USBGenericRequest_SETADDRESS
+/// - USBGenericRequest_GETDESCRIPTOR
+/// - USBGenericRequest_SETDESCRIPTOR
+/// - USBGenericRequest_GETCONFIGURATION
+/// - USBGenericRequest_SETCONFIGURATION
+/// - USBGenericRequest_GETINTERFACE
+/// - USBGenericRequest_SETINTERFACE
+/// - USBGenericRequest_SYNCHFRAME
+///
+/// - USB Request Recipients
+/// - USBGenericRequest_DEVICE
+/// - USBGenericRequest_INTERFACE
+/// - USBGenericRequest_ENDPOINT
+/// - USBGenericRequest_OTHER
+///
+/// - USB Request Types
+/// - USBGenericRequest_STANDARD
+/// - USBGenericRequest_CLASS
+/// - USBGenericRequest_VENDOR
+///
+/// - USB Request Directions
+/// - USBGenericRequest_IN
+/// - USBGenericRequest_OUT
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Request codes"
+///
+/// This page lists the USB generic request codes.
+///
+/// !Codes
+/// - USBGenericRequest_GETSTATUS
+/// - USBGenericRequest_CLEARFEATURE
+/// - USBGenericRequest_SETFEATURE
+/// - USBGenericRequest_SETADDRESS
+/// - USBGenericRequest_GETDESCRIPTOR
+/// - USBGenericRequest_SETDESCRIPTOR
+/// - USBGenericRequest_GETCONFIGURATION
+/// - USBGenericRequest_SETCONFIGURATION
+/// - USBGenericRequest_GETINTERFACE
+/// - USBGenericRequest_SETINTERFACE
+/// - USBGenericRequest_SYNCHFRAME
+
+/// GET_STATUS request code.
+#define USBGenericRequest_GETSTATUS 0
+/// CLEAR_FEATURE request code.
+#define USBGenericRequest_CLEARFEATURE 1
+/// SET_FEATURE request code.
+#define USBGenericRequest_SETFEATURE 3
+/// SET_ADDRESS request code.
+#define USBGenericRequest_SETADDRESS 5
+/// GET_DESCRIPTOR request code.
+#define USBGenericRequest_GETDESCRIPTOR 6
+/// SET_DESCRIPTOR request code.
+#define USBGenericRequest_SETDESCRIPTOR 7
+/// GET_CONFIGURATION request code.
+#define USBGenericRequest_GETCONFIGURATION 8
+/// SET_CONFIGURATION request code.
+#define USBGenericRequest_SETCONFIGURATION 9
+/// GET_INTERFACE request code.
+#define USBGenericRequest_GETINTERFACE 10
+/// SET_INTERFACE request code.
+#define USBGenericRequest_SETINTERFACE 11
+/// SYNCH_FRAME request code.
+#define USBGenericRequest_SYNCHFRAME 12
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Request Recipients"
+///
+/// This page lists codes of USB request recipients.
+///
+/// !Recipients
+/// - USBGenericRequest_DEVICE
+/// - USBGenericRequest_INTERFACE
+/// - USBGenericRequest_ENDPOINT
+/// - USBGenericRequest_OTHER
+
+/// Recipient is the whole device.
+#define USBGenericRequest_DEVICE 0
+/// Recipient is an interface.
+#define USBGenericRequest_INTERFACE 1
+/// Recipient is an endpoint.
+#define USBGenericRequest_ENDPOINT 2
+/// Recipient is another entity.
+#define USBGenericRequest_OTHER 3
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Request Types"
+///
+/// This page lists codes of USB request types.
+///
+/// !Types
+/// - USBGenericRequest_STANDARD
+/// - USBGenericRequest_CLASS
+/// - USBGenericRequest_VENDOR
+
+/// Request is standard.
+#define USBGenericRequest_STANDARD 0
+/// Request is class-specific.
+#define USBGenericRequest_CLASS 1
+/// Request is vendor-specific.
+#define USBGenericRequest_VENDOR 2
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB Request Directions"
+///
+/// This page lists codes of USB request directions.
+///
+/// !Directions
+/// - USBGenericRequest_IN
+/// - USBGenericRequest_OUT
+
+/// Transfer occurs from device to the host.
+#define USBGenericRequest_OUT 0
+/// Transfer occurs from the host to the device.
+#define USBGenericRequest_IN 1
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Generic USB SETUP request sent over Control endpoints.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Type of request
+ /// \sa "USB Request Recipients"
+ /// \sa "USB Request Types"
+ /// \sa "USB Request Directions"
+ unsigned char bmRequestType:8;
+ /// Request code
+ /// \sa "USB Request Codes"
+ unsigned char bRequest:8;
+ /// Request-specific value parameter.
+ unsigned short wValue:16;
+ /// Request-specific index parameter.
+ unsigned short wIndex:16;
+ /// Expected length (in bytes) of the data phase.
+ unsigned short wLength:16;
+
+} USBGenericRequest;
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char USBGenericRequest_GetType(
+ const USBGenericRequest *request);
+
+
+extern unsigned char USBGenericRequest_GetRequest(
+ const USBGenericRequest *request);
+
+extern unsigned short USBGenericRequest_GetValue(
+ const USBGenericRequest *request);
+
+extern unsigned short USBGenericRequest_GetIndex(
+ const USBGenericRequest *request);
+
+extern unsigned short USBGenericRequest_GetLength(
+ const USBGenericRequest *request);
+
+extern unsigned char USBGenericRequest_GetEndpointNumber(
+ const USBGenericRequest *request);
+
+extern unsigned char USBGenericRequest_GetRecipient(
+ const USBGenericRequest *request);
+
+extern unsigned char USBGenericRequest_GetDirection(
+ const USBGenericRequest *request);
+
+#endif //#ifndef USBGENERICREQUEST_H
+
diff --git a/usb/common/core/USBGetDescriptorRequest.c b/usb/common/core/USBGetDescriptorRequest.c new file mode 100644 index 0000000..2937929 --- /dev/null +++ b/usb/common/core/USBGetDescriptorRequest.c @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBGetDescriptorRequest implementation
+
+ About: Purpose
+ Implementation of the USBGetDescriptorRequest class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGetDescriptorRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the type of the descriptor requested by the host given the
+/// corresponding GET_DESCRIPTOR request.
+/// \param request Pointer to a USBGenericDescriptor instance.
+/// \return Type of the requested descriptor.
+//------------------------------------------------------------------------------
+unsigned char USBGetDescriptorRequest_GetDescriptorType(
+ const USBGenericRequest *request)
+{
+ // Requested descriptor type is in the high-byte of the wValue field
+ return (USBGenericRequest_GetValue(request) >> 8) & 0xFF;
+}
+
+//------------------------------------------------------------------------------
+/// Returns the index of the requested descriptor, given the corresponding
+/// GET_DESCRIPTOR request.
+/// \param request Pointer to a USBGenericDescriptor instance.
+/// \return Index of the requested descriptor.
+//------------------------------------------------------------------------------
+unsigned char USBGetDescriptorRequest_GetDescriptorIndex(
+ const USBGenericRequest *request)
+{
+ // Requested descriptor index if in the low byte of the wValue field
+ return USBGenericRequest_GetValue(request) & 0xFF;
+}
+
diff --git a/usb/common/core/USBGetDescriptorRequest.h b/usb/common/core/USBGetDescriptorRequest.h new file mode 100644 index 0000000..43f6afd --- /dev/null +++ b/usb/common/core/USBGetDescriptorRequest.h @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of the USBGetDescriptorRequest class.
+
+ !!!Usage
+
+ - After a GET_DESCRIPTOR request has been received, retrive the useful
+ values with following functions:
+ - USBGetDescriptorRequest_GetDescriptorType: the descriptor type
+ - USBGetDescriptorRequest_GetDescriptorIndex: the index of the requested
+ descriptor
+
+*/
+
+#ifndef USBGETDESCRIPTORREQUEST_H
+#define USBGETDESCRIPTORREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGenericRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char USBGetDescriptorRequest_GetDescriptorType(
+ const USBGenericRequest *request);
+
+extern unsigned char USBGetDescriptorRequest_GetDescriptorIndex(
+ const USBGenericRequest *request);
+
+#endif //#ifndef USBGETDESCRIPTORREQUEST_H
+
diff --git a/usb/common/core/USBInterfaceAssociationDescriptor.h b/usb/common/core/USBInterfaceAssociationDescriptor.h new file mode 100644 index 0000000..5f3dd21 --- /dev/null +++ b/usb/common/core/USBInterfaceAssociationDescriptor.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \page USBInterfaceAssociateDescriptor
+ * !!!Purpose
+ *
+ * Class for manipulating USB IAD descriptors.
+ *
+ * !!!Usage
+ *
+ * -# Test
+ */
+
+#ifndef USBDIADDESCRIPTOR_H
+#define USBDIADDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+/*
+ Type: USBDeviceDescriptor
+ USB standard device descriptor structure.
+
+ Variables:
+ bLength - Size of this descriptor in bytes.
+ bDescriptorType - Descriptor type (<USBGenericDescriptor_IAD>).
+ bFirstInterface - Interface number of the first interface that is
+ associated with this function.
+ bInterfaceCount - Number of contiguous interfaces that are
+ associated with this function.
+ bFunctionClass - Class code (assigned by USB-IF).
+ bFunctionSubClass - Subclass code (assigned by USB-IF).
+ bFunctionProtocol - Protocol code (assigned by USB-IF)
+ iFunction - Index of string descriptor describing this function.
+*/
+typedef struct {
+
+ unsigned char bLength;
+ unsigned char bDescriptorType;
+ unsigned char bFirstInterface;
+ unsigned char bInterfaceCount;
+ unsigned char bFunctionClass;
+ unsigned char bFunctionSubClass;
+ unsigned char bFunctionProtocol;
+ unsigned char iFunction;
+} __attribute__ ((packed)) USBInterfaceAssociationDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef USBDIADDESCRIPTOR_H
+
diff --git a/usb/common/core/USBInterfaceDescriptor.h b/usb/common/core/USBInterfaceDescriptor.h new file mode 100644 index 0000000..63910bf --- /dev/null +++ b/usb/common/core/USBInterfaceDescriptor.h @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for manipulating USB interface descriptors.
+
+ !!!Usage
+
+ - Declare USBInterfaceDescriptor instance as a part of the configuration
+ descriptors of a USB device.
+
+*/
+
+#ifndef USBINTERFACEDESCRIPTOR_H
+#define USBINTERFACEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// USB standard interface descriptor structure.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of the descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (USBGenericDescriptor_INTERFACE).
+ unsigned char bDescriptorType;
+ /// Number of the interface in its configuration.
+ unsigned char bInterfaceNumber;
+ /// Value to select this alternate interface setting.
+ unsigned char bAlternateSetting;
+ /// Number of endpoints used by the inteface (excluding endpoint 0).
+ unsigned char bNumEndpoints;
+ /// Interface class code.
+ unsigned char bInterfaceClass;
+ /// Interface subclass code.
+ unsigned char bInterfaceSubClass;
+ /// Interface protocol code.
+ unsigned char bInterfaceProtocol;
+ /// Index of the interface string descriptor.
+ unsigned char iInterface;
+
+} __attribute__ ((packed)) USBInterfaceDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef USBINTERFACEDESCRIPTOR_H
+
diff --git a/usb/common/core/USBInterfaceRequest.c b/usb/common/core/USBInterfaceRequest.c new file mode 100644 index 0000000..61bf6ed --- /dev/null +++ b/usb/common/core/USBInterfaceRequest.c @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBInterfaceRequest
+
+ About: Purpose
+ Implementation of USBInterfaceRequest class methods.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBInterfaceRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Indicates which interface is targetted by a GET_INTERFACE or
+/// SET_INTERFACE request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Interface number.
+//------------------------------------------------------------------------------
+unsigned char USBInterfaceRequest_GetInterface(const USBGenericRequest *request)
+{
+ return (USBGenericRequest_GetIndex(request) & 0xFF);
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the new alternate setting that the interface targetted by a
+/// SET_INTERFACE request should use.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return New active setting for the interface.
+//------------------------------------------------------------------------------
+unsigned char USBInterfaceRequest_GetAlternateSetting(
+ const USBGenericRequest *request)
+{
+ return (USBGenericRequest_GetValue(request) & 0xFF);
+}
+
diff --git a/usb/common/core/USBInterfaceRequest.h b/usb/common/core/USBInterfaceRequest.h new file mode 100644 index 0000000..bd4cddd --- /dev/null +++ b/usb/common/core/USBInterfaceRequest.h @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions for manipulating SET_INTERFACE and GET_INTERFACE request.
+
+ !!!Usage
+
+ -# After a SET_INTERFACE request has been received, retrieve the
+ target interface using USBInterfaceRequest_GetInterface and its
+ new alternate setting with USBInterfaceRequest_GetAlternateSetting.
+ -# After a GET_INTERFACE request has been received, retrieve the target
+ interface using USBInterfaceRequest_GetInterface.
+
+*/
+
+#ifndef USBINTERFACEREQUEST_H
+#define USBINTERFACEREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGenericRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char USBInterfaceRequest_GetInterface(
+ const USBGenericRequest *request);
+
+
+extern unsigned char USBInterfaceRequest_GetAlternateSetting(
+ const USBGenericRequest *request);
+
+#endif //#ifndef USBINTERFACEREQUEST_H
+
diff --git a/usb/common/core/USBIrqHandler.c b/usb/common/core/USBIrqHandler.c new file mode 100644 index 0000000..386ebd2 --- /dev/null +++ b/usb/common/core/USBIrqHandler.c @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBIrqHandler implementation
+
+ About: Purpose
+ Implementation of the USB Interrupt Handler.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <board.h>
+#include <usb/device/core/USBD.h>
+
+#include <exceptions.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// Call Arbitrer, device and host interrupt handler.
+/// The IRQ functions are defined with weak and can be surcharged if needed.
+//------------------------------------------------------------------------------
+void USB_IrqHandler( void )
+{
+ // Most arbitrer interrupt
+ usb_general_interrupt();
+ // Device interrupt
+ USBD_IrqHandler();
+ // Host interrupt
+ usb_pipe_interrupt();
+}
+
+
diff --git a/usb/common/core/USBIrqHandler.h b/usb/common/core/USBIrqHandler.h new file mode 100644 index 0000000..77d2679 --- /dev/null +++ b/usb/common/core/USBIrqHandler.h @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Implementation of the USB Interrupt Handler.
+
+ !!!Usage
+
+ -# The IRQ functions are defined with weak and can be surcharged if needed.
+
+*/
+
+#ifndef USBIRQHANDLER_H
+#define USBIRQHANDLER_H
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+extern void USB_IrqHandler( void );
+
+#endif //#ifndef USBIRQHANDLER_H
+
diff --git a/usb/common/core/USBSetAddressRequest.c b/usb/common/core/USBSetAddressRequest.c new file mode 100644 index 0000000..0e82a7f --- /dev/null +++ b/usb/common/core/USBSetAddressRequest.c @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBSetAddressRequest implementation
+
+ About: Purpose
+ Implementation of the USBSetAddressRequest class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBSetAddressRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// Returns the address that the device must take in response to a
+/// SET_ADDRESS request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return New device address.
+//------------------------------------------------------------------------------
+unsigned char USBSetAddressRequest_GetAddress(const USBGenericRequest *request)
+{
+ return USBGenericRequest_GetValue(request) & 0x7F;
+}
+
diff --git a/usb/common/core/USBSetAddressRequest.h b/usb/common/core/USBSetAddressRequest.h new file mode 100644 index 0000000..78034c3 --- /dev/null +++ b/usb/common/core/USBSetAddressRequest.h @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for manipulating SET_ADDRESS USB requests.
+
+ !!!Usage
+
+ - After a SET_ADDRESS request has been received, retrive the new address
+ value with USBSetAddressRequest_GetAddress.
+*/
+
+#ifndef USBSETADDRESSREQUEST_H
+#define USBSETADDRESSREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGenericRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char USBSetAddressRequest_GetAddress(
+ const USBGenericRequest *request);
+
+#endif //#ifndef USBSETADDRESSREQUEST_H
+
diff --git a/usb/common/core/USBSetConfigurationRequest.c b/usb/common/core/USBSetConfigurationRequest.c new file mode 100644 index 0000000..3aa747d --- /dev/null +++ b/usb/common/core/USBSetConfigurationRequest.c @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: USBSetConfigurationRequest implementation
+
+ About: Purpose
+ Implementation of the USBSetConfigurationRequest class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBSetConfigurationRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the number of the configuration that should be set in response
+/// to the given SET_CONFIGURATION request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Number of the requested configuration.
+//------------------------------------------------------------------------------
+unsigned char USBSetConfigurationRequest_GetConfiguration(
+ const USBGenericRequest *request)
+{
+ return USBGenericRequest_GetValue(request);
+}
+
diff --git a/usb/common/core/USBSetConfigurationRequest.h b/usb/common/core/USBSetConfigurationRequest.h new file mode 100644 index 0000000..aa1fa17 --- /dev/null +++ b/usb/common/core/USBSetConfigurationRequest.h @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for the Set Configuration request.
+
+ !!!Usage
+
+ - After a SET_CONFIGURATION request has been received, retrive the new
+ configuration value with USBSetConfigurationRequest_GetConfiguration.
+
+*/
+
+#ifndef USBSETCONFIGURATIONREQUEST_H
+#define USBSETCONFIGURATIONREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBGenericRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char USBSetConfigurationRequest_GetConfiguration(
+ const USBGenericRequest *request);
+
+#endif //#ifndef USBSETCONFIGURATIONREQUEST_H
+
diff --git a/usb/common/core/USBStringDescriptor.h b/usb/common/core/USBStringDescriptor.h new file mode 100644 index 0000000..bcf4b83 --- /dev/null +++ b/usb/common/core/USBStringDescriptor.h @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Definition of a class for manipulating String descriptors.
+//------------------------------------------------------------------------------
+
+#ifndef USBSTRINGDESCRIPTOR_H
+#define USBSTRINGDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB String Descriptor definitions"
+///
+/// This page lists the codes and macros for USB string descriptor definition.
+///
+/// !Language IDs
+/// - USBStringDescriptor_ENGLISH_US
+///
+/// !String Descriptor Length
+/// - USBStringDescriptor_LENGTH
+///
+/// !ASCII to UNICODE convertion
+/// - USBStringDescriptor_UNICODE
+
+/// Language ID for US english.
+#define USBStringDescriptor_ENGLISH_US 0x09, 0x04
+
+/// Calculates the length of a string descriptor given the number of ascii
+/// characters/language IDs in it.
+/// \param length The ascii format string length.
+/// \return The actual data length in bytes.
+#define USBStringDescriptor_LENGTH(length) ((length) * 2 + 2)
+/// Converts an ascii character to its unicode representation.
+/// \param ascii The ASCII character to convert
+/// \return A 2-byte-array for the UNICODE based on given ASCII
+#define USBStringDescriptor_UNICODE(ascii) (ascii), 0
+//------------------------------------------------------------------------------
+
+#endif //#ifndef USBSTRINGDESCRIPTOR_H
+
diff --git a/usb/common/core/core.dir b/usb/common/core/core.dir new file mode 100644 index 0000000..7ac93c3 --- /dev/null +++ b/usb/common/core/core.dir @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !!!Purpose
+///
+/// This directory contains definitions, structures and functions described by
+/// USB specification. They can be divided into two groups:
+/// - USB descriptors, prefixed with USB and suffixed with Descriptor.
+/// - USB requests, prefixed with USB and suffixed with Request.
+//------------------------------------------------------------------------------
+
+/**
+ \page "Standard USB Structures"
+
+ !!!Standard USB Structures
+
+ The following standard structures is implemented in the USB framework:
+ - Setup request data: USBGenericRequest
+ - Descriptor header: USBGenericDescriptor
+ - Device descriptor: USBDeviceDescriptor
+ - Configuration descriptor: USBConfigurationDescriptor
+ - Interface descriptor: USBInterfaceDescriptor
+ - %Endpoint descriptor: USBEndpointDescriptor
+ - Device_Qualifier descriptor: USBDeviceQualifierDescriptor
+*/
diff --git a/usb/common/hid/HIDButton.h b/usb/common/hid/HIDButton.h new file mode 100644 index 0000000..ea2557a --- /dev/null +++ b/usb/common/hid/HIDButton.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDButton
+
+ About: Purpose
+ Definitions of constants and methods for the HID Button usage page.
+
+ About: Usage
+ 1 - Use the constants declared in this file when instanciating a
+ Report descriptor instance.
+ 2 - When implementing the functionality of an HID Mouse, use the
+ key codes defined here to indicate keys that are being pressed and
+ released.
+*/
+
+#ifndef _HIDBUTTON_H
+#define _HIDBUTTON_H
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+/// Identifier for the HID button usage page
+#define HIDButton_PAGEID 0x09
+
+
+#endif
diff --git a/usb/common/hid/HIDDescriptor.h b/usb/common/hid/HIDDescriptor.h new file mode 100644 index 0000000..ae00102 --- /dev/null +++ b/usb/common/hid/HIDDescriptor.h @@ -0,0 +1,93 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Methods and definitions for manipulating a HID descriptor.
+*/
+
+#ifndef HIDDESCRIPTOR_H
+#define HIDDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Release Numbers"
+/// ...
+///
+/// !Numbers
+/// - HIDDescriptor_HID1_11
+
+/// Identifies version 1.11 of the HID specification.
+#define HIDDescriptor_HID1_11 0x0111
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Identifies the length of type of subordinate descriptors of a HID
+/// device. This particular type only supports one subordinate descriptor.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Size of descriptor in bytes.
+ unsigned char bLength;
+ /// Descriptor type (HIDGenericDescriptor_HID).
+ unsigned char bDescriptorType;
+ /// HID class specification release number in BCD format.
+ unsigned short bcdHID;
+ /// Country code of the device if it is localized.
+ unsigned char bCountryCode;
+ /// Number of subordinate descriptors.
+ unsigned char bNumDescriptors;
+ /// Type of the first subordinate descriptor.
+ unsigned char bDescriptorType0;
+ /// Size in bytes of the first subordinate descriptor.
+ unsigned short wDescriptorLength0;
+
+} __attribute__ ((packed)) HIDDescriptor; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef HIDDESCRIPTOR_H
+
diff --git a/usb/common/hid/HIDDeviceDescriptor.h b/usb/common/hid/HIDDeviceDescriptor.h new file mode 100644 index 0000000..267c73e --- /dev/null +++ b/usb/common/hid/HIDDeviceDescriptor.h @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions used for declaring the device descriptor of a HID device.
+
+ !!!Usage
+
+ Use this constants when defining an instance of USBDeviceDescriptor for
+ an HID device.
+*/
+
+#ifndef HIDDEVICEDESCRIPTOR_H
+#define HIDDEVICEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Device Descriptor Codes"
+/// This page lists HID device class, subclass and protocol codes.
+///
+/// !Codes
+/// - HIDDeviceDescriptor_CLASS
+/// - HIDDeviceDescriptor_SUBCLASS
+/// - HIDDeviceDescriptor_PROTOCOL
+
+/// Class code for a HID device.
+#define HIDDeviceDescriptor_CLASS 0
+/// Subclass code for a HID device.
+#define HIDDeviceDescriptor_SUBCLASS 0
+/// Protocol code for a HID device.
+#define HIDDeviceDescriptor_PROTOCOL 0
+//------------------------------------------------------------------------------
+
+#endif //#ifndef HIDDEVICEDESCRIPTOR_H
+
diff --git a/usb/common/hid/HIDGenericDescriptor.h b/usb/common/hid/HIDGenericDescriptor.h new file mode 100644 index 0000000..2324d53 --- /dev/null +++ b/usb/common/hid/HIDGenericDescriptor.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions for using HID-specific descriptors.
+*/
+
+#ifndef HIDGENERICDESCRIPTOR_H
+#define HIDGENERICDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Descriptors Types"
+/// ...
+///
+/// !Types
+/// - HIDGenericDescriptor_HID
+/// - HIDGenericDescriptor_REPORT
+/// - HIDGenericDescriptor_PHYSICAL
+
+/// HID descriptor type.
+#define HIDGenericDescriptor_HID 0x21
+/// Report descriptor type.
+#define HIDGenericDescriptor_REPORT 0x22
+/// Physical descriptor type.
+#define HIDGenericDescriptor_PHYSICAL 0x23
+//------------------------------------------------------------------------------
+
+#endif //#ifndef HIDGENERICDESCRIPTOR_H
+
diff --git a/usb/common/hid/HIDGenericDesktop.h b/usb/common/hid/HIDGenericDesktop.h new file mode 100644 index 0000000..ac1165c --- /dev/null +++ b/usb/common/hid/HIDGenericDesktop.h @@ -0,0 +1,98 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Constants for using the HID generic desktop usage page.
+
+ !!!Usage
+
+ Use these constants when declaring a Report descriptor which references
+ the generic desktop page.
+*/
+
+#ifndef HIDGENERICDESKTOP_H
+#define HIDGENERICDESKTOP_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID GenericDesktop Page ID"
+/// ...
+///
+/// !ID
+/// - HIDGenericDesktop_PAGEID
+
+/// ID for the HID generic desktop usage page.
+#define HIDGenericDesktop_PAGEID 0x01
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID GenericDesktop Usages"
+/// ...
+///
+/// !Usages
+/// - HIDGenericDesktop_POINTER
+/// - HIDGenericDesktop_MOUSE
+/// - HIDGenericDesktop_JOYSTICK
+/// - HIDGenericDesktop_GAMEPAD
+/// - HIDGenericDesktop_KEYBOARD
+/// - HIDGenericDesktop_KEYPAD
+/// - HIDGenericDesktop_MULTIAXIS
+/// - HIDGenericDesktop_X
+/// - HIDGenericDesktop_Y
+
+/// Pointer usage ID.
+#define HIDGenericDesktop_POINTER 0x01
+/// Mouse usage ID.
+#define HIDGenericDesktop_MOUSE 0x02
+/// Joystick usage ID.
+#define HIDGenericDesktop_JOYSTICK 0x04
+/// Gamepad usage ID.
+#define HIDGenericDesktop_GAMEPAD 0x05
+/// Keyboard usage ID.
+#define HIDGenericDesktop_KEYBOARD 0x06
+/// Keypad usage ID.
+#define HIDGenericDesktop_KEYPAD 0x07
+/// Multi-axis controller usage ID.
+#define HIDGenericDesktop_MULTIAXIS 0x08
+
+/// Axis Usage X direction ID.
+#define HIDGenericDesktop_X 0x30
+/// Axis Usage Y direction ID.
+#define HIDGenericDesktop_Y 0x31
+//------------------------------------------------------------------------------
+
+#endif //#ifndef HIDGENERICDESKTOP_H
+
diff --git a/usb/common/hid/HIDGenericRequest.h b/usb/common/hid/HIDGenericRequest.h new file mode 100644 index 0000000..356f498 --- /dev/null +++ b/usb/common/hid/HIDGenericRequest.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDGenericRequest
+
+ About: Purpose
+ Definition of constants for using HID-specific requests.
+
+ About: Usage
+ When constructing or receiving an HID SETUP request, use the request
+ codes provided by this header file.
+*/
+
+#ifndef HIDGENERICREQUEST_H
+#define HIDGENERICREQUEST_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Request Codes"
+/// ...
+///
+/// !Codes
+/// - HIDGenericRequest_GETREPORT
+/// - HIDGenericRequest_GETIDLE
+/// - HIDGenericRequest_GETPROTOCOL
+/// - HIDGenericRequest_SETREPORT
+/// - HIDGenericRequest_SETIDLE
+/// - HIDGenericRequest_SETPROTOCOL
+
+/// GetReport request code.
+#define HIDGenericRequest_GETREPORT 0x01
+/// GetIdle request code.
+#define HIDGenericRequest_GETIDLE 0x02
+/// GetProtocol request code.
+#define HIDGenericRequest_GETPROTOCOL 0x03
+/// SetReport request code.
+#define HIDGenericRequest_SETREPORT 0x09
+/// SetIdle request code.
+#define HIDGenericRequest_SETIDLE 0x0A
+/// SetProtocol request code.
+#define HIDGenericRequest_SETPROTOCOL 0x0B
+//------------------------------------------------------------------------------
+
+#endif //#ifndef HIDGENERICREQUEST_H
+
diff --git a/usb/common/hid/HIDIdleRequest.c b/usb/common/hid/HIDIdleRequest.c new file mode 100644 index 0000000..640f2d5 --- /dev/null +++ b/usb/common/hid/HIDIdleRequest.c @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDIdleRequest implementation
+
+ About: Purpose
+ Implementation of the HIDIdleRequest methods.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDIdleRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Retrieves the Idle rate (in milliseconds) indicated by a SET_IDLE
+/// request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return New idle rate for the report.
+//------------------------------------------------------------------------------
+unsigned char HIDIdleRequest_GetIdleRate(const USBGenericRequest *request)
+{
+ return ((USBGenericRequest_GetValue(request) >> 8) & 0xFF);
+}
diff --git a/usb/common/hid/HIDIdleRequest.h b/usb/common/hid/HIDIdleRequest.h new file mode 100644 index 0000000..1f9a361 --- /dev/null +++ b/usb/common/hid/HIDIdleRequest.h @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Methods and constants for manipulating HID-specific GET_IDLE and SET_IDLE
+ requests.
+
+ !!!Usage
+
+ -# Retrieve the idle rate indicated by a GET_IDLE or SET_IDLE request
+ with HIDIdleRequest_GetIdleRate.
+*/
+
+#ifndef HIDIDLEREQUEST_H
+#define HIDIDLEREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Infinite idle rate.
+#define HIDIdleRequest_INFINITE 0
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char HIDIdleRequest_GetIdleRate(
+ const USBGenericRequest *request);
+
+#endif //#ifndef HIDIDLEREQUEST_H
+
diff --git a/usb/common/hid/HIDInterfaceDescriptor.h b/usb/common/hid/HIDInterfaceDescriptor.h new file mode 100644 index 0000000..4ef1bc7 --- /dev/null +++ b/usb/common/hid/HIDInterfaceDescriptor.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Constants used when declaring an HID interface.
+
+ !!!Usage
+
+ Use the constants defined here when declaring a USBInterfaceDescriptor
+ instance for a HID interface.
+*/
+
+#ifndef HIDINTERFACEDESCRIPTOR_H
+#define HIDINTERFACEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Interface Descriptor Codes"
+/// This page lists HID Interface class, subclass and protocol codes.
+///
+/// !Codes
+/// - HIDInterfaceDescriptor_CLASS
+/// - HIDInterfaceDescriptor_SUBCLASS_NONE
+/// - HIDInterfaceDescriptor_SUBCLASS_BOOT
+/// - HIDInterfaceDescriptor_PROTOCOL_NONE
+/// - HIDInterfaceDescriptor_PROTOCOL_KEYBOARD
+/// - HIDInterfaceDescriptor_PROTOCOL_MOUSE
+
+/// HID interface class code.
+#define HIDInterfaceDescriptor_CLASS 0x03
+/// Indicates the interface does not implement a particular subclass.
+#define HIDInterfaceDescriptor_SUBCLASS_NONE 0x00
+/// Indicates the interface is compliant with the boot specification.
+#define HIDInterfaceDescriptor_SUBCLASS_BOOT 0x01
+/// Indicates the interface does not implement a particular protocol.
+#define HIDInterfaceDescriptor_PROTOCOL_NONE 0x00
+/// Indicates the interface supports the boot specification as a keyboard.
+#define HIDInterfaceDescriptor_PROTOCOL_KEYBOARD 0x01
+/// Indicates the interface supports the boot specification as a mouse.
+#define HIDInterfaceDescriptor_PROTOCOL_MOUSE 0x02
+//------------------------------------------------------------------------------
+
+#endif //#ifndef HIDINTERFACEDESCRIPTOR_H
+
diff --git a/usb/common/hid/HIDKeypad.c b/usb/common/hid/HIDKeypad.c new file mode 100644 index 0000000..19f533e --- /dev/null +++ b/usb/common/hid/HIDKeypad.c @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDKeypad implementation
+
+ About: Purpose
+ Implementation of HID keypad usage page methods.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDKeypad.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Indicates if the given key code is associated with a modified key.
+/// \param key Key code.
+/// \return 1 if the key code represents a modifier key; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char HIDKeypad_IsModifierKey(unsigned char key)
+{
+ return ((key >= HIDKeypad_LEFTCONTROL) && (key <= HIDKeypad_RIGHTGUI));
+}
+
diff --git a/usb/common/hid/HIDKeypad.h b/usb/common/hid/HIDKeypad.h new file mode 100644 index 0000000..06ad747 --- /dev/null +++ b/usb/common/hid/HIDKeypad.h @@ -0,0 +1,276 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+!!!Purpose
+
+ Definitions of constants and methods for the HID keypad usage page.
+
+ !!!Usage
+
+ -# Use the constants declared in this file when instanciating a
+ Report descriptor instance.
+ -# When implementing the functionality of an HID keyboard, use the
+ key codes defined here to indicate keys that are being pressed and
+ released.
+*/
+
+#ifndef HIDKEYPAD_H
+#define HIDKEYPAD_H
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Keypad Page ID"
+/// This page lists HID Keypad page ID.
+///
+/// !ID
+/// - HIDKeypad_PAGEID
+
+/// Identifier for the HID keypad usage page
+#define HIDKeypad_PAGEID 0x07
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Alphabetic Keys"
+/// ...
+///
+/// !Keys
+/// - HIDKeypad_A
+/// - HIDKeypad_B
+/// - HIDKeypad_C
+/// - HIDKeypad_D
+/// - HIDKeypad_E
+/// - HIDKeypad_F
+/// - HIDKeypad_G
+/// - HIDKeypad_H
+/// - HIDKeypad_I
+/// - HIDKeypad_J
+/// - HIDKeypad_K
+/// - HIDKeypad_L
+/// - HIDKeypad_M
+/// - HIDKeypad_N
+/// - HIDKeypad_O
+/// - HIDKeypad_P
+/// - HIDKeypad_Q
+/// - HIDKeypad_R
+/// - HIDKeypad_S
+/// - HIDKeypad_T
+/// - HIDKeypad_U
+/// - HIDKeypad_V
+/// - HIDKeypad_W
+/// - HIDKeypad_X
+/// - HIDKeypad_Y
+/// - HIDKeypad_Z
+
+/// Key code for 'a' and 'A'.
+#define HIDKeypad_A 4
+/// Key code for 'b' and 'B'.
+#define HIDKeypad_B 5
+/// Key code for 'c' and 'C'.
+#define HIDKeypad_C 6
+/// Key code for 'd' and 'D'.
+#define HIDKeypad_D 7
+/// Key code for 'e' and 'E'.
+#define HIDKeypad_E 8
+/// Key code for 'f' and 'F'.
+#define HIDKeypad_F 9
+/// Key code for 'g' and 'G'.
+#define HIDKeypad_G 10
+/// Key code for 'h' and 'H'.
+#define HIDKeypad_H 11
+/// Key code for 'i' and 'I'.
+#define HIDKeypad_I 12
+/// Key code for 'j' and 'J'.
+#define HIDKeypad_J 13
+/// Key code for 'k' and 'K'.
+#define HIDKeypad_K 14
+/// Key code for 'l' and 'L'.
+#define HIDKeypad_L 15
+/// Key code for 'm' and 'M'.
+#define HIDKeypad_M 16
+/// Key code for 'n' and 'N'.
+#define HIDKeypad_N 17
+/// Key code for 'o' and 'O'.
+#define HIDKeypad_O 18
+/// Key code for 'p' and 'P'.
+#define HIDKeypad_P 19
+/// Key code for 'q' and 'Q'.
+#define HIDKeypad_Q 20
+/// Key code for 'r' and 'R'.
+#define HIDKeypad_R 21
+/// Key code for 's' and 'S'.
+#define HIDKeypad_S 22
+/// Key code for 't' and 'T'.
+#define HIDKeypad_T 23
+/// Key code for 'u' and 'U'.
+#define HIDKeypad_U 24
+/// Key code for 'v' and 'V'.
+#define HIDKeypad_V 25
+/// Key code for 'w' and 'W'.
+#define HIDKeypad_W 26
+/// Key code for 'x' and 'X'.
+#define HIDKeypad_X 27
+/// Key code for 'y' and 'Y'.
+#define HIDKeypad_Y 28
+/// Key code for 'z' and 'Z'.
+#define HIDKeypad_Z 29
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Numeric Keys"
+/// ...
+///
+/// !Keys
+/// - HIDKeypad_1
+/// - HIDKeypad_2
+/// - HIDKeypad_3
+/// - HIDKeypad_4
+/// - HIDKeypad_5
+/// - HIDKeypad_6
+/// - HIDKeypad_7
+/// - HIDKeypad_8
+/// - HIDKeypad_9
+/// - HIDKeypad_0
+
+/// Key code for '1' and '!'.
+#define HIDKeypad_1 30
+/// Key code for '2' and '@'.
+#define HIDKeypad_2 31
+/// Key code for '3' and '#'.
+#define HIDKeypad_3 32
+/// Key code for '4' and '$'.
+#define HIDKeypad_4 33
+/// Key code for '5' and '%'.
+#define HIDKeypad_5 34
+/// Key code for '6' and '^'.
+#define HIDKeypad_6 35
+/// Key code for '7' and '&'.
+#define HIDKeypad_7 36
+/// Key code for '8' and '*'.
+#define HIDKeypad_8 37
+/// Key code for '9' and '('.
+#define HIDKeypad_9 38
+/// Key code for '0' and ')'.
+#define HIDKeypad_0 39
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Special Keys"
+/// ...
+///
+/// !Keys
+/// - HIDKeypad_ENTER
+/// - HIDKeypad_ESCAPE
+/// - HIDKeypad_BACKSPACE
+/// - HIDKeypad_TAB
+/// - HIDKeypad_SPACEBAR
+/// - HIDKeypad_PRINTSCREEN
+/// - HIDKeypad_SCROLLLOCK
+/// - HIDKeypad_NUMLOCK
+
+/// Enter key code.
+#define HIDKeypad_ENTER 40
+/// Escape key code.
+#define HIDKeypad_ESCAPE 41
+/// Backspace key code.
+#define HIDKeypad_BACKSPACE 42
+/// Tab key code.
+#define HIDKeypad_TAB 43
+/// Spacebar key code.
+#define HIDKeypad_SPACEBAR 44
+/// Printscreen key code.
+#define HIDKeypad_PRINTSCREEN 70
+/// Scroll lock key code.
+#define HIDKeypad_SCROLLLOCK 71
+/// Num lock key code.
+#define HIDKeypad_NUMLOCK 83
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Modified Keys"
+/// ...
+///
+/// !Keys
+/// - HIDKeypad_LEFTCONTROL
+/// - HIDKeypad_LEFTSHIFT
+/// - HIDKeypad_LEFTALT
+/// - HIDKeypad_LEFTGUI
+/// - HIDKeypad_RIGHTCONTROL
+/// - HIDKeypad_RIGHTSHIFT
+/// - HIDKeypad_RIGHTALT
+/// - HIDKeypad_RIGHTGUI
+
+/// Key code for the left 'Control' key.
+#define HIDKeypad_LEFTCONTROL 224
+/// Key code for the left 'Shift' key.
+#define HIDKeypad_LEFTSHIFT 225
+/// Key code for the left 'Alt' key.
+#define HIDKeypad_LEFTALT 226
+/// Key code for the left 'GUI' (e.g. Windows) key.
+#define HIDKeypad_LEFTGUI 227
+/// Key code for the right 'Control' key.
+#define HIDKeypad_RIGHTCONTROL 228
+/// Key code for the right 'Shift' key.
+#define HIDKeypad_RIGHTSHIFT 229
+/// Key code for the right 'Alt' key.
+#define HIDKeypad_RIGHTALT 230
+/// Key code for the right 'GUI' key.
+#define HIDKeypad_RIGHTGUI 231
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Error Codes"
+/// ...
+///
+/// !Codes
+/// - HIDKeypad_ERRORROLLOVER
+/// - HIDKeypad_POSTFAIL
+/// - HIDKeypad_ERRORUNDEFINED
+
+/// Indicates that too many keys have been pressed at the same time.
+#define HIDKeypad_ERRORROLLOVER 1
+/// ?
+#define HIDKeypad_POSTFAIL 2
+/// Indicates an undefined error.
+#define HIDKeypad_ERRORUNDEFINED 3
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char HIDKeypad_IsModifierKey(unsigned char key);
+
+#endif //#ifndef HIDKEYPAD_H
+
diff --git a/usb/common/hid/HIDLeds.h b/usb/common/hid/HIDLeds.h new file mode 100644 index 0000000..22ee54d --- /dev/null +++ b/usb/common/hid/HIDLeds.h @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition for the HID LEDs usage page.
+
+ !!!Usage
+
+ Uses the constants defined in this header file when declaring a Report
+ descriptor which references the LEDs usage page.
+*/
+
+#ifndef HIDLEDS_H
+#define HIDLEDS_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID LEDs Page ID"
+/// This page lists the page ID of the HID LEDs usage page.
+///
+/// !ID
+/// - HIDLeds_PAGEID
+
+/// ID of the HID LEDs usage page.
+#define HIDLeds_PAGEID 0x08
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID LEDs Usages"
+/// This page lists the Usages of the HID LEDs.
+///
+/// !Usages
+/// - HIDLeds_NUMLOCK
+/// - HIDLeds_CAPSLOCK
+/// - HIDLeds_SCROLLLOCK
+
+/// Num lock LED usage.
+#define HIDLeds_NUMLOCK 0x01
+/// Caps lock LED usage.
+#define HIDLeds_CAPSLOCK 0x02
+/// Scroll lock LED usage.
+#define HIDLeds_SCROLLLOCK 0x03
+//------------------------------------------------------------------------------
+
+#endif //#ifndef HIDLEDS_H
+
diff --git a/usb/common/hid/HIDReport.h b/usb/common/hid/HIDReport.h new file mode 100644 index 0000000..ec02ded --- /dev/null +++ b/usb/common/hid/HIDReport.h @@ -0,0 +1,231 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions used when declaring an HID report descriptor.
+
+ !!!Usage
+
+ Use the definitions provided here when declaring a report descriptor,
+ which shall be an unsigned char array.
+*/
+
+#ifndef HIDREPORT_H
+#define HIDREPORT_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Main Item Tags"
+/// This page lists the Main Item Tags defined for HID %device.
+/// ( HID Spec. 6.2.2 )
+///
+/// !Tags
+/// - HIDReport_INPUT
+/// - HIDReport_OUPUT
+/// - HIDReport_FEATURE
+/// - HIDReport_COLLECTION
+/// - HIDReport_ENDCOLLECTION
+
+/// Input item.
+#define HIDReport_INPUT 0x80
+/// Output item.
+#define HIDReport_OUTPUT 0x90
+/// Feature item.
+#define HIDReport_FEATURE 0xB0
+/// Collection item.
+#define HIDReport_COLLECTION 0xA0
+/// End of collection item.
+#define HIDReport_ENDCOLLECTION 0xC0
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Items for Data Fields"
+/// This page lists defintions for HID Input, Output and Feature items that
+/// are used to create the data fields within a report.
+/// ( HID Spec. 6.2.2.5 )
+///
+/// !Items
+/// - HIDReport_CONSTANT
+/// - HIDReport_VARIABLE
+/// - HIDReport_RELATIVE
+/// - HIDReport_WRAP
+/// - HIDReport_NONLINEAR
+/// - HIDReport_NOPREFERRED
+/// - HIDReport_NULLSTATE
+/// - HIDReport_VOLATILE
+/// - HIDReport_BUFFEREDBYTES
+
+/// The report value is constant (vs. variable).
+#define HIDReport_CONSTANT (1 << 0)
+/// Data reported is a variable (vs. array).
+#define HIDReport_VARIABLE (1 << 1)
+/// Data is relative (vs. absolute).
+#define HIDReport_RELATIVE (1 << 2)
+/// Value rolls over when it reach a maximum/minimum.
+#define HIDReport_WRAP (1 << 3)
+/// Indicates that the data reported has been processed and is no longuer
+/// linear with the original measurements.
+#define HIDReport_NONLINEAR (1 << 4)
+/// Device has no preferred state to which it automatically returns.
+#define HIDReport_NOPREFERRED (1 << 5)
+/// Device has a null state, in which it does not report meaningful
+/// information.
+#define HIDReport_NULLSTATE (1 << 6)
+/// Indicates data can change without the host intervention.
+#define HIDReport_VOLATILE (1 << 7)
+/// Indicates the device produces a fixed-length stream of bytes.
+#define HIDReport_BUFFEREDBYTES (1 << 8)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Collection Items"
+/// This page lists definitions for HID Collection Items.
+/// ( HID Spec. 6.2.2.6 )
+///
+/// !Items
+/// - HIDReport_COLLECTION_PHYSICAL
+/// - HIDReport_COLLECTION_APPLICATION
+/// - HIDReport_COLLECTION_LOGICAL
+/// - HIDReport_COLLECTION_REPORT
+/// - HIDReport_COLLECTION_NAMEDARRAY
+/// - HIDReport_COLLECTION_USAGESWITCH
+/// - HIDReport_COLLECTION_USAGEMODIFIER
+
+/// Physical collection.
+#define HIDReport_COLLECTION_PHYSICAL 0x00
+/// Application collection.
+#define HIDReport_COLLECTION_APPLICATION 0x01
+/// Logical collection.
+#define HIDReport_COLLECTION_LOGICAL 0x02
+/// Report collection.
+#define HIDReport_COLLECTION_REPORT 0x03
+/// Named array collection.
+#define HIDReport_COLLECTION_NAMEDARRAY 0x04
+/// Usage switch collection.
+#define HIDReport_COLLECTION_USAGESWITCH 0x05
+/// Usage modifier collection
+#define HIDReport_COLLECTION_USAGEMODIFIER 0x06
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Global Items"
+/// This page lists HID Global Items.
+/// ( HID Spec. 6.2.2.7 )
+///
+/// !Items
+/// - HIDReport_GLOBAL_USAGEPAGE
+/// - HIDReport_GLOBAL_LOGICALMINIMUM
+/// - HIDReport_GLOBAL_LOGICALMAXIMUM
+/// - HIDReport_GLOBAL_PHYSICALMINIMUM
+/// - HIDReport_GLOBAL_PHYSICALMAXIMUM
+/// - HIDReport_GLOBAL_UNITEXPONENT
+/// - HIDReport_GLOBAL_UNIT
+/// - HIDReport_GLOBAL_REPORTSIZE
+/// - HIDReport_GLOBAL_REPORTID
+/// - HIDReport_GLOBAL_REPORTCOUNT
+/// - HIDReport_GLOBAL_PUSH
+/// - HIDReport_GLOBAL_POP
+
+/// Current usage page.
+#define HIDReport_GLOBAL_USAGEPAGE 0x04
+/// Minimum value that a variable or array item will report.
+#define HIDReport_GLOBAL_LOGICALMINIMUM 0x14
+/// Maximum value that a variable or array item will report.
+#define HIDReport_GLOBAL_LOGICALMAXIMUM 0x24
+/// Minimum value for the physical extent of a variable item.
+#define HIDReport_GLOBAL_PHYSICALMINIMUM 0x34
+/// Maximum value for the physical extent of a variable item.
+#define HIDReport_GLOBAL_PHYSICALMAXIMUM 0x44
+/// Value of the unit exponent in base 10.
+#define HIDReport_GLOBAL_UNITEXPONENT 0x54
+/// Unit values.
+#define HIDReport_GLOBAL_UNIT 0x64
+/// Size of the report fields in bits.
+#define HIDReport_GLOBAL_REPORTSIZE 0x74
+/// Specifies the report ID.
+#define HIDReport_GLOBAL_REPORTID 0x84
+/// Number of data fields for an item.
+#define HIDReport_GLOBAL_REPORTCOUNT 0x94
+/// Places a copy of the global item state table on the stack.
+#define HIDReport_GLOBAL_PUSH 0xA4
+/// Replaces the item state table with the top structure from the stack.
+#define HIDReport_GLOBAL_POP 0xB4
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Local Items"
+/// This page lists definitions for HID Local Items.
+///
+/// !Items
+/// - HIDReport_LOCAL_USAGE
+/// - HIDReport_LOCAL_USAGEMINIMUM
+/// - HIDReport_LOCAL_USAGEMAXIMUM
+/// - HIDReport_LOCAL_DESIGNATORINDEX
+/// - HIDReport_LOCAL_DESIGNATORMINIMUM
+/// - HIDReport_LOCAL_DESIGNATORMAXIMUM
+/// - HIDReport_LOCAL_STRINGINDEX
+/// - HIDReport_LOCAL_STRINGMINIMUM
+/// - HIDReport_LOCAL_STRINGMAXIMUM
+/// - HIDReport_LOCAL_DELIMITER
+
+/// Suggested usage for an item or collection.
+#define HIDReport_LOCAL_USAGE 0x08
+/// Defines the starting usage associated with an array or bitmap.
+#define HIDReport_LOCAL_USAGEMINIMUM 0x18
+/// Defines the ending usage associated with an array or bitmap.
+#define HIDReport_LOCAL_USAGEMAXIMUM 0x28
+/// Determines the body part used for a control.
+#define HIDReport_LOCAL_DESIGNATORINDEX 0x38
+/// Defines the index of the starting designator associated with an array or
+/// bitmap.
+#define HIDReport_LOCAL_DESIGNATORMINIMUM 0x48
+/// Defines the index of the ending designator associated with an array or
+/// bitmap.
+#define HIDReport_LOCAL_DESIGNATORMAXIMUM 0x58
+/// String index for a string descriptor.
+#define HIDReport_LOCAL_STRINGINDEX 0x78
+/// Specifies the first string index when assigning a group of sequential
+/// strings to controls in an array or bitmap.
+#define HIDReport_LOCAL_STRINGMINIMUM 0x88
+/// Specifies the last string index when assigning a group of sequential
+/// strings to controls in an array or bitmap.
+#define HIDReport_LOCAL_STRINGMAXIMUM 0x98
+/// Defines the beginning or end of a set of local items.
+#define HIDReport_LOCAL_DELIMITER 0xA8
+//------------------------------------------------------------------------------
+
+#endif //#ifndef HIDREPORT_H
+
diff --git a/usb/common/hid/HIDReportRequest.c b/usb/common/hid/HIDReportRequest.c new file mode 100644 index 0000000..3e9d2e8 --- /dev/null +++ b/usb/common/hid/HIDReportRequest.c @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDReportRequest implementation
+
+ About: Purpose
+ Implementation of the HIDReportRequest methods.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDReportRequest.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Indicates the type of report targetted by a SET_REPORT or GET_REPORT
+/// request.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Requested report type (see "HID Report Types").
+//------------------------------------------------------------------------------
+unsigned char HIDReportRequest_GetReportType(const USBGenericRequest *request)
+{
+ return ((USBGenericRequest_GetValue(request) >> 8) & 0xFF);
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the ID of the report targetted by a SET_REPORT or GET_REPORT
+/// request. This value should be 0 if report IDs are not used.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return Requested report ID.
+//------------------------------------------------------------------------------
+unsigned char HIDReportRequest_GetReportId(const USBGenericRequest *request)
+{
+ return (USBGenericRequest_GetValue(request) & 0xFF);
+}
+
diff --git a/usb/common/hid/HIDReportRequest.h b/usb/common/hid/HIDReportRequest.h new file mode 100644 index 0000000..75ea379 --- /dev/null +++ b/usb/common/hid/HIDReportRequest.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for manipulating HID-specific GET_REPORT and
+ SET_REPORT requests.
+
+ !!!Usage
+
+ -# Receive a GET_REPORT or SET_REPORT request from the host.
+ -# Retrieve the report type using HIDReportRequest_GetReportType.
+ -# Retrieve the report ID using HIDReportRequest_GetReportId.
+*/
+
+#ifndef HIDREPORTREQUEST_H
+#define HIDREPORTREQUEST_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Report Types"
+/// This page lists the types for USB HID Reports.
+///
+/// !Types
+/// - HIDReportRequest_INPUT
+/// - HIDReportRequest_OUTPUT
+/// - HIDReportRequest_FEATURE
+
+/// Input report.
+#define HIDReportRequest_INPUT 1
+/// Output report.
+#define HIDReportRequest_OUTPUT 2
+/// Feature report.
+#define HIDReportRequest_FEATURE 3
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char HIDReportRequest_GetReportType(
+ const USBGenericRequest *request);
+
+extern unsigned char HIDReportRequest_GetReportId(
+ const USBGenericRequest *request);
+
+#endif //#ifndef HIDREPORTREQUEST_H
+
diff --git a/usb/common/hid/hid.dir b/usb/common/hid/hid.dir new file mode 100644 index 0000000..d46589b --- /dev/null +++ b/usb/common/hid/hid.dir @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !Purpose
+///
+/// This directory contains structures and definitions related to the USB HID
+/// specification. They can be divided into two groups:
+/// - HID-specific descriptors, prefixed with HID and suffixed with Descriptor.
+/// - HID-specific requests, prefixed with HID and suffixed with Request.
+//------------------------------------------------------------------------------
+
diff --git a/usb/common/massstorage/MSDeviceDescriptor.h b/usb/common/massstorage/MSDeviceDescriptor.h new file mode 100644 index 0000000..9f4f700 --- /dev/null +++ b/usb/common/massstorage/MSDeviceDescriptor.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Declaration of constants for using Device Descriptors with a Mass Storage
+/// driver.
+///
+/// !Usage
+///
+/// - For a USB device:
+/// -# When declaring a USBDeviceDescriptor instance, use the Mass Storage
+/// codes defined in this file (see "MS device codes").
+//------------------------------------------------------------------------------
+
+#ifndef MSDEVICEDESCRIPTOR_H
+#define MSDEVICEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MS device codes"
+/// This page lists the class, subclass & protocol codes used by a device with
+/// a Mass Storage driver.
+///
+/// !Codes
+///
+/// - MSDeviceDescriptor_CLASS
+/// - MSDeviceDescriptor_SUBCLASS
+/// - MSDeviceDescriptor_PROTOCOL
+
+/// Class code for a Mass Storage device.
+#define MSDeviceDescriptor_CLASS 0
+
+/// Subclass code for a Mass Storage device.
+#define MSDeviceDescriptor_SUBCLASS 0
+
+/// Protocol code for a Mass Storage device.
+#define MSDeviceDescriptor_PROTOCOL 0
+//------------------------------------------------------------------------------
+
+#endif //#ifndef MSDEVICEDESCRIPTOR_H
+
diff --git a/usb/common/massstorage/MSInterfaceDescriptor.h b/usb/common/massstorage/MSInterfaceDescriptor.h new file mode 100644 index 0000000..e51dba6 --- /dev/null +++ b/usb/common/massstorage/MSInterfaceDescriptor.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Definition of several constants used when manipulating Mass Storage interface
+/// descriptors.
+///
+/// !Usage
+///
+/// - For a USB device:
+/// -# When declaring an interface descriptor for a Mass Storage device, use
+/// the class, subclass and protocol codes defined here (see
+/// "MS interface codes").
+//------------------------------------------------------------------------------
+
+#ifndef MSINTERFACEDESCRIPTOR_H
+#define MSINTERFACEDESCRIPTOR_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MS interface codes"
+/// This page lists the available class, subclass & protocol codes for a Mass
+/// Storage interface.
+///
+/// !Codes
+///
+/// - MSInterfaceDescriptor_CLASS
+/// - MSInterfaceDescriptor_SCSI
+/// - MSInterfaceDescriptor_BULKONLY
+
+/// Class code for a Mass Storage interface.
+#define MSInterfaceDescriptor_CLASS 0x08
+
+/// Subclass code for a Mass Storage interface using the SCSI protocol.
+#define MSInterfaceDescriptor_SCSI 0x06
+
+/// Protocol code for a Mass Storage interface using Bulk-Only Transport.
+#define MSInterfaceDescriptor_BULKONLY 0x50
+//------------------------------------------------------------------------------
+
+
+#endif //#ifndef MSINTERFACEDESCRIPTOR_H
+
diff --git a/usb/common/massstorage/massstorage.dir b/usb/common/massstorage/massstorage.dir new file mode 100644 index 0000000..f9474f1 --- /dev/null +++ b/usb/common/massstorage/massstorage.dir @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !Purpose
+///
+/// This directory contains structures and definitions related to the USB mass
+/// storage specification.
+/// - Mass-storage-specific descriptors, prefixed with MS and suffixed with
+/// Descriptor.
+//------------------------------------------------------------------------------
+
diff --git a/usb/device/USBDCallbackInvocationFlowchart.png b/usb/device/USBDCallbackInvocationFlowchart.png Binary files differnew file mode 100644 index 0000000..af8028e --- /dev/null +++ b/usb/device/USBDCallbackInvocationFlowchart.png diff --git a/usb/device/USBDeviceStateDiagram.png b/usb/device/USBDeviceStateDiagram.png Binary files differnew file mode 100644 index 0000000..eacdd41 --- /dev/null +++ b/usb/device/USBDeviceStateDiagram.png diff --git a/usb/device/audio-looprec/AUDDLoopRecChannel.c b/usb/device/audio-looprec/AUDDLoopRecChannel.c new file mode 100644 index 0000000..c6d9a08 --- /dev/null +++ b/usb/device/audio-looprec/AUDDLoopRecChannel.c @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: AUDDLoopRecChannel implementation
+
+ About: Purpose
+ Implementation of the AUDDLoopRecChannel functions.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "AUDDLoopRecChannel.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+// Callbacks
+//------------------------------------------------------------------------------
+/*
+ Function: AUDDLoopRecChannel_MuteChanged
+ Callback triggered when the mute status of a channel changes. This is
+ a default implementation which does nothing and must be overriden.
+
+ Parameters:
+ channel - Pointer to a AUDDLoopRecChannel instance.
+ muted - New mute status.
+*/
+//__attribute__ ((weak)) void AUDDLoopRecChannel_MuteChanged(
+// AUDDLoopRecChannel *channel,
+// unsigned char muted)
+//{
+// TRACE_DEBUG("MuteChanged(%d, %d) ", channel->number, muted);
+//}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the member variables of an AUDDLoopRecChannel object to the
+/// given values.
+/// \param channel Pointer to an AUDDLoopRecChannel instance.
+/// \param number Channel number in the audio function.
+/// \param muted Indicates if the channel is muted.
+//------------------------------------------------------------------------------
+void AUDDLoopRecChannel_Initialize(AUDDLoopRecChannel *channel,
+ unsigned char number,
+ unsigned char muted)
+{
+ channel->number = number;
+ channel->muted = muted;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the number of a channel.
+/// \param channel Pointer to an AUDDLoopRecChannel instance.
+/// \return Channel number.
+//------------------------------------------------------------------------------
+unsigned char AUDDLoopRecChannel_GetNumber(const AUDDLoopRecChannel *channel)
+{
+ return channel->number;
+}
+
+//------------------------------------------------------------------------------
+/// Mutes the given channel and triggers the MuteChanged callback if
+/// necessary.
+/// \param channel Pointer to an AUDDLoopRecChannelInstance.
+//------------------------------------------------------------------------------
+void AUDDLoopRecChannel_Mute(AUDDLoopRecChannel *channel)
+{
+ if (!channel->muted) {
+
+ channel->muted = 1;
+ AUDDLoopRecChannel_MuteChanged(channel, 1);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Unmutes the given channel and triggers the MuteChanged callback if
+/// necessary.
+/// \param channel Pointer to an AUDDLoopRecChannelInstance.
+//------------------------------------------------------------------------------
+void AUDDLoopRecChannel_Unmute(AUDDLoopRecChannel *channel)
+{
+ if (channel->muted) {
+
+ channel->muted = 0;
+ AUDDLoopRecChannel_MuteChanged(channel, 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Indicates if the given channel is currently muted or not.
+/// \param channel Pointer an AUDDLoopRecChannel instance.
+/// \return 1 if the channel is muted; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char AUDDLoopRecChannel_IsMuted(const AUDDLoopRecChannel *channel)
+{
+ return channel->muted;
+}
+
diff --git a/usb/device/audio-looprec/AUDDLoopRecChannel.h b/usb/device/audio-looprec/AUDDLoopRecChannel.h new file mode 100644 index 0000000..6cfad6b --- /dev/null +++ b/usb/device/audio-looprec/AUDDLoopRecChannel.h @@ -0,0 +1,92 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !Purpose
+
+ Manipulation of the channels of an USB audio LoopRec device.
+
+ !Usage
+
+ -# Initialize a AUDDLoopRecChannel instance using
+ AUDDLoopRecChannel_Initialize.
+ -# Retrieves the current status of a channel with the
+ AUDDLoopRecChannel_IsMuted method.
+ -# Re-implement the AUDDLoopRecChannel_MuteChanged callback to get
+ notified when the status of a channel changes.
+*/
+
+#ifndef AUDDLOOPRECCHANNEL_H
+#define AUDDLOOPRECCHANNEL_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Modelizes a channel of an USB audio LoopRec device.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Zero-based channel number in the audio function.
+ unsigned char number;
+ /// Indicates if the channel is currently muted.
+ unsigned char muted;
+
+} AUDDLoopRecChannel;
+
+//------------------------------------------------------------------------------
+// Callbacks
+//------------------------------------------------------------------------------
+
+extern void AUDDLoopRecChannel_MuteChanged(AUDDLoopRecChannel *channel,
+ unsigned char muted);
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void AUDDLoopRecChannel_Initialize(AUDDLoopRecChannel *channel,
+ unsigned char number,
+ unsigned char muted);
+
+extern unsigned char AUDDLoopRecChannel_GetNumber(
+ const AUDDLoopRecChannel *channel);
+
+extern void AUDDLoopRecChannel_Mute(AUDDLoopRecChannel *channel);
+
+extern void AUDDLoopRecChannel_Unmute(AUDDLoopRecChannel *channel);
+
+extern unsigned char AUDDLoopRecChannel_IsMuted(
+ const AUDDLoopRecChannel *channel);
+
+#endif //#ifndef AUDDLOOPRECCHANNEL_H
+
diff --git a/usb/device/audio-looprec/AUDDLoopRecDriver.c b/usb/device/audio-looprec/AUDDLoopRecDriver.c new file mode 100644 index 0000000..45534b5 --- /dev/null +++ b/usb/device/audio-looprec/AUDDLoopRecDriver.c @@ -0,0 +1,493 @@ +/* ----------------------------------------------------------------------------
+ * 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 "AUDDLoopRecDriver.h"
+#include "AUDDLoopRecDriverDescriptors.h"
+#include "AUDDLoopRecChannel.h"
+#include <utility/trace.h>
+#include <utility/assert.h>
+#include <utility/led.h>
+#include <usb/common/audio/AUDGenericRequest.h>
+#include <usb/common/audio/AUDFeatureUnitRequest.h>
+#include <usb/device/core/USBDDriver.h>
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Audio LoopRec driver internal state.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// USB device driver instance.
+ USBDDriver usbdDriver;
+ #if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ /// Multi-Buffer-Transfer List
+ USBDTransferBuffer * pMbl;
+ /// List Size
+ unsigned short listSize;
+ /// Current buffer
+ unsigned short currBuffer;
+ #endif
+ /// Callback for ISO IN
+ AUDDFrameTransferCallback fWrCallback;
+ /// List of AUDDLoopRecChannel instances for playback.
+ AUDDLoopRecChannel channels[AUDDLoopRecDriver_NUMCHANNELS+1];
+ /// List of AUDDLoopRecChannel instances for record.
+ AUDDLoopRecChannel recChannels[1];
+
+} AUDDLoopRecDriver;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Global USB audio LoopRec driver instance.
+static AUDDLoopRecDriver auddLoopRecDriver;
+/// Array for storing the current setting of each interface.
+static unsigned char auddLoopRecDriverInterfaces[3];
+/// Intermediate storage variable for the mute status of a channel.
+static unsigned char muted;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Callback triggered after the new mute status of a channel has been read
+/// by AUDDLoopRecDriver_SetFeatureCurrentValue. Changes the mute status
+/// of the given channel accordingly.
+/// \param channel Number of the channel whose mute status has changed.
+//------------------------------------------------------------------------------
+static void AUDDLoopRecDriver_MuteReceived(unsigned int channel)
+{
+ AUDDLoopRecChannel * pChannel;
+ if ((unsigned char)(channel >> 8) ==
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC) {
+ pChannel = &auddLoopRecDriver.recChannels[0];
+ }
+ else {
+ pChannel = &auddLoopRecDriver.channels[channel];
+ }
+ if (muted) {
+
+ AUDDLoopRecChannel_Mute(pChannel);
+ }
+ else {
+
+ AUDDLoopRecChannel_Unmute(pChannel);
+ }
+
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sets the current value of a particular Feature control of a channel.
+/// \param entity Entity number.
+/// \param channel Channel number.
+/// \param control Control selector value (see TODO).
+/// \param length Length of the data containing the new value.
+//------------------------------------------------------------------------------
+static void AUDDLoopRecDriver_SetFeatureCurrentValue(unsigned char entity,
+ unsigned char channel,
+ unsigned char control,
+ unsigned short length)
+{
+ TRACE_INFO_WP("sFeature ");
+ TRACE_DEBUG("\b(E%d, CS%d, CN%d, L%d) ",
+ entity, control, channel, length);
+
+ // Check the the requested control is supported
+ // Control/channel combination not supported
+ if ((control != AUDFeatureUnitRequest_MUTE) ||
+ (length != 1) ||
+ ((entity == AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL) &&
+ (channel > AUDDLoopRecDriver_NUMCHANNELS)) ||
+ ((entity == AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC) &&
+ (channel > 0))) {
+
+ USBD_Stall(0);
+ }
+ // Mute control on master channel / speakerphone
+ else {
+
+ unsigned int argument = channel | (entity << 8);
+ USBD_Read(0, // Endpoint #0
+ &muted,
+ sizeof(muted),
+ (TransferCallback) AUDDLoopRecDriver_MuteReceived,
+ (void *) argument);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current value of a particular channel Feature to the USB host.
+/// \param entity Entity number.
+/// \param channel Channel number.
+/// \param control Control selector value (see TODO).
+/// \param length Length of the data to return.
+//------------------------------------------------------------------------------
+static void AUDDLoopRecDriver_GetFeatureCurrentValue(unsigned char entity,
+ unsigned char channel,
+ unsigned char control,
+ unsigned char length)
+{
+ TRACE_INFO_WP("gFeature ");
+ TRACE_DEBUG("\b(CS%d, CN%d, L%d) ", control, channel, length);
+
+ // Check that the requested control is supported
+ // Master channel mute control
+ if ((control == AUDFeatureUnitRequest_MUTE)
+ && (channel < (AUDDLoopRecDriver_NUMCHANNELS+1))
+ && (length == 1)) {
+
+ if (entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT) {
+ muted = auddLoopRecDriver.channels[channel].muted;
+ }
+ else {
+ muted = auddLoopRecDriver.recChannels[0].muted;
+ }
+ USBD_Write(0, &muted, sizeof(muted), 0, 0);
+ }
+ else {
+
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Callback used by MBL transfer functions (USBD_Read & USBD_Write) to notify
+/// that a transaction is complete.
+/// \param pArg Pointer to callback arguments.
+/// \param status USBD status.
+/// \param nbBuffer Number of buffer that is processed.
+//------------------------------------------------------------------------------
+void AUDDLoopRecDriver_MblWriteCallback(void *pArg,
+ unsigned char status,
+ unsigned int nbBuffer)
+{
+ char rc = 1;
+ if (auddLoopRecDriver.fWrCallback) {
+
+ rc = auddLoopRecDriver.fWrCallback(pArg, status);
+ }
+ if (rc && status == USBD_STATUS_PARTIAL_DONE) {
+
+ while(nbBuffer --) {
+ USBD_MblReuse(AUDDLoopRecDriverDescriptors_DATAIN,
+ 0, 0);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Callback re-implementation
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Triggered when the USB host emits a new SETUP request. The request is
+/// forward to <AUDDLoopRecDriver_RequestHandler>.
+/// \param request Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ AUDDLoopRecDriver_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)
+{
+ if ((interface == AUDDLoopRecDriverDescriptors_STREAMING)
+ && (setting == 0)) {
+
+ LED_Clear(USBD_LEDOTHER);
+ }
+ else {
+
+ LED_Set(USBD_LEDOTHER);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes an USB audio LoopRec device driver, as well as the underlying
+/// USB controller.
+//------------------------------------------------------------------------------
+void AUDDLoopRecDriver_Initialize()
+{
+ // Reset callback function
+ auddLoopRecDriver.fWrCallback = 0;
+
+ // Initialize LoopRec channels
+ AUDDLoopRecChannel_Initialize(&(auddLoopRecDriver.channels[0]),
+ AUDDLoopRecDriver_MASTERCHANNEL,
+ 0);
+ AUDDLoopRecChannel_Initialize(&(auddLoopRecDriver.channels[1]),
+ AUDDLoopRecDriver_LEFTCHANNEL,
+ 0);
+ AUDDLoopRecChannel_Initialize(&(auddLoopRecDriver.channels[2]),
+ AUDDLoopRecDriver_RIGHTCHANNEL,
+ 0);
+ AUDDLoopRecChannel_Initialize(&(auddLoopRecDriver.recChannels[0]),
+ AUDDLoopRecDriver_RECCHANNEL,
+ 0);
+
+ // Initialize the USB driver
+ USBDDriver_Initialize(&(auddLoopRecDriver.usbdDriver),
+ &auddLoopRecDriverDescriptors,
+ auddLoopRecDriverInterfaces);
+ USBD_Init();
+
+ // Initialize the third LED to indicate when the audio interface is active
+ LED_Configure(USBD_LEDOTHER);
+}
+
+//------------------------------------------------------------------------------
+/// Handles audio-specific USB requests sent by the host, and forwards
+/// standard ones to the USB device driver.
+/// \param request Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+void AUDDLoopRecDriver_RequestHandler(const USBGenericRequest *request)
+{
+ unsigned char entity;
+ unsigned char interface;
+
+ TRACE_INFO_WP("NewReq ");
+
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ // Check if the request is supported
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case AUDGenericRequest_SETCUR:
+ TRACE_INFO_WP(
+ "sCur(0x%04X) ",
+ USBGenericRequest_GetIndex(request));
+
+ // Check the target interface and entity
+ entity = AUDGenericRequest_GetEntity(request);
+ interface = AUDGenericRequest_GetInterface(request);
+ if (((entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT)
+ ||(entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC))
+ && (interface == AUDDLoopRecDriverDescriptors_CONTROL)) {
+
+ AUDDLoopRecDriver_SetFeatureCurrentValue(
+ entity,
+ AUDFeatureUnitRequest_GetChannel(request),
+ AUDFeatureUnitRequest_GetControl(request),
+ USBGenericRequest_GetLength(request));
+ }
+ else {
+
+ TRACE_WARNING(
+ "AUDDLoopRecDriver_RequestHandler: Unsupported entity/interface combination (0x%04X)\n\r",
+ USBGenericRequest_GetIndex(request));
+ USBD_Stall(0);
+ }
+ break;
+
+ case AUDGenericRequest_GETCUR:
+ TRACE_INFO_WP(
+ "gCur(0x%04X) ",
+ USBGenericRequest_GetIndex(request));
+
+ // Check the target interface and entity
+ entity = AUDGenericRequest_GetEntity(request);
+ interface = AUDGenericRequest_GetInterface(request);
+ if (((entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT)
+ ||(entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC))
+ && (interface == AUDDLoopRecDriverDescriptors_CONTROL)) {
+
+ AUDDLoopRecDriver_GetFeatureCurrentValue(
+ entity,
+ AUDFeatureUnitRequest_GetChannel(request),
+ AUDFeatureUnitRequest_GetControl(request),
+ USBGenericRequest_GetLength(request));
+ }
+ else {
+
+ TRACE_WARNING(
+ "AUDDLoopRecDriver_RequestHandler: Unsupported entity/interface combination (0x%04X)\n\r",
+ USBGenericRequest_GetIndex(request));
+ USBD_Stall(0);
+ }
+ break;
+
+ default:
+
+ TRACE_WARNING(
+ "AUDDLoopRecDriver_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) {
+
+ // Forward request to the standard handler
+ USBDDriver_RequestHandler(&(auddLoopRecDriver.usbdDriver), request);
+ }
+ // Unsupported request type
+ else {
+
+ TRACE_WARNING(
+ "AUDDLoopRecDriver_RequestHandler: Unsupported request type (%d)\n\r",
+ USBGenericRequest_GetType(request));
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reads incoming audio data sent by the USB host into the provided
+/// buffer. When the transfer is complete, an optional callback function is
+/// invoked.
+/// \param buffer Pointer to the data storage buffer.
+/// \param length Size of the buffer in bytes.
+/// \param callback Optional callback function.
+/// \param argument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the transfer is started successfully;
+/// otherwise an error code.
+//------------------------------------------------------------------------------
+unsigned char AUDDLoopRecDriver_Read(void *buffer,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Read(AUDDLoopRecDriverDescriptors_DATAOUT,
+ buffer,
+ length,
+ callback,
+ argument);
+}
+
+//------------------------------------------------------------------------------
+/// Initialize Frame List for sending audio data.
+/// \param pMultiBufferList Pointer to the transfer list to initialize.
+/// \param pBufferList Pointer list to the buffers used for frames sending.
+/// \param listSize Number of frames.
+/// \param frameSize Size in number of bytes of each frame.
+//------------------------------------------------------------------------------
+void AUDDLoopRecDriver_SetupWriteMbl(void * pMultiBufferList,
+ unsigned char **pBufferList,
+ unsigned short listSize,
+ unsigned short frameSize)
+{
+ int i;
+
+ SANITY_CHECK(pMultiBufferList && pBufferList && listSize && frameSize);
+
+#if (defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)) && defined(DMA)
+ // Initialize for circled DMA LLI
+ {
+ USBDDmaDescriptor * pLl = (USBDDmaDescriptor*)pMultiBufferList;
+ for (i = 0; ; i ++) {
+ pLl[i].pDataAddr = pBufferList[i];
+ pLl[i].bufferLength = frameSize;
+ if (i < listSize - 1) {
+ pLl[i].pNxtDesc = &pLl[i + 1];
+ }
+ else {
+ pLl[i].pNxtDesc = &pLl[0];
+ break;
+ }
+ }
+ }
+#else
+ // Initialize for circled multi-buffer-list
+ {
+ USBDTransferBuffer * pMbl = (USBDTransferBuffer*)pMultiBufferList;
+ for (i = 0; i < listSize; i ++) {
+ pMbl[i].pBuffer = pBufferList[i];
+ pMbl[i].size = frameSize;
+ pMbl[i].transferred = 0;
+ pMbl[i].buffered = 0;
+ pMbl[i].remaining = frameSize;
+ }
+ }
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Start sending audio data, through MBL window.
+/// When any frame is complete, an optional callback function is invoked, return
+/// 1 of the callback cause the frame buffer re-used.
+/// If callback not assigned, frames always reused.
+/// \param buffer Pointer to the data storage buffer.
+/// \param length Size of the buffer in bytes.
+/// \param callback Optional callback function.
+/// \param argument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the transfer is started successfully;
+/// otherwise an error code.
+//------------------------------------------------------------------------------
+unsigned char AUDDLoopRecDriver_Write(void * pMbl,
+ unsigned short listSize,
+ AUDDFrameTransferCallback callback,
+ void * argument)
+{
+ auddLoopRecDriver.fWrCallback = callback;
+ return USBD_MblWrite(AUDDLoopRecDriverDescriptors_DATAIN,
+ pMbl,
+ listSize,
+ 1,
+ 0,
+ AUDDLoopRecDriver_MblWriteCallback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//-----------------------------------------------------------------------------
+void AUDDLoopRecDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&auddLoopRecDriver.usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+}
+
+
diff --git a/usb/device/audio-looprec/AUDDLoopRecDriver.h b/usb/device/audio-looprec/AUDDLoopRecDriver.h new file mode 100644 index 0000000..8db30a1 --- /dev/null +++ b/usb/device/audio-looprec/AUDDLoopRecDriver.h @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !Purpose
+
+ Definition of a USB Audio Loop Record Driver with two playback channels
+ and one record channel.
+
+ !Usage
+
+ -# Enable and setup USB related pins (see pio & board.h).
+ -# Configure the USB Audio Loop Record driver using
+ AUDDLoopRecDriver_Initialize
+ -# To get %audio stream frames from host, use
+ AUDDLoopRecDriver_Read
+ -# To send %audio sampling stream to host, use
+ AUDDLoopRecDriver_Write
+
+*/
+
+#ifndef AUDDLoopRecDriver_H
+#define AUDDLoopRecDriver_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Loop Record stream information"
+///
+/// This page lists codes for USB Audio Loop Record stream information.
+///
+/// !Code
+/// - AUDDLoopRecDriver_SAMPLERATE
+/// - AUDDLoopRecDriver_NUMCHANNELS
+/// - AUDDLoopRecDriver_BYTESPERSAMPLE
+/// - AUDDLoopRecDriver_BITSPERSAMPLE
+/// - AUDDLoopRecDriver_SAMPLESPERFRAME
+/// - AUDDLoopRecDriver_BYTESPERFRAME
+
+#if defined(at91sam7s) || defined(at91sam9xe)
+ /// Sample rate in Hz.
+ #define AUDDLoopRecDriver_SAMPLERATE 32000
+ /// Number of channels in audio stream.
+ #define AUDDLoopRecDriver_NUMCHANNELS 1
+ /// Number of bytes in one sample.
+ #define AUDDLoopRecDriver_BYTESPERSAMPLE 2
+#else
+ /// Sample rate in Hz.
+ #define AUDDLoopRecDriver_SAMPLERATE 48000
+ /// Number of channels in audio stream.
+ #define AUDDLoopRecDriver_NUMCHANNELS 2
+ /// Number of bytes in one sample.
+ #define AUDDLoopRecDriver_BYTESPERSAMPLE 2
+#endif
+/// Number of bits in one sample.
+#define AUDDLoopRecDriver_BITSPERSAMPLE (AUDDLoopRecDriver_BYTESPERSAMPLE * 8)
+/// Number of bytes in one USB subframe.
+#define AUDDLoopRecDriver_BYTESPERSUBFRAME (AUDDLoopRecDriver_NUMCHANNELS * \
+ AUDDLoopRecDriver_BYTESPERSAMPLE)
+/// Number of samples in one USB frame.
+#define AUDDLoopRecDriver_SAMPLESPERFRAME (AUDDLoopRecDriver_SAMPLERATE / 1000 \
+ * AUDDLoopRecDriver_NUMCHANNELS)
+/// Number of bytes in one USB frame.
+#define AUDDLoopRecDriver_BYTESPERFRAME (AUDDLoopRecDriver_SAMPLESPERFRAME * \
+ AUDDLoopRecDriver_BYTESPERSAMPLE)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Loop Record Channel Numbers"
+///
+/// This page lists codes for USB Audio Loop Record channel numbers.
+///
+/// !Playback channel numbers
+/// - AUDDLoopRecDriver_MASTERCHANNEL
+/// - AUDDLoopRecDriver_LEFTCHANNEL
+/// - AUDDLoopRecDriver_RIGHTCHANNEL
+///
+/// !Record channel number
+/// - AUDDLoopRecDriver_RECCHANNEL
+
+/// Master channel of playback.
+#define AUDDLoopRecDriver_MASTERCHANNEL 0
+/// Front left channel of playback.
+#define AUDDLoopRecDriver_LEFTCHANNEL 1
+/// Front right channel of playback.
+#define AUDDLoopRecDriver_RIGHTCHANNEL 2
+/// Channel of record.
+#define AUDDLoopRecDriver_RECCHANNEL 0
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Callback function for audio frames.
+/// \param pArg Pointer to transfer arguments.
+/// \param status Frame transfer status.
+/// \return 1 to continue, 0 to stop frames.
+//------------------------------------------------------------------------------
+typedef char (*AUDDFrameTransferCallback)(void* pArg, char status);
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void AUDDLoopRecDriver_Initialize();
+
+extern void AUDDLoopRecDriver_RequestHandler(const USBGenericRequest *request);
+
+extern unsigned char AUDDLoopRecDriver_Read(void *buffer,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument);
+
+extern void AUDDLoopRecDriver_SetupWriteMbl(void * pMultiBufferList,
+ unsigned char **pBufferList,
+ unsigned short listSize,
+ unsigned short frameSize);
+
+extern unsigned char AUDDLoopRecDriver_Write(void * pMbl,
+ unsigned short listSize,
+ AUDDFrameTransferCallback callback,
+ void *argument);
+
+extern void AUDDLoopRecDriver_RemoteWakeUp(void);
+
+#endif //#ifndef AUDDLoopRecDriver_H
+
diff --git a/usb/device/audio-looprec/AUDDLoopRecDriverDescriptors.c b/usb/device/audio-looprec/AUDDLoopRecDriverDescriptors.c new file mode 100644 index 0000000..9f961fd --- /dev/null +++ b/usb/device/audio-looprec/AUDDLoopRecDriverDescriptors.c @@ -0,0 +1,1461 @@ +/* ----------------------------------------------------------------------------
+ * 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 "AUDDLoopRecDriverDescriptors.h"
+#include "AUDDLoopRecDriver.h"
+#include <board.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/audio/AUDGenericDescriptor.h>
+#include <usb/common/audio/AUDDeviceDescriptor.h>
+#include <usb/common/audio/AUDControlInterfaceDescriptor.h>
+#include <usb/common/audio/AUDStreamingInterfaceDescriptor.h>
+#include <usb/common/audio/AUDEndpointDescriptor.h>
+#include <usb/common/audio/AUDDataEndpointDescriptor.h>
+#include <usb/common/audio/AUDFormatTypeOneDescriptor.h>
+#include <usb/common/audio/AUDHeaderDescriptor.h>
+#include <usb/common/audio/AUDFeatureUnitDescriptor.h>
+#include <usb/common/audio/AUDInputTerminalDescriptor.h>
+#include <usb/common/audio/AUDOutputTerminalDescriptor.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Loop Record Device Codes"
+///
+/// This page lists the %device IDs and release number of the USB Audio Loop Record
+/// %device.
+///
+/// !Codes
+/// - AUDDLoopRecDriverDescriptors_VENDORID
+/// - AUDDLoopRecDriverDescriptors_PRODUCTID
+/// - AUDDLoopRecDriverDescriptors_RELEASE
+
+/// Device vendor ID.
+#define AUDDLoopRecDriverDescriptors_VENDORID 0x03EB
+/// Device product ID.
+#define AUDDLoopRecDriverDescriptors_PRODUCTID 0x6128
+/// Device release number in BCD format.
+#define AUDDLoopRecDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Audio control header descriptor with one slave interface.
+//------------------------------------------------------------------------------
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Header descriptor with 1 interface.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Header descriptor.
+ AUDHeaderDescriptor header;
+ /// Id of the first grouped interface - Speaker.
+ unsigned char bInterface0;
+ /// Id of the second grouped interface - Speakerphone.
+ unsigned char bInterface1;
+
+} __attribute__ ((packed)) AUDHeaderDescriptor2; // GCC
+
+//------------------------------------------------------------------------------
+/// Feature unit descriptor with 3 channel controls (master, right, left).
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Feature unit descriptor.
+ AUDFeatureUnitDescriptor feature;
+ /// Available controls for each channel.
+ unsigned char bmaControls[3];
+ /// Index of a string descriptor for the feature unit.
+ unsigned char iFeature;
+
+} __attribute__ ((packed)) AUDFeatureUnitDescriptor3; // GCC
+
+//------------------------------------------------------------------------------
+/// List of descriptors for detailling the audio control interface of a
+/// device using a USB Audio Loop Recorder driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Header descriptor (with one slave interface).
+ AUDHeaderDescriptor2 header;
+ /// Input terminal descriptor.
+ AUDInputTerminalDescriptor inputLoopRec;
+ /// Output terminal descriptor.
+ AUDOutputTerminalDescriptor outputLoopRec;
+ /// Feature unit descriptor - LoopRec.
+ AUDFeatureUnitDescriptor3 featureLoopRec;
+ /// Input terminal descriptor.
+ AUDInputTerminalDescriptor inputRec;
+ /// Output terminal descriptor.
+ AUDOutputTerminalDescriptor outputRec;
+ /// Feature unit descriptor - LoopRecphone.
+ AUDFeatureUnitDescriptor3 featureRec;
+
+} __attribute__ ((packed)) AUDDLoopRecDriverAudioControlDescriptors; // GCC
+
+//------------------------------------------------------------------------------
+/// Format type I descriptor with one discrete sampling frequency.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Format type I descriptor.
+ AUDFormatTypeOneDescriptor formatType;
+ /// Sampling frequency in Hz.
+ unsigned char tSamFreq[3];
+
+} __attribute__ ((packed)) AUDFormatTypeOneDescriptor1; // GCC
+
+//------------------------------------------------------------------------------
+/// Holds a list of descriptors returned as part of the configuration of
+/// a USB Audio Loop Record device.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration.
+ USBConfigurationDescriptor configuration;
+ /// Audio control interface.
+ USBInterfaceDescriptor control;
+ /// Descriptors for the audio control interface.
+ AUDDLoopRecDriverAudioControlDescriptors controlDescriptors;
+ //- AUDIO OUT
+ /// Streaming out interface descriptor (with no endpoint, required).
+ USBInterfaceDescriptor streamingOutNoIsochronous;
+ /// Streaming out interface descriptor.
+ USBInterfaceDescriptor streamingOut;
+ /// Audio class descriptor for the streaming out interface.
+ AUDStreamingInterfaceDescriptor streamingOutClass;
+ /// Stream format descriptor.
+ AUDFormatTypeOneDescriptor1 streamingOutFormatType;
+ /// Streaming out endpoint descriptor.
+ AUDEndpointDescriptor streamingOutEndpoint;
+ /// Audio class descriptor for the streaming out endpoint.
+ AUDDataEndpointDescriptor streamingOutDataEndpoint;
+ //- AUDIO IN
+ /// Streaming in interface descriptor (with no endpoint, required).
+ USBInterfaceDescriptor streamingInNoIsochronous;
+ /// Streaming in interface descriptor.
+ USBInterfaceDescriptor streamingIn;
+ /// Audio class descriptor for the streaming in interface.
+ AUDStreamingInterfaceDescriptor streamingInClass;
+ /// Stream format descriptor.
+ AUDFormatTypeOneDescriptor1 streamingInFormatType;
+ /// Streaming in endpoint descriptor.
+ AUDEndpointDescriptor streamingInEndpoint;
+ /// Audio class descriptor for the streaming in endpoint.
+ AUDDataEndpointDescriptor streamingInDataEndpoint;
+
+} __attribute__ ((packed)) AUDDLoopRecDriverConfigurationDescriptors; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Device descriptor for a USB Audio Loop Record driver.
+const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ AUDDeviceDescriptor_CLASS,
+ AUDDeviceDescriptor_SUBCLASS,
+ AUDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ AUDDLoopRecDriverDescriptors_VENDORID,
+ AUDDLoopRecDriverDescriptors_PRODUCTID,
+ AUDDLoopRecDriverDescriptors_RELEASE,
+ 1, // Manufacturer string descriptor index
+ 2, // Product string descriptor index
+ 3, // Index of serial number string descriptor
+ 1 // One possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// USB device qualifier descriptor.
+const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ USBDeviceDescriptor_USB2_00,
+ AUDDeviceDescriptor_CLASS,
+ AUDDeviceDescriptor_SUBCLASS,
+ AUDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+/// HS Configuration descriptors for a USB Audio Loop Record driver.
+const AUDDLoopRecDriverConfigurationDescriptors hsConfigurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(AUDDLoopRecDriverConfigurationDescriptors),
+ 3, // This configuration has 3 interfaces
+ 1, // This is configuration #1
+ 0, // No string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Audio control interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_CONTROL,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoint
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio control interface descriptors
+ {
+ // Header descriptor
+ {
+ {
+ sizeof(AUDHeaderDescriptor2),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_HEADER,
+ AUDHeaderDescriptor_AUD1_00,
+ sizeof(AUDDLoopRecDriverAudioControlDescriptors),
+ 2 // Two streaming interface
+ },
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN
+ },
+ // Input terminal descriptor ( speaker )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDInputTerminalDescriptor_USBSTREAMING,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speaker )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDOutputTerminalDescriptor_SPEAKER,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speaker )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 1, // 1 byte per channel for controls
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Master channel controls
+ 0, // Right channel controls
+ 0 // Left channel controls
+ },
+ 0 // No string descriptor
+ },
+ // Input terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDInputTerminalDescriptor_SPEAKERPHONE,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDOutputTerminalDescriptor_USBTREAMING,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speakerphone )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ 1
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Mic controls
+ 0,
+ 0
+ },
+ 0 // No string descriptor
+ }
+ },
+ // - AUIDO OUT
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ AUDDLoopRecDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_HS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ },
+ //- AUDIO IN
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ AUDDLoopRecDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_HS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ }
+};
+
+/// HS Other Speed Configuration descriptors for a USB Audio Loop Record driver.
+const AUDDLoopRecDriverConfigurationDescriptors
+ fsOtherSpeedConfigurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(AUDDLoopRecDriverConfigurationDescriptors),
+ 3, // This configuration has 3 interfaces
+ 1, // This is configuration #1
+ 0, // No string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Audio control interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_CONTROL,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoint
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio control interface descriptors
+ {
+ // Header descriptor
+ {
+ {
+ sizeof(AUDHeaderDescriptor2),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_HEADER,
+ AUDHeaderDescriptor_AUD1_00,
+ sizeof(AUDDLoopRecDriverAudioControlDescriptors),
+ 2 // Two streaming interface
+ },
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN
+ },
+ // Input terminal descriptor ( speaker )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDInputTerminalDescriptor_USBSTREAMING,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speaker )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDOutputTerminalDescriptor_SPEAKER,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speaker )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 1, // 1 byte per channel for controls
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Master channel controls
+ 0, // Right channel controls
+ 0 // Left channel controls
+ },
+ 0 // No string descriptor
+ },
+ // Input terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDInputTerminalDescriptor_SPEAKERPHONE,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDOutputTerminalDescriptor_USBTREAMING,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speakerphone )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ 1
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Mic controls
+ 0,
+ 0
+ },
+ 0 // No string descriptor
+ }
+ },
+ // - AUIDO OUT
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ AUDDLoopRecDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_HS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ },
+ //- AUDIO IN
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ AUDDLoopRecDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_HS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ }
+};
+
+/// HS Other Speed Configuration descriptors.
+const AUDDLoopRecDriverConfigurationDescriptors
+ hsOtherSpeedConfigurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(AUDDLoopRecDriverConfigurationDescriptors),
+ 3, // This configuration has 3 interfaces
+ 1, // This is configuration #1
+ 0, // No string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Audio control interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_CONTROL,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoint
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio control interface descriptors
+ {
+ // Header descriptor
+ {
+ {
+ sizeof(AUDHeaderDescriptor2),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_HEADER,
+ AUDHeaderDescriptor_AUD1_00,
+ sizeof(AUDDLoopRecDriverAudioControlDescriptors),
+ 2 // Two streaming interface
+ },
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN
+ },
+ // Input terminal descriptor ( speaker )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDInputTerminalDescriptor_USBSTREAMING,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speaker )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDOutputTerminalDescriptor_SPEAKER,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speaker )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 1, // 1 byte per channel for controls
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Master channel controls
+ 0, // Right channel controls
+ 0 // Left channel controls
+ },
+ 0 // No string descriptor
+ },
+ // Input terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDInputTerminalDescriptor_SPEAKERPHONE,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDOutputTerminalDescriptor_USBTREAMING,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speakerphone )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ 1
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Mic controls
+ 0,
+ 0
+ },
+ 0 // No string descriptor
+ }
+ },
+ // - AUIDO OUT
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ AUDDLoopRecDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_FS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ },
+ //- AUDIO IN
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ AUDDLoopRecDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_FS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ }
+};
+
+#endif // defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// FS Configuration descriptors for a USB Audio Loop Record driver.
+const AUDDLoopRecDriverConfigurationDescriptors fsConfigurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(AUDDLoopRecDriverConfigurationDescriptors),
+ 3, // This configuration has 3 interfaces
+ 1, // This is configuration #1
+ 0, // No string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Audio control interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_CONTROL,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoint
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio control interface descriptors
+ {
+ // Header descriptor
+ {
+ {
+ sizeof(AUDHeaderDescriptor2),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_HEADER,
+ AUDHeaderDescriptor_AUD1_00,
+ sizeof(AUDDLoopRecDriverAudioControlDescriptors),
+ 2 // Two streaming interface
+ },
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN
+ },
+ // Input terminal descriptor ( speaker )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDInputTerminalDescriptor_USBSTREAMING,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speaker )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL,
+ AUDOutputTerminalDescriptor_SPEAKER,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speaker )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 1, // 1 byte per channel for controls
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Master channel controls
+ 0, // Right channel controls
+ 0 // Left channel controls
+ },
+ 0 // No string descriptor
+ },
+ // Input terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDInputTerminalDescriptor_SPEAKERPHONE,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ #if AUDDLoopRecDriver_NUMCHANNELS > 1
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ #else
+ 0, // Mono sets no position bits.
+ #endif
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor ( speakerphone )
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ AUDOutputTerminalDescriptor_USBTREAMING,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor ( speakerphone )
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC,
+ 1
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Mic controls
+ 0,
+ 0
+ },
+ 0 // No string descriptor
+ }
+ },
+ // - AUIDO OUT
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMING,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_INPUTTERMINAL,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ AUDDLoopRecDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_FS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ },
+ //- AUDIO IN
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDLoopRecDriverDescriptors_STREAMINGIN,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDLoopRecDriver_NUMCHANNELS,
+ AUDDLoopRecDriver_BYTESPERSAMPLE,
+ AUDDLoopRecDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDLoopRecDriver_SAMPLERATE & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDLoopRecDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ AUDDLoopRecDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ AUDDLoopRecDriver_BYTESPERFRAME,
+ AUDDLoopRecDriverDescriptors_FS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ }
+};
+
+/// 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(15),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('k'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('k'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('r')
+};
+
+/// Product serial number.
+const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(4),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3')
+};
+
+/// Array of pointers to the four string descriptors.
+const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+/// List of descriptors required by an USB Audio Loop Recorder device driver.
+const USBDDriverDescriptors auddLoopRecDriverDescriptors = {
+
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &fsConfigurationDescriptors,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &fsOtherSpeedConfigurationDescriptors,
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &hsConfigurationDescriptors,
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &hsOtherSpeedConfigurationDescriptors,
+#else
+ 0, 0, 0, 0, 0, 0,
+#endif
+ stringDescriptors,
+ 4 // Number of string descriptors
+};
+
diff --git a/usb/device/audio-looprec/AUDDLoopRecDriverDescriptors.h b/usb/device/audio-looprec/AUDDLoopRecDriverDescriptors.h new file mode 100644 index 0000000..4b333d7 --- /dev/null +++ b/usb/device/audio-looprec/AUDDLoopRecDriverDescriptors.h @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Declaration of the descriptors required by a USB audio speaker driver.
+
+ !!!Usage
+
+ -# Initialize a USBDDriver instance using the
+ auddSpeakerDriverDescriptors list.
+*/
+
+#ifndef AUDDLOOPRECDESCRIPTORS_H
+#define AUDDLOOPRECDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Endpoint Numbers"
+///
+/// This page lists the endpoint number settings for USB Audio Speaker device.
+///
+/// !Endpoints
+/// - AUDDLoopRecDriverDescriptors_DATAOUT
+/// - AUDDLoopRecDriverDescriptors_DATAIN
+/// - AUDDLoopRecDriverDescriptors_HS_INTERVAL
+/// - AUDDLoopRecDriverDescriptors_FS_INTERVAL
+
+#if defined(at91sam7s) || defined(at91sam9xe)
+ /// Data out endpoint number, size 64B.
+ #define AUDDLoopRecDriverDescriptors_DATAOUT 0x01
+ /// Data in endpoint number, size 64B
+ #define AUDDLoopRecDriverDescriptors_DATAIN 0x02
+#elif defined(CHIP_USB_UDP)
+ /// Data out endpoint number, size 192B.
+ #define AUDDLoopRecDriverDescriptors_DATAOUT 0x04
+ /// Data in endpoint number, size 192B.
+ #define AUDDLoopRecDriverDescriptors_DATAIN 0x05
+#elif defined(at91sam9m10ek) || defined(at91sam9m10ekes)
+ /// Data out endpoint number, size 192B.
+ #define AUDDLoopRecDriverDescriptors_DATAOUT 0x01
+ /// Data in endpoint number, size 192B
+ #define AUDDLoopRecDriverDescriptors_DATAIN 0x06
+#else
+ /// Data out endpoint number, size 192B.
+ #define AUDDLoopRecDriverDescriptors_DATAOUT 0x05
+ /// Data in endpoint number, size 192B
+ #define AUDDLoopRecDriverDescriptors_DATAIN 0x06
+#endif
+
+/// Endpoint polling interval 2^(x-1) * 125us
+#define AUDDLoopRecDriverDescriptors_HS_INTERVAL 0x04
+/// Endpoint polling interval 2^(x-1) * ms
+#define AUDDLoopRecDriverDescriptors_FS_INTERVAL 0x01
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Interface IDs"
+///
+/// This page lists the interface numbers for USB Audio Speaker device.
+///
+/// !Interfaces
+/// - AUDDLoopRecDriverDescriptors_CONTROL
+/// - AUDDLoopRecDriverDescriptors_STREAMING
+/// - AUDDLoopRecDriverDescriptors_STREAMINGIN
+
+/// Audio control interface ID.
+#define AUDDLoopRecDriverDescriptors_CONTROL 0
+/// Audio streaming interface ID (OUT, for playback).
+#define AUDDLoopRecDriverDescriptors_STREAMING 1
+/// Audio streaming interface ID (IN, for record).
+#define AUDDLoopRecDriverDescriptors_STREAMINGIN 2
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Entity IDs"
+///
+/// This page lists the entity IDs for USB Audio Speaker device.
+///
+/// !Entities
+/// - AUDDLoopRecDriverDescriptors_INPUTTERMINAL
+/// - AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL
+/// - AUDDLoopRecDriverDescriptors_FEATUREUNIT
+/// - AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC
+/// - AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC
+/// - AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC
+
+/// Playback input terminal ID.
+#define AUDDLoopRecDriverDescriptors_INPUTTERMINAL 0
+/// Playback output terminal ID.
+#define AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL 1
+/// Playback feature unit ID.
+#define AUDDLoopRecDriverDescriptors_FEATUREUNIT 2
+/// Record input terminal ID.
+#define AUDDLoopRecDriverDescriptors_INPUTTERMINAL_REC 3
+/// Record output terminal ID.
+#define AUDDLoopRecDriverDescriptors_OUTPUTTERMINAL_REC 4
+/// Record feature unit ID
+#define AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC 5
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors auddLoopRecDriverDescriptors;
+
+#endif //#ifndef AUDDLOOPRECDESCRIPTORS_H
+
diff --git a/usb/device/audio-looprec/audio-looprec.dir b/usb/device/audio-looprec/audio-looprec.dir new file mode 100644 index 0000000..bbd6c6a --- /dev/null +++ b/usb/device/audio-looprec/audio-looprec.dir @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB Audio
+/// Class device - USB audio-looprec demo, to implement an USB desktop speaker
+/// which echos audio stream back to host.
+///
+/// !!!Contents
+/// There are two things for the implement of the audio-speaker device driver:
+/// - Implement the audio-looprec driver structs and functions for the device,
+/// to initialize, to handle audio class specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the audio-speaker device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the device as a USB audio "desktop speaker" device.
+///
+/// This project is simply addon to the audio speaker demo. For more
+/// information, please refer to "USB Audio Speaker Device".
+//------------------------------------------------------------------------------
\ No newline at end of file diff --git a/usb/device/audio-speaker/AUDDSpeakerChannel.c b/usb/device/audio-speaker/AUDDSpeakerChannel.c new file mode 100644 index 0000000..30f39c5 --- /dev/null +++ b/usb/device/audio-speaker/AUDDSpeakerChannel.c @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: AUDDSpeakerChannel implementation
+
+ About: Purpose
+ Implementation of the AUDDSpeakerChannel functions.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "AUDDSpeakerChannel.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+// Callbacks
+//------------------------------------------------------------------------------
+/*
+ Function: AUDDSpeakerChannel_MuteChanged
+ Callback triggered when the mute status of a channel changes. This is
+ a default implementation which does nothing and must be overriden.
+
+ Parameters:
+ channel - Pointer to a AUDDSpeakerChannel instance.
+ muted - New mute status.
+*/
+//__attribute__ ((weak)) void AUDDSpeakerChannel_MuteChanged(
+// AUDDSpeakerChannel *channel,
+// unsigned char muted)
+//{
+// TRACE_DEBUG("MuteChanged(%d, %d) ", channel->number, muted);
+//}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the member variables of an AUDDSpeakerChannel object to the
+/// given values.
+/// \param channel Pointer to an AUDDSpeakerChannel instance.
+/// \param number Channel number in the audio function.
+/// \param muted Indicates if the channel is muted.
+//------------------------------------------------------------------------------
+void AUDDSpeakerChannel_Initialize(AUDDSpeakerChannel *channel,
+ unsigned char number,
+ unsigned char muted)
+{
+ channel->number = number;
+ channel->muted = muted;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the number of a channel.
+/// \param channel Pointer to an AUDDSpeakerChannel instance.
+/// \return Channel number.
+//------------------------------------------------------------------------------
+unsigned char AUDDSpeakerChannel_GetNumber(const AUDDSpeakerChannel *channel)
+{
+ return channel->number;
+}
+
+//------------------------------------------------------------------------------
+/// Mutes the given channel and triggers the MuteChanged callback if
+/// necessary.
+/// \param channel Pointer to an AUDDSpeakerChannelInstance.
+//------------------------------------------------------------------------------
+void AUDDSpeakerChannel_Mute(AUDDSpeakerChannel *channel)
+{
+ if (!channel->muted) {
+
+ channel->muted = 1;
+ AUDDSpeakerChannel_MuteChanged(channel, 1);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Unmutes the given channel and triggers the MuteChanged callback if
+/// necessary.
+/// \param channel Pointer to an AUDDSpeakerChannelInstance.
+//------------------------------------------------------------------------------
+void AUDDSpeakerChannel_Unmute(AUDDSpeakerChannel *channel)
+{
+ if (channel->muted) {
+
+ channel->muted = 0;
+ AUDDSpeakerChannel_MuteChanged(channel, 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Indicates if the given channel is currently muted or not.
+/// \param channel Pointer an AUDDSpeakerChannel instance.
+/// \return 1 if the channel is muted; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char AUDDSpeakerChannel_IsMuted(const AUDDSpeakerChannel *channel)
+{
+ return channel->muted;
+}
+
diff --git a/usb/device/audio-speaker/AUDDSpeakerChannel.h b/usb/device/audio-speaker/AUDDSpeakerChannel.h new file mode 100644 index 0000000..5eeca7e --- /dev/null +++ b/usb/device/audio-speaker/AUDDSpeakerChannel.h @@ -0,0 +1,92 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !Purpose
+
+ Manipulation of the channels of an USB audio speaker device.
+
+ !Usage
+
+ -# Initialize a AUDDSpeakerChannel instance using
+ AUDDSpeakerChannel_Initialize.
+ -# Retrieves the current status of a channel with the
+ AUDDSpeakerChannel_IsMuted method.
+ -# Re-implement the AUDDSpeakerChannel_MuteChanged callback to get
+ notified when the status of a channel changes.
+*/
+
+#ifndef AUDDSPEAKERCHANNEL_H
+#define AUDDSPEAKERCHANNEL_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Modelizes a channel of an USB audio speaker device.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Zero-based channel number in the audio function.
+ unsigned char number;
+ /// Indicates if the channel is currently muted.
+ unsigned char muted;
+
+} AUDDSpeakerChannel;
+
+//------------------------------------------------------------------------------
+// Callbacks
+//------------------------------------------------------------------------------
+
+extern void AUDDSpeakerChannel_MuteChanged(AUDDSpeakerChannel *channel,
+ unsigned char muted);
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void AUDDSpeakerChannel_Initialize(AUDDSpeakerChannel *channel,
+ unsigned char number,
+ unsigned char muted);
+
+extern unsigned char AUDDSpeakerChannel_GetNumber(
+ const AUDDSpeakerChannel *channel);
+
+extern void AUDDSpeakerChannel_Mute(AUDDSpeakerChannel *channel);
+
+extern void AUDDSpeakerChannel_Unmute(AUDDSpeakerChannel *channel);
+
+extern unsigned char AUDDSpeakerChannel_IsMuted(
+ const AUDDSpeakerChannel *channel);
+
+#endif //#ifndef AUDDSPEAKERCHANNEL_H
+
diff --git a/usb/device/audio-speaker/AUDDSpeakerDriver.c b/usb/device/audio-speaker/AUDDSpeakerDriver.c new file mode 100644 index 0000000..7ca58bd --- /dev/null +++ b/usb/device/audio-speaker/AUDDSpeakerDriver.c @@ -0,0 +1,378 @@ +/* ----------------------------------------------------------------------------
+ * 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 "AUDDSpeakerDriver.h"
+#include "AUDDSpeakerDriverDescriptors.h"
+#include "AUDDSpeakerChannel.h"
+#include <utility/trace.h>
+#include <utility/led.h>
+#include <usb/common/audio/AUDGenericRequest.h>
+#include <usb/common/audio/AUDFeatureUnitRequest.h>
+#include <usb/device/core/USBDDriver.h>
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Audio speaker driver internal state.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// USB device driver instance.
+ USBDDriver usbdDriver;
+ /// List of AUDDSpeakerChannel instances for playback.
+ AUDDSpeakerChannel channels[AUDDSpeakerDriver_NUMCHANNELS+1];
+
+} AUDDSpeakerDriver;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Global USB audio speaker driver instance.
+static AUDDSpeakerDriver auddSpeakerDriver;
+/// Array for storing the current setting of each interface.
+static unsigned char auddSpeakerDriverInterfaces[2];
+/// Intermediate storage variable for the mute status of a channel.
+static unsigned char muted;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Callback triggered after the new mute status of a channel has been read
+/// by AUDDSpeakerDriver_SetFeatureCurrentValue. Changes the mute status
+/// of the given channel accordingly.
+/// \param channel Number of the channel whose mute status has changed.
+//------------------------------------------------------------------------------
+static void AUDDSpeakerDriver_MuteReceived(unsigned int channel)
+{
+ if (muted) {
+
+ AUDDSpeakerChannel_Mute(&(auddSpeakerDriver.channels[channel]));
+ }
+ else {
+
+ AUDDSpeakerChannel_Unmute(&(auddSpeakerDriver.channels[channel]));
+ }
+
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sets the current value of a particular Feature control of a channel.
+/// \param entity Entity number.
+/// \param channel Channel number.
+/// \param control Control selector value (see TODO).
+/// \param length Length of the data containing the new value.
+//------------------------------------------------------------------------------
+static void AUDDSpeakerDriver_SetFeatureCurrentValue(unsigned char entity,
+ unsigned char channel,
+ unsigned char control,
+ unsigned short length)
+{
+ TRACE_INFO_WP("sFeature ");
+ TRACE_DEBUG("\b(E%d, CS%d, CN%d, L%d) ",
+ entity, control, channel, length);
+
+ // Check the the requested control is supported
+ // Control/channel combination not supported
+ if ((control == AUDFeatureUnitRequest_MUTE)
+ && (channel < (AUDDSpeakerDriver_NUMCHANNELS+1))
+ && (length == 1)) {
+
+ unsigned int argument = channel; // Avoids compiler warning
+ USBD_Read(0, // Endpoint #0
+ &muted,
+ sizeof(muted),
+ (TransferCallback) AUDDSpeakerDriver_MuteReceived,
+ (void *) argument);
+ }
+ // Control/channel combination not supported
+ else {
+
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current value of a particular channel Feature to the USB host.
+/// \param entity Entity number.
+/// \param channel Channel number.
+/// \param control Control selector value (see TODO).
+/// \param length Length of the data to return.
+//------------------------------------------------------------------------------
+static void AUDDSpeakerDriver_GetFeatureCurrentValue(unsigned char entity,
+ unsigned char channel,
+ unsigned char control,
+ unsigned char length)
+{
+ TRACE_INFO_WP("gFeature ");
+ TRACE_DEBUG("\b(CS%d, CN%d, L%d) ", control, channel, length);
+
+ // Check that the requested control is supported
+ // Master channel mute control
+ if ((control == AUDFeatureUnitRequest_MUTE)
+ && (channel < (AUDDSpeakerDriver_NUMCHANNELS+1))
+ && (length == 1)) {
+
+ muted = AUDDSpeakerChannel_IsMuted(&(auddSpeakerDriver.channels[channel]));
+ USBD_Write(0, &muted, sizeof(muted), 0, 0);
+ }
+ else {
+
+ USBD_Stall(0);
+ }
+}
+
+///*
+// Function: AUDDSpeakerDriver_SetInterface
+// Changes the current active alternate setting of the given interface.
+//
+// Parameters:
+//
+//*/
+//TRACE_DEBUG_M("SetInterface(%d,%d) ", setup->wIndex, setup->wValue);
+//
+// /* Check that interface is AudioStreaming OUT */
+// if (setup->wIndex == INTERFACE_ID_AUDIOSTREAMING_OUT) {
+//
+// /* Check desired alternate setting */
+// switch (setup->wValue) {
+// case 0:
+// case 1:
+// if (speakerDriver->isOutStreamEnabled != setup->wValue) {
+//
+// speakerDriver->isOutStreamEnabled = setup->wValue;
+// SPK_OutStreamStatusChanged(speakerDriver);
+// LED_SetGlowing(LED_OTHER, setup->wValue);
+// }
+// USB_SendZLP0(usbDriver, 0, 0);
+// break;
+//
+// default:
+// USB_Stall(usbDriver, 0);
+// }
+// }
+// else {
+//
+// USB_Stall(usbDriver, 0);
+// }
+//
+
+//------------------------------------------------------------------------------
+// Callback re-implementation
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Triggered when the USB host emits a new SETUP request. The request is
+/// forward to <AUDDSpeakerDriver_RequestHandler>.
+/// \param request Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ AUDDSpeakerDriver_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)
+{
+ if ((interface == AUDDSpeakerDriverDescriptors_STREAMING)
+ && (setting == 0)) {
+
+ LED_Clear(USBD_LEDOTHER);
+ }
+ else {
+
+ LED_Set(USBD_LEDOTHER);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes an USB audio speaker device driver, as well as the underlying
+/// USB controller.
+//------------------------------------------------------------------------------
+void AUDDSpeakerDriver_Initialize()
+{
+ // Initialize speaker channels
+ AUDDSpeakerChannel_Initialize(&(auddSpeakerDriver.channels[0]),
+ AUDDSpeakerDriver_MASTERCHANNEL,
+ 0);
+ AUDDSpeakerChannel_Initialize(&(auddSpeakerDriver.channels[1]),
+ AUDDSpeakerDriver_LEFTCHANNEL,
+ 0);
+ AUDDSpeakerChannel_Initialize(&(auddSpeakerDriver.channels[2]),
+ AUDDSpeakerDriver_RIGHTCHANNEL,
+ 0);
+
+ // Initialize the USB driver
+ USBDDriver_Initialize(&(auddSpeakerDriver.usbdDriver),
+ &auddSpeakerDriverDescriptors,
+ auddSpeakerDriverInterfaces);
+ USBD_Init();
+
+ // Initialize the third LED to indicate when the audio interface is active
+ LED_Configure(USBD_LEDOTHER);
+}
+
+//------------------------------------------------------------------------------
+/// Handles audio-specific USB requests sent by the host, and forwards
+/// standard ones to the USB device driver.
+/// \param request Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+void AUDDSpeakerDriver_RequestHandler(const USBGenericRequest *request)
+{
+ unsigned char entity;
+ unsigned char interface;
+
+ TRACE_INFO_WP("NewReq ");
+
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ // Check if the request is supported
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case AUDGenericRequest_SETCUR:
+ TRACE_INFO_WP(
+ "sCur(0x%04X) ",
+ USBGenericRequest_GetIndex(request));
+
+ // Check the target interface and entity
+ entity = AUDGenericRequest_GetEntity(request);
+ interface = AUDGenericRequest_GetInterface(request);
+ if ((entity == AUDDSpeakerDriverDescriptors_FEATUREUNIT)
+ && (interface == AUDDSpeakerDriverDescriptors_CONTROL)) {
+
+ AUDDSpeakerDriver_SetFeatureCurrentValue(
+ entity,
+ AUDFeatureUnitRequest_GetChannel(request),
+ AUDFeatureUnitRequest_GetControl(request),
+ USBGenericRequest_GetLength(request));
+ }
+ else {
+
+ TRACE_WARNING(
+ "AUDDSpeakerDriver_RequestHandler: Unsupported entity/interface combination (0x%04X)\n\r",
+ USBGenericRequest_GetIndex(request));
+ USBD_Stall(0);
+ }
+ break;
+
+ case AUDGenericRequest_GETCUR:
+ TRACE_INFO_WP(
+ "gCur(0x%04X) ",
+ USBGenericRequest_GetIndex(request));
+
+ // Check the target interface and entity
+ entity = AUDGenericRequest_GetEntity(request);
+ interface = AUDGenericRequest_GetInterface(request);
+ if ((entity == AUDDSpeakerDriverDescriptors_FEATUREUNIT)
+ && (interface == AUDDSpeakerDriverDescriptors_CONTROL)) {
+
+ AUDDSpeakerDriver_GetFeatureCurrentValue(
+ entity,
+ AUDFeatureUnitRequest_GetChannel(request),
+ AUDFeatureUnitRequest_GetControl(request),
+ USBGenericRequest_GetLength(request));
+ }
+ else {
+
+ TRACE_WARNING(
+ "AUDDSpeakerDriver_RequestHandler: Unsupported entity/interface combination (0x%04X)\n\r",
+ USBGenericRequest_GetIndex(request));
+ USBD_Stall(0);
+ }
+ break;
+
+ default:
+
+ TRACE_WARNING(
+ "AUDDSpeakerDriver_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) {
+
+ // Forward request to the standard handler
+ USBDDriver_RequestHandler(&(auddSpeakerDriver.usbdDriver), request);
+ }
+ // Unsupported request type
+ else {
+
+ TRACE_WARNING(
+ "AUDDSpeakerDriver_RequestHandler: Unsupported request type (%d)\n\r",
+ USBGenericRequest_GetType(request));
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reads incoming audio data sent by the USB host into the provided
+/// buffer. When the transfer is complete, an optional callback function is
+/// invoked.
+/// \param buffer Pointer to the data storage buffer.
+/// \param length Size of the buffer in bytes.
+/// \param callback Optional callback function.
+/// \param argument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the transfer is started successfully;
+/// otherwise an error code.
+//------------------------------------------------------------------------------
+unsigned char AUDDSpeakerDriver_Read(void *buffer,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Read(AUDDSpeakerDriverDescriptors_DATAOUT,
+ buffer,
+ length,
+ callback,
+ argument);
+}
+
diff --git a/usb/device/audio-speaker/AUDDSpeakerDriver.h b/usb/device/audio-speaker/AUDDSpeakerDriver.h new file mode 100644 index 0000000..133d6df --- /dev/null +++ b/usb/device/audio-speaker/AUDDSpeakerDriver.h @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !Purpose
+
+ Definition of a USB Audio Speaker Driver with two playback channels and one
+ record channel.
+
+ !Usage
+
+ -# Enable and setup USB related pins (see pio & board.h).
+ -# Configure the USB Audio Speaker driver using
+ AUDDSpeakerDriver_Initialize
+ -# To get %audio stream frames from host, use
+ AUDDSpeakerDriver_Read
+ -# To send %audio sampling stream to host, use
+ AUDDSpeakerDriver_Write
+
+*/
+
+#ifndef AUDDSPEAKERDRIVER_H
+#define AUDDSPEAKERDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker stream information"
+///
+/// This page lists codes for USB Audio Speaker stream information.
+///
+/// !Code
+/// - AUDDSpeakerDriver_SAMPLERATE
+/// - AUDDSpeakerDriver_NUMCHANNELS
+/// - AUDDSpeakerDriver_BYTESPERSAMPLE
+/// - AUDDSpeakerDriver_BITSPERSAMPLE
+/// - AUDDSpeakerDriver_SAMPLESPERFRAME
+/// - AUDDSpeakerDriver_BYTESPERFRAME
+
+#if defined(at91sam7s)
+ /// Sample rate in Hz.
+ #define AUDDSpeakerDriver_SAMPLERATE 32000
+ /// Number of channels in audio stream.
+ #define AUDDSpeakerDriver_NUMCHANNELS 1
+ /// Number of bytes in one sample.
+ #define AUDDSpeakerDriver_BYTESPERSAMPLE 2
+#else
+ /// Sample rate in Hz.
+ #define AUDDSpeakerDriver_SAMPLERATE 48000
+ /// Number of channels in audio stream.
+ #define AUDDSpeakerDriver_NUMCHANNELS 2
+ /// Number of bytes in one sample.
+ #define AUDDSpeakerDriver_BYTESPERSAMPLE 2
+#endif
+/// Number of bits in one sample.
+#define AUDDSpeakerDriver_BITSPERSAMPLE (AUDDSpeakerDriver_BYTESPERSAMPLE * 8)
+/// Number of bytes in one USB subframe.
+#define AUDDSpeakerDriver_BYTESPERSUBFRAME (AUDDSpeakerDriver_NUMCHANNELS * \
+ AUDDSpeakerDriver_BYTESPERSAMPLE)
+/// Number of samples in one USB frame.
+#define AUDDSpeakerDriver_SAMPLESPERFRAME (AUDDSpeakerDriver_SAMPLERATE / 1000 \
+ * AUDDSpeakerDriver_NUMCHANNELS)
+/// Number of bytes in one USB frame.
+#define AUDDSpeakerDriver_BYTESPERFRAME (AUDDSpeakerDriver_SAMPLESPERFRAME * \
+ AUDDSpeakerDriver_BYTESPERSAMPLE)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Channel Numbers"
+///
+/// This page lists codes for USB Audio Speaker channel numbers.
+///
+/// !Playback channel numbers
+/// - AUDDSpeakerDriver_MASTERCHANNEL
+/// - AUDDSpeakerDriver_LEFTCHANNEL
+/// - AUDDSpeakerDriver_RIGHTCHANNEL
+///
+/// !Record channel number
+/// - AUDDSpeakerDriver_RECCHANNEL
+
+/// Master channel of playback.
+#define AUDDSpeakerDriver_MASTERCHANNEL 0
+/// Front left channel of playback.
+#define AUDDSpeakerDriver_LEFTCHANNEL 1
+/// Front right channel of playback.
+#define AUDDSpeakerDriver_RIGHTCHANNEL 2
+/// Channel of record.
+#define AUDDSpeakerDriver_RECCHANNEL 0
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void AUDDSpeakerDriver_Initialize();
+
+extern void AUDDSpeakerDriver_RequestHandler(const USBGenericRequest *request);
+
+extern unsigned char AUDDSpeakerDriver_Read(void *buffer,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument);
+
+#endif //#ifndef AUDDSPEAKERDRIVER_H
+
+//#ifndef SPEAKER_DRIVER_H
+//#define SPEAKER_DRIVER_H
+//
+////------------------------------------------------------------------------------
+//// Definitions
+////------------------------------------------------------------------------------
+//
+///*! Sampling frequency in Hz */
+//#define SPEAKER_SAMPLERATE 48000
+///*! Number of samples in one isochronous packet (1ms frame) */
+//#define SPEAKER_SAMPLESPERPACKET (SPEAKER_SAMPLERATE / 1000)
+///*! Size of one sample (in bytes) */
+//#define SPEAKER_SAMPLESIZE 2
+///*! Number of channels */
+//#define SPEAKER_NUMCHANNELS 2
+///*! Size of one frame (number of bytes sent for one sample on all channels) */
+//#define SPEAKER_FRAMESIZE (SPEAKER_SAMPLESIZE * SPEAKER_NUMCHANNELS)
+///*! Required bit rate given the sample frequency, sample size and number of
+// channels. */
+//#define SPEAKER_BITRATE (SPEAKER_SAMPLERATE * SPEAKER_FRAMESIZE)
+///*! Size of one isochronous packet */
+//#define SPEAKER_PACKETSIZE (SPEAKER_SAMPLESPERPACKET * SPEAKER_FRAMESIZE)
+//
+////------------------------------------------------------------------------------
+//// Structures
+////------------------------------------------------------------------------------
+///*!
+// Holds the speaker driver state.
+// */
+//typedef struct {
+//
+// S_std_class standardDriver;
+//
+// unsigned char isOutStreamEnabled;
+// unsigned char isChannelMuted[SPEAKER_NUMCHANNELS+1];
+//
+// Callback_f outStreamStatusChanged;
+// Callback_f outStreamMuteChanged;
+//
+//} __attribute__((packed)) S_speaker;
+//
+////------------------------------------------------------------------------------
+//// Exported functions
+////------------------------------------------------------------------------------
+//
+//extern void SPK_Init(S_speaker *speakerDriver, const S_usb *usbDriver);
+//extern void SPK_SetCallbacks(S_speaker *speakerDriver,
+// Callback_f outStreamStatusChanged,
+// Callback_f outStreamMuteChanged);
+//extern void SPK_RequestHandler(S_speaker *speakerDriver);
+//extern char SPK_Read(S_speaker *speakerDriver,
+// void *buffer,
+// unsigned int length,
+// Callback_f callback,
+// void *argument);
+//
+//#endif //#ifndef SPEAKER_DRIVER_H
+//
diff --git a/usb/device/audio-speaker/AUDDSpeakerDriverDescriptors.c b/usb/device/audio-speaker/AUDDSpeakerDriverDescriptors.c new file mode 100644 index 0000000..2501120 --- /dev/null +++ b/usb/device/audio-speaker/AUDDSpeakerDriverDescriptors.c @@ -0,0 +1,620 @@ +/* ----------------------------------------------------------------------------
+ * 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 "AUDDSpeakerDriverDescriptors.h"
+#include "AUDDSpeakerDriver.h"
+#include <board.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/audio/AUDGenericDescriptor.h>
+#include <usb/common/audio/AUDDeviceDescriptor.h>
+#include <usb/common/audio/AUDControlInterfaceDescriptor.h>
+#include <usb/common/audio/AUDStreamingInterfaceDescriptor.h>
+#include <usb/common/audio/AUDEndpointDescriptor.h>
+#include <usb/common/audio/AUDDataEndpointDescriptor.h>
+#include <usb/common/audio/AUDFormatTypeOneDescriptor.h>
+#include <usb/common/audio/AUDHeaderDescriptor.h>
+#include <usb/common/audio/AUDFeatureUnitDescriptor.h>
+#include <usb/common/audio/AUDInputTerminalDescriptor.h>
+#include <usb/common/audio/AUDOutputTerminalDescriptor.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Device Codes"
+///
+/// This page lists the %device IDs and release number of the USB Audio Speaker
+/// %device.
+///
+/// !Codes
+/// - AUDDSpeakerDriverDescriptors_VENDORID
+/// - AUDDSpeakerDriverDescriptors_PRODUCTID
+/// - AUDDSpeakerDriverDescriptors_RELEASE
+
+/// Device vendor ID.
+#define AUDDSpeakerDriverDescriptors_VENDORID 0x03EB
+/// Device product ID.
+#define AUDDSpeakerDriverDescriptors_PRODUCTID 0x6128
+/// Device release number in BCD format.
+#define AUDDSpeakerDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Audio control header descriptor with one slave interface.
+//------------------------------------------------------------------------------
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Header descriptor with 1 interface.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Header descriptor.
+ AUDHeaderDescriptor header;
+ /// Id of the first grouped interface - Speaker.
+ unsigned char bInterface0;
+
+} __attribute__ ((packed)) AUDHeaderDescriptor1; // GCC
+
+//------------------------------------------------------------------------------
+/// Feature unit descriptor with 3 channel controls (master, right, left).
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Feature unit descriptor.
+ AUDFeatureUnitDescriptor feature;
+ /// Available controls for each channel.
+ unsigned char bmaControls[3];
+ /// Index of a string descriptor for the feature unit.
+ unsigned char iFeature;
+
+} __attribute__ ((packed)) AUDFeatureUnitDescriptor3; // GCC
+
+//------------------------------------------------------------------------------
+/// List of descriptors for detailling the audio control interface of a
+/// device using a USB audio speaker driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Header descriptor (with one slave interface).
+ AUDHeaderDescriptor1 header;
+ /// Input terminal descriptor.
+ AUDInputTerminalDescriptor input;
+ /// Output terminal descriptor.
+ AUDOutputTerminalDescriptor output;
+ /// Feature unit descriptor.
+ AUDFeatureUnitDescriptor3 feature;
+
+} __attribute__ ((packed)) AUDDSpeakerDriverAudioControlDescriptors; // GCC
+
+//------------------------------------------------------------------------------
+/// Format type I descriptor with one discrete sampling frequency.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Format type I descriptor.
+ AUDFormatTypeOneDescriptor formatType;
+ /// Sampling frequency in Hz.
+ unsigned char tSamFreq[3];
+
+} __attribute__ ((packed)) AUDFormatTypeOneDescriptor1; // GCC
+
+//------------------------------------------------------------------------------
+/// Holds a list of descriptors returned as part of the configuration of
+/// a USB audio speaker device.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration.
+ USBConfigurationDescriptor configuration;
+ /// Audio control interface.
+ USBInterfaceDescriptor control;
+ /// Descriptors for the audio control interface.
+ AUDDSpeakerDriverAudioControlDescriptors controlDescriptors;
+ //- AUDIO OUT
+ /// Streaming out interface descriptor (with no endpoint, required).
+ USBInterfaceDescriptor streamingOutNoIsochronous;
+ /// Streaming out interface descriptor.
+ USBInterfaceDescriptor streamingOut;
+ /// Audio class descriptor for the streaming out interface.
+ AUDStreamingInterfaceDescriptor streamingOutClass;
+ /// Stream format descriptor.
+ AUDFormatTypeOneDescriptor1 streamingOutFormatType;
+ /// Streaming out endpoint descriptor.
+ AUDEndpointDescriptor streamingOutEndpoint;
+ /// Audio class descriptor for the streaming out endpoint.
+ AUDDataEndpointDescriptor streamingOutDataEndpoint;
+
+} __attribute__ ((packed)) AUDDSpeakerDriverConfigurationDescriptors; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Device descriptor for a USB audio speaker driver.
+const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ AUDDeviceDescriptor_CLASS,
+ AUDDeviceDescriptor_SUBCLASS,
+ AUDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ AUDDSpeakerDriverDescriptors_VENDORID,
+ AUDDSpeakerDriverDescriptors_PRODUCTID,
+ AUDDSpeakerDriverDescriptors_RELEASE,
+ 1, // Manufacturer string descriptor index
+ 2, // Product string descriptor index
+ 3, // Index of serial number string descriptor
+ 1 // One possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// USB device qualifier descriptor.
+const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ AUDDeviceDescriptor_CLASS,
+ AUDDeviceDescriptor_SUBCLASS,
+ AUDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+#endif
+
+/// Configuration descriptors for a USB audio speaker driver.
+const AUDDSpeakerDriverConfigurationDescriptors fsConfigurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(AUDDSpeakerDriverConfigurationDescriptors),
+ 2, // This configuration has 2 interfaces
+ 1, // This is configuration #1
+ 0, // No string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Audio control interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDSpeakerDriverDescriptors_CONTROL,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoint
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio control interface descriptors
+ {
+ // Header descriptor
+ {
+ {
+ sizeof(AUDHeaderDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_HEADER,
+ AUDHeaderDescriptor_AUD1_00,
+ sizeof(AUDDSpeakerDriverAudioControlDescriptors),
+ 1 // One streaming interface
+ },
+ AUDDSpeakerDriverDescriptors_STREAMING
+ },
+ // Input terminal descriptor
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ AUDInputTerminalDescriptor_USBSTREAMING,
+ AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL,
+ AUDDSpeakerDriver_NUMCHANNELS,
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL,
+ AUDOutputTerminalDescriptor_SPEAKER,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ AUDDSpeakerDriverDescriptors_FEATUREUNIT,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDSpeakerDriverDescriptors_FEATUREUNIT,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ 1, // 1 byte per channel for controls
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Master channel controls
+ 0, // Right channel controls
+ 0 // Left channel controls
+ },
+ 0 // No string descriptor
+ }
+ },
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDSpeakerDriverDescriptors_STREAMING,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDSpeakerDriverDescriptors_STREAMING,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDSpeakerDriver_NUMCHANNELS,
+ AUDDSpeakerDriver_BYTESPERSAMPLE,
+ AUDDSpeakerDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDSpeakerDriver_SAMPLERATE & 0xFF,
+ (AUDDSpeakerDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDSpeakerDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ AUDDSpeakerDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(AUDDSpeakerDriverDescriptors_DATAOUT),
+ AUDDSpeakerDriverDescriptors_FS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ }
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Configuration descriptors for a USB audio speaker driver.
+const AUDDSpeakerDriverConfigurationDescriptors hsConfigurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(AUDDSpeakerDriverConfigurationDescriptors),
+ 2, // This configuration has 2 interfaces
+ 1, // This is configuration #1
+ 0, // No string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Audio control interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDSpeakerDriverDescriptors_CONTROL,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoint
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio control interface descriptors
+ {
+ // Header descriptor
+ {
+ {
+ sizeof(AUDHeaderDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_HEADER,
+ AUDHeaderDescriptor_AUD1_00,
+ sizeof(AUDDSpeakerDriverAudioControlDescriptors),
+ 1 // One streaming interface
+ },
+ AUDDSpeakerDriverDescriptors_STREAMING
+ },
+ // Input terminal descriptor
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ AUDInputTerminalDescriptor_USBSTREAMING,
+ AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL,
+ AUDDSpeakerDriver_NUMCHANNELS,
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL,
+ AUDOutputTerminalDescriptor_SPEAKER,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ AUDDSpeakerDriverDescriptors_FEATUREUNIT,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDDSpeakerDriverDescriptors_FEATUREUNIT,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ 1, // 1 byte per channel for controls
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Master channel controls
+ 0, // Right channel controls
+ 0 // Left channel controls
+ },
+ 0 // No string descriptor
+ }
+ },
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDSpeakerDriverDescriptors_STREAMING,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDDSpeakerDriverDescriptors_STREAMING,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDDSpeakerDriverDescriptors_INPUTTERMINAL,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDDSpeakerDriver_NUMCHANNELS,
+ AUDDSpeakerDriver_BYTESPERSAMPLE,
+ AUDDSpeakerDriver_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDDSpeakerDriver_SAMPLERATE & 0xFF,
+ (AUDDSpeakerDriver_SAMPLERATE >> 8) & 0xFF,
+ (AUDDSpeakerDriver_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ AUDDSpeakerDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(AUDDSpeakerDriverDescriptors_DATAOUT),
+ AUDDSpeakerDriverDescriptors_HS_INTERVAL, // Polling interval = 1 ms
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ }
+};
+#endif // defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// 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(15),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('k'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('k'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('r')
+};
+
+/// Product serial number.
+const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(4),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3')
+};
+
+/// Array of pointers to the four string descriptors.
+const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+/// List of descriptors required by an USB audio speaker device driver.
+const USBDDriverDescriptors auddSpeakerDriverDescriptors = {
+
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &fsConfigurationDescriptors,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &hsConfigurationDescriptors,
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &hsConfigurationDescriptors,
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &hsConfigurationDescriptors,
+#else
+ 0, 0, 0, 0, 0, 0,
+#endif
+ stringDescriptors,
+ 4 // Number of string descriptors
+};
+
diff --git a/usb/device/audio-speaker/AUDDSpeakerDriverDescriptors.h b/usb/device/audio-speaker/AUDDSpeakerDriverDescriptors.h new file mode 100644 index 0000000..7bc7352 --- /dev/null +++ b/usb/device/audio-speaker/AUDDSpeakerDriverDescriptors.h @@ -0,0 +1,146 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Declaration of the descriptors required by a USB audio speaker driver.
+
+ !!!Usage
+
+ -# Initialize a USBDDriver instance using the
+ auddSpeakerDriverDescriptors list.
+*/
+
+#ifndef AUDDSPEAKERDRIVERDESCRIPTORS_H
+#define AUDDSPEAKERDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Endpoint Numbers"
+///
+/// This page lists the endpoint number settings for USB Audio Speaker device.
+///
+/// !Endpoints
+/// - AUDDSpeakerDriverDescriptors_DATAOUT
+/// - AUDDSpeakerDriverDescriptors_DATAIN
+/// - AUDDSpeakerDriverDescriptors_FS_INTERVAL
+/// - AUDDSpeakerDriverDescriptors_HS_INTERVAL
+///
+/// \note for UDP, uses IN EPs that support double buffer; for UDPHS, uses
+/// IN EPs that support DMA and High bandwidth.
+
+#if defined(at91sam7s) || defined(at91sam9xe)
+ /// Data out endpoint number.
+ #define AUDDSpeakerDriverDescriptors_DATAOUT 0x01
+ /// Data in endpoint number.
+ #define AUDDSpeakerDriverDescriptors_DATAIN 0x02
+#elif defined(CHIP_USB_UDP)
+ /// Data out endpoint number.
+ #define AUDDSpeakerDriverDescriptors_DATAOUT 0x04
+ /// Data in endpoint number.
+ #define AUDDSpeakerDriverDescriptors_DATAIN 0x05
+#else
+ /// Data out endpoint number.
+ #define AUDDSpeakerDriverDescriptors_DATAOUT 0x05
+ /// Data in endpoint number.
+ #define AUDDSpeakerDriverDescriptors_DATAIN 0x06
+#endif
+
+/// Endpoint polling interval 2^(x-1) * 125us
+#define AUDDSpeakerDriverDescriptors_HS_INTERVAL 0x04
+/// Endpoint polling interval 2^(x-1) * ms
+#define AUDDSpeakerDriverDescriptors_FS_INTERVAL 0x01
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Interface IDs"
+///
+/// This page lists the interface numbers for USB Audio Speaker device.
+///
+/// !Interfaces
+/// - AUDDSpeakerDriverDescriptors_CONTROL
+/// - AUDDSpeakerDriverDescriptors_STREAMING
+/// - AUDDSpeakerDriverDescriptors_STREAMINGIN
+
+/// Audio control interface ID.
+#define AUDDSpeakerDriverDescriptors_CONTROL 0
+/// Audio streaming interface ID (OUT, for playback).
+#define AUDDSpeakerDriverDescriptors_STREAMING 1
+/// Audio streaming interface ID (IN, for record).
+#define AUDDSpeakerDriverDescriptors_STREAMINGIN 2
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Audio Speaker Entity IDs"
+///
+/// This page lists the entity IDs for USB Audio Speaker device.
+///
+/// !Entities
+/// - AUDDSpeakerDriverDescriptors_INPUTTERMINAL
+/// - AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL
+/// - AUDDSpeakerDriverDescriptors_FEATUREUNIT
+/// - AUDDSpeakerDriverDescriptors_INPUTTERMINAL_REC
+/// - AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL_REC
+/// - AUDDSpeakerDriverDescriptors_FEATUREUNIT_REC
+
+/// Playback input terminal ID.
+#define AUDDSpeakerDriverDescriptors_INPUTTERMINAL 0
+/// Playback output terminal ID.
+#define AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL 1
+/// Playback feature unit ID.
+#define AUDDSpeakerDriverDescriptors_FEATUREUNIT 2
+/// Record input terminal ID.
+#define AUDDSpeakerDriverDescriptors_INPUTTERMINAL_REC 3
+/// Record output terminal ID.
+#define AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL_REC 4
+/// Record feature unit ID
+#define AUDDSpeakerDriverDescriptors_FEATUREUNIT_REC 5
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors auddSpeakerDriverDescriptors;
+
+#endif //#ifndef AUDDSPEAKERDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/audio-speaker/USBAudioSpeaker.png b/usb/device/audio-speaker/USBAudioSpeaker.png Binary files differnew file mode 100644 index 0000000..bcae300 --- /dev/null +++ b/usb/device/audio-speaker/USBAudioSpeaker.png diff --git a/usb/device/audio-speaker/USBAudioSpeakerDescriptors.png b/usb/device/audio-speaker/USBAudioSpeakerDescriptors.png Binary files differnew file mode 100644 index 0000000..251a2d1 --- /dev/null +++ b/usb/device/audio-speaker/USBAudioSpeakerDescriptors.png diff --git a/usb/device/audio-speaker/USBAudioSpeakerRecorder.png b/usb/device/audio-speaker/USBAudioSpeakerRecorder.png Binary files differnew file mode 100644 index 0000000..ddbd234 --- /dev/null +++ b/usb/device/audio-speaker/USBAudioSpeakerRecorder.png diff --git a/usb/device/audio-speaker/USBAudioSpeakerRecorderDescriptors.png b/usb/device/audio-speaker/USBAudioSpeakerRecorderDescriptors.png Binary files differnew file mode 100644 index 0000000..c5c3324 --- /dev/null +++ b/usb/device/audio-speaker/USBAudioSpeakerRecorderDescriptors.png diff --git a/usb/device/audio-speaker/audio-speaker.dir b/usb/device/audio-speaker/audio-speaker.dir new file mode 100644 index 0000000..be90df0 --- /dev/null +++ b/usb/device/audio-speaker/audio-speaker.dir @@ -0,0 +1,617 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB Audio
+/// Class device - USB audio-speaker demo, to implement an USB desktop speaker.
+///
+/// !!!Contents
+/// There are two things for the implement of the audio-speaker device driver:
+/// - Implement the audio-speaker driver structs and functions for the device,
+/// to initialize, to handle audio class specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the audio-speaker device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the device as a USB audio "desktop speaker" device.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB Audio Speaker Device".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB Audio Speaker Device"
+ This page describes how to use the USB framework to produce a USB Audio Class
+ Device driver.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/audio10.pdf">
+ Audio Device Document 1.0</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/frmts10.pdf">
+ Audio Data Formats 1.0</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/termt10.pdf">
+ Autio Terminal Types 1.0</a>
+
+ !!!Audio Speaker Driver API
+ - AUDDSpeakerDriver_Initialize
+ - AUDDSpeakerDriver_RequestHandler
+ - AUDDSpeakerDriver_Read
+
+ !!!Audio Desktop Speaker Description
+ The %device described here is a USB desktop speaker. It receives a stero
+ %audio data stream from the Host over its Audio Streaming interface. The used
+ Audio Data Format is 16-bit 48KHz 2-channel PCM (or mono 16-bit 32KHz PCM for
+ sam7s chips). The following is the internal topology of the speaker.
+
+ \image USBAudioSpeaker.png "USB Desktop Speaker Topology"
+
+ The %audio function contains one Onput Terminal that represents the actual
+ speaker output element, followed by the Digital-to-Analog Converter (DAC).
+ The digital input stream of the host enters the %audio function through the
+ single Input %Pin of the Output terminal. There is a Feature Unit on the
+ %audio stream, to mute or unmute the speaker. The Input Terminal is the
+ representation within the %audio fucntion of the USB OUT endpoint that
+ eventually receives the %audio data stream from the Host. The internals of the
+ %audio function are presented to the Host through the (mandatory) AudioControl
+ interface wheras the USB OUT endpoint resides in the AudioStreaming interface.
+
+ !!!Descriptor Hierarchy
+ This USB Desktop Speaker %device includes the AudioControl interface
+ (interface 0) and a single AudioStreaming interface (interface 1). The
+ AudioStreaming interface features two alternate settings. The first alternate
+ setting (Alternate Setting 0) has zero bandwidth associated with it so that
+ switching to this alternate setting effectively frees all allocated bandwidth
+ on the USB for this device. Zero bandwidth is indicated by the lack of a
+ streaming endpoint. Alternate Setting 1 is the operational part of the
+ interface and it has one isochronous OUT endpoint. Figure presents the
+ descriptor hierarchy.
+
+ \image UsbAudioSpeakerDescriptors.png "USB Desktop Speaker Hierarchy"
+
+ !!!Descriptors
+ The following sections present all the descriptors that are used to describe
+ the %device.
+
+ All descriptors are combined into a list and pass to USBDDriver_Initialize
+ invoked in AUDDSpeakerDriver_Initialize.
+
+\code
+const USBDDriverDescriptors auddSpeakerDriverDescriptors;
+\endcode
+
+ !!Device Descriptor
+\code
+const USBDeviceDescriptor deviceDescriptor;
+\endcode
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x12|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x01|DEVICE descriptor (USBGenericDescriptor_DEVICE).
+|2|bcdUSB|2|0x0200|2.00 - current revision of USB specification.
+|4|bDeviceClass|1|0x00|Device defined at interface level.
+|5|bDeviceSubClass|1|0x00|Unused.
+|6|bDeviceProtocol|1|0x00|Unused.
+|7|bMaxPacketSize0|1|0x08|8 bytes (BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0)).
+|8|idVendor|2|0x03EB|Atmel Vendor ID (AUDDSpeakerDriverDescriptors_VENDORID).
+|10|idProduct|2|0x6128|Product ID (AUDDSpeakerDriverDescriptors_PRODUCTID).
+|12|bcdDevice|2|0x0100|Device Release Code\n
+ (AUDDSpeakerDriverDescriptors_RELEASE).
+|14|iManufacturer|1|0x01|Index to manufacture name in Unicode\n
+ (manufacturerDescriptor).
+|15|iProduct|1|0x02|Index to product name in Unicode (productDescriptor).
+|16|iSerialNumber|1|0x03|Index to serial number in Unicode\n
+ (serialNumberDescriptor).
+|17|bNumConfigurations|1|0x01|One configuration.
+
+ !!Configuration Descriptor
+\code
+const AUDDSpeakerDriverConfigurationDescriptors configurationDescriptors;
+\endcode
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x02|CONFIGURATION descriptor\n
+ (USBGenericDescriptor_CONFIGURATION).
+|2|wTotalLength|2|0x????|Length of the total configuration block in bytes\n
+ including this descriptor\n
+ (AUDDSpeakerDriverConfigurationDescriptors)
+|4|bNumInterfaces|1|0x02|Two interfaces.
+|5|bConfigurationValue|1|0x01|ID of this configuration.
+|6|iConfiguration|1|0x00|Unused.
+|7|bmAttributes|1|0x??|BOARD_USB_BMATTRIBUTES
+|8|bMaxPower|1|0x32|100mA Max. %power consumption.\n
+ USBConfigurationDescriptor_POWER(100)
+
+ !!AudioControl Interface Descriptor
+ The AudioControl interface describes the %device structure (%audio function
+ topology) and is used to manipulate the Audio Controls.
+
+ !Standard AC Interface Descriptor
+ The AudioControl interface has no dedicated endpoints associated with it. It
+ uses the default pipe (endpoint 0) for all communication purposes. Class-
+ specific AudioControl Requests are sent using the default pipe. There is no
+ Status Interrupt endpoint provided.
+
+ See USBInterfaceDescriptor.
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x04|INTERFACE descriptor\n
+ (USBGenericDescriptor_INTERFACE).
+|2|bInterfaceNumber|1|0x00|Index of this interface.
+|3|bAlternateSetting|1|0x00|Index of this setting.
+|4|bNumEndpoints|1|0x00|0 endpoints.
+|5|bInterfaceClass|1|0x01|AUDIO (AUDControlInterfaceDescriptor_CLASS).
+|6|bInterfaceSubClass|1|0x01|AUDIO_CONTROL\n
+ (AUDControlInterfaceDescriptor_SUBCLASS).
+|7|bInterfaceProtocol|1|0x00|Unused.
+|8|iInterface|1|0x00|Unused.
+
+ !Class-specific AC Interface Descriptor
+ The Class-specific AC interface descriptor is always headed by a Header
+ descriptor that contains general information about the AudioControl interface.
+ It contains all the pointers needed to describe the AudioInterface Collection,
+ associated with the described %audio function.
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubtype|1|0x01|HEADER subtype (AUDGenericDescriptor_HEADER).
+|3|bcdADC|2|0x0100|Revision of class specification - 1.0
+|5|wTotalLength|2|0x????|Total size of class specific descriptors\n
+ (AUDDSpeakerDriverAudioControlDescriptors).
+|7|bInCollection|1|0x01|Number of streaming interfaces.
+|8|baInterfaceNr(1)|1|0x01|AudioStreaming interface 1 belongs to this AudioControl interface.
+
+ !Input Terminal Descriptor for playback
+ This descriptor describes the Input Terminal that represents the USB pipe from
+ the Host PC. Its Output Pin is connected to the Input Pin of the Feature Unit
+ ...
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x0C|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x02|INPUT_TERMINAL subtype\n
+ (AUDGenericDescriptor_INPUTTERMINAL).
+|3|bTerminalID|1|0x00|ID of this Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL).
+|4|wTerminalType|2|0x0101|Terminal is USB stream\n
+ (AUDInputTerminalDescriptor_USBSTREAMING).
+|6|bAssocTerminal|1|0x01|Associated to Output Terminal\n
+ (AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL).
+|7|bNrChannels|1|0x02|Two channel.
+|8|wChannelConfig|2|0x0003|Left plus right front channel.
+|10|iChannelNames|1|0x00|Unused.
+|11|iTerminal|1|0x00|Unused.
+
+ !Output Terminal Descriptor for playback
+ ...
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x03|OUTPUT_TERMINAL subtype\n
+ (AUDGenericDescriptor_OUTPUTTERMINAL).
+|3|bTerminalID|1|0x01|ID of this Output Terminal\n
+ (AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL).
+|4|wTerminalType|2|0x0301|Terminal is Desktop speaker.
+|6|bAssocTerminal|1|0x01|Associated to Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL).
+|7|bSourceID|1|0x02|From Feature Unit\n
+ (AUDDSpeakerDriverDescriptors_FEATUREUNIT).
+|8|iTerminal|1|0x00|Unused.
+
+ !Feature Unit Descriptor for playback
+ ...
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x0A|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x02|FEATURE_UNIT subtype\n
+ (AUDGenericDescriptor_FEATUREUNIT).
+|3|bUnitID|1|0x02|ID of this Feature Unit\n
+ (AUDDSpeakerDriverDescriptors_FEATUREUNIT).
+|4|bSourceID|1|0x00|From Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL).
+|5|bControlSize|1|0x01|1 byte per channel for controls
+|6|bmaControls|3|0x000001|Master channel mute control, no other controls.
+|9|iFeature|1|0x00|Unused.
+
+ !!AudioStreaming Interface Descriptor
+ The AudioStreaming interface has two possible alternate settings.
+
+ !Zero-bandwidth Alternate Setting 0
+ Alternate setting 0 is a zero-bandwidth setting, used to relinquish the
+ claimed bandwidth on the bus when the microphone is not in use. It is the
+ default setting after power-up. The zero bandwidth is implemented by
+ specifying that this alternate setting of the interface has no endpoints
+ associated with it (bNumEndpoints=0). The collection of descriptors for this
+ alternate setting reduces to the standard interface descriptor.
+
+ Standard AS Interface Descriptor (USBInterfaceDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x04|INTERFACE descriptor\n
+ (USBGenericDescriptor_INTERFACE).
+|2|bInterfaceNumber|1|0x01|Index of this interface.
+|3|bAlternateSetting|1|0x00|Index of this setting.
+|4|bNumEndpoints|1|0x00|0 endpoint.
+|5|bInterfaceClass|1|0x01|AUDIO (AUDStreamingInterfaceDescriptor_CLASS).
+|6|bInterfaceSubClass|1|0x02|AUDIO_STREAMING\n
+ (AUDStreamingInterfaceDescriptor_SUBCLASS).
+|7|bInterfaceProtocol|1|0x00|Unused (AUDStreamingInterfaceDescriptor_PROTOCOL).
+|8|iInterface|1|0x00|Unused.
+
+ !Operational Alternate Setting 1
+ Alternate setting 1 is the operational setting of the interface. It contains
+ the standard and class-specific interface and endpoint descriptors.
+
+ Standard AS Interface Descriptor (USBInterfaceDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of USBInterfaceDescriptor in bytes.
+|1|bDescriptorType|1|0x04|INTERFACE descriptor\n
+ (USBGenericDescriptor_INTERFACE).
+|2|bInterfaceNumber|1|0x01|Index of this interface.
+|3|bAlternateSetting|1|0x01|Index of this setting.
+|4|bNumEndpoints|1|0x01|1 endpoint.
+|5|bInterfaceClass|1|0x01|AUDIO (AUDStreamingInterfaceDescriptor_CLASS).
+|6|bInterfaceSubClass|1|0x02|AUDIO_STREAMING\n
+ (AUDStreamingInterfaceDescriptor_SUBCLASS).
+|7|bInterfaceProtocol|1|0x00|Unused (AUDStreamingInterfaceDescriptor_PROTOCOL).
+|8|iInterface|1|0x00|Unused.
+
+ Class-specific AS General Interface Descriptor (AUDStreamingInterfaceDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x06|Size of AUDStreamingInterfaceDescriptor in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x01|GENERAL subtype\n
+ (AUDStreamingInterfaceDescriptor_GENERAL).
+|3|bTerminalLink|1|0x02|Unit ID of the Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL).
+|4|bDelay|1|0x00|No interface delay.
+|5|wFormatTag|2|0x0001|PCM Format (AUDFormatTypeOneDescriptor_PCM).
+
+ Type I Format Type Descriptor (AUDFormatTypeOneDescriptor1)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x0B|Size of AUDFormatTypeOneDescriptor1 in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x02|FORMAT_TYPE subtype\n
+ (AUDStreamingInterfaceDescriptor_FORMATTYPE).
+|3|bFormatType|1|0x01|FORMAT_TYPE_I (AUDFormatTypeOneDescriptor_FORMATTYPEONE).
+|4|bNrChannels|1|0x02|2 channels (AUDDSpeakerDriver_NUMCHANNELS).
+|5|bSubFrameSize|1|0x02|Two bytes per audio subframe\n
+ (AUDDSpeakerDriver_BYTESPERSAMPLE).
+|6|bBitResolution|1|0x10|16 bits per sample\n
+ (AUDDSpeakerDriver_BYTESPERSAMPLE * 2).
+|7|bSamFreqType|1|0x01|One frequency supported.
+|8|tSamFreq|3|4800|4800Hz (AUDDSpeakerDriver_SAMPLERATE).
+
+ Standard %Endpoint Descriptor (AUDEndpointDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of AUDFormatTypeOneDescriptor1 in bytes.
+|1|bDescriptorType|1|0x24|ENDPOINT descriptor (USBGenericDescriptor_ENDPOINT).
+|2|bEndpointAddress|1|0x04\nTest|OUT endpoint 4\n
+ See USBEndpointDescriptor_ADDRESS\n
+ See AUDDSpeakerDriverDescriptors_DATAOUT.
+|3|bmAttributes|1|0x01|Isochronous, not shared\n
+ (USBEndpointDescriptor_ISOCHRONOUS).
+|4|wMaxPacketSize|2|0x????|BOARD_USB_ENDPOINTS_MAXPACKETSIZE().
+|6|bInterval|1|0x01|One packet per frame.
+|7|bRefresh|1|0x00|Unused.
+|8|bSynchAddress|1|0x00|Unused.
+
+ Class-specific Isochronous Audio Data Endpoint Descriptor
+ (AUDDataEndpointDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x07|Size of AUDDataEndpointDescriptor in bytes.
+|1|bDescriptorType|1|0x25|CS_ENDPOINT descriptor\n
+ (AUDGenericDescriptor_ENDPOINT).
+|2|bDescriptorSubType|1|0x01|GENERAL subtype\n
+ (AUDDataEndpointDescriptor_SUBTYPE).
+|3|bmAttributes|1|0x00|No sampling frequency control\n
+ no pitch control\n
+ no packet padding.
+|4|bLockDelayUnits|1|0x00|Unused.
+|5|wLockDelay|2|0x0000|Unused.
+
+ !!String Descriptors
+ There are three string descriptors available. The Manufacturer, Product and
+ Serial Number descriptor.
+
+ See manufacturerDescriptor, productDescriptor, serialNumberDescriptor.
+
+ !!!Requests
+ The Audio Speaker Driver supports all necessary standard requests, and some
+ class-specific requests.
+
+ USBDCallbacks_RequestReceived is used to filter all requests,
+ AUDDSpeakerDriver_RequestHandler is invoked to handle Audio Class requests
+ and forward standard request to AUDDSpeakerDriver_RequestHandler.
+
+ !!Standard requests
+ Set Interface request should be processed to control bandwidth allocation.
+
+ !Set Interface
+ USBDDriverCallbacks_InterfaceSettingChanged is re-implemented to handle the
+ event.
+||Offset||Field||Size||Value||Description
+|0|bmRequestType|1|0x01|D7:0=Host to Device.\n
+ D6..5:00=Standard Request.\n
+ D4..0:00001=Recipient is interface.
+|1|bRequest|1|0x0B|SET_INTERFACE.
+|2|wValue|2|0x0000\n
+ or\n
+ 0x0001|Zero bandwidth or normal isochronous operation.
+|4|wIndex|2|0x0001|Interface number of the AudioStreaming interface.
+|6|wLength|2|0x0000|No Parameter Block.
+
+ !!Class-specific requests
+ The only class-specific Request supported is the Set/Get Feature Unit Control
+ Request. For mute control of the Feature Unit.
+
+ !Set Feature Unit Control Request
+||Offset||Field||Size||Value||Description
+|0|bmRequestType|1|0x01|D7:0=Host to Device.\n
+ D6..5:01=Class Request.\n
+ D4..0:00001=Recipient is interface.
+|1|bRequest|1|0x01|SET_CUR.
+|2|wValue|2|0x0100|Mute control (AUDFeatureUnitRequest_MUTE) of\n
+ Master channel (AUDDSpeakerDriver_MASTERCHANNEL).
+|4|wIndex|2|0x0200|Feature Unit (AUDDSpeakerDriverDescriptors_FEATUREUNIT)\n
+ and\n
+ AudioControl Interface (AUDDSpeakerDriverDescriptors_CONTROL).
+|6|wLength|2|0x0001|Paramter Block Length
+
+ The one-byte Parameter Block contains the new bMuted value for Feature
+ Control.
+
+ !Get Feature Unit Control Request
+||Offset||Field||Size||Value||Description
+|0|bmRequestType|1|0x01|D7:0=Host to Device.\n
+ D6..5:01=Class Request.\n
+ D4..0:00001=Recipient is interface.
+|1|bRequest|1|0x81|GET_CUR.
+|2|wValue|2|0x0100|Mute control (AUDFeatureUnitRequest_MUTE) of\n
+ Master channel (AUDDSpeakerDriver_MASTERCHANNEL).
+|4|wIndex|2|0x0200|Feature Unit (AUDDSpeakerDriverDescriptors_FEATUREUNIT)\n
+ and\n
+ AudioControl Interface (AUDDSpeakerDriverDescriptors_CONTROL).
+|6|wLength|2|0x0001|Paramter Block Length
+
+ The one-byte Parameter Block contains the new bMuted value for Feature
+ Control.
+
+ !!!Modify the Device Driver
+ You can modify your project from the USB Audio Demoes:
+ - usb-device-audio-speaker-ac97-project
+ - usb-device-audio-speaker-project
+
+ !!Change Device ID and Display
+ All Device ID and Display Strings are in AUDDSpeakerDriverDescriptors.c.
+
+ !Device IDs
+ You can find "Audio Speaker Device Codes"
+ - AUDDSpeakerDriverDescriptors_VENDORID
+ - AUDDSpeakerDriverDescriptors_PRODUCTID
+ - AUDDSpeakerDriverDescriptors_RELEASE
+
+ !Display Strings
+ You can modify the string descriptors
+ - manufacturerDescriptor
+ - productDescriptor
+ - serialNumberDescriptor
+
+ !!!Add Recorder Function
+ See "USB Audio Recorder".
+
+*/
+
+/**
+ \page "USB Audio Recorder"
+ This page describes how to add recorder function into the
+ "USB Audio Speaker Device", So that you can learn how to extend your audio
+ device driver from current Audio Speaker demo.
+
+ !!!Description
+ To add %audio record function, new Input Terminal, Output Termnial and Feature
+ Unit is added.
+
+ \image UsbAudioSpeakerRecorder.png "USB Desktop Speaker Hierarchy"
+
+
+ !!!Modify the configuration descriptor:
+ New descriptor for the terminals and unit should be added, and according
+ interface, too.
+
+ \image UsbAudioSpeakerRecorderDescriptors.png "USB Desktop Speaker Descriptors"
+
+
+
+ !!Terminal Descriptors and Unit Descriptor
+ ...
+ !Input Terminal Descriptor for recording
+ ...
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x0C|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x03|INPUT_TERMINAL subtype\n
+ (AUDGenericDescriptor_INPUTTERMINAL).
+|3|bTerminalID|1|0x03|ID of this Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL_REC).
+|4|wTerminalType|2|0x0403|Terminal is Speaker Phone\n
+ (AUDInputTerminalDescriptor_SPEAKERPHONE).
+|6|bAssocTerminal|1|0x04|Associated to Output Terminal\n
+ (AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL_REC).
+|7|bNrChannels|1|0x02|Two channel.
+|8|wChannelConfig|2|0x0003|Left plus right front channel.
+|10|iChannelNames|1|0x00|Unused.
+|11|iTerminal|1|0x00|Unused.
+
+ !Output Terminal Descriptor for recording
+ ...
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x04|OUTPUT_TERMINAL subtype\n
+ (AUDGenericDescriptor_OUTPUTTERMINAL).
+|3|bTerminalID|1|0x04|ID of this Output Terminal\n
+ (AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL_REC).
+|4|wTerminalType|2|0x0301|Terminal is USB stream\n
+ (AUDOutputTerminalDescriptor_USBTREAMING).
+|6|bAssocTerminal|1|0x03|Associated to Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL_REC).
+|7|bSourceID|1|0x05|From Feature Unit\n
+ (AUDDSpeakerDriverDescriptors_FEATUREUNIT_REC).
+|8|iTerminal|1|0x00|Unused.
+
+ !Feature Unit Descriptor for recording
+ ...
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x0A|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x02|FEATURE_UNIT subtype\n
+ (AUDGenericDescriptor_FEATUREUNIT).
+|3|bUnitID|1|0x05|ID of this Feature Unit\n
+ (AUDDSpeakerDriverDescriptors_FEATUREUNIT_REC).
+|4|bSourceID|1|0x03|From Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL_REC).
+|5|bControlSize|1|0x01|1 byte per channel for controls
+|6|bmaControls|3|0x000001|Master channel mute control, no other controls.
+|9|iFeature|1|0x00|Unused.
+
+ !!Interface Descriptor and Endpoint Descriptor for recording
+ ...
+
+ !Zero-bandwidth Alternate Setting 0
+ Standard AS Interface Descriptor (USBInterfaceDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of this descriptor, in bytes.
+|1|bDescriptorType|1|0x04|INTERFACE descriptor\n
+ (USBGenericDescriptor_INTERFACE).
+|2|bInterfaceNumber|1|0x02|Index of this interface.
+|3|bAlternateSetting|1|0x00|Index of this setting.
+|4|bNumEndpoints|1|0x00|0 endpoint.
+|5|bInterfaceClass|1|0x01|AUDIO (AUDStreamingInterfaceDescriptor_CLASS).
+|6|bInterfaceSubClass|1|0x02|AUDIO_STREAMING\n
+ (AUDStreamingInterfaceDescriptor_SUBCLASS).
+|7|bInterfaceProtocol|1|0x00|Unused (AUDStreamingInterfaceDescriptor_PROTOCOL).
+|8|iInterface|1|0x00|Unused.
+
+ !Operational Alternate Setting 1
+ Standard AS Interface Descriptor (USBInterfaceDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of USBInterfaceDescriptor in bytes.
+|1|bDescriptorType|1|0x04|INTERFACE descriptor\n
+ (USBGenericDescriptor_INTERFACE).
+|2|bInterfaceNumber|1|0x02|Index of this interface.
+|3|bAlternateSetting|1|0x01|Index of this setting.
+|4|bNumEndpoints|1|0x01|1 endpoint.
+|5|bInterfaceClass|1|0x01|AUDIO (AUDStreamingInterfaceDescriptor_CLASS).
+|6|bInterfaceSubClass|1|0x02|AUDIO_STREAMING\n
+ (AUDStreamingInterfaceDescriptor_SUBCLASS).
+|7|bInterfaceProtocol|1|0x00|Unused (AUDStreamingInterfaceDescriptor_PROTOCOL).
+|8|iInterface|1|0x00|Unused.
+
+ Class-specific AS General Interface Descriptor (AUDStreamingInterfaceDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x06|Size of AUDStreamingInterfaceDescriptor in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x01|GENERAL subtype\n
+ (AUDStreamingInterfaceDescriptor_GENERAL).
+|3|bTerminalLink|1|0x02|Unit ID of the Input Terminal\n
+ (AUDDSpeakerDriverDescriptors_INPUTTERMINAL).
+|4|bDelay|1|0x00|No interface delay.
+|5|wFormatTag|2|0x0001|PCM Format (AUDFormatTypeOneDescriptor_PCM).
+
+ Type I Format Type Descriptor (AUDFormatTypeOneDescriptor1)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x0B|Size of AUDFormatTypeOneDescriptor1 in bytes.
+|1|bDescriptorType|1|0x24|CS_INTERFACE descriptor\n
+ (AUDGenericDescriptor_INTERFACE).
+|2|bDescriptorSubType|1|0x02|FORMAT_TYPE subtype\n
+ (AUDStreamingInterfaceDescriptor_FORMATTYPE).
+|3|bFormatType|1|0x01|FORMAT_TYPE_I (AUDFormatTypeOneDescriptor_FORMATTYPEONE).
+|4|bNrChannels|1|0x02|2 channels (AUDDSpeakerDriver_NUMCHANNELS).
+|5|bSubFrameSize|1|0x02|Two bytes per audio subframe\n
+ (AUDDSpeakerDriver_BYTESPERSAMPLE).
+|6|bBitResolution|1|0x10|16 bits per sample\n
+ (AUDDSpeakerDriver_BYTESPERSAMPLE * 2).
+|7|bSamFreqType|1|0x01|One frequency supported.
+|8|tSamFreq|3|4800|4800Hz (AUDDSpeakerDriver_SAMPLERATE).
+
+ Standard %Endpoint Descriptor (AUDEndpointDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x09|Size of AUDFormatTypeOneDescriptor1 in bytes.
+|1|bDescriptorType|1|0x24|ENDPOINT descriptor (USBGenericDescriptor_ENDPOINT).
+|2|bEndpointAddress|1|0x85|IN endpoint 5\n
+ USBEndpointDescriptor_ADDRESS()\n
+ AUDDSpeakerDriverDescriptors_DATAIN
+|3|bmAttributes|1|0x01|Isochronous, not shared\n
+ (USBEndpointDescriptor_ISOCHRONOUS).
+|4|wMaxPacketSize|2|0x????|BOARD_USB_ENDPOINTS_MAXPACKETSIZE(5).
+|6|bInterval|1|0x01|One packet per frame.
+|7|bRefresh|1|0x00|Unused.
+|8|bSynchAddress|1|0x00|Unused.
+
+ Class-specific Isochronous Audio Data Endpoint Descriptor
+ (AUDDataEndpointDescriptor)
+||Offset||Field||Size||Value||Description
+|0|bLength|1|0x07|Size of AUDDataEndpointDescriptor in bytes.
+|1|bDescriptorType|1|0x25|CS_ENDPOINT descriptor\n
+ (AUDGenericDescriptor_ENDPOINT).
+|2|bDescriptorSubType|1|0x01|GENERAL subtype\n
+ (AUDDataEndpointDescriptor_SUBTYPE).
+|3|bmAttributes|1|0x00|No sampling frequency control\n
+ no pitch control\n
+ no packet padding
+|4|bLockDelayUnits|1|0x00|Unused.
+|5|wLockDelay|2|0x0000|Unused.
+
+ !!!Modified methods for new function
+ Several methods modified for new recorder function.
+
+ !!Request handlers callbacks
+ Add handler for new Interface, Terminal and Unit IDs.
+ See AUDDSpeakerDriver_RequestHandler.
+
+ !!Add function for recording USB stream
+ See AUDDSpeakerDriver_Write.
+*/
diff --git a/usb/device/ccid/cciddriver.c b/usb/device/ccid/cciddriver.c new file mode 100644 index 0000000..d72b4ab --- /dev/null +++ b/usb/device/ccid/cciddriver.c @@ -0,0 +1,1503 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// CCID driver
+///
+/// !Usage
+///
+/// Explanation on the usage of the code made available through the header file.
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <utility/trace.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/device/ccid/cciddriver.h>
+#include <usb/device/ccid/cciddriverdescriptors.h>
+#include <iso7816/iso7816_4.h>
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// Local definition
+//------------------------------------------------------------------------------
+
+/// Constants: IDs: Device product ID.
+#define CCIDDriverDescriptors_PRODUCTID 0x6129
+/// Constants: IDs: Device vendor ID.
+#define CCIDDriverDescriptors_VENDORID 0x03EB
+/// Constants: IDs: Device release number.
+#define CCIDDriverDescriptors_RELEASE 0x0100
+
+/// Returns the minimum between two values.
+#define MIN(a, b) ((a < b) ? a : b)
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+/// CCIDDriverConfiguration Descriptors
+/// List of descriptors that make up the configuration descriptors of a
+/// device using the CCID driver.
+typedef struct {
+
+ /// Configuration descriptor
+ USBConfigurationDescriptor configuration;
+ /// Interface descriptor
+ USBInterfaceDescriptor interface;
+ /// CCID descriptor
+ CCIDDescriptor ccid;
+ /// Bulk OUT endpoint descriptor
+ USBEndpointDescriptor bulkOut;
+ /// Bulk IN endpoint descriptor
+ USBEndpointDescriptor bulkIn;
+ /// Interrupt OUT endpoint descriptor
+ USBEndpointDescriptor interruptIn;
+
+} __attribute__ ((packed)) CCIDDriverConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+/// Driver structure for an CCID device
+typedef struct {
+
+ /// Standard USB device driver instance
+ USBDDriver usbdDriver;
+ /// CCID message
+ S_ccid_bulk_in_header sCcidMessage;
+ /// CCID command
+ S_ccid_bulk_out_header sCcidCommand;
+ /// Interrupt message answer
+ unsigned char BufferINT[4];
+ /// Buffer data of message
+ unsigned char ProtocolDataStructure[10];
+ /// Protocol used
+ unsigned char bProtocol;
+ /// SlotStatus
+ /// Bit 0 = Slot 0 current state
+ /// Bit 1 = Slot 0 changed status
+ /// Bit 2 = Slot 1 current state
+ /// Bit 3 = Slot 1 changed status
+ /// Bit 4 = Slot 2 current state
+ /// Bit 5 = Slot 2 changed status
+ unsigned char SlotStatus;
+
+} CCIDDriver;
+
+//------------------------------------------------------------------------------
+// Local variables
+//------------------------------------------------------------------------------
+
+/// Static instance of the CCID device driver.
+static CCIDDriver ccidDriver;
+
+/// Standard USB device descriptor.
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ 0,
+ 0,
+ 0,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ CCIDDriverDescriptors_VENDORID,
+ CCIDDriverDescriptors_PRODUCTID,
+ CCIDDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+
+
+/// List of configuration descriptors.
+static const CCIDDriverConfigurationDescriptors configurationDescriptorsFS = {
+
+ // Standard USB configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CCIDDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // CCID interface descriptor
+ // Table 4.3-1 Interface Descriptor
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // Interface 0
+ 0, // No alternate settings
+ 3, // uses bulk-IN, bulk-OUT and interrupt–IN
+ SMART_CARD_DEVICE_CLASS,
+ 0, // Subclass code
+ 0, // bulk transfers optional interrupt-IN
+ 0 // No associated string descriptor
+ },
+ {
+ sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+ CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
+ CCID1_10, // bcdCCID: CCID version
+ 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
+ VOLTS_5_0, // bVoltageSupport
+ PROTOCOL_TO, // dwProtocols
+ 3580, // dwDefaultClock
+ 3580, // dwMaxClock
+ 0, // bNumClockSupported
+ 9600, // dwDataRate : 9600 bauds
+ 9600, // dwMaxDataRate : 9600 bauds
+ 0, // bNumDataRatesSupported
+ 0xfe, // dwMaxIFSD
+ 0, // dwSynchProtocols
+ 0, // dwMechanical
+ //0x00010042, // dwFeatures: Short APDU level exchanges
+ CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+ 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+ 0xFF, // bClassGetResponse: Echoes the class of the APDU
+ 0xFF, // bClassEnvelope: Echoes the class of the APDU
+ 0, // wLcdLayout: no LCD
+ 0, // bPINSupport: No PIN
+ 1 // bMaxCCIDBusySlot
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Notification endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ 0x10
+ }
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+static const CCIDDriverConfigurationDescriptors configurationDescriptorsHS = {
+
+ // Standard USB configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CCIDDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // CCID interface descriptor
+ // Table 4.3-1 Interface Descriptor
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // Interface 0
+ 0, // No alternate settings
+ 3, // uses bulk-IN, bulk-OUT and interrupt–IN
+ SMART_CARD_DEVICE_CLASS,
+ 0, // Subclass code
+ 0, // bulk transfers optional interrupt-IN
+ 0 // No associated string descriptor
+ },
+ {
+ sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+ CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
+ CCID1_10, // bcdCCID: CCID version
+ 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
+ VOLTS_5_0, // bVoltageSupport
+ PROTOCOL_TO, // dwProtocols
+ 3580, // dwDefaultClock
+ 3580, // dwMaxClock
+ 0, // bNumClockSupported
+ 9600, // dwDataRate : 9600 bauds
+ 9600, // dwMaxDataRate : 9600 bauds
+ 0, // bNumDataRatesSupported
+ 0xfe, // dwMaxIFSD
+ 0, // dwSynchProtocols
+ 0, // dwMechanical
+ //0x00010042, // dwFeatures: Short APDU level exchanges
+ CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+ 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+ 0xFF, // bClassGetResponse: Echoes the class of the APDU
+ 0xFF, // bClassEnvelope: Echoes the class of the APDU
+ 0, // wLcdLayout: no LCD
+ 0, // bPINSupport: No PIN
+ 1 // bMaxCCIDBusySlot
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Notification endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
+ 0x10
+ }
+};
+
+/// Qualifier descriptor
+const USBDeviceQualifierDescriptor deviceQualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor), // Size of this descriptor in bytes
+ USBGenericDescriptor_DEVICEQUALIFIER, // Qualifier Descriptor Type
+ USBDeviceDescriptor_USB2_00, // USB specification 2.00
+ 0x00, // Class is specified in interface
+ 0x00, // Subclass is specified in interface
+ 0x00, // Protocol is specified in interface
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 0x01, // One possible configuration
+ 0x00 // Reserved for future use, must be zero
+};
+
+/// OtherSpeed configuration descriptor in Full Speed mode
+static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationFS = {
+
+ // Standard USB configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(CCIDDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // CCID interface descriptor
+ // Table 4.3-1 Interface Descriptor
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // Interface 0
+ 0, // No alternate settings
+ 3, // uses bulk-IN, bulk-OUT and interrupt–IN
+ SMART_CARD_DEVICE_CLASS,
+ 0, // Subclass code
+ 0, // bulk transfers optional interrupt-IN
+ 0 // No associated string descriptor
+ },
+ {
+ sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+ CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
+ CCID1_10, // bcdCCID: CCID version
+ 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
+ VOLTS_5_0, // bVoltageSupport
+ PROTOCOL_TO, // dwProtocols
+ 3580, // dwDefaultClock
+ 3580, // dwMaxClock
+ 0, // bNumClockSupported
+ 9600, // dwDataRate : 9600 bauds
+ 9600, // dwMaxDataRate : 9600 bauds
+ 0, // bNumDataRatesSupported
+ 0xfe, // dwMaxIFSD
+ 0, // dwSynchProtocols
+ 0, // dwMechanical
+ //0x00010042, // dwFeatures: Short APDU level exchanges
+ CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+ 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+ 0xFF, // bClassGetResponse: Echoes the class of the APDU
+ 0xFF, // bClassEnvelope: Echoes the class of the APDU
+ 0, // wLcdLayout: no LCD
+ 0, // bPINSupport: No PIN
+ 1 // bMaxCCIDBusySlot
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Notification endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ 0x10
+ }
+};
+
+/// OtherSpeed configuration descriptor in High Speed mode
+static const CCIDDriverConfigurationDescriptors sOtherSpeedConfigurationHS = {
+
+ // Standard USB configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(CCIDDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // CCID interface descriptor
+ // Table 4.3-1 Interface Descriptor
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // Interface 0
+ 0, // No alternate settings
+ 3, // uses bulk-IN, bulk-OUT and interrupt–IN
+ SMART_CARD_DEVICE_CLASS,
+ 0, // Subclass code
+ 0, // bulk transfers optional interrupt-IN
+ 0 // No associated string descriptor
+ },
+ {
+ sizeof(CCIDDescriptor), // bLength: Size of this descriptor in bytes
+ CCID_DECRIPTOR_TYPE, // bDescriptorType:Functional descriptor type
+ CCID1_10, // bcdCCID: CCID version
+ 0, // bMaxSlotIndex: Value 0 indicates that one slot is supported
+ VOLTS_5_0, // bVoltageSupport
+ PROTOCOL_TO, // dwProtocols
+ 3580, // dwDefaultClock
+ 3580, // dwMaxClock
+ 0, // bNumClockSupported
+ 9600, // dwDataRate : 9600 bauds
+ 9600, // dwMaxDataRate : 9600 bauds
+ 0, // bNumDataRatesSupported
+ 0xfe, // dwMaxIFSD
+ 0, // dwSynchProtocols
+ 0, // dwMechanical
+ //0x00010042, // dwFeatures: Short APDU level exchanges
+ CCID_FEATURES_AUTO_PCONF | CCID_FEATURES_AUTO_PNEGO | CCID_FEATURES_EXC_TPDU,
+ 0x0000010F, // dwMaxCCIDMessageLength: For extended APDU level the value shall be between 261 + 10
+ 0xFF, // bClassGetResponse: Echoes the class of the APDU
+ 0xFF, // bClassEnvelope: Echoes the class of the APDU
+ 0, // wLcdLayout: no LCD
+ 0, // bPINSupport: No PIN
+ 1 // bMaxCCIDBusySlot
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_OUT, CCID_EPT_DATA_OUT ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_OUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_DATA_IN ),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_DATA_IN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0x00 // Does not apply to Bulk endpoints
+ },
+ // Notification endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS( USBEndpointDescriptor_IN, CCID_EPT_NOTIFICATION ),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CCID_EPT_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
+ 0x10
+ }
+};
+#endif
+
+/// Language ID string descriptor.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static 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.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(23),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('C'),
+ USBStringDescriptor_UNICODE('C'),
+ USBStringDescriptor_UNICODE('I'),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('R'),
+ USBStringDescriptor_UNICODE('I'),
+ USBStringDescriptor_UNICODE('V'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('R'),
+ USBStringDescriptor_UNICODE(' ')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(12),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('F')
+};
+
+/// Array of pointers to string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor
+};
+
+
+/// List of standard descriptors for the serial driver.
+const USBDDriverDescriptors ccidDriverDescriptors = {
+
+ &deviceDescriptor, // FS
+ (USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // FS
+ (USBConfigurationDescriptor *) &sOtherSpeedConfigurationFS,
+ &deviceDescriptor, // HS
+ (USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ (USBDeviceQualifierDescriptor *) &deviceQualifierDescriptor, // HS
+ (USBConfigurationDescriptor *) &sOtherSpeedConfigurationHS,
+#else
+ 0, // No qualifier descriptor FS
+ 0, // No other-speed configuration FS
+ 0, // No device descriptor HS
+ 0, // No configuration HS
+ 0, // No qualifier descriptor HS
+ 0, // No other-speed configuration HS
+#endif
+ stringDescriptors,
+ 4 // Four string descriptors in array
+};
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Return the Slot Status to the host
+/// Answer to:
+/// PC_to_RDR_IccPowerOff
+/// PC_to_RDR_GetSlotStatus
+/// PC_to_RDR_IccClock
+/// PC_to_RDR_T0APDU
+/// PC_to_RDR_Mechanical
+/// PC_to_RDR_Abort and Class specific ABORT request
+//------------------------------------------------------------------------------
+static void RDRtoPCSlotStatus( void )
+{
+ TRACE_DEBUG("RDRtoPCSlotStatus\n\r");
+
+ // Header fields settings
+ ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
+ ccidDriver.sCcidMessage.wLength = 0;
+ ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
+ ccidDriver.sCcidMessage.bError = 0;
+ // 00h Clock running
+ // 01h Clock stopped in state L
+ // 02h Clock stopped in state H
+ // 03h Clock stopped in an unknown state
+ // All other values are Reserved for Future Use.
+ ccidDriver.sCcidMessage.bSpecific = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to PC_to_RDR_IccPowerOn
+//------------------------------------------------------------------------------
+static void RDRtoPCDatablock_ATR( void )
+{
+ unsigned char i;
+ unsigned char Atr[ATR_SIZE_MAX];
+ unsigned char length;
+
+ //TRACE_DEBUG("RDRtoPCDatablock\n\r");
+
+ ISO7816_Datablock_ATR( Atr, &length );
+
+ if( length > 5 ) {
+ ccidDriver.ProtocolDataStructure[1] = Atr[5]&0x0F; // TD(1)
+ ccidDriver.bProtocol = Atr[5]&0x0F; // TD(1)
+ }
+
+ // S_ccid_protocol_t0
+ // bmFindexDindex
+ ccidDriver.ProtocolDataStructure[0] = Atr[2]; // TA(1)
+
+ // bmTCCKST0
+ // For T=0 ,B0 – 0b, B7-2 – 000000b
+ // B1 – Convention used (b1=0 for direct, b1=1 for inverse)
+
+ // bGuardTimeT0
+ // Extra Guardtime between two characters. Add 0 to 254 etu to the normal
+ // guardtime of 12etu. FFh is the same as 00h.
+ ccidDriver.ProtocolDataStructure[2] = Atr[4]; // TC(1)
+ // AT91C_BASE_US0->US_TTGR = 0; // TC1
+
+ // bWaitingIntegerT0
+ // WI for T=0 used to define WWT
+ ccidDriver.ProtocolDataStructure[3] = Atr[7]; // TC(2)
+
+ // bClockStop
+ // ICC Clock Stop Support
+ // 00 = Stopping the Clock is not allowed
+ // 01 = Stop with Clock signal Low
+ // 02 = Stop with Clock signal High
+ // 03 = Stop with Clock either High or Low
+ ccidDriver.ProtocolDataStructure[4] = 0x00; // 0 to 3
+
+ // Header fields settings
+ ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
+ ccidDriver.sCcidMessage.wLength = length; // Size of ATR
+ ccidDriver.sCcidMessage.bSizeToSend += length; // Size of ATR
+ // bChainParameter: 00 the response APDU begins and ends in this command
+ ccidDriver.sCcidMessage.bSpecific = 0;
+
+ for( i=0; i<length; i++ ) {
+
+ ccidDriver.sCcidMessage.abData[i] = Atr[i];
+ }
+
+ // Set the slot to an active status
+ ccidDriver.sCcidMessage.bStatus = 0;
+ ccidDriver.sCcidMessage.bError = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// In other cases, the response message has the following format:
+/// The response data will contain the optional data returned by the ICC,
+/// followed by the 2 byte-size status words SW1-SW2.
+///
+/// Answer to:
+/// PC_to_RDR_XfrBlock
+/// PC_to_RDR_Secure
+//------------------------------------------------------------------------------
+static void RDRtoPCDatablock( void )
+{
+ //TRACE_DEBUG("RDRtoPCDatablock\n\r");
+
+ // Header fields settings
+ ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATABLOCK;
+ ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
+ // bChainParameter: 00 the response APDU begins and ends in this command
+ ccidDriver.sCcidMessage.bSpecific = 0;
+
+ // Set the slot to an active status
+ ccidDriver.sCcidMessage.bStatus = 0;
+ ccidDriver.sCcidMessage.bError = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to:
+/// PC_to_RDR_GetParameters
+/// PC_to_RDR_ResetParameters
+/// PC_to_RDR_SetParameters
+//------------------------------------------------------------------------------
+static void RDRtoPCParameters( void )
+{
+ unsigned int i;
+
+ TRACE_DEBUG("RDRtoPCParameters\n\r");
+
+ // Header fields settings
+ ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_PARAMETERS;
+
+ //ccidDriver.sCcidMessage.bStatus = 0;
+ ccidDriver.sCcidMessage.bError = 0;
+
+ if( ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO ) {
+
+ // T=0
+ ccidDriver.sCcidMessage.wLength = sizeof(S_ccid_protocol_t0);
+ ccidDriver.sCcidMessage.bSpecific = PROTOCOL_TO;
+ }
+ else {
+
+ // T=1
+ ccidDriver.sCcidMessage.wLength = sizeof(S_ccid_protocol_t1);
+ ccidDriver.sCcidMessage.bSpecific = PROTOCOL_T1;
+ }
+
+ ccidDriver.sCcidMessage.bSizeToSend += ccidDriver.sCcidMessage.wLength;
+
+ for( i=0; i<ccidDriver.sCcidMessage.wLength; i++ ) {
+ ccidDriver.sCcidMessage.abData[i] = ccidDriver.ProtocolDataStructure[i];
+ }
+
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to:
+/// PC_to_RDR_Escape
+//------------------------------------------------------------------------------
+static void RDRtoPCEscape( unsigned char length, unsigned char *data_send_from_CCID )
+{
+ unsigned int i;
+
+ TRACE_DEBUG("RDRtoPCEscape\n\r");
+
+ // Header fields settings
+ ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_ESCAPE;
+
+ ccidDriver.sCcidMessage.wLength = length;
+
+ ccidDriver.sCcidMessage.bStatus = 0;
+ ccidDriver.sCcidMessage.bError = 0;
+
+ ccidDriver.sCcidMessage.bSpecific = 0; // bRFU
+
+ for( i=0; i<length; i++ ) {
+ ccidDriver.sCcidMessage.abData[i] = data_send_from_CCID[i];
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Response Pipe, Bulk-IN Messages
+/// Answer to:
+/// PC_to_RDR_SetDataRateAndClockFrequency
+//------------------------------------------------------------------------------
+static void RDRtoPCDataRateAndClockFrequency( unsigned int dwClockFrequency,
+ unsigned int dwDataRate )
+{
+ TRACE_DEBUG("RDRtoPCDataRateAndClockFrequency\n\r");
+
+ // Header fields settings
+ ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_DATARATEANDCLOCKFREQUENCY;
+
+ ccidDriver.sCcidMessage.wLength = 8;
+
+ ccidDriver.sCcidMessage.bStatus = 0;
+ ccidDriver.sCcidMessage.bError = 0;
+
+ ccidDriver.sCcidMessage.bSpecific = 0; // bRFU
+
+ ccidDriver.sCcidMessage.abData[0] = dwClockFrequency;
+
+ ccidDriver.sCcidMessage.abData[4] = dwDataRate;
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// Power On Command - Cold Reset & Warm Reset
+/// Return the ATR to the host
+//------------------------------------------------------------------------------
+static void PCtoRDRIccPowerOn( void )
+{
+ TRACE_DEBUG("PCtoRDRIccPowerOn\n\r");
+
+ if( CCID_FEATURES_AUTO_VOLT == (configurationDescriptorsFS.ccid.dwFeatures & CCID_FEATURES_AUTO_VOLT) ) {
+
+ // bPowerSelect = ccidDriver.sCcidCommand.bSpecific_0;
+ ccidDriver.sCcidCommand.bSpecific_0 = VOLTS_AUTO;
+ }
+
+ ISO7816_cold_reset();
+
+ // for emulation only //JCB
+ if ( ccidDriver.sCcidCommand.bSpecific_0 != VOLTS_5_0 ) {
+
+ TRACE_ERROR("POWER_NOT_SUPPORTED\n\r");
+ }
+
+ else {
+
+ RDRtoPCDatablock_ATR();
+
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// Power Off Command - Set the ICC in an inactive state
+/// Return the slot status to the host
+//------------------------------------------------------------------------------
+static void PCtoRDRIccPowerOff( void )
+{
+ unsigned char bStatus;
+
+ TRACE_DEBUG("PCtoRDRIccPowerOff\n\r");
+
+ ISO7816_IccPowerOff();
+
+ //JCB stub
+ bStatus = ICC_BS_PRESENT_NOTACTIVATED;
+
+ // Set the slot to an inactive status
+ ccidDriver.sCcidMessage.bStatus = 0;
+ ccidDriver.sCcidMessage.bError = 0;
+
+ // if error, see Table 6.1-2 errors
+
+ // Return the slot status to the host
+ RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// Get slot status
+//------------------------------------------------------------------------------
+static void PCtoRDRGetSlotStatus( void )
+{
+ TRACE_DEBUG("PCtoRDRGetSlotStatus\n\r");
+
+ ccidDriver.sCcidMessage.bStatus = 0;
+ ccidDriver.sCcidMessage.bError = 0;
+
+ // Return the slot status to the host
+ RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// If the command header is valid, an APDU command is received and can be read
+/// by the application
+//------------------------------------------------------------------------------
+static void PCtoRDRXfrBlock( void )
+{
+ unsigned char indexMessage = 0;
+ unsigned char i;
+
+ //TRACE_DEBUG("PCtoRDRXfrBlock\n\r");
+
+ i = 0;
+
+ // Check the block length
+ if ( ccidDriver.sCcidCommand.wLength > (configurationDescriptorsFS.ccid.dwMaxCCIDMessageLength-10) ) {
+
+ ccidDriver.sCcidMessage.bStatus = 1;
+ ccidDriver.sCcidMessage.bError = 0;
+ }
+ // check bBWI
+ else if ( 0 != ccidDriver.sCcidCommand.bSpecific_0 ) {
+
+ TRACE_ERROR("Bad bBWI\n\r");
+ }
+ else {
+
+ // APDU or TPDU
+ switch(configurationDescriptorsFS.ccid.dwFeatures
+ & (CCID_FEATURES_EXC_TPDU|CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU)) {
+
+ case CCID_FEATURES_EXC_TPDU:
+ if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_TO) {
+
+ // Send commande APDU
+ indexMessage = ISO7816_XfrBlockTPDU_T0( ccidDriver.sCcidCommand.APDU ,
+ ccidDriver.sCcidMessage.abData,
+ ccidDriver.sCcidCommand.wLength );
+ }
+ else {
+ if (ccidDriver.ProtocolDataStructure[1] == PROTOCOL_T1) {
+ TRACE_INFO("Not supported T=1\n\r");
+ }
+ else {
+ TRACE_INFO("Not supported\n\r");
+ }
+ }
+ break;
+
+ case CCID_FEATURES_EXC_APDU:
+ TRACE_INFO("Not supported\n\r");
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+ ccidDriver.sCcidMessage.wLength = indexMessage;
+ TRACE_DEBUG("USB: 0x%X, 0x%X, 0x%X, 0x%X, 0x%X\n\r", ccidDriver.sCcidMessage.abData[0],
+ ccidDriver.sCcidMessage.abData[1],
+ ccidDriver.sCcidMessage.abData[2],
+ ccidDriver.sCcidMessage.abData[3],
+ ccidDriver.sCcidMessage.abData[4] );
+ RDRtoPCDatablock();
+
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// return parameters by the command: RDR_to_PC_Parameters
+//------------------------------------------------------------------------------
+static void PCtoRDRGetParameters( void )
+{
+ TRACE_DEBUG("PCtoRDRGetParameters\n\r");
+
+ // We support only one slot
+
+ // bmIccStatus
+ if( ISO7816_StatusReset() ) {
+ // 0: An ICC is present and active (power is on and stable, RST is inactive
+ ccidDriver.sCcidMessage.bStatus = 0;
+ }
+ else {
+ // 1: An ICC is present and inactive (not activated or shut down by hardware error)
+ ccidDriver.sCcidMessage.bStatus = 1;
+ }
+
+ RDRtoPCParameters();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command resets the slot parameters to their default values
+//------------------------------------------------------------------------------
+static void PCtoRDRResetParameters( void )
+{
+ TRACE_DEBUG("PCtoRDRResetParameters\n\r");
+
+ ccidDriver.SlotStatus = ICC_NOT_PRESENT;
+ ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
+
+ RDRtoPCParameters();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used to change the parameters for a given slot.
+//------------------------------------------------------------------------------
+static void PCtoRDRSetParameters( void )
+{
+ TRACE_DEBUG("PCtoRDRSetParameters\n\r");
+
+ ccidDriver.SlotStatus = ccidDriver.sCcidCommand.bSlot;
+ ccidDriver.sCcidMessage.bStatus = ccidDriver.SlotStatus;
+ // Not all feature supported
+
+ RDRtoPCParameters();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command allows the CCID manufacturer to define and access extended
+/// features.
+/// Information sent via this command is processed by the CCID control logic.
+//------------------------------------------------------------------------------
+static void PCtoRDREscape( void )
+{
+ TRACE_DEBUG("PCtoRDREscape\n\r");
+
+ // If needed by the user
+ ISO7816_Escape();
+
+ // stub, return all value send
+ RDRtoPCEscape( ccidDriver.sCcidCommand.wLength, ccidDriver.sCcidCommand.APDU);
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command stops or restarts the clock.
+//------------------------------------------------------------------------------
+static void PCtoRDRICCClock( void )
+{
+ TRACE_DEBUG("PCtoRDRICCClock\n\r");
+
+ if( 0 == ccidDriver.sCcidCommand.bSpecific_0 ) {
+ // restarts the clock
+ ISO7816_RestartClock();
+ }
+ else {
+ // stop clock in the state shown in the bClockStop field
+ ISO7816_StopClock();
+ }
+
+ RDRtoPCSlotStatus( );
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command changes the parameters used to perform the transportation of
+/// APDU messages by the T=0 protocol.
+//------------------------------------------------------------------------------
+static void PCtoRDRtoAPDU( void )
+{
+ unsigned char bmChanges;
+ unsigned char bClassGetResponse;
+ unsigned char bClassEnvelope;
+
+ TRACE_DEBUG("PCtoRDRtoAPDU\n\r");
+
+ if( configurationDescriptorsFS.ccid.dwFeatures == (CCID_FEATURES_EXC_SAPDU|CCID_FEATURES_EXC_APDU) ) {
+
+ bmChanges = ccidDriver.sCcidCommand.bSpecific_0;
+ bClassGetResponse = ccidDriver.sCcidCommand.bSpecific_1;
+ bClassEnvelope = ccidDriver.sCcidCommand.bSpecific_2;
+
+ ISO7816_toAPDU();
+ }
+
+ RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This is a command message to allow entering the PIN for verification or
+/// modification.
+//------------------------------------------------------------------------------
+static void PCtoRDRSecure( void )
+{
+ TRACE_DEBUG("PCtoRDRSecure\n\r");
+
+ TRACE_DEBUG("For user\n\r");
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used to manage motorized type CCID functionality.
+/// The Lock Card function is used to hold the ICC.
+/// This prevents an ICC from being easily removed from the CCID.
+/// The Unlock Card function is used to remove the hold initiated by the Lock
+/// Card function
+//------------------------------------------------------------------------------
+static void PCtoRDRMechanical( void )
+{
+ TRACE_DEBUG("PCtoRDRMechanical\n\r");
+ TRACE_DEBUG("Not implemented\n\r");
+
+ RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used with the Control pipe Abort request to tell the CCID
+/// to stop any current transfer at the specified slot and return to a state
+/// where the slot is ready to accept a new command pipe Bulk-OUT message.
+//------------------------------------------------------------------------------
+static void PCtoRDRAbort( void )
+{
+ TRACE_DEBUG("PCtoRDRAbort\n\r");
+
+ RDRtoPCSlotStatus();
+}
+
+//------------------------------------------------------------------------------
+/// Command Pipe, Bulk-OUT Messages
+/// This command is used to manually set the data rate and clock frequency of
+/// a specific slot.
+//------------------------------------------------------------------------------
+static void PCtoRDRSetDataRateAndClockFrequency( void )
+{
+ unsigned int dwClockFrequency;
+ unsigned int dwDataRate;
+
+ TRACE_DEBUG("PCtoRDRSetDatarateandClockFrequency\n\r");
+
+ dwClockFrequency = ccidDriver.sCcidCommand.APDU[0]
+ + (ccidDriver.sCcidCommand.APDU[1]<<8)
+ + (ccidDriver.sCcidCommand.APDU[2]<<16)
+ + (ccidDriver.sCcidCommand.APDU[3]<<24);
+
+ dwDataRate = ccidDriver.sCcidCommand.APDU[4]
+ + (ccidDriver.sCcidCommand.APDU[5]<<8)
+ + (ccidDriver.sCcidCommand.APDU[6]<<16)
+ + (ccidDriver.sCcidCommand.APDU[7]<<24);
+
+ ISO7816_SetDataRateandClockFrequency( dwClockFrequency, dwDataRate );
+
+ RDRtoPCDataRateAndClockFrequency( dwClockFrequency, dwDataRate );
+
+}
+
+//------------------------------------------------------------------------------
+/// Report the CMD_NOT_SUPPORTED error to the host
+//------------------------------------------------------------------------------
+static void vCCIDCommandNotSupported( void )
+{
+ // Command not supported
+ // vCCIDReportError(CMD_NOT_SUPPORTED);
+
+ TRACE_DEBUG("CMD_NOT_SUPPORTED\n\r");
+
+ // Header fields settings
+ ccidDriver.sCcidMessage.bMessageType = RDR_TO_PC_SLOTSTATUS;
+ ccidDriver.sCcidMessage.wLength = 0;
+ ccidDriver.sCcidMessage.bSpecific = 0;
+
+ ccidDriver.sCcidMessage.bStatus |= ICC_CS_FAILED;
+
+ // Send the response to the host
+ //vCCIDSendResponse();
+}
+
+//------------------------------------------------------------------------------
+/// Sent CCID response on USB
+//------------------------------------------------------------------------------
+static void vCCIDSendResponse( void )
+{
+ unsigned char bStatus;
+
+ do {
+ bStatus = USBD_Write( CCID_EPT_DATA_IN, (void*)&ccidDriver.sCcidMessage,
+ ccidDriver.sCcidMessage.bSizeToSend, 0, 0 );
+ }
+ while (bStatus != USBD_STATUS_SUCCESS);
+}
+
+
+//------------------------------------------------------------------------------
+/// Description: CCID Command dispatcher
+//------------------------------------------------------------------------------
+static void CCIDCommandDispatcher( void )
+{
+ unsigned char MessageToSend = 0;
+
+ //TRACE_DEBUG("Command: 0x%X 0x%x 0x%X 0x%X 0x%X 0x%X 0x%X\n\r\n\r",
+ // (unsigned int)ccidDriver.sCcidCommand.bMessageType,
+ // (unsigned int)ccidDriver.sCcidCommand.wLength,
+ // (unsigned int)ccidDriver.sCcidCommand.bSlot,
+ // (unsigned int)ccidDriver.sCcidCommand.bSeq,
+ // (unsigned int)ccidDriver.sCcidCommand.bSpecific_0,
+ // (unsigned int)ccidDriver.sCcidCommand.bSpecific_1,
+ // (unsigned int)ccidDriver.sCcidCommand.bSpecific_2);
+
+ // Check the slot number
+ if ( ccidDriver.sCcidCommand.bSlot > 0 ) {
+
+ TRACE_ERROR("BAD_SLOT_NUMBER\n\r");
+ }
+
+ TRACE_DEBUG("typ=0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
+
+ ccidDriver.sCcidMessage.bStatus = 0;
+
+ ccidDriver.sCcidMessage.bSeq = ccidDriver.sCcidCommand.bSeq;
+ ccidDriver.sCcidMessage.bSlot = ccidDriver.sCcidCommand.bSlot;
+
+ ccidDriver.sCcidMessage.bSizeToSend = sizeof(S_ccid_bulk_in_header)-(ABDATA_SIZE+1);
+
+
+ // Command dispatcher
+ switch ( ccidDriver.sCcidCommand.bMessageType ) {
+
+ case PC_TO_RDR_ICCPOWERON:
+ PCtoRDRIccPowerOn();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_ICCPOWEROFF:
+ PCtoRDRIccPowerOff();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_GETSLOTSTATUS:
+ PCtoRDRGetSlotStatus();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_XFRBLOCK:
+ PCtoRDRXfrBlock();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_GETPARAMETERS:
+ PCtoRDRGetParameters();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_RESETPARAMETERS:
+ PCtoRDRResetParameters();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_SETPARAMETERS:
+ PCtoRDRSetParameters();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_ESCAPE:
+ PCtoRDREscape();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_ICCCLOCK:
+ PCtoRDRICCClock();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_T0APDU:
+ // Only CCIDs reporting a short or extended APDU level in the dwFeatures
+ // field of the CCID class descriptor may take this command into account.
+ if( (CCID_FEATURES_EXC_SAPDU == (CCID_FEATURES_EXC_SAPDU&configurationDescriptorsFS.ccid.dwFeatures))
+ || (CCID_FEATURES_EXC_APDU == (CCID_FEATURES_EXC_APDU &configurationDescriptorsFS.ccid.dwFeatures)) ) {
+
+ // command supported
+ PCtoRDRtoAPDU();
+ }
+ else {
+ // command not supported
+ TRACE_DEBUG("PC_TO_RDR_T0APDU\n\r");
+ vCCIDCommandNotSupported();
+ }
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_SECURE:
+ PCtoRDRSecure();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_MECHANICAL:
+ PCtoRDRMechanical();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_ABORT:
+ PCtoRDRAbort();
+ MessageToSend = 1;
+ break;
+
+ case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY:
+ PCtoRDRSetDataRateAndClockFrequency();
+ MessageToSend = 1;
+ break;
+
+ default:
+ TRACE_DEBUG("default: 0x%X\n\r", ccidDriver.sCcidCommand.bMessageType);
+ vCCIDCommandNotSupported();
+ MessageToSend = 1;
+ break;
+
+ }
+
+ if( MessageToSend == 1 ) {
+ vCCIDSendResponse();
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// SETUP request handler for a CCID device
+/// \param pRequest Pointer to a USBGenericRequest instance
+//------------------------------------------------------------------------------
+static void CCID_RequestHandler(const USBGenericRequest *pRequest)
+{
+ TRACE_DEBUG("CCID_RHl\n\r");
+
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_CLASS) {
+
+ // Check if the request is supported
+ switch (USBGenericRequest_GetRequest(pRequest)) {
+
+ case CCIDGenericRequest_ABORT:
+ TRACE_DEBUG("CCIDGenericRequest_ABORT\n\r");
+ break;
+
+ case CCIDGenericRequest_GET_CLOCK_FREQUENCIES:
+ TRACE_DEBUG("Not supported\n\r");
+ // A CCID with bNumClockSupported equal to 00h does not have
+ // to support this request
+ break;
+
+ case CCIDGenericRequest_GET_DATA_RATES:
+ TRACE_DEBUG("Not supported\n\r");
+ // A CCID with bNumDataRatesSupported equal to 00h does not have
+ // to support this request.
+ break;
+
+ default:
+ TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request (%d)\n\r",
+ USBGenericRequest_GetRequest(pRequest));
+ USBD_Stall(0);
+ }
+ }
+
+ else if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_STANDARD) {
+
+ // Forward request to the standard handler
+ USBDDriver_RequestHandler(&(ccidDriver.usbdDriver), pRequest);
+ }
+ else {
+
+ // Unsupported request type
+ TRACE_WARNING( "CCIDDriver_RequestHandler: Unsupported request type (%d)\n\r",
+ USBGenericRequest_GetType(pRequest));
+ USBD_Stall(0);
+ }
+}
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Optional callback re-implementation
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+// not static function
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ CCID_RequestHandler(request);
+}
+#endif
+
+
+//------------------------------------------------------------------------------
+/// Handles SmartCart request
+//------------------------------------------------------------------------------
+void CCID_SmartCardRequest( void )
+{
+ unsigned char bStatus;
+
+ do {
+
+ bStatus = CCID_Read( (void*)&ccidDriver.sCcidCommand,
+ sizeof(S_ccid_bulk_out_header),
+ (TransferCallback)&CCIDCommandDispatcher,
+ (void*)0 );
+ }
+ while (bStatus != USBD_STATUS_SUCCESS);
+
+}
+
+//------------------------------------------------------------------------------
+/// Initializes the CCID device driver.
+//------------------------------------------------------------------------------
+void CCIDDriver_Initialize( void )
+{
+ TRACE_DEBUG("CCID_Init\n\r");
+ USBDDriver_Initialize(&(ccidDriver.usbdDriver),
+ &ccidDriverDescriptors,
+ 0); // Multiple interface settings not supported
+ USBD_Init();
+}
+
+//------------------------------------------------------------------------------
+/// Reads data from the Data OUT endpoint
+/// \param pBuffer Buffer to store the received data
+/// \param dLength data buffer length
+/// \param fCallback Optional callback function
+/// \param pArgument Optional parameter for the callback function
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Read(void *pBuffer,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument)
+{
+ return USBD_Read(CCID_EPT_DATA_OUT, pBuffer, dLength, fCallback, pArgument);
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through the Data IN endpoint
+/// \param pBuffer Buffer holding the data to transmit
+/// \param dLength Length of data buffer
+/// \param fCallback Optional callback function
+/// \param pArgument Optional parameter for the callback function
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Write(void *pBuffer,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument)
+{
+ return USBD_Write(CCID_EPT_DATA_IN, pBuffer, dLength, fCallback, pArgument);
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through the interrupt endpoint, ICC insertion event
+/// RDR_to_PC_NotifySlotChange
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Insertion( void )
+{
+ TRACE_DEBUG("CCID_Insertion\n\r");
+
+ // Build the Interrupt-IN message
+ ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
+ ccidDriver.BufferINT[1] = ICC_INSERTED_EVENT;
+ ccidDriver.SlotStatus = ICC_INSERTED_EVENT;
+
+ // Notify the host that a ICC is inserted
+ return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 );
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through the interrupt endpoint, ICC removal event
+/// RDR_to_PC_NotifySlotChange
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char CCID_Removal( void )
+{
+ TRACE_DEBUG("CCID_Removal\n\r");
+
+ // Build the Interrupt-IN message
+ ccidDriver.BufferINT[0] = RDR_TO_PC_NOTIFYSLOTCHANGE;
+ ccidDriver.BufferINT[1] = ICC_NOT_PRESENT;
+ ccidDriver.SlotStatus = ICC_NOT_PRESENT;
+
+ // Notify the host that a ICC is inserted
+ return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 2, 0, 0 );
+}
+
+//------------------------------------------------------------------------------
+/// Interrupt-IN Messages
+/// This message is sent when any bit in the bHardwareErrorCode field is set.
+/// If this message is sent when there is no “outstanding” command, the bSeq
+/// field will be undefined.
+/// \param bSlot ICC slot number
+/// \param bSeq Sequence number of the bulk OUT command when the hardware error
+/// occured
+/// \param bHardwareErrorCode Hardware error code
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char RDRtoPCHardwareError( unsigned char bSlot,
+ unsigned char bSeq,
+ unsigned char bHardwareErrorCode )
+{
+ TRACE_DEBUG("RDRtoPCHardwareError\n\r");
+
+ // Build the Interrupt-IN message
+ ccidDriver.BufferINT[0] = RDR_TO_PC_HARDWAREERROR;
+ ccidDriver.BufferINT[1] = bSlot;
+ ccidDriver.BufferINT[2] = bSeq;
+ ccidDriver.BufferINT[3] = bHardwareErrorCode;
+
+ // Notify the host that a ICC is inserted
+ return USBD_Write( CCID_EPT_NOTIFICATION, ccidDriver.BufferINT, 4, 0, 0 );
+}
+
+
diff --git a/usb/device/ccid/cciddriver.h b/usb/device/ccid/cciddriver.h new file mode 100644 index 0000000..8bac286 --- /dev/null +++ b/usb/device/ccid/cciddriver.h @@ -0,0 +1,378 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definition of methods for using a CCID device driver.
+///
+/// !Usage
+///
+/// -# CCIDDriver_Initialize
+/// -# CCID_Read
+/// -# CCID_Write
+/// -# CCID_SmartCardRequest
+/// -# CCID_Insertion
+/// -# CCID_Removal
+/// -# RDRtoPCHardwareError
+//------------------------------------------------------------------------------
+
+#ifndef CCID_DRIVER_H
+#define CCID_DRIVER_H
+
+/// For reference, the absolute maximum block size
+/// for a TPDU T=0 block is 260 bytes (5 bytes command; 255 bytes data), or
+/// for a TPDU T=1 block is 259 bytes, or
+/// for a short APDU T=1 block is 261 bytes, or
+/// for an extended APDU T=1 block is 65544 bytes.
+#define ABDATA_SIZE 260
+
+/// define protocol T=0
+#define PROTOCOL_TO 0
+/// define protocol T=1
+#define PROTOCOL_T1 1
+
+/// define for dwFeatures see Table 5.1-1 Smart Card Device Class Descriptors
+/// No special characteristics
+#define CCID_FEATURES_NADA 0x00000000
+/// Automatic parameter configuration based on ATR data
+#define CCID_FEATURES_AUTO_PCONF 0x00000002
+/// Automatic activation of ICC on inserting
+#define CCID_FEATURES_AUTO_ACTIV 0x00000004
+/// Automatic ICC voltage selection
+#define CCID_FEATURES_AUTO_VOLT 0x00000008
+/// Automatic ICC clock frequency change according to active parameters provided
+/// by the Host or self determined
+#define CCID_FEATURES_AUTO_CLOCK 0x00000010
+/// Automatic baud rate change according to active parameters provided by the
+/// Host or self determined
+#define CCID_FEATURES_AUTO_BAUD 0x00000020
+/// Automatic parameters negotiation made by the CCID (use of warm or cold
+/// resets or PPS according to a manufacturer proprietary algorithm to select
+/// the communication parameters with the ICC)
+#define CCID_FEATURES_AUTO_PNEGO 0x00000040
+/// Automatic PPS made by the CCID according to the active parameters
+#define CCID_FEATURES_AUTO_PPS 0x00000080
+/// CCID can set ICC in clock stop mode
+#define CCID_FEATURES_ICCSTOP 0x00000100
+/// NAD value other than 00 accepted (T=1 protocol in use)
+#define CCID_FEATURES_NAD 0x00000200
+/// Automatic IFSD exchange as first exchange (T=1 protocol in use)
+#define CCID_FEATURES_AUTO_IFSD 0x00000400
+/// TPDU level exchanges with CCID
+#define CCID_FEATURES_EXC_TPDU 0x00010000
+/// Short APDU level exchange with CCID
+#define CCID_FEATURES_EXC_SAPDU 0x00020000
+/// Short and Extended APDU level exchange with CCID
+#define CCID_FEATURES_EXC_APDU 0x00040000
+/// USB Wake up signaling supported on card insertion and removal
+#define CCID_FEATURES_WAKEUP 0x00100000
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+/// Bulk CCID Message header structure
+typedef struct
+{
+ unsigned char bMessageType;
+ /// Message-specific data length
+ unsigned long wLength;
+ /// Identifies the slot number for this command
+ unsigned char bSlot;
+ /// Sequence number for command.
+ unsigned char bSeq;
+ /// Slot status register
+ unsigned char bStatus;
+ /// Slot error
+ unsigned char bError;
+ /// specific register
+ unsigned char bSpecific;
+ /// Data block sent to the CCID.
+ unsigned char abData[ABDATA_SIZE];
+ unsigned char bSizeToSend;
+} __attribute__ ((packed)) S_ccid_bulk_in_header;
+
+/// 6.1 Bulk Transfers
+typedef struct
+{
+ unsigned char bMessageType;
+ /// Message-specific data length
+ unsigned long wLength;
+ /// Identifies the slot number for this command
+ unsigned char bSlot;
+ /// Sequence number for command.
+ unsigned char bSeq;
+ /// specific register
+ unsigned char bSpecific_0;
+ unsigned char bSpecific_1;
+ unsigned char bSpecific_2;
+ /// Application Protocol Data Unit
+ unsigned char APDU[ABDATA_SIZE];
+} __attribute__ ((packed)) S_ccid_bulk_out_header;
+
+
+/// 6.1.11.2 PIN Verification Data Structure
+typedef struct
+{
+ /// Number of seconds.
+ unsigned char bTimerOut;
+ /// Several parameters for the PIN format options
+ unsigned char bmFormatString;
+ /// Define the length of the PIN to present in the APDU command
+ unsigned char bmPINBlockString;
+ /// Allows the length PIN insertion in the APDU command
+ unsigned char bmPINLengthFormat;
+ /// Minimum PIN size in digit and Maximum PIN size in digit
+ unsigned char wPINMaxExtraDigit;
+ /// The value is a bit wise OR operation.
+ unsigned char bEntryValidationCondition;
+ /// Number of messages to display for the PIN modify command
+ unsigned char bNumberMessage;
+ /// Language used to display the messages.
+ unsigned char wLangId;
+ /// Message index in the Reader message table
+ unsigned char bMsgIndex;
+ /// T=1 I-block prologue field to use
+ unsigned char bTeoPrologue[3];
+ /// APDU to send to the ICC
+ unsigned char abPINApdu[255];
+}__attribute__ ((packed)) S_ccid_PIN_Verification;
+
+
+/// 6.1.11.7 PIN Modification Data Structure
+typedef struct
+{
+ /// Number of seconds. If 00h then CCID default value is used.
+ unsigned char bTimeOut;
+ /// Several parameters for the PIN format options (defined in § 6.1.11.4)
+ unsigned char bmFormatString4;
+ /// Define the length of the PIN to present in the APDU command
+ unsigned char bmPINBlockString;
+ /// Allows the length PIN insertion in the APDU command (defined in § 6.1.11.6)
+ unsigned char bmPinLengthFormat;
+ /// Insertion position offset in byte for the current PIN
+ unsigned char bInsertionOffsetOld;
+ /// Insertion position offset in byte for the new PIN
+ unsigned char bInsertionOffsetNew;
+ /// XXYYh
+ /// XX: Minimum PIN size in digit
+ /// YY: Maximum PIN size in digit
+ unsigned char wPINMaxExtraDigit;
+ /// 00h,01h,02h,03h
+ /// Indicates if a confirmation is requested before acceptance of a new PIN (meaning that the user has to enter this new PIN twice before it is accepted)
+ /// Indicates if the current PIN must be entered and set in the same APDU field of not.
+ unsigned char bConfirmPIN;
+ /// The value is a bit wise OR operation.
+ /// 01h Max size reached
+ /// 02h Validation key pressed
+ /// 04h Timeout occurred
+ unsigned char bEntryValidationCondition;
+ /// 00h,01h,02h,03h,or FFh
+ /// Number of messages to display for the PIN modify command.
+ unsigned char bNumberMessage;
+ /// Language used to display the messages. The 16 bit
+ unsigned char wLangId;
+ /// Message index in the Reader message table (should be 00h or 01h).
+ unsigned char bMsgIndex1;
+ /// Message index in the Reader message table (should be 01h or 02h).
+ unsigned char bMsgIndex2;
+ /// Message index in the Reader message table (should be 02h).
+ unsigned char bMsgIndex3;
+ /// T=1 I-block prologue field to use. Significant only if protocol in use is T=1.
+ unsigned char bTeoPrologue[3];
+ /// Byte array APDU to send to the ICC
+ unsigned char abPINApdu[255];
+}__attribute__ ((packed)) S_ccid_PIN_Modification;
+
+/// Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h)
+typedef struct
+{
+ /// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
+ /// clock rate conversion factor
+ /// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
+ /// baud rate conversion factor
+ unsigned char bmFindexDindex;
+ /// For T=0 ,B0 – 0b, B7-2 – 000000b
+ /// B1 – Convention used (b1=0 for direct, b1=1 for inverse)
+ unsigned char bmTCCKST0; // 0 to 2
+ /// Extra Guardtime between two characters. Add 0 to 254 etu to the normal
+ /// guardtime of 12etu. FFh is the same as 00h.
+ unsigned char bGuardTimeT0; // 0 to FF
+ /// WI for T=0 used to define WWT
+ unsigned char bWaitingIntegerT0; // 0 to FF
+ /// ICC Clock Stop Support
+ /// 00 = Stopping the Clock is not allowed
+ /// 01 = Stop with Clock signal Low
+ /// 02 = Stop with Clock signal High
+ /// 03 = Stop with Clock either High or Low
+ unsigned char bClockStop; // 0 to 3
+} __attribute__ ((packed)) S_ccid_protocol_t0;
+
+
+/// Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h)
+typedef struct
+{
+ /// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
+ /// clock rate conversion factor
+ /// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
+ /// baud rate conversion factor
+ unsigned char bmFindexDindex;
+ /// For T=1, B7-2 – 000100b
+ /// B0 – Checksum type (b0=0 for LRC, b0=1 for CRC
+ /// B1 – Convention used (b1=0 for direct, b1=1 for inverse)
+ unsigned char bmTCCKST1; // 10h, 11h, 12h, 13h
+ /// Extra Guardtime (0 to 254 etu between two characters).
+ /// If value is FFh, then guardtime is reduced by 1.
+ unsigned char bGuardTimeT1; // 0 to FF
+ /// B7-4 = BWI
+ /// B3-0 = CWI
+ unsigned char bmWaitingIntegersT1; // 0 to 9
+ /// ICC Clock Stop Support
+ /// 00 = Stopping the Clock is not allowed
+ /// 01 = Stop with Clock signal Low
+ /// 02 = Stop with Clock signal High
+ /// 03 = Stop with Clock either High or Low
+ unsigned char bClockStop; // 0 to 3
+ /// Size of negotiated IFSC
+ unsigned char bIFSC; // 0 to FE
+ /// Nad value used by CCID
+ unsigned char bNadValue; // 0 to FF
+} __attribute__ ((packed)) S_ccid_protocol_t1;
+
+
+/// Identifies the length of type of subordinate descriptors of a CCID device
+/// Table 5.1-1 Smart Card Device Class descriptors
+typedef struct
+{
+ /// Size of this descriptor, in bytes.
+ unsigned char bLength;
+ /// Functional Descriptor type
+ unsigned char bDescriptorType;
+ /// Integrated Circuit(s) Cards Interface Devices (CCID) Specification
+ /// Release Number
+ unsigned short bcdCCID;
+ /// Index of the highest available slot. An USB-ICC is regarded as a single
+ /// slot CCID.
+ unsigned char bMaxSlotIndex;
+ /// This value indicates what voltages the CCID can supply to its slots.
+ /// It is a bitwise OR operation performed on the following values:
+ /// - 01h 5.0V
+ /// - 02h 3.0V
+ /// - 04h 1.8V
+ /// Other bits are RFU.
+ unsigned char bVoltageSupport;
+ /// RRRR –Upper Word- is RFU = 0000h
+ /// PPPP –Lower Word- Encodes the supported protocol types. A ‘1’ in a given
+ /// bit position indicates support for the associated ISO protocol.
+ /// 0001h = Protocol T=0
+ /// 0002h = Protocol T=1
+ /// All other bits are reserved and must be set to zero. The field is
+ /// intended to correspond to the PCSC specification definitions.
+ unsigned long dwProtocols;
+ /// Default ICC clock frequency in KHz. This is an integer value.
+ unsigned long dwDefaultClock;
+ /// Maximum supported ICC clock frequency in KHz. This is an integer value.
+ unsigned long dwMaximumClock;
+ /// The number of clock frequencies that are supported by the CCID. If the
+ /// value is 00h, the supported clock frequencies are assumed to be the
+ /// default clock frequency defined by dwDefaultClock and the maximum clock
+ /// frequency defined by dwMaximumClock.
+ unsigned char bNumClockSupported;
+ /// Default ICC I/O data rate in bps. This is an integer value
+ unsigned long dwDataRate;
+ /// Maximum supported ICC I/O data rate in bps
+ unsigned long dwMaxDataRate;
+ /// The number of data rates that are supported by the CCID.
+ unsigned char bNumDataRatesSupported;
+ /// Indicates the maximum IFSD supported by CCID for protocol T=1.
+ unsigned long dwMaxIFSD;
+ /// - RRRR-Upper Word- is RFU = 0000h
+ /// - PPPP-Lower Word- encodes the supported protocol types. A ‘1’ in a given
+ /// bit position indicates support for the associated protocol.
+ /// 0001h indicates support for the 2-wire protocol 1
+ /// 0002h indicates support for the 3-wire protocol 1
+ /// 0004h indicates support for the I2C protocol 1
+ /// All other values are outside of this specification, and must be handled
+ /// by vendor-supplied drivers.
+ unsigned long dwSynchProtocols;
+ /// The value is a bitwise OR operation performed on the following values:
+ /// - 00000000h No special characteristics
+ /// - 00000001h Card accept mechanism 2
+ /// - 00000002h Card ejection mechanism 2
+ /// - 00000004h Card capture mechanism 2
+ /// - 00000008h Card lock/unlock mechanism
+ unsigned long dwMechanical;
+ /// This value indicates what intelligent features the CCID has.
+ unsigned long dwFeatures;
+ /// For extended APDU level the value shall be between 261 + 10 (header) and
+ /// 65544 +10, otherwise the minimum value is the wMaxPacketSize of the
+ /// Bulk-OUT endpoint.
+ unsigned long dwMaxCCIDMessageLength;
+ /// Significant only for CCID that offers an APDU level for exchanges.
+ unsigned char bClassGetResponse;
+ /// Significant only for CCID that offers an extended APDU level for exchanges.
+ unsigned char bClassEnvelope;
+ /// Number of lines and characters for the LCD display used to send messages for PIN entry.
+ unsigned short wLcdLayout;
+ /// This value indicates what PIN support features the CCID has.
+ unsigned char bPINSupport;
+ /// Maximum number of slots which can be simultaneously busy.
+ unsigned char bMaxCCIDBusySlots;
+
+} __attribute__ ((packed)) CCIDDescriptor;
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern unsigned char RDRtoPCHardwareError( unsigned char bSlot,
+ unsigned char bSeq,
+ unsigned char bHardwareErrorCode );
+
+#if !defined(NOAUTOCALLBACK)
+extern void USBDCallbacks_RequestReceived(const USBGenericRequest *pRequest);
+#endif
+extern void CCID_SmartCardRequest( void );
+extern void CCIDDriver_Initialize( void );
+extern unsigned char CCID_Read(void *pBuffer,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument);
+extern unsigned char CCID_Write(void *pBuffer,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument);
+extern unsigned char CCID_Insertion( void );
+extern unsigned char CCID_Removal( void );
+
+#endif //#ifndef CCID_DRIVER_H
+
diff --git a/usb/device/ccid/cciddriverdescriptors.h b/usb/device/ccid/cciddriverdescriptors.h new file mode 100644 index 0000000..2daea67 --- /dev/null +++ b/usb/device/ccid/cciddriverdescriptors.h @@ -0,0 +1,152 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+// Title: cciddriverdescriptors.h
+//
+// About: Purpose
+// Definitions of the descriptors required by the ccid device driver.
+// DWG_Smart-Card_CCID_Rev110.pdf
+//------------------------------------------------------------------------------
+
+#ifndef CCID_DRIVER_DESCRIPTORS_H
+#define CCID_DRIVER_DESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Constants: Endpoints
+// CCID_EPT_DATA_OUT endpoint data out bulk 1
+// CCID_EPT_DATA_IN endpoint data in bulk 2
+// CCID_EPT_NOTIFICATION endpoint data interupt 3
+//------------------------------------------------------------------------------
+#define CCID_EPT_DATA_OUT 1
+#define CCID_EPT_DATA_IN 2
+#define CCID_EPT_NOTIFICATION 3
+
+//------------------------------------------------------------------------------
+// USB-ICC protocol
+//------------------------------------------------------------------------------
+// CCID specification version 1.10
+#define CCID1_10 0x0110
+
+#define SMART_CARD_DEVICE_CLASS 0x0B
+// Smart Card Device Class Descriptor Type
+#define CCID_DECRIPTOR_TYPE 0x21
+
+// Table 5.3-1 Summary of CCID Class Specific Request
+#define CCIDGenericRequest_ABORT 0x01
+#define CCIDGenericRequest_GET_CLOCK_FREQUENCIES 0x02
+#define CCIDGenericRequest_GET_DATA_RATES 0x03
+
+// 6.1 Command Pipe, Bulk-OUT Messages
+#define PC_TO_RDR_ICCPOWERON 0x62
+#define PC_TO_RDR_ICCPOWEROFF 0x63
+#define PC_TO_RDR_GETSLOTSTATUS 0x65
+#define PC_TO_RDR_XFRBLOCK 0x6F
+#define PC_TO_RDR_GETPARAMETERS 0x6C
+#define PC_TO_RDR_RESETPARAMETERS 0x6D
+#define PC_TO_RDR_SETPARAMETERS 0x61
+#define PC_TO_RDR_ESCAPE 0x6B
+#define PC_TO_RDR_ICCCLOCK 0x6E
+#define PC_TO_RDR_T0APDU 0x6A
+#define PC_TO_RDR_SECURE 0x69
+#define PC_TO_RDR_MECHANICAL 0x71
+#define PC_TO_RDR_ABORT 0x72
+#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73
+
+// 6.2 Response Pipe, Bulk-IN Messages
+#define RDR_TO_PC_DATABLOCK 0x80
+#define RDR_TO_PC_SLOTSTATUS 0x81
+#define RDR_TO_PC_PARAMETERS 0x82
+#define RDR_TO_PC_ESCAPE 0x83
+#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84
+
+// 6.3 Interrupt-IN Messages
+#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50
+#define RDR_TO_PC_HARDWAREERROR 0x51
+
+// Table 6.2-2 Slot error register when bmCommandStatus = 1
+#define CMD_ABORTED 0xFF
+#define ICC_MUTE 0xFE
+#define XFR_PARITY_ERROR 0xFD
+#define XFR_OVERRUN 0xFC
+#define HW_ERROR 0xFB
+#define BAD_ATR_TS 0xF8
+#define BAD_ATR_TCK 0xF7
+#define ICC_PROTOCOL_NOT_SUPPORTED 0xF6
+#define ICC_CLASS_NOT_SUPPORTED 0xF5
+#define PROCEDURE_BYTE_CONFLICT 0xF4
+#define DEACTIVATED_PROTOCOL 0xF3
+#define BUSY_WITH_AUTO_SEQUENCE 0xF2
+#define PIN_TIMEOUT 0xF0
+#define PIN_CANCELLED 0xEF
+#define CMD_SLOT_BUSY 0xE0
+// User defined 0xC0 to 0x81
+// Reserved for futur use 0x80
+// not supported incorrect message parameter 0x7F to 0x01
+// Command not supported 0x00
+
+// CCID rev 1.1, p.27
+#define VOLTS_AUTO 0x00
+#define VOLTS_5_0 0x01
+#define VOLTS_3_0 0x02
+#define VOLTS_1_8 0x03
+
+// 6.3.1 RDR_to_PC_NotifySlotChange
+#define ICC_NOT_PRESENT 0x00
+#define ICC_PRESENT 0x01
+#define ICC_CHANGE 0x02
+#define ICC_INSERTED_EVENT ICC_PRESENT+ICC_CHANGE
+
+// ICCD: Table 6.1-8 Bitmap for bStatus field
+#define ICC_BS_PRESENT_ACTIVATED 0x00 // USB-ICC is present and activated
+#define ICC_BS_PRESENT_NOTACTIVATED 0x01 // USB-ICC is present but not activated
+#define ICC_BS_NOTPRESENT 0x02 // USB-ICC is virtually not present
+#define ICC_BS_RFU 0x03 // RFU
+#define ICC_CS_NO_ERROR (0x00<<6) // Processed without error
+#define ICC_CS_FAILED (0x01<<6) // Failed, error condition given by bError
+#define ICC_CS_TIME_EXT (0x02<<6) // Time extension is requested
+#define ICC_CS_RFU (0x03<<6) // RFU
+
+/*
+#define NO_ERROR 0x00
+#define NO_EXTRA_BYTES 0x00
+#define CCID_FLAG_INITIAL_VALUE 0x05
+#define CCID_EVENT_SIZE 0x02
+#define STATUS_MASK 0x41
+*/
+//------------------------------------------------------------------------------
+// Structures
+//------------------------------------------------------------------------------
+
+#endif //#ifndef CCID_DRIVER_DESCRIPTORS_H
+
diff --git a/usb/device/cdc-serial/CDCDSerialDriver.c b/usb/device/cdc-serial/CDCDSerialDriver.c new file mode 100644 index 0000000..3e58592 --- /dev/null +++ b/usb/device/cdc-serial/CDCDSerialDriver.c @@ -0,0 +1,300 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: CDCDSerialDriver implementation
+
+ About: Purpose
+ Implementation of the CDCDSerialDriver class methods.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "CDCDSerialDriver.h"
+#include "CDCDSerialDriverDescriptors.h"
+#include <utility/trace.h>
+#include <utility/assert.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/common/cdc/CDCLineCoding.h>
+#include <usb/common/cdc/CDCGenericRequest.h>
+#include <usb/common/cdc/CDCSetControlLineStateRequest.h>
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// USB driver for a CDC class implementing a virtual COM serial connection.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard USBDDriver instance.
+ USBDDriver usbdDriver;
+ /// Current line coding (baudrate, parity, stop bits).
+ CDCLineCoding lineCoding;
+ /// Indicates if the RS232 carrier is active.
+ unsigned char isCarrierActivated;
+ /// Current serial port states
+ unsigned short serialState;
+
+} CDCDSerialDriver;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Static instance of the CDC serial driver.
+static CDCDSerialDriver cdcdSerialDriver;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Callback function which should be invoked after the data of a
+/// SetLineCoding request has been retrieved. Sends a zero-length packet
+/// to the host for acknowledging the request.
+//------------------------------------------------------------------------------
+static void CDCDSerialDriver_SetLineCodingCallback()
+{
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Receives new line coding information from the USB host.
+//------------------------------------------------------------------------------
+static void CDCDSerialDriver_SetLineCoding()
+{
+ TRACE_INFO_WP("sLineCoding ");
+
+ USBD_Read(0,
+ (void *) &(cdcdSerialDriver.lineCoding),
+ sizeof(CDCLineCoding),
+ (TransferCallback) CDCDSerialDriver_SetLineCodingCallback,
+ 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current line coding information to the host through Control
+/// endpoint 0.
+//------------------------------------------------------------------------------
+static void CDCDSerialDriver_GetLineCoding()
+{
+ TRACE_INFO_WP("gLineCoding ");
+
+ USBD_Write(0,
+ (void *) &(cdcdSerialDriver.lineCoding),
+ sizeof(CDCLineCoding),
+ 0,
+ 0);
+}
+
+//------------------------------------------------------------------------------
+/// Changes the state of the serial driver according to the information
+/// sent by the host via a SetControlLineState request, and acknowledges
+/// the request with a zero-length packet.
+//------------------------------------------------------------------------------
+static void CDCDSerialDriver_SetControlLineState(unsigned char activateCarrier,
+ unsigned char isDTEPresent)
+{
+ TRACE_INFO_WP(
+ "sControlLineState(%d, %d) ",
+ activateCarrier,
+ isDTEPresent);
+
+ cdcdSerialDriver.isCarrierActivated = activateCarrier;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+//------------------------------------------------------------------------------
+/// Re-implemented callback, invoked when a new USB Request is received.
+//------------------------------------------------------------------------------
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ CDCDSerialDriver_RequestHandler(request);
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the USB Device CDC serial driver & USBD Driver.
+//------------------------------------------------------------------------------
+void CDCDSerialDriver_Initialize()
+{
+ TRACE_INFO("CDCDSerialDriver_Initialize\n\r");
+
+ // Initialize Abstract Control Model attributes
+ CDCLineCoding_Initialize(&(cdcdSerialDriver.lineCoding),
+ 115200,
+ CDCLineCoding_ONESTOPBIT,
+ CDCLineCoding_NOPARITY,
+ 8);
+ cdcdSerialDriver.isCarrierActivated = 0;
+ cdcdSerialDriver.serialState = 0;
+
+ // Initialize the standard driver
+ USBDDriver_Initialize(&(cdcdSerialDriver.usbdDriver),
+ &cdcdSerialDriverDescriptors,
+ 0); // Multiple settings for interfaces not supported
+
+ // Initialize the USB driver
+ USBD_Init();
+}
+
+//------------------------------------------------------------------------------
+/// Handles CDC-specific SETUP requests. Should be called from a
+/// re-implementation of USBDCallbacks_RequestReceived() method.
+/// \param Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+void CDCDSerialDriver_RequestHandler(const USBGenericRequest *request)
+{
+ TRACE_INFO_WP("NewReq ");
+
+ // Handle the request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case CDCGenericRequest_SETLINECODING:
+
+ CDCDSerialDriver_SetLineCoding();
+ break;
+
+ case CDCGenericRequest_GETLINECODING:
+
+ CDCDSerialDriver_GetLineCoding();
+ break;
+
+ case CDCGenericRequest_SETCONTROLLINESTATE:
+
+ CDCDSerialDriver_SetControlLineState(
+ CDCSetControlLineStateRequest_ActivateCarrier(request),
+ CDCSetControlLineStateRequest_IsDtePresent(request));
+
+ break;
+
+ default:
+
+ USBDDriver_RequestHandler(&(cdcdSerialDriver.usbdDriver), request);
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Receives data from the host through the virtual COM port created by
+/// the CDC device serial driver. This function behaves like USBD_Read.
+/// \param data Pointer to the data buffer to put received data.
+/// \param size Size of the data buffer in bytes.
+/// \param callback Optional callback function to invoke when the transfer
+/// finishes.
+/// \param argument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the read operation has been started normally;
+/// otherwise, the corresponding error code.
+//------------------------------------------------------------------------------
+unsigned char CDCDSerialDriver_Read(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Read(CDCDSerialDriverDescriptors_DATAOUT,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//------------------------------------------------------------------------------
+/// Sends a data buffer through the virtual COM port created by the CDC
+/// device serial driver. This function behaves exactly like USBD_Write.
+/// \param data Pointer to the data buffer to send.
+/// \param size Size of the data buffer in bytes.
+/// \param callback Optional callback function to invoke when the transfer
+/// finishes.
+/// \param argument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the read operation has been started normally;
+/// otherwise, the corresponding error code.
+//------------------------------------------------------------------------------
+unsigned char CDCDSerialDriver_Write(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Write(CDCDSerialDriverDescriptors_DATAIN,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current status of the RS-232 line.
+//------------------------------------------------------------------------------
+unsigned short CDCDSerialDriver_GetSerialState()
+{
+ return cdcdSerialDriver.serialState;
+}
+
+//------------------------------------------------------------------------------
+/// Sets the current serial state of the device to the given value.
+/// \param serialState New device state.
+//------------------------------------------------------------------------------
+void CDCDSerialDriver_SetSerialState(unsigned short serialState)
+{
+ ASSERT((serialState & 0xFF80) == 0,
+ "CDCDSerialDriver_SetSerialState: Bits D7-D15 are reserved\n\r");
+
+ // If new state is different from previous one, send a notification to the
+ // host
+ if (cdcdSerialDriver.serialState != serialState) {
+
+ cdcdSerialDriver.serialState = serialState;
+ USBD_Write(CDCDSerialDriverDescriptors_NOTIFICATION,
+ &(cdcdSerialDriver.serialState),
+ 2,
+ 0,
+ 0);
+
+ // Reset one-time flags
+ cdcdSerialDriver.serialState &= ~(CDCDSerialDriver_STATE_OVERRUN
+ | CDCDSerialDriver_STATE_PARITY
+ | CDCDSerialDriver_STATE_FRAMING
+ | CDCDSerialDriver_STATE_RINGSIGNAL
+ | CDCDSerialDriver_STATE_BREAK);
+ }
+}
+
diff --git a/usb/device/cdc-serial/CDCDSerialDriver.h b/usb/device/cdc-serial/CDCDSerialDriver.h new file mode 100644 index 0000000..5ccc901 --- /dev/null +++ b/usb/device/cdc-serial/CDCDSerialDriver.h @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for implementing a USB device CDC serial driver.
+
+ !!!Usage
+
+ -# Re-implement the USBDCallbacks_RequestReceived method to pass
+ received requests to CDCDSerialDriver_RequestHandler. *This is
+ automatically done unless the NOAUTOCALLBACK symbol is defined*.
+ -# Initialize the CDC serial and USB drivers using
+ CDCDSerialDriver_Initialize.
+ -# Logically connect the device to the host using USBD_Connect.
+ -# Send serial data to the USB host using CDCDSerialDriver_Write.
+ -# Receive serial data from the USB host using CDCDSerialDriver_Read.
+*/
+
+#ifndef CDCDSERIALDRIVER_H
+#define CDCDSERIALDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Serial Port States"
+/// This page lists the bit map for CDC Serial Port States.
+///
+/// !BitMaps
+/// - CDCDSerialDriver_STATE_RXDRIVER
+/// - CDCDSerialDriver_STATE_TXCARRIER
+/// - CDCDSerialDriver_STATE_BREAK
+/// - CDCDSerialDriver_STATE_RINGSIGNAL
+/// - CDCDSerialDriver_STATE_FRAMING
+/// - CDCDSerialDriver_STATE_PARITY
+/// - CDCDSerialDriver_STATE_OVERRUN
+
+/// Indicates the receiver carrier signal is present.
+#define CDCDSerialDriver_STATE_RXDRIVER (1 << 0)
+/// Indicates the transmission carrier signal is present.
+#define CDCDSerialDriver_STATE_TXCARRIER (1 << 1)
+/// Indicates a break has been detected.
+#define CDCDSerialDriver_STATE_BREAK (1 << 2)
+/// Indicates a ring signal has been detected.
+#define CDCDSerialDriver_STATE_RINGSIGNAL (1 << 3)
+/// Indicates a framing error has occured.
+#define CDCDSerialDriver_STATE_FRAMING (1 << 4)
+/// Indicates a parity error has occured.
+#define CDCDSerialDriver_STATE_PARITY (1 << 5)
+/// Indicates a data overrun error has occured.
+#define CDCDSerialDriver_STATE_OVERRUN (1 << 6)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void CDCDSerialDriver_Initialize();
+
+extern void CDCDSerialDriver_RequestHandler(const USBGenericRequest *request);
+
+extern unsigned char CDCDSerialDriver_Write(
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument);
+
+extern unsigned char CDCDSerialDriver_Read(
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument);
+
+extern unsigned short CDCDSerialDriver_GetSerialState();
+
+extern void CDCDSerialDriver_SetSerialState(unsigned short serialState);
+
+#endif //#ifndef CDCSERIALDRIVER_H
+
diff --git a/usb/device/cdc-serial/CDCDSerialDriverDescriptors.c b/usb/device/cdc-serial/CDCDSerialDriverDescriptors.c new file mode 100644 index 0000000..8864451 --- /dev/null +++ b/usb/device/cdc-serial/CDCDSerialDriverDescriptors.c @@ -0,0 +1,661 @@ +/* ----------------------------------------------------------------------------
+ * 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 "CDCDSerialDriverDescriptors.h"
+#include <board.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+#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>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Serial Device IDs"
+/// This page lists the IDs used in the CDC Serial Device Descriptor.
+///
+/// !IDs
+/// - CDCDSerialDriverDescriptors_PRODUCTID
+/// - CDCDSerialDriverDescriptors_VENDORID
+/// - CDCDSerialDriverDescriptors_RELEASE
+
+/// Device product ID.
+#define CDCDSerialDriverDescriptors_PRODUCTID 0x6119
+/// Device vendor ID (Atmel).
+#define CDCDSerialDriverDescriptors_VENDORID 0x03EB
+/// Device release number.
+#define CDCDSerialDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+/// Returns the minimum between two values.
+#define MIN(a, b) ((a < b) ? a : b)
+
+//------------------------------------------------------------------------------
+// Internal structures
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Configuration descriptor list for a device implementing a CDC serial driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration descriptor.
+ USBConfigurationDescriptor configuration;
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ USBOtgDescriptor otgDescriptor;
+#endif
+ /// Communication interface descriptor.
+ USBInterfaceDescriptor communication;
+ /// CDC header functional descriptor.
+ CDCHeaderDescriptor header;
+ /// CDC call management functional descriptor.
+ CDCCallManagementDescriptor callManagement;
+ /// CDC abstract control management functional descriptor.
+ CDCAbstractControlManagementDescriptor abstractControlManagement;
+ /// CDC union functional descriptor (with one slave interface).
+ CDCUnionDescriptor union1;
+ /// Notification endpoint descriptor.
+ USBEndpointDescriptor notification;
+ /// Data interface descriptor.
+ USBInterfaceDescriptor data;
+ /// Data OUT endpoint descriptor.
+ USBEndpointDescriptor dataOut;
+ /// Data IN endpoint descriptor.
+ USBEndpointDescriptor dataIn;
+
+} __attribute__ ((packed)) CDCDSerialDriverConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Standard USB device descriptor for the CDC serial driver
+const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ CDCDeviceDescriptor_CLASS,
+ CDCDeviceDescriptor_SUBCLASS,
+ CDCDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ CDCDSerialDriverDescriptors_VENDORID,
+ CDCDSerialDriverDescriptors_PRODUCTID,
+ CDCDSerialDriverDescriptors_RELEASE,
+ 0, // No string descriptor for manufacturer
+ 1, // Index of product string descriptor is #1
+ 0, // No string descriptor for serial number
+ 1 // Device has 1 possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// USB device qualifier descriptor.
+const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ USBDeviceDescriptor_USB2_00,
+ CDCDeviceDescriptor_CLASS,
+ CDCDeviceDescriptor_SUBCLASS,
+ CDCDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+#endif
+
+/// Standard USB configuration descriptor for the CDC serial driver
+const CDCDSerialDriverConfigurationDescriptors configurationDescriptorsFS = {
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CDCDSerialDriverConfigurationDescriptors),
+ 2, // There are two interfaces in this configuration
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ 0 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ 0, // Number of master interface is #0
+ 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ 10 // Endpoint is polled every 10ms
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ }
+};
+
+/// Language ID string descriptor
+const unsigned char languageIdStringDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Other-speed configuration descriptor (when in full-speed).
+const CDCDSerialDriverConfigurationDescriptors otherSpeedDescriptorsFS = {
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(CDCDSerialDriverConfigurationDescriptors),
+ 2, // There are two interfaces in this configuration
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ 0 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ 0, // Number of master interface is #0
+ 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
+ 10 // Endpoint is polled every 10ms
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ }
+};
+
+
+/// Configuration descriptor (when in high-speed).
+const CDCDSerialDriverConfigurationDescriptors configurationDescriptorsHS = {
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CDCDSerialDriverConfigurationDescriptors),
+ 2, // There are two interfaces in this configuration
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ 0 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ 0, // Number of master interface is #0
+ 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_HS),
+ 8 // Endpoint is polled every 16ms
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ }
+};
+
+/// Other-speed configuration descriptor (when in high-speed).
+const CDCDSerialDriverConfigurationDescriptors otherSpeedDescriptorsHS = {
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(CDCDSerialDriverConfigurationDescriptors),
+ 2, // There are two interfaces in this configuration
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ 0 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ 0, // Number of master interface is #0
+ 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ 10 // Endpoint is polled every 10ms
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ }
+};
+#endif
+
+/// Product string descriptor
+const unsigned char productStringDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(13),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('U'),
+ USBStringDescriptor_UNICODE('S'),
+ USBStringDescriptor_UNICODE('B'),
+ USBStringDescriptor_UNICODE('S'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('r'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('l')
+};
+
+/// List of string descriptors used by the device
+const unsigned char *stringDescriptors[] = {
+
+ languageIdStringDescriptor,
+ productStringDescriptor,
+};
+
+/// List of standard descriptors for the serial driver.
+USBDDriverDescriptors cdcdSerialDriverDescriptors = {
+
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &(configurationDescriptorsFS),
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &(otherSpeedDescriptorsFS),
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &(configurationDescriptorsHS),
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &(otherSpeedDescriptorsHS),
+#else
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration
+ 0, // No high-speed device descriptor
+ 0, // No high-speed configuration descriptor
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+
+#endif
+ stringDescriptors,
+ 2 // 2 string descriptors in list
+};
+
diff --git a/usb/device/cdc-serial/CDCDSerialDriverDescriptors.h b/usb/device/cdc-serial/CDCDSerialDriverDescriptors.h new file mode 100644 index 0000000..8ab4edf --- /dev/null +++ b/usb/device/cdc-serial/CDCDSerialDriverDescriptors.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of the USB descriptors required by a CDC device serial
+ driver.
+*/
+
+#ifndef CDCDSERIALDRIVERDESCRIPTORS_H
+#define CDCDSERIALDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "CDC Serial Endpoints"
+/// This page lists the endpoints used in CDC Serial Device.
+///
+/// !Endpoints
+/// - CDCDSerialDriverDescriptors_DATAOUT
+/// - CDCDSerialDriverDescriptors_DATAIN
+/// - CDCDSerialDriverDescriptors_NOTIFICATION
+
+/// Data OUT endpoint number.
+#define CDCDSerialDriverDescriptors_DATAOUT 1
+/// Data IN endpoint number.
+#define CDCDSerialDriverDescriptors_DATAIN 2
+/// Notification endpoint number.
+#define CDCDSerialDriverDescriptors_NOTIFICATION 3
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors for a CDC device serial driver.
+extern USBDDriverDescriptors cdcdSerialDriverDescriptors;
+
+#endif //#ifndef CDCDDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/cdc-serial/CDCarchitecture.png b/usb/device/cdc-serial/CDCarchitecture.png Binary files differnew file mode 100644 index 0000000..9d0e924 --- /dev/null +++ b/usb/device/cdc-serial/CDCarchitecture.png diff --git a/usb/device/cdc-serial/USB-SerialConverter.png b/usb/device/cdc-serial/USB-SerialConverter.png Binary files differnew file mode 100644 index 0000000..bc05c1f --- /dev/null +++ b/usb/device/cdc-serial/USB-SerialConverter.png diff --git a/usb/device/cdc-serial/cdc-serial.dir b/usb/device/cdc-serial/cdc-serial.dir new file mode 100644 index 0000000..ff18ab0 --- /dev/null +++ b/usb/device/cdc-serial/cdc-serial.dir @@ -0,0 +1,646 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB CDC
+/// %device - USB CDC Serial Converter demo, to implement an USB Serial COM port
+/// driver.
+///
+/// !!!Contents
+///
+/// There are two things for the implement of the USB CDC Serial %device driver:
+/// - Implement the CDC Serial driver structs and functions for the %device,
+/// to initialize, to handle CDC-specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the CDC Serial device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the %device as a USB CDC Serial COM port %device.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB CDC Serial Device".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB CDC Serial Device"
+ This page describes how to use the USB framework to produce a USB CDC Serial
+ Device driver, which appears as a virtual COM port on host.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/CDC1.2_WMC1.1.zip">
+ Communication Device Class Documents</a> (.zip file format)
+ - Abstract Control Model Serial Emulation (USB Class Definitions for
+ Communication Devices, section 3.6.2.1).
+
+ !!!Communication Device Class
+
+ You can get some basic information about the Communication Device Class.
+
+ !!Purpose
+
+ CDC is used to connect communication devices, such as modems (digital or
+ analog), telephones or networking devices. Its generic framework supports a
+ wide variety of physical layers (xDSL, ATM, etc.) and protocols.
+
+ In this document, CDC is used to implement a USB to a serial data converter.
+ A USB to serial converter can be used in this case to bridge a legacy RS-232
+ interface with a USB port.
+
+ !!Architecture
+ ...
+
+ !Communication Class Interface
+ The #Communication Class Interface# is used for %device management. It
+ includes requests to manage the %device state, its responses, as well as
+ event notifications. This interface can also be optionally used for call
+ management, i.e., setting up and terminating calls as well as managing
+ their parameters.
+
+ The interface requires at least one endpoint (#Default EP0#) to used for
+ %device management. Optionally, another endpoint can be dedicated to
+ event notification. This will usually be an #Interrupt IN# endpoint.
+
+ !Data Class Interface
+ The #Data Class Interface# is used for generic data transmissions. It provides
+ a means for a communication %device to actually transfer data to and from the
+ host. In addition, it also enables the multiplexing of data and commands on
+ the same interface, through the use of wrappers.
+
+ %Endpoints for this interface must exist in pairs of the same type. This is
+ necessary to allow both IN and OUT communication. Only the #Bulk# and
+ #Isochronous# types can be used for these %endpoints.
+
+ \image CDCArchitecture.png "CDC Class Driver Architecture"
+
+ !Models
+ To account for the wide variety of existing communication devices, several
+ #models# have been defined, for more details you can refer to CDC spec. 1.1.
+ - POTS (Plain Old Telephone Service)
+ - Direct Line Control Model
+ - Datapump Model
+ - Abstract Control Model (ACM)
+ - Telephone
+ - Telephone Control Model
+ - ISDN
+ - Multi-Channel Model
+ - USB CAPI Model
+ - Networking
+ - Ethernet Networking Model
+ - ATM Networking Control Model
+
+ !Class-specific Descriptors
+ CDC-specific information is described using Functional Descriptors. They
+ define various parameters of an interface, such as how the %device handles
+ call management, or model-specific attributes.
+
+ Since the CDC specification defines quite a number of functional descriptors,
+ they are not detailed here. Instead, they are presented in the various case
+ studies of this document in which they are used.
+
+ !!Host Drivers
+ Most Operating Systems (OS) now include generic drivers for a wide variety of
+ USB classes. This makes developing a %device simpler, since the host complexity
+ is now handled by the OS. Manufacturers can thus concentrate on the %device
+ itself, not on developing specific host drivers.
+
+ Here is a brief list of the various CDC implementations supported by several
+ OS:
+ - Windows
+ - Abstract Control Model
+ - Remote NDIS
+ - Linux
+ - Abstract Control Model
+ - Ethernet Model
+
+ !!!USB to Serial Converter
+ This section describes the implementation of the USB to serial converter using
+ the CDC class and the AT91 USB Device Framework.
+
+ !!Bridging a Legacy Device and a Host with USB-Serial Converter
+ \image USB-SerialConverter.png
+
+ !!Model
+ The CDC specification defines a model which suits this application perfectly:
+ the #Abstract Control Model (ACM)#. It implements the requests and
+ notifications necessary to communicate with an RS-232 interface.
+
+ The Abstract Control Model requires two interfaces, one #Communication Class
+ Interface# and one #Data Class Interface#. Each of them must have two
+ associated endpoints. The former shall have one endpoint dedicated to %device
+ management (default Control endpoint 0) and one for events notification
+ (additional Interrupt IN endpoint).
+
+ The Data Class Interface needs two endpoints through which to carry data to
+ and from the host. Depending on the application, these endpoints can either
+ be Bulk or Isochronous. In the case of a USB to serial converter, using Bulk
+ endpoints is probably more appropriate, since the reliability of the
+ transmission is important and the data transfers are not time-critical.
+
+ !!Descriptors
+ The descriptors are modtly standard ones. The following code examples thus
+ use the structures described in the "AT91 USB device framework".
+
+ For CDC-specific descriptors, some new types are defined:
+ - CDCHeaderDescriptor
+ - CDCCallManagementDescriptor
+ - CDCAbstractControlManagementDescriptor
+ - CDCUnionDescriptor
+
+ All the descriptors can be found in CDCDSerialDriverDescriptors.c.
+
+ !Device Descriptor
+ \code
+const USBDeviceDescriptor deviceDescriptor = {
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ CDCDeviceDescriptor_CLASS,
+ CDCDeviceDescriptor_SUBCLASS,
+ CDCDeviceDescriptor_PROTOCOL,
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ CDCDSerialDriverDescriptors_VENDORID,
+ CDCDSerialDriverDescriptors_PRODUCTID,
+ CDCDSerialDriverDescriptors_RELEASE,
+ 0, // No string descriptor for manufacturer
+ 1, // Index of product string descriptor is #1
+ 0, // No string descriptor for serial number
+ 1 // Device has 1 possible configuration
+};
+ \endcode
+ The Vendor ID and Product ID fields are used to determine which driver to use
+ when the %device is enumerated. The Vendor ID is provided by the USB-IF
+ organization after registration; the product ID is completely vendor-specific.
+ In the example implementation provided with this document, the Atmel vendor ID
+ (03EBh) is used along with a custom product ID (6119h).
+
+ The configuration descriptor is followed by interface, endpoint and class-
+ specific descriptors.
+\code
+const CDCDSerialDriverConfigurationDescriptors configurationDescriptors[];
+\endcode
+
+ !Configuration Descriptor
+\code
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CDCDSerialDriverConfigurationDescriptors),
+ 2, // There are two interfaces in this configuration
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+\endcode
+
+ !Communication Class Interface Descriptor
+ The bInterfaceClass should be set to 0x02 and bInterfaceSubClass should be set
+ to 0x02.
+\code
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+\endcode
+
+ !Functional - Header Descriptor
+\code
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+\endcode
+
+ !Functional - Call Management Descriptor
+\code
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ 0 // No associated data interface
+ },
+\endcode
+
+ !Functional - Abstract Control Management Descriptor
+\code
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+\endcode
+
+ !Functional - Union Descriptor
+\code
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ 0, // Number of master interface is #0
+ 1 // First slave interface is #1
+ },
+\endcode
+
+ !Notification Endpoint Descriptor
+ The EP is defined as CDCDSerialDriverDescriptors_NOTIFICATION.
+\code
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
+ CDCDSerialDriverDescriptors_NOTIFICATION),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ 10 // Endpoint is polled every 10ms
+ },
+\endcode
+
+ !Data Class Interface Descriptor
+\code
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+\endcode
+
+ !Data Endpoint Descriptors
+ The EPs are defined as CDCDSerialDriverDescriptors_DATAOUT &
+ CDCDSerialDriverDescriptors_DATAIN.
+\code
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
+ CDCDSerialDriverDescriptors_DATAOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_BULK,
+ MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
+ CDCDSerialDriverDescriptors_DATAIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+\endcode
+
+ !String Descriptors
+ Several descriptors (device, configuration, interface, etc.) can specify the
+ index of a string descriptor to comment their use.
+
+ The actual string code is defined:
+ productStringDescriptor.
+
+ !!Class-specific Requests
+ The CDC specification defines a set of #class-specific requests# for devices
+ implementing the ACM. This section details these requests. Please refer to
+ section 3.6.2.1 of the CDC spec. 1.1 for more information.
+
+ !SetLineCoding, GetLineCoding
+ These requests are sent by the host to modify or retrieve the configuration of
+ the serial line, which includes:
+ - Baudrate
+ - Number of stop bits
+ - Parity check
+ - Number of data bits
+
+ When the terminal application (such as HyperTerminal) on the host (PC) side
+ changes the setting of the COM port, a SetLineCoding request is sent with the
+ new parameters. The host may also retrieve the current setting using
+ GetLineCoding, not modifying them if they are correct.
+
+ When a SET_LINE_CODING request is received, the %device should read the new
+ parameters. Then program the new parameters in the USART. A callback must be
+ provided to the USBD_Read function.
+ See CDCDSerialDriver_SetLineCoding.
+
+ The code handling GET_LINE_CODING shall simply invoke the USBD_Write function
+ to send the current settings of the USART to the host.
+ See CDCDSerialDriver_GetLineCoding.
+
+ !SetControlLineState
+ This request is sent by the host to notify the %device of two state changes.
+ The first bit (D0) of the wValue field of the request indicates whether or not
+ a terminal is connected to the virtual COM port. Bit D1 indicates that the
+ USART should enable/disable its carrier signal to start/stop receiving and
+ transmitting data.
+
+ In practice, the USB to serial converter should operate only when those two
+ bits are set. Otherwise, it should not transmit or receive data.
+
+ Since the SET_CONTROL_LINE_STATE request does not have a data payload, the
+ %device only has to acknowledge the request by sending a ZLP (zero-length
+ packet), using the USBD_Write method.
+ See CDCDSerialDriver_SetControlLineState.
+
+ Before that, the wValue field should be parsed to retrieve the new control
+ line state. A single boolean variable can be used to keep track of the
+ connection state. If both the D0 and D1 bits are set, then the converter
+ should operate normally, i.e., forward data between the USART and the USB
+ host. Otherwise, it should stop its activity.
+
+ !!Notifications
+ Notifications are sent by the %device when an event, such as a serial line
+ state change, has occurred. In this example, they are transmitted through a
+ dedicated Interrupt IN endpoint. A special header must precede the data
+ payload of each notification. This header has the same format of a SETUP
+ request, so the USBGenericRequest structure defined in the
+ "AT91 USB device framework" can be used.
+
+ Note that the %device should only send a notification when there is a state
+ change, and not continuously. This does not really matter in practice, but
+ only sending notifications sporadically will reduce the stress on the %device.
+
+ When the serial state is changed by CDCDSerialDriver_SetSerialState, the
+ notification is sent to the host.
+
+ !!!CDC Serial Driver API
+ - CDCDSerialDriver_Initialize
+ - CDCDSerialDriver_RequestHandler
+ - CDCDSerialDriver_Read
+ - CDCDSerialDriver_Write
+ - CDCDSerialDriver_GetSerialState
+ - CDCDSerialDriver_SetSerialState
+
+ !!!Main Application
+ The job of the main application is to bridge the USART and the USB. This means
+ that data read from one end must be forwarded to the other end. This section
+ describes several possibilities to do this.
+
+ !!USB Operation
+ Reading data coming from the host is done using the CDCDSerialDriver_Read.
+ Since this is an asynchronous function, it does not block the execution flow.
+ This means that other actions (like reading data from the USART) can be
+ performed while the transfer is going on. Whenever some data is sent by the
+ host, the transfer terminates and the associated callback function is invoked.
+ This callback (UsbDataReceived) can be programmed to forward the received data
+ through the USART.
+
+ Likewise, the CDCDSerialDriver_Write function can be called as soon as there
+ is data to transmit, again without block the program flow. However, there
+ cannot be two write operations at the same time, so the program must check
+ whether or not the last transfer is complete. This can be done by checking the
+ result code of the CDCDSerialDriver_Write method. If USB_STATUS_LOCKED is
+ returned, then there is already another operation in progress. The %device
+ will have to buffer the data retrieved from the USART until the endpoint
+ becomes free again.
+
+ !!USART Operation
+ The USART peripheral present on AT91 chips can be used in two different ways.
+ The classic way is to read and write one byte at a time in the correct
+ registers to send and receive data.
+
+ A more powerful method is available on AT91SAM chips, by using the embedded
+ Peripheral DMA Controller (PDC). The PDC can take care of transfers between
+ the processor, memory and %peripherals, thus freeing the processor to perform
+ other tasks. Since the PDC interrupt happens on the buffer full, Some timer
+ can be used to check if there is any data frags input from the USART.
+
+ !!!Using a Generic Host Driver
+ See "USB CDC Serial Host Driver".
+
+ !!!Add two or more ports in one USB device
+ See "USB Dual Port CDC Serial Device".
+
+*/
+
+/**
+ \page "USB CDC Serial Host Driver"
+ Both Microsoft Windows and Linux offer a generic driver for using a USB to
+ serial converter %device. This page details the steps required to make use
+ of them.
+
+ !!!Windows
+ On Microsoft Windows, the standard USB serial driver is named usbser.sys and
+ is part of the standard set of drivers. It has been available since Windows
+ 98SE. However, conversely to other generic driver such as the one for Mass
+ Storage Devices (MSD), usbser.sys is not automatically loaded when a CDC
+ %device is plugged in.
+
+ !!Writing a Windows Driver File
+ For Windows to recognize the %device correctly, it is necessary to write a
+ .inf file. The Windows Driver Development Kit (DDK) contains information on
+ this topic. A basic driver, named 6119.inf in the example software provided,
+ will now be described. The driver file is made up of several sections.
+
+ The first section of the .inf file must be the #[Version]# section. It
+ contains information about the driver version, provider, release data, and so
+ on.
+\code
+[Version]
+Signature="$Chicago$"
+Class=Ports
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
+Provider=%ATMEL%
+DriverVer=09/12/2006,1.1.1.1
+\endcode
+
+ The Signature attribute is mandatory and can be either "$Windows 95$",
+ "$Windows NT$" or "$Chicago$", depending on which Windows version(s) the
+ driver supports. "$Chicago$" is used to notify that every Windows version is
+ supported. Since in this example, the USB to serial converter is a virtual COM
+ port, the Class attribute should be equal to "Ports". The value of ClassGuid
+ depends on which class the %device uses. The Provider value indicates that the
+ string descriptor for the driver provider will be defined further, under the
+ tag ATMEL. Finally, the last tag show the driver version and release date. For
+ the version number, each digit is optional (except the first one), but must
+ not be null if present.
+
+ Next come two sections, #[SourceDisksNames]# and #[SourceDisksFiles]#. They
+ are used to specify the installation disks required and the location of each
+ needed files on these disks. But they are not implemented because the file
+ is offered by windows or its install disk automatically.
+\code
+;[SourceDisksNames]
+;1="Windows Install CD"
+;[SourceDisksFiles]
+;usbser.sys=1
+\endcode
+
+ The driver file must now specify where copied files will be stored, using the
+ #[DestinationDirs]# section.
+\code
+[DestinationDirs]
+DefaultDestDir=12
+\endcode
+ The target directory must be identified by its ID, which is system-defined.
+ The ID for the drivers directory is 12.
+
+ The #[Manufacturer]# section lists the possible manufacturers for all devices
+ supported by this driver. In this case, the only supported %device is an ATMEL
+ one, so this will be the only value.
+\code
+[Manufacturer]
+%ATMEL%=AtmelMfg
+\endcode
+
+ The attribute must be a string tag; its value must be the name of the Models
+ section in which all supported devices from this manufacturer will be listed.
+ In this case, it will be named AtmelMfg, which is the next section.
+
+ Each Models section must list the hardware ID of each supported %device. For
+ USB devices, the hardware ID is made up of the Vendor ID, the Product ID and
+ (optionally) the Device Release Number. Those values are extracted from the
+ %device descriptor provided during the enumeration phase.
+\code
+[AtmelMfg]
+%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6119
+\endcode
+
+ The attribute name is again a string tag, which will be used to describe the
+ %device. The value is comprised of both the %device install section name
+ (USBtoSer.Install) and the hardware ID. The hardware ID is the same as the one
+ defined in "CDC Serial Device IDs".
+
+ Now, the .inf file must detail the install section of each %device previously
+ listed. In this example, there is only one install section, named
+ #[USBtoSer.Install]#:
+\code
+[USBtoSer.Install]
+CopyFiles=USBtoSer.CopyFiles
+AddReg=USBtoSer.AddReg
+
+[USBtoSer.CopyFiles]
+usbser.sys,,,0x00000002
+
+[USBtoSer.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,usbser.sys
+
+[USBtoSer.Install.Services]
+AddService=usbser,0x00000002,USBtoSer.AddService
+
+[USBtoSer.AddService]
+DisplayName=%USBSer%
+ServiceType=1r
+StartType=3
+ServiceBinary=%12%\usbser.sys
+\endcode
+
+ The install section is actually divided in five. In the first section, two
+ other section names are specified: one for the list of files to copy, and one
+ for the keys to add to the Windows registry. There is only one file to copy,
+ usbser.sys; a flag (0x00000002) is used to specify that the user cannot skip
+ copying it. The registry keys are needed to install the driver on older
+ versions of Windows (such as Windows 98). For newer versions, the
+ #[USBtoSer.Install.Services]# registers the needed kernel services; each
+ service is actually listed in a section on its own.
+
+ Finally, the last section, [Strings], defines all the string constants used
+ through this file:
+\code
+[Strings]
+ATMEL="ATMEL Corp."
+USBtoSerialConverter="AT91 USB to Serial Converter"
+USBSer="USB Serial Driver"
+\endcode
+
+ !!Using the Driver
+ When a new %device is plugged in for the first time, Windows looks for an
+ appropriate specific or generic driver to use it. If it does not find one, the
+ user is asked what to do.
+
+ This is the case with the USB to serial converter, since there is no generic
+ driver for it. To install the custom driver given in the previous section,
+ Windows must be told where to look for it. This can be done by selecting the
+ second option, "Install from a list or specific location", when the driver
+ installation wizards pops up. It will then ask for the directory where the
+ driver is located. After that, it should recognize the "AT91 USB to Serial
+ Converter" driver as an appropriate one and display it in the list.
+
+ During the installation, the wizard asks for the location of the usbser.sys
+ file. If it is already installed on the system, it can be found in
+ "C:\Windows\System32\Drivers\". Otherwise, it is present on the Windows
+ installation CD.
+
+ Once the driver is installed properly, a new COM port is added to the system
+ and can be used with HyperTerminal, for example.
+
+ !!!Linux
+ Linux has two different generic drivers which are appropriate for a USB to
+ serial converter. The first one is an Abstract Control Model driver designed
+ for modem devices, and is simply named #acm#. The other one is a generic USB
+ to serial driver named #usbserial#.
+
+ If the support for the #acm# driver has been compiled in the kernel, Linux
+ will automatically load it. A new terminal %device will be created under
+ /dev/ttyACMx.
+
+ The usbserial driver must be loaded manually by using the modprobe command
+ with the vendor ID and product ID values used by the %device:
+\code
+ modprobe usbserial vendor=0x03EB product=0x6119
+\endcode
+
+ Once the driver is loaded, a new terminal entry appears and should be named
+ /dev/ttyUSBx.
+*/
+
+/**
+ \page "USB Dual Port CDC Serial Device"
+
+*/
diff --git a/usb/device/cdc-serial/drv/6119.inf b/usb/device/cdc-serial/drv/6119.inf new file mode 100644 index 0000000..14bd8d3 --- /dev/null +++ b/usb/device/cdc-serial/drv/6119.inf @@ -0,0 +1,45 @@ +; $Id: 6119.inf,v 1.1.2.1 2006/12/05 08:33:25 danielru Exp $
+
+[Version] ; Version section
+Signature="$Chicago$" ; All Windows versions
+Class=Ports ; This is a serial port driver
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} ; Associated GUID
+Provider=%ATMEL% ; Driver is provided by ATMEL
+DriverVer=09/12/2006,1.1.1.5 ; Driver version 1.1.1.5 published on 23 February 2007
+
+[DestinationDirs] ; DestinationDirs section
+DefaultDestDir=12 ; Default install directory is \drivers or \IOSubSys
+
+[Manufacturer] ; Manufacturer section
+%ATMEL%=AtmelMfg ; Only one manufacturer (ATMEL), models section is named
+ ; AtmelMfg
+
+[AtmelMfg] ; Models section corresponding to ATMEL
+%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6119 ; Identifies a device with ATMEL Vendor ID (03EBh) and
+ ; Product ID equal to 6119h. Corresponding Install section
+ ; is named USBtoSer.Install
+
+[USBtoSer.Install] ; Install section
+include=mdmcpq.inf
+CopyFiles=FakeModemCopyFileSection
+AddReg=USBtoSer.AddReg ; Registry keys to add are listed in USBtoSer.AddReg
+
+[USBtoSer.AddReg] ; AddReg section
+HKR,,DevLoader,,*ntkern ;
+HKR,,NTMPDriver,,usbser.sys
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[USBtoSer.Install.Services] ; Services section
+AddService=usbser,0x00000002,USBtoSer.AddService ; Assign usbser as the PnP driver for the device
+
+[USBtoSer.AddService] ; Service install section
+DisplayName=%USBSer% ; Name of the serial driver
+ServiceType=1 ; Service kernel driver
+StartType=3 ; Driver is started by the PnP manager
+ErrorControl=1 ; Warn about errors
+ServiceBinary=%12%\usbser.sys ; Driver filename
+
+[Strings] ; Strings section
+ATMEL="ATMEL Corp." ; String value for the ATMEL symbol
+USBtoSerialConverter="AT91 USB to Serial Converter" ; String value for the USBtoSerialConverter symbol
+USBSer="USB Serial Driver" ; String value for the USBSer symbol
\ No newline at end of file diff --git a/usb/device/cdc-serial/drv/drv.dir b/usb/device/cdc-serial/drv/drv.dir new file mode 100644 index 0000000..a2ff78a --- /dev/null +++ b/usb/device/cdc-serial/drv/drv.dir @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides install file for a CDC serial port %device.
+///
+/// !!!Contents
+///
+/// 6119.inf
+///
+//------------------------------------------------------------------------------
diff --git a/usb/device/composite/AUDDFunctionDriver.c b/usb/device/composite/AUDDFunctionDriver.c new file mode 100644 index 0000000..a1645aa --- /dev/null +++ b/usb/device/composite/AUDDFunctionDriver.c @@ -0,0 +1,282 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+// GENERAL
+#include <utility/trace.h>
+#include <utility/assert.h>
+#include <utility/led.h>
+// USB
+#include <usb/device/core/USBD.h>
+// AUDIO
+#include <usb/common/audio/AUDGenericRequest.h>
+#include <usb/common/audio/AUDFeatureUnitRequest.h>
+
+#include "AUDDFunctionDriver.h"
+#include "AUDDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// USB audio speaker driver instance.
+static AUDDSpeakerChannel auddSpeakerChannels[AUDD_NUMCHANNELS+1];
+/// Intermediate storage variable for the mute status of a channel.
+static unsigned char muted;
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Changes the mute status of the given channel accordingly.
+/// \param channel Number of the channel whose mute status has changed.
+//-----------------------------------------------------------------------------
+static void AUDD_MuteReceived(unsigned char channel)
+{
+ AUDDSpeakerChannel *pChannel = &auddSpeakerChannels[channel];
+ if (muted) {
+
+ if (!pChannel->muted) {
+
+ pChannel->muted = 1;
+ AUDDSpeakerChannel_MuteChanged(pChannel, 1);
+ }
+ }
+ else {
+
+ if (pChannel->muted) {
+
+ pChannel->muted = 0;
+ AUDDSpeakerChannel_MuteChanged(pChannel, 0);
+ }
+ }
+
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Sets the current value of a particular Feature control of a channel.
+/// \param channel Number of the channel whose feature will change.
+/// \param control The feature control that will change.
+/// \param length The feature data size.
+//-----------------------------------------------------------------------------
+static void AUDD_SetFeatureCurrentValue(unsigned char channel,
+ unsigned char control,
+ unsigned short length)
+{
+ TRACE_INFO_WP("sFeature ");
+ TRACE_DEBUG("\b(CS%d, CN%d, L%d) ", control, channel, length);
+
+ // Check the the requested control is supported
+ // Mute control on master channel
+ if ((control == AUDFeatureUnitRequest_MUTE)
+ && (channel < (AUDD_NUMCHANNELS+1))
+ && (length == 1)) {
+
+ unsigned int argument = channel; // Avoids compiler warning
+ USBD_Read(0, // Endpoint #0
+ &muted,
+ sizeof(muted),
+ (TransferCallback) AUDD_MuteReceived,
+ (void *) argument);
+ }
+ // Control/channel combination not supported
+ else {
+
+ USBD_Stall(0);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Sends the current value of a particular channel Feature to the USB host.
+/// \param channel Number of the channel whose feature will be sent.
+/// \param control The feature control that will be sent.
+/// \param length The feature data size.
+//-----------------------------------------------------------------------------
+static void AUDD_GetFeatureCurrentValue(unsigned char channel,
+ unsigned char control,
+ unsigned char length)
+{
+ TRACE_INFO_WP("gFeature ");
+ TRACE_DEBUG("\b(CS%d, CN%d, L%d) ", control, channel, length);
+
+ // Check that the requested control is supported
+ // Master channel mute control
+ if ((control == AUDFeatureUnitRequest_MUTE)
+ && (channel < (AUDD_NUMCHANNELS+1))
+ && (length == 1)) {
+
+ muted = auddSpeakerChannels[channel].muted;
+ USBD_Write(0, &muted, sizeof(muted), 0, 0);
+ }
+ else {
+
+ USBD_Stall(0);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes an USB audio speaker function driver
+//-----------------------------------------------------------------------------
+void AUDDFunctionDriver_Initialize()
+{
+ auddSpeakerChannels[0].muted = 0;
+ auddSpeakerChannels[0].number = AUDD_MASTERCHANNEL;
+ auddSpeakerChannels[1].muted = 0;
+ auddSpeakerChannels[1].number = AUDD_LEFTCHANNEL;
+ auddSpeakerChannels[2].muted = 0;
+ auddSpeakerChannels[2].number = AUDD_RIGHTCHANNEL;
+
+ // Initialize the third LED to indicate when the audio interface is active
+ LED_Configure(USBD_LEDOTHER);
+}
+
+//-----------------------------------------------------------------------------
+/// Handles AUDIO-specific USB requests sent by the host
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return 0 if the request is Unsupported, 1 if the request handled.
+//-----------------------------------------------------------------------------
+unsigned char AUDDFunctionDriver_RequestHandler(
+ const USBGenericRequest *request)
+{
+ unsigned char entity;
+ unsigned char interface;
+
+ // Check if the request is supported
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case AUDGenericRequest_SETCUR:
+ TRACE_INFO_WP(
+ "sCur(0x%04X) ",
+ USBGenericRequest_GetIndex(request));
+
+ // Check the target interface and entity
+ entity = AUDGenericRequest_GetEntity(request);
+ interface = AUDGenericRequest_GetInterface(request);
+ if ((entity == AUDD_Descriptors_FEATUREUNIT)
+ && (interface == AUDD_Descriptors_CONTROL)) {
+
+ AUDD_SetFeatureCurrentValue(
+ AUDFeatureUnitRequest_GetChannel(request),
+ AUDFeatureUnitRequest_GetControl(request),
+ USBGenericRequest_GetLength(request));
+ }
+ else {
+
+ TRACE_WARNING(
+ "AUDDSpeakerDriver_RequestHandler: Unsupported entity/interface combination (0x%04X)\n\r",
+ USBGenericRequest_GetIndex(request));
+ USBD_Stall(0);
+ }
+ break;
+
+ case AUDGenericRequest_GETCUR:
+ TRACE_INFO_WP(
+ "gCur(0x%04X) ",
+ USBGenericRequest_GetIndex(request));
+
+ // Check the target interface and entity
+ entity = AUDGenericRequest_GetEntity(request);
+ interface = AUDGenericRequest_GetInterface(request);
+ if ((entity == AUDD_Descriptors_FEATUREUNIT)
+ && (interface == AUDD_Descriptors_CONTROL)) {
+
+ AUDD_GetFeatureCurrentValue(
+ AUDFeatureUnitRequest_GetChannel(request),
+ AUDFeatureUnitRequest_GetControl(request),
+ USBGenericRequest_GetLength(request));
+ }
+ else {
+
+ TRACE_WARNING(
+ "AUDDSpeakerDriver_RequestHandler: Unsupported entity/interface combination (0x%04X)\n\r",
+ USBGenericRequest_GetIndex(request));
+ USBD_Stall(0);
+ }
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+/// 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 AUDDFunctionCallbacks_InterfaceSettingChanged(unsigned char interface,
+ unsigned char setting)
+{
+ if ((interface == AUDD_Descriptors_STREAMING) && (setting == 0)) {
+
+ LED_Clear(USBD_LEDOTHER);
+ }
+ else {
+
+ LED_Set(USBD_LEDOTHER);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Reads incoming audio data sent by the USB host into the provided buffer.
+/// When the transfer is complete, an optional callback function is invoked.
+/// \param buffer Pointer to the data storage buffer.
+/// \param length Size of the buffer in bytes.
+/// \param callback Optional callback function.
+/// \param argument Optional argument to the callback function.
+/// \return <USBD_STATUS_SUCCESS> if the transfer is started successfully;
+/// otherwise an error code.
+//-----------------------------------------------------------------------------
+unsigned char AUDDSpeakerDriver_Read(void *buffer,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Read(AUDD_Descriptors_DATAOUT,
+ buffer,
+ length,
+ callback,
+ argument);
+}
+
+#endif // (AUDIO defined)
+
diff --git a/usb/device/composite/AUDDFunctionDriver.h b/usb/device/composite/AUDDFunctionDriver.h new file mode 100644 index 0000000..637fc67 --- /dev/null +++ b/usb/device/composite/AUDDFunctionDriver.h @@ -0,0 +1,105 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef AUDDFUNCTIONDRIVER_H
+#define AUDDFUNCTIONDRIVER_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Sample rate in Hz.
+#define AUDD_SAMPLERATE 48000
+/// Number of channels in audio stream.
+#define AUDD_NUMCHANNELS 2
+/// Number of bytes in one sample.
+#define AUDD_BYTESPERSAMPLE 2
+/// Number of bits in one sample.
+#define AUDD_BITSPERSAMPLE (AUDD_BYTESPERSAMPLE * 8)
+/// Number of samples in one USB subframe.
+#define AUDD_BYTESPERSUBFRAME (AUDD_NUMCHANNELS * AUDD_BYTESPERSAMPLE)
+/// Number of samples in one USB frame.
+#define AUDD_SAMPLESPERFRAME (AUDD_SAMPLERATE / 1000 * AUDD_NUMCHANNELS)
+/// Number of bytes in one USB frame.
+#define AUDD_BYTESPERFRAME (AUDD_SAMPLESPERFRAME * AUDD_BYTESPERSAMPLE)
+/// Master channel.
+#define AUDD_MASTERCHANNEL 0
+/// Front left channel.
+#define AUDD_LEFTCHANNEL 1
+/// Front right channel.
+#define AUDD_RIGHTCHANNEL 2
+
+//-----------------------------------------------------------------------------
+// Structs
+//-----------------------------------------------------------------------------
+
+/// AUDIO Speaker channel struct
+typedef struct {
+
+ unsigned char number;
+ unsigned char muted;
+
+} AUDDSpeakerChannel;
+
+//-----------------------------------------------------------------------------
+// Callbacks
+//-----------------------------------------------------------------------------
+extern void AUDDSpeakerChannel_MuteChanged(AUDDSpeakerChannel *channel,
+ unsigned char muted);
+
+extern void AUDDFunctionCallbacks_InterfaceSettingChanged(
+ unsigned char interface,
+ unsigned char setting);
+
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//- Function API For composite device
+extern void AUDDFunctionDriver_Initialize();
+
+extern unsigned char AUDDFunctionDriver_RequestHandler(
+ const USBGenericRequest * request);
+
+//- AUDIO Speaker API
+extern unsigned char AUDDSpeakerDriver_Read(void *buffer,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument);
+
+#endif // #define AUDDFUNCTIONDRIVER_H
+
diff --git a/usb/device/composite/AUDDFunctionDriverDescriptors.h b/usb/device/composite/AUDDFunctionDriverDescriptors.h new file mode 100644 index 0000000..a5a64f4 --- /dev/null +++ b/usb/device/composite/AUDDFunctionDriverDescriptors.h @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef AUDDFUNCTIONDRIVERDESCRIPTORS_H
+#define AUDDFUNCTIONDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// COMPOSITE option
+#if defined(usb_CDCAUDIO)
+#define AUDD_Descriptors_INTERFACE 2
+#elif defined(usb_HIDAUDIO)
+#define AUDD_Descriptors_INTERFACE 1
+#endif
+
+/// - Endpoint numbers
+/// Data out endpoint number
+#define AUDD_Descriptors_DATAOUT 0x05
+
+/// - Interface IDs
+/// Audio control interface ID
+#define AUDD_Descriptors_CONTROL (AUDD_Descriptors_INTERFACE + 0)
+/// Audio streaming interface ID
+#define AUDD_Descriptors_STREAMING (AUDD_Descriptors_INTERFACE + 1)
+
+/// - Entity IDs
+/// Input terminal ID.
+#define AUDD_Descriptors_INPUTTERMINAL 0
+/// Output terminal ID.
+#define AUDD_Descriptors_OUTPUTTERMINAL 1
+/// Feature unit ID.
+#define AUDD_Descriptors_FEATUREUNIT 2
+
+#endif // #define AUDDFUNCTIONDRIVERDESCRIPTORS_H
diff --git a/usb/device/composite/CDCDFunctionDriver.c b/usb/device/composite/CDCDFunctionDriver.c new file mode 100644 index 0000000..4e42015 --- /dev/null +++ b/usb/device/composite/CDCDFunctionDriver.c @@ -0,0 +1,337 @@ +/* ----------------------------------------------------------------------------
+ * 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>
+// USB
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+// CDC
+#include <usb/common/cdc/CDCGenericRequest.h>
+#include <usb/common/cdc/CDCSetControlLineStateRequest.h>
+
+#include "CDCDFunctionDriver.h"
+#include "CDCDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+/// CDC Function Driver Struct
+typedef struct {
+ USBDDriver * pUsbdDriver;
+ CDCDSerialPort * pCdcPorts;
+ unsigned char numPorts;
+} CDCFunDriver;
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// CDC Function Driver instance
+static CDCFunDriver cdcFunDriver;
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Callback function which should be invoked after the data of a
+/// SetLineCoding request has been retrieved. Sends a zero-length packet
+/// to the host for acknowledging the request.
+//-----------------------------------------------------------------------------
+static void CDCD_SetLineCodingCallback()
+{
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Return the port index that host send this request for.
+//-----------------------------------------------------------------------------
+static char CDCD_GetSerialPort(const USBGenericRequest *request)
+{
+ unsigned char i;
+ for (i = 0; i < cdcFunDriver.numPorts; i ++) {
+ if (request->wIndex == cdcFunDriver.pCdcPorts[i].interfaceNum + 1)
+ return i;
+ }
+ return 0xFF;
+}
+
+//-----------------------------------------------------------------------------
+/// Receives new line coding information from the USB host.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+static void CDCD_SetLineCoding(const USBGenericRequest *request)
+{
+ unsigned char serial;
+ serial = CDCD_GetSerialPort(request);
+
+ TRACE_INFO_WP("sLineCoding_%d ", serial);
+
+ USBD_Read(0,
+ (void *) &(cdcFunDriver.pCdcPorts[serial].lineCoding),
+ sizeof(CDCLineCoding),
+ (TransferCallback) CDCD_SetLineCodingCallback,
+ 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Sends the current line coding information to the host through Control
+/// endpoint 0.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+static void CDCD_GetLineCoding(const USBGenericRequest *request)
+{
+ unsigned char serial;
+ serial = CDCD_GetSerialPort(request);
+
+ TRACE_INFO_WP("gLineCoding_%d ", serial);
+
+ USBD_Write(0,
+ (void *) &(cdcFunDriver.pCdcPorts[serial].lineCoding),
+ sizeof(CDCLineCoding),
+ 0,
+ 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Changes the state of the serial driver according to the information
+/// sent by the host via a SetControlLineState request, and acknowledges
+/// the request with a zero-length packet.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \param activateCarrier The active carrier state to set.
+/// \param isDTEPresent The DTE status.
+//-----------------------------------------------------------------------------
+static void CDCD_SetControlLineState(const USBGenericRequest *request,
+ unsigned char activateCarrier,
+ unsigned char isDTEPresent)
+{
+ unsigned char serial;
+ serial = CDCD_GetSerialPort(request);
+
+ TRACE_INFO_WP(
+ "sControlLineState_%d(%d, %d) ",
+ serial,
+ activateCarrier,
+ isDTEPresent);
+
+ cdcFunDriver.pCdcPorts[serial].isCarrierActivated = activateCarrier;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the USB device CDC serial function driver.
+//-----------------------------------------------------------------------------
+void CDCDFunctionDriver_Initialize(USBDDriver * pUsbdDriver,
+ CDCDSerialPort * pCdcPorts,
+ unsigned char numPorts)
+{
+ unsigned char serial;
+
+ TRACE_INFO("CDCDFunctionDriver_Initialize\n\r");
+
+ cdcFunDriver.pUsbdDriver = pUsbdDriver;
+ cdcFunDriver.pCdcPorts = pCdcPorts;
+ cdcFunDriver.numPorts = numPorts;
+
+ for (serial = 0; serial < numPorts; serial ++) {
+
+ CDCDSerialPort * pSerial = &cdcFunDriver.pCdcPorts[serial];
+
+ // Initialize Abstract Control Model attributes
+ CDCLineCoding_Initialize(&(pSerial->lineCoding),
+ 115200,
+ CDCLineCoding_ONESTOPBIT,
+ CDCLineCoding_NOPARITY,
+ 8);
+ pSerial->isCarrierActivated = 0;
+ pSerial->serialState = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Handles CDC/ACM-specific USB requests sent by the host
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return 0 if the request is Unsupported, 1 if the request handled.
+//-----------------------------------------------------------------------------
+unsigned char CDCDFunctionDriver_RequestHandler(
+ const USBGenericRequest *request)
+{
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case CDCGenericRequest_SETLINECODING:
+
+ CDCD_SetLineCoding(request);
+ break;
+
+ case CDCGenericRequest_GETLINECODING:
+
+ CDCD_GetLineCoding(request);
+ break;
+
+ case CDCGenericRequest_SETCONTROLLINESTATE:
+
+ CDCD_SetControlLineState(request,
+ CDCSetControlLineStateRequest_ActivateCarrier(request),
+ CDCSetControlLineStateRequest_IsDtePresent(request));
+
+ break;
+
+ // Unsupported request
+ default:
+ return 0;
+
+ }
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+/// Receives data from the host through the virtual COM port created by
+/// the CDC function serial driver. This function behaves like <USBD_Read>.
+/// \param Port Port index to receive.
+/// \param Pointer to the data buffer to send.
+/// \param Size of the data buffer in bytes.
+/// \param callback Optional callback function to invoke when the transfer
+/// finishes.
+/// \param argument Optional argument to the callback function.
+/// \return <USBD_STATUS_SUCCESS> if the read operation started normally;
+/// otherwise, the corresponding error code.
+//-----------------------------------------------------------------------------
+unsigned char CDCDSerialDriver_Read(unsigned char port,
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ unsigned char ep = cdcFunDriver.pCdcPorts[port].bulkOutEndpoint;
+
+ if (port > cdcFunDriver.numPorts)
+ return USBD_STATUS_INVALID_PARAMETER;
+
+ return USBD_Read(ep,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// Sends a data buffer through the virtual COM port created by the CDC
+/// function serial driver. This function behaves exactly like <USBD_Write>.
+/// \param port Port index to receive.
+/// \param data - Pointer to the data buffer to send.
+/// \param size - Size of the data buffer in bytes.
+/// \param callback - Optional callback function to invoke when the transfer
+/// finishes.
+/// \param argument - Optional argument to the callback function.
+/// \return <USBD_STATUS_SUCCESS> if the write operation started normally;
+/// otherwise, the corresponding error code.
+//-----------------------------------------------------------------------------
+unsigned char CDCDSerialDriver_Write(unsigned char port,
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ unsigned char ep = cdcFunDriver.pCdcPorts[port].bulkInEndpoint;
+
+ if (port > cdcFunDriver.numPorts)
+ return USBD_STATUS_INVALID_PARAMETER;
+
+ return USBD_Write(ep,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current status of the RS-232 line.
+/// \param port The port number that checked.
+//------------------------------------------------------------------------------
+unsigned short CDCDSerialDriver_GetSerialState(unsigned char port)
+{
+ if (port > cdcFunDriver.numPorts)
+ return USBD_STATUS_INVALID_PARAMETER;
+
+ return cdcFunDriver.pCdcPorts[port].serialState;
+}
+
+//------------------------------------------------------------------------------
+/// Sets the current serial state of the device to the given value.
+/// \param port The port number that the port state should be changed.
+/// \param serialState New device state.
+//------------------------------------------------------------------------------
+void CDCDSerialDriver_SetSerialState(unsigned char port,
+ unsigned short serialState)
+{
+ CDCDSerialPort * pPort;
+ unsigned char ep;
+
+ ASSERT((serialState & 0xFF80) == 0,
+ "CDCDSerialDriver_SetSerialState: Bits D7-D15 are reserved!\n\r");
+
+ if (port > cdcFunDriver.numPorts)
+ return;
+
+ // If new state is different from previous one, send a notification to the
+ // host
+ pPort = &cdcFunDriver.pCdcPorts[port];
+ ep = pPort->interruptInEndpoint;
+ if (pPort->serialState != serialState) {
+
+ pPort->serialState = serialState;
+ USBD_Write(ep,
+ &(pPort->serialState),
+ 2,
+ 0,
+ 0);
+
+ // Reset one-time flags
+ pPort->serialState &= ~(CDCD_STATE_OVERRUN
+ | CDCD_STATE_PARITY
+ | CDCD_STATE_FRAMING
+ | CDCD_STATE_RINGSIGNAL
+ | CDCD_STATE_BREAK);
+ }
+}
diff --git a/usb/device/composite/CDCDFunctionDriver.h b/usb/device/composite/CDCDFunctionDriver.h new file mode 100644 index 0000000..0a9e5d2 --- /dev/null +++ b/usb/device/composite/CDCDFunctionDriver.h @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef CDCDFUNCTIONDRIVER_H
+#define CDCDFUNCTIONDRIVER_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/common/cdc/CDCLineCoding.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Indicates the receiver carrier signal is present.
+#define CDCD_STATE_RXDRIVER (1 << 0)
+/// Indicates the transmission carrier signal is present.
+#define CDCD_STATE_TXCARRIER (1 << 1)
+/// Indicates a break has been detected.
+#define CDCD_STATE_BREAK (1 << 2)
+/// Indicates a ring signal has been detected.
+#define CDCD_STATE_RINGSIGNAL (1 << 3)
+/// Indicates a framing error has occured.
+#define CDCD_STATE_FRAMING (1 << 4)
+/// Indicates a parity error has occured.
+#define CDCD_STATE_PARITY (1 << 5)
+/// Indicates a data overrun error has occured.
+#define CDCD_STATE_OVERRUN (1 << 6)
+
+//-----------------------------------------------------------------------------
+// Structs
+//-----------------------------------------------------------------------------
+
+/// CDC Serial port struct
+typedef struct _CDCDSerialPort{
+
+ /// USB interface settings
+ unsigned char interfaceNum;
+ unsigned char interruptInEndpoint;
+ unsigned char bulkInEndpoint;
+ unsigned char bulkOutEndpoint;
+ /// serial port settings
+ CDCLineCoding lineCoding;
+ unsigned char isCarrierActivated;
+ unsigned short serialState;
+
+} CDCDSerialPort;
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+
+#define CDCDFunctionDriver_ConfigurePort(pPort,ifNum,intIN,bulkIN,bulkOUT) \
+{\
+ (pPort)->interfaceNum=(ifNum);(pPort)->interruptInEndpoint=(intIN); \
+ (pPort)->bulkInEndpoint=(bulkIN);(pPort)->bulkOutEndpoint=(bulkOUT); \
+}
+
+//-----------------------------------------------------------------------------
+// Callbacks
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//- Function API for composite device
+extern void CDCDFunctionDriver_Initialize(USBDDriver * pUsbdDriver,
+ CDCDSerialPort * pCdcPorts,
+ unsigned char numPorts);
+
+extern unsigned char CDCDFunctionDriver_RequestHandler(
+ const USBGenericRequest * request);
+
+//- CDC Serial Port API
+extern unsigned char CDCDSerialDriver_Write(
+ unsigned char port,
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument);
+
+extern unsigned char CDCDSerialDriver_Read(
+ unsigned char port,
+ void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument);
+
+extern unsigned short CDCDSerialDriver_GetSerialState(unsigned char port);
+
+extern void CDCDSerialDriver_SetSerialState(
+ unsigned char port,
+ unsigned short serialState);
+
+
+#endif // #define CDCDFUNCTIONDRIVER_H
+
diff --git a/usb/device/composite/CDCDFunctionDriverDescriptors.h b/usb/device/composite/CDCDFunctionDriverDescriptors.h new file mode 100644 index 0000000..33490ae --- /dev/null +++ b/usb/device/composite/CDCDFunctionDriverDescriptors.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef CDCDFUNCTIONDRIVERDESCRIPTORS_H
+#define CDCDFUNCTIONDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+#if defined(usb_CDCAUDIO)
+#define CDCD_Descriptors_INTERFACENUM0 0
+#define CDCD_Descriptors_NOTIFICATION0 3
+#define CDCD_Descriptors_DATAIN0 2
+#define CDCD_Descriptors_DATAOUT0 1
+#endif
+
+/// Default CDC interrupt endpoints max packat size (8).
+#define CDCD_Descriptors_INTERRUPT_MAXPACKETSIZE 8
+/// Default CDC bulk endpoints max packat size (128, for HS actually).
+#define CDCD_Descriptors_BULK_MAXPACKETSIZE 128
+
+/// Default CDC interrupt IN endpoint polling rate of Full Speed (16ms).
+#define CDCD_Descriptors_INTERRUPTIN_POLLING_FS 16
+/// Default CDC interrupt IN endpoint polling rate of High Speed (16ms).
+#define CDCD_Descriptors_INTERRUPTIN_POLLING_HS 8
+/// Default interrupt OUT endpoint polling rate of Full Speed (16ms).
+#define CDCD_Descriptors_INTERRUPTOUT_POLLING_FS 16
+/// Default interrupt OUT endpoint polling rate of High Speed (16ms).
+#define CDCD_Descriptors_INTERRUPTOUT_POLLING_HS 8
+
+#endif // #define CDCFUNCTIONDRIVERDESCRIPTORS_H
diff --git a/usb/device/composite/CDCHIDDDriver.c b/usb/device/composite/CDCHIDDDriver.c new file mode 100644 index 0000000..84c16a6 --- /dev/null +++ b/usb/device/composite/CDCHIDDDriver.c @@ -0,0 +1,227 @@ +/* ----------------------------------------------------------------------------
+ * 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>
+
+//- HID
+#include <usb/device/hid-keyboard/HIDDKeyboardDriver.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardCallbacks.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDGenericRequest.h>
+#include <usb/common/hid/HIDReportRequest.h>
+#include <usb/common/hid/HIDIdleRequest.h>
+#include <usb/common/hid/HIDKeypad.h>
+
+//- MSD
+#if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+#endif
+
+//- CDCHID
+#include "CDCHIDDDriver.h"
+#include "CDCHIDDDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+/// Interface setting spaces (4 byte aligned)
+#define NUM_INTERFACES ((CDCHIDDDriverDescriptors_NUMINTERFACE+3)&0xFC)
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// USBDDriver instance
+static USBDDriver usbdDriver;
+
+/// CDCDSeriaoPort instance
+static CDCDSerialPort cdcdPort;
+
+/// Array for storing the current setting of each interface
+static unsigned char cdchiddDriverInterfaces[NUM_INTERFACES];
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//-----------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ CDCHIDDDriver_RequestHandler(request);
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// 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)
+{
+ // HID
+ HIDDFunctionCallbacks_ConfigurationChanged(cfgnum);
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the USB device composite device driver.
+//-----------------------------------------------------------------------------
+void CDCHIDDDriver_Initialize()
+{
+ // CDC
+ CDCDFunctionDriver_ConfigurePort(&cdcdPort,
+ CDCD_Descriptors_INTERFACENUM0,
+ CDCD_Descriptors_NOTIFICATION0,
+ CDCD_Descriptors_DATAIN0,
+ CDCD_Descriptors_DATAOUT0);
+ CDCDFunctionDriver_Initialize(&usbdDriver,
+ &cdcdPort,
+ 1);
+
+ // HID
+ HIDDFunctionDriver_Initialize(&usbdDriver,
+ HIDD_Descriptors_INTERFACENUM,
+ HIDD_Descriptors_INTERRUPTIN,
+ HIDD_Descriptors_INTERRUPTOUT);
+
+ // Initialize the standard USB driver
+ USBDDriver_Initialize(&usbdDriver,
+ &cdchiddDriverDescriptors,
+ cdchiddDriverInterfaces);
+
+ // 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 CDCHIDDDriver_RequestHandler(const USBGenericRequest *request)
+{
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ unsigned char rc = 0;
+
+ // CDC class request
+ if (rc == 0) {
+
+ rc = CDCDFunctionDriver_RequestHandler(request);
+ }
+
+ // HID class request
+ if (rc == 0) {
+
+ rc = HIDDFunctionDriver_RequestHandler(request);
+ }
+
+ if (!rc) {
+
+ TRACE_WARNING(
+ "CDCHIDDDriver_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;
+
+ rc = HIDDFunctionDriver_RequestHandler(request);
+
+ // Forward request to the standard handler
+ if (rc == 0) {
+
+ USBDDriver_RequestHandler(&(usbdDriver), request);
+ }
+ }
+ // Unsupported request type
+ else {
+
+ TRACE_WARNING(
+ "CDCHIDDDriver_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 CDCHIDDDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+ // Remote wake-up NOT enabled
+ else {
+
+ TRACE_WARNING("CDCHIDDDriver_RemoteWakeUp: not enabled\n\r");
+ }
+}
+
+
diff --git a/usb/device/composite/CDCHIDDDriver.h b/usb/device/composite/CDCHIDDDriver.h new file mode 100644 index 0000000..d7ef755 --- /dev/null +++ b/usb/device/composite/CDCHIDDDriver.h @@ -0,0 +1,78 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definitions and methods for USB composite device implement.
+///
+/// !Usage
+///
+/// -# Initialize USB function specified driver ( for MSD currently )
+/// - MSDDFunctionDriver_Initialize
+///
+/// -# Initialize USB composite driver and USB driver
+/// - CDCHIDDDriver_Initialize
+///
+/// -# Handle and dispach USB requests
+/// - CDCHIDDDriver_RequestHandler
+///
+/// -# Try starting a remote wake-up sequence
+/// - CDCHIDDDriver_RemoteWakeUp
+//-----------------------------------------------------------------------------
+
+#ifndef CDCHIDDDRIVER_H
+#define CDCHIDDDRIVER_H
+
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+#include "CDCDFunctionDriver.h"
+#include "HIDDFunctionDriver.h"
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+// -CDCHID
+extern void CDCHIDDDriver_Initialize();
+
+extern void CDCHIDDDriver_RequestHandler(const USBGenericRequest *request);
+
+extern void CDCHIDDDriver_RemoteWakeUp(void);
+
+#endif //#ifndef CDCHIDDDRIVER_H
+
diff --git a/usb/device/composite/CDCHIDDDriverDescriptors.c b/usb/device/composite/CDCHIDDDriverDescriptors.c new file mode 100644 index 0000000..e19ba2d --- /dev/null +++ b/usb/device/composite/CDCHIDDDriverDescriptors.c @@ -0,0 +1,592 @@ +/* ----------------------------------------------------------------------------
+ * 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 <board.h>
+
+//- Composite
+#include "CDCHIDDDriver.h"
+#include "CDCHIDDDriverDescriptors.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 "CDCDFunctionDriverDescriptors.h"
+
+//- HID
+#include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDeviceDescriptor.h>
+#include <usb/common/hid/HIDInterfaceDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDReport.h>
+#include <usb/common/hid/HIDGenericDesktop.h>
+#include <usb/common/hid/HIDLeds.h>
+#include <usb/common/hid/HIDKeypad.h>
+#include "HIDDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Device product ID.
+#define CDCHIDDDriverDescriptors_PRODUCTID 0x6130
+
+/// Device vendor ID (Atmel).
+#define CDCHIDDDriverDescriptors_VENDORID 0x03EB
+
+/// Device release number.
+#define CDCHIDDDriverDescriptors_RELEASE 0x0003
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+
+/// Returns the minimum between two values.
+#define MIN(a, b) ((a < b) ? a : b)
+
+//-----------------------------------------------------------------------------
+// Internal structures
+//-----------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//-----------------------------------------------------------------------------
+/// Configuration descriptor list for a device implementing a composite driver.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration descriptor.
+ USBConfigurationDescriptor configuration;
+
+ /// --- CDC 0
+ /// 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;
+
+ /// --- HID
+ USBInterfaceDescriptor hidInterface;
+ HIDDescriptor hid;
+ USBEndpointDescriptor hidInterruptIn;
+ USBEndpointDescriptor hidInterruptOut;
+
+} __attribute__ ((packed)) CdcHidDriverConfigurationDescriptors;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Standard USB device descriptor for the composite device driver
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ 0xEF,// MI
+ 0x02,//
+ 0x01,//
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ CDCHIDDDriverDescriptors_VENDORID,
+ CDCHIDDDriverDescriptors_PRODUCTID,
+ CDCHIDDDriverDescriptors_RELEASE,
+ 0, // No string descriptor for manufacturer
+ 1, // Index of product string descriptor is #1
+ 0, // No string descriptor for serial number
+ 1 // Device has 1 possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// USB device qualifier descriptor.
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ USBDeviceDescriptor_USB2_00,
+ 0xEF,// MI
+ 0x02,//
+ 0x01,//
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+/// USB configuration descriptors for the composite device driver
+static const CdcHidDriverConfigurationDescriptors configurationDescriptorsHS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CdcHidDriverConfigurationDescriptors),
+ CDCHIDDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // CDC 0
+ // IAD for CDC/ACM port
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM0,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM0 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM0, // Number of master interface is #0
+ CDCD_Descriptors_INTERFACENUM0 + 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
+ CDCD_Descriptors_INTERRUPT_MAXPACKETSIZE),
+ CDCD_Descriptors_INTERRUPTOUT_POLLING_HS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0 + 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+
+ // HID
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ HIDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDD_Descriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDD_Descriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING_HS
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDD_Descriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDD_Descriptors_INTERRUPTOUT_POLLING_HS
+ }
+};
+
+#endif
+
+/// USB configuration descriptors for the composite device driver
+static const CdcHidDriverConfigurationDescriptors configurationDescriptorsFS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CdcHidDriverConfigurationDescriptors),
+ CDCHIDDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // CDC 0
+ // IAD for CDC/ACM port
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM0,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM0 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM0, // Number of master interface is #0
+ CDCD_Descriptors_INTERFACENUM0 + 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ CDCD_Descriptors_INTERRUPTOUT_POLLING_FS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0 + 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+
+ // HID
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ HIDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDD_Descriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDD_Descriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING_FS
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDD_Descriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDD_Descriptors_INTERRUPTOUT_POLLING_FS
+ }
+};
+
+/// String descriptor with the supported languages.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static 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.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(14),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('C'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('o')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(4),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3')
+};
+
+/// Array of pointers to the four string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors required by an USB audio speaker device driver.
+const USBDDriverDescriptors cdchiddDriverDescriptors = {
+
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#else
+ 0, 0, 0, 0, 0, 0,
+#endif
+ stringDescriptors,
+ 4 // Number of string descriptors
+};
diff --git a/usb/device/composite/CDCHIDDDriverDescriptors.h b/usb/device/composite/CDCHIDDDriverDescriptors.h new file mode 100644 index 0000000..0a34f8a --- /dev/null +++ b/usb/device/composite/CDCHIDDDriverDescriptors.h @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef CDCHIDDDRIVERDESCRIPTORS_H
+#define CDCHIDDDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Number of interfaces of the device
+#define CDCHIDDDriverDescriptors_NUMINTERFACE 3
+
+/// Number of the CDC interface.
+#define CDCD_Descriptors_INTERFACENUM0 0
+/// Address of the CDC interrupt-in endpoint.
+#define CDCD_Descriptors_NOTIFICATION0 3
+/// Address of the CDC bulk-in endpoint.
+#define CDCD_Descriptors_DATAIN0 2
+/// Address of the CDC bulk-out endpoint.
+#define CDCD_Descriptors_DATAOUT0 1
+
+/// Number of the HID interface.
+#define HIDD_Descriptors_INTERFACENUM 2
+/// Address of the HID interrupt IN endpoint.
+#define HIDD_Descriptors_INTERRUPTIN 4
+/// Address of the HID interrupt OUT endpoint.
+#define HIDD_Descriptors_INTERRUPTOUT 5
+
+
+//-----------------------------------------------------------------------------
+// Exported variables
+//-----------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors cdchiddDriverDescriptors;
+
+#endif //#ifndef CDCHIDDDRIVERDESCRIPTORS_H
diff --git a/usb/device/composite/CDCMSDDDriver.c b/usb/device/composite/CDCMSDDDriver.c new file mode 100644 index 0000000..9a605a7 --- /dev/null +++ b/usb/device/composite/CDCMSDDDriver.c @@ -0,0 +1,213 @@ +/* ----------------------------------------------------------------------------
+ * 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>
+
+//- CDCMSD
+#include "CDCMSDDDriver.h"
+#include "CDCMSDDDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+/// Interface setting spaces (4 byte aligned)
+#define NUM_INTERFACES ((CDCMSDDDriverDescriptors_NUMINTERFACE+3)&0xFC)
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// USBDDriver instance
+static USBDDriver usbdDriver;
+
+/// CDCDSeriaoPort instance
+static CDCDSerialPort cdcdPort;
+
+/// Array for storing the current setting of each interface
+static unsigned char cdcmsddDriverInterfaces[NUM_INTERFACES];
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//-----------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ CDCMSDDDriver_RequestHandler(request);
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// 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)
+{
+ // MSD
+ MSDDFunctionCallbacks_ConfigurationChanged(cfgnum);
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the USB device CDCMSD device driver.
+//-----------------------------------------------------------------------------
+void CDCMSDDDriver_Initialize(MSDLun *pLuns, unsigned char numLuns)
+{
+ // CDC
+ CDCDFunctionDriver_ConfigurePort(&cdcdPort,
+ CDCD_Descriptors_INTERFACENUM0,
+ CDCD_Descriptors_NOTIFICATION0,
+ CDCD_Descriptors_DATAIN0,
+ CDCD_Descriptors_DATAOUT0);
+ CDCDFunctionDriver_Initialize(&usbdDriver,
+ &cdcdPort,
+ 1);
+
+ // MSD
+ MSDDFunctionDriver_Initialize(&usbdDriver,
+ pLuns, numLuns,
+ MSDD_Descriptors_INTERFACENUM,
+ MSDD_Descriptors_BULKIN,
+ MSDD_Descriptors_BULKOUT);
+
+ // Initialize the standard USB driver
+ USBDDriver_Initialize(&usbdDriver,
+ &cdcmsddDriverDescriptors,
+ cdcmsddDriverInterfaces);
+
+ // Initialize the USB driver
+ USBD_Init();
+}
+
+//-----------------------------------------------------------------------------
+/// Handles CDCMSD-specific USB requests sent by the host, and forwards
+/// standard ones to the USB device driver.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+void CDCMSDDDriver_RequestHandler(const USBGenericRequest *request)
+{
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ unsigned char rc = 0;
+
+ // CDC class request
+ if (rc == 0) {
+
+ rc = CDCDFunctionDriver_RequestHandler(request);
+ }
+
+ // MSD class request
+ if (rc == 0) {
+
+ rc = MSDDFunctionDriver_RequestHandler(request);
+ }
+
+ if (!rc) {
+
+ TRACE_WARNING(
+ "CDCMSDDDriver_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;
+
+ if (rc == 0) {
+
+ rc = MSDDFunctionDriver_RequestHandler(request);
+ }
+
+ // Forward request to the standard handler
+ if (rc == 0) {
+
+ USBDDriver_RequestHandler(&(usbdDriver), request);
+ }
+ }
+ // Unsupported request type
+ else {
+
+ TRACE_WARNING(
+ "CDCMSDDDriver_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 CDCMSDDDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+ // Remote wake-up NOT enabled
+ else {
+
+ TRACE_WARNING("CDCMSDDDriver_RemoteWakeUp: not enabled\n\r");
+ }
+}
+
+
diff --git a/usb/device/composite/CDCMSDDDriver.h b/usb/device/composite/CDCMSDDDriver.h new file mode 100644 index 0000000..e6a6834 --- /dev/null +++ b/usb/device/composite/CDCMSDDDriver.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definitions and methods for USB CDCMSD device implement.
+///
+/// !Usage
+///
+/// -# Initialize USB function specified driver ( for MSD currently )
+/// - MSDDFunctionDriver_Initialize
+///
+/// -# Initialize USB CDCMSD driver and USB driver
+/// - CDCMSDDDriver_Initialize
+///
+/// -# Handle and dispach USB requests
+/// - CDCMSDDDriver_RequestHandler
+///
+/// -# Try starting a remote wake-up sequence
+/// - CDCMSDDDriver_RemoteWakeUp
+//-----------------------------------------------------------------------------
+
+#ifndef CDCMSDDDRIVER_H
+#define CDCMSDDDRIVER_H
+
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+#include "CDCDFunctionDriver.h"
+#include "MSDDFunctionDriver.h"
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+// -CDCMSD
+extern void CDCMSDDDriver_Initialize(MSDLun *pLuns, unsigned char numLuns);
+
+extern void CDCMSDDDriver_RequestHandler(const USBGenericRequest *request);
+
+extern void CDCMSDDDriver_RemoteWakeUp(void);
+
+#endif //#ifndef CDCMSDDDRIVER_H
+
diff --git a/usb/device/composite/CDCMSDDDriverDescriptors.c b/usb/device/composite/CDCMSDDDriverDescriptors.c new file mode 100644 index 0000000..27932ac --- /dev/null +++ b/usb/device/composite/CDCMSDDDriverDescriptors.c @@ -0,0 +1,568 @@ +/* ----------------------------------------------------------------------------
+ * 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 "CDCMSDDDriver.h"
+#include "CDCMSDDDriverDescriptors.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 "CDCDFunctionDriverDescriptors.h"
+
+//- MSD
+#include <usb/common/massstorage/MSDeviceDescriptor.h>
+#include <usb/common/massstorage/MSInterfaceDescriptor.h>
+#include "MSDDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Device product ID.
+#define CDCMSDDDriverDescriptors_PRODUCTID 0x6132
+
+/// Device vendor ID (Atmel).
+#define CDCMSDDDriverDescriptors_VENDORID 0x03EB
+
+/// Device release number.
+#define CDCMSDDDriverDescriptors_RELEASE 0x0003
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+
+/// Returns the minimum between two values.
+#define MIN(a, b) ((a < b) ? a : b)
+
+//-----------------------------------------------------------------------------
+// Internal structures
+//-----------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//-----------------------------------------------------------------------------
+/// Configuration descriptor list for a device implementing a CDCMSD driver.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration descriptor.
+ USBConfigurationDescriptor configuration;
+
+ /// --- CDC 0
+ /// 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;
+
+ /// --- MSD
+ /// Mass storage interface descriptor.
+ USBInterfaceDescriptor msdInterface;
+ /// Bulk-out endpoint descriptor.
+ USBEndpointDescriptor msdBulkOut;
+ /// Bulk-in endpoint descriptor.
+ USBEndpointDescriptor msdBulkIn;
+
+} __attribute__ ((packed)) CDCMSDDriverConfigurationDescriptors;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Standard USB device descriptor for the CDCMSD device driver
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ 0xEF,// MI
+ 0x02,//
+ 0x01,//
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ CDCMSDDDriverDescriptors_VENDORID,
+ CDCMSDDDriverDescriptors_PRODUCTID,
+ CDCMSDDDriverDescriptors_RELEASE,
+ 0, // No string descriptor for manufacturer
+ 1, // Index of product string descriptor is #1
+ 0, // No string descriptor for serial number
+ 1 // Device has 1 possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// USB device qualifier descriptor.
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ USBDeviceDescriptor_USB2_00,
+ 0xEF,// MI
+ 0x02,//
+ 0x01,//
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+/// USB configuration descriptors for the CDCMSD device driver
+static const CDCMSDDriverConfigurationDescriptors configurationDescriptorsHS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CDCMSDDriverConfigurationDescriptors),
+ CDCMSDDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // CDC
+ // IAD for CDC/ACM port
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM0,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM0 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM0, // Number of master interface is #0
+ CDCD_Descriptors_INTERFACENUM0 + 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
+ CDCD_Descriptors_INTERRUPT_MAXPACKETSIZE),
+ CDCD_Descriptors_INTERRUPTIN_POLLING_HS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0 + 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ MSDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ }
+
+};
+
+#endif
+
+/// USB configuration descriptors for the CDCMSD device driver
+static const CDCMSDDriverConfigurationDescriptors configurationDescriptorsFS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CDCMSDDriverConfigurationDescriptors),
+ CDCMSDDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // CDC
+ // IAD for CDC/ACM port
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM0,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM0 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM0, // Number of master interface is #0
+ CDCD_Descriptors_INTERFACENUM0 + 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
+ CDCD_Descriptors_INTERRUPT_MAXPACKETSIZE),
+ CDCD_Descriptors_INTERRUPTIN_POLLING_FS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0 + 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ MSDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ }
+
+};
+
+/// String descriptor with the supported languages.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static 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.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(14),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('C'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('o')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(4),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3')
+};
+
+/// Array of pointers to the four string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors required by an USB audio speaker device driver.
+const USBDDriverDescriptors cdcmsddDriverDescriptors = {
+
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#else
+ 0, 0, 0, 0, 0, 0,
+#endif
+ stringDescriptors,
+ 4 // Number of string descriptors
+};
diff --git a/usb/device/composite/CDCMSDDDriverDescriptors.h b/usb/device/composite/CDCMSDDDriverDescriptors.h new file mode 100644 index 0000000..5db1a0c --- /dev/null +++ b/usb/device/composite/CDCMSDDDriverDescriptors.h @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef CDCMSDDDRIVERDESCRIPTORS_H
+#define CDCMSDDDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Number of interfaces of the device
+#define CDCMSDDDriverDescriptors_NUMINTERFACE 3
+
+/// Number of the CDC interface.
+#define CDCD_Descriptors_INTERFACENUM0 0
+/// Address of the CDC interrupt-in endpoint.
+#define CDCD_Descriptors_NOTIFICATION0 3
+/// Address of the CDC bulk-in endpoint.
+#define CDCD_Descriptors_DATAIN0 2
+/// Address of the CDC bulk-out endpoint.
+#define CDCD_Descriptors_DATAOUT0 1
+
+/// Number of the Mass Storage interface.
+#define MSDD_Descriptors_INTERFACENUM 2
+
+/// Address of the Mass Storage bulk-out endpoint.
+#define MSDD_Descriptors_BULKOUT 4
+
+/// Address of the Mass Storage bulk-in endpoint.
+#define MSDD_Descriptors_BULKIN 5
+
+//-----------------------------------------------------------------------------
+// Exported variables
+//-----------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors cdcmsddDriverDescriptors;
+
+#endif //#ifndef CDCMSDDDRIVERDESCRIPTORS_H
diff --git a/usb/device/composite/COMPOSITEDDriver.c b/usb/device/composite/COMPOSITEDDriver.c new file mode 100644 index 0000000..88d64b6 --- /dev/null +++ b/usb/device/composite/COMPOSITEDDriver.c @@ -0,0 +1,292 @@ +/* ----------------------------------------------------------------------------
+ * 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>
+
+//- HID
+#if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ #include <usb/device/hid-keyboard/HIDDKeyboardDriver.h>
+ #include <usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h>
+ #include <usb/device/hid-keyboard/HIDDKeyboardCallbacks.h>
+ #include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+ #include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+
+ #include <usb/common/hid/HIDGenericDescriptor.h>
+ #include <usb/common/hid/HIDDescriptor.h>
+ #include <usb/common/hid/HIDGenericRequest.h>
+ #include <usb/common/hid/HIDReportRequest.h>
+ #include <usb/common/hid/HIDIdleRequest.h>
+ #include <usb/common/hid/HIDKeypad.h>
+#endif // (HID defined)
+
+//- MSD
+#if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+#endif
+
+//- COMPOSITE
+#include "COMPOSITEDDriver.h"
+#include "COMPOSITEDDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+/// Interface setting spaces (4 byte aligned)
+#define NUM_INTERFACES ((COMPOSITEDDriverDescriptors_NUMINTERFACE+3)&0xFC)
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// USBDDriver instance
+static USBDDriver usbdDriver;
+
+// CDC
+#if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCCDC) || defined(usb_CDCMSD)
+/// CDCDSeriaoPort instance
+static CDCDSerialPort cdcdPort;
+#endif // CDC defined
+
+/// Array for storing the current setting of each interface
+static unsigned char compositedDriverInterfaces[NUM_INTERFACES];
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//-----------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ COMPOSITEDDriver_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)
+{
+ // AUDIO
+ #if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+ AUDDFunctionCallbacks_InterfaceSettingChanged(interface, setting);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+// 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)
+{
+ // HID
+ #if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ HIDDFunctionCallbacks_ConfigurationChanged(cfgnum);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the USB device composite device driver.
+//-----------------------------------------------------------------------------
+void COMPOSITEDDriver_Initialize()
+{
+ // CDC
+ #if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCCDC) || defined(usb_CDCMSD)
+ CDCDFunctionDriver_ConfigurePort(&cdcdPort,
+ CDCD_Descriptors_INTERFACENUM0,
+ CDCD_Descriptors_NOTIFICATION0,
+ CDCD_Descriptors_DATAIN0,
+ CDCD_Descriptors_DATAOUT0);
+ CDCDFunctionDriver_Initialize(&usbdDriver,
+ &cdcdPort,
+ 1);
+ #endif
+
+ // AUDIO
+ #if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+ AUDDFunctionDriver_Initialize();
+ #endif
+
+ // HID
+ #if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ HIDDFunctionDriver_Initialize(&usbdDriver,
+ HIDD_Descriptors_INTERFACENUM,
+ HIDD_Descriptors_INTERRUPTIN,
+ HIDD_Descriptors_INTERRUPTOUT);
+ #endif
+
+ // MSD
+ #if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+ // Function driver initialize is put to main() for additional LUN list
+ #endif
+
+ // Initialize the standard USB driver
+ USBDDriver_Initialize(&usbdDriver,
+ &compositedDriverDescriptors,
+ compositedDriverInterfaces);
+
+ // 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 COMPOSITEDDriver_RequestHandler(const USBGenericRequest *request)
+{
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ unsigned char rc = 0;
+
+ // AUDIO class request
+ #if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+ if (rc == 0) {
+
+ rc = AUDDFunctionDriver_RequestHandler(request);
+ }
+ #endif
+
+ // CDC class request
+ #if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCMSD) || defined(usb_CDCCDC)
+ if (rc == 0) {
+
+ rc = CDCDFunctionDriver_RequestHandler(request);
+ }
+ #endif
+
+ // MSD class request
+ #if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+ if (rc == 0) {
+
+ rc = MSDDFunctionDriver_RequestHandler(request);
+ }
+ #endif
+
+ // HID class request
+ #if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ if (rc == 0) {
+
+ rc = HIDDFunctionDriver_RequestHandler(request);
+ }
+ #endif
+
+ if (!rc) {
+
+ TRACE_WARNING(
+ "COMPOSITEDDriver_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;
+
+ #if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ rc = HIDDFunctionDriver_RequestHandler(request);
+ #endif
+
+ #if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+ if (rc == 0) {
+
+ rc = MSDDFunctionDriver_RequestHandler(request);
+ }
+ #endif
+
+ // Forward request to the standard handler
+ if (rc == 0) {
+
+ USBDDriver_RequestHandler(&(usbdDriver), request);
+ }
+ }
+ // Unsupported request type
+ else {
+
+ TRACE_WARNING(
+ "COMPOSITEDDriver_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 COMPOSITEDDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+ // Remote wake-up NOT enabled
+ else {
+
+ TRACE_WARNING("COMPOSITEDDriver_RemoteWakeUp: not enabled\n\r");
+ }
+}
+
+
diff --git a/usb/device/composite/COMPOSITEDDriver.h b/usb/device/composite/COMPOSITEDDriver.h new file mode 100644 index 0000000..6106a9f --- /dev/null +++ b/usb/device/composite/COMPOSITEDDriver.h @@ -0,0 +1,93 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definitions and methods for USB composite device implement.
+///
+/// !Usage
+///
+/// -# Initialize USB function specified driver ( for MSD currently )
+/// - MSDDFunctionDriver_Initialize
+///
+/// -# Initialize USB composite driver and USB driver
+/// - COMPOSITEDDriver_Initialize
+///
+/// -# Handle and dispach USB requests
+/// - COMPOSITEDDriver_RequestHandler
+///
+/// -# Try starting a remote wake-up sequence
+/// - COMPOSITEDDriver_RemoteWakeUp
+//-----------------------------------------------------------------------------
+
+#ifndef COMPOSITEDDRIVER_H
+#define COMPOSITEDDRIVER_H
+
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+#if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCCDC) || defined(usb_CDCMSD)
+ #include "CDCDFunctionDriver.h"
+ #include "CDCDFunctionDriverDescriptors.h"
+#endif
+
+#if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+ #include "AUDDFunctionDriver.h"
+#endif
+
+#if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ #include "HIDDFunctionDriver.h"
+ #include "HIDDFunctionDriverDescriptors.h"
+#endif
+
+#if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+ #include "MSDDFunctionDriver.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+// -COMPOSITE
+extern void COMPOSITEDDriver_Initialize();
+
+extern void COMPOSITEDDriver_RequestHandler(const USBGenericRequest *request);
+
+extern void COMPOSITEDDriver_RemoteWakeUp(void);
+
+#endif //#ifndef COMPOSITEDDRIVER_H
+
diff --git a/usb/device/composite/COMPOSITEDDriverDescriptors.c b/usb/device/composite/COMPOSITEDDriverDescriptors.c new file mode 100644 index 0000000..db195af --- /dev/null +++ b/usb/device/composite/COMPOSITEDDriverDescriptors.c @@ -0,0 +1,954 @@ +/* ----------------------------------------------------------------------------
+ * 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 "COMPOSITEDDriver.h"
+#include "COMPOSITEDDriverDescriptors.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
+#if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCCDC) || defined(usb_CDCMSD)
+ #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 "CDCDFunctionDriverDescriptors.h"
+#endif // (CDC defined)
+
+//- HID
+#if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ #include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+ #include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+ #include <usb/common/hid/HIDGenericDescriptor.h>
+ #include <usb/common/hid/HIDDeviceDescriptor.h>
+ #include <usb/common/hid/HIDInterfaceDescriptor.h>
+ #include <usb/common/hid/HIDDescriptor.h>
+ #include <usb/common/hid/HIDReport.h>
+ #include <usb/common/hid/HIDGenericDesktop.h>
+ #include <usb/common/hid/HIDLeds.h>
+ #include <usb/common/hid/HIDKeypad.h>
+ #include "HIDDFunctionDriverDescriptors.h"
+#endif // (HID defined)
+
+//- AUDIO
+#if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+ #include <usb/common/audio/AUDGenericDescriptor.h>
+ #include <usb/common/audio/AUDDeviceDescriptor.h>
+ #include <usb/common/audio/AUDControlInterfaceDescriptor.h>
+ #include <usb/common/audio/AUDStreamingInterfaceDescriptor.h>
+ #include <usb/common/audio/AUDEndpointDescriptor.h>
+ #include <usb/common/audio/AUDDataEndpointDescriptor.h>
+ #include <usb/common/audio/AUDFormatTypeOneDescriptor.h>
+ #include <usb/common/audio/AUDHeaderDescriptor.h>
+ #include <usb/common/audio/AUDFeatureUnitDescriptor.h>
+ #include <usb/common/audio/AUDInputTerminalDescriptor.h>
+ #include <usb/common/audio/AUDOutputTerminalDescriptor.h>
+ #include "AUDDFunctionDriverDescriptors.h"
+#endif // (AUDIO defined)
+
+//- MSD
+#if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+ #include <usb/common/massstorage/MSDeviceDescriptor.h>
+ #include <usb/common/massstorage/MSInterfaceDescriptor.h>
+ #include "MSDDFunctionDriverDescriptors.h"
+#endif // (MSD defined)
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Device product ID.
+#if defined(usb_CDCHID)
+#define COMPOSITEDDriverDescriptors_PRODUCTID 0x6130
+#elif defined(usb_CDCAUDIO)
+#define COMPOSITEDDriverDescriptors_PRODUCTID 0x6131
+#elif defined(usb_CDCMSD)
+#define COMPOSITEDDriverDescriptors_PRODUCTID 0x6132
+#elif defined(usb_CDCCDC)
+#define COMPOSITEDDriverDescriptors_PRODUCTID 0x6133
+#elif defined(usb_HIDAUDIO)
+#define COMPOSITEDDriverDescriptors_PRODUCTID 0x6134
+#elif defined(usb_HIDMSD)
+#define COMPOSITEDDriverDescriptors_PRODUCTID 0x6135
+#else
+#error COMPOSITE Device Classes not defined!
+#endif
+
+/// Device vendor ID (Atmel).
+#define COMPOSITEDDriverDescriptors_VENDORID 0x03EB
+
+/// Device release number.
+#define COMPOSITEDDriverDescriptors_RELEASE 0x0003
+
+//-----------------------------------------------------------------------------
+// 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
+
+//- AUDIO
+#if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+typedef struct {
+
+ /// Header descriptor.
+ AUDHeaderDescriptor header;
+ /// Id of the first grouped interface.
+ unsigned char bInterface0;
+
+} __attribute__ ((packed)) AUDHeaderDescriptor1; // GCC
+
+//-----------------------------------------------------------------------------
+/// Feature unit descriptor with 3 channel controls (master, right, left).
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Feature unit descriptor.
+ AUDFeatureUnitDescriptor feature;
+ /// Available controls for each channel.
+ unsigned char bmaControls[3];
+ /// Index of a string descriptor for the feature unit.
+ unsigned char iFeature;
+
+} __attribute__ ((packed)) AUDFeatureUnitDescriptor3; // GCC
+
+//-----------------------------------------------------------------------------
+/// List of descriptors for detailling the audio control interface of a
+/// device using a USB audio speaker driver.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Header descriptor (with one slave interface).
+ AUDHeaderDescriptor1 header;
+ /// Input terminal descriptor.
+ AUDInputTerminalDescriptor input;
+ /// Output terminal descriptor.
+ AUDOutputTerminalDescriptor output;
+ /// Feature unit descriptor.
+ AUDFeatureUnitDescriptor3 feature;
+
+} __attribute__ ((packed)) AUDDSpeakerDriverAudioControlDescriptors; // GCC
+
+//-----------------------------------------------------------------------------
+/// Format type I descriptor with one discrete sampling frequency.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Format type I descriptor.
+ AUDFormatTypeOneDescriptor formatType;
+ /// Sampling frequency in Hz.
+ unsigned char tSamFreq[3];
+
+} __attribute__ ((packed)) AUDFormatTypeOneDescriptor1; // GCC
+#endif // (AUDIO defined)
+
+//-----------------------------------------------------------------------------
+/// Configuration descriptor list for a device implementing a composite driver.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration descriptor.
+ USBConfigurationDescriptor configuration;
+
+ #if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCCDC) || defined(usb_CDCMSD)
+ /// --- CDC 0
+ /// 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;
+ #endif // (CDC defined)
+
+ #if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ /// --- HID
+ USBInterfaceDescriptor hidInterface;
+ HIDDescriptor hid;
+ USBEndpointDescriptor hidInterruptIn;
+ USBEndpointDescriptor hidInterruptOut;
+ #endif // (HID defined)
+
+ #if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+ /// --- AUDIO
+ /// IAD 1
+ USBInterfaceAssociationDescriptor audIAD;
+ /// Audio control interface.
+ USBInterfaceDescriptor audInterface;
+ /// Descriptors for the audio control interface.
+ AUDDSpeakerDriverAudioControlDescriptors audControl;
+ /// -- AUDIO out
+ /// Streaming out interface descriptor (with no endpoint, required).
+ USBInterfaceDescriptor audStreamingOutNoIsochronous;
+ /// Streaming out interface descriptor.
+ USBInterfaceDescriptor audStreamingOut;
+ /// Audio class descriptor for the streaming out interface.
+ AUDStreamingInterfaceDescriptor audStreamingOutClass;
+ /// Stream format descriptor.
+ AUDFormatTypeOneDescriptor1 audStreamingOutFormatType;
+ /// Streaming out endpoint descriptor.
+ AUDEndpointDescriptor audStreamingOutEndpoint;
+ /// Audio class descriptor for the streaming out endpoint.
+ AUDDataEndpointDescriptor audStreamingOutDataEndpoint;
+ #endif // (AUDIO defined)
+
+ #if defined(usb_CDCCDC)
+ /// --- CDC 1
+ /// IAD 1
+ USBInterfaceAssociationDescriptor cdcIAD1;
+ /// Communication interface descriptor
+ USBInterfaceDescriptor cdcCommunication1;
+ /// CDC header functional descriptor.
+ CDCHeaderDescriptor cdcHeader1;
+ /// CDC call management functional descriptor.
+ CDCCallManagementDescriptor cdcCallManagement1;
+ /// CDC abstract control management functional descriptor.
+ CDCAbstractControlManagementDescriptor cdcAbstractControlManagement1;
+ /// CDC union functional descriptor (with one slave interface).
+ CDCUnionDescriptor cdcUnion1;
+ /// Notification endpoint descriptor.
+ USBEndpointDescriptor cdcNotification1;
+ /// Data interface descriptor.
+ USBInterfaceDescriptor cdcData1;
+ /// Data OUT endpoint descriptor.
+ USBEndpointDescriptor cdcDataOut1;
+ /// Data IN endpoint descriptor.
+ USBEndpointDescriptor cdcDataIn1;
+ #endif // (Another CDC defined)
+
+ #if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+ /// --- MSD
+ /// Mass storage interface descriptor.
+ USBInterfaceDescriptor msdInterface;
+ /// Bulk-out endpoint descriptor.
+ USBEndpointDescriptor msdBulkOut;
+ /// Bulk-in endpoint descriptor.
+ USBEndpointDescriptor msdBulkIn;
+ #endif // (MSD defined)
+
+} __attribute__ ((packed)) CompositeDriverConfigurationDescriptors;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Standard USB device descriptor for the composite device driver
+const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ #if defined(usb_HIDMSD)
+ 0x00,
+ 0x00,
+ 0x00,
+ #else
+ 0xEF,// MI
+ 0x02,//
+ 0x01,//
+ #endif
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ COMPOSITEDDriverDescriptors_VENDORID,
+ COMPOSITEDDriverDescriptors_PRODUCTID,
+ COMPOSITEDDriverDescriptors_RELEASE,
+ 0, // No string descriptor for manufacturer
+ 1, // Index of product string descriptor is #1
+ 0, // No string descriptor for serial number
+ 1 // Device has 1 possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// 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
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+#endif
+
+/// USB configuration descriptors for the composite device driver
+const CompositeDriverConfigurationDescriptors configurationDescriptors = {
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(CompositeDriverConfigurationDescriptors),
+ COMPOSITEDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ #if defined(usb_CDCAUDIO) || defined(usb_CDCHID) || defined(usb_CDCCDC) || defined(usb_CDCMSD)
+ // CDC
+ // IAD for CDC/ACM port
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM0,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM0 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM0, // Number of master interface is #0
+ CDCD_Descriptors_INTERFACENUM0 + 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ 10 // Endpoint is polled every 10ms
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0 + 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ #endif // (CDC defined)
+
+ #if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ HIDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDD_Descriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDD_Descriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDD_Descriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING
+ },
+ #endif // (HID defined)
+
+ #if defined(usb_CDCAUDIO) || defined(usb_HIDAUDIO)
+ // AUDIO
+ // IAD for AUDIO function
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ AUDD_Descriptors_INTERFACE,
+ 2,
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Audio control interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDD_Descriptors_CONTROL,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoint
+ AUDControlInterfaceDescriptor_CLASS,
+ AUDControlInterfaceDescriptor_SUBCLASS,
+ AUDControlInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio control interface descriptors
+ {
+ // Header descriptor
+ {
+ {
+ sizeof(AUDHeaderDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_HEADER,
+ AUDHeaderDescriptor_AUD1_00,
+ sizeof(AUDDSpeakerDriverAudioControlDescriptors),
+ 1 // One streaming interface
+ },
+ AUDD_Descriptors_STREAMING
+ },
+ // Input terminal descriptor
+ {
+ sizeof(AUDInputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_INPUTTERMINAL,
+ AUDD_Descriptors_INPUTTERMINAL,
+ AUDInputTerminalDescriptor_USBSTREAMING,
+ AUDD_Descriptors_OUTPUTTERMINAL,
+ AUDD_NUMCHANNELS,
+ AUDInputTerminalDescriptor_LEFTFRONT
+ | AUDInputTerminalDescriptor_RIGHTFRONT,
+ 0, // No string descriptor for channels
+ 0 // No string descriptor for input terminal
+ },
+ // Output terminal descriptor
+ {
+ sizeof(AUDOutputTerminalDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_OUTPUTTERMINAL,
+ AUDD_Descriptors_OUTPUTTERMINAL,
+ AUDOutputTerminalDescriptor_SPEAKER,
+ AUDD_Descriptors_INPUTTERMINAL,
+ AUDD_Descriptors_FEATUREUNIT,
+ 0 // No string descriptor
+ },
+ // Feature unit descriptor
+ {
+ {
+ sizeof(AUDFeatureUnitDescriptor3),
+ AUDGenericDescriptor_INTERFACE,
+ AUDGenericDescriptor_FEATUREUNIT,
+ AUDD_Descriptors_FEATUREUNIT,
+ AUDD_Descriptors_INPUTTERMINAL,
+ 1, // 1 byte per channel for controls
+ },
+ {
+ AUDFeatureUnitDescriptor_MUTE, // Master channel controls
+ 0, // Right channel controls
+ 0 // Left channel controls
+ },
+ 0 // No string descriptor
+ }
+ },
+ // Audio streaming interface with 0 endpoints
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDD_Descriptors_STREAMING,
+ 0, // This is alternate setting #0
+ 0, // This interface uses no endpoints
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming interface with data endpoint
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ AUDD_Descriptors_STREAMING,
+ 1, // This is alternate setting #1
+ 1, // This interface uses 1 endpoint
+ AUDStreamingInterfaceDescriptor_CLASS,
+ AUDStreamingInterfaceDescriptor_SUBCLASS,
+ AUDStreamingInterfaceDescriptor_PROTOCOL,
+ 0 // No string descriptor
+ },
+ // Audio streaming class-specific descriptor
+ {
+ sizeof(AUDStreamingInterfaceDescriptor),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_GENERAL,
+ AUDD_Descriptors_INPUTTERMINAL,
+ 0, // No internal delay because of data path
+ AUDFormatTypeOneDescriptor_PCM
+ },
+ // Format type I descriptor
+ {
+ {
+ sizeof(AUDFormatTypeOneDescriptor1),
+ AUDGenericDescriptor_INTERFACE,
+ AUDStreamingInterfaceDescriptor_FORMATTYPE,
+ AUDFormatTypeOneDescriptor_FORMATTYPEONE,
+ AUDD_NUMCHANNELS,
+ AUDD_BYTESPERSAMPLE,
+ AUDD_BYTESPERSAMPLE*8,
+ 1 // One discrete frequency supported
+ },
+ {
+ AUDD_SAMPLERATE & 0xFF,
+ (AUDD_SAMPLERATE >> 8) & 0xFF,
+ (AUDD_SAMPLERATE >> 16) & 0xFF
+ }
+ },
+ // Audio streaming endpoint standard descriptor
+ {
+ sizeof(AUDEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ AUDD_Descriptors_DATAOUT),
+ USBEndpointDescriptor_ISOCHRONOUS,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(AUDD_Descriptors_DATAOUT),
+ 1, // Polling interval = 2^(x-1) milliseconds (1 ms)
+ 0, // This is not a synchronization endpoint
+ 0 // No associated synchronization endpoint
+ },
+ // Audio streaming endpoint class-specific descriptor
+ {
+ sizeof(AUDDataEndpointDescriptor),
+ AUDGenericDescriptor_ENDPOINT,
+ AUDDataEndpointDescriptor_SUBTYPE,
+ 0, // No attributes
+ 0, // Endpoint is not synchronized
+ 0 // Endpoint is not synchronized
+ },
+ #endif // (AUDIO defined)
+
+ #if defined(usb_CDCCDC)
+ // CDC 1
+ // IAD for CDC/ACM port 1
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM1,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM1, // This is interface #2
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM1 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM1, // Number of master interface is #2
+ CDCD_Descriptors_INTERFACENUM1+1 // First slave interface is #3
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION1),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION1),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ 10 // Endpoint is polled every 10ms
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM1 + 1, // This is interface #3
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT1),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT1),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN1),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN1),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ #endif // (2 CDCs defined)
+
+ #if defined(usb_CDCMSD) || defined(usb_HIDMSD)
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ MSDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ },
+ #endif // (MSD defined)
+
+};
+
+/// 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(14),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('C'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('o')
+};
+
+/// Product serial number.
+const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(4),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3')
+};
+
+/// Array of pointers to the four string descriptors.
+const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors required by an USB audio speaker device driver.
+const USBDDriverDescriptors compositedDriverDescriptors = {
+
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptors,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptors,
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptors,
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptors,
+#else
+ 0, 0, 0, 0, 0, 0,
+#endif
+ stringDescriptors,
+ 4 // Number of string descriptors
+};
+
+#if defined(usb_CDCHID) || defined(usb_HIDAUDIO) || defined(usb_HIDMSD)
+/// Report descriptor used by the driver.
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDD_Descriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDD_Descriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDD_Descriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDD_Descriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDD_Descriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDD_Descriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+
+ HIDReport_ENDCOLLECTION
+};
+#endif // (HID defined)
+
diff --git a/usb/device/composite/COMPOSITEDDriverDescriptors.h b/usb/device/composite/COMPOSITEDDriverDescriptors.h new file mode 100644 index 0000000..c82f9bc --- /dev/null +++ b/usb/device/composite/COMPOSITEDDriverDescriptors.h @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef COMPOSITEDDRIVERDESCRIPTORS_H
+#define COMPOSITEDDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Number of interfaces of the device
+#if defined(usb_CDCAUDIO) || defined(usb_CDCCDC)
+ #define COMPOSITEDDriverDescriptors_NUMINTERFACE 4
+#elif defined(usb_CDCHID) || defined(usb_CDCMSD) || defined(usb_HIDAUDIO)
+ #define COMPOSITEDDriverDescriptors_NUMINTERFACE 3
+#elif defined(usb_HIDMSD)
+ #define COMPOSITEDDriverDescriptors_NUMINTERFACE 2
+#else
+ #error USB Composite class not defined.
+#endif
+
+//-----------------------------------------------------------------------------
+// Exported variables
+//-----------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors compositedDriverDescriptors;
+
+#endif //#ifndef COMPOSITEDDRIVERDESCRIPTORS_H
diff --git a/usb/device/composite/DUALCDCDDriver.c b/usb/device/composite/DUALCDCDDriver.c new file mode 100644 index 0000000..cced6f3 --- /dev/null +++ b/usb/device/composite/DUALCDCDDriver.c @@ -0,0 +1,189 @@ +/* ----------------------------------------------------------------------------
+ * 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>
+
+//- DUALCDC
+#include "DUALCDCDDriver.h"
+#include "DUALCDCDDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+/// Interface setting spaces (4 byte aligned)
+#define NUM_INTERFACES ((DUALCDCDDriverDescriptors_NUMINTERFACE+3)&0xFC)
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// USBDDriver instance
+static USBDDriver usbdDriver;
+
+/// CDCDSeriaoPort instance for 2 CDC/CAM serial ports.
+static CDCDSerialPort cdcdPorts[2];
+
+/// Array for storing the current setting of each interface
+static unsigned char compositedDriverInterfaces[NUM_INTERFACES];
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//-----------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ DUALCDCDDriver_RequestHandler(request);
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// ConfigurationChanged() callback re-implementation
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the USB device composite device driver.
+//-----------------------------------------------------------------------------
+void DUALCDCDDriver_Initialize()
+{
+ // CDC
+ CDCDFunctionDriver_ConfigurePort(&cdcdPorts[0],
+ CDCD_Descriptors_INTERFACENUM0,
+ CDCD_Descriptors_NOTIFICATION0,
+ CDCD_Descriptors_DATAIN0,
+ CDCD_Descriptors_DATAOUT0);
+ CDCDFunctionDriver_ConfigurePort(&cdcdPorts[1],
+ CDCD_Descriptors_INTERFACENUM1,
+ CDCD_Descriptors_NOTIFICATION1,
+ CDCD_Descriptors_DATAIN1,
+ CDCD_Descriptors_DATAOUT1);
+ CDCDFunctionDriver_Initialize(&usbdDriver,
+ cdcdPorts,
+ 2);
+
+ // Initialize the standard USB driver
+ USBDDriver_Initialize(&usbdDriver,
+ &dualcdcdDriverDescriptors,
+ compositedDriverInterfaces);
+
+ // 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 DUALCDCDDriver_RequestHandler(const USBGenericRequest *request)
+{
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ unsigned char rc = 0;
+
+ if (rc == 0) {
+
+ rc = CDCDFunctionDriver_RequestHandler(request);
+ }
+
+ if (!rc) {
+
+ TRACE_WARNING(
+ "DUALCDCDDriver_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(
+ "DUALCDCDDriver_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 DUALCDCDDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+ // Remote wake-up NOT enabled
+ else {
+
+ TRACE_WARNING("DUALCDCDDriver_RemoteWakeUp: not enabled\n\r");
+ }
+}
+
+
diff --git a/usb/device/composite/DUALCDCDDriver.h b/usb/device/composite/DUALCDCDDriver.h new file mode 100644 index 0000000..8ff2c66 --- /dev/null +++ b/usb/device/composite/DUALCDCDDriver.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definitions and methods for USB composite device implement.
+///
+/// !Usage
+///
+/// -# Initialize USB function specified driver ( for MSD currently )
+/// - MSDDFunctionDriver_Initialize
+///
+/// -# Initialize USB composite driver and USB driver
+/// - DUALCDCDDriver_Initialize
+///
+/// -# Handle and dispach USB requests
+/// - DUALCDCDDriver_RequestHandler
+///
+/// -# Try starting a remote wake-up sequence
+/// - DUALCDCDDriver_RemoteWakeUp
+//-----------------------------------------------------------------------------
+
+#ifndef DUALCDCDDRIVER_H
+#define DUALCDCDDRIVER_H
+
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+#include "CDCDFunctionDriver.h"
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+// -DUALCDC
+extern void DUALCDCDDriver_Initialize();
+
+extern void DUALCDCDDriver_RequestHandler(const USBGenericRequest *request);
+
+extern void DUALCDCDDriver_RemoteWakeUp(void);
+
+#endif //#ifndef DUALCDCDDRIVER_H
+
diff --git a/usb/device/composite/DUALCDCDDriverDescriptors.c b/usb/device/composite/DUALCDCDDriverDescriptors.c new file mode 100644 index 0000000..f39b29e --- /dev/null +++ b/usb/device/composite/DUALCDCDDriverDescriptors.c @@ -0,0 +1,702 @@ +/* ----------------------------------------------------------------------------
+ * 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 "DUALCDCDDriver.h"
+#include "DUALCDCDDriverDescriptors.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>
+
+#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 "CDCDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Device product ID.
+#define DUALCDCDDriverDescriptors_PRODUCTID 0x6133
+
+/// Device vendor ID (Atmel).
+#define DUALCDCDDriverDescriptors_VENDORID 0x03EB
+
+/// Device release number.
+#define DUALCDCDDriverDescriptors_RELEASE 0x0003
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+
+/// Returns the minimum between two values.
+#define MIN(a, b) ((a < b) ? a : b)
+
+//-----------------------------------------------------------------------------
+// Internal structures
+//-----------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//-----------------------------------------------------------------------------
+/// Configuration descriptor list for a device implementing a composite driver.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration descriptor.
+ USBConfigurationDescriptor configuration;
+
+ /// --- CDC 0
+ /// 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;
+
+ /// --- CDC 1
+ /// IAD 1
+ USBInterfaceAssociationDescriptor cdcIAD1;
+ /// Communication interface descriptor
+ USBInterfaceDescriptor cdcCommunication1;
+ /// CDC header functional descriptor.
+ CDCHeaderDescriptor cdcHeader1;
+ /// CDC call management functional descriptor.
+ CDCCallManagementDescriptor cdcCallManagement1;
+ /// CDC abstract control management functional descriptor.
+ CDCAbstractControlManagementDescriptor cdcAbstractControlManagement1;
+ /// CDC union functional descriptor (with one slave interface).
+ CDCUnionDescriptor cdcUnion1;
+ /// Notification endpoint descriptor.
+ USBEndpointDescriptor cdcNotification1;
+ /// Data interface descriptor.
+ USBInterfaceDescriptor cdcData1;
+ /// Data OUT endpoint descriptor.
+ USBEndpointDescriptor cdcDataOut1;
+ /// Data IN endpoint descriptor.
+ USBEndpointDescriptor cdcDataIn1;
+
+} __attribute__ ((packed)) DualCdcDriverConfigurationDescriptors;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Standard USB device descriptor for the composite device driver
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ 0xEF,// MI
+ 0x02,//
+ 0x01,//
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ DUALCDCDDriverDescriptors_VENDORID,
+ DUALCDCDDriverDescriptors_PRODUCTID,
+ DUALCDCDDriverDescriptors_RELEASE,
+ 0, // No string descriptor for manufacturer
+ 1, // Index of product string descriptor is #1
+ 0, // No string descriptor for serial number
+ 1 // Device has 1 possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// USB device qualifier descriptor.
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ USBDeviceDescriptor_USB2_00,
+ 0xEF,// MI
+ 0x02,//
+ 0x01,//
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+/// USB configuration descriptors for the composite device driver
+static const DualCdcDriverConfigurationDescriptors configurationDescriptorsHS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(DualCdcDriverConfigurationDescriptors),
+ DUALCDCDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // CDC 0
+ // IAD for CDC/ACM port
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM0,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM0 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM0, // Number of master interface is #0
+ CDCD_Descriptors_INTERFACENUM0 + 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
+ CDCD_Descriptors_INTERRUPT_MAXPACKETSIZE),
+ CDCD_Descriptors_INTERRUPTIN_POLLING_HS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0 + 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+
+ // CDC 1
+ // IAD for CDC/ACM port 1
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM1,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM1, // This is interface #2
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM1 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM1, // Number of master interface is #2
+ CDCD_Descriptors_INTERFACENUM1+1 // First slave interface is #3
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION1),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION1),
+ CDCD_Descriptors_INTERRUPT_MAXPACKETSIZE),
+ CDCD_Descriptors_INTERRUPTIN_POLLING_HS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM1 + 1, // This is interface #3
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT1),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT1),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN1),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN1),
+ CDCD_Descriptors_BULK_MAXPACKETSIZE),
+ 0 // Must be 0 for full-speed bulk endpoints
+ }
+
+};
+
+#endif
+
+/// USB configuration descriptors for the composite device driver
+static const DualCdcDriverConfigurationDescriptors configurationDescriptorsFS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(DualCdcDriverConfigurationDescriptors),
+ DUALCDCDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // CDC 0
+ // IAD for CDC/ACM port
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM0,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0, // This is interface #0
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM0 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM0, // Number of master interface is #0
+ CDCD_Descriptors_INTERFACENUM0 + 1 // First slave interface is #1
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION0),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ CDCD_Descriptors_INTERRUPTIN_POLLING_FS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM0 + 1, // This is interface #1
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN0),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+
+ // CDC 1
+ // IAD for CDC/ACM port 1
+ {
+ sizeof(USBInterfaceAssociationDescriptor),
+ USBGenericDescriptor_INTERFACEASSOCIATION,
+ CDCD_Descriptors_INTERFACENUM1,
+ 2,
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Communication class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM1, // This is interface #2
+ 0, // This is alternate setting #0 for this interface
+ 1, // This interface uses 1 endpoint
+ CDCCommunicationInterfaceDescriptor_CLASS,
+ CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL,
+ CDCCommunicationInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Class-specific header functional descriptor
+ {
+ sizeof(CDCHeaderDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_HEADER,
+ CDCGenericDescriptor_CDC1_10
+ },
+ // Class-specific call management functional descriptor
+ {
+ sizeof(CDCCallManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_CALLMANAGEMENT,
+ CDCCallManagementDescriptor_SELFCALLMANAGEMENT,
+ CDCD_Descriptors_INTERFACENUM1 + 1 // No associated data interface
+ },
+ // Class-specific abstract control management functional descriptor
+ {
+ sizeof(CDCAbstractControlManagementDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT,
+ CDCAbstractControlManagementDescriptor_LINE
+ },
+ // Class-specific union functional descriptor with one slave interface
+ {
+ sizeof(CDCUnionDescriptor),
+ CDCGenericDescriptor_INTERFACE,
+ CDCGenericDescriptor_UNION,
+ CDCD_Descriptors_INTERFACENUM1, // Number of master interface is #2
+ CDCD_Descriptors_INTERFACENUM1+1 // First slave interface is #3
+ },
+ // Notification endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_NOTIFICATION1),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_NOTIFICATION1),
+ USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
+ CDCD_Descriptors_INTERRUPTIN_POLLING_FS
+ },
+ // Data class interface standard descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ CDCD_Descriptors_INTERFACENUM1 + 1, // This is interface #3
+ 0, // This is alternate setting #0 for this interface
+ 2, // This interface uses 2 endpoints
+ CDCDataInterfaceDescriptor_CLASS,
+ CDCDataInterfaceDescriptor_SUBCLASS,
+ CDCDataInterfaceDescriptor_NOPROTOCOL,
+ 0 // No string descriptor for this interface
+ },
+ // Bulk-OUT endpoint standard descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
+ CDCD_Descriptors_DATAOUT1),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAOUT1),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
+ CDCD_Descriptors_DATAIN1),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCD_Descriptors_DATAIN1),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed bulk endpoints
+ }
+
+};
+
+/// String descriptor with the supported languages.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static 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.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(14),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('C'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('o')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(4),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3')
+};
+
+/// Array of pointers to the four string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors required by an USB audio speaker device driver.
+const USBDDriverDescriptors dualcdcdDriverDescriptors = {
+
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#else
+ 0, 0, 0, 0, 0, 0,
+#endif
+ stringDescriptors,
+ 4 // Number of string descriptors
+};
diff --git a/usb/device/composite/DUALCDCDDriverDescriptors.h b/usb/device/composite/DUALCDCDDriverDescriptors.h new file mode 100644 index 0000000..13e1f4d --- /dev/null +++ b/usb/device/composite/DUALCDCDDriverDescriptors.h @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef DUALCDCDDRIVERDESCRIPTORS_H
+#define DUALCDCDDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Number of interfaces of the device
+#define DUALCDCDDriverDescriptors_NUMINTERFACE 4
+
+/// Number of the CDC0 interface.
+#define CDCD_Descriptors_INTERFACENUM0 0
+/// Address of the CDC0 interrupt-in endpoint.
+#define CDCD_Descriptors_NOTIFICATION0 3
+/// Address of the CDC0 bulk-in endpoint.
+#define CDCD_Descriptors_DATAIN0 2
+/// Address of the CDC0 bulk-out endpoint.
+#define CDCD_Descriptors_DATAOUT0 1
+
+/// Number of the CDC1 interface.
+#define CDCD_Descriptors_INTERFACENUM1 2
+/// Address of the CDC1 interrupt-in endpoint.
+#define CDCD_Descriptors_NOTIFICATION1 6
+/// Address of the CDC1 bulk-in endpoint.
+#define CDCD_Descriptors_DATAIN1 5
+/// Address of the CDC1 bulk-out endpoint.
+#define CDCD_Descriptors_DATAOUT1 4
+
+
+//-----------------------------------------------------------------------------
+// Exported variables
+//-----------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors dualcdcdDriverDescriptors;
+
+#endif //#ifndef DUALCDCDDRIVERDESCRIPTORS_H
diff --git a/usb/device/composite/HIDDFunctionDriver.c b/usb/device/composite/HIDDFunctionDriver.c new file mode 100644 index 0000000..03f8a1c --- /dev/null +++ b/usb/device/composite/HIDDFunctionDriver.c @@ -0,0 +1,477 @@ +/* ----------------------------------------------------------------------------
+ * 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>
+// USB
+#include <usb/device/core/USBD.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
+#include <usb/device/core/USBDDriver.h>
+// HID
+#include <usb/device/hid-keyboard/HIDDKeyboardDriver.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardCallbacks.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDGenericRequest.h>
+#include <usb/common/hid/HIDReportRequest.h>
+#include <usb/common/hid/HIDIdleRequest.h>
+#include <usb/common/hid/HIDKeypad.h>
+
+#include "HIDDFunctionDriver.h"
+#include "HIDDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Internal types
+//-----------------------------------------------------------------------------
+
+/// Driver structure for an HID device implementing keyboard functionalities.
+typedef struct {
+
+ /// Pointer to USB device driver instance
+ USBDDriver * pUsbdDriver;
+ /// Interface Number to access this function
+ unsigned char interfaceNum;
+ /// Interrupt IN endpoint address
+ unsigned char interruptInEndpoint;
+ /// Interrupt OUT endpoint address
+ unsigned char interruptOutEndpoint;
+ /// Idle rate (in milliseconds) of the input report
+ unsigned char inputReportIdleRate;
+ /// Input report instance.
+ HIDDKeyboardInputReport inputReport;
+ /// Output report instance.
+ HIDDKeyboardOutputReport outputReport;
+
+} HIDDKeyboardDriver;
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// Static instance of the HID keyboard device driver.
+static HIDDKeyboardDriver hiddKeyboardDriver;
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Returns the descriptor requested by the host.
+/// \param type Descriptor type.
+/// \param length Maximum number of bytes to send.
+/// \return 1 if the request has been handled by this function, otherwise 0.
+//-----------------------------------------------------------------------------
+static unsigned char HIDD_GetDescriptor(unsigned char type,
+ unsigned char length)
+{
+ const USBConfigurationDescriptor *pConfiguration;
+ HIDDescriptor *hidDescriptors[2];
+
+ switch (type) {
+
+ case HIDGenericDescriptor_REPORT:
+ TRACE_INFO_WP("Report ");
+
+ // Adjust length and send report descriptor
+ if (length > HIDD_Descriptors_REPORTSIZE) {
+
+ length = HIDD_Descriptors_REPORTSIZE;
+ }
+ USBD_Write(0, &hiddReportDescriptor, length, 0, 0);
+ break;
+
+ case HIDGenericDescriptor_HID:
+ TRACE_INFO_WP("HID ");
+
+ // Configuration descriptor is different depending on speed
+ if (USBD_IsHighSpeed()) {
+
+ pConfiguration = hiddKeyboardDriver
+ .pUsbdDriver->pDescriptors->pHsConfiguration;
+ }
+ else {
+
+ pConfiguration = hiddKeyboardDriver
+ .pUsbdDriver->pDescriptors->pFsConfiguration;
+ }
+
+ // Parse the device configuration to get the HID descriptor
+ USBConfigurationDescriptor_Parse(pConfiguration,
+ 0,
+ 0,
+ (USBGenericDescriptor **) hidDescriptors);
+
+ // Adjust length and send HID descriptor
+ if (length > sizeof(HIDDescriptor)) {
+
+ length = sizeof(HIDDescriptor);
+ }
+ USBD_Write(0, hidDescriptors[0], length, 0, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+/// Sends the current Idle rate of the input report to the host.
+//-----------------------------------------------------------------------------
+static void HIDD_GetIdle()
+{
+ TRACE_INFO_WP("gIdle ");
+
+ USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Retrieves the new idle rate of the input report from the USB host.
+/// \param idleRate New input report idle rate.
+//-----------------------------------------------------------------------------
+static void HIDD_SetIdle(unsigned char idleRate)
+{
+ TRACE_INFO_WP("sIdle(%d) ", idleRate);
+
+ hiddKeyboardDriver.inputReportIdleRate = idleRate;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Sends the requested report to the host.
+/// \param type Report type.
+/// \param length Maximum number of bytes to send.
+//-----------------------------------------------------------------------------
+static void HIDD_GetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO_WP("gReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ TRACE_INFO_WP("In ");
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardInputReport)) {
+
+ length = sizeof(HIDDKeyboardInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ TRACE_INFO_WP("Out ");
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardOutputReport)) {
+
+ length = sizeof(HIDDKeyboardOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Callback invoked when an output report has been received from the host.
+/// Forward the new status of the LEDs to the user program via the
+//-----------------------------------------------------------------------------
+static void HIDD_ReportReceived()
+{
+ TRACE_INFO_WP("oReport ");
+
+ // Trigger callback
+ HIDDKeyboardCallbacks_LedsChanged(
+ HIDDKeyboardOutputReport_GetNumLockStatus(
+ &(hiddKeyboardDriver.outputReport)),
+ HIDDKeyboardOutputReport_GetCapsLockStatus(
+ &(hiddKeyboardDriver.outputReport)),
+ HIDDKeyboardOutputReport_GetScrollLockStatus(
+ &(hiddKeyboardDriver.outputReport)));
+
+ // Restart transfer
+ USBD_Read(hiddKeyboardDriver.interruptOutEndpoint,
+ &(hiddKeyboardDriver.outputReport),
+ sizeof(HIDDKeyboardOutputReport),
+ (TransferCallback) HIDD_ReportReceived,
+ 0); // No argument for callback function
+}
+
+//-----------------------------------------------------------------------------
+/// Retrieves the new value of a report from the host and saves it.
+/// \param type Report type.
+/// \param length Report length.
+//-----------------------------------------------------------------------------
+static void HIDD_SetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO_WP("sReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDKeyboardOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ (TransferCallback) HIDD_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes an USB HID keyboard function driver.
+/// \param pUsbdDriver Pointer to the USB driver instance.
+/// \param interfaceNum Interface number to access the MSD function
+/// \param interruptInEndpoint Interrupt IN endpoint address
+/// \param interruptOutEndpoint Interrupt OUT endpoint address
+//-----------------------------------------------------------------------------
+void HIDDFunctionDriver_Initialize(USBDDriver * pUsbdDriver,
+ unsigned char interfaceNum,
+ unsigned char interruptInEndpoint,
+ unsigned char interruptOutEndpoint)
+{
+ hiddKeyboardDriver.inputReportIdleRate = 0;
+ HIDDKeyboardInputReport_Initialize(&(hiddKeyboardDriver.inputReport));
+ HIDDKeyboardOutputReport_Initialize(&(hiddKeyboardDriver.outputReport));
+
+ hiddKeyboardDriver.pUsbdDriver = pUsbdDriver;
+ hiddKeyboardDriver.interfaceNum = interfaceNum;
+ hiddKeyboardDriver.interruptInEndpoint = interruptInEndpoint;
+ hiddKeyboardDriver.interruptOutEndpoint = interruptOutEndpoint;
+}
+
+//-----------------------------------------------------------------------------
+/// Handles HID-specific SETUP request sent by the host.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return 0 if the request is Unsupported, 1 if the request handled.
+//-----------------------------------------------------------------------------
+unsigned char HIDDFunctionDriver_RequestHandler(
+ const USBGenericRequest *request)
+{
+ TRACE_INFO_WP("NewReq ");
+
+ // Check if this is a standard request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
+
+ // This is a standard request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor, otherwise forward it to
+ // the standard driver
+ if (!HIDD_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(hiddKeyboardDriver.pUsbdDriver,
+ request);
+ }
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ // Check if this is a class request
+ else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ // This is a class-specific request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case HIDGenericRequest_GETIDLE:
+ HIDD_GetIdle();
+ break;
+
+ case HIDGenericRequest_SETIDLE:
+ HIDD_SetIdle(HIDIdleRequest_GetIdleRate(request));
+ break;
+
+ case HIDGenericRequest_GETREPORT:
+ HIDD_GetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ case HIDGenericRequest_SETREPORT:
+ HIDD_SetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+/// Invoked whenever the configuration of the device is changed by the host.
+/// \param cfgnum Newly configuration number.
+//-----------------------------------------------------------------------------
+void HIDDFunctionCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ // Start receiving output reports
+ USBD_Read(hiddKeyboardDriver.interruptOutEndpoint,
+ &(hiddKeyboardDriver.outputReport),
+ sizeof(HIDDKeyboardOutputReport),
+ (TransferCallback) HIDD_ReportReceived,
+ 0); // No argument for callback function
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Reports a change in which keys are currently pressed or release to the
+/// host.
+/// \param pressedKeys Pointer to an array of key codes indicating keys that
+/// have been pressed since the last call to
+/// <HIDDKeyboardDriver_ChangeKeys>.
+/// \param pressedKeysSize Number of key codes in the pressedKeys array.
+/// \param releasedKeys Pointer to an array of key codes indicates keys that
+/// have been released since the last call to
+/// <HIDDKeyboardDriver_ChangeKeys>.
+/// \param releasedKeysSize Number of key codes in the releasedKeys array.
+/// \return <USBD_STATUS_SUCCESS> if the report has been sent to the host;
+/// otherwise an error code.
+//-----------------------------------------------------------------------------
+unsigned char HIDDKeyboardDriver_ChangeKeys(unsigned char *pressedKeys,
+ unsigned char pressedKeysSize,
+ unsigned char *releasedKeys,
+ unsigned char releasedKeysSize)
+{
+ // Press keys
+ while (pressedKeysSize > 0) {
+
+ // Check if this is a standard or modifier key
+ if (HIDKeypad_IsModifierKey(*pressedKeys)) {
+
+ // Set the corresponding bit in the input report
+ HIDDKeyboardInputReport_PressModifierKey(
+ &(hiddKeyboardDriver.inputReport),
+ *pressedKeys);
+ }
+ else {
+
+ HIDDKeyboardInputReport_PressStandardKey(
+ &(hiddKeyboardDriver.inputReport),
+ *pressedKeys);
+ }
+
+ pressedKeysSize--;
+ pressedKeys++;
+ }
+
+ // Release keys
+ while (releasedKeysSize > 0) {
+
+ // Check if this is a standard or modifier key
+ if (HIDKeypad_IsModifierKey(*releasedKeys)) {
+
+ // Set the corresponding bit in the input report
+ HIDDKeyboardInputReport_ReleaseModifierKey(
+ &(hiddKeyboardDriver.inputReport),
+ *releasedKeys);
+ }
+ else {
+
+ HIDDKeyboardInputReport_ReleaseStandardKey(
+ &(hiddKeyboardDriver.inputReport),
+ *releasedKeys);
+ }
+
+ releasedKeysSize--;
+ releasedKeys++;
+ }
+
+ // Send input report through the interrupt IN endpoint
+ return USBD_Write(hiddKeyboardDriver.interruptInEndpoint,
+ &(hiddKeyboardDriver.inputReport),
+ sizeof(HIDDKeyboardInputReport),
+ 0,
+ 0);
+}
+
+//-----------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//-----------------------------------------------------------------------------
+void HIDDKeyboardDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(hiddKeyboardDriver.pUsbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+}
diff --git a/usb/device/composite/HIDDFunctionDriver.h b/usb/device/composite/HIDDFunctionDriver.h new file mode 100644 index 0000000..a788d57 --- /dev/null +++ b/usb/device/composite/HIDDFunctionDriver.h @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef HIDDFUNCTIONDRIVER_H
+#define HIDDFUNCTIONDRIVER_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriver.h>
+#include <usb/common/core/USBGenericRequest.h>
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//- Function API for composite device
+extern void HIDDFunctionDriver_Initialize(USBDDriver * pUsbdDriver,
+ unsigned char interfaceNum,
+ unsigned char interruptInEndpoint,
+ unsigned char interruptOutEndpoint);
+
+extern unsigned char HIDDFunctionDriver_RequestHandler(
+ const USBGenericRequest *request);
+
+extern void HIDDFunctionCallbacks_ConfigurationChanged(unsigned char cfgnum);
+
+//- HID Keyboard API
+extern unsigned char HIDDKeyboardDriver_ChangeKeys(
+ unsigned char *pressedKeys,
+ unsigned char pressedKeysSize,
+ unsigned char *releasedKeys,
+ unsigned char releasedKeysSize);
+
+extern void HIDDKeyboardDriver_RemoteWakeUp(void);
+
+#endif // #define HIDDFUNCTIONDRIVER_H
diff --git a/usb/device/composite/HIDDFunctionDriverDescriptors.c b/usb/device/composite/HIDDFunctionDriverDescriptors.c new file mode 100644 index 0000000..747a5fb --- /dev/null +++ b/usb/device/composite/HIDDFunctionDriverDescriptors.c @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------
+ * 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 <board.h>
+
+//- HID
+#include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDeviceDescriptor.h>
+#include <usb/common/hid/HIDInterfaceDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDReport.h>
+#include <usb/common/hid/HIDGenericDesktop.h>
+#include <usb/common/hid/HIDLeds.h>
+#include <usb/common/hid/HIDKeypad.h>
+#include "HIDDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Internal structures
+//-----------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// Report descriptor used by the HID function driver.
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDD_Descriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDD_Descriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDD_Descriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDD_Descriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDD_Descriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDD_Descriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+
+ HIDReport_ENDCOLLECTION
+};
diff --git a/usb/device/composite/HIDDFunctionDriverDescriptors.h b/usb/device/composite/HIDDFunctionDriverDescriptors.h new file mode 100644 index 0000000..7f64321 --- /dev/null +++ b/usb/device/composite/HIDDFunctionDriverDescriptors.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef HIDDFUNCTIONDRIVERDESCRIPTORS_H
+#define HIDDFUNCTIONDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+#include <usb/common/hid/HIDKeypad.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+//- Interface & Endpoints
+/// Interface Number.
+/// Interrupt IN endpoint number.
+/// Interrupt OUT endpoint number.
+/// Interrupt IN endpoint polling rate (in milliseconds).
+/// Interrupt OUT endpoint polling rate (in milliseconds).
+#if defined(usb_HIDAUDIO)
+#define HIDD_Descriptors_INTERFACENUM 0
+#define HIDD_Descriptors_INTERRUPTIN 1
+#define HIDD_Descriptors_INTERRUPTOUT 2
+#define HIDD_Descriptors_INTERRUPTIN_POLLING 10
+#endif
+
+/// Default HID interrupt IN endpoint polling rate (16ms).
+#define HIDD_Descriptors_INTERRUPTIN_POLLING_FS 16
+#define HIDD_Descriptors_INTERRUPTIN_POLLING_HS 8
+/// Default interrupt OUT endpoint polling rate (16ms).
+#define HIDD_Descriptors_INTERRUPTOUT_POLLING_FS 16
+#define HIDD_Descriptors_INTERRUPTOUT_POLLING_HS 8
+
+//- Keypad keys
+/// Key code of the first accepted modifier key.
+#define HIDD_Descriptors_FIRSTMODIFIERKEY HIDKeypad_LEFTCONTROL
+/// Key code of the last accepted modifier key.
+#define HIDD_Descriptors_LASTMODIFIERKEY HIDKeypad_RIGHTGUI
+/// Key code of the first accepted standard key.
+#define HIDD_Descriptors_FIRSTSTANDARDKEY 0
+/// Key code of the last accepted standard key.
+#define HIDD_Descriptors_LASTSTANDARDKEY HIDKeypad_NUMLOCK
+
+//- Report descriptor
+/// Size of the report descriptor in bytes.
+#define HIDD_Descriptors_REPORTSIZE 61
+
+//-----------------------------------------------------------------------------
+// Exported variables
+//-----------------------------------------------------------------------------
+
+/// Report descriptor used by the driver.
+extern const unsigned char hiddReportDescriptor[];
+
+#endif // #define HIDDFUNCTIONDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/composite/HIDMSDDDriver.c b/usb/device/composite/HIDMSDDDriver.c new file mode 100644 index 0000000..2ef2ea7 --- /dev/null +++ b/usb/device/composite/HIDMSDDDriver.c @@ -0,0 +1,227 @@ +/* ----------------------------------------------------------------------------
+ * 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>
+
+//- HID
+#include <usb/device/hid-keyboard/HIDDKeyboardDriver.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardCallbacks.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDGenericRequest.h>
+#include <usb/common/hid/HIDReportRequest.h>
+#include <usb/common/hid/HIDIdleRequest.h>
+#include <usb/common/hid/HIDKeypad.h>
+
+//- MSD
+
+//- HIDMSD
+#include "HIDMSDDDriver.h"
+#include "HIDMSDDDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+/// Interface setting spaces (4 byte aligned)
+#define NUM_INTERFACES ((HIDMSDDDriverDescriptors_NUMINTERFACE+3)&0xFC)
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// USBDDriver instance
+static USBDDriver usbdDriver;
+
+/// Array for storing the current setting of each interface
+static unsigned char hidmsddDriverInterfaces[NUM_INTERFACES];
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//-----------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ HIDMSDDDriver_RequestHandler(request);
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// 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)
+{
+ // HID
+ HIDDFunctionCallbacks_ConfigurationChanged(cfgnum);
+
+ // MSD
+ MSDDFunctionCallbacks_ConfigurationChanged(cfgnum);
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the USB device HIDMSD device driver.
+//-----------------------------------------------------------------------------
+void HIDMSDDDriver_Initialize(MSDLun *pLuns, unsigned char numLuns)
+{
+ // HID
+ HIDDFunctionDriver_Initialize(&usbdDriver,
+ HIDD_Descriptors_INTERFACENUM,
+ HIDD_Descriptors_INTERRUPTIN,
+ HIDD_Descriptors_INTERRUPTOUT);
+
+ // MSD
+ MSDDFunctionDriver_Initialize(&usbdDriver,
+ pLuns, numLuns,
+ MSDD_Descriptors_INTERFACENUM,
+ MSDD_Descriptors_BULKIN,
+ MSDD_Descriptors_BULKOUT);
+
+ // Initialize the standard USB driver
+ USBDDriver_Initialize(&usbdDriver,
+ &hidmsddDriverDescriptors,
+ hidmsddDriverInterfaces);
+
+ // Initialize the USB driver
+ USBD_Init();
+}
+
+//-----------------------------------------------------------------------------
+/// Handles HIDMSD-specific USB requests sent by the host, and forwards
+/// standard ones to the USB device driver.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+void HIDMSDDDriver_RequestHandler(const USBGenericRequest *request)
+{
+ // Check if this is a class request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ unsigned char rc = 0;
+
+ // MSD class request
+ if (rc == 0) {
+
+ rc = MSDDFunctionDriver_RequestHandler(request);
+ }
+
+ // HID class request
+ if (rc == 0) {
+
+ rc = HIDDFunctionDriver_RequestHandler(request);
+ }
+
+ if (!rc) {
+
+ TRACE_WARNING(
+ "HIDMSDDDriver_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;
+
+ rc = HIDDFunctionDriver_RequestHandler(request);
+
+ if (rc == 0) {
+
+ rc = MSDDFunctionDriver_RequestHandler(request);
+ }
+
+ // Forward request to the standard handler
+ if (rc == 0) {
+
+ USBDDriver_RequestHandler(&(usbdDriver), request);
+ }
+ }
+ // Unsupported request type
+ else {
+
+ TRACE_WARNING(
+ "HIDMSDDDriver_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 HIDMSDDDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+ // Remote wake-up NOT enabled
+ else {
+
+ TRACE_WARNING("HIDMSDDDriver_RemoteWakeUp: not enabled\n\r");
+ }
+}
+
+
diff --git a/usb/device/composite/HIDMSDDDriver.h b/usb/device/composite/HIDMSDDDriver.h new file mode 100644 index 0000000..ba37205 --- /dev/null +++ b/usb/device/composite/HIDMSDDDriver.h @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+/// \unit
+///
+/// !Purpose
+///
+/// Definitions and methods for USB HID + MSD HIDMSD device implement.
+///
+/// !Usage
+///
+/// -# Initialize USB function specified driver ( for MSD currently )
+/// - MSDDFunctionDriver_Initialize
+///
+/// -# Initialize USB HIDMSD driver and USB driver
+/// - HIDMSDDDriver_Initialize
+///
+/// -# Handle and dispach USB requests
+/// - HIDMSDDDriver_RequestHandler
+///
+/// -# Try starting a remote wake-up sequence
+/// - HIDMSDDDriver_RemoteWakeUp
+//-----------------------------------------------------------------------------
+
+#ifndef HIDMSDDDRIVER_H
+#define HIDMSDDDRIVER_H
+
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+#include "HIDDFunctionDriver.h"
+#include "MSDDFunctionDriver.h"
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+// -HIDMSD Composite device
+extern void HIDMSDDDriver_Initialize(MSDLun *pLuns,
+ unsigned char numLuns);
+
+extern void HIDMSDDDriver_RequestHandler(const USBGenericRequest *request);
+
+extern void HIDMSDDDriver_RemoteWakeUp(void);
+
+#endif //#ifndef HIDMSDDDRIVER_H
+
diff --git a/usb/device/composite/HIDMSDDDriverDescriptors.c b/usb/device/composite/HIDMSDDDriverDescriptors.c new file mode 100644 index 0000000..aecfd61 --- /dev/null +++ b/usb/device/composite/HIDMSDDDriverDescriptors.c @@ -0,0 +1,449 @@ +/* ----------------------------------------------------------------------------
+ * 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 "HIDMSDDDriver.h"
+#include "HIDMSDDDriverDescriptors.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>
+
+//- HID
+#include <usb/device/hid-keyboard/HIDDKeyboardInputReport.h>
+#include <usb/device/hid-keyboard/HIDDKeyboardOutputReport.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDeviceDescriptor.h>
+#include <usb/common/hid/HIDInterfaceDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDReport.h>
+#include <usb/common/hid/HIDGenericDesktop.h>
+#include <usb/common/hid/HIDLeds.h>
+#include <usb/common/hid/HIDKeypad.h>
+#include "HIDDFunctionDriverDescriptors.h"
+
+//- MSD
+#include <usb/common/massstorage/MSDeviceDescriptor.h>
+#include <usb/common/massstorage/MSInterfaceDescriptor.h>
+#include "MSDDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Device product ID.
+#define HIDMSDDDriverDescriptors_PRODUCTID 0x6135
+
+/// Device vendor ID (Atmel).
+#define HIDMSDDDriverDescriptors_VENDORID 0x03EB
+
+/// Device release number.
+#define HIDMSDDDriverDescriptors_RELEASE 0x0003
+
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration descriptor.
+ USBConfigurationDescriptor configuration;
+
+ /// --- HID
+ USBInterfaceDescriptor hidInterface;
+ HIDDescriptor hid;
+ USBEndpointDescriptor hidInterruptIn;
+ USBEndpointDescriptor hidInterruptOut;
+
+ /// --- MSD
+ /// Mass storage interface descriptor.
+ USBInterfaceDescriptor msdInterface;
+ /// Bulk-out endpoint descriptor.
+ USBEndpointDescriptor msdBulkOut;
+ /// Bulk-in endpoint descriptor.
+ USBEndpointDescriptor msdBulkIn;
+
+} __attribute__ ((packed)) HidMsdDriverConfigurationDescriptors;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Standard USB device descriptor for the composite device driver
+static const USBDeviceDescriptor deviceDescriptor =
+{
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ 0x00,
+ 0x00,
+ 0x00,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDMSDDDriverDescriptors_VENDORID,
+ HIDMSDDDriverDescriptors_PRODUCTID,
+ HIDMSDDDriverDescriptors_RELEASE,
+ 0, // No string descriptor for manufacturer
+ 1, // Index of product string descriptor is #1
+ 0, // No string descriptor for serial number
+ 1 // Device has 1 possible configuration
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+/// USB device qualifier descriptor.
+static const USBDeviceQualifierDescriptor qualifierDescriptor =
+{
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ USBDeviceDescriptor_USB2_00,
+ 0x00,
+ 0x00,
+ 0x00,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration
+ 0 // Reserved
+};
+
+/// USB configuration descriptors for the composite device driver
+static const HidMsdDriverConfigurationDescriptors configurationDescriptorsHS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HidMsdDriverConfigurationDescriptors),
+ HIDMSDDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ HIDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDD_Descriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDD_Descriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING_HS
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDD_Descriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING_HS
+ },
+
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ MSDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ }
+
+};
+
+#endif
+
+/// USB FS configuration descriptors for the composite device driver
+static const HidMsdDriverConfigurationDescriptors configurationDescriptorsFS =
+{
+
+ // Standard configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HidMsdDriverConfigurationDescriptors),
+ HIDMSDDDriverDescriptors_NUMINTERFACE,
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ HIDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDD_Descriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDD_Descriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING_FS
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDD_Descriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDD_Descriptors_INTERRUPTIN_POLLING_FS
+ },
+
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ MSDD_Descriptors_INTERFACENUM,
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDD_Descriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ }
+
+};
+
+/// String descriptor with the supported languages.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static 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.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(14),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('C'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('p'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('o')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(4),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3')
+};
+
+/// Array of pointers to the four string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors required by an USB audio speaker device driver.
+const USBDDriverDescriptors hidmsddDriverDescriptors = {
+
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &deviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &qualifierDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#else
+ 0, 0, 0, 0, 0, 0,
+#endif
+ stringDescriptors,
+ 4 // Number of string descriptors
+};
diff --git a/usb/device/composite/HIDMSDDDriverDescriptors.h b/usb/device/composite/HIDMSDDDriverDescriptors.h new file mode 100644 index 0000000..85739be --- /dev/null +++ b/usb/device/composite/HIDMSDDDriverDescriptors.h @@ -0,0 +1,66 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef HIDMSDDDRIVERDESCRIPTORS_H
+#define HIDMSDDDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <board.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+/// Number of interfaces of the device
+#define HIDMSDDDriverDescriptors_NUMINTERFACE 2
+
+#define HIDD_Descriptors_INTERFACENUM 0
+/// Address of the HID interrupt IN endpoint.
+#define HIDD_Descriptors_INTERRUPTIN 1
+/// Address of the HID interrupt OUT endpoint.
+#define HIDD_Descriptors_INTERRUPTOUT 2
+
+#define MSDD_Descriptors_INTERFACENUM 1
+/// Address of the Mass Storage bulk-out endpoint.
+#define MSDD_Descriptors_BULKOUT 4
+/// Address of the Mass Storage bulk-in endpoint.
+#define MSDD_Descriptors_BULKIN 5
+
+
+//-----------------------------------------------------------------------------
+// Exported variables
+//-----------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors hidmsddDriverDescriptors;
+
+#endif //#ifndef HIDMSDDDRIVERDESCRIPTORS_H
diff --git a/usb/device/composite/MSDDFunctionDriver.c b/usb/device/composite/MSDDFunctionDriver.c new file mode 100644 index 0000000..840294e --- /dev/null +++ b/usb/device/composite/MSDDFunctionDriver.c @@ -0,0 +1,327 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+
+// GENERAL
+#include <utility/trace.h>
+#include <utility/assert.h>
+// USB
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+// MSD
+#include <usb/device/massstorage/SBCMethods.h>
+#include <usb/device/massstorage/MSDDStateMachine.h>
+#include "MSDDFunctionDriverDescriptors.h"
+
+//-----------------------------------------------------------------------------
+// Internal types
+//-----------------------------------------------------------------------------
+
+/// Driver structure for an HID device implementing keyboard functionalities.
+typedef struct {
+
+ /// Pointer to USB device driver instance
+ USBDDriver * pUsbdDriver;
+ /// Pointer to MSD driver instance
+ MSDDriver * pMsdDriver;
+ /// Interface Number of MS Function
+ unsigned char interfaceNum;
+ /// Interrupt IN endpoint address
+ unsigned char bulkInEndpoint;
+ /// Interrupt OUT endpoint address
+ unsigned char bulkOutEndpoint;
+
+} MSDFunctionDriver;
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// Mass storage general driver instance.
+static MSDDriver msdDriver;
+
+/// Mass storage function driver instance.
+static MSDFunctionDriver msdFunDriver;
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Resets the state of the MSD driver
+//-----------------------------------------------------------------------------
+static void MSDD_Reset()
+{
+ TRACE_INFO_WP("MSDReset ");
+
+ msdDriver.state = MSDD_STATE_READ_CBW;
+ msdDriver.waitResetRecovery = 0;
+ msdDriver.commandState.state = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes a MSD driver
+/// \param luns Pointer to a list of LUNs
+/// \param numLuns Number of LUN in list
+/// \param interfaceNum Interface number to access the MSD function
+/// \param bulkInEndpoint Bulk IN endpoint address
+/// \param bulkOutEndpoint Bulk OUT endpoint address
+//-----------------------------------------------------------------------------
+void MSDDFunctionDriver_Initialize(USBDDriver * pUsbdDriver,
+ MSDLun *luns, unsigned char numLuns,
+ unsigned char interfaceNum,
+ unsigned char bulkInEndpoint,
+ unsigned char bulkOutEndpoint)
+{
+ TRACE_INFO("MSD init\n\r");
+
+ msdFunDriver.pUsbdDriver = pUsbdDriver;
+ msdFunDriver.pMsdDriver = &msdDriver;
+ msdFunDriver.interfaceNum = interfaceNum;
+ msdFunDriver.bulkInEndpoint = bulkInEndpoint;
+ msdFunDriver.bulkOutEndpoint = bulkOutEndpoint;
+
+ // Command state initialization
+ msdDriver.commandState.state = 0;
+ msdDriver.commandState.postprocess = 0;
+ msdDriver.commandState.length = 0;
+ msdDriver.commandState.transfer.semaphore = 0;
+
+ // LUNs
+ msdDriver.luns = luns;
+ msdDriver.maxLun = (unsigned char) (numLuns - 1);
+
+ // Reset BOT driver
+ MSDD_Reset();
+}
+
+//-----------------------------------------------------------------------------
+/// Invoked when a new SETUP request is received from the host. Forwards the
+/// request to the Mass Storage device driver handler function.
+/// \param request Pointer to a USBGenericRequest instance.
+/// \return 0 if the request is Unsupported, 1 if the request handled.
+//-----------------------------------------------------------------------------
+unsigned char MSDDFunctionDriver_RequestHandler(
+ const USBGenericRequest *request)
+{
+ // Handle requests
+ switch (USBGenericRequest_GetRequest(request)) {
+ //---------------------
+ case USBGenericRequest_CLEARFEATURE:
+ //---------------------
+ TRACE_INFO_WP("ClrFeat ");
+
+ switch (USBFeatureRequest_GetFeatureSelector(request)) {
+
+ //---------------------
+ case USBFeatureRequest_ENDPOINTHALT:
+ //---------------------
+ TRACE_INFO_WP("Hlt ");
+
+ // Do not clear the endpoint halt status if the device is waiting
+ // for a reset recovery sequence
+ if (!msdDriver.waitResetRecovery) {
+
+ // Forward the request to the standard handler
+ return 0;
+ }
+ else {
+
+ TRACE_INFO_WP("No ");
+ }
+
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ //------
+ default:
+ //------
+ // Forward the request to the standard handler
+ return 0;
+ }
+ break;
+
+ //-------------------
+ case MSD_GET_MAX_LUN:
+ //-------------------
+ TRACE_INFO_WP("gMaxLun ");
+
+ // Check request parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == msdFunDriver.interfaceNum)
+ && (request->wLength == 1)) {
+
+ USBD_Write(0, &(msdDriver.maxLun), 1, 0, 0);
+
+ }
+ else {
+
+ TRACE_WARNING(
+ "MSDDriver_RequestHandler: GetMaxLUN(%d,%d,%d)\n\r",
+ request->wValue, request->wIndex, request->wLength);
+ USBD_Stall(0);
+ }
+ break;
+
+ //-----------------------
+ case MSD_BULK_ONLY_RESET:
+ //-----------------------
+ TRACE_INFO_WP("Rst ");
+
+ // Check parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == msdFunDriver.interfaceNum)
+ && (request->wLength == 0)) {
+
+ // Reset the MSD driver
+ MSDD_Reset();
+ USBD_Write(0, 0, 0, 0, 0);
+ }
+ else {
+
+ TRACE_WARNING(
+ "MSDDriver_RequestHandler: Reset(%d,%d,%d)\n\r",
+ request->wValue, request->wIndex, request->wLength);
+ USBD_Stall(0);
+ }
+ break;
+
+ //------
+ default:
+ //------
+ // Forward request to standard handler
+ return 0;
+ }
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+/// Invoked whenever the configuration of the device is changed by the host.
+/// \param cfgnum Newly configuration number.
+//-----------------------------------------------------------------------------
+void MSDDFunctionCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ MSDD_Reset();
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Reads from host through MSD defined pipe. Act as USBD_Read.
+/// \param data Pointer to the data buffer that contains data read from host.
+/// \param size The number of bytes should be read (buffer size).
+/// \param callback Pointer to the function invoked on end of reading.
+/// \param argument Pointer to additional argument data struct.
+//-----------------------------------------------------------------------------
+char MSDD_Read(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+
+{
+ return USBD_Read(msdFunDriver.bulkOutEndpoint,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// Writes to host through MSD defined pipe. Act as USBD_Write.
+/// \param data Pointer to the data that writes to the host.
+/// \param size The number of bytes should be write.
+/// \param callback Pointer to the function invoked on end of writing.
+/// \param argument Pointer to additional argument data struct.
+//-----------------------------------------------------------------------------
+char MSDD_Write(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Write(msdFunDriver.bulkInEndpoint,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// HALT Specified USB pipe.
+/// \param stallCASE Case of the stall condition (Bulk In/Out/Both).
+//-----------------------------------------------------------------------------
+void MSDD_Halt(unsigned int stallCASE)
+{
+ if (stallCASE & MSDD_CASE_STALL_OUT) {
+
+ USBD_Halt(msdFunDriver.bulkOutEndpoint);
+ }
+
+ if (stallCASE & MSDD_CASE_STALL_IN) {
+
+ USBD_Halt(msdFunDriver.bulkInEndpoint);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Return halted status
+/// \return stallCASE bitmap, case of the stall condition
+/// (bit: MSDD_CASE_STALL_OUT or MSDD_CASE_STALL_IN)
+//-----------------------------------------------------------------------------
+unsigned int MSDD_IsHalted(void)
+{
+ unsigned int stallCASE = 0;
+ if (USBD_IsHalted(msdFunDriver.bulkOutEndpoint)) {
+
+ stallCASE |= MSDD_CASE_STALL_OUT;
+ }
+ if (USBD_IsHalted(msdFunDriver.bulkInEndpoint)) {
+
+ stallCASE |= MSDD_CASE_STALL_IN;
+ }
+ return stallCASE;
+}
+
+//-----------------------------------------------------------------------------
+/// State machine for the MSD driver
+//-----------------------------------------------------------------------------
+void MSDDriver_StateMachine(void)
+{
+ MSDD_StateMachine(&msdDriver);
+}
diff --git a/usb/device/composite/MSDDFunctionDriver.h b/usb/device/composite/MSDDFunctionDriver.h new file mode 100644 index 0000000..c96fbfd --- /dev/null +++ b/usb/device/composite/MSDDFunctionDriver.h @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Mass storage function driver implementation.
+///
+/// !Usage
+/// TODO
+//-----------------------------------------------------------------------------
+
+#ifndef MSDDFUNCTIONDRIVER_H
+#define MSDDFUNCTIONDRIVER_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/device/massstorage/MSD.h>
+#include <usb/device/massstorage/MSDLun.h>
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//- Function API for composite device
+extern void MSDDFunctionDriver_Initialize(USBDDriver * pUsbdDriver,
+ MSDLun *luns, unsigned char numLuns,
+ unsigned char interfaceNum,
+ unsigned char bulkInEndpoint,
+ unsigned char bulkOutEndpoint);
+
+extern unsigned char MSDDFunctionDriver_RequestHandler(
+ const USBGenericRequest *request);
+
+extern void MSDDFunctionCallbacks_ConfigurationChanged(unsigned char cfgnum);
+
+//- MSD APIs
+extern void MSDDriver_StateMachine(void);
+
+#endif // #define MSDDFUNCTIONDRIVER_H
+
diff --git a/usb/device/composite/MSDDFunctionDriverDescriptors.h b/usb/device/composite/MSDDFunctionDriverDescriptors.h new file mode 100644 index 0000000..6da6214 --- /dev/null +++ b/usb/device/composite/MSDDFunctionDriverDescriptors.h @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef MSDDFUNCTIONDRIVERDESCRIPTORS_H
+#define MSDDFUNCTIONDRIVERDESCRIPTORS_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// \page "MS interface & endpoint descriptor settings"
+/// This page lists the definition used by the Mass Storage driver.
+///
+/// !Settings
+///
+/// - MSDD_Descriptors_INTERFACENUM
+/// - MSDD_Descriptors_BULKOUT
+/// - MSDD_Descriptors_BULKIN
+
+/// Number of the Mass Storage interface.
+#if defined(usb_CDCMSD)
+#define MSDD_Descriptors_INTERFACENUM 2
+#elif defined(usb_HIDMSD)
+#define MSDD_Descriptors_INTERFACENUM 1
+#endif
+
+/// Address of the Mass Storage bulk-out endpoint.
+#define MSDD_Descriptors_BULKOUT 4
+
+/// Address of the Mass Storage bulk-in endpoint.
+#define MSDD_Descriptors_BULKIN 5
+//-----------------------------------------------------------------------------
+
+
+#endif // #define MSDDFUNCTIONDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/composite/drv/CompositeCDCSerial.inf b/usb/device/composite/drv/CompositeCDCSerial.inf new file mode 100644 index 0000000..973a14b --- /dev/null +++ b/usb/device/composite/drv/CompositeCDCSerial.inf @@ -0,0 +1,57 @@ +; $Id: 6119.inf,v 1.1.2.1 2006/12/05 08:33:25 danielru Exp $
+
+[Version] ; Version section
+Signature="$Chicago$" ; All Windows versions
+Class=Ports ; This is a serial port driver
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} ; Associated GUID
+Provider=%ATMEL% ; Driver is provided by ATMEL
+DriverVer=09/12/2006,1.1.1.5 ; Driver version 1.1.1.5 published on 23 February 2007
+
+[DestinationDirs] ; DestinationDirs section
+DefaultDestDir=12 ; Default install directory is \drivers or \IOSubSys
+
+[Manufacturer] ; Manufacturer section
+%ATMEL%=AtmelMfg ; Only one manufacturer (ATMEL), models section is named
+ ; AtmelMfg
+
+[AtmelMfg] ; Models section corresponding to ATMEL
+%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6130&MI_00 ; Identifies a device with ATMEL Vendor ID (03EBh) and
+ ; Product ID equal to 6130h. Corresponding Install section
+ ; is named USBtoSer.Install ( CDCHID )
+%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6131&MI_00 ; Identifies a device with ATMEL Vendor ID (03EBh) and
+ ; Product ID equal to 6131h. Corresponding Install section
+ ; is named USBtoSer.Install ( CDCAUDIO )
+%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6132&MI_00 ; Identifies a device with ATMEL Vendor ID (03EBh) and
+ ; Product ID equal to 6132h. Corresponding Install section
+ ; is named USBtoSer.Install ( CDCMSD )
+%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6133&MI_00 ; Identifies a device with ATMEL Vendor ID (03EBh) and
+ ; Product ID equal to 6133h. Corresponding Install section
+ ; is named USBtoSer.Install ( CDCCDC )
+%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6133&MI_02 ; Identifies a device with ATMEL Vendor ID (03EBh) and
+ ; Product ID equal to 6133h. Corresponding Install section
+ ; is named USBtoSer.Install ( CDCCDC )
+
+[USBtoSer.Install] ; Install section
+include=mdmcpq.inf
+CopyFiles=FakeModemCopyFileSection
+AddReg=USBtoSer.AddReg ; Registry keys to add are listed in USBtoSer.AddReg
+
+[USBtoSer.AddReg] ; AddReg section
+HKR,,DevLoader,,*ntkern ;
+HKR,,NTMPDriver,,usbser.sys
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[USBtoSer.Install.Services] ; Services section
+AddService=usbser,0x00000002,USBtoSer.AddService ; Assign usbser as the PnP driver for the device
+
+[USBtoSer.AddService] ; Service install section
+DisplayName=%USBSer% ; Name of the serial driver
+ServiceType=1 ; Service kernel driver
+StartType=3 ; Driver is started by the PnP manager
+ErrorControl=1 ; Warn about errors
+ServiceBinary=%12%\usbser.sys ; Driver filename
+
+[Strings] ; Strings section
+ATMEL="ATMEL Corp." ; String value for the ATMEL symbol
+USBtoSerialConverter="AT91 USB to Serial Converter" ; String value for the USBtoSerialConverter symbol
+USBSer="USB Composite Serial Driver" ; String value for the USBSer symbol
\ No newline at end of file diff --git a/usb/device/composite/drv/drv.dir b/usb/device/composite/drv/drv.dir new file mode 100644 index 0000000..1f2d5d6 --- /dev/null +++ b/usb/device/composite/drv/drv.dir @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides install file for
+/// - CDC HID
+/// - CDC AUDIO
+/// - CDC MSD
+/// - CDC CDC
+///
+/// !!!Contents
+///
+/// CompositeCDCSerial.inf
+///
+//------------------------------------------------------------------------------
diff --git a/usb/device/core/USBD.h b/usb/device/core/USBD.h new file mode 100644 index 0000000..e6c2e9b --- /dev/null +++ b/usb/device/core/USBD.h @@ -0,0 +1,276 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Collection of methods for using the USB device controller on AT91
+/// microcontrollers.
+///
+/// !!!Usage
+///
+/// Please refer to the corresponding application note.
+/// - "AT91 USB device framework"
+/// - "USBD API" . "USBD API Methods"
+//------------------------------------------------------------------------------
+
+#ifndef USBD_H
+#define USBD_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <board.h>
+#include <memories/Media.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Compile Options
+//------------------------------------------------------------------------------
+
+/// Compile option for HS or OTG, use DMA. Remove this define for not use DMA.
+#if defined(CHIP_USB_OTGHS) || defined(CHIP_USB_UDPHS)
+#define DMA
+#endif
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB device API return values"
+///
+/// This page lists the return values of the USB %device driver API
+///
+/// !Return codes
+/// - USBD_STATUS_SUCCESS
+/// - USBD_STATUS_LOCKED
+/// - USBD_STATUS_ABORTED
+/// - USBD_STATUS_RESET
+
+/// Indicates the operation was successful.
+#define USBD_STATUS_SUCCESS 0
+/// Endpoint/device is already busy.
+#define USBD_STATUS_LOCKED 1
+/// Operation has been aborted.
+#define USBD_STATUS_ABORTED 2
+/// Operation has been aborted because the device has been reset.
+#define USBD_STATUS_RESET 3
+/// Part ot operation successfully done.
+#define USBD_STATUS_PARTIAL_DONE 4
+/// Operation failed because parameter error
+#define USBD_STATUS_INVALID_PARAMETER 5
+/// Operation failed because in unexpected state
+#define USBD_STATUS_WRONG_STATE 6
+/// Operation failed because HW not supported
+#define USBD_STATUS_HW_NOT_SUPPORTED 0xFE
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB device states"
+///
+/// This page lists the %device states of the USB %device driver.
+///
+/// !States
+/// - USBD_STATE_SUSPENDED
+/// - USBD_STATE_ATTACHED
+/// - USBD_STATE_POWERED
+/// - USBD_STATE_DEFAULT
+/// - USBD_STATE_ADDRESS
+/// - USBD_STATE_CONFIGURED
+
+/// The device is currently suspended.
+#define USBD_STATE_SUSPENDED 0
+/// USB cable is plugged into the device.
+#define USBD_STATE_ATTACHED 1
+/// Host is providing +5V through the USB cable.
+#define USBD_STATE_POWERED 2
+/// Device has been reset.
+#define USBD_STATE_DEFAULT 3
+/// The device has been given an address on the bus.
+#define USBD_STATE_ADDRESS 4
+/// A valid configuration has been selected.
+#define USBD_STATE_CONFIGURED 5
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "USB device LEDs"
+///
+/// This page lists the LEDs used in the USB %device driver.
+///
+/// !LEDs
+/// - USBD_LEDPOWER
+/// - USBD_LEDUSB
+/// - USBD_LEDOTHER
+
+/// LED for indicating that the device is powered.
+#define USBD_LEDPOWER 0
+/// LED for indicating USB activity.
+#define USBD_LEDUSB 1
+/// LED for custom usage.
+#define USBD_LEDOTHER 2
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Buffer struct used for multi-buffer-listed transfer.
+/// The driver can process 255 bytes of buffers or buffer list window.
+//------------------------------------------------------------------------------
+typedef struct _USBDTransferBuffer {
+ /// Pointer to frame buffer
+ unsigned char * pBuffer;
+ /// Size of the frame (up to 64K-1)
+ unsigned short size;
+ /// Bytes transferred
+ unsigned short transferred;
+ /// Bytes in FIFO
+ unsigned short buffered;
+ /// Bytes remaining
+ unsigned short remaining;
+} USBDTransferBuffer;
+
+#ifdef __ICCARM__ // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Struct used for USBD DMA Link List Transfer Descriptor, must be 16-bytes
+/// aligned.
+/// (For USB, DMA transfer is linked to EPs and FIFO address is EP defined)
+//------------------------------------------------------------------------------
+typedef struct _USBDDmaDescriptor {
+ /// Pointer to Next Descriptor
+ void* pNxtDesc;
+ /// Pointer to data buffer address
+ void* pDataAddr;
+ /// DMA Control setting register value
+ unsigned int ctrlSettings:8, /// Control settings
+ reserved:8, /// Not used
+ bufferLength:16; /// Length of buffer
+ /// Loaded to DMA register, OK to modify
+ unsigned int used;
+} __attribute__((aligned(16))) USBDDmaDescriptor;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// Callback used by transfer functions (USBD_Read & USBD_Write) to notify
+/// that a transaction is complete.
+//------------------------------------------------------------------------------
+typedef void (*TransferCallback)(void *pArg,
+ unsigned char status,
+ unsigned int transferred,
+ unsigned int remaining);
+
+//------------------------------------------------------------------------------
+/// Callback used by MBL transfer functions (USBD_Read & USBD_Write) to notify
+/// that a transaction is complete.
+/// \param pArg Pointer to callback arguments.
+/// \param status USBD status.
+/// \param nbFreed Number of buffers that is freed since last callback.
+//------------------------------------------------------------------------------
+typedef void (*MblTransferCallback)(void *pArg,
+ unsigned char status,
+ unsigned int nbFreed);
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBD_IrqHandler(void);
+
+extern void USBD_Init(void);
+
+extern void USBD_ConfigureSpeed(unsigned char forceFS);
+
+extern void USBD_Connect(void);
+
+extern void USBD_Disconnect(void);
+
+extern char USBD_Write(
+ unsigned char bEndpoint,
+ const void *pData,
+ unsigned int size,
+ TransferCallback callback,
+ void *pArg);
+
+extern char USBD_MblWrite(
+ unsigned char bEndpoint,
+ void * pMbl,
+ unsigned short wListSize,
+ unsigned char bCircList,
+ unsigned short wStartNdx,
+ MblTransferCallback fCallback,
+ void * pArgument);
+
+extern char USBD_MblReuse(
+ unsigned char bEndpoint,
+ unsigned char * pNewBuffer,
+ unsigned short wNewSize);
+
+extern char USBD_Read(
+ unsigned char bEndpoint,
+ void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArg);
+
+extern unsigned char USBD_Stall(unsigned char bEndpoint);
+
+extern void USBD_Halt(unsigned char bEndpoint);
+
+extern void USBD_Unhalt(unsigned char bEndpoint);
+
+extern void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor);
+
+extern unsigned char USBD_IsHalted(unsigned char bEndpoint);
+
+extern void USBD_RemoteWakeUp(void);
+
+extern void USBD_SetAddress(unsigned char address);
+
+extern void USBD_SetConfiguration(unsigned char cfgnum);
+
+extern unsigned char USBD_GetState(void);
+
+extern unsigned char USBD_IsHighSpeed(void);
+
+extern void USBD_Test(unsigned char bIndex);
+
+#endif //#ifndef USBD_H
+
diff --git a/usb/device/core/USBDCallbacks.h b/usb/device/core/USBDCallbacks.h new file mode 100644 index 0000000..d4d5c7e --- /dev/null +++ b/usb/device/core/USBDCallbacks.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions of callbacks used by the USBD API to notify the user
+ application of incoming events. These functions are declared as 'weak',
+ so they can be re-implemented elsewhere in the application in a
+ transparent way.
+*/
+
+#ifndef USBDCALLBACKS_H
+#define USBDCALLBACKS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBDCallbacks_Initialized(void);
+
+extern void USBDCallbacks_Reset(void);
+
+extern void USBDCallbacks_Suspended(void);
+
+extern void USBDCallbacks_Resumed(void);
+
+extern void USBDCallbacks_RequestReceived(const USBGenericRequest *request);
+
+#endif //#ifndef USBDCALLBACKS_H
+
diff --git a/usb/device/core/USBDCallbacks_Initialized.c b/usb/device/core/USBDCallbacks_Initialized.c new file mode 100644 index 0000000..0ac4ffe --- /dev/null +++ b/usb/device/core/USBDCallbacks_Initialized.c @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDCallbacks.h"
+#include "USBD.h"
+#include <board.h>
+#include <irq/irq.h>
+
+//------------------------------------------------------------------------------
+// Exported function
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Invoked after the USB driver has been initialized. By default, configures
+/// the UDP/UDPHS interrupt.
+//------------------------------------------------------------------------------
+void USBDCallbacks_Initialized(void)
+{
+#if defined(CHIP_USB_UDP)
+ // Configure and enable the UDP interrupt
+ IRQ_ConfigureIT(AT91C_ID_UDP, 0, USBD_IrqHandler);
+ IRQ_EnableIT(AT91C_ID_UDP);
+
+#elif defined(CHIP_USB_UDPHS)
+ // Configure and enable the UDPHS interrupt
+ IRQ_ConfigureIT(AT91C_ID_UDPHS, 0, USBD_IrqHandler);
+ IRQ_EnableIT(AT91C_ID_UDPHS);
+
+#elif defined(CHIP_USB_OTGHS)
+ IRQ_ConfigureIT(AT91C_ID_OTGHS, 1, (void*) 0);
+ IRQ_EnableIT(AT91C_ID_OTGHS);
+
+#else
+ #error Unsupported controller.
+#endif
+}
+
diff --git a/usb/device/core/USBDCallbacks_RequestReceived.c b/usb/device/core/USBDCallbacks_RequestReceived.c new file mode 100644 index 0000000..29468ff --- /dev/null +++ b/usb/device/core/USBDCallbacks_RequestReceived.c @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDCallbacks.h"
+
+//------------------------------------------------------------------------------
+// Exported function
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// USBDCallbacks_RequestReceived - Invoked when a new SETUP request is
+/// received. Does nothing by default.
+/// \param pRequest Pointer to the request to handle.
+//------------------------------------------------------------------------------
+void USBDCallbacks_RequestReceived(const USBGenericRequest *pRequest)
+{
+ // Does nothing
+}
+
diff --git a/usb/device/core/USBDCallbacks_Reset.c b/usb/device/core/USBDCallbacks_Reset.c new file mode 100644 index 0000000..64d9aaa --- /dev/null +++ b/usb/device/core/USBDCallbacks_Reset.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDCallbacks.h"
+
+//------------------------------------------------------------------------------
+// Exported function
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Invoked when the USB driver is reset. Does nothing by default.
+//------------------------------------------------------------------------------
+void USBDCallbacks_Reset(void)
+{
+ // Does nothing
+}
+
diff --git a/usb/device/core/USBDCallbacks_Resumed.c b/usb/device/core/USBDCallbacks_Resumed.c new file mode 100644 index 0000000..3d58646 --- /dev/null +++ b/usb/device/core/USBDCallbacks_Resumed.c @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDCallbacks.h"
+#include "USBD.h"
+#include <utility/led.h>
+
+//------------------------------------------------------------------------------
+// Exported function
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// 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);
+}
+
diff --git a/usb/device/core/USBDCallbacks_Suspended.c b/usb/device/core/USBDCallbacks_Suspended.c new file mode 100644 index 0000000..dbc10b9 --- /dev/null +++ b/usb/device/core/USBDCallbacks_Suspended.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDCallbacks.h"
+#include "USBD.h"
+#include <utility/led.h>
+
+//------------------------------------------------------------------------------
+// Exported function
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// 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);
+}
+
diff --git a/usb/device/core/USBDDriver.c b/usb/device/core/USBDDriver.c new file mode 100644 index 0000000..6a7c000 --- /dev/null +++ b/usb/device/core/USBDDriver.c @@ -0,0 +1,753 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDDriver.h"
+#include "USBDDriverCallbacks.h"
+#include "USBD.h"
+#include <board.h>
+#include <utility/trace.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBDeviceQualifierDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include <usb/common/core/USBSetAddressRequest.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
+#include <usb/common/core/USBSetConfigurationRequest.h>
+#include <usb/common/core/USBInterfaceRequest.h>
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// Local functions
+//------------------------------------------------------------------------------
+#if defined(CHIP_USB_OTGHS)
+static unsigned char otg_features_supported = 0;
+#endif
+
+//------------------------------------------------------------------------------
+/// Send a NULL packet
+//------------------------------------------------------------------------------
+static void TerminateCtrlInWithNull(void *pArg,
+ unsigned char status,
+ unsigned int transferred,
+ unsigned int remaining)
+{
+ USBD_Write(0, // Endpoint #0
+ 0, // No data buffer
+ 0, // No data buffer
+ (TransferCallback) 0,
+ (void *) 0);
+}
+
+//------------------------------------------------------------------------------
+/// Configures the device by setting it into the Configured state and
+/// initializing all endpoints.
+/// \param pDriver Pointer to a USBDDriver instance.
+/// \param cfgnum Configuration number to set.
+//------------------------------------------------------------------------------
+static void SetConfiguration(USBDDriver *pDriver, unsigned char cfgnum)
+{
+ USBEndpointDescriptor *pEndpoints[CHIP_USB_NUMENDPOINTS+1];
+ const USBConfigurationDescriptor *pConfiguration;
+
+ // Use different descriptor depending on device speed
+ if (USBD_IsHighSpeed()) {
+
+ pConfiguration = pDriver->pDescriptors->pHsConfiguration;
+ }
+ else {
+
+ pConfiguration = pDriver->pDescriptors->pFsConfiguration;
+ }
+
+ // Set & save the desired configuration
+ USBD_SetConfiguration(cfgnum);
+ pDriver->cfgnum = cfgnum;
+
+ // If the configuration is not 0, configure endpoints
+ if (cfgnum != 0) {
+
+ // Parse configuration to get endpoint descriptors
+ USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0);
+
+ // Configure endpoints
+ int i = 0;
+ while (pEndpoints[i] != 0) {
+
+ USBD_ConfigureEndpoint(pEndpoints[i]);
+ i++;
+ }
+ }
+ // Should be done before send the ZLP
+ USBDDriverCallbacks_ConfigurationChanged(cfgnum);
+
+ // Acknowledge the request
+ USBD_Write(0, // Endpoint #0
+ 0, // No data buffer
+ 0, // No data buffer
+ (TransferCallback) 0,
+ (void *) 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current configuration number to the host.
+/// \param pDriver Pointer to a USBDDriver instance.
+//------------------------------------------------------------------------------
+static void GetConfiguration(const USBDDriver *pDriver)
+{
+ USBD_Write(0, &(pDriver->cfgnum), 1, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current status of the device to the host.
+/// \param pDriver Pointer to a USBDDriver instance.
+//------------------------------------------------------------------------------
+static void GetDeviceStatus(const USBDDriver *pDriver)
+{
+ static unsigned short data;
+ const USBConfigurationDescriptor *pConfiguration;
+
+ data = 0;
+ // Use different configuration depending on device speed
+ if (USBD_IsHighSpeed()) {
+
+ pConfiguration = pDriver->pDescriptors->pHsConfiguration;
+ }
+ else {
+
+ pConfiguration = pDriver->pDescriptors->pFsConfiguration;
+ }
+
+ // Check current configuration for power mode (if device is configured)
+ if (pDriver->cfgnum != 0) {
+
+ if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration)) {
+
+ data |= 1;
+ }
+ }
+
+ // Check if remote wake-up is enabled
+ if (pDriver->isRemoteWakeUpEnabled) {
+
+ data |= 2;
+ }
+
+ // Send the device status
+ USBD_Write(0, &data, 2, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current status of an endpoints to the USB host.
+/// \param bEndpoint Endpoint number.
+//------------------------------------------------------------------------------
+static void GetEndpointStatus(unsigned char bEndpoint)
+{
+ static unsigned short data;
+
+ data = 0;
+ // Check if the endpoint exists
+ if (bEndpoint > CHIP_USB_NUMENDPOINTS) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ // Check if the endpoint if currently halted
+ if (USBD_IsHalted(bEndpoint)) {
+
+ data = 1;
+ }
+
+ // Send the endpoint status
+ USBD_Write(0, &data, 2, 0, 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sends the requested USB descriptor to the host if available, or STALLs the
+/// request.
+/// \param pDriver Pointer to a USBDDriver instance.
+/// \param type Type of the requested descriptor
+/// \param index Index of the requested descriptor.
+/// \param length Maximum number of bytes to return.
+//------------------------------------------------------------------------------
+static void GetDescriptor(
+ const USBDDriver *pDriver,
+ unsigned char type,
+ unsigned char indexRDesc,
+ unsigned int length)
+{
+ const USBDeviceDescriptor *pDevice;
+ const USBConfigurationDescriptor *pConfiguration;
+ const USBDeviceQualifierDescriptor *pQualifier;
+ const USBConfigurationDescriptor *pOtherSpeed;
+ const USBGenericDescriptor **pStrings =
+ (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
+ const USBGenericDescriptor *pString;
+ unsigned char numStrings = pDriver->pDescriptors->numStrings;
+ unsigned char terminateWithNull = 0;
+
+ // Use different set of descriptors depending on device speed
+ if (USBD_IsHighSpeed()) {
+
+ TRACE_DEBUG("HS ");
+ pDevice = pDriver->pDescriptors->pHsDevice;
+ pConfiguration = pDriver->pDescriptors->pHsConfiguration;
+ pQualifier = pDriver->pDescriptors->pHsQualifier;
+ pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
+ }
+ else {
+
+ TRACE_DEBUG("FS ");
+ pDevice = pDriver->pDescriptors->pFsDevice;
+ pConfiguration = pDriver->pDescriptors->pFsConfiguration;
+ pQualifier = pDriver->pDescriptors->pFsQualifier;
+ pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
+ }
+
+ // Check the descriptor type
+ switch (type) {
+
+ case USBGenericDescriptor_DEVICE:
+ TRACE_INFO_WP("Dev ");
+
+ // Adjust length and send descriptor
+ if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {
+
+ length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
+ }
+ USBD_Write(0, pDevice, length, 0, 0);
+ break;
+
+ case USBGenericDescriptor_CONFIGURATION:
+ TRACE_INFO_WP("Cfg ");
+
+ // Adjust length and send descriptor
+ if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {
+
+ length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
+ terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
+ }
+ USBD_Write(0,
+ pConfiguration,
+ length,
+ terminateWithNull ? TerminateCtrlInWithNull : 0,
+ 0);
+ break;
+
+ case USBGenericDescriptor_DEVICEQUALIFIER:
+ TRACE_INFO_WP("Qua ");
+
+ // Check if descriptor exists
+ if (!pQualifier) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ // Adjust length and send descriptor
+ if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {
+
+ length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
+ }
+ USBD_Write(0, pQualifier, length, 0, 0);
+ }
+ break;
+
+ case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
+ TRACE_INFO_WP("OSC ");
+
+ // Check if descriptor exists
+ if (!pOtherSpeed) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ // Adjust length and send descriptor
+ if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {
+
+ length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
+ terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
+ }
+ USBD_Write(0,
+ pOtherSpeed,
+ length,
+ terminateWithNull ? TerminateCtrlInWithNull : 0,
+ 0);
+ }
+ break;
+
+ case USBGenericDescriptor_STRING:
+ TRACE_INFO_WP("Str%d ", indexRDesc);
+
+ // Check if descriptor exists
+ if (indexRDesc >= numStrings) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ pString = pStrings[indexRDesc];
+
+ // Adjust length and send descriptor
+ if (length > USBGenericDescriptor_GetLength(pString)) {
+
+ length = USBGenericDescriptor_GetLength(pString);
+ terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
+ }
+ USBD_Write(0,
+ pString,
+ length,
+ terminateWithNull ? TerminateCtrlInWithNull : 0,
+ 0);
+ }
+ break;
+
+ default:
+ TRACE_WARNING(
+ "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
+ type);
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sets the active setting of the given interface if the configuration supports
+/// it; otherwise, the control pipe is STALLed. If the setting of an interface
+/// changes.
+/// \parma pDriver Pointer to a USBDDriver instance.
+/// \parma infnum Interface number.
+/// \parma setting New active setting for the interface.
+//------------------------------------------------------------------------------
+static void SetInterface(
+ USBDDriver *pDriver,
+ unsigned char infnum,
+ unsigned char setting)
+{
+ // Make sure alternate settings are supported
+ if (!pDriver->pInterfaces) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ // Change the current setting of the interface and trigger the callback
+ // if necessary
+ if (pDriver->pInterfaces[infnum] != setting) {
+
+ pDriver->pInterfaces[infnum] = setting;
+ USBDDriverCallbacks_InterfaceSettingChanged(infnum, setting);
+ }
+
+ // Acknowledge the request
+ USBD_Write(0, 0, 0, 0, 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sends the currently active setting of the given interface to the USB
+/// host. If alternate settings are not supported, this function STALLs the
+/// control pipe.
+/// \param pDriver Pointer to a USBDDriver instance.
+/// \param infnum Interface number.
+//------------------------------------------------------------------------------
+static void GetInterface(
+ const USBDDriver *pDriver,
+ unsigned char infnum)
+{
+ // Make sure alternate settings are supported, or STALL the control pipe
+ if (!pDriver->pInterfaces) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ // Sends the current interface setting to the host
+ USBD_Write(0, &(pDriver->pInterfaces[infnum]), 1, 0, 0);
+ }
+}
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+//------------------------------------------------------------------------------
+// Performs the selected test on the USB device (high-speed only).
+// \param test Test selector value.
+//------------------------------------------------------------------------------
+static void USBDDriver_Test(unsigned char test)
+{
+ TRACE_DEBUG("UDPHS_Test\n\r");
+
+ // the lower byte of wIndex must be zero
+ // the most significant byte of wIndex is used to specify the specific test mode
+ switch (test) {
+ case USBFeatureRequest_TESTPACKET:
+ //Test mode Test_Packet:
+ //Upon command, a port must repetitively transmit the following test packet until
+ //the exit action is taken. This enables the testing of rise and fall times, eye
+ //patterns, jitter, and any other dynamic waveform specifications.
+ //The test packet is made up by concatenating the following strings.
+ //(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one
+ //transmitted. “S” indicates that a bit stuff occurs, which inserts an “extra” NRZI data bit.
+ //“* N” is used to indicate N occurrences of a string of bits or symbols.)
+ //A port in Test_Packet mode must send this packet repetitively. The inter-packet timing
+ //must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and
+ //no greater than 125 us.
+ // Send ZLP
+ USBD_Test(USBFeatureRequest_TESTSENDZLP);
+ // Tst PACKET
+ USBD_Test(USBFeatureRequest_TESTPACKET);
+ while (1);
+ //break; not reached
+
+ case USBFeatureRequest_TESTJ:
+ //Test mode Test_J:
+ //Upon command, a port’s transceiver must enter the high-speed J state and remain in that
+ //state until the exit action is taken. This enables the testing of the high output drive
+ //level on the D+ line.
+ // Send ZLP
+ USBD_Test(USBFeatureRequest_TESTSENDZLP);
+ // Tst J
+ USBD_Test(USBFeatureRequest_TESTJ);
+ while (1);
+ //break; not reached
+
+ case USBFeatureRequest_TESTK:
+ //Test mode Test_K:
+ //Upon command, a port’s transceiver must enter the high-speed K state and remain in
+ //that state until the exit action is taken. This enables the testing of the high output drive
+ //level on the D- line.
+ // Send a ZLP
+ USBD_Test(USBFeatureRequest_TESTSENDZLP);
+ USBD_Test(USBFeatureRequest_TESTK);
+ while (1);
+ //break; not reached
+
+ case USBFeatureRequest_TESTSE0NAK:
+ //Test mode Test_SE0_NAK:
+ //Upon command, a port’s transceiver must enter the high-speed receive mode
+ //and remain in that mode until the exit action is taken. This enables the testing
+ //of output impedance, low level output voltage, and loading characteristics.
+ //In addition, while in this mode, upstream facing ports (and only upstream facing ports)
+ //must respond to any IN token packet with a NAK handshake (only if the packet CRC is
+ //determined to be correct) within the normal allowed device response time. This enables testing of
+ //the device squelch level circuitry and, additionally, provides a general purpose stimulus/response
+ //test for basic functional testing.
+ // Send a ZLP
+ USBD_Test(USBFeatureRequest_TESTSENDZLP);
+ // Test SE0_NAK
+ USBD_Test(USBFeatureRequest_TESTSE0NAK);
+ while (1);
+ //break; not reached
+
+ default:
+ USBD_Stall(0);
+ break;
+
+ }
+ // The exit action is to power cycle the device.
+ // The device must be disconnected from the host
+}
+#endif
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes a USBDDriver instance with a list of descriptors. If
+/// interfaces can have multiple alternate settings, an array to store the
+/// current setting for each interface must be provided.
+/// \param pDriver Pointer to a USBDDriver instance.
+/// \param pDescriptors Pointer to a USBDDriverDescriptors instance.
+/// \param pInterfaces Pointer to an array for storing the current alternate
+/// setting of each interface (optional).
+//------------------------------------------------------------------------------
+void USBDDriver_Initialize(
+ USBDDriver *pDriver,
+ const USBDDriverDescriptors *pDescriptors,
+ unsigned char *pInterfaces)
+{
+
+ pDriver->cfgnum = 0;
+#if (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_SELFPOWERED_RWAKEUP) \
+ || (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_BUSPOWERED_RWAKEUP)
+ pDriver->isRemoteWakeUpEnabled = 1;
+#else
+ pDriver->isRemoteWakeUpEnabled = 0;
+#endif
+
+ pDriver->pDescriptors = pDescriptors;
+ pDriver->pInterfaces = pInterfaces;
+
+ // Initialize interfaces array if not null
+ if (pInterfaces != 0) {
+
+ memset(pInterfaces, sizeof(pInterfaces), 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Handles the given request if it is standard, otherwise STALLs it.
+/// \param pDriver Pointer to a USBDDriver instance.
+/// \param pRequest Pointer to a USBGenericRequest instance.
+//------------------------------------------------------------------------------
+void USBDDriver_RequestHandler(
+ USBDDriver *pDriver,
+ const USBGenericRequest *pRequest)
+{
+ unsigned char cfgnum;
+ unsigned char infnum;
+ unsigned char eptnum;
+ unsigned char setting;
+ unsigned char type;
+ unsigned char indexDesc;
+ unsigned int length;
+ unsigned int address;
+
+ TRACE_INFO_WP("Std ");
+
+ // Check request code
+ switch (USBGenericRequest_GetRequest(pRequest)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ TRACE_INFO_WP("gDesc ");
+
+ // Send the requested descriptor
+ type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
+ indexDesc = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
+ length = USBGenericRequest_GetLength(pRequest);
+ GetDescriptor(pDriver, type, indexDesc, length);
+ break;
+
+ case USBGenericRequest_SETADDRESS:
+ TRACE_INFO_WP("sAddr ");
+
+ // Sends a zero-length packet and then set the device address
+ address = USBSetAddressRequest_GetAddress(pRequest);
+ USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
+ break;
+
+ case USBGenericRequest_SETCONFIGURATION:
+ TRACE_INFO_WP("sCfg ");
+
+ // Set the requested configuration
+ cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
+ SetConfiguration(pDriver, cfgnum);
+ break;
+
+ case USBGenericRequest_GETCONFIGURATION:
+ TRACE_INFO_WP("gCfg ");
+
+ // Send the current configuration number
+ GetConfiguration(pDriver);
+ break;
+
+ case USBGenericRequest_GETSTATUS:
+ TRACE_INFO_WP("gSta ");
+
+ // Check who is the recipient
+ switch (USBGenericRequest_GetRecipient(pRequest)) {
+
+ case USBGenericRequest_DEVICE:
+ TRACE_INFO_WP("Dev ");
+
+ // Send the device status
+ GetDeviceStatus(pDriver);
+ break;
+
+ case USBGenericRequest_ENDPOINT:
+ TRACE_INFO_WP("Ept ");
+
+ // Send the endpoint status
+ eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
+ GetEndpointStatus(eptnum);
+ break;
+
+ default:
+ TRACE_WARNING(
+ "USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
+ USBGenericRequest_GetRecipient(pRequest));
+ USBD_Stall(0);
+ }
+ break;
+
+ case USBGenericRequest_CLEARFEATURE:
+ TRACE_INFO_WP("cFeat ");
+
+ // Check which is the requested feature
+ switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
+
+ case USBFeatureRequest_ENDPOINTHALT:
+ TRACE_INFO_WP("Hlt ");
+
+ // Unhalt endpoint and send a zero-length packet
+ USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ case USBFeatureRequest_DEVICEREMOTEWAKEUP:
+ TRACE_INFO_WP("RmWU ");
+
+ // Disable remote wake-up and send a zero-length packet
+ pDriver->isRemoteWakeUpEnabled = 0;
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ default:
+ TRACE_WARNING(
+ "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
+ USBFeatureRequest_GetFeatureSelector(pRequest));
+ USBD_Stall(0);
+ }
+ break;
+
+ case USBGenericRequest_SETFEATURE:
+ TRACE_INFO_WP("sFeat ");
+
+ // Check which is the selected feature
+ switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
+
+ case USBFeatureRequest_DEVICEREMOTEWAKEUP:
+ TRACE_INFO_WP("RmWU ");
+
+ // Enable remote wake-up and send a ZLP
+ pDriver->isRemoteWakeUpEnabled = 1;
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ case USBFeatureRequest_ENDPOINTHALT:
+ TRACE_INFO_WP("Halt ");
+ // Halt endpoint
+ USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+
+ case USBFeatureRequest_TESTMODE:
+ // 7.1.20 Test Mode Support, 9.4.9 SetFeature
+ if ((USBGenericRequest_GetRecipient(pRequest) == USBGenericRequest_DEVICE)
+ && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {
+
+ // Handle test request
+ USBDDriver_Test(USBFeatureRequest_GetTestSelector(pRequest));
+ }
+ else {
+
+ USBD_Stall(0);
+ }
+ break;
+#endif
+#if defined(CHIP_USB_OTGHS)
+ case USBFeatureRequest_OTG_B_HNP_ENABLE:
+ TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
+ otg_features_supported |= 1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+ case USBFeatureRequest_OTG_A_HNP_SUPPORT:
+ TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
+ otg_features_supported |= 1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+ case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
+ TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
+ otg_features_supported |= 1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+#endif
+ default:
+ TRACE_WARNING(
+ "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
+ USBFeatureRequest_GetFeatureSelector(pRequest));
+ USBD_Stall(0);
+ }
+ break;
+
+ case USBGenericRequest_SETINTERFACE:
+ TRACE_INFO_WP("sInterface ");
+
+ infnum = USBInterfaceRequest_GetInterface(pRequest);
+ setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
+ SetInterface(pDriver, infnum, setting);
+ break;
+
+ case USBGenericRequest_GETINTERFACE:
+ TRACE_INFO_WP("gInterface ");
+
+ infnum = USBInterfaceRequest_GetInterface(pRequest);
+ GetInterface(pDriver, infnum);
+ break;
+
+ default:
+ TRACE_WARNING(
+ "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
+ USBGenericRequest_GetRequest(pRequest));
+ USBD_Stall(0);
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Test if RemoteWakeUP feature is enabled
+/// \param pDriver Pointer to an USBDDriver instance.
+/// \return 1 if remote wake up has been enabled by the host; otherwise, returns
+/// 0
+//------------------------------------------------------------------------------
+unsigned char USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver)
+{
+ return pDriver->isRemoteWakeUpEnabled;
+}
+
+#if defined(CHIP_USB_OTGHS)
+//------------------------------------------------------------------------------
+/// Return OTG features supported
+/// \return the OTG features
+//------------------------------------------------------------------------------
+unsigned char USBDDriver_returnOTGFeatures(void)
+{
+ return otg_features_supported;
+}
+
+//------------------------------------------------------------------------------
+/// Clear OTG features supported
+/// \return none
+//------------------------------------------------------------------------------
+void USBDDriver_clearOTGFeatures(void)
+{
+ otg_features_supported = 0;
+}
+#endif
+
diff --git a/usb/device/core/USBDDriver.h b/usb/device/core/USBDDriver.h new file mode 100644 index 0000000..40ca6d7 --- /dev/null +++ b/usb/device/core/USBDDriver.h @@ -0,0 +1,101 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ USB Device Driver class definition.
+
+ !!!Usage
+
+ -# Instanciate a USBDDriver object and initialize it using
+ USBDDriver_Initialize.
+ -# When a USB SETUP request is received, forward it to the standard
+ driver using USBDDriver_RequestHandler.
+ -# Check the Remote Wakeup setting via USBDDriver_IsRemoteWakeUpEnabled.
+*/
+
+#ifndef USBDDRIVER_H
+#define USBDDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBDDriverDescriptors.h"
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// USB device driver structure, holding a list of descriptors identifying
+/// the device as well as the driver current state.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// List of descriptors used by the device.
+ const USBDDriverDescriptors *pDescriptors;
+ /// Current setting for each interface.
+ unsigned char *pInterfaces;
+ /// Current configuration number (0 -> device is not configured).
+ unsigned char cfgnum;
+ /// Indicates if remote wake up has been enabled by the host.
+ unsigned char isRemoteWakeUpEnabled;
+#if defined(CHIP_USB_OTGHS)
+ /// Features supported by OTG
+ unsigned char otg_features_supported;
+#endif
+} USBDDriver;
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBDDriver_Initialize(
+ USBDDriver *pDriver,
+ const USBDDriverDescriptors *pDescriptors,
+ unsigned char *pInterfaces);
+
+extern void USBDDriver_RequestHandler(
+ USBDDriver *pDriver,
+ const USBGenericRequest *pRequest);
+
+extern unsigned char USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver);
+
+#if defined(CHIP_USB_OTGHS)
+extern unsigned char USBDDriver_returnOTGFeatures(void);
+extern void USBDDriver_clearOTGFeatures(void);
+#endif
+
+#endif //#ifndef USBDDRIVER_H
+
diff --git a/usb/device/core/USBDDriverCallbacks.h b/usb/device/core/USBDDriverCallbacks.h new file mode 100644 index 0000000..053e8ac --- /dev/null +++ b/usb/device/core/USBDDriverCallbacks.h @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of several callbacks which are triggered by the USB software
+ driver after receiving specific requests.
+
+ !!!Usage
+
+ -# Re-implement the USBDDriverCallbacks_ConfigurationChanged
+ callback to know when the hosts changes the active configuration of
+ the device.
+ -# Re-implement the USBDDriverCallbacks_InterfaceSettingChanged
+ callback to get notified whenever the active setting of an interface
+ is changed by the host.
+*/
+
+#ifndef USBDDRIVERCALLBACKS_H
+#define USBDDRIVERCALLBACKS_H
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum);
+
+extern void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
+ unsigned char setting);
+
+#endif //#ifndef USBDDRIVERCALLBACKS_H
+
diff --git a/usb/device/core/USBDDriverCb_CfgChanged.c b/usb/device/core/USBDDriverCb_CfgChanged.c new file mode 100644 index 0000000..08e2b2f --- /dev/null +++ b/usb/device/core/USBDDriverCb_CfgChanged.c @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDDriverCallbacks.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+// Global functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Indicates that the current configuration of the device has changed.
+/// \param cfgnum New device configuration index.
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ TRACE_INFO_WP("ConfigurationChanged ");
+}
+
diff --git a/usb/device/core/USBDDriverCb_IfSettingChanged.c b/usb/device/core/USBDDriverCb_IfSettingChanged.c new file mode 100644 index 0000000..c9049e6 --- /dev/null +++ b/usb/device/core/USBDDriverCb_IfSettingChanged.c @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBDDriverCallbacks.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+// Global functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Notifies of a change in the currently active setting of an interface.
+/// \param interface Number of the interface whose setting has changed.
+/// \param setting New interface setting.
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_InterfaceSettingChanged(
+ unsigned char interface,
+ unsigned char setting)
+{
+ TRACE_INFO_WP("InterfaceSettingChanged ");
+}
+
diff --git a/usb/device/core/USBDDriverDescriptors.h b/usb/device/core/USBDDriverDescriptors.h new file mode 100644 index 0000000..f1064e4 --- /dev/null +++ b/usb/device/core/USBDDriverDescriptors.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of a class for declaring USB descriptors required by the
+ device driver.
+*/
+
+#ifndef USBDDRIVERDESCRIPTORS_H
+#define USBDDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBDeviceQualifierDescriptor.h>
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// List of all descriptors used by a USB device driver. Each descriptor can
+/// be provided in two versions: full-speed and high-speed. Devices which are
+/// not high-speed capable do not need to provided high-speed descriptors and
+/// the full-speed qualifier & other speed descriptors.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Pointer to the full-speed device descriptor.
+ const USBDeviceDescriptor *pFsDevice;
+ /// Pointer to the full-speed configuration descriptor.
+ const USBConfigurationDescriptor *pFsConfiguration;
+ /// Pointer to the full-speed qualifier descriptor.
+ const USBDeviceQualifierDescriptor *pFsQualifier;
+ /// Pointer to the full-speed other speed configuration descriptor.
+ const USBConfigurationDescriptor *pFsOtherSpeed;
+ /// Pointer to the high-speed device descriptor.
+ const USBDeviceDescriptor *pHsDevice;
+ /// Pointer to the high-speed configuration descriptor.
+ const USBConfigurationDescriptor *pHsConfiguration;
+ /// Pointer to the high-speed qualifier descriptor.
+ const USBDeviceQualifierDescriptor *pHsQualifier;
+ /// Pointer to the high-speed other speed configuration descriptor.
+ const USBConfigurationDescriptor *pHsOtherSpeed;
+ /// Pointer to the list of string descriptors.
+ const unsigned char **pStrings;
+ /// Number of string descriptors in list.
+ unsigned char numStrings;
+
+} USBDDriverDescriptors;
+
+#endif //#ifndef USBDDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/core/USBD_OTGHS.c b/usb/device/core/USBD_OTGHS.c new file mode 100644 index 0000000..1795aaf --- /dev/null +++ b/usb/device/core/USBD_OTGHS.c @@ -0,0 +1,1697 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBD.h"
+#include "USBDCallbacks.h"
+#include "USBDDriver.h"
+#include <board.h>
+#include <pio/pio.h>
+#include <utility/trace.h>
+#include <utility/led.h>
+#include <usb/common/core/USBConfigurationOTG.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include <pmc/pmc.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Maximum number of endpoints interrupts.
+#define NUM_IT_MAX \
+ (AT91C_BASE_OTGHS->OTGHS_IPFEATURES & AT91C_OTGHS_EPT_NBR_MAX)
+/// Maximum number of endpoint DMA interrupts
+#define NUM_IT_MAX_DMA \
+ ((AT91C_BASE_OTGHS->OTGHS_IPFEATURES & AT91C_OTGHS_DMA_CHANNEL_NBR)>>4)
+/// Bits that should be shifted to access DMA control bits.
+#define SHIFT_DMA 24
+/// Bits that should be shifted to access interrupt bits.
+#define SHIFT_INTERUPT 12
+
+/// Max size of the FMA FIFO
+#define DMA_MAX_FIFO_SIZE 32768
+
+#define EPT_VIRTUAL_SIZE 8192
+
+//------------------------------------------------------------------------------
+/// \page "Endpoint states"
+/// This page lists the endpoint states.
+/// !States
+// - UDP_ENDPOINT_DISABLED
+// - UDP_ENDPOINT_HALTED
+// - UDP_ENDPOINT_IDLE
+// - UDP_ENDPOINT_SENDING
+// - UDP_ENDPOINT_RECEIVING
+
+/// Endpoint states: Endpoint is disabled
+#define UDP_ENDPOINT_DISABLED 0
+/// Endpoint states: Endpoint is halted (i.e. STALLs every request)
+#define UDP_ENDPOINT_HALTED 1
+/// Endpoint states: Endpoint is idle (i.e. ready for transmission)
+#define UDP_ENDPOINT_IDLE 2
+/// Endpoint states: Endpoint is sending data
+#define UDP_ENDPOINT_SENDING 3
+/// Endpoint states: Endpoint is receiving data
+#define UDP_ENDPOINT_RECEIVING 4
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Structures
+//------------------------------------------------------------------------------
+
+/// Describes an ongoing transfer on a UDP endpoint.
+typedef struct
+{
+ /// Pointer to a data buffer used for emission/reception.
+ char *pData;
+ /// Number of bytes which have been written into the UDP internal FIFO
+ /// buffers.
+ volatile int buffered;
+ /// Number of bytes which have been sent/received.
+ volatile int transferred;
+ /// Number of bytes which have not been buffered/transferred yet.
+ volatile int remaining;
+ /// Optional callback to invoke when the transfer completes.
+ volatile TransferCallback fCallback;
+ /// Optional argument to the callback function.
+ void *pArgument;
+} Transfer;
+
+//------------------------------------------------------------------------------
+/// Describes the state of an endpoint of the UDP controller.
+//------------------------------------------------------------------------------
+typedef struct
+{
+ /// Current endpoint state.
+ volatile unsigned char state;
+ /// Current reception bank (0 or 1).
+ unsigned char bank;
+ /// Maximum packet size for the endpoint.
+ unsigned short size;
+ /// Describes an ongoing transfer (if current state is either
+ /// <UDP_ENDPOINT_SENDING> or <UDP_ENDPOINT_RECEIVING>)
+ Transfer transfer;
+ /// Special case for send a ZLP
+ unsigned char sendZLP;
+} Endpoint;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Holds the internal state for each endpoint of the UDP.
+static Endpoint endpoints[CHIP_USB_NUMENDPOINTS];
+/// Device current state.
+static unsigned char deviceState;
+/// Indicates the previous device state
+static unsigned char previousDeviceState;
+
+/// 7.1.20 Test Mode Support
+/// Test codes for the USB HS test mode.
+static const char test_packet_buffer[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9
+ 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8
+ 0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
+ 0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8
+ 0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK
+};
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Enable UDPHS clock
+//------------------------------------------------------------------------------
+static inline void OTGHS_EnableUsbClock( void )
+{
+
+}
+
+//------------------------------------------------------------------------------
+/// Disable UDPHS clock
+//------------------------------------------------------------------------------
+static inline void OTGHS_DisableUsbClock( void )
+{
+
+}
+
+//------------------------------------------------------------------------------
+/// Enables the transceiver of the USB controller
+//------------------------------------------------------------------------------
+static void OTGHS_EnableTransceiver(void)
+{
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_OTGPADE;
+}
+
+//------------------------------------------------------------------------------
+/// Disables the transceiver of the USB controller associated with the specified
+/// USB driver
+//------------------------------------------------------------------------------
+static void OTGHS_DisableTransceiver(void)
+{
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_OTGPADE;
+}
+
+//------------------------------------------------------------------------------
+/// Handles a completed transfer on the given endpoint, invoking the
+/// configured callback if any.
+/// \param bEndpoint Number of the endpoint for which the transfer has completed.
+/// \param bStatus Status code returned by the transfer operation
+//------------------------------------------------------------------------------
+static void OTGHS_EndOfTransfer( unsigned char bEndpoint, char bStatus )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = &(pEndpoint->transfer);
+
+ // Check that endpoint was sending or receiving data
+ if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING) ) {
+
+ TRACE_DEBUG_WP("Eo");
+ if(pEndpoint->state == UDP_ENDPOINT_SENDING) {
+ pEndpoint->sendZLP = 0;
+ }
+ // Endpoint returns in Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Invoke callback is present
+ if (pTransfer->fCallback != 0) {
+
+ ((TransferCallback) pTransfer->fCallback)
+ (pTransfer->pArgument,
+ bStatus,
+ pTransfer->transferred,
+ pTransfer->remaining + pTransfer->buffered);
+ }
+ else {
+ TRACE_DEBUG_WP("No callBack\n\r");
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from the current tranfer buffer to the endpoint
+/// FIFO
+/// \param bEndpoint Number of the endpoint which is sending data.
+//------------------------------------------------------------------------------
+static void OTGHS_WritePayload( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = &(pEndpoint->transfer);
+ char *pFifo;
+ signed int size;
+ unsigned int dCtr;
+
+ pFifo = (char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO + (EPT_VIRTUAL_SIZE * bEndpoint));
+
+ // Get the number of bytes to send
+ size = pEndpoint->size;
+ if (size > pTransfer->remaining) {
+
+ size = pTransfer->remaining;
+ }
+
+ // Update transfer descriptor information
+ pTransfer->buffered += size;
+ pTransfer->remaining -= size;
+
+ // Write packet in the FIFO buffer
+ dCtr = 0;
+ while (size > 0) {
+
+ pFifo[dCtr] = *(pTransfer->pData);
+ pTransfer->pData++;
+ size--;
+ dCtr++;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from an endpoint FIFO to the current transfer buffer
+/// \param bEndpoint Endpoint number.
+/// \param wPacketSize Size of received data packet
+//------------------------------------------------------------------------------
+static void OTGHS_ReadPayload( unsigned char bEndpoint, int wPacketSize )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = &(pEndpoint->transfer);
+ char *pFifo;
+ unsigned char dBytes=0;
+
+ pFifo = (char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO + (EPT_VIRTUAL_SIZE * bEndpoint));
+
+ // Check that the requested size is not bigger than the remaining transfer
+ if (wPacketSize > pTransfer->remaining) {
+
+ pTransfer->buffered += wPacketSize - pTransfer->remaining;
+ wPacketSize = pTransfer->remaining;
+ }
+
+ // Update transfer descriptor information
+ pTransfer->remaining -= wPacketSize;
+ pTransfer->transferred += wPacketSize;
+
+ // Retrieve packet
+ while (wPacketSize > 0) {
+
+ *(pTransfer->pData) = pFifo[dBytes];
+ pTransfer->pData++;
+ wPacketSize--;
+ dBytes++;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Received SETUP packet from endpoint 0 FIFO
+/// \param pRequest Generic USB SETUP request sent over Control endpoints
+//------------------------------------------------------------------------------
+static void OTGHS_ReadRequest( USBGenericRequest *pRequest )
+{
+ unsigned int *pData = (unsigned int *)pRequest;
+ unsigned int fifo;
+
+ fifo = (AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0[0]);
+ *pData = fifo;
+ fifo = (AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0[0]);
+ pData++;
+ *pData = fifo;
+ //TRACE_ERROR("SETUP: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n\r", pData[0],pData[1],pData[2],pData[3],pData[4],pData[5],pData[6],pData[7]);
+}
+
+//------------------------------------------------------------------------------
+/// Reset all endpoint transfer descriptors
+//------------------------------------------------------------------------------
+static void OTGHS_ResetEndpoints( void )
+{
+ Endpoint *pEndpoint;
+ Transfer *pTransfer;
+
+ unsigned char bEndpoint;
+
+ // Reset the transfer descriptor of every endpoint
+ for( bEndpoint = 0; bEndpoint < CHIP_USB_NUMENDPOINTS; bEndpoint++ ) {
+
+ pEndpoint = &(endpoints[bEndpoint]);
+ pTransfer = &(pEndpoint->transfer);
+
+ // Reset endpoint transfer descriptor
+ pTransfer->pData = 0;
+ pTransfer->transferred = -1;
+ pTransfer->buffered = -1;
+ pTransfer->remaining = -1;
+ pTransfer->fCallback = 0;
+ pTransfer->pArgument = 0;
+
+ // Reset endpoint state
+ pEndpoint->bank = 0;
+ pEndpoint->state = UDP_ENDPOINT_DISABLED;
+ // Reset ZLP
+ pEndpoint->sendZLP = 0;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Disable all endpoints (except control endpoint 0), aborting current
+/// transfers if necessary
+//------------------------------------------------------------------------------
+static void OTGHS_DisableEndpoints( void )
+{
+ unsigned char bEndpoint;
+
+ // Disable each endpoint, terminating any pending transfer
+
+
+ // Control endpoint 0 is not disabled
+ for( bEndpoint = 1; bEndpoint < CHIP_USB_NUMENDPOINTS; bEndpoint++ ) {
+
+ OTGHS_EndOfTransfer( bEndpoint, USBD_STATUS_ABORTED );
+ endpoints[bEndpoint].state = UDP_ENDPOINT_DISABLED;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Endpoint interrupt handler.
+/// Handle IN/OUT transfers, received SETUP packets and STALLing
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void OTGHS_EndpointHandler( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = &(pEndpoint->transfer);
+ unsigned int status = AT91C_BASE_OTGHS->OTGHS_DEVEPTISR[bEndpoint];
+ unsigned short wPacketSize;
+ USBGenericRequest request;
+
+ TRACE_DEBUG_WP("E%d ", bEndpoint);
+ TRACE_DEBUG_WP("st:0x%X ", status);
+
+ // Handle interrupts
+ // IN packet sent
+ if((AT91C_BASE_OTGHS->OTGHS_DEVEPTIMR[bEndpoint] & AT91C_OTGHS_TXINI)
+ && (status & AT91C_OTGHS_TXINI )) {
+
+ TRACE_DEBUG_WP("Wr ");
+
+ // Check that endpoint was in Sending state
+ if( pEndpoint->state == UDP_ENDPOINT_SENDING ) {
+
+ if (pTransfer->buffered > 0) {
+ pTransfer->transferred += pTransfer->buffered;
+ pTransfer->buffered = 0;
+ }
+
+ if( ((pTransfer->buffered)==0)
+ &&((pTransfer->transferred)==0)
+ &&((pTransfer->remaining)==0)
+ &&(pEndpoint->sendZLP == 0)) {
+ pEndpoint->sendZLP = 1;
+ }
+
+ // End of transfer ?
+ if( (pTransfer->remaining > 0)
+ ||(pEndpoint->sendZLP == 1)) {
+
+ pEndpoint->sendZLP = 2;
+ // Transfer remaining data
+ TRACE_DEBUG_WP(" %d ", pEndpoint->size);
+ // Send next packet
+ OTGHS_WritePayload(bEndpoint);
+
+ // Send Token IN
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_TXINI;
+ // For a non-control endpoint, the FIFOCON bit must be cleared
+ // to start the transfer
+ if ((AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])
+ != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+ // Send IN
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_FIFOCON;
+ }
+ }
+ else {
+
+ TRACE_DEBUG_WP("\n\r0pTransfer->buffered %d \n\r", pTransfer->buffered);
+ TRACE_DEBUG_WP("0pTransfer->transferred %d \n\r", pTransfer->transferred);
+ TRACE_DEBUG_WP("0pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+ TRACE_DEBUG_WP(" %d ", pTransfer->transferred);
+
+ // Disable interrupt if this is not a control endpoint
+ if ((AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])
+ != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+
+ AT91C_BASE_OTGHS->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
+
+ }
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_TXINI;
+ OTGHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ pEndpoint->sendZLP = 0;
+ }
+ }
+ else {
+ TRACE_DEBUG("Error Wr %d", pEndpoint->sendZLP);
+ }
+ }
+
+ // OUT packet received
+ if( AT91C_OTGHS_RXOUT == (status & AT91C_OTGHS_RXOUT) ) {
+
+ // Check that the endpoint is in Receiving state
+ if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) {
+
+ // Check if an ACK has been received on a Control endpoint
+ if( ((AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])
+ == AT91C_OTGHS_EPT_TYPE_CTL_EPT)
+ && (0 == (status & AT91C_OTGHS_BYCT)) ) {
+
+ // Control endpoint, 0 bytes received
+ // Acknowledge the data and finish the current transfer
+ TRACE_DEBUG_WP("Ack ");
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_RXOUT;
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_RXOUT;
+ //OTGHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ // Check if the data has been STALLed
+ else if( AT91C_OTGHS_STALL == (status & AT91C_OTGHS_STALL)) {
+
+ // Discard STALLed data
+ TRACE_DEBUG_WP("Discard ");
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_RXOUT;
+ }
+ else {
+ // NAK the data
+ TRACE_DEBUG_WP("Nak ");
+ AT91C_BASE_OTGHS->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
+ }
+ }
+ else {
+
+ // Endpoint is in Read state
+ // Retrieve data and store it into the current transfer buffer
+ wPacketSize = (unsigned short) ((status >> 20) & 0x7FF);
+
+ //TRACE_ERROR_WP("out:%d ", wPacketSize);
+ OTGHS_ReadPayload(bEndpoint, wPacketSize);
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_RXOUT;
+ if((AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])
+ != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_FIFOCON;
+ }
+
+ // Check if the transfer is finished
+ if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) {
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_RXOUT;
+
+ // Disable interrupt if this is not a control endpoint
+ if ((AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])
+ != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+
+ AT91C_BASE_OTGHS->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
+ }
+ //TRACE_ERROR_WP("Y ");
+ OTGHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ }
+ }
+
+ // STALL sent
+ if( AT91C_OTGHS_STALL == (status & AT91C_OTGHS_STALL) ) {
+
+ TRACE_WARNING( "Sta 0x%X [%d] ", status, bEndpoint);
+
+ // Acknowledge the stall flag
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_STALL;
+
+ // If the endpoint is not halted, clear the STALL condition
+ if (pEndpoint->state != UDP_ENDPOINT_HALTED) {
+
+ TRACE_WARNING("_ " );
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_STALLRQ;
+ }
+ }
+
+ // SETUP packet received
+ if( AT91C_OTGHS_RXSTP == (status & AT91C_OTGHS_RXSTP) ) {
+
+ TRACE_DEBUG_WP("Stp ");
+
+ // If a transfer was pending, complete it
+ // Handles the case where during the status phase of a control write
+ // transfer, the host receives the device ZLP and ack it, but the ack
+ // is not received by the device
+ if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+ OTGHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+
+ // Copy the setup packet
+ OTGHS_ReadRequest(&request);
+
+ // Acknowledge setup packet
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_RXSTP;
+
+ // Forward the request to the upper layer
+ USBDCallbacks_RequestReceived(&request);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Interrupt service routine
+//------------------------------------------------------------------------------
+#ifdef DMA
+//----------------------------------------------------------------------------
+/// Endpoint DMA interrupt handler.
+/// This function (ISR) handles dma interrupts
+/// \param bEndpoint Index of endpoint
+//----------------------------------------------------------------------------
+static void OTGHS_DmaHandler( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = &(pEndpoint->transfer);
+ int justTransferred;
+ unsigned int status;
+ unsigned char result = USBD_STATUS_SUCCESS;
+
+ status = AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMASTATUS;
+ TRACE_DEBUG_WP("Dma Ept%d ", bEndpoint);
+
+ // Disable DMA interrupt to avoid receiving 2 interrupts (B_EN and TR_EN)
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL &=
+ ~(unsigned int)(AT91C_OTGHS_END_TR_EN | AT91C_OTGHS_END_B_EN);
+
+ AT91C_BASE_OTGHS->OTGHS_DEVIDR = (1<<SHIFT_DMA<<bEndpoint);
+
+ if( AT91C_OTGHS_END_BF_ST == (status & AT91C_OTGHS_END_BF_ST) ) {
+
+ TRACE_DEBUG_WP("EndBuffer ");
+
+ // BUFF_COUNT holds the number of untransmitted bytes.
+ // BUFF_COUNT is equal to zero in case of good transfer
+ justTransferred = pTransfer->buffered
+ - ((status & (unsigned int)AT91C_OTGHS_BUFF_COUNT) >> 16);
+ pTransfer->transferred += justTransferred;
+
+ pTransfer->buffered = ((status & (unsigned int)AT91C_OTGHS_BUFF_COUNT) >> 16);
+
+ pTransfer->remaining -= justTransferred;
+
+ TRACE_DEBUG_WP("\n\r1pTransfer->buffered %d \n\r", pTransfer->buffered);
+ TRACE_DEBUG_WP("1pTransfer->transferred %d \n\r", pTransfer->transferred);
+ TRACE_DEBUG_WP("1pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+ if( (pTransfer->remaining + pTransfer->buffered) > 0 ) {
+
+ // Prepare an other transfer
+ if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+ pTransfer->buffered = DMA_MAX_FIFO_SIZE;
+ }
+ else {
+ pTransfer->buffered = pTransfer->remaining;
+ }
+
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS =
+ (unsigned int)((pTransfer->pData) + (pTransfer->transferred));
+
+ // Clear unwanted interrupts
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMASTATUS;
+
+ // Enable DMA endpoint interrupt
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = (1 << SHIFT_DMA << bEndpoint);
+ // DMA config for receive the good size of buffer, or an error buffer
+
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = 0; // raz
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL =
+ ( ((pTransfer->buffered << 16) & AT91C_OTGHS_BUFF_COUNT)
+ | AT91C_OTGHS_END_TR_EN
+ | AT91C_OTGHS_END_TR_IT
+ | AT91C_OTGHS_END_B_EN
+ | AT91C_OTGHS_END_BUFFIT
+ | AT91C_OTGHS_CHANN_ENB );
+ }
+ }
+ else if( AT91C_OTGHS_END_TR_ST == (status & AT91C_OTGHS_END_TR_ST) ) {
+
+ TRACE_DEBUG_WP("EndTransf ");
+
+ pTransfer->transferred = pTransfer->buffered
+ - ((status & (unsigned int)AT91C_OTGHS_BUFF_COUNT) >> 16);
+ pTransfer->remaining = 0;
+ TRACE_DEBUG_WP("\n\r0pTransfer->buffered %d \n\r", pTransfer->buffered);
+ TRACE_DEBUG_WP("0pTransfer->transferred %d \n\r", pTransfer->transferred);
+ TRACE_DEBUG_WP("0pTransfer->remaining %d \n\r", pTransfer->remaining);
+ }
+ else {
+
+ TRACE_ERROR("OTGHS_DmaHandler: Error (0x%08X)\n\r", status);
+ result = USBD_STATUS_ABORTED;
+ }
+
+ // Invoke callback
+ if( pTransfer->remaining == 0 ) {
+
+ TRACE_DEBUG_WP("EOT ");
+ OTGHS_EndOfTransfer(bEndpoint, result);
+ }
+}
+#endif
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// USB device interrupt handler
+/// Manages device resume, suspend, end of bus reset.
+/// Forwards endpoint interrupts to the appropriate handler.
+//------------------------------------------------------------------------------
+void USBD_IrqHandler(void)
+{
+ unsigned int status;
+ unsigned char numIT;
+
+ if (deviceState >= USBD_STATE_POWERED) {
+
+ LED_Set(USBD_LEDUSB);
+ }
+
+#ifndef OTG_PROJECT
+ // Get interrupts status
+ status = AT91C_BASE_OTGHS->OTGHS_SR & AT91C_BASE_OTGHS->OTGHS_CTRL & 0xFF;
+ while (status != 0) {
+ //TRACE_ERROR_WP("~");
+ if((status&AT91C_OTGHS_VBUSTI)==AT91C_OTGHS_VBUSTI) {
+ TRACE_DEBUG_WP("__VBus\n\r");
+
+ USBD_Connect();
+
+ // Acknowledge the interrupt
+ AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_VBUSTI;
+ }
+
+ // Don't treat others interrupt for this time
+ AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_IDT | AT91C_OTGHS_SRP
+ | AT91C_OTGHS_VBERR | AT91C_OTGHS_BCERR
+ | AT91C_OTGHS_ROLEEX | AT91C_OTGHS_HNPERR
+ | AT91C_OTGHS_STO;
+
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_IDT;
+
+ status = AT91C_BASE_OTGHS->OTGHS_SR & AT91C_BASE_OTGHS->OTGHS_CTRL & 0xFF;
+ }
+#endif
+
+ // Get OTG Device interrupts status
+ status = AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_BASE_OTGHS->OTGHS_DEVIMR;
+ //TRACE_ERROR_WP("S=0x%X\n\r", AT91C_BASE_OTGHS->OTGHS_DEVISR );
+ //TRACE_ERROR_WP("M=0x%X\n\r", AT91C_BASE_OTGHS->OTGHS_DEVIMR );
+ while (status != 0) {
+ //TRACE_ERROR_WP("=");
+ // Start Of Frame (SOF)
+ if((status&AT91C_OTGHS_SOF)==AT91C_OTGHS_SOF) {
+ TRACE_DEBUG_WP("SOF ");
+
+ // Invoke the SOF callback
+ //USB_StartOfFrameCallback();
+
+ // Acknowledge interrupt
+ AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_SOF;
+ status &= ~(unsigned int)AT91C_OTGHS_SOF;
+ }
+
+ // Suspend
+ // This interrupt is always treated last (hence the '==')
+ else if (status == AT91C_OTGHS_SUSP) {
+
+ TRACE_DEBUG_WP("S");
+
+ // The device enters the Suspended state
+ // MCK + UDPCK must be off
+ // Pull-Up must be connected
+ // Transceiver must be disabled
+
+ LED_Clear(USBD_LEDUSB);
+
+ // Enable wakeup
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = AT91C_OTGHS_EORST | AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM;
+
+ // Acknowledge interrupt
+ AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_SUSP;
+ previousDeviceState = deviceState;
+ deviceState = USBD_STATE_SUSPENDED;
+ OTGHS_DisableTransceiver();
+ OTGHS_DisableUsbClock();
+ // Invoke the Suspend callback
+ USBDCallbacks_Suspended();
+ }
+
+ // Resume
+ else if( ((status & AT91C_OTGHS_WAKEUP) != 0) // line activity
+ || ((status & AT91C_OTGHS_EORSM) != 0)) { // pc wakeup
+
+ // Invoke the Resume callback
+ USBDCallbacks_Resumed();
+
+ TRACE_DEBUG_WP("R");
+
+ OTGHS_EnableUsbClock();
+ OTGHS_EnableTransceiver();
+
+ // The device enters Configured state
+ // MCK + UDPCK must be on
+ // Pull-Up must be connected
+ // Transceiver must be enabled
+
+ deviceState = previousDeviceState;
+
+ AT91C_BASE_OTGHS->OTGHS_DEVICR =
+ (AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM | AT91C_OTGHS_SUSP);
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = (AT91C_OTGHS_EORST | AT91C_OTGHS_SUSP);
+ AT91C_BASE_OTGHS->OTGHS_DEVICR = (AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM);
+ AT91C_BASE_OTGHS->OTGHS_DEVIDR = AT91C_OTGHS_WAKEUP;
+
+ }
+
+ // End of bus reset
+ else if ((status & AT91C_OTGHS_EORST) == AT91C_OTGHS_EORST) {
+
+ TRACE_DEBUG_WP("EoB ");
+
+ // The device enters the Default state
+ deviceState = USBD_STATE_DEFAULT;
+ // MCK + UDPCK are already enabled
+ // Pull-Up is already connected
+ // Transceiver must be enabled
+ // Endpoint 0 must be enabled
+
+ OTGHS_EnableTransceiver();
+ USBDDriver_clearOTGFeatures();
+
+ // The device leaves the Address & Configured states
+ OTGHS_ResetEndpoints();
+ OTGHS_DisableEndpoints();
+ USBD_ConfigureEndpoint(0);
+
+ // Flush and enable the Suspend interrupt
+ AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_WAKEUP | AT91C_OTGHS_SUSP;
+
+ //// Enable the Start Of Frame (SOF) interrupt if needed
+ //if (pCallbacks->startOfFrame != 0)
+ //{
+ // AT91C_BASE_OTGHS->OTGHS_DEVIER |= AT91C_OTGHS_SOF;
+ //}
+
+ // Invoke the Reset callback
+ USBDCallbacks_Reset();
+
+ // Acknowledge end of bus reset interrupt
+ AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_EORST;
+ }
+
+ // Handle upstream resume interrupt
+ else if (status & AT91C_OTGHS_UPRSM) {
+
+ TRACE_DEBUG_WP("ExtRes ");
+
+ // - Acknowledge the IT
+ AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_UPRSM;
+ }
+
+ // Endpoint interrupts
+ else {
+#ifndef DMA
+
+ // Handle endpoint interrupts
+ for (numIT = 0; numIT < NUM_IT_MAX; numIT++) {
+
+ if ((status & (1 << SHIFT_INTERUPT << numIT)) != 0) {
+
+ OTGHS_EndpointHandler(numIT);
+ }
+ }
+#else
+ // Handle endpoint control interrupt
+ if ((status & (1 << SHIFT_INTERUPT << 0)) != 0) {
+
+ OTGHS_EndpointHandler( 0 );
+ }
+ else {
+
+ numIT = 1;
+ while((status&(0x7E<<SHIFT_DMA)) != 0) {
+
+ // Check if endpoint has a pending interrupt
+ if ((status & (1 << SHIFT_DMA << numIT)) != 0) {
+
+ OTGHS_DmaHandler(numIT);
+ status &= ~(1 << SHIFT_DMA << numIT);
+ if (status != 0) {
+
+ TRACE_INFO_WP("\n\r - ");
+ }
+ }
+ numIT++;
+ }
+ }
+#endif
+ }
+
+ // Retrieve new interrupt status
+ status = AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_BASE_OTGHS->OTGHS_DEVIMR;
+
+ TRACE_DEBUG_WP("\n\r");
+
+ if (status != 0) {
+
+ TRACE_DEBUG_WP(" - ");
+ }
+ }
+
+ if (deviceState >= USBD_STATE_POWERED) {
+
+ LED_Clear(USBD_LEDUSB);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Configure an endpoint with the provided endpoint descriptor
+/// \param pDdescriptor Pointer to the endpoint descriptor
+//------------------------------------------------------------------------------
+void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor)
+
+{
+ Endpoint *pEndpoint;
+ unsigned char bEndpoint;
+ unsigned char bType;
+ unsigned char bEndpointDir;
+ unsigned char bSizeEpt = 0;
+
+ // NULL descriptor -> Control endpoint 0
+ if (pDescriptor == 0) {
+
+ bEndpoint = 0;
+ pEndpoint = &(endpoints[bEndpoint]);
+ bType = USBEndpointDescriptor_CONTROL;
+ bEndpointDir = 0;
+ pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0);
+ pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);
+ }
+ else {
+
+ // The endpoint number
+ bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
+ pEndpoint = &(endpoints[bEndpoint]);
+ // Transfer type: Control, Isochronous, Bulk, Interrupt
+ bType = USBEndpointDescriptor_GetType(pDescriptor);
+ // Direction, ignored for control endpoints
+ bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
+ pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
+ pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);
+ }
+
+ // Abort the current transfer is the endpoint was configured and in
+ // Write or Read state
+ if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING) ) {
+
+ OTGHS_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
+ }
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Disable endpoint
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_TXINI
+ | AT91C_OTGHS_RXOUT
+ | AT91C_OTGHS_RXSTP
+ | AT91C_OTGHS_NAKOUT
+ | AT91C_OTGHS_NAKIN
+ | AT91C_OTGHS_OVERFL
+ | AT91C_OTGHS_STALL
+ | AT91C_OTGHS_SHRTPACK
+ | AT91C_OTGHS_MADATA
+ | AT91C_OTGHS_DATAX
+ | AT91C_OTGHS_ERRTRANS
+ | AT91C_OTGHS_NBUSYBK
+ | AT91C_OTGHS_FIFOCON
+ | AT91C_OTGHS_EPDISHDMA
+ | AT91C_OTGHS_NYETDIS
+ | AT91C_OTGHS_STALLRQ;
+
+ // Reset Endpoint Fifos
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT |= (1<<bEndpoint<<16);
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT &= ~(1<<bEndpoint<<16);
+
+ // Configure endpoint
+ if( pEndpoint->size <= 8 ) {
+ bSizeEpt = 0;
+ }
+ else if ( pEndpoint->size <= 16 ) {
+ bSizeEpt = 1;
+ }
+ else if ( pEndpoint->size <= 32 ) {
+ bSizeEpt = 2;
+ }
+ else if ( pEndpoint->size <= 64 ) {
+ bSizeEpt = 3;
+ }
+ else if ( pEndpoint->size <= 128 ) {
+ bSizeEpt = 4;
+ }
+ else if ( pEndpoint->size <= 256 ) {
+ bSizeEpt = 5;
+ }
+ else if ( pEndpoint->size <= 512 ) {
+ bSizeEpt = 6;
+ }
+ else if ( pEndpoint->size <= 1024 ) {
+ bSizeEpt = 7;
+ } //else {
+ // sizeEpt = 0; // control endpoint
+ //}
+
+ // Enable endpoint
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT |= (1<<bEndpoint);
+
+ // Configure endpoint
+ if (bType == USBEndpointDescriptor_CONTROL) {
+
+ // Enable endpoint IT for control endpoint
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = 1<<SHIFT_INTERUPT<<bEndpoint;
+ }
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint] = (bSizeEpt << 4)
+ | (bEndpointDir << 8)
+ | (bType << 11)
+ | (((pEndpoint->bank)-1) << 2);
+
+ if (bType == USBEndpointDescriptor_CONTROL) {
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_RXSTP;
+ }
+#ifdef DMA
+ else {
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint] |= AT91C_OTGHS_AUTOSW;
+ }
+#endif
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_NYETDIS;// with nyet
+ //AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_NYETDIS; // without nyet
+
+ // Check if the configuration is ok
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint] |= AT91C_OTGHS_ALLOC;
+ if((AT91C_BASE_OTGHS->OTGHS_DEVEPTISR[bEndpoint]&AT91C_OTGHS_CFGOK)==0) {
+
+ TRACE_ERROR("PB bEndpoint: 0x%X\n\r", bEndpoint);
+ TRACE_ERROR("PB bSizeEpt: 0x%X\n\r", bSizeEpt);
+ TRACE_ERROR("PB bEndpointDir: 0x%X\n\r", bEndpointDir);
+ TRACE_ERROR("PB bType: 0x%X\n\r", bType);
+ TRACE_ERROR("PB pEndpoint->bank: 0x%X\n\r", pEndpoint->bank);
+ TRACE_ERROR("PB OTGHS_EPTCFG: 0x%X\n\r", AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint]);
+ for(;;);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through an USB endpoint (IN)
+/// Sets up the transfer descriptor, write one or two data payloads
+/// (depending on the number of FIFO banks for the endpoint) and then
+/// starts the actual transfer. The operation is complete when all
+/// the data has been sent.
+/// \param bEndpoint Index of endpoint
+/// \param *pData Data to be written
+/// \param dLength Data length to be send
+/// \param fCallback Callback to be call after the success command
+/// \param *pArgument Callback argument
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+char USBD_Write( unsigned char bEndpoint,
+ const void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = &(pEndpoint->transfer);
+//unsigned char i;
+//unsigned char * data;
+
+ // Return if the endpoint is not in IDLE state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength);
+ pEndpoint->sendZLP = 0;
+ // Setup the transfer descriptor
+ pTransfer->pData = (void *) pData;
+ pTransfer->remaining = dLength;
+ pTransfer->buffered = 0;
+ pTransfer->transferred = 0;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+
+ // Send one packet
+ pEndpoint->state = UDP_ENDPOINT_SENDING;
+
+#ifdef DMA
+ // Test if endpoint type control
+ if (AT91C_OTGHS_EPT_TYPE_CTL_EPT == (AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])) {
+#endif
+ // Enable endpoint IT
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_TXINI;
+
+#ifdef DMA
+ }
+ else {
+ if( CHIP_USB_ENDPOINTS_DMA(bEndpoint) == 0 ) {
+ TRACE_FATAL("Endpoint has no DMA\n\r");
+ }
+ if( pTransfer->remaining == 0 ) {
+
+ // DMA not handle ZLP
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_TXINI;
+ // For a non-control endpoint, the FIFOCON bit must be cleared
+ // to start the transfer
+ if ((AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])
+ != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_FIFOCON;
+ }
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_TXINI;
+
+ // Enable endpoint IT
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
+ }
+ else {
+ // Others endpoints (not control)
+ if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+ // Transfer the max
+ pTransfer->buffered = DMA_MAX_FIFO_SIZE;
+ }
+ else {
+ // Transfer the good size
+ pTransfer->buffered = pTransfer->remaining;
+ }
+
+ TRACE_DEBUG_WP("\n\r_WR:%d ", pTransfer->remaining );
+ TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
+ TRACE_DEBUG_WP("T:%d ", pTransfer->transferred );
+
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS = (unsigned int)(pTransfer->pData);
+
+ // Clear unwanted interrupts
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMASTATUS;
+
+ // Enable DMA endpoint interrupt
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = (1<<SHIFT_DMA<<bEndpoint);
+ // DMA config
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = 0; // raz
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL =
+ (((pTransfer->buffered<<16)&AT91C_OTGHS_BUFF_LENGTH)
+ | AT91C_OTGHS_END_B_EN
+ | AT91C_OTGHS_END_BUFFIT
+ | AT91C_OTGHS_CHANN_ENB);
+ }
+ }
+#endif
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Reads incoming data on an USB endpoint (OUT)
+/// \param bEndpoint Index of endpoint
+/// \param *pData Data to be readen
+/// \param dLength Data length to be receive
+/// \param fCallback Callback to be call after the success command
+/// \param *pArgument Callback argument
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+char USBD_Read( unsigned char bEndpoint,
+ void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = &(pEndpoint->transfer);
+
+ // Return if the endpoint is not in IDLE state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+ //TRACE_ERROR_WP("Read%d(%d) ", bEndpoint, dLength);
+
+ // Endpoint enters Receiving state
+ pEndpoint->state = UDP_ENDPOINT_RECEIVING;
+
+ // Set the transfer descriptor
+ pTransfer->pData = pData;
+ pTransfer->remaining = dLength;
+ pTransfer->buffered = 0;
+ pTransfer->transferred = 0;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+
+#ifdef DMA
+ // Test if endpoint type control
+ if (AT91C_OTGHS_EPT_TYPE_CTL_EPT == (AT91C_OTGHS_EPT_TYPE & AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint])) {
+#endif
+ // Control endpoint
+ // Enable endpoint IT
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_RXOUT;
+#ifdef DMA
+ }
+ else {
+ if( CHIP_USB_ENDPOINTS_DMA(bEndpoint) == 0 ) {
+ TRACE_FATAL("Endpoint has no DMA\n\r");
+ }
+ TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+
+ // Others endpoints (not control)
+ if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+ // Transfer the max
+ pTransfer->buffered = DMA_MAX_FIFO_SIZE;
+ }
+ else {
+ // Transfer the good size
+ pTransfer->buffered = pTransfer->remaining;
+ }
+
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS = (unsigned int)(pTransfer->pData);
+
+ // Clear unwanted interrupts
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMASTATUS;
+
+ // Enable DMA endpoint interrupt
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = (1<<SHIFT_DMA<<bEndpoint);
+
+ TRACE_DEBUG_WP("\n\r_RR:%d ", pTransfer->remaining );
+ TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
+ TRACE_DEBUG_WP("T:%d ", pTransfer->transferred );
+
+ // DMA config
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = 0; // raz
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL =
+ (((pTransfer->buffered<<16)&AT91C_OTGHS_BUFF_LENGTH)
+ | AT91C_OTGHS_END_TR_EN
+ | AT91C_OTGHS_END_TR_IT
+ | AT91C_OTGHS_END_B_EN
+ | AT91C_OTGHS_END_BUFFIT
+ | AT91C_OTGHS_CHANN_ENB);
+ }
+#endif
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Put endpoint into Halt state
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Halt( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ TRACE_INFO("usbd_Halt%d ", bEndpoint);
+ //TRACE_ERROR("usbd_Halt%d ", bEndpoint);
+
+ // Check that endpoint is enabled and not already in Halt state
+ if( (pEndpoint->state != UDP_ENDPOINT_DISABLED)
+ && (pEndpoint->state != UDP_ENDPOINT_HALTED) ) {
+
+ TRACE_INFO("Halt%d ", bEndpoint);
+
+ // Abort the current transfer if necessary
+ OTGHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
+
+ pEndpoint->state = UDP_ENDPOINT_HALTED;
+ // Put endpoint into Halt state
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_STALLRQ;
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_STALL;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the Halt feature on the given endpoint.
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Unhalt( unsigned char bEndpoint )
+{
+ unsigned int cfgSav;
+
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check if the endpoint is enabled
+ //if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
+ if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+
+ TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
+ //TRACE_ERROR("Unhalt%d ", bEndpoint);
+
+ // Return endpoint to Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ cfgSav = AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint];
+
+ // Reset Endpoint Fifos
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT |= (1<<bEndpoint<<16);
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT &= ~(1<<bEndpoint<<16);
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[bEndpoint] = cfgSav;
+
+ if((AT91C_BASE_OTGHS->OTGHS_DEVEPTISR[bEndpoint]&AT91C_OTGHS_CFGOK)==0) {
+
+ TRACE_ERROR("PB bEndpoint: 0x%X\n\r", bEndpoint);
+ for(;;);
+ }
+
+ // Reset data-toggle
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_RSTDT;
+
+ // Clear FORCESTALL flag
+ // Disable stall on endpoint
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[bEndpoint] = AT91C_OTGHS_STALLRQ;
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[bEndpoint] = AT91C_OTGHS_STALL;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current Halt status of an endpoint.
+/// \param bEndpoint Index of endpoint
+/// \return 1 if the endpoint is currently halted; otherwise 0
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHalted( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ unsigned char status = 0;
+
+ if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+ status = 1;
+ }
+ return( status );
+}
+
+//------------------------------------------------------------------------------
+/// IS High Speed device working in High Speed ?
+/// \return 1 if the device is in High Speed; otherwise 0 (Full Speed)
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHighSpeed( void )
+{
+ unsigned char status = 0;
+
+ if(AT91C_OTGHS_SPEED_SR_HS == (AT91C_BASE_OTGHS->OTGHS_SR & (0x03<<12))) {
+ // High Speed
+ TRACE_DEBUG_WP("High Speed\n\r");
+ status = 1;
+ }
+ else {
+ TRACE_DEBUG_WP("Full Speed\n\r");
+ }
+ return( status );
+}
+
+//------------------------------------------------------------------------------
+/// Causes the endpoint to acknowledge the next received packet with a STALL
+/// handshake.
+/// Further packets are then handled normally.
+/// \param bEndpoint Index of endpoint
+/// \return Operation result code: USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char USBD_Stall( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check that endpoint is in Idle state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ TRACE_WARNING("UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
+ return USBD_STATUS_LOCKED;
+ }
+
+ TRACE_DEBUG_WP("Stall%d ", bEndpoint);
+
+ // Sends a STALL handshake for the next host request.
+ // A STALL handshake will be sent for each following request until a SETUP
+ // or a Clear Halt Feature occurs for this endpoint.
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[bEndpoint] = AT91C_OTGHS_STALLRQ|AT91C_OTGHS_RXSTP;
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Activates a remote wakeup procedure
+//------------------------------------------------------------------------------
+void USBD_RemoteWakeUp(void)
+{
+ TRACE_DEBUG_WP("Remote WakeUp\n\r");
+
+ // Device is currently suspended
+ if (deviceState == USBD_STATE_SUSPENDED) {
+
+ TRACE_DEBUG_WP("RW\n\r");
+ OTGHS_EnableUsbClock();
+ OTGHS_EnableTransceiver();
+
+ // Activates a remote wakeup
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_RMWKUP;
+ }
+ // Device is NOT suspended
+ else {
+
+ TRACE_WARNING("USBD_RemoteWakeUp: Device is not suspended\n\r");
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sets the device address
+/// \param address Adress to be set
+//------------------------------------------------------------------------------
+void USBD_SetAddress( unsigned char address )
+{
+ TRACE_DEBUG_WP("SetAddr(%d) ", address);
+
+ // Set address
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL &= ~(unsigned int)AT91C_OTGHS_UADD;
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= address & AT91C_OTGHS_UADD;
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_ADDEN;
+
+ // If the address is 0, the device returns to the Default state
+ if (address == 0) {
+ deviceState = USBD_STATE_DEFAULT;
+ }
+ // If the address is non-zero, the device enters the Address state
+ else {
+ deviceState = USBD_STATE_ADDRESS;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Changes the device state from Address to Configured, or from Configured
+/// to Address.
+/// This method directly access the last received SETUP packet to decide on
+/// what to do.
+/// \param cfgnum configuration number
+//------------------------------------------------------------------------------
+void USBD_SetConfiguration( unsigned char cfgnum )
+{
+ TRACE_DEBUG_WP("SetCfg(%d) ", cfgnum);
+
+ // Check the request
+ if( cfgnum != 0 ) {
+
+ // Enter Configured state
+ deviceState = USBD_STATE_CONFIGURED;
+ }
+ // If the configuration number is zero, the device goes back to the Address
+ // state
+ else {
+
+ // Go back to Address state
+ deviceState = USBD_STATE_ADDRESS;
+
+ // Abort all transfers
+ OTGHS_DisableEndpoints();
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Enables the pull-up on the D+ line to connect the device to the USB.
+//------------------------------------------------------------------------------
+void USBD_Connect( void )
+{
+ TRACE_DEBUG_WP("Conn ");
+#if defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL &= ~(unsigned int)AT91C_OTGHS_DETACH;
+#else
+ #error "not defined"
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Disables the pull-up on the D+ line to disconnect the device from the bus.
+//------------------------------------------------------------------------------
+void USBD_Disconnect( void )
+{
+ TRACE_DEBUG_WP("Disc ");
+#if defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_DETACH;
+
+#else
+ #error "not defined"
+#endif
+ // Device returns to the Powered state
+ if (deviceState > USBD_STATE_POWERED) {
+
+ deviceState = USBD_STATE_POWERED;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Certification test for High Speed device.
+/// \param bIndex Test to be done
+//------------------------------------------------------------------------------
+void USBD_Test( unsigned char bIndex )
+{
+ char *pFifo;
+ unsigned char i;
+
+ AT91C_BASE_OTGHS->OTGHS_DEVIDR &= ~(unsigned int)AT91C_OTGHS_SUSP;
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_SPDCONF_HS; // remove suspend ?
+
+ switch( bIndex ) {
+ case USBFeatureRequest_TESTPACKET:
+ TRACE_DEBUG_WP("TEST_PACKET ");
+
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[1].OTGHS_DEVDMACONTROL = 0; // raz
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[2].OTGHS_DEVDMACONTROL = 0; // raz
+
+ // Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[2] = AT91C_OTGHS_EPT_SIZE_64
+ | AT91C_OTGHS_EPT_DIR_IN
+ | AT91C_OTGHS_EPT_TYPE_BUL_EPT
+ | AT91C_OTGHS_BK_NUMBER_1;
+ // Check if the configuration is ok
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[2] |= AT91C_OTGHS_ALLOC;
+ while((AT91C_BASE_OTGHS->OTGHS_DEVEPTISR[2]&AT91C_OTGHS_CFGOK)==0) {
+ }
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT |= AT91C_OTGHS_EPEN2;
+
+ // Write FIFO
+ pFifo = (char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO + (EPT_VIRTUAL_SIZE * 2));
+ for( i=0; i<sizeof(test_packet_buffer); i++) {
+ pFifo[i] = test_packet_buffer[i];
+ }
+ // Tst PACKET
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_TSTPCKT;
+ // Send packet
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[2] = AT91C_OTGHS_TXINI;
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[2] = AT91C_OTGHS_FIFOCON;
+ break;
+
+ case USBFeatureRequest_TESTJ:
+ TRACE_DEBUG_WP("TEST_J ");
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_TSTJ;
+ break;
+
+ case USBFeatureRequest_TESTK:
+ TRACE_DEBUG_WP("TEST_K ");
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_TSTK;
+ break;
+
+ case USBFeatureRequest_TESTSE0NAK:
+ TRACE_DEBUG_WP("TEST_SEO_NAK ");
+ AT91C_BASE_OTGHS->OTGHS_DEVIDR = 0xFFFFFFFF;
+ break;
+
+ case USBFeatureRequest_TESTSENDZLP:
+ //while( 0 != (AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & AT91C_UDPHS_TX_PK_RDY ) ) {}
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTICR[0] = AT91C_OTGHS_TXINI;
+ //while( 0 != (AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & AT91C_UDPHS_TX_PK_RDY ) ) {}
+ TRACE_DEBUG_WP("SEND_ZLP ");
+ break;
+ }
+ TRACE_DEBUG_WP("\n\r");
+}
+
+//------------------------------------------------------------------------------
+/// Initializes the specified USB driver
+/// This function initializes the current FIFO bank of endpoints,
+/// configures the pull-up and VBus lines, disconnects the pull-up and
+/// then trigger the Init callback.
+//------------------------------------------------------------------------------
+void USBD_Init(void)
+{
+ // forceFS must not be used !
+ unsigned int i;
+
+ TRACE_DEBUG_WP("USBD Init()\n\r");
+
+ // Enable USB macro
+ *AT91C_OTGHS_CTRL |= AT91C_OTGHS_USBECTRL;
+
+ // Automatic mode speed for device
+ *AT91C_OTGHS_DEVCTRL &= ~(unsigned int)AT91C_OTGHS_SPDCONF_FS; // Normal mode
+
+ *AT91C_OTGHS_DEVCTRL &= ~(unsigned int)( AT91C_OTGHS_LS | AT91C_OTGHS_TSTJ
+ | AT91C_OTGHS_TSTK | AT91C_OTGHS_TSTPCKT
+ | AT91C_OTGHS_OPMODE2 ); // Normal mode
+
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL = 0;
+ AT91C_BASE_OTGHS->OTGHS_HSTCTRL = 0;
+
+ // Enable OTG pad
+ *AT91C_OTGHS_CTRL |= AT91C_OTGHS_OTGPADE;
+
+ // Enable clock OTG pad
+ *AT91C_OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_FRZCLKCTRL;
+
+ //Usb_disable();
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_USBECTRL;
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_OTGPADE;
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_FRZCLKCTRL;
+ //Usb_enable();
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_USBECTRL;
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_OTGPADE;
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_FRZCLKCTRL;
+ //Usb_select_device();
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_UIDE;
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_UIMOD;
+
+ // Device is in the Attached state
+ deviceState = USBD_STATE_SUSPENDED;
+ previousDeviceState = USBD_STATE_POWERED;
+
+
+ PMC_EnablePeripheral(AT91C_ID_OTGHS);
+
+ // Reset endpoint structures
+ OTGHS_ResetEndpoints();
+
+ // Enables the USB Clock
+ OTGHS_EnableUsbClock();
+
+ //926C
+ // Enable USB macro and clear all other bit
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_USBECTRL;
+ AT91C_BASE_OTGHS->OTGHS_CTRL = AT91C_OTGHS_USBECTRL;
+
+ // Configure the pull-up on D+ and disconnect it
+ USBD_Disconnect();
+
+ // Enable clock OTG pad
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_FRZCLKCTRL;
+ TRACE_DEBUG("AT91C_OTGHS_CTRL: 0x%X\n\r", AT91C_BASE_OTGHS->OTGHS_CTRL );
+
+ // Clear General IT
+ AT91C_BASE_OTGHS->OTGHS_SCR = 0x01FF;
+
+ // Clear OTG Device IT
+ AT91C_BASE_OTGHS->OTGHS_DEVICR = 0xFF;
+
+ // Clear OTG Host IT
+ AT91C_BASE_OTGHS->OTGHS_HSTICR = 0x7F;
+
+ // Reset all Endpoints Fifos
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT |= (0x7F<<16);
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT &= ~(unsigned int)(0x7F<<16);
+
+ // Disable all endpoints
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT &= ~(unsigned int)0x7F;
+
+ AT91C_BASE_OTGHS->OTGHS_TSTA2 = 0;
+
+ // Device is in the Attached state
+ deviceState = USBD_STATE_SUSPENDED;
+ previousDeviceState = USBD_STATE_POWERED;
+
+ // Automatic mode speed for device
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL &= ~(unsigned int)AT91C_OTGHS_SPDCONF_FS;
+ // Force Full Speed mode for device
+ //*AT91C_OTGHS_DEVCTRL = AT91C_OTGHS_SPDCONF_FS;
+ // Force High Speed mode for device
+ //*AT91C_OTGHS_DEVCTRL = AT91C_OTGHS_SPDCONF_HS;
+
+ AT91C_BASE_OTGHS->OTGHS_DEVCTRL &= ~(unsigned int)( AT91C_OTGHS_LS
+ | AT91C_OTGHS_TSTJ
+ | AT91C_OTGHS_TSTK
+ | AT91C_OTGHS_TSTPCKT
+ | AT91C_OTGHS_OPMODE2 );
+
+
+ // Automatic mode speed for host
+ AT91C_BASE_OTGHS->OTGHS_HSTCTRL &= ~(unsigned int)AT91C_OTGHS_SPDCONF_HST_FS;
+ // Force Full Speed mode for host
+ //AT91C_BASE_OTGHS->OTGHS_HSTCTRL = AT91C_OTGHS_SPDCONF_HST_FS;
+ // Force High Speed mode for host
+ //*AT91C_BASE_OTGHS->OTGHS_HSTCTRL = AT91C_OTGHS_SPDCONF_HST_HS;
+
+ // Enable USB macro
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_USBECTRL;
+
+ // Enable the UID pin select
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_UIDE;
+
+ // Enable OTG pad
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_OTGPADE;
+
+ // Enable clock OTG pad
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_FRZCLKCTRL;
+
+
+ // With OR without DMA !!!
+ // Initialization of DMA
+ for( i=1; i<=(unsigned int)((AT91C_BASE_OTGHS->OTGHS_IPFEATURES & AT91C_OTGHS_DMA_CHANNEL_NBR)>>4); i++ ) {
+
+ // RESET endpoint canal DMA:
+ // DMA stop channel command
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMACONTROL = 0; // STOP command
+
+ // Disable endpoint
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[i] = 0XFFFFFFFF;
+
+ // Reset endpoint config
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[i] = 0;
+
+ // Reset DMA channel (Buff count and Control field)
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMACONTROL = 0x02; // NON STOP command
+
+ // Reset DMA channel 0 (STOP)
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMACONTROL = 0; // STOP command
+
+ // Clear DMA channel status (read the register for clear it)
+ AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMASTATUS = AT91C_BASE_OTGHS->OTGHS_DEVDMA[i].OTGHS_DEVDMASTATUS;
+
+ }
+
+
+ // Configure interrupts
+ USBDCallbacks_Initialized();
+
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_VBUSTI;
+
+ TRACE_DEBUG("AT91C_OTGHS_CTRL: 0x%X\n\r", AT91C_BASE_OTGHS->OTGHS_CTRL );
+ TRACE_DEBUG("AT91C_OTGHS_SR: 0x%X\n\r", AT91C_BASE_OTGHS->OTGHS_SR );
+
+ AT91C_BASE_OTGHS->OTGHS_DEVIER = AT91C_OTGHS_WAKEUP;
+
+ TRACE_DEBUG("NUM_IT_MAX_DMA: 0x%X\n\r", NUM_IT_MAX_DMA );
+ TRACE_DEBUG("NUM_IT_MAX: 0x%X\n\r", NUM_IT_MAX );
+
+}
+
+
+//------------------------------------------------------------------------------
+/// Returns the current state of the USB device.
+/// \return Device current state.
+//------------------------------------------------------------------------------
+unsigned char USBD_GetState( void )
+{
+ return deviceState;
+}
+
diff --git a/usb/device/core/USBD_UDP.c b/usb/device/core/USBD_UDP.c new file mode 100644 index 0000000..437d185 --- /dev/null +++ b/usb/device/core/USBD_UDP.c @@ -0,0 +1,1692 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Implementation of USB device functions on a UDP controller.
+
+ See "USBD API Methods".
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "USBD.h"
+#include "USBDCallbacks.h"
+#include <board.h>
+#include <pio/pio.h>
+#include <utility/trace.h>
+#include <utility/led.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "UDP register field values"
+///
+/// This page lists the initialize values of UDP registers.
+///
+/// !Values
+/// - UDP_RXDATA
+
+/// Bit mask for both banks of the UDP_CSR register.
+#define UDP_RXDATA (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "Endpoint states"
+///
+/// This page lists the endpoint states.
+///
+/// !States
+// - UDP_ENDPOINT_DISABLED
+// - UDP_ENDPOINT_HALTED
+// - UDP_ENDPOINT_IDLE
+// - UDP_ENDPOINT_SENDING
+// - UDP_ENDPOINT_RECEIVING
+// - UDP_ENDPOINT_SENDINGM
+// - UDP_ENDPOINT_RECEIVINGM
+
+/// Endpoint states: Endpoint is disabled
+#define UDP_ENDPOINT_DISABLED 0
+/// Endpoint states: Endpoint is halted (i.e. STALLs every request)
+#define UDP_ENDPOINT_HALTED 1
+/// Endpoint states: Endpoint is idle (i.e. ready for transmission)
+#define UDP_ENDPOINT_IDLE 2
+/// Endpoint states: Endpoint is sending data
+#define UDP_ENDPOINT_SENDING 3
+/// Endpoint states: Endpoint is receiving data
+#define UDP_ENDPOINT_RECEIVING 4
+/// Endpoint states: Endpoint is sending MBL
+#define UDP_ENDPOINT_SENDINGM 5
+/// Endpoint states: Endpoint is receiving MBL
+#define UDP_ENDPOINT_RECEIVINGM 6
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "UDP_CSR register access"
+///
+/// This page lists the macroes to access UDP CSR register.
+///
+/// !Macros
+/// - CLEAR_CSR
+/// - SET_CSR
+
+/// Bitmap for all status bits in CSR.
+#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
+ |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
+ |AT91C_UDP_TXCOMP
+
+/// Clears the specified bit(s) in the UDP_CSR register.
+/// \param endpoint The endpoint number of the CSR to process.
+/// \param flags The bitmap to set to 1.
+#define SET_CSR(endpoint, flags) \
+ { \
+ volatile unsigned int reg; \
+ int timeOut = 200; \
+ reg = AT91C_BASE_UDP->UDP_CSR[endpoint] ; \
+ reg |= REG_NO_EFFECT_1_ALL; \
+ reg |= (flags); \
+ AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
+ while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) != (flags)) \
+ { \
+ if (-- timeOut <= 0) break; \
+ } \
+ }
+
+/// Sets the specified bit(s) in the UDP_CSR register.
+/// \param endpoint The endpoint number of the CSR to process.
+/// \param flags The bitmap to clear to 0.
+#define CLEAR_CSR(endpoint, flags) \
+ { \
+ volatile unsigned int reg; \
+ reg = AT91C_BASE_UDP->UDP_CSR[endpoint]; \
+ reg |= REG_NO_EFFECT_1_ALL; \
+ reg &= ~(flags); \
+ AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
+ while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) == (flags)); \
+ }
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+/// Describes an ongoing transfer on a UDP endpoint.
+typedef struct {
+
+ /// Pointer to a data buffer used for emission/reception.
+ char *pData;
+ /// Number of bytes which have been written into the UDP internal FIFO
+ /// buffers.
+ volatile int buffered;
+ /// Number of bytes which have been sent/received.
+ volatile int transferred;
+ /// Number of bytes which have not been buffered/transferred yet.
+ volatile int remaining;
+ /// Optional callback to invoke when the transfer completes.
+ volatile TransferCallback fCallback;
+ /// Optional argument to the callback function.
+ void *pArgument;
+} Transfer;
+
+/// Describes Multi Buffer List transfer on a UDP endpoint.
+typedef struct {
+ /// Pointer to frame list
+ USBDTransferBuffer *pMbl;
+ /// Pointer to last loaded buffer
+ USBDTransferBuffer *pLastLoaded;
+ /// List size
+ unsigned short listSize;
+ /// Current processing frame
+ unsigned short currBuffer;
+ /// First freed frame to re-use
+ unsigned short freedBuffer;
+ /// Frame setting, circle frame list
+ unsigned char circList;
+ /// All buffer listed is used
+ unsigned char allUsed;
+ /// Optional callback to invoke when the transfer completes.
+ MblTransferCallback fCallback;
+ /// Optional argument to the callback function.
+ void *pArgument;
+} MblTransfer;
+
+//------------------------------------------------------------------------------
+/// Describes the state of an endpoint of the UDP controller.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Current endpoint state.
+ volatile unsigned char state;
+ /// Current reception bank (0 or 1).
+ volatile unsigned char bank;
+ /// Maximum packet size for the endpoint.
+ volatile unsigned short size;
+ /// Describes an ongoing transfer (if current state is either
+ /// <UDP_ENDPOINT_SENDING> or <UDP_ENDPOINT_RECEIVING>)
+ union {
+ Transfer singleTransfer;
+ MblTransfer mblTransfer;
+ } transfer;
+} Endpoint;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Holds the internal state for each endpoint of the UDP.
+static Endpoint endpoints[CHIP_USB_NUMENDPOINTS];
+
+/// Device current state.
+static unsigned char deviceState;
+/// Indicates the previous device state
+static unsigned char previousDeviceState;
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Enables the clock of the UDP peripheral.
+//------------------------------------------------------------------------------
+static inline void UDP_EnablePeripheralClock(void)
+{
+ AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_UDP;
+}
+
+//------------------------------------------------------------------------------
+/// Disables the UDP peripheral clock.
+//------------------------------------------------------------------------------
+static inline void UDP_DisablePeripheralClock(void)
+{
+ AT91C_BASE_PMC->PMC_PCDR = 1 << AT91C_ID_UDP;
+}
+
+//------------------------------------------------------------------------------
+/// Enables the 48MHz USB clock.
+//------------------------------------------------------------------------------
+static inline void UDP_EnableUsbClock(void)
+{
+ AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
+}
+
+//------------------------------------------------------------------------------
+/// Disables the 48MHz USB clock.
+//------------------------------------------------------------------------------
+static inline void UDP_DisableUsbClock(void)
+{
+ AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_UDP;
+}
+
+//------------------------------------------------------------------------------
+/// Enables the UDP transceiver.
+//------------------------------------------------------------------------------
+static inline void UDP_EnableTransceiver(void)
+{
+ AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_TXVDIS;
+}
+
+//------------------------------------------------------------------------------
+/// Disables the UDP transceiver.
+//------------------------------------------------------------------------------
+static inline void UDP_DisableTransceiver(void)
+{
+ AT91C_BASE_UDP->UDP_TXVC |= AT91C_UDP_TXVDIS;
+}
+
+//------------------------------------------------------------------------------
+/// Handles a completed transfer on the given endpoint, invoking the
+/// configured callback if any.
+/// \param bEndpoint Number of the endpoint for which the transfer has completed.
+/// \param bStatus Status code returned by the transfer operation
+//------------------------------------------------------------------------------
+static void UDP_EndOfTransfer(unsigned char bEndpoint, char bStatus)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check that endpoint was sending or receiving data
+ if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+ Transfer *pTransfer = (Transfer *)&(pEndpoint->transfer);
+
+ TRACE_DEBUG_WP("EoT ");
+
+ // Endpoint returns in Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Invoke callback is present
+ if (pTransfer->fCallback != 0) {
+
+ ((TransferCallback) pTransfer->fCallback)
+ (pTransfer->pArgument,
+ bStatus,
+ pTransfer->transferred,
+ pTransfer->remaining + pTransfer->buffered);
+ }
+ else {
+ TRACE_DEBUG_WP("NoCB ");
+ }
+ }
+ else if ( (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDINGM) ) {
+
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+
+ TRACE_DEBUG_WP("EoMT ");
+
+ // Endpoint returns in Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+ // Invoke callback
+ if (pTransfer->fCallback != 0) {
+
+ ((MblTransferCallback) pTransfer->fCallback)
+ (pTransfer->pArgument,
+ bStatus,
+ 0);
+ }
+ else {
+ TRACE_DEBUG_WP("NoCB ");
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the correct reception flag (bank 0 or bank 1) of an endpoint
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDP_ClearRxFlag(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Clear flag and change banks
+ if (pEndpoint->bank == 0) {
+
+ CLEAR_CSR(bEndpoint, AT91C_UDP_RX_DATA_BK0);
+ // Swap bank if in dual-fifo mode
+ if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) {
+
+ pEndpoint->bank = 1;
+ }
+ }
+ else {
+
+ CLEAR_CSR(bEndpoint, AT91C_UDP_RX_DATA_BK1);
+ pEndpoint->bank = 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Update multi-buffer-transfer descriptors.
+/// \param pTransfer Pointer to instance MblTransfer.
+/// \param size Size of bytes that processed.
+/// \param forceEnd Force the buffer END.
+/// \return 1 if current buffer ended.
+//------------------------------------------------------------------------------
+static char UDP_MblUpdate(MblTransfer *pTransfer,
+ USBDTransferBuffer * pBi,
+ unsigned short size,
+ unsigned char forceEnd)
+{
+ // Update transfer descriptor
+ pBi->remaining -= size;
+ // Check if current buffer ended
+ if (pBi->remaining == 0 || forceEnd) {
+
+ // Process to next buffer
+ if ((++ pTransfer->currBuffer) == pTransfer->listSize) {
+ if (pTransfer->circList) {
+ pTransfer->currBuffer = 0;
+ }
+ else {
+ pTransfer->allUsed = 1;
+ }
+ }
+ // All buffer in the list is processed
+ if (pTransfer->currBuffer == pTransfer->freedBuffer) {
+ pTransfer->allUsed = 1;
+ }
+ // Continue transfer, prepare for next operation
+ if (pTransfer->allUsed == 0) {
+ pBi = &pTransfer->pMbl[pTransfer->currBuffer];
+ pBi->buffered = 0;
+ pBi->transferred = 0;
+ pBi->remaining = pBi->size;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from the current tranfer buffer to the endpoint
+/// FIFO
+/// \param bEndpoint Number of the endpoint which is sending data.
+//------------------------------------------------------------------------------
+static char UDP_MblWriteFifo(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+ USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->currBuffer]);
+ signed int size;
+
+ volatile unsigned char * pBytes;
+ volatile char bufferEnd = 1;
+
+ // Get the number of bytes to send
+ size = pEndpoint->size;
+ if (size > pBi->remaining) {
+
+ size = pBi->remaining;
+ }
+
+ TRACE_DEBUG_WP("w%d.%d ", pTransfer->currBuffer, size);
+ if (size == 0) {
+
+ return 1;
+ }
+
+ pTransfer->pLastLoaded = pBi;
+ pBytes = &(pBi->pBuffer[pBi->transferred + pBi->buffered]);
+ pBi->buffered += size;
+ bufferEnd = UDP_MblUpdate(pTransfer, pBi, size, 0);
+
+ // Write packet in the FIFO buffer
+ if (size) {
+ signed int c8 = size >> 3;
+ signed int c1 = size & 0x7;
+ //printf("%d[%x] ", pBi->transferred, pBytes);
+ for (; c8; c8 --) {
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ }
+ for (; c1; c1 --) {
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pBytes ++);
+ }
+ }
+ return bufferEnd;
+}
+/*
+//------------------------------------------------------------------------------
+/// Transfers a data payload from an endpoint FIFO to the current transfer
+/// buffer, if NULL packet received, the current buffer is ENDed.
+/// \param bEndpoint Endpoint number.
+/// \param wPacketSize Size of received data packet
+/// \return 1 if the buffer ENDed.
+//------------------------------------------------------------------------------
+static char UDP_MblReadFifo(unsigned char bEndpoint, unsigned short wPacketSize)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+ USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->currBuffer]);
+ char bufferEnd;
+
+ // Check that the requested size is not bigger than the remaining transfer
+ if (wPacketSize > pTransfer->remaining) {
+
+ pTransfer->buffered += wPacketSize - pTransfer->remaining;
+ wPacketSize = pTransfer->remaining;
+ }
+
+ // Update transfer descriptor information
+ pBi->transferred += wPacketSize;
+ bufferEnd = UDP_MblUpdate(pTransfer,
+ wPacketSize,
+ (wPacketSize < pEndpoint->size));
+
+ // Retrieve packet
+ if (wPacketSize) {
+ unsigned char * pBytes = &pBi->pBuffer[pBi->transferred];
+ signed int c8 = wPacketSize >> 3;
+ signed int c1 = wPacketSize & 0x7;
+ for (; c8; c8 --) {
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ }
+ for (; c1; c1 --) {
+ *(pBytes ++) = AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ }
+ }
+ return bufferEnd;
+}
+*/
+//------------------------------------------------------------------------------
+/// Transfers a data payload from the current tranfer buffer to the endpoint
+/// FIFO
+/// \param bEndpoint Number of the endpoint which is sending data.
+//------------------------------------------------------------------------------
+static void UDP_WritePayload(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+ signed int size;
+
+ // Get the number of bytes to send
+ size = pEndpoint->size;
+ if (size > pTransfer->remaining) {
+
+ size = pTransfer->remaining;
+ }
+
+ // Update transfer descriptor information
+ pTransfer->buffered += size;
+ pTransfer->remaining -= size;
+
+ // Write packet in the FIFO buffer
+ while (size > 0) {
+
+ AT91C_BASE_UDP->UDP_FDR[bEndpoint] = *(pTransfer->pData);
+ pTransfer->pData++;
+ size--;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from an endpoint FIFO to the current transfer buffer
+/// \param bEndpoint Endpoint number.
+/// \param wPacketSize Size of received data packet
+//------------------------------------------------------------------------------
+static void UDP_ReadPayload(unsigned char bEndpoint, int wPacketSize)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Check that the requested size is not bigger than the remaining transfer
+ if (wPacketSize > pTransfer->remaining) {
+
+ pTransfer->buffered += wPacketSize - pTransfer->remaining;
+ wPacketSize = pTransfer->remaining;
+ }
+
+ // Update transfer descriptor information
+ pTransfer->remaining -= wPacketSize;
+ pTransfer->transferred += wPacketSize;
+
+ // Retrieve packet
+ while (wPacketSize > 0) {
+
+ *(pTransfer->pData) = (char) AT91C_BASE_UDP->UDP_FDR[bEndpoint];
+ pTransfer->pData++;
+ wPacketSize--;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Received SETUP packet from endpoint 0 FIFO
+/// \param pRequest Generic USB SETUP request sent over Control endpoints
+//------------------------------------------------------------------------------
+static void UDP_ReadRequest(USBGenericRequest *pRequest)
+{
+ unsigned char *pData = (unsigned char *)pRequest;
+ unsigned int i;
+
+ // Copy packet
+ for (i = 0; i < 8; i++) {
+
+ *pData = (unsigned char) AT91C_BASE_UDP->UDP_FDR[0];
+ pData++;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reset all endpoint transfer descriptors
+//------------------------------------------------------------------------------
+static void UDP_ResetEndpoints( void )
+{
+ Endpoint *pEndpoint;
+ Transfer *pTransfer;
+ unsigned char bEndpoint;
+
+ // Reset the transfer descriptor of every endpoint
+ for (bEndpoint = 0; bEndpoint < CHIP_USB_NUMENDPOINTS; bEndpoint++) {
+
+ pEndpoint = &(endpoints[bEndpoint]);
+ pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Reset endpoint transfer descriptor
+ pTransfer->pData = 0;
+ pTransfer->transferred = -1;
+ pTransfer->buffered = -1;
+ pTransfer->remaining = -1;
+ pTransfer->fCallback = 0;
+ pTransfer->pArgument = 0;
+
+ // Reset endpoint state
+ pEndpoint->bank = 0;
+ pEndpoint->state = UDP_ENDPOINT_DISABLED;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Disable all endpoints (except control endpoint 0), aborting current
+/// transfers if necessary
+//------------------------------------------------------------------------------
+static void UDP_DisableEndpoints( void )
+
+{
+ unsigned char bEndpoint;
+
+ // Disable each endpoint, terminating any pending transfer
+ // Control endpoint 0 is not disabled
+ for (bEndpoint = 1; bEndpoint < CHIP_USB_NUMENDPOINTS; bEndpoint++) {
+
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
+ endpoints[bEndpoint].state = UDP_ENDPOINT_DISABLED;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Checks if an ongoing transfer on an endpoint has been completed.
+/// \param bEndpoint Endpoint number.
+/// \return 1 if the current transfer on the given endpoint is complete;
+/// otherwise 0.
+//------------------------------------------------------------------------------
+static unsigned char UDP_IsTransferFinished(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Check if it is a Control endpoint
+ // -> Control endpoint must always finish their transfer with a zero-length
+ // packet
+ if ((AT91C_BASE_UDP->UDP_CSR[bEndpoint] & AT91C_UDP_EPTYPE)
+ == AT91C_UDP_EPTYPE_CTRL) {
+
+ return (pTransfer->buffered < pEndpoint->size);
+ }
+ // Other endpoints only need to transfer all the data
+ else {
+
+ return (pTransfer->buffered <= pEndpoint->size)
+ && (pTransfer->remaining == 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Endpoint interrupt handler.
+/// Handle IN/OUT transfers, received SETUP packets and STALLing
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDP_EndpointHandler(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+ MblTransfer *pMblt = (MblTransfer*)&(pEndpoint->transfer);
+ unsigned int status = AT91C_BASE_UDP->UDP_CSR[bEndpoint];
+ unsigned short wPacketSize;
+ USBGenericRequest request;
+
+ TRACE_DEBUG_WP("E%d ", bEndpoint);
+ TRACE_DEBUG_WP("st:0x%X ", status);
+
+ // Handle interrupts
+ // IN packet sent
+ if ((status & AT91C_UDP_TXCOMP) != 0) {
+
+ TRACE_DEBUG_WP("Wr ");
+
+ // Check that endpoint was in MBL Sending state
+ if (pEndpoint->state == UDP_ENDPOINT_SENDINGM) {
+
+ USBDTransferBuffer * pMbli = pMblt->pLastLoaded;
+ unsigned char bufferEnd = 0;
+
+ TRACE_DEBUG_WP("TxM%d.%d ", pMblt->allUsed, pMbli->buffered);
+
+ // End of transfer ?
+ if (pMblt->allUsed && pMbli->buffered == 0) {
+
+ pMbli->transferred += pMbli->buffered;
+ pMbli->buffered = 0;
+
+ // Disable interrupt
+ AT91C_BASE_UDP->UDP_IDR = 1 << bEndpoint;
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+ }
+ else {
+
+ // Transfer remaining data
+ TRACE_DEBUG_WP("%d ", pEndpoint->size);
+
+ if (pMbli->buffered > pEndpoint->size) {
+ pMbli->transferred += pEndpoint->size;
+ pMbli->buffered -= pEndpoint->size;
+ }
+ else {
+ pMbli->transferred += pMbli->buffered;
+ pMbli->buffered = 0;
+ }
+
+ // Send next packet
+ if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) == 1) {
+
+ // No double buffering
+ bufferEnd = UDP_MblWriteFifo(bEndpoint);
+ SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+ CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+ }
+ else {
+ // Double buffering
+ SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+ CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+ bufferEnd = UDP_MblWriteFifo(bEndpoint);
+ }
+
+ if (bufferEnd && pMblt->fCallback) {
+ ((MblTransferCallback) pTransfer->fCallback)
+ (pTransfer->pArgument,
+ USBD_STATUS_PARTIAL_DONE,
+ 1);
+ }
+ }
+ }
+ // Check that endpoint was in Sending state
+ else if (pEndpoint->state == UDP_ENDPOINT_SENDING) {
+
+ // End of transfer ?
+ if (UDP_IsTransferFinished(bEndpoint)) {
+
+ pTransfer->transferred += pTransfer->buffered;
+ pTransfer->buffered = 0;
+
+ // Disable interrupt if this is not a control endpoint
+ if ((status & AT91C_UDP_EPTYPE) != AT91C_UDP_EPTYPE_CTRL) {
+
+ AT91C_BASE_UDP->UDP_IDR = 1 << bEndpoint;
+ }
+
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+ }
+ else {
+
+ // Transfer remaining data
+ TRACE_DEBUG_WP(" %d ", pEndpoint->size);
+
+ pTransfer->transferred += pEndpoint->size;
+ pTransfer->buffered -= pEndpoint->size;
+
+ // Send next packet
+ if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) == 1) {
+
+ // No double buffering
+ UDP_WritePayload(bEndpoint);
+ SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+ CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+ }
+ else {
+ // Double buffering
+ SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+ CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+ UDP_WritePayload(bEndpoint);
+ }
+ }
+ }
+ else {
+ // Acknowledge interrupt
+ TRACE_ERROR("Error Wr%d, %x\n\r", bEndpoint, pEndpoint->state);
+ CLEAR_CSR(bEndpoint, AT91C_UDP_TXCOMP);
+ }
+ }
+
+ // OUT packet received
+ if ((status & UDP_RXDATA) != 0) {
+
+ TRACE_DEBUG_WP("Rd ");
+
+ // Check that the endpoint is in Receiving state
+ if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) {
+
+ // Check if an ACK has been received on a Control endpoint
+ if (((status & AT91C_UDP_EPTYPE) == AT91C_UDP_EPTYPE_CTRL)
+ && ((status & AT91C_UDP_RXBYTECNT) == 0)) {
+
+ // Acknowledge the data and finish the current transfer
+ UDP_ClearRxFlag(bEndpoint);
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ // Check if the data has been STALLed
+ else if ((status & AT91C_UDP_FORCESTALL) != 0) {
+
+ // Discard STALLed data
+ TRACE_DEBUG_WP("Discard ");
+ UDP_ClearRxFlag(bEndpoint);
+ }
+ // NAK the data
+ else {
+
+ TRACE_DEBUG_WP("Nak ");
+ AT91C_BASE_UDP->UDP_IDR = 1 << bEndpoint;
+ }
+ }
+ // Endpoint is in Read state
+ else {
+
+ // Retrieve data and store it into the current transfer buffer
+ wPacketSize = (unsigned short) (status >> 16);
+ TRACE_DEBUG_WP("%d ", wPacketSize);
+ UDP_ReadPayload(bEndpoint, wPacketSize);
+ UDP_ClearRxFlag(bEndpoint);
+
+ // Check if the transfer is finished
+ if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) {
+
+ // Disable interrupt if this is not a control endpoint
+ if ((status & AT91C_UDP_EPTYPE) != AT91C_UDP_EPTYPE_CTRL) {
+
+ AT91C_BASE_UDP->UDP_IDR = 1 << bEndpoint;
+ }
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ }
+ }
+
+ // STALL sent
+ if ((status & AT91C_UDP_STALLSENT) != 0) {
+
+ TRACE_WARNING( "Sta 0x%X [%d] ", status, bEndpoint);
+
+ // If the endpoint is not halted, clear the STALL condition
+ CLEAR_CSR(bEndpoint, AT91C_UDP_STALLSENT);
+ if (pEndpoint->state != UDP_ENDPOINT_HALTED) {
+
+ TRACE_WARNING( "_ " );
+ CLEAR_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+ }
+ }
+
+ // SETUP packet received
+ if ((status & AT91C_UDP_RXSETUP) != 0) {
+
+ TRACE_DEBUG_WP("Stp ");
+
+ // If a transfer was pending, complete it
+ // Handles the case where during the status phase of a control write
+ // transfer, the host receives the device ZLP and ack it, but the ack
+ // is not received by the device
+ if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ // Copy the setup packet
+ UDP_ReadRequest(&request);
+
+ // Set the DIR bit before clearing RXSETUP in Control IN sequence
+ if (USBGenericRequest_GetDirection(&request) == USBGenericRequest_IN) {
+
+ SET_CSR(bEndpoint, AT91C_UDP_DIR);
+ }
+ // Acknowledge setup packet
+ CLEAR_CSR(bEndpoint, AT91C_UDP_RXSETUP);
+
+ // Forward the request to the upper layer
+ USBDCallbacks_RequestReceived(&request);
+ }
+
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+/// USB device interrupt handler
+/// Manages device resume, suspend, end of bus reset.
+/// Forwards endpoint interrupts to the appropriate handler.
+//------------------------------------------------------------------------------
+void USBD_IrqHandler(void)
+{
+ unsigned int status;
+ int eptnum = 0;
+
+ // Get interrupt status
+ // Some interrupts may get masked depending on the device state
+ status = AT91C_BASE_UDP->UDP_ISR;
+ status &= AT91C_BASE_UDP->UDP_IMR;
+
+ if (deviceState < USBD_STATE_POWERED) {
+
+ status &= AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
+ AT91C_BASE_UDP->UDP_ICR = ~status;
+ }
+
+ // Return immediately if there is no interrupt to service
+ if (status == 0) {
+
+ TRACE_DEBUG_WP(".\n\r");
+ return;
+ }
+
+ // Toggle USB LED if the device is active
+ if (deviceState >= USBD_STATE_POWERED) {
+
+ LED_Set(USBD_LEDUSB);
+ }
+
+ // Service interrupts
+
+ //// Start Of Frame (SOF)
+ //if (ISSET(dStatus, AT91C_UDP_SOFINT)) {
+ //
+ // TRACE_DEBUG("SOF");
+ //
+ // // Invoke the SOF callback
+ // USB_StartOfFrameCallback(pUsb);
+ //
+ // // Acknowledge interrupt
+ // AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_SOFINT;
+ // dStatus &= ~AT91C_UDP_SOFINT;
+ //}
+
+ // Resume
+ if ((status & (AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM)) != 0) {
+
+ TRACE_INFO_WP("Res ");
+
+ // Don't do anything if the device was not suspended
+ if (deviceState == USBD_STATE_SUSPENDED) {
+
+ // The device enters its previous state
+ UDP_EnablePeripheralClock();
+ UDP_EnableUsbClock();
+
+ // Enable the transceiver if the device was past the Default
+ // state
+ deviceState = previousDeviceState;
+ if (deviceState >= USBD_STATE_DEFAULT) {
+
+ UDP_EnableTransceiver();
+
+ // Invoke the Resume callback
+ USBDCallbacks_Resumed();
+ }
+ }
+
+ // Clear and disable resume interrupts
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_WAKEUP
+ | AT91C_UDP_RXRSM
+ | AT91C_UDP_RXSUSP;
+ AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
+ }
+
+ // Suspend
+ // This interrupt is always treated last (hence the '==')
+ if (status == AT91C_UDP_RXSUSP) {
+
+ TRACE_INFO_WP("Susp ");
+
+ // Don't do anything if the device is already suspended
+ if (deviceState != USBD_STATE_SUSPENDED) {
+
+ // The device enters the Suspended state
+ // Enable wakeup
+ AT91C_BASE_UDP->UDP_IER = AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
+
+ // Acknowledge interrupt
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_RXSUSP;
+
+ // Switch to the Suspended state
+ previousDeviceState = deviceState;
+ deviceState = USBD_STATE_SUSPENDED;
+ // Invoke the Suspended callback
+ USBDCallbacks_Suspended();
+ UDP_DisableTransceiver();
+ UDP_DisablePeripheralClock();
+ UDP_DisableUsbClock();
+ }
+ }
+ #if 0
+ // Resume
+ else if ((status & (AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM)) != 0) {
+
+ TRACE_INFO_WP("Res ");
+
+ // Don't do anything if the device was not suspended
+ if (deviceState == USBD_STATE_SUSPENDED) {
+
+ // The device enters its previous state
+ UDP_EnablePeripheralClock();
+ UDP_EnableUsbClock();
+
+ // Enable the transceiver if the device was past the Default
+ // state
+ deviceState = previousDeviceState;
+ if (deviceState >= USBD_STATE_DEFAULT) {
+
+ UDP_EnableTransceiver();
+
+ // Invoke the Resume callback
+ USBDCallbacks_Resumed();
+ }
+ }
+
+ // Clear and disable resume interrupts
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_WAKEUP
+ | AT91C_UDP_RXRSM
+ | AT91C_UDP_RXSUSP;
+ AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM;
+ }
+ #endif
+ // End of bus reset
+ else if ((status & AT91C_UDP_ENDBUSRES) != 0) {
+
+ TRACE_INFO_WP("EoBRes ");
+
+ // The device enters the Default state
+ deviceState = USBD_STATE_DEFAULT;
+ UDP_EnableTransceiver();
+ UDP_ResetEndpoints();
+ UDP_DisableEndpoints();
+ USBD_ConfigureEndpoint(0);
+
+ // Flush and enable the Suspend interrupt
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_WAKEUP
+ | AT91C_UDP_RXRSM
+ | AT91C_UDP_RXSUSP;
+ AT91C_BASE_UDP->UDP_IER = AT91C_UDP_RXSUSP;
+
+ //// Enable the Start Of Frame (SOF) interrupt if needed
+ //if (pUsb->pCallbacks->startOfFrame != 0) {
+ //
+ // AT91C_BASE_UDP->UDP_IER = AT91C_UDP_SOFINT;
+ //}
+
+ // Invoke the Reset callback
+ USBDCallbacks_Reset();
+
+ // Acknowledge end of bus reset interrupt
+ AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
+ }
+ // Endpoint interrupts
+ else {
+
+ status &= ((1 << CHIP_USB_NUMENDPOINTS) - 1);
+ while (status != 0) {
+
+ // Check if endpoint has a pending interrupt
+ if ((status & (1 << eptnum)) != 0) {
+
+ UDP_EndpointHandler(eptnum);
+ status &= ~(1 << eptnum);
+
+ if (status != 0) {
+
+ TRACE_INFO_WP("\n\r - ");
+ }
+ }
+ eptnum++;
+ }
+ }
+
+ // Toggle LED back to its previous state
+ TRACE_DEBUG_WP("!");
+ TRACE_INFO_WP("\n\r");
+ if (deviceState >= USBD_STATE_POWERED) {
+
+ LED_Clear(USBD_LEDUSB);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Configures an endpoint according to its Endpoint Descriptor.
+/// \param pDescriptor Pointer to an Endpoint descriptor.
+//------------------------------------------------------------------------------
+void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor)
+{
+ Endpoint *pEndpoint;
+ unsigned char bEndpoint;
+ unsigned char bType;
+ unsigned char bEndpointDir;
+
+ // NULL descriptor -> Control endpoint 0
+ if (pDescriptor == 0) {
+
+ bEndpoint = 0;
+ pEndpoint = &(endpoints[bEndpoint]);
+ bType= USBEndpointDescriptor_CONTROL;
+ bEndpointDir = 0;
+ pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0);
+ }
+ else {
+
+ bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
+ pEndpoint = &(endpoints[bEndpoint]);
+ bType = USBEndpointDescriptor_GetType(pDescriptor);
+ bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
+ pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
+ }
+
+ // Abort the current transfer is the endpoint was configured and in
+ // Write or Read state
+ if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING)
+ || (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDINGM)) {
+
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
+ }
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Reset Endpoint Fifos
+ AT91C_BASE_UDP->UDP_RSTEP |= (1 << bEndpoint);
+ AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << bEndpoint);
+
+ // Configure endpoint
+ SET_CSR(bEndpoint, (unsigned int)AT91C_UDP_EPEDS
+ | (bType << 8) | (bEndpointDir << 10));
+ if (bType != USBEndpointDescriptor_CONTROL) {
+
+ }
+ else {
+
+ AT91C_BASE_UDP->UDP_IER = (1 << bEndpoint);
+ }
+
+ TRACE_INFO_WP("CfgEpt%d ", bEndpoint);
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through a USB endpoint. Sets up the transfer descriptor,
+/// writes one or two data payloads (depending on the number of FIFO bank
+/// for the endpoint) and then starts the actual transfer. The operation is
+/// complete when all the data has been sent.
+///
+/// *If the size of the buffer is greater than the size of the endpoint
+/// (or twice the size if the endpoint has two FIFO banks), then the buffer
+/// must be kept allocated until the transfer is finished*. This means that
+/// it is not possible to declare it on the stack (i.e. as a local variable
+/// of a function which returns after starting a transfer).
+///
+/// \param bEndpoint Endpoint number.
+/// \param pData Pointer to a buffer with the data to send.
+/// \param dLength Size of the data buffer.
+/// \param fCallback Optional callback function to invoke when the transfer is
+/// complete.
+/// \param pArgument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the transfer has been started;
+/// otherwise, the corresponding error status code.
+//------------------------------------------------------------------------------
+char USBD_Write( unsigned char bEndpoint,
+ const void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Check that the endpoint is in Idle state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ return USBD_STATUS_LOCKED;
+ }
+ TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength);
+
+ // Setup the transfer descriptor
+ pTransfer->pData = (void *) pData;
+ pTransfer->remaining = dLength;
+ pTransfer->buffered = 0;
+ pTransfer->transferred = 0;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+
+ // Send the first packet
+ pEndpoint->state = UDP_ENDPOINT_SENDING;
+ while((AT91C_BASE_UDP->UDP_CSR[bEndpoint]&AT91C_UDP_TXPKTRDY)==AT91C_UDP_TXPKTRDY);
+ UDP_WritePayload(bEndpoint);
+ SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+
+ // If double buffering is enabled and there is data remaining,
+ // prepare another packet
+ if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) && (pTransfer->remaining > 0)) {
+
+ UDP_WritePayload(bEndpoint);
+ }
+
+ // Enable interrupt on endpoint
+ AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Sends data frames through a USB endpoint. Sets up the transfer descriptor
+/// list, writes one or two data payloads (depending on the number of FIFO bank
+/// for the endpoint) and then starts the actual transfer. The operation is
+/// complete when all the data has been sent.
+///
+/// *If the size of the frame is greater than the size of the endpoint
+/// (or twice the size if the endpoint has two FIFO banks), then the buffer
+/// must be kept allocated until the frame is finished*. This means that
+/// it is not possible to declare it on the stack (i.e. as a local variable
+/// of a function which returns after starting a transfer).
+///
+/// \param bEndpoint Endpoint number.
+/// \param pMbl Pointer to a frame (USBDTransferBuffer) list that describes
+/// the buffer list to send.
+/// \param wListSize Size of the frame list.
+/// \param bCircList Circle the list.
+/// \param wStartNdx For circled list only, the first buffer index to transfer.
+/// \param fCallback Optional callback function to invoke when the transfer is
+/// complete.
+/// \param pArgument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the transfer has been started;
+/// otherwise, the corresponding error status code.
+/// \see USBDTransferBuffer, MblTransferCallback, USBD_MblReuse
+//------------------------------------------------------------------------------
+char USBD_MblWrite( unsigned char bEndpoint,
+ void *pMbl,
+ unsigned short wListSize,
+ unsigned char bCircList,
+ unsigned short wStartNdx,
+ MblTransferCallback fCallback,
+ void *pArgument )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+ unsigned short i;
+
+ // EP0 is not suitable for Mbl
+ if (bEndpoint == 0) {
+
+ return USBD_STATUS_INVALID_PARAMETER;
+ }
+
+ // Check that the endpoint is in Idle state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ return USBD_STATUS_LOCKED;
+ }
+ pEndpoint->state = UDP_ENDPOINT_SENDINGM;
+
+ TRACE_DEBUG_WP("WriteM%d(0x%x,%d) ", bEndpoint, pMbl, wListSize);
+
+ // Start from first if not circled list
+ if (!bCircList) wStartNdx = 0;
+
+ // Setup the transfer descriptor
+ pTransfer->pMbl = (USBDTransferBuffer*)pMbl;
+ pTransfer->listSize = wListSize;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+ pTransfer->currBuffer = wStartNdx;
+ pTransfer->freedBuffer = 0;
+ pTransfer->pLastLoaded = &(((USBDTransferBuffer*)pMbl)[wStartNdx]);
+ pTransfer->circList = bCircList;
+ pTransfer->allUsed = 0;
+
+ // Clear all buffer
+ for (i = 0; i < wListSize; i ++) {
+
+ pTransfer->pMbl[i].transferred = 0;
+ pTransfer->pMbl[i].buffered = 0;
+ pTransfer->pMbl[i].remaining = pTransfer->pMbl[i].size;
+ }
+
+ // Send the first packet
+ while((AT91C_BASE_UDP->UDP_CSR[bEndpoint]&AT91C_UDP_TXPKTRDY)
+ ==AT91C_UDP_TXPKTRDY);
+ UDP_MblWriteFifo(bEndpoint);
+ SET_CSR(bEndpoint, AT91C_UDP_TXPKTRDY);
+
+ // If double buffering is enabled and there is data remaining,
+ // prepare another packet
+ if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1)
+ && (pTransfer->pMbl[pTransfer->currBuffer].remaining > 0)) {
+
+ UDP_MblWriteFifo(bEndpoint);
+ }
+
+ // Enable interrupt on endpoint
+ AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Reads incoming data on an USB endpoint This methods sets the transfer
+/// descriptor and activate the endpoint interrupt. The actual transfer is
+/// then carried out by the endpoint interrupt handler. The Read operation
+/// finishes either when the buffer is full, or a short packet (inferior to
+/// endpoint maximum size) is received.
+///
+/// *The buffer must be kept allocated until the transfer is finished*.
+/// \param bEndpoint Endpoint number.
+/// \param pData Pointer to a data buffer.
+/// \param dLength Size of the data buffer in bytes.
+/// \param fCallback Optional end-of-transfer callback function.
+/// \param pArgument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the read operation has been started;
+/// otherwise, the corresponding error code.
+//------------------------------------------------------------------------------
+char USBD_Read(unsigned char bEndpoint,
+ void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Return if the endpoint is not in IDLE state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ // Endpoint enters Receiving state
+ pEndpoint->state = UDP_ENDPOINT_RECEIVING;
+ TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+
+ // Set the transfer descriptor
+ pTransfer->pData = pData;
+ pTransfer->remaining = dLength;
+ pTransfer->buffered = 0;
+ pTransfer->transferred = 0;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+
+ // Enable interrupt on endpoint
+ AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Reuse first used/released buffer with new buffer address and size to be used
+/// in transfer again. Only valid when frame list is ringed. Can be used for
+/// both read & write.
+/// \param bEndpoint Endpoint number.
+/// \param pNewBuffer Pointer to new buffer with data to send (0 to keep last).
+/// \param wNewSize Size of the data buffer
+//------------------------------------------------------------------------------
+char USBD_MblReuse( unsigned char bEndpoint,
+ unsigned char *pNewBuffer,
+ unsigned short wNewSize )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+ USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->freedBuffer]);
+
+ TRACE_DEBUG_WP("MblReuse(%d), st%x, circ%d\n\r",
+ bEndpoint, pEndpoint->state, pTransfer->circList);
+
+ // Only for Multi-buffer-circle list
+ if (bEndpoint != 0
+ && (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM
+ || pEndpoint->state == UDP_ENDPOINT_SENDINGM)
+ && pTransfer->circList) {
+ }
+ else {
+
+ return USBD_STATUS_WRONG_STATE;
+ }
+
+ // Check if there is freed buffer
+ if (pTransfer->freedBuffer == pTransfer->currBuffer
+ && !pTransfer->allUsed) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ // Update transfer information
+ if ((++ pTransfer->freedBuffer) == pTransfer->listSize)
+ pTransfer->freedBuffer = 0;
+ if (pNewBuffer) {
+ pBi->pBuffer = pNewBuffer;
+ pBi->size = wNewSize;
+ }
+ pBi->buffered = 0;
+ pBi->transferred = 0;
+ pBi->remaining = pBi->size;
+
+ // At least one buffer is not processed
+ pTransfer->allUsed = 0;
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Sets the HALT feature on the given endpoint (if not already in this state).
+/// \param bEndpoint Endpoint number.
+//------------------------------------------------------------------------------
+void USBD_Halt(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check that endpoint is enabled and not already in Halt state
+ if ((pEndpoint->state != UDP_ENDPOINT_DISABLED)
+ && (pEndpoint->state != UDP_ENDPOINT_HALTED)) {
+
+ TRACE_DEBUG_WP("Halt%d ", bEndpoint);
+
+ // Abort the current transfer if necessary
+ UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
+
+ // Put endpoint into Halt state
+ SET_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+ pEndpoint->state = UDP_ENDPOINT_HALTED;
+
+ // Enable the endpoint interrupt
+ AT91C_BASE_UDP->UDP_IER = 1 << bEndpoint;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the Halt feature on the given endpoint.
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Unhalt(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check if the endpoint is enabled
+ //if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
+ if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+
+ TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
+
+ // Return endpoint to Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Clear FORCESTALL flag
+ CLEAR_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+
+ // Reset Endpoint Fifos, beware this is a 2 steps operation
+ AT91C_BASE_UDP->UDP_RSTEP |= 1 << bEndpoint;
+ AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << bEndpoint);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current Halt status of an endpoint.
+/// \param bEndpoint Index of endpoint
+/// \return 1 if the endpoint is currently halted; otherwise 0
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHalted(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ unsigned char status = 0;
+
+ if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+
+ status = 1;
+ }
+ return( status );
+}
+
+//------------------------------------------------------------------------------
+/// Indicates if the device is running in high or full-speed. Always returns 0
+/// since UDP does not support high-speed mode.
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHighSpeed(void)
+{
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+/// Causes the given endpoint to acknowledge the next packet it receives
+/// with a STALL handshake.
+/// \param bEndpoint Endpoint number.
+/// \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
+//------------------------------------------------------------------------------
+unsigned char USBD_Stall(unsigned char bEndpoint)
+
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check that endpoint is in Idle state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ TRACE_WARNING("UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
+ return USBD_STATUS_LOCKED;
+ }
+
+ TRACE_DEBUG_WP("Stall%d ", bEndpoint);
+ SET_CSR(bEndpoint, AT91C_UDP_FORCESTALL);
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Starts a remote wake-up procedure.
+//------------------------------------------------------------------------------
+void USBD_RemoteWakeUp(void)
+{
+ // Device is NOT suspended
+ if (deviceState != USBD_STATE_SUSPENDED) {
+
+ TRACE_WARNING("USBD_RemoteWakeUp: Device is not suspended\n\r");
+ return;
+ }
+
+
+ UDP_EnablePeripheralClock();
+ UDP_EnableUsbClock();
+ UDP_EnableTransceiver();
+
+ TRACE_INFO_WP("RWUp ");
+
+ // Activates a remote wakeup (edge on ESR), then clear ESR
+ AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_ESR;
+ AT91C_BASE_UDP->UDP_GLBSTATE &= ~AT91C_UDP_ESR;
+}
+
+//------------------------------------------------------------------------------
+/// Sets the device address to the given value.
+/// \param address New device address.
+//------------------------------------------------------------------------------
+void USBD_SetAddress(unsigned char address)
+{
+ TRACE_INFO_WP("SetAddr(%d) ", address);
+
+ // Set address
+ AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | address;
+
+ // If the address is 0, the device returns to the Default state
+ if (address == 0) {
+
+ AT91C_BASE_UDP->UDP_GLBSTATE = 0;
+ deviceState = USBD_STATE_DEFAULT;
+ }
+ // If the address is non-zero, the device enters the Address state
+ else {
+
+ AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
+ deviceState = USBD_STATE_ADDRESS;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sets the current device configuration.
+/// \param cfgnum - Configuration number to set.
+//------------------------------------------------------------------------------
+void USBD_SetConfiguration(unsigned char cfgnum)
+{
+ TRACE_INFO_WP("SetCfg(%d) ", cfgnum);
+
+ // If the configuration number if non-zero, the device enters the
+ // Configured state
+ if (cfgnum != 0) {
+
+ // Enter Configured state
+ deviceState = USBD_STATE_CONFIGURED;
+ AT91C_BASE_UDP->UDP_GLBSTATE |= AT91C_UDP_CONFG;
+ }
+ // If the configuration number is zero, the device goes back to the Address
+ // state
+ else {
+
+ deviceState = USBD_STATE_ADDRESS;
+ AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
+
+ // Abort all transfers
+ UDP_DisableEndpoints();
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Connects the pull-up on the D+ line of the USB.
+//------------------------------------------------------------------------------
+void USBD_Connect(void)
+{
+ TRACE_DEBUG("Conn ");
+
+#if defined(CHIP_USB_PULLUP_EXTERNAL)
+ const Pin pinPullUp = PIN_USB_PULLUP;
+ if (pinPullUp.type == PIO_OUTPUT_0) {
+
+ PIO_Set(&pinPullUp);
+ }
+ else {
+
+ PIO_Clear(&pinPullUp);
+ }
+#elif defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_UDP->UDP_TXVC |= AT91C_UDP_PUON;
+#elif defined(CHIP_USB_PULLUP_MATRIX)
+ AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;
+#elif !defined(CHIP_USB_PULLUP_ALWAYSON)
+ #error Unsupported pull-up type.
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Disconnects the pull-up from the D+ line of the USB.
+//------------------------------------------------------------------------------
+void USBD_Disconnect(void)
+{
+ TRACE_DEBUG("Disc ");
+
+#if defined(CHIP_USB_PULLUP_EXTERNAL)
+ const Pin pinPullUp = PIN_USB_PULLUP;
+ if (pinPullUp.type == PIO_OUTPUT_0) {
+
+ PIO_Clear(&pinPullUp);
+ }
+ else {
+
+ PIO_Set(&pinPullUp);
+ }
+#elif defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
+#elif defined(CHIP_USB_PULLUP_MATRIX)
+ AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+#elif !defined(CHIP_USB_PULLUP_ALWAYSON)
+ #error Unsupported pull-up type.
+#endif
+
+ // Device returns to the Powered state
+ if (deviceState > USBD_STATE_POWERED) {
+
+ deviceState = USBD_STATE_POWERED;
+ }
+
+ if (previousDeviceState > USBD_STATE_POWERED) {
+
+ previousDeviceState = USBD_STATE_POWERED;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Initializes the USB driver.
+//------------------------------------------------------------------------------
+void USBD_Init(void)
+{
+ TRACE_INFO_WP("USBD_Init\n\r");
+
+ // Reset endpoint structures
+ UDP_ResetEndpoints();
+
+ // Configure the pull-up on D+ and disconnect it
+#if defined(CHIP_USB_PULLUP_EXTERNAL)
+ const Pin pinPullUp = PIN_USB_PULLUP;
+ PIO_Configure(&pinPullUp, 1);
+#elif defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_UDP->UDP_TXVC &= ~AT91C_UDP_PUON;
+#elif defined(CHIP_USB_PULLUP_MATRIX)
+ AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+#elif !defined(CHIP_USB_PULLUP_ALWAYSON)
+ #error Missing pull-up definition.
+#endif
+
+ // Device is in the Attached state
+ deviceState = USBD_STATE_SUSPENDED;
+ previousDeviceState = USBD_STATE_POWERED;
+ UDP_EnablePeripheralClock();
+ UDP_EnableUsbClock();
+
+ AT91C_BASE_UDP->UDP_IDR = 0xFE;
+
+ AT91C_BASE_UDP->UDP_IER = AT91C_UDP_WAKEUP;
+
+ // Configure interrupts
+ USBDCallbacks_Initialized();
+}
+
+//------------------------------------------------------------------------------
+/// Configure USB Speed, should be invoked before USB attachment.
+/// \param forceFS Force to use FS mode.
+//------------------------------------------------------------------------------
+void USBD_ConfigureSpeed(unsigned char forceFS)
+{
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current state of the USB device.
+/// \return Device current state.
+//------------------------------------------------------------------------------
+unsigned char USBD_GetState(void)
+{
+ return deviceState;
+}
+
diff --git a/usb/device/core/USBD_UDPHS.c b/usb/device/core/USBD_UDPHS.c new file mode 100644 index 0000000..f02fa55 --- /dev/null +++ b/usb/device/core/USBD_UDPHS.c @@ -0,0 +1,2384 @@ +/* ----------------------------------------------------------------------------
+ * 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 "USBD.h"
+#include "USBDCallbacks.h"
+#include "USBDDriver.h"
+#include <board.h>
+#include <pio/pio.h>
+#include <utility/trace.h>
+#include <utility/led.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBFeatureRequest.h>
+
+#include <stdio.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Maximum number of endpoints interrupts.
+#define NUM_IT_MAX \
+ (AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_EPT_NBR_MAX)
+/// Maximum number of endpoint DMA interrupts
+#define NUM_IT_MAX_DMA \
+ ((AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_DMA_CHANNEL_NBR)>>4)
+/// Bits that should be shifted to access DMA control bits.
+#define SHIFT_DMA 24
+/// Bits that should be shifted to access interrupt bits.
+#define SHIFT_INTERUPT 8
+
+/// Max size of the FMA FIFO
+#define DMA_MAX_FIFO_SIZE 65536
+
+#define EPT_VIRTUAL_SIZE 16384
+
+//------------------------------------------------------------------------------
+/// \page "Endpoint states"
+/// This page lists the endpoint states.
+/// !States
+// - UDP_ENDPOINT_DISABLED
+// - UDP_ENDPOINT_HALTED
+// - UDP_ENDPOINT_IDLE
+// - UDP_ENDPOINT_SENDING
+// - UDP_ENDPOINT_RECEIVING
+
+/// Endpoint states: Endpoint is disabled
+#define UDP_ENDPOINT_DISABLED 0
+/// Endpoint states: Endpoint is halted (i.e. STALLs every request)
+#define UDP_ENDPOINT_HALTED 1
+/// Endpoint states: Endpoint is idle (i.e. ready for transmission)
+#define UDP_ENDPOINT_IDLE 2
+/// Endpoint states: Endpoint is sending data
+#define UDP_ENDPOINT_SENDING 3
+/// Endpoint states: Endpoint is receiving data
+#define UDP_ENDPOINT_RECEIVING 4
+/// Endpoint states: Endpoint is sending MBL
+#define UDP_ENDPOINT_SENDINGM 5
+/// Endpoint states: Endpoint is receiving MBL
+#define UDP_ENDPOINT_RECEIVINGM 6
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+/// Check if DMA is used to transfer data
+#define UDP_IsDmaUsed(ep) (CHIP_USB_ENDPOINTS_DMA(ep))
+
+//------------------------------------------------------------------------------
+// Structures
+//------------------------------------------------------------------------------
+
+/// Describes an ongoing transfer on a UDP endpoint.
+typedef struct
+{
+ /// Pointer to a data buffer used for emission/reception.
+ char *pData;
+ /// Number of bytes which have been written into the UDP internal FIFO
+ /// buffers.
+ int buffered;
+ /// Number of bytes which have been sent/received.
+ int transferred;
+ /// Number of bytes which have not been buffered/transferred yet.
+ int remaining;
+ /// Optional callback to invoke when the transfer completes.
+ TransferCallback fCallback;
+ /// Optional argument to the callback function.
+ void *pArgument;
+} Transfer;
+
+/// Describes Multi Buffer List transfer on a UDP endpoint.
+typedef struct {
+ /// Pointer to frame list
+ USBDTransferBuffer *pMbl;
+ /// Pointer to last loaded buffer
+ USBDTransferBuffer *pLastLoaded;
+ /// List size
+ unsigned short listSize;
+ /// Current processing frame
+ unsigned short currBuffer;
+ /// First freed frame to re-use
+ unsigned short freedBuffer;
+ /// Frame setting, circle frame list
+ unsigned char circList;
+ /// All buffer listed is used
+ unsigned char allUsed;
+ /// Optional callback to invoke when the transfer completes.
+ MblTransferCallback fCallback;
+ /// Optional argument to the callback function.
+ void *pArgument;
+} MblTransfer;
+
+/// Describes DMA Link List transfer on a UDPHS endpoint.
+typedef struct {
+ /// Pointer to frame list
+ USBDDmaDescriptor *pMbl;
+ /// Pointer to current buffer
+ USBDDmaDescriptor *pCurrBuffer;
+ /// Pointer to freed buffer
+ USBDDmaDescriptor *pFreedBuffer;
+ /// List size
+ unsigned short listSize;
+ /// Frame setting, circle frame list
+ unsigned char circList;
+ /// All buffer listed is used
+ unsigned char allUsed;
+ /// Optional callback to invoke when the transfer completes.
+ MblTransferCallback fCallback;
+ /// Optional argument to the callback function.
+ void *pArgument;
+} DmaLlTransfer;
+
+//------------------------------------------------------------------------------
+/// Describes the state of an endpoint of the UDP controller.
+//------------------------------------------------------------------------------
+typedef struct
+{
+ /// Current endpoint state.
+ volatile unsigned char state;
+ /// Current reception bank (0 or 1).
+ unsigned char bank;
+ /// Maximum packet size for the endpoint.
+ unsigned short size;
+ /// Describes an ongoing transfer (if current state is either
+ /// <UDP_ENDPOINT_SENDING> or <UDP_ENDPOINT_RECEIVING>)
+ union {
+ Transfer singleTransfer;
+ MblTransfer mblTransfer;
+ DmaLlTransfer dmaTransfer;
+ } transfer;
+ /// Special case for send a ZLP
+ unsigned char sendZLP;
+} Endpoint;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Holds the internal state for each endpoint of the UDP.
+static Endpoint endpoints[CHIP_USB_NUMENDPOINTS];
+/// Device current state.
+static unsigned char deviceState;
+/// Indicates the previous device state
+static unsigned char previousDeviceState;
+
+/// 7.1.20 Test Mode Support
+/// Test codes for the USB HS test mode.
+static const char test_packet_buffer[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9
+ 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8
+ 0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
+ 0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8
+ 0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK
+};
+
+// Force HS
+static const unsigned char forceUsbFS = 0;
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Disables the BIAS of the USB controller
+//------------------------------------------------------------------------------
+static inline void UDPHS_DisableBIAS( void )
+{
+ AT91C_BASE_PMC->PMC_UCKR &= ~(unsigned int)AT91C_CKGR_BIASEN_ENABLED;
+}
+
+//------------------------------------------------------------------------------
+/// Enables the BIAS of the USB controller
+//------------------------------------------------------------------------------
+static inline void UDPHS_EnableBIAS( void )
+{
+ UDPHS_DisableBIAS();
+ AT91C_BASE_PMC->PMC_UCKR |= AT91C_CKGR_BIASEN_ENABLED;
+}
+
+//------------------------------------------------------------------------------
+/// Enable UDPHS Peripheral
+//------------------------------------------------------------------------------
+static inline void UDPHS_EnablePeripheral( void )
+{
+#if !defined (PMC_BY_HARD)
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDPHS);
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Enable UDPHS clock
+//------------------------------------------------------------------------------
+static inline void UDPHS_EnableUsbClock( void )
+{
+#if !defined (PMC_BY_HARD)
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDPHS);
+ // Enable 480MHZ
+ //AT91C_BASE_CKGR->CKGR_UCKR |= (AT91C_CKGR_PLLCOUNT & (3 << 20)) | AT91C_CKGR_UPLLEN;
+ AT91C_BASE_CKGR->CKGR_UCKR |= ((0xf << 20) & (3 << 20)) | AT91C_CKGR_UPLLEN;
+ // Wait until UTMI PLL is locked
+ while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKU) == 0);
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Disable UDPHS clock
+//------------------------------------------------------------------------------
+static inline void UDPHS_DisableUsbClock( void )
+{
+#if !defined (PMC_BY_HARD)
+ AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_UDPHS);
+ // 480MHZ
+ AT91C_BASE_CKGR->CKGR_UCKR &= ~(unsigned int)AT91C_CKGR_UPLLEN;
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Handles a completed transfer on the given endpoint, invoking the
+/// configured callback if any.
+/// \param bEndpoint Number of the endpoint for which the transfer has completed.
+/// \param bStatus Status code returned by the transfer operation
+//------------------------------------------------------------------------------
+static void UDPHS_EndOfTransfer( unsigned char bEndpoint, char bStatus )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Check that endpoint was sending or receiving data
+ if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING) ) {
+
+ TRACE_DEBUG_WP("Eo");
+ if(pEndpoint->state == UDP_ENDPOINT_SENDING) {
+ pEndpoint->sendZLP = 0;
+ }
+ // Endpoint returns in Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Invoke callback is present
+ if (pTransfer->fCallback != 0) {
+
+ ((TransferCallback) pTransfer->fCallback)
+ (pTransfer->pArgument,
+ bStatus,
+ pTransfer->transferred,
+ pTransfer->remaining + pTransfer->buffered);
+ }
+ else {
+ TRACE_DEBUG_WP("No callBack\n\r");
+ }
+ }
+ else if ( (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDINGM) ) {
+
+ MblTransfer* pMblt = (MblTransfer*)&(pEndpoint->transfer);
+ MblTransferCallback fCallback;
+ void* pArg;
+
+ TRACE_DEBUG_WP("EoMT ");
+
+ #ifdef DMA
+ { DmaLlTransfer *pDmat = (DmaLlTransfer*)&(pEndpoint->transfer);
+ fCallback = UDP_IsDmaUsed(bEndpoint) ?
+ pDmat->fCallback : pMblt->fCallback;
+ pArg = UDP_IsDmaUsed(bEndpoint) ?
+ pDmat->pArgument : pMblt->pArgument;
+ }
+ #else
+ fCallback = pMblt->fCallback;
+ pArg = pMblt->pArgument;
+ #endif
+
+ // Endpoint returns in Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+ // Invoke callback
+ if (fCallback != 0) {
+
+ (fCallback)(pArg, bStatus, 0);
+ }
+ else {
+ TRACE_DEBUG_WP("NoCB ");
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the correct RX flag in endpoint status register
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDPHS_ClearRxFlag( unsigned char bEndpoint )
+{
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_RX_BK_RDY;
+}
+
+//------------------------------------------------------------------------------
+/// Update multi-buffer-transfer descriptors.
+/// \param pTransfer Pointer to instance MblTransfer.
+/// \param size Size of bytes that processed.
+/// \param forceEnd Force the buffer END.
+/// \return 1 if current buffer ended.
+//------------------------------------------------------------------------------
+static char UDPHS_MblUpdate(MblTransfer *pTransfer,
+ USBDTransferBuffer * pBi,
+ unsigned short size,
+ unsigned char forceEnd)
+{
+ // Update transfer descriptor
+ pBi->remaining -= size;
+ // Check if current buffer ended
+ if (pBi->remaining == 0 || forceEnd) {
+
+ // Process to next buffer
+ if ((++ pTransfer->currBuffer) == pTransfer->listSize) {
+ if (pTransfer->circList) {
+ pTransfer->currBuffer = 0;
+ }
+ else {
+ pTransfer->allUsed = 1;
+ }
+ }
+ // All buffer in the list is processed
+ if (pTransfer->currBuffer == pTransfer->freedBuffer) {
+ pTransfer->allUsed = 1;
+ }
+ // Continue transfer, prepare for next operation
+ if (pTransfer->allUsed == 0) {
+ pBi = &pTransfer->pMbl[pTransfer->currBuffer];
+ pBi->buffered = 0;
+ pBi->transferred = 0;
+ pBi->remaining = pBi->size;
+ }
+ return 1;
+ }
+ return 0;
+}
+/*
+void UDPHS_WriteFifo(volatile char* pFifo,
+ unsigned char* pBuffer,
+ unsigned int size)
+{
+ register unsigned int c8 = size >> 3;
+ register unsigned int c1 = size & 0x7;
+ for (; c8; c8 --) {
+ *pFifo = *(pBuffer ++);
+ *pFifo = *(pBuffer ++);
+ *pFifo = *(pBuffer ++);
+ *pFifo = *(pBuffer ++);
+
+ *pFifo = *(pBuffer ++);
+ *pFifo = *(pBuffer ++);
+ *pFifo = *(pBuffer ++);
+ *pFifo = *(pBuffer ++);
+ }
+ for (; c1; c1 --) {
+ *pFifo = *(pBuffer ++);
+ }
+}
+*/
+//------------------------------------------------------------------------------
+/// Transfers a data payload from the current tranfer buffer to the endpoint
+/// FIFO
+/// \param bEndpoint Number of the endpoint which is sending data.
+//------------------------------------------------------------------------------
+static char UDPHS_MblWriteFifo(unsigned char bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+ USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->currBuffer]);
+ volatile char *pFifo;
+ signed int size;
+
+ volatile unsigned char * pBytes;
+ volatile char bufferEnd = 1;
+
+ // Get the number of bytes to send
+ size = pEndpoint->size;
+ if (size > pBi->remaining) {
+
+ size = pBi->remaining;
+ }
+
+ TRACE_DEBUG_WP("w%d.%d ", pTransfer->currBuffer, size);
+ if (size == 0) {
+
+ return 1;
+ }
+
+ pTransfer->pLastLoaded = pBi;
+ pBytes = &(pBi->pBuffer[pBi->transferred + pBi->buffered]);
+ pBi->buffered += size;
+ bufferEnd = UDPHS_MblUpdate(pTransfer, pBi, size, 0);
+
+ // Write packet in the FIFO buffer
+ pFifo = (char*)((unsigned int *)AT91C_BASE_UDPHS_EPTFIFO
+ + (EPT_VIRTUAL_SIZE * bEndpoint));
+ if (size) {
+ signed int c8 = size >> 3;
+ signed int c1 = size & 0x7;
+ //printf("%d[%x] ", pBi->transferred, pBytes);
+ for (; c8; c8 --) {
+ *(pFifo++) = *(pBytes ++);
+ *(pFifo++) = *(pBytes ++);
+ *(pFifo++) = *(pBytes ++);
+ *(pFifo++) = *(pBytes ++);
+
+ *(pFifo++) = *(pBytes ++);
+ *(pFifo++) = *(pBytes ++);
+ *(pFifo++) = *(pBytes ++);
+ *(pFifo++) = *(pBytes ++);
+ }
+ for (; c1; c1 --) {
+ *(pFifo++) = *(pBytes ++);
+ }
+ }
+ return bufferEnd;
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from the current tranfer buffer to the endpoint
+/// FIFO
+/// \param bEndpoint Number of the endpoint which is sending data.
+//------------------------------------------------------------------------------
+static void UDPHS_WritePayload( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+ char *pFifo;
+ signed int size;
+ unsigned int dCtr;
+
+ pFifo = (char*)((unsigned int *)AT91C_BASE_UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * bEndpoint));
+
+ // Get the number of bytes to send
+ size = pEndpoint->size;
+ if (size > pTransfer->remaining) {
+
+ size = pTransfer->remaining;
+ }
+
+ // Update transfer descriptor information
+ pTransfer->buffered += size;
+ pTransfer->remaining -= size;
+
+ // Write packet in the FIFO buffer
+ dCtr = 0;
+ while (size > 0) {
+
+ pFifo[dCtr] = *(pTransfer->pData);
+ pTransfer->pData++;
+ size--;
+ dCtr++;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Transfers a data payload from an endpoint FIFO to the current transfer buffer
+/// \param bEndpoint Endpoint number.
+/// \param wPacketSize Size of received data packet
+//------------------------------------------------------------------------------
+static void UDPHS_ReadPayload( unsigned char bEndpoint, int wPacketSize )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+ char *pFifo;
+ unsigned char dBytes=0;
+
+ pFifo = (char*)((unsigned int *)AT91C_BASE_UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * bEndpoint));
+
+ // Check that the requested size is not bigger than the remaining transfer
+ if (wPacketSize > pTransfer->remaining) {
+
+ pTransfer->buffered += wPacketSize - pTransfer->remaining;
+ wPacketSize = pTransfer->remaining;
+ }
+
+ // Update transfer descriptor information
+ pTransfer->remaining -= wPacketSize;
+ pTransfer->transferred += wPacketSize;
+
+ // Retrieve packet
+ while (wPacketSize > 0) {
+
+ *(pTransfer->pData) = pFifo[dBytes];
+ pTransfer->pData++;
+ wPacketSize--;
+ dBytes++;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Received SETUP packet from endpoint 0 FIFO
+/// \param pRequest Generic USB SETUP request sent over Control endpoints
+//------------------------------------------------------------------------------
+static void UDPHS_ReadRequest( USBGenericRequest *pRequest )
+{
+ unsigned int *pData = (unsigned int *)pRequest;
+ unsigned int fifo;
+
+ fifo = (AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[0]);
+ *pData = fifo;
+ fifo = (AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0[0]);
+ pData++;
+ *pData = fifo;
+ //TRACE_ERROR("SETUP: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n\r", pData[0],pData[1],pData[2],pData[3],pData[4],pData[5],pData[6],pData[7]);
+}
+
+//------------------------------------------------------------------------------
+/// Reset all endpoint transfer descriptors
+//------------------------------------------------------------------------------
+static void UDPHS_ResetEndpoints( void )
+{
+ Endpoint *pEndpoint;
+ Transfer *pTransfer;
+ unsigned char bEndpoint;
+
+ // Reset the transfer descriptor of every endpoint
+ for( bEndpoint = 0; bEndpoint < CHIP_USB_NUMENDPOINTS; bEndpoint++ ) {
+
+ pEndpoint = &(endpoints[bEndpoint]);
+ pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Reset endpoint transfer descriptor
+ pTransfer->pData = 0;
+ pTransfer->transferred = -1;
+ pTransfer->buffered = -1;
+ pTransfer->remaining = -1;
+ pTransfer->fCallback = 0;
+ pTransfer->pArgument = 0;
+
+ // Reset endpoint state
+ pEndpoint->bank = 0;
+ pEndpoint->state = UDP_ENDPOINT_DISABLED;
+ // Reset ZLP
+ pEndpoint->sendZLP = 0;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Disable all endpoints (except control endpoint 0), aborting current
+/// transfers if necessary
+//------------------------------------------------------------------------------
+static void UDPHS_DisableEndpoints( void )
+{
+ unsigned char bEndpoint;
+
+ // Disable each endpoint, terminating any pending transfer
+ // Control endpoint 0 is not disabled
+ for( bEndpoint = 1; bEndpoint < CHIP_USB_NUMENDPOINTS; bEndpoint++ ) {
+
+ UDPHS_EndOfTransfer( bEndpoint, USBD_STATUS_ABORTED );
+ endpoints[bEndpoint].state = UDP_ENDPOINT_DISABLED;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Endpoint interrupt handler.
+/// Handle IN/OUT transfers, received SETUP packets and STALLing
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+static void UDPHS_EndpointHandler( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+ MblTransfer *pMblt = (MblTransfer*)&(pEndpoint->transfer);
+ unsigned int status = AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSTA;
+ unsigned short wPacketSize;
+ USBGenericRequest request;
+
+ TRACE_DEBUG_WP("E%d ", bEndpoint);
+ TRACE_DEBUG_WP("st:0x%X ", status);
+
+ // Handle interrupts
+ // IN packet sent
+ if( (AT91C_UDPHS_TX_PK_RDY == (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTL & AT91C_UDPHS_TX_PK_RDY))
+ && (0 == (status & AT91C_UDPHS_TX_PK_RDY )) ) {
+
+ TRACE_DEBUG_WP("Wr ");
+
+ // Check that endpoint was sending multi-buffer-list
+ if( pEndpoint->state == UDP_ENDPOINT_SENDINGM ) {
+
+ USBDTransferBuffer * pMbli = pMblt->pLastLoaded;
+
+ TRACE_DEBUG_WP("TxM%d.%d,%d ",
+ pMblt->allUsed, pMbli->buffered, pMbli->remaining);
+
+ // End of transfer ?
+ if (pMblt->allUsed && pMbli->remaining == 0) {
+
+ pMbli->transferred += pMbli->buffered;
+ pMbli->buffered = 0;
+
+ // Disable interrupt
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS =
+ AT91C_UDPHS_TX_PK_RDY;
+ UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ else {
+
+ // Transfer remaining data
+ TRACE_DEBUG_WP("%d ", pEndpoint->size);
+
+ if (pMbli->buffered > pEndpoint->size) {
+ pMbli->transferred += pEndpoint->size;
+ pMbli->buffered -= pEndpoint->size;
+ }
+ else {
+ pMbli->transferred += pMbli->buffered;
+ pMbli->buffered = 0;
+ }
+
+ // Send next packet
+ UDPHS_MblWriteFifo(bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA =
+ AT91C_UDPHS_TX_PK_RDY;
+
+ if (pMbli->remaining == 0 && pMbli->buffered == 0) {
+
+ if (pMblt->fCallback) {
+ ((MblTransferCallback) pTransfer->fCallback)
+ (pTransfer->pArgument,
+ USBD_STATUS_PARTIAL_DONE,
+ 1);
+ }
+ }
+ }
+ }
+
+ // Check that endpoint was in Sending state
+ if( pEndpoint->state == UDP_ENDPOINT_SENDING ) {
+
+ if (pTransfer->buffered > 0) {
+ pTransfer->transferred += pTransfer->buffered;
+ pTransfer->buffered = 0;
+ }
+
+ if( ((pTransfer->buffered)==0)
+ &&((pTransfer->transferred)==0)
+ &&((pTransfer->remaining)==0)
+ &&(pEndpoint->sendZLP == 0)) {
+ pEndpoint->sendZLP = 1;
+ }
+
+ // End of transfer ?
+ if( (pTransfer->remaining > 0)
+ ||(pEndpoint->sendZLP == 1)) {
+
+ pEndpoint->sendZLP = 2;
+ TRACE_DEBUG_WP("\n\r1pTransfer->buffered %d \n\r", pTransfer->buffered);
+ TRACE_DEBUG_WP("1pTransfer->transferred %d \n\r", pTransfer->transferred);
+ TRACE_DEBUG_WP("1pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+ // Transfer remaining data
+ TRACE_DEBUG_WP(" %d ", pEndpoint->size);
+
+ // Send next packet
+ UDPHS_WritePayload(bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+ }
+ else {
+ TRACE_DEBUG_WP("\n\r0pTransfer->buffered %d \n\r", pTransfer->buffered);
+ TRACE_DEBUG_WP("0pTransfer->transferred %d \n\r", pTransfer->transferred);
+ TRACE_DEBUG_WP("0pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+ TRACE_DEBUG_WP(" %d ", pTransfer->transferred);
+
+ // Disable interrupt if this is not a control endpoint
+ if( AT91C_UDPHS_EPT_TYPE_CTL_EPT != (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)) ) {
+
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
+ }
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_TX_PK_RDY;
+
+ UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ pEndpoint->sendZLP = 0;
+ }
+ }
+ else {
+
+ TRACE_DEBUG("Error Wr %d", pEndpoint->sendZLP);
+ }
+ }
+
+ // OUT packet received
+ if( AT91C_UDPHS_RX_BK_RDY == (status & AT91C_UDPHS_RX_BK_RDY) ) {
+
+ TRACE_DEBUG_WP("Rd ");
+
+ // Check that the endpoint is in Receiving state
+ if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) {
+
+ // Check if an ACK has been received on a Control endpoint
+ if( (0 == (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG & AT91C_UDPHS_EPT_TYPE))
+ && (0 == (status & AT91C_UDPHS_BYTE_COUNT)) ) {
+
+ // Control endpoint, 0 bytes received
+ // Acknowledge the data and finish the current transfer
+ TRACE_DEBUG_WP("Ack ");
+ UDPHS_ClearRxFlag(bEndpoint);
+ UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ //todo remove endoftranfer and test
+ }
+ // Check if the data has been STALLed
+ else if( AT91C_UDPHS_FRCESTALL == (status & AT91C_UDPHS_FRCESTALL)) {
+
+ // Discard STALLed data
+ TRACE_DEBUG_WP("Discard ");
+ UDPHS_ClearRxFlag(bEndpoint);
+ }
+ // NAK the data
+ else {
+
+ TRACE_DEBUG_WP("Nak ");
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
+ }
+ }
+ else {
+
+ // Endpoint is in Read state
+ // Retrieve data and store it into the current transfer buffer
+ wPacketSize = (unsigned short)((status & AT91C_UDPHS_BYTE_COUNT)>>20);
+
+ TRACE_DEBUG_WP("%d ", wPacketSize);
+ UDPHS_ReadPayload(bEndpoint, wPacketSize);
+ UDPHS_ClearRxFlag(bEndpoint);
+
+ // Check if the transfer is finished
+ if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) {
+
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_RX_BK_RDY;
+
+ // Disable interrupt if this is not a control endpoint
+ if( AT91C_UDPHS_EPT_TYPE_CTL_EPT != (AT91C_UDPHS_EPT_TYPE & (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)) ) {
+
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
+ }
+ UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ }
+ }
+
+
+ // STALL sent
+ if( AT91C_UDPHS_STALL_SNT == (status & AT91C_UDPHS_STALL_SNT) ) {
+
+ TRACE_WARNING( "Sta 0x%X [%d] ", status, bEndpoint);
+
+ // Acknowledge the stall flag
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_STALL_SNT;
+
+ // If the endpoint is not halted, clear the STALL condition
+ if (pEndpoint->state != UDP_ENDPOINT_HALTED) {
+
+ TRACE_WARNING( "_ " );
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_FRCESTALL;
+ }
+ }
+
+ // SETUP packet received
+ if( AT91C_UDPHS_RX_SETUP == (status & AT91C_UDPHS_RX_SETUP) ) {
+
+ TRACE_DEBUG_WP("Stp ");
+
+ // If a transfer was pending, complete it
+ // Handles the case where during the status phase of a control write
+ // transfer, the host receives the device ZLP and ack it, but the ack
+ // is not received by the device
+ if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {
+
+ UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
+ }
+ // Copy the setup packet
+ UDPHS_ReadRequest(&request);
+
+ // Acknowledge setup packet
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_RX_SETUP;
+
+ // Forward the request to the upper layer
+ USBDCallbacks_RequestReceived(&request);
+ }
+
+}
+
+//------------------------------------------------------------------------------
+// Interrupt service routine
+//------------------------------------------------------------------------------
+#ifdef DMA
+//----------------------------------------------------------------------------
+/// Endpoint DMA interrupt handler.
+/// This function (ISR) handles dma interrupts
+/// \param bEndpoint Index of endpoint
+//----------------------------------------------------------------------------
+static void UDPHS_DmaHandler( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+ int justTransferred;
+ unsigned int status;
+ unsigned char result = USBD_STATUS_SUCCESS;
+
+ status = AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+ TRACE_DEBUG_WP("DmaE%d,%x ", bEndpoint, status);
+
+ if (pEndpoint->state == UDP_ENDPOINT_SENDINGM) {
+
+ DmaLlTransfer *pDmat = (DmaLlTransfer*)&(pEndpoint->transfer);
+ USBDDmaDescriptor *pDi = pDmat->pCurrBuffer;
+ USBDDmaDescriptor *pNi = (USBDDmaDescriptor*)AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMANXTDSC;
+ unsigned char bufCnt = 0;
+
+ if (AT91C_UDPHS_END_BF_ST == (status & AT91C_UDPHS_END_BF_ST)) {
+
+ // Stop loading descriptors
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL &=
+ ~((unsigned int)AT91C_UDPHS_LDNXT_DSC);
+
+ //printf("%x,%x|",
+ // (char)status,
+ // (short)AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMANXTDSC);
+
+ while( pDi->pNxtDesc != pNi ) {
+
+ // All descriptor processed
+ if (pDi == 0) break;
+ if (pDi->used) break;
+
+ // Current descriptor processed
+ /*
+ pDi->ctrlSettings = 0
+ //|AT91C_UDPHS_CHANN_ENB
+ //| AT91C_UDPHS_LDNXT_DSC
+ //| AT91C_UDPHS_END_TR_EN
+ //| AT91C_UDPHS_END_TR_IT
+ //| AT91C_UDPHS_END_B_EN
+ //| AT91C_UDPHS_END_BUFFIT
+ //| AT91C_UDPHS_DESC_LD_IT
+ ; */
+ pDi->used = 1; // Flag as used
+ bufCnt ++;
+ pDi = pDi->pNxtDesc;
+ }
+ pDmat->pCurrBuffer = pDi;
+
+ if (bufCnt) {
+
+ if (pDmat->fCallback) {
+
+ pDmat->fCallback(pDmat->pArgument,
+ ((result == USBD_STATUS_SUCCESS) ?
+ USBD_STATUS_PARTIAL_DONE : result),
+ bufCnt);
+ }
+ }
+
+ if ( (pNi == 0)
+ || (pNi->used && pNi) ) {
+
+ // Disable DMA endpoint interrupt
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0;
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1 << SHIFT_DMA << bEndpoint);
+
+ TRACE_DEBUG_WP("EoMDT ");
+ //printf("E:N%x,C%d ", (short)pNi, bufCnt);
+
+ UDPHS_EndOfTransfer(bEndpoint, result);
+ }
+ else {
+
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL |=
+ (AT91C_UDPHS_LDNXT_DSC);
+ }
+ }
+ else {
+
+ TRACE_ERROR("UDPHS: Dma(0x%X)\n\r", status);
+ result = USBD_STATUS_ABORTED;
+ UDPHS_EndOfTransfer(bEndpoint, result);
+ }
+ return;
+ }
+ else if (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM) {
+ return;
+ }
+
+ // Disable DMA interrupt to avoid receiving 2 interrupts (B_EN and TR_EN)
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL &=
+ ~(unsigned int)(AT91C_UDPHS_END_TR_EN | AT91C_UDPHS_END_B_EN);
+
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1 << SHIFT_DMA << bEndpoint);
+
+ if( AT91C_UDPHS_END_BF_ST == (status & AT91C_UDPHS_END_BF_ST) ) {
+
+ TRACE_DEBUG_WP("EndBuffer ");
+
+ // BUFF_COUNT holds the number of untransmitted bytes.
+ // BUFF_COUNT is equal to zero in case of good transfer
+ justTransferred = pTransfer->buffered
+ - ((status & (unsigned int)AT91C_UDPHS_BUFF_COUNT) >> 16);
+ pTransfer->transferred += justTransferred;
+
+ pTransfer->buffered =
+ ((status & (unsigned int)AT91C_UDPHS_BUFF_COUNT) >> 16);
+
+ pTransfer->remaining -= justTransferred;
+
+ TRACE_DEBUG_WP("\n\r1pTransfer->buffered %d \n\r", pTransfer->buffered);
+ TRACE_DEBUG_WP("1pTransfer->transferred %d \n\r", pTransfer->transferred);
+ TRACE_DEBUG_WP("1pTransfer->remaining %d \n\r", pTransfer->remaining);
+
+ if( (pTransfer->remaining + pTransfer->buffered) > 0 ) {
+
+ // Prepare an other transfer
+ if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+ pTransfer->buffered = DMA_MAX_FIFO_SIZE;
+ }
+ else {
+ pTransfer->buffered = pTransfer->remaining;
+ }
+
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS =
+ (unsigned int)((pTransfer->pData) + (pTransfer->transferred));
+
+ // Clear unwanted interrupts
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+
+ // Enable DMA endpoint interrupt
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
+ // DMA config for receive the good size of buffer, or an error buffer
+
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
+ ( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
+ | AT91C_UDPHS_END_TR_EN
+ | AT91C_UDPHS_END_TR_IT
+ | AT91C_UDPHS_END_B_EN
+ | AT91C_UDPHS_END_BUFFIT
+ | AT91C_UDPHS_CHANN_ENB );
+ }
+ }
+ else if( AT91C_UDPHS_END_TR_ST == (status & AT91C_UDPHS_END_TR_ST) ) {
+
+ TRACE_DEBUG_WP("EndTransf ");
+
+ pTransfer->transferred = pTransfer->buffered
+ - ((status & (unsigned int)AT91C_UDPHS_BUFF_COUNT) >> 16);
+ pTransfer->remaining = 0;
+ TRACE_DEBUG_WP("\n\r0pTransfer->buffered %d \n\r", pTransfer->buffered);
+ TRACE_DEBUG_WP("0pTransfer->transferred %d \n\r", pTransfer->transferred);
+ TRACE_DEBUG_WP("0pTransfer->remaining %d \n\r", pTransfer->remaining);
+ }
+ else {
+
+ TRACE_ERROR("UDPHS_DmaHandler: Error (0x%08X)\n\r", status);
+ result = USBD_STATUS_ABORTED;
+ }
+
+ // Invoke callback
+ if( pTransfer->remaining == 0 ) {
+
+ TRACE_DEBUG_WP("EOT ");
+ UDPHS_EndOfTransfer(bEndpoint, result);
+ }
+}
+#endif
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// USB device interrupt handler
+/// Manages device resume, suspend, end of bus reset.
+/// Forwards endpoint interrupts to the appropriate handler.
+//------------------------------------------------------------------------------
+void USBD_IrqHandler(void)
+{
+ unsigned int status;
+ unsigned char numIT;
+
+ if (deviceState >= USBD_STATE_POWERED) {
+
+ LED_Set(USBD_LEDUSB);
+ }
+
+ // Get interrupts status
+ status = AT91C_BASE_UDPHS->UDPHS_INTSTA;
+ status &= AT91C_BASE_UDPHS->UDPHS_IEN;
+
+ // Handle all UDPHS interrupts
+ TRACE_DEBUG_WP("H");
+ while (status != 0) {
+
+ // Start Of Frame (SOF)
+ if ((status & AT91C_UDPHS_IEN_SOF) != 0) {
+
+ TRACE_DEBUG_WP("SOF ");
+
+ // Invoke the SOF callback
+ //USB_StartOfFrameCallback(pUsb);
+
+ // Acknowledge interrupt
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_IEN_SOF;
+ status &= ~(unsigned int)AT91C_UDPHS_IEN_SOF;
+ }
+ // Suspend
+ // This interrupt is always treated last (hence the '==')
+ else if (status == AT91C_UDPHS_DET_SUSPD) {
+
+ TRACE_DEBUG_WP("S");
+
+ // The device enters the Suspended state
+ // MCK + UDPCK must be off
+ // Pull-Up must be connected
+ // Transceiver must be disabled
+
+ LED_Clear(USBD_LEDUSB);
+
+ UDPHS_DisableBIAS();
+
+ // Enable wakeup
+ AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM;
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(unsigned int)AT91C_UDPHS_DET_SUSPD;
+
+ // Acknowledge interrupt
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_DET_SUSPD | AT91C_UDPHS_WAKE_UP;
+ previousDeviceState = deviceState;
+ deviceState = USBD_STATE_SUSPENDED;
+ UDPHS_DisableUsbClock();
+
+ // Invoke the Suspend callback
+ USBDCallbacks_Suspended();
+ }
+ // Resume
+ else if( ((status & AT91C_UDPHS_WAKE_UP) != 0) // line activity
+ || ((status & AT91C_UDPHS_ENDOFRSM) != 0)) { // pc wakeup
+ {
+ // Invoke the Resume callback
+ USBDCallbacks_Resumed();
+
+ TRACE_DEBUG_WP("R");
+
+ UDPHS_EnableUsbClock();
+ UDPHS_EnableBIAS();
+
+ // The device enters Configured state
+ // MCK + UDPCK must be on
+ // Pull-Up must be connected
+ // Transceiver must be enabled
+
+ deviceState = previousDeviceState;
+
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM | AT91C_UDPHS_DET_SUSPD;
+
+ AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_ENDOFRSM | AT91C_UDPHS_DET_SUSPD;
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_ENDOFRSM;
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(unsigned int)AT91C_UDPHS_WAKE_UP;
+ }
+ }
+ // End of bus reset
+ else if ((status & AT91C_UDPHS_ENDRESET) == AT91C_UDPHS_ENDRESET) {
+
+// TRACE_DEBUG_WP("EoB ");
+
+ // The device enters the Default state
+ deviceState = USBD_STATE_DEFAULT;
+ // MCK + UDPCK are already enabled
+ // Pull-Up is already connected
+ // Transceiver must be enabled
+ // Endpoint 0 must be enabled
+
+ UDPHS_ResetEndpoints();
+ UDPHS_DisableEndpoints();
+ USBD_ConfigureEndpoint(0);
+
+ // Flush and enable the Suspend interrupt
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_WAKE_UP | AT91C_UDPHS_DET_SUSPD;
+
+ //// Enable the Start Of Frame (SOF) interrupt if needed
+ //if (pCallbacks->startOfFrame != 0)
+ //{
+ // AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_IEN_SOF;
+ //}
+
+ // Invoke the Reset callback
+ USBDCallbacks_Reset();
+
+ // Acknowledge end of bus reset interrupt
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_ENDRESET;
+
+ AT91C_BASE_UDPHS->UDPHS_IEN |= AT91C_UDPHS_DET_SUSPD;
+ }
+ // Handle upstream resume interrupt
+ else if (status & AT91C_UDPHS_UPSTR_RES) {
+
+ TRACE_DEBUG_WP("ExtRes ");
+
+ // - Acknowledge the IT
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_UPSTR_RES;
+ }
+ // Endpoint interrupts
+ else {
+#ifndef DMA
+ // Handle endpoint interrupts
+ for (numIT = 0; numIT < NUM_IT_MAX; numIT++) {
+
+ if ((status & (1 << SHIFT_INTERUPT << numIT)) != 0) {
+
+ UDPHS_EndpointHandler(numIT);
+ }
+ }
+#else
+ // Handle endpoint control interrupt
+ if ((status & (1 << SHIFT_INTERUPT << 0)) != 0) {
+
+ UDPHS_EndpointHandler( 0 );
+ }
+ else {
+
+ numIT = 1;
+ while((status&(0x7E<<SHIFT_DMA)) != 0) {
+
+ // Check if endpoint has a pending interrupt
+ if ((status & (1 << SHIFT_DMA << numIT)) != 0) {
+
+ UDPHS_DmaHandler(numIT);
+ status &= ~(1 << SHIFT_DMA << numIT);
+ if (status != 0) {
+
+ TRACE_INFO_WP("\n\r - ");
+ }
+ }
+ numIT++;
+ }
+ }
+#endif
+ }
+
+ // Retrieve new interrupt status
+ status = AT91C_BASE_UDPHS->UDPHS_INTSTA;
+ status &= AT91C_BASE_UDPHS->UDPHS_IEN;
+
+ TRACE_DEBUG_WP("\n\r");
+ if (status != 0) {
+
+ TRACE_DEBUG_WP(" - ");
+ }
+ }
+
+ if (deviceState >= USBD_STATE_POWERED) {
+
+ LED_Clear(USBD_LEDUSB);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Configure an endpoint with the provided endpoint descriptor
+/// \param pDdescriptor Pointer to the endpoint descriptor
+//------------------------------------------------------------------------------
+void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor)
+{
+ Endpoint *pEndpoint;
+ unsigned char bEndpoint;
+ unsigned char bType;
+ unsigned char bEndpointDir;
+ //unsigned char bInterval = 0;
+ unsigned char bNbTrans = 1;
+ unsigned char bSizeEpt = 0;
+ unsigned char bHs = ((AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_UDPHS_SPEED)
+ > 0);
+
+ // NULL descriptor -> Control endpoint 0
+ if (pDescriptor == 0) {
+
+ bEndpoint = 0;
+ pEndpoint = &(endpoints[bEndpoint]);
+ bType = USBEndpointDescriptor_CONTROL;
+ bEndpointDir = 0;
+ pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0);
+ pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(0);
+ }
+ else {
+
+ // The endpoint number
+ bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor);
+ pEndpoint = &(endpoints[bEndpoint]);
+ // Transfer type: Control, Isochronous, Bulk, Interrupt
+ bType = USBEndpointDescriptor_GetType(pDescriptor);
+ // interval
+ //bInterval = USBEndpointDescriptor_GetInterval(pDescriptor);
+ // Direction, ignored for control endpoints
+ bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor);
+ pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor);
+ pEndpoint->bank = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);
+
+ // Convert descriptor value to EP configuration
+ if (bHs) { // HS Interval, *125us
+
+ // MPS: Bit12,11 specify NB_TRANS
+ bNbTrans = ((pEndpoint->size >> 11) & 0x3);
+ if (bNbTrans == 3)
+ bNbTrans = 1;
+ else
+ bNbTrans ++;
+
+ // Mask, bit 10..0 is the size
+ pEndpoint->size &= 0x3FF;
+ }
+ }
+
+ // Abort the current transfer is the endpoint was configured and in
+ // Write or Read state
+ if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDING)
+ || (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM)
+ || (pEndpoint->state == UDP_ENDPOINT_SENDINGM) ) {
+
+ UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_RESET);
+ }
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Disable endpoint
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = (unsigned int)AT91C_UDPHS_SHRT_PCKT
+ | AT91C_UDPHS_BUSY_BANK
+ | AT91C_UDPHS_NAK_OUT
+ | AT91C_UDPHS_NAK_IN
+ | AT91C_UDPHS_STALL_SNT
+ | AT91C_UDPHS_RX_SETUP
+ | AT91C_UDPHS_TX_PK_RDY
+ | AT91C_UDPHS_TX_COMPLT
+ | AT91C_UDPHS_RX_BK_RDY
+ | AT91C_UDPHS_ERR_OVFLW
+ | AT91C_UDPHS_MDATA_RX
+ | AT91C_UDPHS_DATAX_RX
+ | AT91C_UDPHS_NYET_DIS
+ | AT91C_UDPHS_INTDIS_DMA
+ | AT91C_UDPHS_AUTO_VALID
+ | AT91C_UDPHS_EPT_DISABL;
+
+ // Reset Endpoint Fifos
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ | AT91C_UDPHS_FRCESTALL;
+ AT91C_BASE_UDPHS->UDPHS_EPTRST = 1<<bEndpoint;
+
+ // Configure endpoint
+ if( pEndpoint->size <= 8 ) {
+ bSizeEpt = 0;
+ }
+ else if ( pEndpoint->size <= 16 ) {
+ bSizeEpt = 1;
+ }
+ else if ( pEndpoint->size <= 32 ) {
+ bSizeEpt = 2;
+ }
+ else if ( pEndpoint->size <= 64 ) {
+ bSizeEpt = 3;
+ }
+ else if ( pEndpoint->size <= 128 ) {
+ bSizeEpt = 4;
+ }
+ else if ( pEndpoint->size <= 256 ) {
+ bSizeEpt = 5;
+ }
+ else if ( pEndpoint->size <= 512 ) {
+ bSizeEpt = 6;
+ }
+ else if ( pEndpoint->size <= 1024 ) {
+ bSizeEpt = 7;
+ } //else {
+ // sizeEpt = 0; // control endpoint
+ //}
+
+ // Configure endpoint
+ if (bType == USBEndpointDescriptor_CONTROL) {
+
+ // Enable endpoint IT for control endpoint
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_INTERUPT<<bEndpoint);
+ }
+
+
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG = bSizeEpt
+ | ( bEndpointDir << 3)
+ | ( bType << 4)
+ | ((pEndpoint->bank) << 6)
+ | ( bNbTrans << 8)
+ ;
+
+ while( (signed int)AT91C_UDPHS_EPT_MAPD != (signed int)((AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG) & (unsigned int)AT91C_UDPHS_EPT_MAPD) ) {
+
+ // resolved by clearing the reset IT in good place
+ TRACE_ERROR("PB bEndpoint: 0x%X\n\r", bEndpoint);
+ TRACE_ERROR("PB bSizeEpt: 0x%X\n\r", bSizeEpt);
+ TRACE_ERROR("PB bEndpointDir: 0x%X\n\r", bEndpointDir);
+ TRACE_ERROR("PB bType: 0x%X\n\r", bType);
+ TRACE_ERROR("PB pEndpoint->bank: 0x%X\n\r", pEndpoint->bank);
+ TRACE_ERROR("PB UDPHS_EPTCFG: 0x%X\n\r", AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG);
+ for(;;);
+ }
+
+ if (bType == USBEndpointDescriptor_CONTROL) {
+
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_RX_BK_RDY
+ | AT91C_UDPHS_RX_SETUP
+ | AT91C_UDPHS_EPT_ENABL;
+ }
+ else {
+#ifndef DMA
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_EPT_ENABL;
+#else
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_AUTO_VALID
+ | AT91C_UDPHS_EPT_ENABL;
+#endif
+ }
+
+}
+
+//------------------------------------------------------------------------------
+/// Sends data through an USB endpoint (IN)
+/// Sets up the transfer descriptor, write one or two data payloads
+/// (depending on the number of FIFO banks for the endpoint) and then
+/// starts the actual transfer. The operation is complete when all
+/// the data has been sent.
+/// \param bEndpoint Index of endpoint
+/// \param *pData Data to be written
+/// \param dLength Data length to be send
+/// \param fCallback Callback to be call after the success command
+/// \param *pArgument Callback argument
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+char USBD_Write( unsigned char bEndpoint,
+ const void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Return if the endpoint is not in IDLE state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength);
+ pEndpoint->sendZLP = 0;
+ // Setup the transfer descriptor
+ pTransfer->pData = (void *) pData;
+ pTransfer->remaining = dLength;
+ pTransfer->buffered = 0;
+ pTransfer->transferred = 0;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+
+ // Send one packet
+ pEndpoint->state = UDP_ENDPOINT_SENDING;
+
+#ifdef DMA
+ // Test if endpoint type control
+ if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG))) {
+#endif
+ // Enable endpoint IT
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_TX_PK_RDY;
+
+#ifdef DMA
+ }
+ else {
+ if( CHIP_USB_ENDPOINTS_DMA(bEndpoint) == 0 ) {
+ TRACE_FATAL("Endpoint has no DMA\n\r");
+ }
+ if( pTransfer->remaining == 0 ) {
+ // DMA not handle ZLP
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+ // Enable endpoint IT
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_TX_PK_RDY;
+ }
+ else {
+ // Others endpoints (not control)
+ if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+ // Transfer the max
+ pTransfer->buffered = DMA_MAX_FIFO_SIZE;
+ }
+ else {
+ // Transfer the good size
+ pTransfer->buffered = pTransfer->remaining;
+ }
+
+ TRACE_DEBUG_WP("\n\r_WR[%x]:%d ", pTransfer->pData, pTransfer->remaining );
+ TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
+ TRACE_DEBUG_WP("T:%d ", pTransfer->transferred );
+
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = (unsigned int)(pTransfer->pData);
+
+ // Clear unwanted interrupts
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+ // Enable DMA endpoint interrupt
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
+ // DMA config
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
+ ( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
+ | AT91C_UDPHS_END_B_EN
+ | AT91C_UDPHS_END_BUFFIT
+ | AT91C_UDPHS_CHANN_ENB );
+ }
+ }
+#endif
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Sends data frames through a USB endpoint. Sets up the transfer descriptor
+/// list, writes one or two data payloads (depending on the number of FIFO bank
+/// for the endpoint) and then starts the actual transfer. The operation invoke
+/// a callback with RC USBD_STATUS_PARTIAL_DONE each time when a buffer is
+/// transferred and is complete when all the data has been sent.
+///
+/// *If the size of the frame is greater than the size of the endpoint
+/// (or twice the size if the endpoint has two FIFO banks), then the buffer
+/// must be kept allocated until the frame is finished*. This means that
+/// it is not possible to declare it on the stack (i.e. as a local variable
+/// of a function which returns after starting a transfer).
+///
+/// \param bEndpoint Endpoint number.
+/// \param pMbl Pointer to a frame list with the data to send.
+/// Two different list is supported, for EPs that support DMA,
+/// the frame is described by USBDDmaDescriptor link list,
+/// for EPs that uses FIFO the frame is described by
+/// USBDTransferBuffer array.
+/// For DMA transfer, the size of each frame is limited by the
+/// max size of one DMA transfer. When using DMA, the frame list
+/// size and size of each frame should be larger so that more
+/// efficiency is achieved and CPU could have more time on
+/// handler of each buffer end event.
+/// \param wListSize Size of the frame list.
+/// \param bCircList Circle the list.
+/// \param wStartNdx Starting buffer index in the list.
+/// \param fCallback Optional callback function to invoke when the transfer is
+/// complete.
+/// \param pArgument Optional argument to the callback function.
+/// \return USBD_STATUS_SUCCESS if the transfer has been started;
+/// otherwise, the corresponding error status code.
+/// \see USBDDmaDescriptor, USBDTransferBuffer
+//------------------------------------------------------------------------------
+char USBD_MblWrite( unsigned char bEndpoint,
+ void *pMbl,
+ unsigned short wListSize,
+ unsigned char bCircList,
+ unsigned short wStartNdx,
+ MblTransferCallback fCallback,
+ void *pArgument )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+ unsigned short i;
+
+ // EP0 is not suitable for Mbl
+ if (bEndpoint == 0) {
+
+ return USBD_STATUS_INVALID_PARAMETER;
+ }
+
+ // Check that the endpoint is in Idle state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ //return USBD_STATUS_LOCKED;
+ }
+ // Setup state
+ pEndpoint->state = UDP_ENDPOINT_SENDINGM;
+
+ TRACE_DEBUG_WP("WriteM%d(0x%x,%d) ", bEndpoint, pMbl, wListSize);
+
+ // Start from first if not circled list
+ if (!bCircList) wStartNdx = 0;
+
+#ifdef DMA
+ if (UDP_IsDmaUsed(bEndpoint)) {
+
+ DmaLlTransfer *pDmallt = (DmaLlTransfer*)&(pEndpoint->transfer);
+ USBDDmaDescriptor * pDi = (USBDDmaDescriptor*)pMbl;
+
+ // DMA config
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0;
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1 << SHIFT_DMA << bEndpoint);
+
+ // Setup the transfer descriptor
+ pDmallt->pMbl = (USBDDmaDescriptor*)pMbl;
+ pDmallt->listSize = wListSize;
+ pDmallt->fCallback = fCallback;
+ pDmallt->pArgument = pArgument;
+ pDmallt->circList = bCircList;
+ pDmallt->allUsed = 0;
+
+ // Check all buffers, fill settings
+ for (i = 0; i < wListSize - 1; i ++) {
+
+ if (pDi->bufferLength > DMA_MAX_FIFO_SIZE) {
+
+ TRACE_ERROR("DMA buffer size %d exceeds max %d\n\r",
+ pDi->bufferLength, DMA_MAX_FIFO_SIZE);
+ return USBD_STATUS_INVALID_PARAMETER;
+ }
+
+ // Channel control value
+ pDi->ctrlSettings = AT91C_UDPHS_CHANN_ENB
+ | AT91C_UDPHS_LDNXT_DSC
+ | AT91C_UDPHS_END_TR_EN
+ //| AT91C_UDPHS_END_TR_IT
+ | AT91C_UDPHS_END_B_EN
+ | AT91C_UDPHS_END_BUFFIT
+ | AT91C_UDPHS_DESC_LD_IT
+ ;
+ pDi->used = 0;
+ pDi = pDi->pNxtDesc;
+ }
+
+ // Circled list check
+ pDi->used = 0;
+ if (bCircList) {
+
+ pDi->pNxtDesc = pDmallt->pMbl;
+ pDi->ctrlSettings = AT91C_UDPHS_CHANN_ENB
+ | AT91C_UDPHS_LDNXT_DSC
+ | AT91C_UDPHS_END_TR_EN
+ //| AT91C_UDPHS_END_TR_IT
+ | AT91C_UDPHS_END_B_EN
+ | AT91C_UDPHS_END_BUFFIT
+ //| AT91C_UDPHS_DESC_LD_IT
+ ;
+ }
+ else {
+
+ pDi->pNxtDesc = 0;
+ pDi->ctrlSettings = AT91C_UDPHS_CHANN_ENB
+ //| AT91C_UDPHS_LDNXT_DSC
+ | AT91C_UDPHS_END_TR_EN
+ //| AT91C_UDPHS_END_TR_IT
+ | AT91C_UDPHS_END_B_EN
+ | AT91C_UDPHS_END_BUFFIT
+ //| AT91C_UDPHS_DESC_LD_IT
+ ;
+ }
+
+ // Start from 'wStartNdx'th descriptor
+ pDi = (USBDDmaDescriptor*)pMbl;
+ for (;wStartNdx; wStartNdx --) {
+ pDi = pDi->pNxtDesc;
+ }
+ pDmallt->pCurrBuffer = (USBDDmaDescriptor*)pDi;
+ pDmallt->pFreedBuffer = (USBDDmaDescriptor*)pDi;
+
+ // Disable DMA when interrupt happenned
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_INTDIS_DMA;
+
+ // Clear unwanted interrupts
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+ // Enable DMA endpoint interrupt
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMANXTDSC = (unsigned int)pMbl;
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = AT91C_UDPHS_LDNXT_DSC
+ //| AT91C_UDPHS_END_TR_EN
+ //| AT91C_UDPHS_END_TR_IT
+ //| AT91C_UDPHS_END_B_EN
+ //| AT91C_UDPHS_END_BUFFIT
+ //| AT91C_UDPHS_DESC_LD_IT
+ ;
+
+ return USBD_STATUS_SUCCESS;
+ }
+#endif
+
+ // DMA is not used
+ {
+ unsigned char nbBanks = CHIP_USB_ENDPOINTS_BANKS(bEndpoint);
+
+ // Setup the transfer descriptor
+ pTransfer->pMbl = (USBDTransferBuffer*)pMbl;
+ pTransfer->listSize = wListSize;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+ pTransfer->currBuffer = wStartNdx;
+ pTransfer->freedBuffer = 0;
+ pTransfer->pLastLoaded = &(((USBDTransferBuffer*)pMbl)[wStartNdx]);
+ pTransfer->circList = bCircList;
+ pTransfer->allUsed = 0;
+
+ // Clear all buffer
+ for (i = 0; i < wListSize; i ++) {
+
+ pTransfer->pMbl[i].transferred = 0;
+ pTransfer->pMbl[i].buffered = 0;
+ pTransfer->pMbl[i].remaining = pTransfer->pMbl[i].size;
+ }
+
+ // Fill data into FIFO
+ for (;
+ nbBanks && pTransfer->pMbl[pTransfer->currBuffer].remaining;
+ nbBanks --) {
+
+ UDPHS_MblWriteFifo(bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA =
+ AT91C_UDPHS_TX_PK_RDY;
+ }
+
+ // Enable interrup
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = 0
+ //| AT91C_UDPHS_TX_COMPLT
+ | AT91C_UDPHS_TX_PK_RDY
+ ;
+ return USBD_STATUS_SUCCESS;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reads incoming data on an USB endpoint (OUT)
+/// \param bEndpoint Index of endpoint
+/// \param *pData Data to be readen
+/// \param dLength Data length to be receive
+/// \param fCallback Callback to be call after the success command
+/// \param *pArgument Callback argument
+/// \return USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+char USBD_Read( unsigned char bEndpoint,
+ void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArgument )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer);
+
+ // Return if the endpoint is not in IDLE state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+
+ // Endpoint enters Receiving state
+ pEndpoint->state = UDP_ENDPOINT_RECEIVING;
+
+ // Set the transfer descriptor
+ pTransfer->pData = pData;
+ pTransfer->remaining = dLength;
+ pTransfer->buffered = 0;
+ pTransfer->transferred = 0;
+ pTransfer->fCallback = fCallback;
+ pTransfer->pArgument = pArgument;
+
+#ifdef DMA
+ // Test if endpoint type control
+ if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG))) {
+#endif
+ // Control endpoint
+ // Enable endpoint IT
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_INTERUPT << bEndpoint);
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_RX_BK_RDY;
+#ifdef DMA
+ }
+ else {
+ if( CHIP_USB_ENDPOINTS_DMA(bEndpoint) == 0 ) {
+ TRACE_FATAL("Endpoint has no DMA\n\r");
+ }
+ TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength);
+
+ // Others endpoints (not control)
+ if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {
+
+ // Transfer the max
+ pTransfer->buffered = DMA_MAX_FIFO_SIZE;
+ }
+ else {
+ // Transfer the good size
+ pTransfer->buffered = pTransfer->remaining;
+ }
+
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = (unsigned int)(pTransfer->pData);
+
+ // Clear unwanted interrupts
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
+
+ // Enable DMA endpoint interrupt
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
+
+ TRACE_DEBUG_WP("\n\r_RR:%d ", pTransfer->remaining );
+ TRACE_DEBUG_WP("B:%d ", pTransfer->buffered );
+ TRACE_DEBUG_WP("T:%d ", pTransfer->transferred );
+
+ // DMA config
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
+ AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
+ ( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
+ | AT91C_UDPHS_END_TR_EN
+ | AT91C_UDPHS_END_TR_IT
+ | AT91C_UDPHS_END_B_EN
+ | AT91C_UDPHS_END_BUFFIT
+ | AT91C_UDPHS_CHANN_ENB );
+ }
+#endif
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Reuse first used/released buffer with new buffer address and size to be used
+/// in transfer again. Only valid when frame list is ringed. Can be used for
+/// both read & write.
+/// \param bEndpoint Endpoint number.
+/// \param pNewBuffer Pointer to new buffer with data to send (0 to keep last).
+/// \param wNewSize Size of the data buffer
+//------------------------------------------------------------------------------
+char USBD_MblReuse( unsigned char bEndpoint,
+ unsigned char *pNewBuffer,
+ unsigned short wNewSize )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer);
+ USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->freedBuffer]);
+
+ // Only for Multi-buffer-circle list
+ if (bEndpoint != 0
+ && (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM
+ || pEndpoint->state == UDP_ENDPOINT_SENDINGM)) {
+ }
+ else {
+
+ return USBD_STATUS_WRONG_STATE;
+ }
+
+ TRACE_DEBUG_WP("MblReuse(%d), st%x, circ%d\n\r",
+ bEndpoint, pEndpoint->state, pTransfer->circList);
+
+#ifdef DMA
+ if (UDP_IsDmaUsed(bEndpoint)) {
+
+ DmaLlTransfer *pDmallt = (DmaLlTransfer*)&(pEndpoint->transfer);
+ USBDDmaDescriptor *pDi = pDmallt->pFreedBuffer;
+
+ // ONLY for circled list
+ if (!pDmallt->circList) {
+
+ return USBD_STATUS_WRONG_STATE;
+ }
+
+ // Check if there is freed buffer
+ if ((pDi == 0) || (pDi && !pDi->used) ) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ // Update transfer information
+ pDmallt->pFreedBuffer = pDi->pNxtDesc;
+ if (pNewBuffer) {
+
+ pDi->pDataAddr = pNewBuffer;
+ pDi->bufferLength = wNewSize;
+ }
+ /*
+ pDi->ctrlSettings = AT91C_UDPHS_CHANN_ENB
+ | AT91C_UDPHS_LDNXT_DSC
+ | AT91C_UDPHS_END_TR_EN
+ //| AT91C_UDPHS_END_TR_IT
+ | AT91C_UDPHS_END_B_EN
+ | AT91C_UDPHS_END_BUFFIT
+ | AT91C_UDPHS_DESC_LD_IT
+ ; */
+ pDi->used = 0;
+
+ pDmallt->allUsed = 0;
+
+ return USBD_STATUS_SUCCESS;
+ }
+#endif
+
+ // DMA is not used
+ {
+
+ // ONLY for circled list
+ if (!pTransfer->circList) {
+
+ return USBD_STATUS_WRONG_STATE;
+ }
+
+ // Check if there is freed buffer
+ if (pTransfer->freedBuffer == pTransfer->currBuffer
+ && !pTransfer->allUsed) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ // Update transfer information
+ if ((++ pTransfer->freedBuffer) == pTransfer->listSize)
+ pTransfer->freedBuffer = 0;
+ if (pNewBuffer) {
+
+ pBi->pBuffer = pNewBuffer;
+ pBi->size = wNewSize;
+ }
+ pBi->buffered = 0;
+ pBi->transferred = 0;
+ pBi->remaining = pBi->size;
+
+ // At least one buffer is not processed
+ pTransfer->allUsed = 0;
+ }
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Put endpoint into Halt state
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Halt( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ TRACE_INFO("usbd_Halt%d ", bEndpoint);
+ // Check that endpoint is enabled and not already in Halt state
+ if( (pEndpoint->state != UDP_ENDPOINT_DISABLED)
+ && (pEndpoint->state != UDP_ENDPOINT_HALTED) ) {
+
+ TRACE_INFO("Halt%d ", bEndpoint);
+
+ // Abort the current transfer if necessary
+ UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED);
+
+ // Put endpoint into Halt state
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_FRCESTALL;
+ pEndpoint->state = UDP_ENDPOINT_HALTED;
+
+#ifdef DMA
+ // Test if endpoint type control
+ if(AT91C_UDPHS_EPT_TYPE_CTL_EPT == (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG))) {
+#endif
+ // Enable the endpoint interrupt
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_INTERUPT<<bEndpoint);
+#ifdef DMA
+ }
+ else {
+ // Enable IT DMA
+ AT91C_BASE_UDPHS->UDPHS_IEN |= (1<<SHIFT_DMA<<bEndpoint);
+ }
+#endif
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Clears the Halt feature on the given endpoint.
+/// \param bEndpoint Index of endpoint
+//------------------------------------------------------------------------------
+void USBD_Unhalt( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check if the endpoint is enabled
+ //if (pEndpoint->state != UDP_ENDPOINT_DISABLED) {
+ if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+
+ TRACE_DEBUG_WP("Unhalt%d ", bEndpoint);
+
+ // Return endpoint to Idle state
+ pEndpoint->state = UDP_ENDPOINT_IDLE;
+
+ // Clear FORCESTALL flag
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ | AT91C_UDPHS_FRCESTALL;
+
+ // Reset Endpoint Fifos
+ AT91C_BASE_UDPHS->UDPHS_EPTRST = (1<<bEndpoint);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Returns the current Halt status of an endpoint.
+/// \param bEndpoint Index of endpoint
+/// \return 1 if the endpoint is currently halted; otherwise 0
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHalted( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+ unsigned char status = 0;
+
+ if (pEndpoint->state == UDP_ENDPOINT_HALTED) {
+ status = 1;
+ }
+ return( status );
+}
+
+//------------------------------------------------------------------------------
+/// IS High Speed device working in High Speed ?
+/// \return 1 if the device is in High Speed; otherwise 0 (Full Speed)
+//------------------------------------------------------------------------------
+unsigned char USBD_IsHighSpeed( void )
+{
+ unsigned char status = 0;
+
+ if( AT91C_UDPHS_SPEED == (AT91C_BASE_UDPHS->UDPHS_INTSTA & AT91C_UDPHS_SPEED) )
+ {
+ // High Speed
+ TRACE_DEBUG_WP("High Speed\n\r");
+ status = 1;
+ }
+ else {
+ TRACE_DEBUG_WP("Full Speed\n\r");
+ }
+ return( status );
+}
+
+
+//------------------------------------------------------------------------------
+/// Causes the endpoint to acknowledge the next received packet with a STALL
+/// handshake.
+/// Further packets are then handled normally.
+/// \param bEndpoint Index of endpoint
+/// \return Operation result code: USBD_STATUS_LOCKED or USBD_STATUS_SUCCESS
+//------------------------------------------------------------------------------
+unsigned char USBD_Stall( unsigned char bEndpoint )
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ // Check that endpoint is in Idle state
+ if (pEndpoint->state != UDP_ENDPOINT_IDLE) {
+
+ TRACE_WARNING("UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
+ return USBD_STATUS_LOCKED;
+ }
+
+ TRACE_DEBUG_WP("Stall%d ", bEndpoint);
+
+ AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_FRCESTALL;
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+/// Activates a remote wakeup procedure
+//------------------------------------------------------------------------------
+void USBD_RemoteWakeUp(void)
+{
+ TRACE_DEBUG_WP("Remote WakeUp\n\r");
+
+ // Device is currently suspended
+ if (deviceState == USBD_STATE_SUSPENDED) {
+
+ TRACE_DEBUG_WP("RW\n\r");
+ UDPHS_EnableUsbClock();
+
+ // Activates a remote wakeup
+ AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_REWAKEUP;
+
+ while ((AT91C_BASE_UDPHS->UDPHS_CTRL&AT91C_UDPHS_REWAKEUP) == AT91C_UDPHS_REWAKEUP) {
+
+ TRACE_DEBUG_WP("W");
+ }
+ UDPHS_EnableBIAS();
+ }
+ // Device is NOT suspended
+ else {
+
+ TRACE_WARNING("USBD_RemoteWakeUp: Device is not suspended\n\r");
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Sets the device address
+/// \param address Adress to be set
+//------------------------------------------------------------------------------
+void USBD_SetAddress( unsigned char address )
+{
+ TRACE_DEBUG_WP("SetAddr(%d) ", address);
+
+ // Set address
+ AT91C_BASE_UDPHS->UDPHS_CTRL &= ~(unsigned int)AT91C_UDPHS_DEV_ADDR; // RAZ Address
+ AT91C_BASE_UDPHS->UDPHS_CTRL |= address | AT91C_UDPHS_FADDR_EN;
+
+ // If the address is 0, the device returns to the Default state
+ if (address == 0) {
+ deviceState = USBD_STATE_DEFAULT;
+ }
+ // If the address is non-zero, the device enters the Address state
+ else {
+ deviceState = USBD_STATE_ADDRESS;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Changes the device state from Address to Configured, or from Configured
+/// to Address.
+/// This method directly access the last received SETUP packet to decide on
+/// what to do.
+/// \param cfgnum configuration number
+//------------------------------------------------------------------------------
+void USBD_SetConfiguration( unsigned char cfgnum )
+{
+ TRACE_DEBUG_WP("SetCfg(%d) ", cfgnum);
+
+ // Check the request
+ if( cfgnum != 0 ) {
+
+ // Enter Configured state
+ deviceState = USBD_STATE_CONFIGURED;
+ }
+ // If the configuration number is zero, the device goes back to the Address
+ // state
+ else {
+
+ // Go back to Address state
+ deviceState = USBD_STATE_ADDRESS;
+
+ // Abort all transfers
+ UDPHS_DisableEndpoints();
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Enables the pull-up on the D+ line to connect the device to the USB.
+//------------------------------------------------------------------------------
+void USBD_Connect( void )
+{
+ TRACE_DEBUG_WP("Conn ");
+#if defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_UDPHS->UDPHS_CTRL &= ~(unsigned int)AT91C_UDPHS_DETACH; // Pull Up on DP
+ AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_PULLD_DIS; // Disable Pull Down
+
+#elif defined(CHIP_USB_PULLUP_INTERNAL_BY_MATRIX)
+ TRACE_DEBUG_WP("PUON 1\n\r");
+ AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;
+
+#elif defined(CHIP_USB_PULLUP_EXTERNAL)
+
+#ifdef PIN_USB_PULLUP
+ const Pin pinPullUp = PIN_USB_PULLUP;
+ if( pinPullUp.type == PIO_OUTPUT_0 ) {
+
+ PIO_Set(&pinPullUp);
+ }
+ else {
+
+ PIO_Clear(&pinPullUp);
+ }
+#else
+ #error unsupported now
+#endif
+
+#elif !defined(CHIP_USB_PULLUP_ALWAYSON)
+ #error Unsupported pull-up type.
+
+#endif
+}
+
+//------------------------------------------------------------------------------
+/// Disables the pull-up on the D+ line to disconnect the device from the bus.
+//------------------------------------------------------------------------------
+void USBD_Disconnect( void )
+{
+ TRACE_DEBUG_WP("Disc ");
+
+#if defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_DETACH; // detach
+ AT91C_BASE_UDPHS->UDPHS_CTRL &= ~(unsigned int)AT91C_UDPHS_PULLD_DIS; // Enable Pull Down
+
+#elif defined(CHIP_USB_PULLUP_INTERNAL_BY_MATRIX)
+ AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+
+#elif defined(CHIP_USB_PULLUP_EXTERNAL)
+
+#ifdef PIN_USB_PULLUP
+ const Pin pinPullUp = PIN_USB_PULLUP;
+ if (pinPullUp.type == PIO_OUTPUT_0) {
+
+ PIO_Clear(&pinPullUp);
+ }
+ else {
+
+ PIO_Set(&pinPullUp);
+ }
+#else
+ #error unsupported now
+#endif
+
+#elif !defined(CHIP_USB_PULLUP_ALWAYSON)
+ #error Unsupported pull-up type.
+
+#endif
+
+ // Device returns to the Powered state
+ if (deviceState > USBD_STATE_POWERED) {
+
+ deviceState = USBD_STATE_POWERED;
+ }
+ if (previousDeviceState > USBD_STATE_POWERED) {
+
+ previousDeviceState = USBD_STATE_POWERED;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Certification test for High Speed device.
+/// \param bIndex Test to be done
+//------------------------------------------------------------------------------
+void USBD_Test( unsigned char bIndex )
+{
+ char *pFifo;
+ unsigned char i;
+
+ AT91C_BASE_UDPHS->UDPHS_IEN &= ~(unsigned int)AT91C_UDPHS_DET_SUSPD; // remove suspend for TEST
+ AT91C_BASE_UDPHS->UDPHS_TST |= AT91C_UDPHS_SPEED_CFG_HS; // force High Speed (remove suspend)
+
+ switch( bIndex ) {
+
+ case USBFeatureRequest_TESTPACKET:
+ TRACE_DEBUG_WP("TEST_PACKET ");
+
+ AT91C_BASE_UDPHS->UDPHS_DMA[1].UDPHS_DMACONTROL = 0;
+ AT91C_BASE_UDPHS->UDPHS_DMA[2].UDPHS_DMACONTROL = 0;
+
+ // Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank
+ AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTCFG = AT91C_UDPHS_EPT_SIZE_64 | AT91C_UDPHS_EPT_DIR_IN | AT91C_UDPHS_EPT_TYPE_BUL_EPT | AT91C_UDPHS_BK_NUMBER_1;
+ while( (signed int)(AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTCFG & (unsigned int)AT91C_UDPHS_EPT_MAPD) != (signed int)AT91C_UDPHS_EPT_MAPD ) {}
+
+ AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTCTLENB = AT91C_UDPHS_EPT_ENABL;
+
+ // Write FIFO
+ pFifo = (char*)((unsigned int *)(AT91C_BASE_UDPHS_EPTFIFO->UDPHS_READEPT0) + (EPT_VIRTUAL_SIZE * 2));
+ for( i=0; i<sizeof(test_packet_buffer); i++) {
+ pFifo[i] = test_packet_buffer[i];
+ }
+ // Tst PACKET
+ AT91C_BASE_UDPHS->UDPHS_TST |= AT91C_UDPHS_TST_PKT;
+ // Send packet
+ AT91C_BASE_UDPHS->UDPHS_EPT[2].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+ break;
+
+ case USBFeatureRequest_TESTJ:
+ TRACE_DEBUG_WP("TEST_J ");
+ AT91C_BASE_UDPHS->UDPHS_TST = AT91C_UDPHS_TST_J;
+ break;
+
+ case USBFeatureRequest_TESTK:
+ TRACE_DEBUG_WP("TEST_K ");
+ AT91C_BASE_UDPHS->UDPHS_TST = AT91C_UDPHS_TST_K;
+ break;
+
+ case USBFeatureRequest_TESTSE0NAK:
+ TRACE_DEBUG_WP("TEST_SEO_NAK ");
+ AT91C_BASE_UDPHS->UDPHS_IEN = 0; // for test
+ break;
+
+ case USBFeatureRequest_TESTSENDZLP:
+ //while( 0 != (AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & AT91C_UDPHS_TX_PK_RDY ) ) {}
+ AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
+ //while( 0 != (AT91C_BASE_UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & AT91C_UDPHS_TX_PK_RDY ) ) {}
+ TRACE_DEBUG_WP("SEND_ZLP ");
+ break;
+ }
+ TRACE_DEBUG_WP("\n\r");
+}
+
+
+//------------------------------------------------------------------------------
+/// Initializes the specified USB driver
+/// This function initializes the current FIFO bank of endpoints,
+/// configures the pull-up and VBus lines, disconnects the pull-up and
+/// then trigger the Init callback.
+//------------------------------------------------------------------------------
+void USBD_Init(void)
+{
+ unsigned char i;
+
+ TRACE_DEBUG_WP("USBD Init()\n\r");
+
+ // Reset endpoint structures
+ UDPHS_ResetEndpoints();
+
+ // Enables the UDPHS peripheral
+ UDPHS_EnablePeripheral();
+
+ // XCHQ[2010.1.21]: From IP recomendation, the order for init is:
+ // - reset IP (EN_UDPHS), - enable PLL 480M, - enable USB Clock
+
+ // Enables the USB Clock
+ // UDPHS_EnableUsbClock();
+
+ // Configure the pull-up on D+ and disconnect it
+#if defined(CHIP_USB_PULLUP_INTERNAL)
+ AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_DETACH; // detach
+ AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_PULLD_DIS; // Disable Pull Down
+
+#elif defined(CHIP_USB_PULLUP_INTERNAL_BY_MATRIX)
+ TRACE_DEBUG_WP("PUON 0\n\r");
+ AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;
+
+#elif defined(CHIP_USB_PULLUP_EXTERNAL)
+#ifdef PIN_USB_PULLUP
+ const Pin pinPullUp = PIN_USB_PULLUP;
+ PIO_Configure(&pinPullUp, 1);
+ if (pinPullUp.type == PIO_OUTPUT_0) {
+
+ PIO_Clear(&pinPullUp);
+ }
+ else {
+
+ PIO_Set(&pinPullUp);
+ }
+#else
+ #error unsupported now
+#endif
+#elif !defined(CHIP_USB_PULLUP_ALWAYSON)
+ #error Unsupported pull-up type.
+
+#endif
+
+ // Reset and enable IP UDPHS
+ AT91C_BASE_UDPHS->UDPHS_CTRL &= ~(unsigned int)AT91C_UDPHS_EN_UDPHS;
+ AT91C_BASE_UDPHS->UDPHS_CTRL |= AT91C_UDPHS_EN_UDPHS;
+ // Enable and disable of the transceiver is automaticaly done by the IP.
+
+ // Enables the USB Clock
+ // (XCHQ[2010.1.21], IP recomendation, setup clock after reset IP)
+ UDPHS_EnableUsbClock();
+
+ // With OR without DMA !!!
+ // Initialization of DMA
+ for( i=1; i<=((AT91C_BASE_UDPHS->UDPHS_IPFEATURES & AT91C_UDPHS_DMA_CHANNEL_NBR)>>4); i++ ) {
+
+ // RESET endpoint canal DMA:
+ // DMA stop channel command
+ AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMACONTROL = 0; // STOP command
+
+ // Disable endpoint
+ AT91C_BASE_UDPHS->UDPHS_EPT[i].UDPHS_EPTCTLDIS = (unsigned int)AT91C_UDPHS_SHRT_PCKT
+ | AT91C_UDPHS_BUSY_BANK
+ | AT91C_UDPHS_NAK_OUT
+ | AT91C_UDPHS_NAK_IN
+ | AT91C_UDPHS_STALL_SNT
+ | AT91C_UDPHS_RX_SETUP
+ | AT91C_UDPHS_TX_PK_RDY
+ | AT91C_UDPHS_TX_COMPLT
+ | AT91C_UDPHS_RX_BK_RDY
+ | AT91C_UDPHS_ERR_OVFLW
+ | AT91C_UDPHS_MDATA_RX
+ | AT91C_UDPHS_DATAX_RX
+ | AT91C_UDPHS_NYET_DIS
+ | AT91C_UDPHS_INTDIS_DMA
+ | AT91C_UDPHS_AUTO_VALID
+ | AT91C_UDPHS_EPT_DISABL;
+
+ // Clear status endpoint
+ AT91C_BASE_UDPHS->UDPHS_EPT[i].UDPHS_EPTCLRSTA = AT91C_UDPHS_TOGGLESQ
+ | AT91C_UDPHS_FRCESTALL
+ | AT91C_UDPHS_RX_BK_RDY
+ | AT91C_UDPHS_TX_COMPLT
+ | AT91C_UDPHS_RX_SETUP
+ | AT91C_UDPHS_STALL_SNT
+ | AT91C_UDPHS_NAK_IN
+ | AT91C_UDPHS_NAK_OUT;
+
+ // Reset endpoint config
+ AT91C_BASE_UDPHS->UDPHS_EPT[i].UDPHS_EPTCTLENB = 0;
+
+ // Reset DMA channel (Buff count and Control field)
+ AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMACONTROL = AT91C_UDPHS_LDNXT_DSC; // NON STOP command
+
+ // Reset DMA channel 0 (STOP)
+ AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMACONTROL = 0; // STOP command
+
+ // Clear DMA channel status (read the register for clear it)
+ AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMASTATUS = AT91C_BASE_UDPHS->UDPHS_DMA[i].UDPHS_DMASTATUS;
+
+ }
+
+ AT91C_BASE_UDPHS->UDPHS_TST = forceUsbFS ? AT91C_UDPHS_SPEED_CFG_FS : 0;
+ AT91C_BASE_UDPHS->UDPHS_IEN = 0;
+ AT91C_BASE_UDPHS->UDPHS_CLRINT = AT91C_UDPHS_UPSTR_RES
+ | AT91C_UDPHS_ENDOFRSM
+ | AT91C_UDPHS_WAKE_UP
+ | AT91C_UDPHS_ENDRESET
+ | AT91C_UDPHS_IEN_SOF
+ | AT91C_UDPHS_MICRO_SOF
+ | AT91C_UDPHS_DET_SUSPD;
+
+ // Device is in the Attached state
+ deviceState = USBD_STATE_SUSPENDED;
+ previousDeviceState = USBD_STATE_POWERED;
+
+ // Enable interrupts
+ AT91C_BASE_UDPHS->UDPHS_IEN = AT91C_UDPHS_ENDOFRSM
+ | AT91C_UDPHS_WAKE_UP
+ | AT91C_UDPHS_DET_SUSPD;
+
+ // Disable USB clocks
+ UDPHS_DisableUsbClock();
+
+ // Configure interrupts
+ USBDCallbacks_Initialized();
+}
+
+//------------------------------------------------------------------------------
+/// Configure USB Speed, should be invoked before USB attachment.
+/// \param forceFS Force to use FS mode.
+//------------------------------------------------------------------------------
+void USBD_ConfigureSpeed(unsigned char forceFS)
+{
+ if (forceFS) {
+ AT91C_BASE_UDPHS->UDPHS_TST |= AT91C_UDPHS_SPEED_CFG_FS;
+ }
+ else {
+ AT91C_BASE_UDPHS->UDPHS_TST &= ~(unsigned int)AT91C_UDPHS_SPEED_CFG_FS;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Returns the current state of the USB device.
+/// \return Device current state.
+//------------------------------------------------------------------------------
+unsigned char USBD_GetState( void )
+{
+ return deviceState;
+}
+
+
diff --git a/usb/device/core/core.dir b/usb/device/core/core.dir new file mode 100644 index 0000000..fcf0dc0 --- /dev/null +++ b/usb/device/core/core.dir @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !Purpose
+///
+/// This directory contains structures, definitions and functions for AT91 UDP.
+/// They can be divided into two groups:
+/// - Hardware layer: low-level operations on the USB UDP controller
+/// - USBD_OTGHS.c USBD_UDP.c USBD_UDPHS.c
+/// - USB Device API: other files in the directory, offers hardware-independent
+/// methods and structures
+//------------------------------------------------------------------------------
+
diff --git a/usb/device/device.dir b/usb/device/device.dir new file mode 100644 index 0000000..2988e1e --- /dev/null +++ b/usb/device/device.dir @@ -0,0 +1,655 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for USB %device
+/// applications with Atmel AT91 microcontrollers and USB %device framework.
+///
+/// You can develop your own USB %device products based on the class-specific
+/// driver code provided, or just take them as a refference.
+///
+/// !!!Contents
+/// There are two groups for the implement:
+/// -# The hardware interface driver for USB peripheral on AT91
+/// microcontrollers (UDP or UDPHS), this is a part of the "AT91 USB
+/// framework".
+/// - "core": hardware interface driver for AT91 USB peripheral
+/// -# The %device class driver to class-specific %device.
+/// - "audio-speaker"
+/// - "ccid"
+/// - "cdc-serial"
+/// - "hid-keyboard"
+/// - "massstorage"
+///
+/// For more information about what a particular group contains, please refer to
+/// its documentation page.
+///
+/// \note
+/// Depending on the project, not all the subdirectories will be available
+/// (i.e. the #ccid# directory will not be in projects without USB CCID
+/// function).
+//------------------------------------------------------------------------------
+
+/**
+ \page "USBD API"
+
+ See "USBD API Structures" and "USBD API Methods".\n
+
+ !!!USBD API Structures
+
+ Several specific structures are used by the USBD API to perform various
+ operations, such as invoking callbacks or accessing the USBD controller.
+
+ There are two %main structures:
+ - USBDDriver:
+ It is the %main structure of the USB API. It should be instanciated
+ in class-specific USB %device driver or user application.
+ - USBDDriverDescriptors:
+ It is a list of all descriptors used by a USB %device driver. It
+ should be instanciated in class-specific USB %device driver or
+ user application and passed to USBD by USBDDriver_Initialize.
+
+ !!!USBD API Methods
+
+ The USB API provides serveral methods to perform the following operations:
+ - Changing the %device state
+ - USBD_Init
+ - USBD_Connect, USBD_Disconnect
+ - USBD_SetAddress
+ - USBD_SetConfiguration
+ - USBD_GetState
+ - "USB Device State Diagram"
+ - Handling events coming from the USB controller
+ - USBD_IrqHandler
+ - Modifying the behavior of an endpoint
+ - USBD_ConfigureEndpoint
+ - USBD_Stall
+ - USBD_Halt
+ - USBD_Unhalt
+ - USBD_IsHalted
+ - Transferring data
+ - USBD_Write
+ - USBD_Read
+ - USBD_IsoWrite
+ - Special functions
+ - USBD_RemoteWakeUp
+
+ See "USBD API Methods" for detailed informations.
+
+*/
+
+/**
+ \page "USBD API Structures"
+
+ !!!USBD API Structures
+
+ Several specific structures are used by the USBD API to perform various
+ operations, such as invoking callbacks or accessing the USBD controller.
+
+ There are two %main structures:
+ - USBDDriver:
+ It is the %main structure of the USB API. It should be instanciated
+ in class-specific USB %device driver or user application.
+ - USBDDriverDescriptors:
+ It is a list of all descriptors used by a USB %device driver. It
+ should be instanciated in class-specific USB %device driver or
+ user application and passed to USBD by USBDDriver_Initialize.
+
+ */
+
+/**
+ \page "USBD API Methods"
+
+ !!!USB API methods
+
+ The USB API provides serveral methods to perform the following operations:
+ - Changing the %device state
+ - USBD_Init
+ - USBD_Connect, USBD_Disconnect
+ - USBD_SetAddress
+ - USBD_SetConfiguration
+ - USBD_GetState
+ - "USB Device State Diagram"
+ - Handling events coming from the USB controller
+ - USBD_IrqHandler
+ - Modifying the behavior of an endpoint
+ - USBD_ConfigureEndpoint
+ - USBD_Stall
+ - USBD_Halt
+ - USBD_Unhalt
+ - USBD_IsHalted
+ - Transferring data
+ - USBD_Write
+ - USBD_Read
+ - USBD_IsoWrite
+ - Special functions
+ - USBD_RemoteWakeUp
+
+ !!!Controlling the Device State
+
+ Chapter 9 of the USB specification 2.0 describes the various states a %device
+ can be in. Most of the methods of this API are used to change between those
+ states.
+
+ !!USBD_Init
+
+ USBD_Init is the first method to call in a user application. Technically, it
+ must occur just before entering the Attached state. It performs the following
+ actions:
+ - USB Device driver and endpoint state initialization
+ - D+ pull-up configuration and disabling
+ - UDP hardware initialization (Peripheral and clock init)
+
+ A USB %device uses a pull-up on the D+ line to signal its connection to the
+ host. Depending on the USB controller present on the chip, either an
+ internal or external pull-up is used. In both cases, its configuration is
+ performed directly by this method. Please refer to the documentation of a
+ particular controller for more information about the D+ pull-up.
+
+ The ini callback has to perform several mandatory operations at this point.
+ You can find the default operations in USBDCallbacks_Initialized.
+
+ !!USBD_Connect, USBD_Disconnect
+
+ These two methods control the state of the D+ upll-up. This makes it possible
+ to connect of disconnect the %device by software when needed. USBD_Connect
+ changes the %device state from Powered to Default, while USBD_Disconnect
+ changes from either Default, Address or Configured to Powered.
+
+ !!USBD_SetAddress
+
+ USBD_SetAddress extracts the information from the last received
+ SETUP packet to either change the %device state from Default to
+ Address or from Address to Default. The difference is made
+ depending on the value of the wValue field of the request.
+
+ This method must only be called right after the SET_ADDRESS
+ request is received.
+
+ !!USBD_SetConfiguration
+
+ This function operates in a way similar to USBD_SetAddress. When the SETUP
+ packet containing a SET_CONFIGURATION request is received,
+ USBD_SetConfiguration should be called to extract the new configuration
+ value to adopt. If the wValue field of the request is non-zero, then the
+ %device must adopt the new configuration and enter the Configuration state;
+ otherwise, it returns (or stays) in the Address state.
+
+ !!USBD_GetState
+
+ As its name implies, USBD_GetState simply returns the current state of the USB
+ driver. See state definitions on "USB %device states".
+ - USBD_STATE_SUSPENDED
+ - USBD_STATE_ATTACHED
+ - USBD_STATE_POWERED
+ - USBD_STATE_DEFAULT
+ - USBD_STATE_ADDRESS
+ - USBD_STATE_CONFIGURED
+
+ !!Device State Diagram
+ See "USB Device State Diagram"
+
+ !!!Event Handling (USBD_IrqHandler)
+ Several events can occur at the USB controller level:
+ - End of bus reset
+ - Reception of a SETUP packet
+ - Change of bus activity (active -> idle -> active ..)
+ - Completin of an endpoint operation
+ - ...
+
+ Whenever such an event occurs, it must be forwarded to the USBD API to be
+ handled in an appropriate way. The USBD_IrqHandler performs this
+ functionality, so the controller interrupt must be configured to call it.
+
+ Several #callbacks# can be triggered depending on the event notified by
+ the controller:
+ - Suspend, when the bus is idle
+ - Resume, when the bus becomes active again
+ - NewRequest, when a setup packet is received on a control endpoint
+ - StartOfFrame, every 1 ms (for full-speed controllers) or 125us (for high-
+ speed controllers)
+
+ More information about these callbacks and their expected behavior can be
+ found in "USBD Callback API".
+
+ !!!Endpoint Behavior Modification
+
+ The USBD API offers following functions to control how an endpoint operates.
+ - USBD_ConfigureEndpoint
+ - USBD_Stall
+ - USBD_Halt
+ - USBD_Unhalt
+ - USBD_IsHalted
+
+ !!USBD_ConfigureEndpoint
+ USBD_ConfigureEndpoint is used to configure an endpoint at the USB controller
+ level. An appropriate endpoint descriptor must be provided to do that. The
+ descriptor is used to configure the endpoint type (either Control, Bulk,
+ Interrupt or Isochronous), direction (IN or OUT) and address.
+
+ Control endpoint 0 is automatically configured by the USBD API when the End of
+ bus reset event is signalled by the USB controller. Therefore, there is no need
+ to do it manually.
+
+ !!USBD_Stall
+ The USBD_Stall method causes and endpoint to acknowledge its next received
+ packet with a STALL handshake. Further packets are then handled normally.
+
+ Most of the time, this method should be used with endpoint 0 to signal the
+ host that the %device cannot process a command.
+
+ !!USBD_Halt, USBD_Unhalt, USBD_IsHalted
+ USBD_Halt sets the Halt status of an endpoint. When in Halt mode, every
+ received packet is acknowledged with a STALL handshake instead of being
+ handled normally.
+
+ #}USB_Halt#} can be called either with the USB_SET_FEATURE, USB_CLEAR_FEATURE
+ or USB_GET_STATUS parameter to modify the endpoint Halt state.
+
+ USBD_Unhalt clears the Halt status of an endpoint.
+
+ USBD_IsHalted gets the Halt status of an endpoint.
+
+ !!!Data Transfer
+ Data transfer (IN or OUT) on an endpoint can be performed by calling two
+ methods, USBD_Write and USBD_Read.
+
+ !!USBD_Write
+ The USBD_Write function sends a data payload on a specific endpoint. If the
+ data payload equals or exceeds the maximum packet size of the endpoint, then
+ several IN transactions are necessary. This method should only be called on an
+ IN or Control endpoint.
+
+ The write is performed #asynchronously#, i.e., the function returns immediately
+ without waiting for the transfer to finish. When the transfer is complete, an
+ optional user-provided callback function is called. This makes it possible to
+ create an #OS-friendly synchronous function# by locking and unlocking a
+ semaphore before and after each write.
+
+ This function handles double-buffering, if it is supported by the USB
+ controller and if it has been enabled for the endpoint. Do not forget that
+ using double-buffering is mandatory for isochronous transactions.
+
+ - #Note#
+ The double-buffering this function supported is only in period of each
+ write action. That is, when the function is invoked to start transfer
+ trunk of data, the data is automatically splitted to several IN
+ transactions and ping-pong is started on the 2nd transaction. But when
+ all the data of the trunk is finished the ping-pong is stopped. So it can
+ not process the list of buffer that should use double-buffering all the
+ time. See USBD_IsoWrite for such kind of operations.
+
+ !!USBD_Read
+ The USBD_Read reads incoming data on an endpoint. The transfer stops either
+ when the provided buffer is full, or a short packet (size inferior to the
+ endpoint maximum packet size) is received. This method must only be called on
+ an OUT or Control endpoint.
+
+ The read is performed #asynchronously#, i.e., the function returns immediately
+ without waiting for the transfer to finish. When the transfer is complete, an
+ optional user-provided callback function is called. This makes it possible to
+ create an #OS-friendly synchronous function# by locking and unlocking a
+ semaphore before and after each read.
+
+ This function handles #double-buffering#, if it is supported by the USB
+ controller and if it has been enabled for the endpoint. Do not forget that
+ using double-buffering is mandatory for isochronous transactions.
+
+ !!USBD_IsoWrite
+ The USBD_IsoWrite function sends a buffer list on a specific endpoint. The each
+ buffer's payload should be equals or less than the maximum packet size of the
+ endpoint. The transfer ends when all buffera are sent out. And the buffer is
+ previously sent can be filled with new data before the transfer ends. To
+ maitain a ring buffer for the outgoing stream. This method should only be
+ called on an ISO IN endpoint.
+
+ The write is performed #asynchronously#, i.e., the function returns immediately
+ without waiting for the transfer to finish. When the transfer is complete, an
+ optional user-provided callback function is called. This makes it possible to
+ create an #OS-friendly synchronous function# by locking and unlocking a
+ semaphore before and after each write.
+
+ This function handles double-buffering, if it is supported by the USB
+ controller and if it has been enabled for the endpoint. Do not forget that
+ using double-buffering is mandatory for isochronous transactions.
+
+ !!!Special Functions
+
+ - USBD_RemoteWakeUp: This method starts a remote wakeup procedure. This makes
+ it possible for a suspended %device to wake a host with may itself be
+ suspended.
+
+*/
+
+/**
+ \page "USB Device State Diagram"
+
+ \image USBDeviceStateDiagram.png "Changing the Device State"
+
+*/
+
+/* (Image Link Backup)
+<img src="USBDeviceStateDiagram.png" border=0 alt="USBDeviceStateDiagram.png" usemap="#USBD_ST_DIA">
+<MAP NAME="USBD_ST_DIA">
+<AREA shape="poly" coords="172,0,330,0,330,26,172,26,172,0" onmouseover="link('_member','core/USBD_Init53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_Init (void )',CAPTION,'<strong>Brief description</strong><BR>Initializes the specified USB driver This<BR>function initializes the current FIFO bank of<BR>endpoints, configures the pull-up and VBus<BR>lines, disconnects the pull-up and then<BR>trigger the Init callback.');" onmouseout="return nd();">
+<AREA shape="poly" coords="269,390,425,390,425,416,269,416,269,390" onmouseover="link('_member','core/USBD_SetAddress2593655934',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_SetAddress (unsigned char address)',CAPTION,'<strong>Brief description</strong><BR>Sets the device address.');" onmouseout="return nd();">
+<AREA shape="poly" coords="76,390,233,390,233,416,76,416,76,390" onmouseover="link('_member','core/USBD_SetAddress2593655934',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_SetAddress (0)',CAPTION,'<strong>Brief description</strong><BR>Unsets the device address.');" onmouseout="return nd();">
+<AREA shape="poly" coords="76,509,233,509,233,535,76,535,76,509" onmouseover="link('_member','core/USBD_SetConfiguration2593655934',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_SetConfiguration (0)',CAPTION,'<strong>Brief description</strong><BR>Changes the device state from Configured to Address.');" onmouseout="return nd();">
+<AREA shape="poly" coords="261,509,418,509,418,535,261,535,261,509" onmouseover="link('_member','core/USBD_SetConfiguration2593655934',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_SetConfiguration (unsigned char cfgnum)',CAPTION,'<strong>Brief description</strong><BR>Changes the device state from Address to Configured.');" onmouseout="return nd();">
+<AREA shape="poly" coords="284,242,440,242,440,269,284,269,284,242" onmouseover="link('_member','core/USBD_Connect53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_Connect (void )',CAPTION,'<strong>Brief description</strong><BR>Enables the pull-up on the D+ line to connect the device to the USB.');" onmouseout="return nd();">
+<AREA shape="poly" coords="60,242,217,242,217,269,60,269,60,242" onmouseover="link('_member','core/USBD_Disconnect53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_Disconnect (void )',CAPTION,'<strong>Brief description</strong><BR>Disables the pull-up on the D+ line to disconnect the<BR>device from the bus.');" onmouseout="return nd();">
+</MAP>
+
+<MAP NAME="usbd_cb_invo_fc">
+<AREA shape="poly" coords="436,739,600,739,600,765,436,765,436,739" onmouseover="link('_member','core/USBDCallbacks_Resumed53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBDCallbacks_Resumed (void )',CAPTION,'<strong>Brief description</strong><BR>Invoked when the USB device leaves the Suspended state.');" onmouseout="return nd();">
+<AREA shape="poly" coords="436,406,600,406,600,432,436,432,436,406" onmouseover="link('_member','core/USBDCallbacks_Resumed53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBDCallbacks_Resumed (void )',CAPTION,'<strong>Brief description</strong><BR>Invoked when the USB device leaves the Suspended state.');" onmouseout="return nd();">
+<AREA shape="poly" coords="436,605,600,605,600,632,436,632,436,605" onmouseover="link('_member','core/USBDCallbacks_Suspended53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBDCallbacks_Suspended (void )',CAPTION,'<strong>Brief description</strong><BR>Invoked when the USB device gets suspended. By default,<BR>turns off all LEDs.');" onmouseout="return nd();">
+<AREA shape="poly" coords="436,339,600,339,600,365,436,365,436,339" onmouseover="link('_member','coreUSBDCallbacks_Suspended53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBDCallbacks_Suspended (void )',CAPTION,'<strong>Brief description</strong><BR>Invoked when the USB device gets suspended. By default,<BR>turns off all LEDs.');" onmouseout="return nd();">
+<AREA shape="poly" coords="436,272,600,272,600,299,436,299,436,272" onmouseover="link('_member','core/USBDCallbacks_RequestReceived2520836348',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBDCallbacks_RequestReceived (const USBGenericRequest * request)',CAPTION,'<strong>Brief description</strong><BR>Triggered when the USB host emits a new SETUP request.');" onmouseout="return nd();">
+<AREA shape="poly" coords="436,206,600,206,600,232,436,232,436,206" onmouseover="link('_member','core/USBDCallbacks_Reset53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBDCallbacks_Reset ( void )',CAPTION,'<strong>Brief description</strong><BR>Triggered when the USB host emits a RESET.')">
+<AREA shape="poly" coords="436,102,600,102,600,129,436,129,436,102" onmouseover="link('_member','core/USBDCallbacks_Initialized53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBDCallbacks_Initialized (void )',CAPTION,'<strong>Brief description</strong><BR>Invoked after the USB driver has been initialized.');" onmouseout="return nd();">
+<AREA shape="poly" coords="221,374,384,374,384,400,221,400,221,374" onmouseover="link('_member','core/USBD_IrqHandler53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_IrqHandler (void )',CAPTION,'<strong>Brief description</strong><BR>UDP interrupt handler. Manages device status changes.');" onmouseout="return nd();">
+<AREA shape="poly" coords="221,307,384,307,384,333,221,333,221,307" onmouseover="link('_member','core/USBD_IrqHandler53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_IrqHandler (void )',CAPTION,'<strong>Brief description</strong><BR>UDP interrupt handler. Manages device status changes.');" onmouseout="return nd();">
+<AREA shape="poly" coords="221,240,384,240,384,266,221,266,221,240" onmouseover="link('_member','core/USBD_IrqHandler53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_IrqHandler (void )',CAPTION,'<strong>Brief description</strong><BR>UDP interrupt handler. Manages device status changes.');" onmouseout="return nd();">
+<AREA shape="poly" coords="221,173,384,173,384,199,221,199,221,173" onmouseover="link('_member','core/USBD_IrqHandler53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_IrqHandler (void )',CAPTION,'<strong>Brief description</strong><BR>UDP interrupt handler. Manages device status changes.');" onmouseout="return nd();">
+<AREA shape="poly" coords="221,36,384,36,384,62,221,62,221,36" onmouseover="link('_member','core/USBD_Init53616',this);overLibDiagram();return overlib('<strong>Syntax</strong><BR>void USBD_Init (void )',CAPTION,'<strong>Brief description</strong><BR>Initializes the USB driver.');" onmouseout="return nd();">
+<AREA shape="poly" coords="0,407,163,407,163,434,0,434,0,407" onmouseover="overLibDiagram();return overlib('UDP_ISR: AT91C_UDP_SOFINT')" onmouseout="return nd();">
+<AREA shape="poly" coords="0,340,163,340,163,367,0,367,0,340" onmouseover="overLibDiagram();return overlib('UDP_ISR: AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM')" onmouseout="return nd();">
+<AREA shape="poly" coords="0,273,163,273,163,300,0,300,0,273" onmouseover="overLibDiagram();return overlib('UDP_ISR: AT91C_UDP_RXSUSP')" onmouseout="return nd();">
+<AREA shape="poly" coords="0,139,163,139,163,165,0,165,0,139" onmouseover="overLibDiagram();return overlib('UDP_ISR: AT91C_UDP_ENDBUSRES')" onmouseout="return nd();">
+<AREA shape="poly" coords="0,206,163,206,163,232,0,232,0,206" onmouseover="overLibDiagram();return overlib('UDP_CSR: AT91C_UDP_RXSETUP')" onmouseout="return nd();">
+<AREA shape="poly" coords="436,672,600,672,600,698,436,698,436,672" title="ISR_Vbus">
+<AREA shape="poly" coords="436,539,600,539,600,565,436,565,436,539" title="ISR_Vbus">
+<AREA shape="poly" coords="482,0,554,0,554,13,482,13,482,0" title="Applications">
+<AREA shape="poly" coords="278,0,331,0,331,13,278,13,278,0" title="USBD API">
+<AREA shape="poly" coords="36,0,128,0,128,13,36,13,36,0" title="UDP_, UDPHS_">
+</MAP>
+<IMG SRC="USBDCallbackInvocationFlowchart.png" border=0 ALT="USBDCallbackInvocationFlowchart.png" usemap="#usbd_cb_invo_fc">
+*/
+
+/**
+ \page "USBD Callback API"
+
+ !!!Callback API
+
+ The callback API is a means of communication between the user application and
+ the USBD API. When particular operations must be performed, the USB driver
+ calls serveral external functions, refferred to as #callbacks#. They can also
+ be invoked to notify the user application of pending events.
+
+ Defining all callbacks is not mandatory. For example, if the %device shall not
+ enter low-power mode, then it is appropriate not to provide a Suspend callback.
+ If a callback is mandatory, this is notified in its description.
+
+ See USBDCallbacks.h for callback definitions.
+
+ !!!Callback Invocation
+ The following events can trigger a callback:
+ - USB initialization: USBDCallbacks_Initialized
+ - End of bus reset: USBDCallbacks_Reset
+ - Device suspend: USBDCallbacks_Suspended
+ - Device resume: USBDCallbacks_Resumed
+ - SETUP request received: USBDCallbacks_RequestReceived
+ - Start of a new USB frame
+
+ \image USBDCallbackInvocationFlowchart.png "Callback Invocation Flowchart"
+
+ !!Init
+ The USBDCallbacks_Initialized callback is invoked when the USBD_Init method is
+ called. It has to perform several mandatory steps to make it possible to use
+ the API:
+ - If an OS is used, perform any specific operation to install the driver
+ - Configure USB controller interrupt
+ - Configure Vbus monitoring PIO and interrupt ( but it's in app layer now )
+ The USB controller interrupt must be configured to #call the
+ USBD_IrqHandler# API function when triggered. This is necessary to have
+ events happening at the USB controller level handled appropriately by the API.
+
+ If a PIO pin is connected to VBus, it is possible to monitor it by configuring
+ the pin as an input and enabling the PIO interrupt. The interrupt service
+ routine should simply check the Vbus status and then %call the USBD_Connect
+ and USBD_Disconnect$ function to put %device into right state.
+
+ Finally, if an OS is being used, then the driver should probably be installed
+ prior to use. Interrupt configuration may also be done differently. Please
+ refer to the documentation of the OS for more information.
+
+ This callback is #mandatory#.
+
+ !!Reset
+ When an End of bus reset has been detected, the USBDCallbacks_Reset callback
+ is triggered. The callback should perform #initialization# or #re-
+ initialization# of the user-level application. For example, a class driver
+ like MSD should re-initialize its internal state when a USB reset is performed.
+
+ !!Suspend
+ When the USB %device enters the Suspended state, the USB API notifies this state
+ change by invoking the USBDCallbacks_Suspended callback. This can happen either
+ when the bus is idle or when the %device is disconnected from the USB.
+
+ If the %device should enter low-power mode when suspended, then this callback
+ must perform the required operations to do so, e.g., switching to a slow clock,
+ disabling PLLs, etc.
+
+ - }Note: The electrical specification of the USB 2.0 defines a maximum current
+ consumption of 500uA for suspended %device. This includes the current passing
+ through pull-ups and upll-downs.}
+
+ !!Resume
+ The USBDCallbacks_Resumed callback is invoked when the USB %device leaves the
+ Suspended state and returns to its previous state (either Powered, Default,
+ Address or Configured). This may happen when activity is detected on the USB,
+ or when the %device gets connected.
+
+ If the %device was in low-power mode because of the Suspend callback, then this
+ callback must perform the necessary poerations to return the %device into a
+ normal operation mode, e.g., switching to a fast clock.
+
+ !!NewRequest
+ When a SETUP request is received on a control endpoint, the USBD API layer
+ triggers the USBDCallbacks_RequestReceived callback to notify the user
+ application. The received request can then be accessed through the
+ corresponding USBGenericRequest structure.
+
+ SETUP packets are used for class-specific requests (e.g. }GetMaxLUN} in MSD)
+ as well as standard USB requests (e.g. }SetConfiguration}). The former are
+ described in }USB Device Class Documents}, such as the }Mass Storage Bulk
+ Only 1.0}, the latter are defined in the USB Specification 2.0.
+
+ - }Note: that SETUP requests which are not understood by the %device should
+ be acknowledged with a STALL handshake. This notifies the host that the
+ %device cannot process the command.}
+
+ This callback is #mandatory#.
+
+ !!StartOfFrame
+ Every 1ms (for a full-speed %device) or 125us (for a high-speed %device) a
+ new USB frame starts. A callback can be invoked whenever this occurs.
+
+ Because the start-of-frame interrupt %puts some stress on the processor
+ (since it is called a lot), it is only activated the corresponding
+ callback is defined (#now it's NOT defined in current framework#).
+
+*/
+
+/**
+ \page "USBD Standard Request Handler"
+
+ !!!Standard Request Handler
+
+ Chapter 9 of the USB specification 2.0 defines a set of standard requests
+ which have to be implemented by all devices. Since most class drivers treat
+ those requests in the standard way, the USB framework provides a way to easily
+ do that.
+
+ !!!USBDDriver_RequestHandler
+
+ USBDDriver_RequestHandler handles the standard requests in an appropriate way.
+ It can answer the following commands:
+
+ - GET_DESCRIPTOR
+ - SET_ADDRESS
+ - SET_CONFIGURATION
+ - GET_CONFIGURATION
+ - CLEAR_FEATURE
+ - SET_FEATURE
+ - GET_STATUS
+
+ Simply using this standard request handler enables a %device to be enumerated
+ correctly.
+
+ !!Get Descriptor
+ The GET_DESCRIPTOR request is used by the host to retrieve information about
+ the %device by means of several descriptors.
+
+ The standard request handler simply sends the corresponding descriptor to the
+ host. How these descriptors are provided to the function is discussed in
+ Structures.
+
+ !!Set Address
+ Whenever the host wants to change the %device state from Default to Address, or
+ vice-versa, it sends a SET_ADDRESS request. The wValue field contains the new
+ address of the %device; if it is null, then the %device returns to the Default
+ state.
+
+ The USBD_SetAddress function is called to perform this operation. Note that a
+ zero-length packet must be sent prior to doing that, to acknowledge the SETUP
+ transfer.
+
+ !!Set Configuration & GetConfiguration
+ The SET_CONFIGURATION request makes it possible for the host to select between
+ one or more configurations for the %device. GET_CONFIGURATION is used to
+ retrieve the currently selected one.
+
+ Those two requests are handled in a very basic way by
+ USBDDriver_RequestHandler: it assumes that the %device has only one
+ configuration. Therefore, the SET_CONFIGURATION request is simply acknowledged
+ with a zero-length packet, and GET_CONFIGURATION is answered with either 0
+ or 1. If the user application needs more than one configuration, it will be
+ the duty of the class driver handler to service those requests.
+
+ In addition, when the SET_CONFIGURATION request causes the %device to enter the
+ Configured state, the standard request handler calls the USBD_ConfigureEndpoint
+ method for each endpoint used by the %device;
+
+ !!Clear Feature, Set Feature & Get Status
+ Several features of a %device can either be activated or deactivated by the USB
+ host:
+ - Remote wakeup
+ - Endpoint Halt state
+ Three requests can be used to either set, clear or get the status of these two
+ features: SET_FEATURE, CLEAR_FEATURE and GET_STATUS.
+
+ The USBDDriver_RequestHandler method answers a Halt state operation by calling
+ the USBD_Halt method on the endpoint with the request.
+
+ !!!Structures
+ Several pieces of information must be known to the USBDDriver_RequestHandler
+ to be able to process some SETUP commands. For example, all the descriptors
+ (configuration, etc.) used by the %device are needed since they must be sent
+ to the host when a GET_DESCRIPTOR is received.
+
+ The USBGenericRequest structure is a "standard USB class driver" object used
+ to hold the required information. It must be passed as an argument to the
+ USBDDriver_RequestHandler method. Another structure, USBDDriverDescriptors, is
+ used to store the descriptors list.
+
+ !!!Usage
+ The NewRequest callback is used to notify the user application that a new SETUP
+ request has been received. SETUP request can either be class-specific or
+ standard.
+
+ The correct way to handle incoming requests is to first process class-specific
+ requests using a class handler. For example, a Mass Storage implementation will
+ define the NewRequest callback to call MSDDriver_RequestHandler. This function
+ will handle the necessary requests, and forward the rest to
+ USBDDriver_RequestHandler.
+
+ If a request cannot be processed, USBDDriver_RequestHandler will STALL control
+ endpoint 0.
+
+*/
+
+/**
+ \page "VID, PID, SN & Strings"
+
+ This page collects the definition for USB %device to indicate the Vendor and
+ Product information.
+
+
+ If you need only the functions in demo %driver, you can easily modify these
+ definitions to change your device's Identification and Display strings.
+
+ They are defined in the driver c code file that suffixed with
+ "DriverDescriptors" under the driver directory.
+
+ !!!VID, PID & SN in Device Descriptor
+
+ Defined as const and used in USBDeviceDescriptor instance initialization.
+ Gives identivication to the USB %device by VID and PID. The INF installation
+ file should mach the VID & PID so that the %device can be installed.
+
+\code
+const USBDeviceDescriptor deviceDescriptor = {...};
+\endcode
+
+ - "audio-speaker": "Audio Speaker Device Codes"
+ - ccid: "CCID Device IDs"
+ - "cdc-serial": "CDC Serial Device IDs"
+ - "hid-keyboard": "HID Device Descriptor IDs"
+ - massstorage: "MSD Device Descriptor IDs"
+
+ !!!Strings
+
+ The strings gives additional information on the USB %device, normally string
+ description about the vendor, product and serial number.
+
+ The strings are defined as a list to initialize the driver's
+ USBDDriverDescriptors instance:
+
+ - "audio-speaker": auddSpeakerDriverDescriptors
+ - ccid: ccidDriverDescriptors
+ - "cdc-serial": cdcdSerialDriverDescriptors
+ - "hid-keyboard": hiddKeyboardDriverDescriptors
+ - massstorage: msdDriverDescriptors
+
+\code
+// String descriptors
+const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor,
+};
+\endcode
+*/
diff --git a/usb/device/hid-keyboard/HIDClassArch.png b/usb/device/hid-keyboard/HIDClassArch.png Binary files differnew file mode 100644 index 0000000..6d09580 --- /dev/null +++ b/usb/device/hid-keyboard/HIDClassArch.png diff --git a/usb/device/hid-keyboard/HIDDKeyboardCallbacks.h b/usb/device/hid-keyboard/HIDDKeyboardCallbacks.h new file mode 100644 index 0000000..6bbfaea --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardCallbacks.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardCallbacks
+
+ !!!Purpose
+
+ Definitions of callbacks used by the HID keyboard device driver to
+ notify the application of events.
+
+ !!!Usage
+
+ -# Re-implement any number of these callbacks anywhere in the program;
+ they will be called automatically by the driver when the related
+ event occurs.
+*/
+
+#ifndef HIDDKEYBOARDCALLBACKS_H
+#define HIDDKEYBOARDCALLBACKS_H
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDKeyboardCallbacks_LedsChanged(unsigned char numLockStatus,
+ unsigned char capsLockStatus,
+ unsigned char scrollLockStatus);
+
+#endif //#ifndef HIDDKEYBOARDCALLBACKS_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c b/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c new file mode 100644 index 0000000..be8963d --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------------
+ * 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 "HIDDKeyboardCallbacks.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Indicates that the status of one or more LEDs has been changed by the
+/// host.
+/// \param numLockStatus Indicates the current status of the num. lock key.
+/// \param capsLockStatus Indicates the current status of the caps lock key.
+/// \param scrollLockStatus Indicates the current status of the scroll lock key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardCallbacks_LedsChanged(
+ unsigned char numLockStatus,
+ unsigned char capsLockStatus,
+ unsigned char scrollLockStatus)
+{
+ TRACE_INFO(
+ "LEDs status: %d, %d, %d\n\r",
+ numLockStatus,
+ capsLockStatus,
+ scrollLockStatus);
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriver.c b/usb/device/hid-keyboard/HIDDKeyboardDriver.c new file mode 100644 index 0000000..e244cb5 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriver.c @@ -0,0 +1,477 @@ +/* ----------------------------------------------------------------------------
+ * 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 "HIDDKeyboardDriver.h"
+#include "HIDDKeyboardDriverDescriptors.h"
+#include "HIDDKeyboardCallbacks.h"
+#include "HIDDKeyboardInputReport.h"
+#include "HIDDKeyboardOutputReport.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDGenericRequest.h>
+#include <usb/common/hid/HIDReportRequest.h>
+#include <usb/common/hid/HIDIdleRequest.h>
+#include <usb/common/hid/HIDKeypad.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Driver structure for an HID device implementing keyboard functionalities.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard USB device driver instance.
+ USBDDriver usbdDriver;
+ /// Idle rate (in milliseconds) of the input report.
+ unsigned char inputReportIdleRate;
+ /// Input report instance.
+ HIDDKeyboardInputReport inputReport;
+ /// Output report instance.
+ HIDDKeyboardOutputReport outputReport;
+
+} HIDDKeyboardDriver;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Static instance of the HID keyboard device driver.
+static HIDDKeyboardDriver hiddKeyboardDriver;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+/**
+ Returns the descriptor requested by the host.
+
+\param type Descriptor type.
+\param length Maximum number of bytes to send.
+\return 1 if the request has been handled by this function, otherwise 0.
+*/
+static unsigned char HIDDKeyboardDriver_GetDescriptor(unsigned char type,
+ unsigned char length)
+{
+ const USBConfigurationDescriptor *pConfiguration;
+ HIDDescriptor *hidDescriptors[2];
+
+ switch (type) {
+
+ case HIDGenericDescriptor_REPORT:
+ TRACE_INFO_WP("Report ");
+
+ // Adjust length and send report descriptor
+ if (length > HIDDKeyboardDriverDescriptors_REPORTSIZE) {
+
+ length = HIDDKeyboardDriverDescriptors_REPORTSIZE;
+ }
+ USBD_Write(0, &hiddReportDescriptor, length, 0, 0);
+ break;
+
+ case HIDGenericDescriptor_HID:
+ TRACE_INFO_WP("HID ");
+
+ // Configuration descriptor is different depending on configuration
+ if (USBD_IsHighSpeed()) {
+
+ pConfiguration = hiddKeyboardDriver.usbdDriver.pDescriptors->pHsConfiguration;
+ }
+ else {
+
+ pConfiguration = hiddKeyboardDriver.usbdDriver.pDescriptors->pFsConfiguration;
+ }
+
+ // Parse the device configuration to get the HID descriptor
+ USBConfigurationDescriptor_Parse(
+ pConfiguration,
+ 0,
+ 0,
+ (USBGenericDescriptor **) hidDescriptors);
+
+ // Adjust length and send HID descriptor
+ if (length > sizeof(HIDDescriptor)) {
+
+ length = sizeof(HIDDescriptor);
+ }
+ USBD_Write(0, hidDescriptors[0], length, 0, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ Sends the current Idle rate of the input report to the host.
+*/
+static void HIDDKeyboardDriver_GetIdle()
+{
+ TRACE_INFO_WP("gIdle ");
+
+ USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
+}
+
+/**
+ Retrieves the new idle rate of the input report from the USB host.
+
+ \param idleRate New input report idle rate.
+*/
+static void HIDDKeyboardDriver_SetIdle(unsigned char idleRate)
+{
+ TRACE_INFO_WP("sIdle(%d) ", idleRate);
+
+ hiddKeyboardDriver.inputReportIdleRate = idleRate;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+/**
+ Sends the requested report to the host.
+
+\param type Report type.
+\param length Maximum number of bytes to send.
+*/
+static void HIDDKeyboardDriver_GetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO_WP("gReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ TRACE_INFO_WP("In ");
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardInputReport)) {
+
+ length = sizeof(HIDDKeyboardInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ TRACE_INFO_WP("Out ");
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardOutputReport)) {
+
+ length = sizeof(HIDDKeyboardOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+/**
+ Callback invoked when an output report has been received from the host.
+ Forward the new status of the LEDs to the user program via the
+ HIDDKeyboardCallbacks_LedsChanged callback.
+*/
+static void HIDDKeyboardDriver_ReportReceived()
+{
+ TRACE_INFO_WP("oReport ");
+
+ // Trigger callback
+ HIDDKeyboardCallbacks_LedsChanged(
+ HIDDKeyboardOutputReport_GetNumLockStatus(&(hiddKeyboardDriver.outputReport)),
+ HIDDKeyboardOutputReport_GetCapsLockStatus(&(hiddKeyboardDriver.outputReport)),
+ HIDDKeyboardOutputReport_GetScrollLockStatus(&(hiddKeyboardDriver.outputReport)));
+
+ // Restart transfer
+ USBD_Read(HIDDKeyboardDriverDescriptors_INTERRUPTOUT,
+ &(hiddKeyboardDriver.outputReport),
+ sizeof(HIDDKeyboardOutputReport),
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument for callback function
+}
+
+/**
+ Retrieves the new value of a report from the host and saves it.
+
+\param type Report type.
+\param length Report length.
+*/
+static void HIDDKeyboardDriver_SetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO_WP("sReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDKeyboardOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ HIDDKeyboardDriver_RequestHandler(request);
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+// ConfigurationChanged() callback re-implementation
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ // Start receiving output reports
+ USBD_Read(HIDDKeyboardDriverDescriptors_INTERRUPTOUT,
+ &(hiddKeyboardDriver.outputReport),
+ sizeof(HIDDKeyboardOutputReport),
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument for callback function
+ }
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+/**
+ Initializes the HID keyboard device driver.
+*/
+void HIDDKeyboardDriver_Initialize()
+{
+ hiddKeyboardDriver.inputReportIdleRate = 0;
+ HIDDKeyboardInputReport_Initialize(&(hiddKeyboardDriver.inputReport));
+ HIDDKeyboardOutputReport_Initialize(&(hiddKeyboardDriver.outputReport));
+ USBDDriver_Initialize(&(hiddKeyboardDriver.usbdDriver),
+ &hiddKeyboardDriverDescriptors,
+ 0); // Multiple interface settings not supported
+ USBD_Init();
+}
+
+/**
+ Handles HID-specific SETUP request sent by the host.
+
+ \param request Pointer to a USBGenericRequest instance.
+*/
+void HIDDKeyboardDriver_RequestHandler(const USBGenericRequest *request)
+{
+ TRACE_INFO_WP("NewReq ");
+
+ // Check if this is a standard request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
+
+ // This is a standard request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor, otherwise forward it to
+ // the standard driver
+ if (!HIDDKeyboardDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ }
+ // Check if this is a class request
+ else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ // This is a class-specific request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case HIDGenericRequest_GETIDLE:
+ HIDDKeyboardDriver_GetIdle();
+ break;
+
+ case HIDGenericRequest_SETIDLE:
+ HIDDKeyboardDriver_SetIdle(HIDIdleRequest_GetIdleRate(request));
+ break;
+
+ case HIDGenericRequest_GETREPORT:
+ HIDDKeyboardDriver_GetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ case HIDGenericRequest_SETREPORT:
+ HIDDKeyboardDriver_SetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ default:
+ TRACE_WARNING(
+ "HIDDKeyboardDriver_RequestHandler: Unknown REQ 0x%02X\n\r",
+ USBGenericRequest_GetRequest(request));
+ USBD_Stall(0);
+ }
+ }
+ else {
+
+ // Vendor request ?
+ USBD_Stall(0);
+ }
+}
+
+/**
+ Reports a change in which keys are currently pressed or release to the
+ host.
+
+\param pressedKeys Pointer to an array of key codes indicating keys that have
+ been pressed since the last call to HIDDKeyboardDriver_ChangeKeys.
+\param pressedKeysSize Number of key codes in the pressedKeys array.
+\param releasedKeys Pointer to an array of key codes indicates keys that have
+ been released since the last call to HIDDKeyboardDriver_ChangeKeys.
+\param releasedKeysSize Number of key codes in the releasedKeys array.
+\return USBD_STATUS_SUCCESS if the report has been sent to the host;
+ otherwise an error code.
+*/
+unsigned char HIDDKeyboardDriver_ChangeKeys(unsigned char *pressedKeys,
+ unsigned char pressedKeysSize,
+ unsigned char *releasedKeys,
+ unsigned char releasedKeysSize)
+{
+ // Press keys
+ while (pressedKeysSize > 0) {
+
+ // Check if this is a standard or modifier key
+ if (HIDKeypad_IsModifierKey(*pressedKeys)) {
+
+ // Set the corresponding bit in the input report
+ HIDDKeyboardInputReport_PressModifierKey(
+ &(hiddKeyboardDriver.inputReport),
+ *pressedKeys);
+ }
+ else {
+
+ HIDDKeyboardInputReport_PressStandardKey(
+ &(hiddKeyboardDriver.inputReport),
+ *pressedKeys);
+ }
+
+ pressedKeysSize--;
+ pressedKeys++;
+ }
+
+ // Release keys
+ while (releasedKeysSize > 0) {
+
+ // Check if this is a standard or modifier key
+ if (HIDKeypad_IsModifierKey(*releasedKeys)) {
+
+ // Set the corresponding bit in the input report
+ HIDDKeyboardInputReport_ReleaseModifierKey(
+ &(hiddKeyboardDriver.inputReport),
+ *releasedKeys);
+ }
+ else {
+
+ HIDDKeyboardInputReport_ReleaseStandardKey(
+ &(hiddKeyboardDriver.inputReport),
+ *releasedKeys);
+ }
+
+ releasedKeysSize--;
+ releasedKeys++;
+ }
+
+ // Send input report through the interrupt IN endpoint
+ return USBD_Write(HIDDKeyboardDriverDescriptors_INTERRUPTIN,
+ &(hiddKeyboardDriver.inputReport),
+ sizeof(HIDDKeyboardInputReport),
+ 0,
+ 0);
+}
+
+//------------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//------------------------------------------------------------------------------
+void HIDDKeyboardDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&(hiddKeyboardDriver.usbdDriver))) {
+
+ USBD_RemoteWakeUp();
+ }
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriver.h b/usb/device/hid-keyboard/HIDDKeyboardDriver.h new file mode 100644 index 0000000..42dc0a2 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriver.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardDriver
+
+ !!!Purpose
+
+ Definition of methods for using a HID keyboard device driver.
+
+ !!!Usage
+
+ -# Re-implement the USBDCallbacks_RequestReceived callback to forward
+ requests to HIDDKeyboardDriver_RequestHandler. This is done
+ automatically unless the NOAUTOCALLBACK symbol is defined during
+ compilation.
+ -# Initialize the driver using HIDDKeyboardDriver_Initialize. The
+ USB driver is automatically initialized by this method.
+ -# Call the HIDDKeyboardDriver_ChangeKeys method when one or more
+ keys are pressed/released.
+*/
+
+#ifndef HIDDKEYBOARDDRIVER_H
+#define HIDDKEYBOARDDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDKeyboardDriver_Initialize();
+
+extern void HIDDKeyboardDriver_RequestHandler(const USBGenericRequest *request);
+
+extern unsigned char HIDDKeyboardDriver_ChangeKeys(
+ unsigned char *pressedKeys,
+ unsigned char pressedKeysSize,
+ unsigned char *releasedKeys,
+ unsigned char releasedKeysSize);
+
+extern void HIDDKeyboardDriver_RemoteWakeUp(void);
+
+#endif //#ifndef HIDDKEYBOARDDRIVER_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c new file mode 100644 index 0000000..51dfb48 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c @@ -0,0 +1,420 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDKeyboardDriverDescriptors
+
+ About: Purpose
+ Declaration of the descriptors used by the HID device keyboard driver.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardDriverDescriptors.h"
+#include "HIDDKeyboardInputReport.h"
+#include "HIDDKeyboardOutputReport.h"
+#include <board.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDeviceDescriptor.h>
+#include <usb/common/hid/HIDInterfaceDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDReport.h>
+#include <usb/common/hid/HIDGenericDesktop.h>
+#include <usb/common/hid/HIDLeds.h>
+#include <usb/common/hid/HIDKeypad.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Device Descriptor IDs"
+/// This page lists VID, PID & Release number.
+///
+/// !IDs
+/// - HIDDKeyboardDriverDescriptors_PRODUCTID
+/// - HIDDKeyboardDriverDescriptors_VENDORID
+/// - HIDDKeyboardDriverDescriptors_RELEASE
+
+/// Device product ID.
+#define HIDDKeyboardDriverDescriptors_PRODUCTID 0x6127
+/// Device vendor ID.
+#define HIDDKeyboardDriverDescriptors_VENDORID 0x03EB
+/// Device release number.
+#define HIDDKeyboardDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// List of descriptors that make up the configuration descriptors of a
+/// device using the HID keyboard driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Configuration descriptor.
+ USBConfigurationDescriptor configuration;
+ /// Interface descriptor.
+ USBInterfaceDescriptor interface;
+ /// HID descriptor.
+ HIDDescriptor hid;
+ /// Interrupt IN endpoint descriptor.
+ USBEndpointDescriptor interruptIn;
+ /// Interrupt OUT endpoint descriptor.
+ USBEndpointDescriptor interruptOut;
+
+} __attribute__ ((packed)) HIDDKeyboardDriverConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Device descriptor.
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDKeyboardDriverDescriptors_VENDORID,
+ HIDDKeyboardDriverDescriptors_PRODUCTID,
+ HIDDKeyboardDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Device qualifier descriptor (high-speed only).
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // One possible configuration
+ 0 // Reserved
+};
+#endif
+
+/// Configuration descriptor.
+static const HIDDKeyboardDriverConfigurationDescriptors configurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+ }
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Other-speed configuration descriptor.
+static const HIDDKeyboardDriverConfigurationDescriptors otherSpeedDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT_POLLING
+ }
+};
+#endif
+
+/// Language ID string descriptor.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static 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.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(23),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('H'),
+ USBStringDescriptor_UNICODE('I'),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('K'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('Y'),
+ USBStringDescriptor_UNICODE('B'),
+ USBStringDescriptor_UNICODE('O'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('R'),
+ USBStringDescriptor_UNICODE('D')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(12),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('F')
+};
+
+/// Array of pointers to string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors used by the HID keyboard driver.
+USBDDriverDescriptors hiddKeyboardDriverDescriptors = {
+
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+#else
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration
+ 0, // No high-speed device descriptor
+ 0, // No high-speed configuration descriptor
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+#endif
+ stringDescriptors,
+ 4 // Four string descriptors in list
+};
+
+/// Report descriptor used by the driver.
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+
+ HIDReport_ENDCOLLECTION
+};
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h new file mode 100644 index 0000000..9a2dc2f --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardDriverDescriptors
+
+ !!!Purpose
+
+ Definitions of the descriptors required by the HID device keyboard
+ driver.
+
+ !!!Usage
+
+ -# Use the hiddKeyboardDriverDescriptors variable to initialize a
+ USBDDriver instance.
+ -# Send hiddReportDescriptor to the host when a GET_DESCRIPTOR request
+ for the report descriptor is received.
+*/
+
+#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+#define HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+#include <usb/common/hid/HIDKeypad.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Endpoints"
+/// This page lists endpoint addresses and polling settings.
+///
+/// !Endpoints
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTIN
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTOUT
+///
+/// !Polling Rates
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTOUT_POLLING
+
+/// Interrupt IN endpoint number.
+#define HIDDKeyboardDriverDescriptors_INTERRUPTIN 1
+/// Interrupt IN endpoint polling rate (in milliseconds).
+#define HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING 10
+/// Interrupt OUT endpoint number.
+#define HIDDKeyboardDriverDescriptors_INTERRUPTOUT 2
+/// Interrupt OUT endpoint polling rate (in milliseconds).
+#define HIDDKeyboardDriverDescriptors_INTERRUPTOUT_POLLING 10
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Keypad keys"
+/// This page lists definition for HID keypad keys.
+///
+/// !Keys
+/// - HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY
+/// - HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY
+/// - HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY
+/// - HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY
+
+/// Key code of the first accepted modifier key.
+#define HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY HIDKeypad_LEFTCONTROL
+/// Key code of the last accepted modifier key.
+#define HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY HIDKeypad_RIGHTGUI
+/// Key code of the first accepted standard key.
+#define HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY 0
+/// Key code of the last accepted standard key.
+#define HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY HIDKeypad_NUMLOCK
+//------------------------------------------------------------------------------
+
+/// Size of the report descriptor in bytes.
+#define HIDDKeyboardDriverDescriptors_REPORTSIZE 61
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+extern USBDDriverDescriptors hiddKeyboardDriverDescriptors;
+
+extern const unsigned char hiddReportDescriptor[];
+
+#endif //#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardInputReport.c b/usb/device/hid-keyboard/HIDDKeyboardInputReport.c new file mode 100644 index 0000000..3257bdb --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardInputReport.c @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDKeyboardInputReport implementation
+
+ About: Purpose
+ Implementation of the HIDDKeyboardInputReport class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardInputReport.h"
+#include "HIDDKeyboardDriverDescriptors.h"
+#include <utility/assert.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes a keyboard input report instance.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_Initialize(HIDDKeyboardInputReport *report)
+{
+ unsigned int i;
+
+ report->bmModifierKeys = 0;
+ for (i = 0; i < HIDDKeyboardInputReport_MAXKEYPRESSES; i++) {
+
+ report->pressedKeys[i] = 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reports a standard key as being pressed.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the standard key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_PressStandardKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT(key <= HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Find first available slot
+ unsigned int i = 0;
+ unsigned char found = 0;
+ while ((i < HIDDKeyboardInputReport_MAXKEYPRESSES) && !found) {
+
+ // Free slot: no key referenced (code = 0) or ErrorRollOver
+ if ((report->pressedKeys[i] == 0)
+ || (report->pressedKeys[i] == HIDKeypad_ERRORROLLOVER)) {
+
+ found = 1;
+ report->pressedKeys[i] = key;
+ }
+
+ i++;
+ }
+
+ // Report ErrorRollOver in all fields if too many keys are pressed
+ if (!found) {
+
+ for (i=0; i < HIDDKeyboardInputReport_MAXKEYPRESSES; i++) {
+
+ report->pressedKeys[i] = HIDKeypad_ERRORROLLOVER;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reports a standard key as not being pressed anymore.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the standard key
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_ReleaseStandardKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT(key <= HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Look for key in array
+ unsigned int i = 0;
+ unsigned char found = 0;
+ while ((i < HIDDKeyboardInputReport_MAXKEYPRESSES) && !found) {
+
+ if (report->pressedKeys[i] == key) {
+
+ found = 1;
+ report->pressedKeys[i] = 0;
+ }
+
+ i++;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reports a modifier key as being currently pressed.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the modifier key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_PressModifierKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT((key >= HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY)
+ && (key <= HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY),
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Set corresponding bit
+ unsigned char bit = key - HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY;
+ report->bmModifierKeys |= 1 << bit;
+}
+
+//------------------------------------------------------------------------------
+/// Reports a modifier key as not being pressed anymore.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the modifier key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_ReleaseModifierKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT((key >= HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY)
+ && (key <= HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY),
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Clear corresponding bit
+ unsigned char bit = key - HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY;
+ report->bmModifierKeys &= ~(1 << bit);
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardInputReport.h b/usb/device/hid-keyboard/HIDDKeyboardInputReport.h new file mode 100644 index 0000000..7eeafd8 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardInputReport.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardInputReport.h
+
+ !!!Purpose
+
+ Class for manipulating HID keyboard input reports.
+
+ !!!Usage
+
+ -# Initialize a newly created input report with
+ HIDDKeyboardInputReport_Initialize.
+ -# Change the standard keys that are pressed and released using
+ HIDDKeyboardInputReport_PressStandardKey and
+ HIDDKeyboardInputReport_ReleaseStandardKey.
+ -# Change the modifier keys that are currently pressed and released
+ using HIDDKeyboardInputReport_PressModifierKey and
+ HIDDKeyboardInputReport_ReleaseModifierKey.
+*/
+
+#ifndef HIDDKEYBOARDINPUTREPORT_H
+#define HIDDKEYBOARDINPUTREPORT_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Maximum number of simultaneous key presses.
+#define HIDDKeyboardInputReport_MAXKEYPRESSES 3
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// HID input report structure used by the keyboard driver to notify the
+/// host of pressed keys.
+///
+/// The first byte is used to report the state of modifier keys. The
+/// other three contains the keycodes of the currently pressed keys.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// State of modifier keys.
+ unsigned char bmModifierKeys:8;
+ /// Key codes of pressed keys.
+ unsigned char pressedKeys[HIDDKeyboardInputReport_MAXKEYPRESSES];
+
+} __attribute__ ((packed)) HIDDKeyboardInputReport; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+/*
+ Function: HIDDKeyboardInputReport_Initialize
+ Initializes a keyboard input report instance.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+*/
+extern void HIDDKeyboardInputReport_Initialize(HIDDKeyboardInputReport *report);
+
+/*
+ Function: HIDDKeyboardInputReport_PressStandardKey
+ Reports a standard key as being pressed.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the standard key.
+*/
+extern void HIDDKeyboardInputReport_PressStandardKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+/*
+ Function: HIDDKeyboardInputReport_ReleaseStandardKey
+ Reports a standard key as not being pressed anymore.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the standard key
+*/
+extern void HIDDKeyboardInputReport_ReleaseStandardKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+/*
+ Function: HIDDKeyboardInputReport_PressModifierKey
+ Reports a modifier key as being currently pressed.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the modifier key.
+*/
+extern void HIDDKeyboardInputReport_PressModifierKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+/*
+ Function: HIDDKeyboardInputReport_ReleaseModifierKey
+ Reports a modifier key as not being pressed anymore.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the modifier key.
+*/
+extern void HIDDKeyboardInputReport_ReleaseModifierKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+#endif //#ifndef HIDDKEYBOARDINPUTREPORT_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c new file mode 100644 index 0000000..f79d7ac --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c @@ -0,0 +1,94 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDKeyboardOutputReport implementation
+
+ About: Purpose
+ Implementation of the HIDDKeyboardOutputReport class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardOutputReport.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes a keyboard output report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+//------------------------------------------------------------------------------
+void HIDDKeyboardOutputReport_Initialize(HIDDKeyboardOutputReport *report)
+{
+ report->numLockStatus = 0;
+ report->capsLockStatus = 0;
+ report->scrollLockStatus = 0;
+ report->padding = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the current status of the num. lock LED according to the
+/// given report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+/// \return 1 if the num. lock LED is light on; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char HIDDKeyboardOutputReport_GetNumLockStatus(
+ const HIDDKeyboardOutputReport *report)
+{
+ return report->numLockStatus;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the current status of the caps lock LED according to the
+/// given report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+/// \return 1 if the caps lock LED is light on; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char HIDDKeyboardOutputReport_GetCapsLockStatus(
+ const HIDDKeyboardOutputReport *report)
+{
+ return report->capsLockStatus;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the current status of the scroll lock LED according to the
+/// given report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+/// \return 1 if the scroll lock LED is light on; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char HIDDKeyboardOutputReport_GetScrollLockStatus(
+ const HIDDKeyboardOutputReport *report)
+{
+ return report->scrollLockStatus;
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardOutputReport.h b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.h new file mode 100644 index 0000000..760df1b --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.h @@ -0,0 +1,96 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardOutputReport
+
+ !!!Purpose
+
+ Definition of a class for manipulating HID keyboard output reports.
+
+ !!!Usage
+
+ -# Initialize a newly-created output report instance with
+ HIDDKeyboardOutputReport_Initialize.
+ -# Retrieve the status of the three LEDs using
+ HIDDKeyboardOutputReport_GetNumLockStatus,
+ HIDDKeyboardOutputReport_GetCapsLockStatus and
+ HIDDKeyboardOutputReport_GetScrollLockStatus.
+*/
+
+#ifndef HIDKEYBOARDOUTPUTREPORT_H
+#define HIDKEYBOARDOUTPUTREPORT_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// HID output report structure used by the host to control the state of
+/// the keyboard LEDs.
+///
+/// Only the first three bits are relevant, the other 5 are used as
+/// padding bits.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char numLockStatus:1, /// State of the num. lock LED.
+ capsLockStatus:1, /// State of the caps lock LED.
+ scrollLockStatus:1, /// State of the scroll lock LED.
+ padding:5; /// Padding bits.
+
+} __attribute__ ((packed)) HIDDKeyboardOutputReport; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDKeyboardOutputReport_Initialize(
+ HIDDKeyboardOutputReport *report);
+
+extern unsigned char HIDDKeyboardOutputReport_GetNumLockStatus(
+ const HIDDKeyboardOutputReport *report);
+
+extern unsigned char HIDDKeyboardOutputReport_GetCapsLockStatus(
+ const HIDDKeyboardOutputReport *report);
+
+extern unsigned char HIDDKeyboardOutputReport_GetScrollLockStatus(
+ const HIDDKeyboardOutputReport *report);
+
+#endif //#ifndef HIDKEYBOARDOUTPUTREPORT_H
+
diff --git a/usb/device/hid-keyboard/hid-keyboard.dir b/usb/device/hid-keyboard/hid-keyboard.dir new file mode 100644 index 0000000..923a362 --- /dev/null +++ b/usb/device/hid-keyboard/hid-keyboard.dir @@ -0,0 +1,787 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB HID
+/// %device - USB HID Keyboard driver, to implement an USB keyboard %device.
+///
+/// !!!Contents
+///
+/// There are three things for the implement of the USB HID Keyboard driver:
+/// - Implement the USB HID driver structs and functions for the %device,
+/// to initialize, to handle HID-specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the HID Keyboard device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the %device as a USB Keyboard %device.
+/// - Implement methods to update the keyboard keys status, so that host can
+/// get it through USB.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB HID Keyboard".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB HID Keyboard"
+ This page describes how to use the "AT91 USB device framework" to produce a USB
+ HID Keyboard driver, which appears as a USB keyboard on host.
+
+ Details about the USB and the HID class can be found in the }USB specification
+ 2.0} and the }HID specification 1.11}, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+ !!!HID Basic
+ See "USB HID Basic".
+
+ !!!Architecture
+ See "USB Device Framework Architecture".
+
+ !!!Descriptors
+
+ ...
+
+ !!Device Descriptor
+ The Device descriptor of an HID %device is very basic, since the HID class
+ code is only specified at the Interface level. Thus, it only contains
+ standard values, as shown below:
+\code
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDKeyboardDriverDescriptors_VENDORID,
+ HIDDKeyboardDriverDescriptors_PRODUCTID,
+ HIDDKeyboardDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+\endcode
+ Note that the Vendor ID is a special value attributed by the USB-IF
+ organization. The product ID can be chosen freely by the vendor.
+
+ !!Configuration Descriptor
+ Since one interface is required by the HID specification, this must be
+ specified in the Configuration descriptor. There is no other value of
+ interest to put here.
+\code
+// Configuration descriptor
+{
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+},
+\endcode
+ When the Configuration descriptor is requested by the host (by using the
+ GET_DESCRIPTOR command), the %device must also sent all the related
+ descriptors, i.e. Interface, Endpoint and Class-Specific descriptors. It is
+ convenient to create a single structure to hold all this data, for sending
+ everything in one chunk. In the example software, a
+ HIDDKeyboardDriverConfigurationDescriptors structure has been declared for
+ that.
+
+ !!HID Class Interface Descriptor
+ Since a keyboard %device needs to transmit as well as receive data, two
+ Interrupt (IN & OUT) endpoints are needed. This must be indicated in the
+ Interface descriptor. Conversely to the mouse example, the Boot protocol is
+ not implemented here, since there are more constraints on a keyboard %device.
+\code
+// Interface descriptor
+{
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+},
+\endcode
+
+ !!HID Descriptor
+ While a HID keyboard produces two different reports, one Input and one Output,
+ only one Report descriptor can be used to describe them. Since having Physical
+ descriptors is also useless for a keyboard, there will only be one HID class
+ descriptor specified here.
+
+ For a keyboard, the }bCountryCode} field can be used to specify the language
+ of the key caps. As this is optional, it is simply set to 00h in the example:
+\code
+// HID descriptor
+{
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+},
+\endcode
+
+ !!Report Descriptor
+ Two current reports are defined in the Report descriptor. The first one is
+ used to notify the host of which keys are pressed, with both modifier keys
+ (alt, ctrl, etc.) and alphanumeric keys. The second report is necessary for
+ the host to send the LED (num lock, caps lock, etc.) states.
+
+ The Report descriptor starts with the global %device functionality, described
+ with a #Usage Page# and a #Usage# items:
+\code
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
+\endcode
+
+ As in the mouse example, the }Generic Desktop} page is used. This time, the
+ specific usage is the }Keyboard} one. An Application collection is then
+ defined to group the reports together:
+\code
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+\endcode
+
+ The first report to be defined is the modifier keys. They are represented as a
+ bitmap field, indicating whether or not each key is pressed. A single byte is
+ used to map keys \#224-231 defined in the }HID Usage Tables} document:
+ LeftControl, LeftShift, LeftAlt, LeftGUI (e.g. Windows key),
+ RightControl, RightShift, RightAlt and RightGUI.
+ The }Keypad} usage page must be specified for this report, and since this is a
+ bitmap value, the data is flagged as }Variable}:
+\code
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Then, the actual alphanumeric key report is described. This is done by
+ defining several bytes of data, one for each pressed key. In the example,
+ up to three keys can be pressed at the same time (and detected) by the user.
+ Once again, the usage page is set to }Keypad}. This time however, the data
+ must be specified as an }Array}, since the same control (the keypad) produces
+ several values:
+\code
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+\endcode
+
+ The LED array is then defined, with the associated usage page. The Report
+ descriptor is formatted in this order to avoid redefining unchanged }Global}
+ items, in order to save memory. This time again, the LED status is reported as
+ a bitmap field. Three LEDs are used here: Num Lock, Caps Lock and Scroll Lock
+ (IDs 01h to 03h). It is important to note that this is an #Output# report:
+\code
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Since the previous report only contains 3 bits, the data must be padded to a
+ multiple of one byte. This is done by using constant Output data, as follows:
+\code
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+\endcode
+
+ The last item, }End Collection}, is necessary to close the previously opened
+ }Application Collection}.
+\code
+ HIDReport_ENDCOLLECTION
+};
+\endcode
+
+ The Input and Output reports defined by this descriptor can be modeled by the
+ following structures:
+\code
+// HID Input Report
+typedef struct {
+
+ // State of modifier keys.
+ unsigned char bmModifierKeys:8;
+ // Key codes of pressed keys.
+ unsigned char pressedKeys[HIDDKeyboardInputReport_MAXKEYPRESSES];
+
+} __attribute__ ((packed)) HIDDKeyboardInputReport; // GCC
+// HID Output Report
+typedef struct {
+
+ unsigned char numLockStatus:1, // State of the num. lock LED.
+ capsLockStatus:1, // State of the caps lock LED.
+ scrollLockStatus:1, // State of the scroll lock LED.
+ padding:5; // Padding bits.
+
+} __attribute__ ((packed)) HIDDKeyboardOutputReport; // GCC
+\endcode
+
+ An instance of each one of the reports is stored in a HIDDKeyboardDriver
+ structure, which holds the standard class driver and HID keyboard-specific
+ data.
+
+ !!Physical Descriptor
+ A Physical descriptor is useless for a keyboard %device, so none are defined
+ in this example.
+
+ !!Endpoint Descriptor
+ Following the Interface and HID-specific descriptors, the two necessary
+ endpoints are defined.
+\code
+// Interrupt IN endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+},
+// Interrupt OUT endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+}
+\endcode
+
+ !!String Descriptors
+ Please refer to "Usage: USBD VID, PID & Strings".
+
+ !!!Class-specific requests
+ A driver request handler should first differentiate between class-specific and
+ standard requests using the corresponding bits in the }bmRequestType} field.
+ In most cases, standard requests can be immediately forwarded to the standard
+ request handler method; class-specific methods must be decoded and treated by
+ the custom handler.
+
+ !!GetDescriptor
+ Three values have been added by the HID specification for the #GET_DESCRIPTOR#
+ request. The high byte of the }wValue} field contains the type of the
+ requested descriptor; in addition to the standard types, the #HID
+ specification# adds the #HID descriptor# (21h), the #Report descriptor#
+ (22h) and the #Physical descriptor# (23h) types.
+
+ There is no particular action to perform besides sending the descriptor. This
+ can be done by using the USBD_Write method, after the requested descriptor has
+ been identified:
+\code
+switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor,
+ // otherwise forward it to
+ // the standard driver
+ if (!HIDDKeyboardDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+}
+\endcode
+ A slight complexity of the GET_DESCRIPTOR and SET_DESCRIPTOR requests is that
+ those are standard requests, but the standard request handler
+ (USBDDriver_RequestHandler) must not always be called to treat them (since
+ they may refer to HID descriptors). The solution is to first identify
+ GET/SET_DESCRIPTOR requests, treat the HID-specific cases and, finally,
+ forward any other request to the standard handler.
+
+ In this case, a GET_DESCRIPTOR request for the Physical descriptor is first
+ forwarded to the standard handler, and STALLed there because it is not
+ recognized. This is done because the %device does not have any Physical
+ descriptors, and thus, does not need to handle the associated request.
+
+ !!SetDescriptor
+ This request is optional and is never issued by most hosts. It is not
+ implemented in this example.
+
+ !!GetReport
+ Since the HID keyboard defines two different reports, the Report Type value
+ specified by this request (upper byte of the }wValue} field) must be examined
+ to decide which report to send. If the type value is 01h, then the Input
+ report must be returned; if it is 02h, the Output report is requested:
+\code
+case HIDGenericRequest_GETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardInputReport)) {
+
+ length = sizeof(HIDDKeyboardInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardOutputReport)) {
+
+ length = sizeof(HIDDKeyboardOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetReport
+ For an HID keyboard, the #SET_REPORT# command can be sent by the host to
+ change the state of the LEDs. Normally, the dedicated Interrupt OUT endpoint
+ will be used for this; but in some cases, using the default Control endpoint
+ can save some bandwidth on the host side.
+
+ Note that the SET_REPORT request can be directed at the Input report of the
+ keyboard; in this case, it can be safely discarded, according to the HID
+ specification. Normally, most host drivers only target the Output report. The
+ Report Type value is stored in the upper byte of the }wValue} field.
+
+ The length of the data phase to follow is stored in the }wLength} field of the
+ request. It should be equal to the total length of the Output report. If it is
+ different, the report status must still be updated with the received data as
+ best as possible.
+
+ When the reception of the new data is completed, some processing must be done
+ to enable/disable the corresponding LEDs. This is done in the callback
+ function passed as an argument to USBD_Read:
+\code
+case HIDGenericRequest_SETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch(type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDKeyboardOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetIdle
+ In this case study, the #SET_IDLE# request is used to set a delay before a key
+ is repeated. This is common behavior on keyboard devices. Usually, this delay
+ is set to about 500 ms by the host.
+
+ The only action here is to store the new Idle rate. The management of this
+ setting must be done in the main function, since Interrupt IN reports are sent
+ from there.
+
+ In practice, it is not necessary to perform any action, apart from sending a
+ zero-length packet to acknowledge it. The main application however has to make
+ sure that only new reports are sent by the %device.
+\code
+case HIDGenericRequest_SETIDLE:
+//-----------------------------
+ hiddKeyboardDriver.inputReportIdleRate =
+ HIDIdleRequest_GetIdleRate(request);
+ USBD_Write(0, 0, 0, 0, 0);
+break;
+\endcode
+
+ !!GetIdle
+ The only necessary operation for this request is to send the previously saved
+ Idle rate. This is done by calling the USBD_Write method with the one-byte
+ variable as its parameter:
+\code
+case HIDGenericRequest_GETIDLE:
+//-----------------------------
+ USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
+break;
+\endcode
+
+ !!GetProtocol, SetProtocol
+ This HID keyboard example does not support the Boot protocol, so there is no
+ need to implement the SET_PROTOCOL and GET_PROTOCOL requests. This means they
+ can be safely STALLed when received.
+
+ !!!Main Application
+ Like the mouse example, the main program must perform two different
+ operations. First, it has to monitor the physical inputs used as keys. In the
+ example software, the buttons present on the evaluation boards are used to
+ produce several modifier and alphanumeric keys.
+
+ Also, the main program is in charge of sending reports as they are modified,
+ taking into account the Idle rate specified by the host. Idle rate management
+ can be carried out by firing/resetting a timer once a new report is sent; if
+ the timer expires, this means the Input report has not changed since.
+ According to the HID specification, a single instance of the report must be
+ sent in this case.
+
+ Finally, the HID specification also defines that if too many keys are pressed
+ at the same time, the %device should report an }ErrorRollOver} usage value
+ (01h) in every byte of the key array. This has to be handled by the main
+ application as well.
+
+*/
+
+/**
+ \page "USB HID Mouse"
+ This page describes how to implement a mouse %device using the HID class and
+ the "AT91 USB device framework". Details about the USB and the HID class can
+ be found in the }USB specification 2.0} and the }HID specification 1.11}
+ documents, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+
+
+*/
+
+/**
+ \page "USB HID Basic"
+
+ This page gives generic details on the HID class, including its purpose,
+ architecture and how it is supported by various operating systems.
+
+ !!!Purpose
+
+ The HID class has been specifically designed for Human Interface Devices,
+ i.e., devices which are manipulated by humans to control a computer or an
+ electronic %device. This includes common peripherals such as a keyboard, a
+ mouse or a joystick, as well as many other interfaces: remote controllers,
+ switches, buttons, dedicated game controls, and so on.
+
+ It is also possible to use the HID class for devices which do not require
+ human interaction, but still deliver information in a similar format. For
+ example, devices like a thermometer or a battery indicator are supported.
+
+ In addition, the HID class also makes it possible to not only receive data
+ from devices but also to send commands to them. Indeed, many devices offer
+ some kind of display to give back information to the user, e.g., the LEDs on a
+ keyboard.
+
+ Finally, since it is quite simple to send and receive data using the HID
+ class, it can be used as a generic means of communication between a %device
+ and a host. This is made possible because of the very flexible framework
+ defined in the HID specification.
+
+ In this document, three uses of the HID class will be detailed step-by-step,
+ each showing one particular feature of the class. The first example shows the
+ interaction with a simple mouse. In the second example, a keyboard is
+ implemented to demonstrate the possibility to send data to a peripheral. The
+ last example explains how to use HID as a simple two-way communication
+ channel.
+
+ !!!Architecture
+ ...
+
+ !!Interface
+ An HID %device only needs #one interface descriptor#. It should have the HID
+ interface class code in its bInterfaceClass field. There are special subclass
+ and protocol codes to specify if the HID %device is a mouse or a keyboard, and
+ must be supported by the BIOS. In such a case, the interface must be declared
+ as a Boot Interface, and the type of the %device (mouse or keyboard) must be
+ given in the bInterfaceProtocol field.
+
+ !!Endpoints
+ Up to three endpoints can be used with an HID interface. The first two are the
+ default Control endpoint 0, as well as an Interrupt IN endpoint. They are
+ mandatory and shall always be declared. An optional Interrupt OUT endpoint can
+ be added as well.
+
+ Endpoint 0 is used for class-specific requests, as well as receiving data from
+ the host if no Interrupt OUT endpoint has been defined. In addition, the host
+ can also explicitly request or send report data through this endpoint.
+
+ The Interrupt IN and OUT pipes are used for sending asynchronous data to the
+ host, and to receive low-latency information.
+
+ \image HIDClassArch.png "HID Class Driver Architecture"
+
+ !!Class-Specific Descriptors
+ There are three class-specific descriptors defined in the }HID specification
+ 1.11}: the HID descriptor, the report descriptor and the physical descriptor.
+
+ !HID Descriptor
+ The HID descriptor gives information about the HID specification revision
+ used, the country for which a %device is localized, and lists the number of
+ class-specific descriptors, including their length and type.
+
+ HID Descriptor Format
+||Field||Size(bytes)||Description
+|bLength|1|Total length of the HID descriptor
+|bDescriptorType|1|HID descriptor type (21h)
+|bcdHID|2|HID specification release number in BCD format
+|bCountryCode|1|Code of the country for which the %device is located.\n
+ Should be 0 if the %device is not localized.
+|bNumDescriptors|1|Number of class-specific descriptors used by the %device.
+|bDescriptorType|1|Type of the first class-specific descriptor.
+|bDescriptorLength|1|Total length of the first class-specific descriptor.
+|[bDescriptorType]|1|Type of the second class-specific descriptor.
+|[bDescriptorLength]|1|Total length of the second class-specific descriptor.
+|...| |
+
+ There is always at least one Report descriptor for an HID %device, so the
+ corresponding fields must be present in the HID descriptor. If other
+ descriptors are defined, they must also be described here.
+
+ !Report Descriptor
+ A HID %device must have at least one #Report descriptor#. It defines the type
+ of data manipulated by the %device, which is referred to as report. When the
+ %device wants to notify that the cursor has moved, for example, it sends the
+ corresponding report in the format previously defined in the Report
+ descriptor.
+
+ This descriptor is quite different from others, as it does not have a fixed
+ table of values. Instead, it is made up of a variable number of items, which
+ collectively identify the information that a host can expect from or send to
+ the %device.
+
+ There are five categories of items:
+ - #Input# items, which define the format and type of the data sent by the
+ %device.
+ - #Output# items, which define the format and type of the data expected by
+ the %device
+ - #Feature# items, which define data sent to or received from the %device,
+ and not intended for the end user, such as configuration parameters.
+- #Collection# items, which identify a set of data as related to the same
+ group.
+- #End Collection# items, which close other Collection items.
+
+ Usually, a Report descriptor defines only one use (report) for a %device, e.g.,
+ a mouse. However, it is possible to declare several reports to perform
+ different tasks, e.g., mouse & keyboard. This is done by assigning a different
+ #Report ID# to each report; this makes it possible for the %device to send
+ both reports through the same Interrupt endpoint, while still permitting the
+ host to correctly identify the data. Using only a single endpoint for several
+ functionalities is very powerful, as the remaining ones can then be used by
+ other interfaces (CDC, MSD, etc.) for an even more versatile %device.
+
+ More details about Report descriptors will be given in the implementation
+ examples. For more information about the possible items, tags and values,
+ please refer to the }HID specification 1.11.}
+
+ !Physical Descriptor
+ A #Physical descriptor# can be used to give information about which human body
+ part is used to activate a particular control. While this is a useless piece
+ of information for most devices, it can be relevant for complex devices which
+ provide many similar controls. In such a case, a Physical descriptor allows an
+ application to assign its functionalities more appropriately; for example, a
+ game controller often has a large number of buttons, with some of them more
+ accessible than the others. Those buttons would be assigned the most useful
+ actions.
+
+ Since physical descriptors are not used very often, and are not useful in the
+ case studies described in this document, they will not be discussed further.
+
+ !!Class-specific Requests
+ ...
+
+ !GetDescriptor
+ While #GET_DESCRIPTOR# is a standard request (defined in the }USB
+ specification 2.0}), new descriptor type values have been added for the HID
+ class. They make it possible for the host to request the HID descriptor,
+ Report descriptor and Physical descriptors used by the %device.
+
+ When requesting a HID-specific descriptor, the }wIndex} field of the request
+ must be set to the HID interface number. For standard requests, this field is
+ either set to 0 or, for String descriptors, to the index of the language ID
+ used.
+
+ !SetDescriptor
+ Similarly, #SET_DESCRIPTOR# is a standard request with added HID-specific
+ values. It is used by the host to change the HID descriptors of a %device.
+ This is an optional request, and has few practical uses.
+
+ !GetReport
+ The host can explicitly ask the %device for a report by using the #GET_REPORT#
+ request. However, it should be used primarily to get the state of feature
+ items and absolute values at initialization time, not for consistent %device
+ polling.
+
+ The requested report is identified either by its Report ID (if they are used),
+ and/or by its type (Input, Output or Feature).
+
+ Please note that a GET_REPORT request is different from a GET_DESCRIPTOR
+ request for the Report descriptor. The latter returns the whole Report
+ descriptor, i.e., all the items declared. The former returns the data defined
+ by this descriptor.
+
+ !SetReport
+ #SET_REPORT# is similar to GET_REPORT, except this request is used for
+ changing the state of a report, instead of simply retrieving it.
+
+ For an Input report, this request can either be considered meaningless, or can
+ be used to reset the current status of a control. For example, it could be
+ used to calibrate the neutral position of a joystick.
+
+ !SetIdle
+ This request is used to specify the minimum amount of time, called #Idle
+ rate#, that a %device must wait before transmitting a report if its state has
+ not changed. This means the %device must NAK all polls on its Interrupt IN
+ endpoint until the report state changes, or the guarding period expires.
+
+ The SET_IDLE command can either be issued for a particular duration, or for an
+ undefined period of time. The upper byte of the wValue field is used to
+ specify this duration. In addition, if the %device generates multiple reports,
+ the Report ID of the target report to affect can be specified in the lower
+ byte.
+
+ In practice, this request is often used with a keyboard to put a small delay
+ before a key is repeated continuously. For a mouse, it must be set to 0,
+ meaning that the %device should never report an unchanged state.
+
+ !GetIdle
+ The GET_IDLE request is issued by the host to retrieve the current Idle rate
+ of the %device. A particular Report can be specified with its Report ID.
+
+ !GetProtocol
+ This request returns the protocol currently used by the %device. This can
+ either be the Report protocol (}wValue} set to 0) or the Boot protocol
+ (}wValue} set to 1). Since a %device supporting the Boot protocol can operate
+ differently depending on which mode it is in, the host system can retrieve or
+ change this mode with the GET_PROTOCOL and SET_PROTOCOL requests.
+
+ This request is only need for devices supporting the Boot protocol.
+
+ !SetProtocol
+ Whenever an HID %device starts up, it should use the Report protocol by
+ default. However, the host driver shall still use the SET_PROTOCOL
+ request to specify if the %device should use the Report protocol or the
+ Boot protocol.
+
+ !!!Host Drivers
+ Most operating systems provide a generic HID driver which automatically
+ handles standard devices, such as keyboard, mice and joystick. In addition,
+ the driver can also be used by the application to easily access custom and
+ vendor-specific devices.
+
+*/
\ No newline at end of file diff --git a/usb/device/hid-mouse/HIDDMouseDriver.c b/usb/device/hid-mouse/HIDDMouseDriver.c new file mode 100644 index 0000000..dc2378c --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriver.c @@ -0,0 +1,392 @@ +/* ----------------------------------------------------------------------------
+ * 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 "HIDDMouseDriver.h"
+#include "HIDDMouseDriverDescriptors.h"
+#include "HIDDMouseInputReport.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDGenericRequest.h>
+#include <usb/common/hid/HIDReportRequest.h>
+#include <usb/common/hid/HIDIdleRequest.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+
+//------------------------------------------------------------------------------
+// Internal Defines
+//------------------------------------------------------------------------------
+
+/// Tag bit (Always 1)
+#define HIDDMouse_TAG (1 << 3)
+
+/// Xsign bit
+#define HIDDMouse_Xsign (1 << 4)
+
+/// Ysign bit
+#define HIDDMouse_Ysign (1 << 5)
+
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Driver structure for an HID device implementing keyboard functionalities.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard USB device driver instance.
+ USBDDriver usbdDriver;
+ /// Idle rate (in milliseconds) of the input report.
+ unsigned char inputReportIdleRate;
+ ///
+ unsigned char inputProtocol;
+ /// Input report instance.
+ HIDDMouseInputReport inputReport;
+
+} HIDDMouseDriver;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Static instance of the HID mouse device driver.
+static HIDDMouseDriver hiddMouseDriver;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the descriptor requested by the host.
+/// \param type Descriptor type.
+/// \param length Maximum number of bytes to send.
+/// \return 1 if the request has been handled by this function, otherwise 0.
+//------------------------------------------------------------------------------
+static unsigned char HIDDMouseDriver_GetDescriptor(unsigned char type,
+ unsigned char length)
+{
+ const USBConfigurationDescriptor *pConfiguration;
+ HIDDescriptor *hidDescriptors[2];
+
+ switch (type) {
+
+ case HIDGenericDescriptor_REPORT:
+ TRACE_INFO("Report ");
+
+ // Adjust length and send report descriptor
+ if (length > HIDDMouseDriverDescriptors_REPORTSIZE) {
+
+ length = HIDDMouseDriverDescriptors_REPORTSIZE;
+ }
+ USBD_Write(0, &hiddReportDescriptor, length, 0, 0);
+ break;
+
+ case HIDGenericDescriptor_HID:
+ TRACE_INFO("HID ");
+
+ // Configuration descriptor is different depending on configuration
+ if (USBD_IsHighSpeed()) {
+
+ pConfiguration =
+ hiddMouseDriver.usbdDriver.pDescriptors->pHsConfiguration;
+ }
+ else {
+
+ pConfiguration =
+ hiddMouseDriver.usbdDriver.pDescriptors->pFsConfiguration;
+ }
+
+ // Parse the device configuration to get the HID descriptor
+ USBConfigurationDescriptor_Parse(pConfiguration, 0, 0,
+ (USBGenericDescriptor **) &hidDescriptors[0]);
+
+ // Adjust length and send HID descriptor
+ if (length > sizeof(HIDDescriptor)) {
+
+ length = sizeof(HIDDescriptor);
+ }
+ USBD_Write(0, hidDescriptors[0], length, 0, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+/// Sends the current Idle rate of the input report to the host.
+//------------------------------------------------------------------------------
+static void HIDDMouseDriver_GetIdle()
+{
+ TRACE_INFO("gIdle ");
+
+ USBD_Write(0, &(hiddMouseDriver.inputReportIdleRate), 1, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Retrieves the new idle rate of the input report from the USB host.
+/// \param idleRate New input report idle rate.
+//------------------------------------------------------------------------------
+static void HIDDMouseDriver_SetIdle(unsigned char idleRate)
+{
+ TRACE_INFO("sIdle(%d) ", idleRate);
+
+ hiddMouseDriver.inputReportIdleRate = idleRate;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Sends the requested report to the host.
+/// \param type Report type.
+/// \param length Maximum number of bytes to send.
+//------------------------------------------------------------------------------
+static void HIDDMouseDriver_GetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO("gReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ TRACE_INFO("In ");
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDMouseInputReport)) {
+
+ length = sizeof(HIDDMouseInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddMouseDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Retrieves the new value of a report from the host and saves it.
+/// \param type Report type.
+/// \param length Report length.
+//------------------------------------------------------------------------------
+static void HIDDMouseDriver_SetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO("sReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+//------------------------------------------------------------------------------
+/// Callback function when new request receivce from host
+/// \param request Pointer to the USBGenericRequest instance
+//------------------------------------------------------------------------------
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ HIDDMouseDriver_RequestHandler(request);
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+// ConfigurationChanged() callback re-implementation
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Callback function when configureation changed
+/// \param cfgnum New configuration number
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ }
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the HID Mouse %device driver.
+//------------------------------------------------------------------------------
+void HIDDMouseDriver_Initialize(void)
+{
+ hiddMouseDriver.inputReportIdleRate = 0;
+ HIDDMouseInputReport_Initialize(&(hiddMouseDriver.inputReport));
+ USBDDriver_Initialize(&(hiddMouseDriver.usbdDriver),
+ &hiddMouseDriverDescriptors,
+ 0); // Multiple interface settings not supported
+ USBD_Init();
+}
+
+//------------------------------------------------------------------------------
+/// Handles HID-specific SETUP request sent by the host.
+/// \param request Pointer to a USBGenericRequest instance
+//------------------------------------------------------------------------------
+void HIDDMouseDriver_RequestHandler(const USBGenericRequest *request)
+{
+ TRACE_INFO("NewReq ");
+
+ // Check if this is a standard request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
+
+ // This is a standard request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor, otherwise forward it to
+ // the standard driver
+ if (!HIDDMouseDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver),
+ request);
+ }
+ }
+ // Check if this is a class request
+ else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ // This is a class-specific request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case HIDGenericRequest_GETIDLE:
+ HIDDMouseDriver_GetIdle();
+ break;
+
+ case HIDGenericRequest_SETIDLE:
+ HIDDMouseDriver_SetIdle(HIDIdleRequest_GetIdleRate(request));
+ break;
+
+ case HIDGenericRequest_GETREPORT:
+ HIDDMouseDriver_GetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ case HIDGenericRequest_SETREPORT:
+ HIDDMouseDriver_SetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ case HIDGenericRequest_GETPROTOCOL:
+ USBD_Write(0, &hiddMouseDriver.inputProtocol, 1, 0, 0);
+ break;
+
+ case HIDGenericRequest_SETPROTOCOL:
+ hiddMouseDriver.inputProtocol = request->wValue;
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ default:
+ TRACE_WARNING(
+ "HIDDMouseDriver_RequestHandler: Unknown request 0x%02X\n\r",
+ USBGenericRequest_GetRequest(request));
+ USBD_Stall(0);
+ }
+ }
+ else {
+
+ // Vendor request ?
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Update the Mouse button status and location changes via input report
+/// to host
+/// \param bmButtons Bit map of the button status
+/// \param deltaX Movment on X direction
+/// \param deltaY Movment on Y direction
+//------------------------------------------------------------------------------
+unsigned char HIDDMouseDriver_ChangePoints(unsigned char bmButtons,
+ signed char deltaX,
+ signed char deltaY)
+{
+ hiddMouseDriver.inputReport.bmButtons = (bmButtons & 0x07)
+ | HIDDMouse_TAG;
+ hiddMouseDriver.inputReport.bX = deltaX;
+ hiddMouseDriver.inputReport.bY = deltaY;
+ // Send input report through the interrupt IN endpoint
+ return USBD_Write(HIDDMouseDriverDescriptors_INTERRUPTIN,
+ &(hiddMouseDriver.inputReport),
+ sizeof(HIDDMouseInputReport),
+ 0,
+ 0);
+}
+
+//------------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//------------------------------------------------------------------------------
+void HIDDMouseDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&(hiddMouseDriver.usbdDriver))) {
+
+ USBD_RemoteWakeUp();
+ }
+}
+
diff --git a/usb/device/hid-mouse/HIDDMouseDriver.h b/usb/device/hid-mouse/HIDDMouseDriver.h new file mode 100644 index 0000000..94dac3a --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriver.h @@ -0,0 +1,107 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of methods for using a HID mouse device driver.
+
+ !!!Usage
+
+ -# Re-implement the USBDCallbacks_RequestReceived callback to forward
+ requests to HIDDMouseDriver_RequestHandler. This is done
+ automatically unless the NOAUTOCALLBACK symbol is defined during
+ compilation.
+ -# Initialize the driver using HIDDMouseDriver_Initialize. The
+ USB driver is automatically initialized by this method.
+ -# Call the HIDDMouseDriver_ChangePoints method when one or more
+ keys are pressed/released.
+*/
+
+#ifndef HIDDKEYBOARDDRIVER_H
+#define HIDDKEYBOARDDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Mouse Button bitmaps"
+/// ...
+/// !Bits
+/// - HIDDMouse_LEFT_BUTTON
+/// - HIDDMouse_RIGHT_BUTTON
+/// - HIDDMouse_MIDDLE_BUTTON
+
+/// Left mouse button
+#define HIDDMouse_LEFT_BUTTON (1 << 0)
+
+/// Right mouse button
+#define HIDDMouse_RIGHT_BUTTON (1 << 1)
+
+/// Middle mouse button
+#define HIDDMouse_MIDDLE_BUTTON (1 << 2)
+
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+/*
+ Function: HIDDMouseDriver_Initialize
+ Initializes the HID keyboard device driver.
+*/
+extern void HIDDMouseDriver_Initialize(void);
+
+/*
+ Function: HIDDMouseDriver_RequestHandler
+ Handles HID-specific SETUP request sent by the host.
+
+ Parameters:
+ request - Pointer to a USBGenericRequest instance.
+*/
+extern void HIDDMouseDriver_RequestHandler(const USBGenericRequest *request);
+
+extern unsigned char HIDDMouseDriver_ChangePoints(unsigned char bmButtons,
+ signed char deltaX,
+ signed char deltaY);
+
+extern void HIDDMouseDriver_RemoteWakeUp(void);
+
+#endif //#ifndef HIDDKEYBOARDDRIVER_H
+
diff --git a/usb/device/hid-mouse/HIDDMouseDriverDescriptors.c b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.c new file mode 100644 index 0000000..6a66d83 --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.c @@ -0,0 +1,385 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDMouseDriverDescriptors
+
+ About: Purpose
+ Declaration of the descriptors used by the HID device keyboard driver.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDMouseDriverDescriptors.h"
+#include "HIDDMouseInputReport.h"
+#include <board.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDeviceDescriptor.h>
+#include <usb/common/hid/HIDInterfaceDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDReport.h>
+#include <usb/common/hid/HIDGenericDesktop.h>
+#include <usb/common/hid/HIDLeds.h>
+#include <usb/common/hid/HIDButton.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Mouse Device Descriptor IDs"
+/// ...
+///
+/// !IDs
+/// - HIDDMouseDriverDescriptors_PRODUCTID
+/// - HIDDMouseDriverDescriptors_VENDORID
+/// - HIDDMouseDriverDescriptors_RELEASE
+
+/// Device product ID.
+#define HIDDMouseDriverDescriptors_PRODUCTID 0x6200
+/// Device vendor ID.
+#define HIDDMouseDriverDescriptors_VENDORID 0x03EB
+/// Device release number.
+#define HIDDMouseDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// List of descriptors that make up the configuration descriptors of a
+/// %device using the HID Mouse driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Configuration descriptor.
+ USBConfigurationDescriptor configuration;
+ /// Interface descriptor.
+ USBInterfaceDescriptor interface;
+ /// HID descriptor.
+ HIDDescriptor hid;
+ /// Interrupt IN endpoint descriptor.
+ USBEndpointDescriptor interruptIn;
+
+} __attribute__ ((packed)) HIDDMouseDriverConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Device descriptor.
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDMouseDriverDescriptors_VENDORID,
+ HIDDMouseDriverDescriptors_PRODUCTID,
+ HIDDMouseDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Device qualifier descriptor (high-speed only).
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // One possible configuration
+ 0 // Reserved
+};
+#endif
+
+/// Configuration descriptor.
+static const HIDDMouseDriverConfigurationDescriptors configurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDMouseDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 1, // One endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_MOUSE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDMouseDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDMouseDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDMouseInputReport),
+ HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING
+ }
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Other-speed configuration descriptor.
+static const HIDDMouseDriverConfigurationDescriptors otherSpeedDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(HIDDMouseDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_MOUSE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDMouseDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDMouseDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDMouseInputReport),
+ HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING
+ }
+};
+#endif
+
+/*
+ Variables: String descriptors
+ languageIdDescriptor - Language ID string descriptor.
+ manufacturerDescriptor - Manufacturer name.
+ productDescriptor - Product name.
+ serialNumberDescriptor - Product serial number.
+ stringDescriptors - Array of pointers to string descriptors.
+*/
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+static const unsigned char manufacturerDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(5),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L')
+};
+
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(19),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('H'),
+ USBStringDescriptor_UNICODE('I'),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('O'),
+ USBStringDescriptor_UNICODE('U'),
+ USBStringDescriptor_UNICODE('S'),
+ USBStringDescriptor_UNICODE('E'),
+};
+
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(12),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('F')
+};
+
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors used by the HID keyboard driver.
+USBDDriverDescriptors hiddMouseDriverDescriptors = {
+
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+#else
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration
+ 0, // No high-speed device descriptor
+ 0, // No high-speed configuration descriptor
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+#endif
+ stringDescriptors,
+ 4 // Four string descriptors in list
+};
+
+/// Report descriptor used by the driver.
+const unsigned char hiddReportDescriptor[] = {
+
+ // Global Usage Page
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ // Collection: Application
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_MOUSE,
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+ // Physical collection: Pointer
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_POINTER,
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_PHYSICAL,
+
+ // Input report: buttons
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDButton_PAGEID,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, 3,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE, // 3 button bits
+
+ // Input report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_INPUT + 1, HIDReport_CONSTANT, // 5 bit padding
+
+ // Input report: pointer
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 2,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_X,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_Y,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, (unsigned char) -127,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 127,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE | HIDReport_RELATIVE,
+
+ HIDReport_ENDCOLLECTION,
+ HIDReport_ENDCOLLECTION
+};
+
diff --git a/usb/device/hid-mouse/HIDDMouseDriverDescriptors.h b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.h new file mode 100644 index 0000000..4f27dec --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions of the descriptors required by the HID device keyboard
+ driver.
+
+ !!!Usage
+ -# Use the hiddMouseDriverDescriptors variable to initialize a
+ USBDDriver instance.
+ -# Send hiddReportDescriptor to the host when a GET_DESCRIPTOR request
+ for the report descriptor is received.
+*/
+
+#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+#define HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+/*
+ Constants: Endpoints
+ HIDDMouseDriverDescriptors_INTERRUPTIN - Interrupt IN endpoint number.
+ HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING - Interrupt IN endpoint
+ polling rate (in milliseconds).
+*/
+#define HIDDMouseDriverDescriptors_INTERRUPTIN 1
+#define HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING 10
+
+/*
+ Constants: Report descriptor
+ HIDDMouseDriverDescriptors_REPORTSIZE - Size of the report descriptor
+ in bytes.
+*/
+#define HIDDMouseDriverDescriptors_REPORTSIZE 50
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+/*
+ Variables: HID keyboard driver descriptors
+ hiddMouseDriverDescriptors - List of descriptors used by the HID
+ keyboard driver.
+ hiddReportDescriptor - Report descriptor used by the driver.
+*/
+extern USBDDriverDescriptors hiddMouseDriverDescriptors;
+extern const unsigned char hiddReportDescriptor[];
+
+#endif //#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/hid-mouse/HIDDMouseInputReport.c b/usb/device/hid-mouse/HIDDMouseInputReport.c new file mode 100644 index 0000000..1c1c979 --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseInputReport.c @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDMouseInputReport implementation
+
+ About: Purpose
+ Implementation of the HIDDMouseInputReport class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDMouseInputReport.h"
+#include "HIDDMouseDriverDescriptors.h"
+#include <utility/assert.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes a mouse input report instance.
+/// \param report Pointer to a HIDDMouseInputReport instance.
+//------------------------------------------------------------------------------
+void HIDDMouseInputReport_Initialize(HIDDMouseInputReport *report)
+{
+ report->bmButtons = 0;
+ report->bX = 0;
+ report->bY = 0;
+}
+
+/*
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void HIDDMouseInputReport_UpdateButtons(HIDDMouseInputReport *report)
+{
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void HIDDMouseInputReport_UpdateAxis(HIDDMouseInputReport *report)
+{
+}
+*/
diff --git a/usb/device/hid-mouse/HIDDMouseInputReport.h b/usb/device/hid-mouse/HIDDMouseInputReport.h new file mode 100644 index 0000000..ca074fd --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseInputReport.h @@ -0,0 +1,93 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Class for manipulating HID Mouse input reports.
+
+ !!!Usage
+
+ -# Initialize a newly created input report with
+ HIDDMouseInputReport_Initialize
+*/
+
+#ifndef HIDDKEYBOARDINPUTREPORT_H
+#define HIDDKEYBOARDINPUTREPORT_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Mouse Keys"
+
+/// Mouse Left Click Button
+#define HIDDMouseInputReport_LEFT_BUTTON (1 << 0)
+/// Mouse Right Click Button
+#define HIDDMouseInputReport_RIGHT_BUTTON (1 << 1)
+/// Mouse Middle Button
+#define HIDDMouseInputReport_MIDDLE_BUTTON (1 << 2)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// HID input report structure used by the Mouse driver to notify the
+/// host of pressed keys.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bmButtons; /// Bitmap state of three mouse buttons.
+ signed char bX; /// Pointer displacement along the X axis.
+ signed char bY; /// Pointer displacement along the Y axis.
+
+} __attribute__ ((packed)) HIDDMouseInputReport; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDMouseInputReport_Initialize(HIDDMouseInputReport *report);
+
+#endif //#ifndef HIDDKEYBOARDINPUTREPORT_H
+
diff --git a/usb/device/hid-mouse/hid-mouse.dir b/usb/device/hid-mouse/hid-mouse.dir new file mode 100644 index 0000000..9dd733b --- /dev/null +++ b/usb/device/hid-mouse/hid-mouse.dir @@ -0,0 +1,544 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB HID
+/// %device - USB HID Mouse driver, to implement an USB Mouse %device.
+///
+/// !!!Contents
+///
+/// There are three things for the implement of the USB HID Mouse driver:
+/// - Implement the USB HID driver structs and functions for the %device,
+/// to initialize, to handle HID-specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the HID Mouse device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the %device as a USB Mouse %device.
+/// - Implement methods to update the Mouse keys status, so that host can
+/// get it through USB.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB HID Mouse".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB HID Mouse"
+ This page describes how to use the "AT91 USB device framework" to produce a USB
+ HID Mouse driver, which appears as a USB Mouse on host.
+
+ Details about the USB and the HID class can be found in the }USB specification
+ 2.0} and the }HID specification 1.11}, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+ !!!HID Basic
+ See "USB HID Basic".
+
+ !!!Architecture
+ See "USB Device Framework Architecture".
+
+ !!!Descriptors
+
+ ...
+
+ !!Device Descriptor
+ The Device descriptor of an HID %device is very basic, since the HID class
+ code is only specified at the Interface level. Thus, it only contains
+ standard values, as shown below:
+\code
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDMouseDriverDescriptors_VENDORID,
+ HIDDMouseDriverDescriptors_PRODUCTID,
+ HIDDMouseDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+\endcode
+ Note that the Vendor ID is a special value attributed by the USB-IF
+ organization. The product ID can be chosen freely by the vendor.
+
+ !!Configuration Descriptor
+ Since one interface is required by the HID specification, this must be
+ specified in the Configuration descriptor. There is no other value of
+ interest to put here.
+\code
+// Configuration descriptor
+{
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDMouseDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+},
+\endcode
+ When the Configuration descriptor is requested by the host (by using the
+ GET_DESCRIPTOR command), the %device must also sent all the related
+ descriptors, i.e. Interface, Endpoint and Class-Specific descriptors. It is
+ convenient to create a single structure to hold all this data, for sending
+ everything in one chunk. In the example software, a
+ HIDDMouseDriverConfigurationDescriptors structure has been declared for
+ that.
+
+ !!HID Class Interface Descriptor
+ Since a Mouse %device needs to transmit as well as receive data, two
+ Interrupt (IN & OUT) endpoints are needed. This must be indicated in the
+ Interface descriptor. Conversely to the mouse example, the Boot protocol is
+ not implemented here, since there are more constraints on a Mouse %device.
+\code
+// Interface descriptor
+{
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+},
+\endcode
+
+ !!HID Descriptor
+ While a HID Mouse produces two different reports, one Input and one Output,
+ only one Report descriptor can be used to describe them. Since having Physical
+ descriptors is also useless for a Mouse, there will only be one HID class
+ descriptor specified here.
+
+ For a Mouse, the }bCountryCode} field can be used to specify the language
+ of the key caps. As this is optional, it is simply set to 00h in the example:
+\code
+// HID descriptor
+{
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDMouseDriverDescriptors_REPORTSIZE
+},
+\endcode
+
+ !!Report Descriptor
+ Two current reports are defined in the Report descriptor. The first one is
+ used to notify the host of which keys are pressed, with both modifier keys
+ (alt, ctrl, etc.) and alphanumeric keys. The second report is necessary for
+ the host to send the LED (num lock, caps lock, etc.) states.
+
+ The Report descriptor starts with the global %device functionality, described
+ with a #Usage Page# and a #Usage# items:
+\code
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_Mouse,
+\endcode
+
+ As in the mouse example, the }Generic Desktop} page is used. This time, the
+ specific usage is the }Mouse} one. An Application collection is then
+ defined to group the reports together:
+\code
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+\endcode
+
+ The first report to be defined is the modifier keys. They are represented as a
+ bitmap field, indicating whether or not each key is pressed. A single byte is
+ used to map keys \#224-231 defined in the }HID Usage Tables} document:
+ LeftControl, LeftShift, LeftAlt, LeftGUI (e.g. Windows key),
+ RightControl, RightShift, RightAlt and RightGUI.
+ The }Keypad} usage page must be specified for this report, and since this is a
+ bitmap value, the data is flagged as }Variable}:
+\code
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDMouseDriverDescriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDMouseDriverDescriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Then, the actual alphanumeric key report is described. This is done by
+ defining several bytes of data, one for each pressed key. In the example,
+ up to three keys can be pressed at the same time (and detected) by the user.
+ Once again, the usage page is set to }Keypad}. This time however, the data
+ must be specified as an }Array}, since the same control (the keypad) produces
+ several values:
+\code
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDDMouseDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDDMouseDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDMouseDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDMouseDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+\endcode
+
+ The LED array is then defined, with the associated usage page. The Report
+ descriptor is formatted in this order to avoid redefining unchanged }Global}
+ items, in order to save memory. This time again, the LED status is reported as
+ a bitmap field. Three LEDs are used here: Num Lock, Caps Lock and Scroll Lock
+ (IDs 01h to 03h). It is important to note that this is an #Output# report:
+\code
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Since the previous report only contains 3 bits, the data must be padded to a
+ multiple of one byte. This is done by using constant Output data, as follows:
+\code
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+\endcode
+
+ The last item, }End Collection}, is necessary to close the previously opened
+ }Application Collection}.
+\code
+ HIDReport_ENDCOLLECTION
+};
+\endcode
+
+ The Input and Output reports defined by this descriptor can be modeled by the
+ following structures:
+\code
+// HID Input Report
+typedef struct {
+
+ // State of modifier keys.
+ unsigned char bmModifierKeys:8;
+ // Key codes of pressed keys.
+ unsigned char pressedKeys[HIDDMouseInputReport_MAXKEYPRESSES];
+
+} __attribute__ ((packed)) HIDDMouseInputReport; // GCC
+// HID Output Report
+typedef struct {
+
+ unsigned char numLockStatus:1, // State of the num. lock LED.
+ capsLockStatus:1, // State of the caps lock LED.
+ scrollLockStatus:1, // State of the scroll lock LED.
+ padding:5; // Padding bits.
+
+} __attribute__ ((packed)) HIDDMouseOutputReport; // GCC
+\endcode
+
+ An instance of each one of the reports is stored in a HIDDMouseDriver
+ structure, which holds the standard class driver and HID Mouse-specific
+ data.
+
+ !!Physical Descriptor
+ A Physical descriptor is useless for a Mouse %device, so none are defined
+ in this example.
+
+ !!Endpoint Descriptor
+ Following the Interface and HID-specific descriptors, the two necessary
+ endpoints are defined.
+\code
+// Interrupt IN endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDMouseDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDMouseInputReport),
+ HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING
+},
+// Interrupt OUT endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDMouseDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDMouseOutputReport),
+ HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING
+}
+\endcode
+
+ !!String Descriptors
+ Please refer to "Usage: USBD VID, PID & Strings".
+
+ !!!Class-specific requests
+ A driver request handler should first differentiate between class-specific and
+ standard requests using the corresponding bits in the }bmRequestType} field.
+ In most cases, standard requests can be immediately forwarded to the standard
+ request handler method; class-specific methods must be decoded and treated by
+ the custom handler.
+
+ !!GetDescriptor
+ Three values have been added by the HID specification for the #GET_DESCRIPTOR#
+ request. The high byte of the }wValue} field contains the type of the
+ requested descriptor; in addition to the standard types, the #HID
+ specification# adds the #HID descriptor# (21h), the #Report descriptor#
+ (22h) and the #Physical descriptor# (23h) types.
+
+ There is no particular action to perform besides sending the descriptor. This
+ can be done by using the USBD_Write method, after the requested descriptor has
+ been identified:
+\code
+switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor,
+ // otherwise forward it to
+ // the standard driver
+ if (!HIDDMouseDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver),
+ request);
+}
+\endcode
+ A slight complexity of the GET_DESCRIPTOR and SET_DESCRIPTOR requests is that
+ those are standard requests, but the standard request handler
+ (USBDDriver_RequestHandler) must not always be called to treat them (since
+ they may refer to HID descriptors). The solution is to first identify
+ GET/SET_DESCRIPTOR requests, treat the HID-specific cases and, finally,
+ forward any other request to the standard handler.
+
+ In this case, a GET_DESCRIPTOR request for the Physical descriptor is first
+ forwarded to the standard handler, and STALLed there because it is not
+ recognized. This is done because the %device does not have any Physical
+ descriptors, and thus, does not need to handle the associated request.
+
+ !!SetDescriptor
+ This request is optional and is never issued by most hosts. It is not
+ implemented in this example.
+
+ !!GetReport
+ Since the HID Mouse defines two different reports, the Report Type value
+ specified by this request (upper byte of the }wValue} field) must be examined
+ to decide which report to send. If the type value is 01h, then the Input
+ report must be returned; if it is 02h, the Output report is requested:
+\code
+case HIDGenericRequest_GETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDMouseInputReport)) {
+
+ length = sizeof(HIDDMouseInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddMouseDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDMouseOutputReport)) {
+
+ length = sizeof(HIDDMouseOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddMouseDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetReport
+ For an HID Mouse, the #SET_REPORT# command can be sent by the host to
+ change the state of the LEDs. Normally, the dedicated Interrupt OUT endpoint
+ will be used for this; but in some cases, using the default Control endpoint
+ can save some bandwidth on the host side.
+
+ Note that the SET_REPORT request can be directed at the Input report of the
+ Mouse; in this case, it can be safely discarded, according to the HID
+ specification. Normally, most host drivers only target the Output report. The
+ Report Type value is stored in the upper byte of the }wValue} field.
+
+ The length of the data phase to follow is stored in the }wLength} field of the
+ request. It should be equal to the total length of the Output report. If it is
+ different, the report status must still be updated with the received data as
+ best as possible.
+
+ When the reception of the new data is completed, some processing must be done
+ to enable/disable the corresponding LEDs. This is done in the callback
+ function passed as an argument to USBD_Read:
+\code
+case HIDGenericRequest_SETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch(type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDMouseOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddMouseDriver.outputReport),
+ length,
+ (TransferCallback) HIDDMouseDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetIdle
+ In this case study, the #SET_IDLE# request is used to set a delay before a key
+ is repeated. This is common behavior on Mouse devices. Usually, this delay
+ is set to about 500 ms by the host.
+
+ The only action here is to store the new Idle rate. The management of this
+ setting must be done in the main function, since Interrupt IN reports are sent
+ from there.
+
+ In practice, it is not necessary to perform any action, apart from sending a
+ zero-length packet to acknowledge it. The main application however has to make
+ sure that only new reports are sent by the %device.
+\code
+case HIDGenericRequest_SETIDLE:
+//-----------------------------
+ hiddMouseDriver.inputReportIdleRate =
+ HIDIdleRequest_GetIdleRate(request);
+ USBD_Write(0, 0, 0, 0, 0);
+break;
+\endcode
+
+ !!GetIdle
+ The only necessary operation for this request is to send the previously saved
+ Idle rate. This is done by calling the USBD_Write method with the one-byte
+ variable as its parameter:
+\code
+case HIDGenericRequest_GETIDLE:
+//-----------------------------
+ USBD_Write(0, &(hiddMouseDriver.inputReportIdleRate), 1, 0, 0);
+break;
+\endcode
+
+ !!GetProtocol, SetProtocol
+ This HID Mouse example does not support the Boot protocol, so there is no
+ need to implement the SET_PROTOCOL and GET_PROTOCOL requests. This means they
+ can be safely STALLed when received.
+
+ !!!Main Application
+ Like the mouse example, the main program must perform two different
+ operations. First, it has to monitor the physical inputs used as keys. In the
+ example software, the buttons present on the evaluation boards are used to
+ produce several modifier and alphanumeric keys.
+
+ Also, the main program is in charge of sending reports as they are modified,
+ taking into account the Idle rate specified by the host. Idle rate management
+ can be carried out by firing/resetting a timer once a new report is sent; if
+ the timer expires, this means the Input report has not changed since.
+ According to the HID specification, a single instance of the report must be
+ sent in this case.
+
+ Finally, the HID specification also defines that if too many keys are pressed
+ at the same time, the %device should report an }ErrorRollOver} usage value
+ (01h) in every byte of the key array. This has to be handled by the main
+ application as well.
+
+*/
\ No newline at end of file diff --git a/usb/device/hid-transfer/HIDDTransferDriver.c b/usb/device/hid-transfer/HIDDTransferDriver.c new file mode 100644 index 0000000..0810474 --- /dev/null +++ b/usb/device/hid-transfer/HIDDTransferDriver.c @@ -0,0 +1,479 @@ +/* ----------------------------------------------------------------------------
+ * 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 "HIDDTransferDriver.h"
+#include "HIDDTransferDriverDesc.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDGenericRequest.h>
+#include <usb/common/hid/HIDReportRequest.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Driver structure for an HID device implementing keyboard functionalities.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard USB device driver instance.
+ USBDDriver usbdDriver;
+
+ // OUT Report - block input
+ unsigned short iReportLen;
+ unsigned char iReportBuf[HIDDTransferDriver_REPORTSIZE];
+
+ // IN Report - block output
+ unsigned short oReportLen;
+ unsigned char oReportBuf[HIDDTransferDriver_REPORTSIZE];
+
+ // Interrupt OUT Data - input
+ /// Input data length
+ unsigned short iLen;
+ /// Input (report) Buffer
+ unsigned char iBuf[HIDDTransferDriver_REPORTSIZE];
+
+ // Nothing more now...
+
+} HIDDTransferDriver;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Static instance of the HID Transfer device driver.
+static HIDDTransferDriver hiddTransferDriver;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Returns the descriptor requested by the host.
+/// \param type Descriptor type.
+/// \param length Maximum number of bytes to send.
+/// \return 1 if the request has been handled by this function, otherwise 0.
+//------------------------------------------------------------------------------
+static unsigned char HIDDTransferDriver_GetDescriptor(unsigned char type,
+ unsigned char length)
+{
+ const USBConfigurationDescriptor *pConfiguration;
+ HIDDescriptor *hidDescriptors[2];
+
+ switch (type) {
+
+ case HIDGenericDescriptor_REPORT:
+ TRACE_INFO("Report ");
+
+ // Adjust length and send report descriptor
+ if (length > HIDDTransferDriverDescriptors_REPORTSIZE) {
+
+ length = HIDDTransferDriverDescriptors_REPORTSIZE;
+ }
+ USBD_Write(0, &hiddReportDescriptor, length, 0, 0);
+ break;
+
+ case HIDGenericDescriptor_HID:
+ TRACE_INFO("HID ");
+
+ // Configuration descriptor is different depending on configuration
+ if (USBD_IsHighSpeed()) {
+
+ pConfiguration =
+ hiddTransferDriver.usbdDriver.pDescriptors->pHsConfiguration;
+ }
+ else {
+
+ pConfiguration =
+ hiddTransferDriver.usbdDriver.pDescriptors->pFsConfiguration;
+ }
+
+ // Parse the device configuration to get the HID descriptor
+ USBConfigurationDescriptor_Parse(pConfiguration, 0, 0,
+ (USBGenericDescriptor **) &hidDescriptors[0]);
+
+ // Adjust length and send HID descriptor
+ if (length > sizeof(HIDDescriptor)) {
+
+ length = sizeof(HIDDescriptor);
+ }
+ USBD_Write(0, hidDescriptors[0], length, 0, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+/// Callback function when SetReport request data received from host
+/// \param pArg Pointer to additional argument struct
+/// \param status Result status
+/// \param transferred Number of bytes transferred
+/// \param remaining Number of bytes that are not transferred yet
+//------------------------------------------------------------------------------
+static void HIDDTransferDriver_ReportReceived(void *pArg,
+ unsigned char status,
+ unsigned int transferred,
+ unsigned int remaining)
+{
+ hiddTransferDriver.iReportLen = transferred;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Callback function when GetReport request data sent to host
+/// \param pArg Pointer to additional argument struct
+/// \param status Result status
+/// \param transferred Number of bytes transferred
+/// \param remaining Number of bytes that are not transferred yet
+//------------------------------------------------------------------------------
+static void HIDDTransferDriver_ReportSent(void *pArg,
+ unsigned char status,
+ unsigned int transferred,
+ unsigned int remaining)
+{
+ USBD_Read(0, 0, 0, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+/// Callback function when interrupt OUT data received from host
+/// \param pArg Pointer to additional argument
+/// \param status Result status
+/// \param transferred Number of bytes transferred
+/// \param remaining Number of bytes that are not transferred yet
+//------------------------------------------------------------------------------
+static void HIDDTransferDriver_DataReceived(void *pArg,
+ unsigned char status,
+ unsigned int transferred,
+ unsigned int remaining)
+{
+ hiddTransferDriver.iLen = transferred;
+
+ USBD_Read(HIDDTransferDriverDescriptors_INTERRUPTOUT,
+ hiddTransferDriver.iBuf,
+ HIDDTransferDriver_REPORTSIZE,
+ (TransferCallback)HIDDTransferDriver_DataReceived,
+ 0);
+}
+
+//------------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+//------------------------------------------------------------------------------
+/// Callback function when new request receivce from host
+/// \param request Pointer to the USBGenericRequest instance
+//------------------------------------------------------------------------------
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ HIDDTransferDriver_RequestHandler(request);
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+// ConfigurationChanged() callback re-implementation
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Callback function when configureation changed
+/// \param cfgnum New configuration number
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ hiddTransferDriver.iLen = 0;
+ USBD_Read(HIDDTransferDriverDescriptors_INTERRUPTOUT,
+ hiddTransferDriver.iBuf,
+ HIDDTransferDriver_REPORTSIZE,
+ HIDDTransferDriver_DataReceived,
+ 0);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+/// Initializes the HID Transfer %device driver.
+//------------------------------------------------------------------------------
+void HIDDTransferDriver_Initialize()
+{
+ hiddTransferDriver.iReportLen = 0;
+
+ USBDDriver_Initialize(&(hiddTransferDriver.usbdDriver),
+ &hiddTransferDriverDescriptors,
+ 0); // Multiple interface settings not supported
+ USBD_Init();
+}
+
+//------------------------------------------------------------------------------
+/// Handles HID-specific SETUP request sent by the host.
+/// \param request Pointer to a USBGenericRequest instance
+//------------------------------------------------------------------------------
+void HIDDTransferDriver_RequestHandler(const USBGenericRequest *request)
+{
+ TRACE_INFO("NewReq ");
+
+ // Check if this is a standard request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
+
+ // This is a standard request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor, otherwise forward it to
+ // the standard driver
+ if (!HIDDTransferDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddTransferDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ case USBGenericRequest_CLEARFEATURE:
+ /* Check which is the requested feature */
+ switch (USBFeatureRequest_GetFeatureSelector(request)) {
+ case USBFeatureRequest_ENDPOINTHALT:
+ { unsigned char ep =
+ USBGenericRequest_GetEndpointNumber(request);
+ if (USBD_IsHalted(ep)) {
+ /* Unhalt endpoint restart OUT EP
+ */
+ USBD_Unhalt(ep);
+ if (ep == HIDDTransferDriverDescriptors_INTERRUPTOUT) {
+ hiddTransferDriver.iLen = 0;
+ USBD_Read(HIDDTransferDriverDescriptors_INTERRUPTOUT,
+ hiddTransferDriver.iBuf,
+ HIDDTransferDriver_REPORTSIZE,
+ HIDDTransferDriver_DataReceived,
+ 0);
+ }
+ }
+ /* and send a zero-length packet */
+ USBD_Write(0, 0, 0, 0, 0);
+ return; /* Done, no others */
+ }
+ }
+
+ default:
+ USBDDriver_RequestHandler(&(hiddTransferDriver.usbdDriver),
+ request);
+ }
+ }
+ // Check if this is a class request
+ else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ unsigned short length = USBGenericRequest_GetLength(request);
+ unsigned char type = HIDReportRequest_GetReportType(request);
+
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case HIDGenericRequest_SETREPORT:
+
+ if (length <= HIDDTransferDriver_REPORTSIZE &&
+ type == HIDReportRequest_OUTPUT) {
+
+ USBD_Read(0,
+ hiddTransferDriver.iReportBuf,
+ length,
+ HIDDTransferDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ else {
+
+ USBD_Stall(0);
+ }
+ break;
+
+ case HIDGenericRequest_GETREPORT:
+
+ if (length <= HIDDTransferDriver_REPORTSIZE &&
+ type == HIDReportRequest_INPUT) {
+
+ USBD_Write(0,
+ hiddTransferDriver.oReportBuf,
+ length,
+ HIDDTransferDriver_ReportSent,
+ 0);
+ }
+ else {
+
+ USBD_Stall(0);
+ }
+ break;
+
+ default:
+ TRACE_WARNING(
+ "HIDDTransferDriver_RequestHandler: request 0x%02X\n\r",
+ USBGenericRequest_GetRequest(request));
+ USBD_Stall(0);
+ }
+ }
+ else {
+
+ // Vendor request ?
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Try to read request buffer of SetReport.
+/// Set pData to 0 to get current data length only.
+/// \param pData Pointer to data buffer
+/// \param dLength Data buffer length
+/// \return Number of bytes read
+//------------------------------------------------------------------------------
+unsigned short HIDDTransferDriver_ReadReport(void *pData,
+ unsigned int dLength)
+{
+ if (pData == 0) {
+
+ return hiddTransferDriver.iReportLen;
+ }
+
+ if (dLength > HIDDTransferDriver_REPORTSIZE) {
+
+ dLength = HIDDTransferDriver_REPORTSIZE;
+ }
+ if (dLength > hiddTransferDriver.iReportLen) {
+
+ dLength = hiddTransferDriver.iReportLen;
+ }
+ hiddTransferDriver.iReportLen = 0;
+ memcpy(pData, hiddTransferDriver.iReportBuf, dLength);
+
+ return dLength;
+}
+
+//------------------------------------------------------------------------------
+/// Try to read request buffer of interrupt OUT EP.
+/// Set pData to 0 to get current data length only.
+/// \param pData Pointer to data buffer
+/// \param dLength Data buffer length
+/// \return Number of bytes read
+//------------------------------------------------------------------------------
+unsigned short HIDDTransferDriver_Read(void *pData,
+ unsigned int dLength)
+{
+ if (pData == 0) {
+
+ return hiddTransferDriver.iLen;
+ }
+
+ if (dLength > HIDDTransferDriver_REPORTSIZE) {
+
+ dLength = HIDDTransferDriver_REPORTSIZE;
+ }
+ if (dLength > hiddTransferDriver.iLen) {
+
+ dLength = hiddTransferDriver.iLen;
+ }
+ hiddTransferDriver.iLen = 0;
+ memcpy(pData, hiddTransferDriver.iBuf, dLength);
+
+ return dLength;
+}
+
+//------------------------------------------------------------------------------
+/// Set data in IN report buffer, which will be sent when GetReport request
+/// issued.
+/// \param pData Pointer to the data sent.
+/// \param dLength The data length.
+//------------------------------------------------------------------------------
+void HIDDTransferDriver_SetReport(const void *pData,
+ unsigned int dLength)
+{
+ if (pData == 0 || dLength == 0)
+ return;
+ if (dLength != HIDDTransferDriver_REPORTSIZE) {
+ dLength = HIDDTransferDriver_REPORTSIZE;
+ }
+ if (hiddTransferDriver.oReportLen) {
+ TRACE_INFO("Changing IN report!\n\r");
+ }
+ memcpy(hiddTransferDriver.oReportBuf, pData, dLength);
+ hiddTransferDriver.oReportLen = dLength;
+}
+
+//------------------------------------------------------------------------------
+/// Write data through USB interrupt IN EP.
+/// \param pData Pointer to the data sent.
+/// \param dLength The data length.
+/// \param fCallback Callback function invoked when transferring done.
+/// \param pArg Pointer to additional arguments.
+//------------------------------------------------------------------------------
+unsigned char HIDDTransferDriver_Write(const void *pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void *pArg)
+{
+ if (dLength != HIDDTransferDriver_REPORTSIZE) {
+
+ dLength = HIDDTransferDriver_REPORTSIZE;
+ }
+ return USBD_Write(HIDDTransferDriverDescriptors_INTERRUPTIN,
+ pData, dLength,
+ fCallback, pArg);
+}
+
+//------------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//------------------------------------------------------------------------------
+void HIDDTransferDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&(hiddTransferDriver.usbdDriver))) {
+
+ USBD_RemoteWakeUp();
+ }
+}
+
diff --git a/usb/device/hid-transfer/HIDDTransferDriver.h b/usb/device/hid-transfer/HIDDTransferDriver.h new file mode 100644 index 0000000..f374ae0 --- /dev/null +++ b/usb/device/hid-transfer/HIDDTransferDriver.h @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definition of methods for using a HID transfer %device driver.
+
+ !!!Usage
+
+ -# Re-implement the USBDCallbacks_RequestReceived callback to forward
+ requests to HIDDTransferDriver_RequestHandler. This is done
+ automatically unless the NOAUTOCALLBACK symbol is defined during
+ compilation.
+ -# Initialize the driver using HIDDTransferDriver_Initialize. The
+ USB driver is automatically initialized by this method.
+ -# Call the HIDDTransferDriver_Write method when sendint data to host.
+ -# Call the HIDDTransferRead, HIDDTransferReadReport when checking and getting
+ received data from host.
+*/
+
+#ifndef HIDDKEYBOARDDRIVER_H
+#define HIDDKEYBOARDDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDTransferDriver_Initialize();
+
+extern void HIDDTransferDriver_RequestHandler(const USBGenericRequest *request);
+
+extern unsigned short HIDDTransferDriver_Read(void *pData,
+ unsigned int dLength);
+
+extern unsigned short HIDDTransferDriver_ReadReport(void *pData,
+ unsigned int dLength);
+
+extern unsigned char HIDDTransferDriver_Write(const void *pData,
+ unsigned int size,
+ TransferCallback callback,
+ void *pArg);
+
+
+extern void HIDDTransferDriver_RemoteWakeUp(void);
+
+#endif //#ifndef HIDDKEYBOARDDRIVER_H
+
diff --git a/usb/device/hid-transfer/HIDDTransferDriverDesc.c b/usb/device/hid-transfer/HIDDTransferDriverDesc.c new file mode 100644 index 0000000..5cd6363 --- /dev/null +++ b/usb/device/hid-transfer/HIDDTransferDriverDesc.c @@ -0,0 +1,417 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDTransferDriverDescriptors
+
+ About: Purpose
+ Declaration of the descriptors used by the HID device Transfer driver.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDTransferDriverDesc.h"
+#include <board.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDeviceDescriptor.h>
+#include <usb/common/hid/HIDInterfaceDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDReport.h>
+#include <usb/common/hid/HIDGenericDesktop.h>
+#include <usb/common/hid/HIDLeds.h>
+#include <usb/common/hid/HIDButton.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Transfer Device Descriptor IDs"
+/// ...
+///
+/// !IDs
+/// - HIDDTransferDriverDescriptors_PRODUCTID
+/// - HIDDTransferDriverDescriptors_VENDORID
+/// - HIDDTransferDriverDescriptors_RELEASE
+
+/// Device product ID.
+#define HIDDTransferDriverDescriptors_PRODUCTID 0x6201
+/// Device vendor ID.
+#define HIDDTransferDriverDescriptors_VENDORID 0x03EB
+/// Device release number.
+#define HIDDTransferDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+/// Returns the minimum between two values.
+#define MIN(a, b) ((a < b) ? a : b)
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+/// List of descriptors that make up the configuration descriptors of a
+/// device using the HID Transfer driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Configuration descriptor.
+ USBConfigurationDescriptor configuration;
+ /// Interface descriptor.
+ USBInterfaceDescriptor interface;
+ /// HID descriptor.
+ HIDDescriptor hid;
+ /// Interrupt IN endpoint descriptor.
+ USBEndpointDescriptor interruptIn;
+ /// Interrupt OUT endpoint descriptor.
+ USBEndpointDescriptor interruptOut;
+
+} __attribute__ ((packed)) HIDDTransferDriverConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Device descriptor.
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDTransferDriverDescriptors_VENDORID,
+ HIDDTransferDriverDescriptors_PRODUCTID,
+ HIDDTransferDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Device qualifier descriptor (high-speed only).
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // One possible configuration
+ 0 // Reserved
+};
+#endif
+
+/// Configuration descriptor.
+static const HIDDTransferDriverConfigurationDescriptors configurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDTransferDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDTransferDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDTransferDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(
+ HIDDTransferDriverDescriptors_INTERRUPTIN),
+ MIN(USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
+ HIDDTransferDriver_REPORTSIZE)),
+ HIDDTransferDriverDescriptors_INTERRUPTIN_POLLING
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDTransferDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(
+ HIDDTransferDriverDescriptors_INTERRUPTOUT),
+ MIN(USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
+ HIDDTransferDriver_REPORTSIZE)),
+ HIDDTransferDriverDescriptors_INTERRUPTOUT_POLLING
+ }
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Other-speed configuration descriptor.
+static const HIDDTransferDriverConfigurationDescriptors otherSpeedDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(HIDDTransferDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDTransferDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDTransferDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(
+ HIDDTransferDriverDescriptors_INTERRUPTIN),
+ MIN(USBEndpointDescriptor_MAXINTERRUPTSIZE_HS,
+ HIDDTransferDriver_REPORTSIZE)),
+ HIDDTransferDriverDescriptors_INTERRUPTIN_POLLING
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDTransferDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(
+ HIDDTransferDriverDescriptors_INTERRUPTOUT),
+ MIN(USBEndpointDescriptor_MAXINTERRUPTSIZE_HS,
+ HIDDTransferDriver_REPORTSIZE)),
+ HIDDTransferDriverDescriptors_INTERRUPTIN_POLLING
+ }
+};
+#endif
+
+/*
+ Variables: String descriptors
+ languageIdDescriptor - Language ID string descriptor.
+ manufacturerDescriptor - Manufacturer name.
+ productDescriptor - Product name.
+ serialNumberDescriptor - Product serial number.
+ stringDescriptors - Array of pointers to string descriptors.
+*/
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+static const unsigned char manufacturerDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(5),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L')
+};
+
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(22),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('H'),
+ USBStringDescriptor_UNICODE('I'),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('R'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('N'),
+ USBStringDescriptor_UNICODE('S'),
+ USBStringDescriptor_UNICODE('F'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('R'),
+};
+
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(12),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('F')
+};
+
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors used by the HID Transfer driver.
+USBDDriverDescriptors hiddTransferDriverDescriptors = {
+
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+#else
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration
+ 0, // No high-speed device descriptor
+ 0, // No high-speed configuration descriptor
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+#endif
+ stringDescriptors,
+ 4 // Four string descriptors in list
+};
+
+/// Report descriptor used by the driver.
+const unsigned char hiddReportDescriptor[] = {
+
+ // Global Usage Page
+ HIDReport_GLOBAL_USAGEPAGE + 2, 0xFF, 0xFF, // Vendor-defined
+ // Collection: Application
+ HIDReport_LOCAL_USAGE + 1, 0xFF, // Vendor-defined
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+ // Input report: Vendor-defined
+ HIDReport_LOCAL_USAGE + 1, 0xFF, // Vendor-defined usage
+ HIDReport_GLOBAL_REPORTCOUNT + 1, HIDDTransferDriver_REPORTSIZE,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, (unsigned char) -128,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, (unsigned char) 127,
+ HIDReport_INPUT + 1, 0, // No Modifiers
+
+ // Output report: vendor-defined
+ HIDReport_LOCAL_USAGE + 1, 0xFF, // Vendor-defined usage
+ HIDReport_GLOBAL_REPORTCOUNT + 1, HIDDTransferDriver_REPORTSIZE,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, (unsigned char) -128,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, (unsigned char) 127,
+ HIDReport_OUTPUT + 1, 0, // No Modifiers
+
+ HIDReport_ENDCOLLECTION
+};
+
diff --git a/usb/device/hid-transfer/HIDDTransferDriverDesc.h b/usb/device/hid-transfer/HIDDTransferDriverDesc.h new file mode 100644 index 0000000..6b9beb7 --- /dev/null +++ b/usb/device/hid-transfer/HIDDTransferDriverDesc.h @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit
+
+ !!!Purpose
+
+ Definitions of the descriptors required by the HID transfer %device driver.
+
+ !!!Usage
+
+ -# Use the hiddTransferDriverDescriptors variable to initialize a
+ USBDDriver instance.
+ -# Send hiddReportDescriptor to the host when a GET_DESCRIPTOR request
+ for the report descriptor is received.
+*/
+
+#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+#define HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+#include <usb/common/hid/HIDKeypad.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Interrupt IN endpoint number.
+#define HIDDTransferDriverDescriptors_INTERRUPTIN 1
+/// Polling rate in ms
+#define HIDDTransferDriverDescriptors_INTERRUPTIN_POLLING 50
+/// Interrupt IN endpoint polling rate (in milliseconds).
+#define HIDDTransferDriverDescriptors_INTERRUPTOUT 2
+/// Polling rate in ms
+#define HIDDTransferDriverDescriptors_INTERRUPTOUT_POLLING 50
+
+/// Size of the report descriptor in bytes.
+#define HIDDTransferDriverDescriptors_REPORTSIZE 32
+
+/// Size of the input and output report, in bytes
+#define HIDDTransferDriver_REPORTSIZE 32
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+/*
+ Variables: HID keyboard driver descriptors
+ hiddTransferDriverDescriptors - List of descriptors used by the HID
+ keyboard driver.
+ hiddReportDescriptor - Report descriptor used by the driver.
+*/
+extern USBDDriverDescriptors hiddTransferDriverDescriptors;
+extern const unsigned char hiddReportDescriptor[];
+
+#endif //#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/hid-transfer/hid-transfer.dir b/usb/device/hid-transfer/hid-transfer.dir new file mode 100644 index 0000000..a478e50 --- /dev/null +++ b/usb/device/hid-transfer/hid-transfer.dir @@ -0,0 +1,473 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB HID
+/// %device - USB HID Transfer driver, to implement an USB HID compatible
+/// %device for customized data transmitting.
+///
+/// !!!Contents
+///
+/// There are three things for the implement of the USB HID Transfer driver:
+/// - Implement the USB HID driver structs and functions for the %device,
+/// to initialize, to handle HID-specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the HID Transfer device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the %device as a USB Transfer %device.
+/// - Implement methods to read/write data through interrupt endpoints, so that
+/// host and device can exchange data.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB HID Transfer".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB HID Transfer"
+ This page describes how to use the "AT91 USB device framework" to produce a USB
+ HID Transfer driver, which appears as a USB HID complient device on host.
+
+ Details about the USB and the HID class can be found in the }USB specification
+ 2.0} and the }HID specification 1.11}, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+ !!!HID Basic
+ See "USB HID Basic".
+
+ !!!Architecture
+ See "USB Device Framework Architecture".
+
+ !!!Descriptors
+
+ ...
+
+ !!Device Descriptor
+ The Device descriptor of an HID %device is very basic, since the HID class
+ code is only specified at the Interface level. Thus, it only contains
+ standard values, as shown below:
+\code
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDKeyboardDriverDescriptors_VENDORID,
+ HIDDKeyboardDriverDescriptors_PRODUCTID,
+ HIDDKeyboardDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+\endcode
+ Note that the Vendor ID is a special value attributed by the USB-IF
+ organization. The product ID can be chosen freely by the vendor.
+
+ !!Configuration Descriptor
+ Since one interface is required by the HID specification, this must be
+ specified in the Configuration descriptor. There is no other value of
+ interest to put here.
+\code
+// Configuration descriptor
+{
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+},
+\endcode
+ When the Configuration descriptor is requested by the host (by using the
+ GET_DESCRIPTOR command), the %device must also sent all the related
+ descriptors, i.e. Interface, Endpoint and Class-Specific descriptors. It is
+ convenient to create a single structure to hold all this data, for sending
+ everything in one chunk. In the example software, a
+ HIDDKeyboardDriverConfigurationDescriptors structure has been declared for
+ that.
+
+ !!HID Class Interface Descriptor
+ Since a keyboard %device needs to transmit as well as receive data, two
+ Interrupt (IN & OUT) endpoints are needed. This must be indicated in the
+ Interface descriptor. Conversely to the mouse example, the Boot protocol is
+ not implemented here, since there are more constraints on a keyboard %device.
+\code
+// Interface descriptor
+{
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+},
+\endcode
+
+ !!HID Descriptor
+ While a HID keyboard produces two different reports, one Input and one Output,
+ only one Report descriptor can be used to describe them. Since having Physical
+ descriptors is also useless for a keyboard, there will only be one HID class
+ descriptor specified here.
+
+ For a keyboard, the }bCountryCode} field can be used to specify the language
+ of the key caps. As this is optional, it is simply set to 00h in the example:
+\code
+// HID descriptor
+{
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+},
+\endcode
+
+ !!Report Descriptor
+ Two current reports are defined in the Report descriptor. The first one is
+ used to notify the host of which keys are pressed, with both modifier keys
+ (alt, ctrl, etc.) and alphanumeric keys. The second report is necessary for
+ the host to send the LED (num lock, caps lock, etc.) states.
+
+ The Report descriptor starts with the global %device functionality, described
+ with a #Usage Page# and a #Usage# items:
+\code
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 2, 0xFF, 0xFF, // Vendor-defined
+ HIDReport_LOCAL_USAGE + 1, 0xFF, // Vendor-defined
+\endcode
+
+ An Application collection is then defined to group the reports together:
+\code
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+\endcode
+
+ The first report to be defined is the input report, all data in the buffer
+ is vendor defined:
+\code
+ // Input report: Vendor-defined
+ HIDReport_LOCAL_USAGE + 1, 0xFF, // Vendor-defined usage
+ HIDReport_GLOBAL_REPORTCOUNT + 1, HIDDTransferDriver_REPORTSIZE,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, (unsigned char) -128,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, (unsigned char) 127,
+ HIDReport_INPUT + 1, 0, // No Modifiers
+\endcode
+
+ The output report is then defined, data is for the user to decode:
+\code
+ // Output report: vendor-defined
+ HIDReport_LOCAL_USAGE + 1, 0xFF, // Vendor-defined usage
+ HIDReport_GLOBAL_REPORTCOUNT + 1, HIDDTransferDriver_REPORTSIZE,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, (unsigned char) -128,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, (unsigned char) 127,
+ HIDReport_OUTPUT + 1, 0, // No Modifiers
+\endcode
+
+ The last item, }End Collection}, is necessary to close the previously opened
+ }Application Collection}.
+\code
+ HIDReport_ENDCOLLECTION
+};
+\endcode
+
+ The input report and output report are all user defined. We define the first
+ byte as bit map of push buttons and LEDs, remaining bytes as data.
+
+ !!Physical Descriptor
+ A Physical descriptor is useless for a general transfer %device, so none is
+ defined in this example.
+
+ !!Endpoint Descriptor
+ Following the Interface and HID-specific descriptors, the two necessary
+ endpoints are defined.
+\code
+// Interrupt IN endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+},
+// Interrupt OUT endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+}
+\endcode
+
+ !!String Descriptors
+ Please refer to "Usage: USBD VID, PID & Strings".
+
+ !!!Class-specific requests
+ A driver request handler should first differentiate between class-specific and
+ standard requests using the corresponding bits in the }bmRequestType} field.
+ In most cases, standard requests can be immediately forwarded to the standard
+ request handler method; class-specific methods must be decoded and treated by
+ the custom handler.
+
+ !!GetDescriptor
+ Three values have been added by the HID specification for the #GET_DESCRIPTOR#
+ request. The high byte of the }wValue} field contains the type of the
+ requested descriptor; in addition to the standard types, the #HID
+ specification# adds the #HID descriptor# (21h), the #Report descriptor#
+ (22h) and the #Physical descriptor# (23h) types.
+
+ There is no particular action to perform besides sending the descriptor. This
+ can be done by using the USBD_Write method, after the requested descriptor has
+ been identified:
+\code
+switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor,
+ // otherwise forward it to
+ // the standard driver
+ if (!HIDDKeyboardDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+}
+\endcode
+ A slight complexity of the GET_DESCRIPTOR and SET_DESCRIPTOR requests is that
+ those are standard requests, but the standard request handler
+ (USBDDriver_RequestHandler) must not always be called to treat them (since
+ they may refer to HID descriptors). The solution is to first identify
+ GET/SET_DESCRIPTOR requests, treat the HID-specific cases and, finally,
+ forward any other request to the standard handler.
+
+ In this case, a GET_DESCRIPTOR request for the Physical descriptor is first
+ forwarded to the standard handler, and STALLed there because it is not
+ recognized. This is done because the %device does not have any Physical
+ descriptors, and thus, does not need to handle the associated request.
+
+ !!SetDescriptor
+ This request is optional and is never issued by most hosts. It is not
+ implemented in this example.
+
+ !!GetReport
+ Since the HID keyboard defines two different reports, the Report Type value
+ specified by this request (upper byte of the }wValue} field) must be examined
+ to decide which report to send. If the type value is 01h, then the Input
+ report must be returned; if it is 02h, the Output report is requested:
+\code
+case HIDGenericRequest_GETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardInputReport)) {
+
+ length = sizeof(HIDDKeyboardInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardOutputReport)) {
+
+ length = sizeof(HIDDKeyboardOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetReport
+ For an HID keyboard, the #SET_REPORT# command can be sent by the host to
+ change the state of the LEDs. Normally, the dedicated Interrupt OUT endpoint
+ will be used for this; but in some cases, using the default Control endpoint
+ can save some bandwidth on the host side.
+
+ Note that the SET_REPORT request can be directed at the Input report of the
+ keyboard; in this case, it can be safely discarded, according to the HID
+ specification. Normally, most host drivers only target the Output report. The
+ Report Type value is stored in the upper byte of the }wValue} field.
+
+ The length of the data phase to follow is stored in the }wLength} field of the
+ request. It should be equal to the total length of the Output report. If it is
+ different, the report status must still be updated with the received data as
+ best as possible.
+
+ When the reception of the new data is completed, some processing must be done
+ to enable/disable the corresponding LEDs. This is done in the callback
+ function passed as an argument to USBD_Read:
+\code
+case HIDGenericRequest_SETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch(type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDKeyboardOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetIdle
+ In this case study, the #SET_IDLE# request is used to set a delay before a key
+ is repeated. This is common behavior on keyboard devices. Usually, this delay
+ is set to about 500 ms by the host.
+
+ The only action here is to store the new Idle rate. The management of this
+ setting must be done in the main function, since Interrupt IN reports are sent
+ from there.
+
+ In practice, it is not necessary to perform any action, apart from sending a
+ zero-length packet to acknowledge it. The main application however has to make
+ sure that only new reports are sent by the %device.
+\code
+case HIDGenericRequest_SETIDLE:
+//-----------------------------
+ hiddKeyboardDriver.inputReportIdleRate =
+ HIDIdleRequest_GetIdleRate(request);
+ USBD_Write(0, 0, 0, 0, 0);
+break;
+\endcode
+
+ !!GetIdle
+ The only necessary operation for this request is to send the previously saved
+ Idle rate. This is done by calling the USBD_Write method with the one-byte
+ variable as its parameter:
+\code
+case HIDGenericRequest_GETIDLE:
+//-----------------------------
+ USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
+break;
+\endcode
+
+ !!GetProtocol, SetProtocol
+ This HID keyboard example does not support the Boot protocol, so there is no
+ need to implement the SET_PROTOCOL and GET_PROTOCOL requests. This means they
+ can be safely STALLed when received.
+
+ !!!Main Application
+ Like the mouse example, the main program must perform two different
+ operations. First, it has to monitor the physical inputs used as keys. In the
+ example software, the buttons present on the evaluation boards are used to
+ produce several modifier and alphanumeric keys.
+
+ Also, the main program is in charge of sending reports as they are modified,
+ taking into account the Idle rate specified by the host. Idle rate management
+ can be carried out by firing/resetting a timer once a new report is sent; if
+ the timer expires, this means the Input report has not changed since.
+ According to the HID specification, a single instance of the report must be
+ sent in this case.
+
+ Finally, the HID specification also defines that if too many keys are pressed
+ at the same time, the %device should report an }ErrorRollOver} usage value
+ (01h) in every byte of the key array. This has to be handled by the main
+ application as well.
+
+*/
\ No newline at end of file diff --git a/usb/device/massstorage/MSD.h b/usb/device/massstorage/MSD.h new file mode 100644 index 0000000..decab4a --- /dev/null +++ b/usb/device/massstorage/MSD.h @@ -0,0 +1,233 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Mass Storage class definitions.
+///
+/// See
+/// - <a
+/// href="http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf">
+/// USB Mass Storage Class Spec. Overview</a>
+/// - <a href="http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf">
+/// USB Mass Storage Class Bulk-Only Transport</a>
+///
+/// !Usage
+///
+/// -# Uses "MSD Requests" to check incoming requests from USB Host.
+/// -# Uses "MSD Subclass Codes" and "MSD Protocol Codes" to fill %device
+/// interface descriptors for a MSD %device.
+/// -# Handle the incoming Bulk data with "MSD CBW Definitions" and MSCbw
+/// structure.
+/// -# Prepare the outgoing Bulk data with "MSD CSW Definitions" and MSCsw
+/// structure.
+//------------------------------------------------------------------------------
+
+#ifndef MSD_H
+#define MSD_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Requests"
+/// This page lists MSD-specific requests ( Actually for Bulk-only protocol ).
+///
+/// !Requests
+/// - MSD_BULK_ONLY_RESET
+/// - MSD_GET_MAX_LUN
+
+/// Reset the mass storage %device and its associated interface.
+#define MSD_BULK_ONLY_RESET 0xFF
+/// Return the maximum LUN number supported by the %device.
+#define MSD_GET_MAX_LUN 0xFE
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Subclass Codes"
+/// This page lists the Subclass Codes for bInterfaceSubClass field.
+/// (Table 2.1, USB Mass Storage Class Spec. Overview)
+///
+/// !SubClasses
+/// - MSD_SUBCLASS_RBC
+/// - MSD_SUBCLASS_SFF_MCC
+/// - MSD_SUBCLASS_QIC
+/// - MSD_SUBCLASS_UFI
+/// - MSD_SUBCLASS_SFF
+/// - MSD_SUBCLASS_SCSI
+
+/// Reduced Block Commands (RBC) T10
+#define MSD_SUBCLASS_RBC 0x01
+/// C/DVD devices
+#define MSD_SUBCLASS_SFF_MCC 0x02
+/// Tape device
+#define MSD_SUBCLASS_QIC 0x03
+/// Floppy disk drive (FDD) device
+#define MSD_SUBCLASS_UFI 0x04
+/// Floppy disk drive (FDD) device
+#define MSD_SUBCLASS_SFF 0x05
+/// SCSI transparent command set
+#define MSD_SUBCLASS_SCSI 0x06
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+/// \page "MSD Protocol Codes"
+/// This page lists the Transport Protocol codes for MSD.
+/// (Table 3.1, USB Mass Storage Class Spec. Overview)
+///
+/// !Protocols
+/// - MSD_PROTOCOL_CBI_COMPLETION
+/// - MSD_PROTOCOL_CBI
+/// - MSD_PROTOCOL_BULK_ONLY
+
+/// Control/Bulk/Interrupt (CBI) Transport (with command complete interrupt)
+#define MSD_PROTOCOL_CBI_COMPLETION 0x00
+/// Control/Bulk/Interrupt (CBI) Transport (no command complete interrupt)
+#define MSD_PROTOCOL_CBI 0x01
+/// Bulk-Only Transport
+#define MSD_PROTOCOL_BULK_ONLY 0x50
+//------------------------------------------------------------------------------
+
+/// Test unit control:
+#define CTRL_NOT_READY 0x00
+#define CTRL_GOOD 0x01
+#define CTRL_BUSY 0x02
+
+//------------------------------------------------------------------------------
+/// \page "MSD CBW Definitions"
+/// This page lists the Command Block Wrapper (CBW) definitions.
+///
+/// !Constants
+/// - MSD_CBW_SIZE
+/// - MSD_CBW_SIGNATURE
+///
+/// !Fields
+/// - MSD_CBW_DEVICE_TO_HOST
+
+/// Command Block Wrapper Size
+#define MSD_CBW_SIZE 31
+/// 'USBC' 0x43425355
+#define MSD_CBW_SIGNATURE 0x43425355
+
+/// CBW bmCBWFlags field
+#define MSD_CBW_DEVICE_TO_HOST (1 << 7)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD CSW Definitions"
+/// This page lists the Command Status Wrapper (CSW) definitions.
+///
+/// !Constants
+/// - MSD_CSW_SIZE
+/// - MSD_CSW_SIGNATURE
+///
+/// !Command Block Status Values
+/// (Table 5.3 , USB Mass Storage Class Bulk-Only Transport)
+/// - MSD_CSW_COMMAND_PASSED
+/// - MSD_CSW_COMMAND_FAILED
+/// - MSD_CSW_PHASE_ERROR
+
+/// Command Status Wrapper Size
+#define MSD_CSW_SIZE 13
+/// 'USBS' 0x53425355
+#define MSD_CSW_SIGNATURE 0x53425355
+
+/// Command Passed (good status)
+#define MSD_CSW_COMMAND_PASSED 0
+/// Command Failed
+#define MSD_CSW_COMMAND_FAILED 1
+/// Phase Error
+#define MSD_CSW_PHASE_ERROR 2
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Structures
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Command Block Wrapper (CBW),
+/// See Table 5.1, USB Mass Storage Class Bulk-Only Transport.
+///
+/// The CBW shall start on a packet boundary and shall end as a
+/// short packet with exactly 31 (1Fh) bytes transferred.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// 'USBC' 0x43425355 (little endian)
+ unsigned int dCBWSignature;
+ /// Must be the same as dCSWTag
+ unsigned int dCBWTag;
+ /// Number of bytes transfer
+ unsigned int dCBWDataTransferLength;
+ /// Indicates the directin of the transfer:
+ /// 0x80=IN=device-to-host,
+ /// 0x00=OUT=host-to-device
+ unsigned char bmCBWFlags;
+ /// bits 0->3: bCBWLUN
+ unsigned char bCBWLUN :4,
+ bReserved1:4; /// reserved
+ /// bits 0->4: bCBWCBLength
+ unsigned char bCBWCBLength:5,
+ bReserved2 :3; /// reserved
+ /// Command block
+ unsigned char pCommand[16];
+
+} MSCbw;
+
+//------------------------------------------------------------------------------
+/// Command Status Wrapper (CSW),
+/// See Table 5.2, USB Mass Storage Class Bulk-Only Transport.
+//------------------------------------------------------------------------------
+typedef struct
+{
+ /// 'USBS' 0x53425355 (little endian)
+ unsigned int dCSWSignature;
+ /// Must be the same as dCBWTag
+ unsigned int dCSWTag;
+ /// For Data-Out the device shall report in the dCSWDataResidue the
+ /// difference between the amount of data expected as stated in the
+ /// dCBWDataTransferLength, and the actual amount of data processed by
+ /// the device. For Data-In the device shall report in the dCSWDataResidue
+ /// the difference between the amount of data expected as stated in the
+ /// dCBWDataTransferLength and the actual amount of relevant data sent by
+ /// the device. The dCSWDataResidue shall not exceed the value sent in the
+ /// dCBWDataTransferLength.
+ unsigned int dCSWDataResidue;
+ /// Indicates the success or failure of the command.
+ unsigned char bCSWStatus;
+
+} MSCsw;
+
+#endif //#ifndef MSD_H
+
diff --git a/usb/device/massstorage/MSDAppArch.png b/usb/device/massstorage/MSDAppArch.png Binary files differnew file mode 100644 index 0000000..eec0f15 --- /dev/null +++ b/usb/device/massstorage/MSDAppArch.png diff --git a/usb/device/massstorage/MSDDStateMachine.c b/usb/device/massstorage/MSDDStateMachine.c new file mode 100644 index 0000000..bc69a49 --- /dev/null +++ b/usb/device/massstorage/MSDDStateMachine.c @@ -0,0 +1,607 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+
+#include "SBCMethods.h"
+#include "MSDDStateMachine.h"
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Returns the expected transfer length and direction (IN, OUT or don't care)
+/// from the host point-of-view.
+/// \param cbw Pointer to the CBW to examinate
+/// \param pLength Expected length of command
+/// \param pType Expected direction of command
+//-----------------------------------------------------------------------------
+static void MSDD_GetCommandInformation(MSCbw *cbw,
+ unsigned int *length,
+ unsigned char *type)
+{
+ // Expected host transfer direction and length
+ (*length) = cbw->dCBWDataTransferLength;
+
+ if (*length == 0) {
+
+ (*type) = MSDD_NO_TRANSFER;
+ }
+ else if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) != 0) {
+
+ (*type) = MSDD_DEVICE_TO_HOST;
+ }
+ else {
+
+ (*type) = MSDD_HOST_TO_DEVICE;
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Pre-processes a command by checking the differences between the host and
+/// device expectations in term of transfer type and length.
+/// Once one of the thirteen cases is identified, the actions to do during the
+/// post-processing phase are stored in the dCase variable of the command
+/// state.
+/// \param pMsdDriver Pointer to a MSDDriver instance
+/// \return 1 if the command is supported, false otherwise
+//-----------------------------------------------------------------------------
+static unsigned char MSDD_PreProcessCommand(MSDDriver *pMsdDriver)
+{
+ unsigned int hostLength = 0;
+ unsigned int deviceLength = 0;
+ unsigned char hostType;
+ unsigned char deviceType;
+ unsigned char isCommandSupported;
+ MSDCommandState *commandState = &(pMsdDriver->commandState);
+ MSCsw *csw = &(commandState->csw);
+ MSCbw *cbw = &(commandState->cbw);
+ MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
+
+ // Get information about the command
+ // Host-side
+ MSDD_GetCommandInformation(cbw, &hostLength, &hostType);
+
+ // Device-side
+ isCommandSupported = SBC_GetCommandInformation(cbw->pCommand,
+ &deviceLength,
+ &deviceType,
+ lun);
+
+ // Initialize data residue and result status
+ csw->dCSWDataResidue = 0;
+ csw->bCSWStatus = MSD_CSW_COMMAND_PASSED;
+
+ // Check if the command is supported
+ if (isCommandSupported) {
+
+ // Identify the command case
+ if(hostType == MSDD_NO_TRANSFER) {
+
+ // Case 1 (Hn = Dn)
+ if(deviceType == MSDD_NO_TRANSFER) {
+
+ //TRACE_WARNING("Case 1\n\r");
+ commandState->postprocess = 0;
+ commandState->length = 0;
+ }
+ else if(deviceType == MSDD_DEVICE_TO_HOST) {
+
+ // Case 2 (Hn < Di)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 2\n\r");
+ commandState->postprocess = MSDD_CASE_PHASE_ERROR;
+ commandState->length = 0;
+ }
+ else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
+
+ // Case 3 (Hn < Do)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 3\n\r");
+ commandState->postprocess = MSDD_CASE_PHASE_ERROR;
+ commandState->length = 0;
+ }
+ }
+
+ // Case 4 (Hi > Dn)
+ else if(hostType == MSDD_DEVICE_TO_HOST) {
+
+ if(deviceType == MSDD_NO_TRANSFER) {
+
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 4\n\r");
+ commandState->postprocess = MSDD_CASE_STALL_IN;
+ commandState->length = 0;
+ csw->dCSWDataResidue = hostLength;
+ }
+ else if(deviceType == MSDD_DEVICE_TO_HOST) {
+
+ if(hostLength > deviceLength) {
+
+ // Case 5 (Hi > Di)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 5\n\r");
+ commandState->postprocess = MSDD_CASE_STALL_IN;
+ commandState->length = deviceLength;
+ csw->dCSWDataResidue = hostLength - deviceLength;
+ }
+ else if(hostLength == deviceLength) {
+
+ // Case 6 (Hi = Di)
+ commandState->postprocess = 0;
+ commandState->length = deviceLength;
+ }
+ else { //if(hostLength < deviceLength) {
+
+ // Case 7 (Hi < Di)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 7\n\r");
+ commandState->postprocess = MSDD_CASE_PHASE_ERROR;
+ commandState->length = hostLength;
+ }
+ }
+ else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
+
+ // Case 8 (Hi <> Do)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 8\n\r");
+ commandState->postprocess =
+ MSDD_CASE_STALL_IN | MSDD_CASE_PHASE_ERROR;
+ commandState->length = 0;
+ }
+ }
+ else if(hostType == MSDD_HOST_TO_DEVICE) {
+
+ if(deviceType == MSDD_NO_TRANSFER) {
+
+ // Case 9 (Ho > Dn)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 9\n\r");
+ commandState->postprocess = MSDD_CASE_STALL_OUT;
+ commandState->length = 0;
+ csw->dCSWDataResidue = hostLength;
+ }
+ else if(deviceType == MSDD_DEVICE_TO_HOST) {
+
+ // Case 10 (Ho <> Di)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 10\n\r");
+ commandState->postprocess =
+ MSDD_CASE_STALL_OUT | MSDD_CASE_PHASE_ERROR;
+ commandState->length = 0;
+ }
+ else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
+
+ if(hostLength > deviceLength) {
+
+ // Case 11 (Ho > Do)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 11\n\r");
+ commandState->postprocess = MSDD_CASE_STALL_OUT;
+// commandState->length = deviceLength;
+// csw->dCSWDataResidue = hostLength - deviceLength;
+ commandState->length = 0;
+ csw->dCSWDataResidue = deviceLength;
+ }
+ else if(hostLength == deviceLength) {
+
+ // Case 12 (Ho = Do)
+ //TRACE_WARNING(
+ // "MSDD_PreProcessCommand: Case 12\n\r");
+ commandState->postprocess = 0;
+ commandState->length = deviceLength;
+ }
+ else { //if(hostLength < deviceLength) {
+
+ // Case 13 (Ho < Do)
+ TRACE_WARNING(
+ "MSDD_PreProcessCommand: Case 13\n\r");
+ commandState->postprocess = MSDD_CASE_PHASE_ERROR;
+ commandState->length = hostLength;
+ }
+ }
+ }
+ }
+
+ return isCommandSupported;
+}
+
+//-----------------------------------------------------------------------------
+/// Post-processes a command given the case identified during the
+/// pre-processing step.
+/// Depending on the case, one of the following actions can be done:
+/// - Bulk IN endpoint is stalled
+/// - Bulk OUT endpoint is stalled
+/// - CSW status set to phase error
+/// \param pMsdDriver Pointer to a MSDDriver instance
+/// \return If the device is halted
+//-----------------------------------------------------------------------------
+static unsigned char MSDD_PostProcessCommand(MSDDriver *pMsdDriver)
+{
+ MSDCommandState *commandState = &(pMsdDriver->commandState);
+ MSCsw *csw = &(commandState->csw);
+ unsigned char haltStatus = 0;
+
+ // STALL Bulk IN endpoint ?
+ if ((commandState->postprocess & MSDD_CASE_STALL_IN) != 0) {
+
+ TRACE_INFO_WP("StallIn ");
+ MSDD_Halt(MSDD_CASE_STALL_IN);
+ haltStatus = 1;
+ }
+
+ // STALL Bulk OUT endpoint ?
+ if ((commandState->postprocess & MSDD_CASE_STALL_OUT) != 0) {
+
+ TRACE_INFO_WP("StallOut ");
+ MSDD_Halt(MSDD_CASE_STALL_OUT);
+ haltStatus = 1;
+ }
+
+ // Set CSW status code to phase error ?
+ if ((commandState->postprocess & MSDD_CASE_PHASE_ERROR) != 0) {
+
+ TRACE_INFO_WP("PhaseErr ");
+ csw->bCSWStatus = MSD_CSW_PHASE_ERROR;
+ }
+
+ return haltStatus;
+}
+
+//-----------------------------------------------------------------------------
+/// Processes the latest command received by the %device.
+/// \param pMsdDriver Pointer to a MSDDriver instance
+/// \return 1 if the command has been completed, false otherwise.
+//-----------------------------------------------------------------------------
+static unsigned char MSDD_ProcessCommand(MSDDriver * pMsdDriver)
+{
+ unsigned char status;
+ MSDCommandState *commandState = &(pMsdDriver->commandState);
+ MSCbw *cbw = &(commandState->cbw);
+ MSCsw *csw = &(commandState->csw);
+ MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
+ unsigned char isCommandComplete = 0;
+
+ // Check if LUN is valid
+ if (cbw->bCBWLUN > pMsdDriver->maxLun) {
+
+ TRACE_WARNING(
+ "MSDD_ProcessCommand: LUN %d not exist\n\r", cbw->bCBWLUN);
+ status = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ // Process command
+ if (pMsdDriver->maxLun > 0) {
+
+ TRACE_INFO_WP("LUN%d ", cbw->bCBWLUN);
+ }
+
+ status = SBC_ProcessCommand(lun, commandState);
+ }
+
+ // Check command result code
+ if (status == MSDD_STATUS_PARAMETER) {
+
+ TRACE_WARNING(
+ "MSDD_ProcessCommand: Unknown cmd 0x%02X\n\r",
+ cbw->pCommand[0]);
+
+ // Update sense data
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_ILLEGAL_REQUEST,
+ SBC_ASC_INVALID_FIELD_IN_CDB,
+ 0);
+
+ // Result codes
+ csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
+ isCommandComplete = 1;
+
+ // stall the request, IN or OUT
+ if (((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0)
+ && (cbw->dCBWDataTransferLength > 0)) {
+
+ // Stall the OUT endpoint : host to device
+ // MSDD_Halt(MSDD_CASE_STALL_OUT);
+ commandState->postprocess = MSDD_CASE_STALL_OUT;
+ TRACE_INFO_WP("StaOUT ");
+ }
+ else {
+
+ // Stall the IN endpoint : device to host
+ // MSDD_Halt(MSDD_CASE_STALL_IN);
+ commandState->postprocess = MSDD_CASE_STALL_IN;
+ TRACE_INFO_WP("StaIN ");
+ }
+ }
+ else if (status == MSDD_STATUS_ERROR) {
+
+ TRACE_WARNING("MSD_ProcessCommand: Cmd %x fail\n\r",
+ ((SBCCommand*)commandState->cbw.pCommand)->bOperationCode);
+
+ // Update sense data
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_MEDIUM_ERROR,
+ SBC_ASC_INVALID_FIELD_IN_CDB,
+ 0);
+
+ // Result codes
+ csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
+ isCommandComplete = 1;
+ }
+ else if (status == MSDD_STATUS_RW) {
+
+ csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
+ isCommandComplete = 1;
+ }
+ else {
+
+ // Update sense data
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_NO_SENSE,
+ 0,
+ 0);
+
+ // Is command complete ?
+ if (status == MSDD_STATUS_SUCCESS) {
+
+ isCommandComplete = 1;
+ }
+ }
+
+ // Check if command has been completed
+ if (isCommandComplete) {
+
+ TRACE_INFO_WP("Cplt ");
+
+ // Adjust data residue
+ if (commandState->length != 0) {
+
+ csw->dCSWDataResidue += commandState->length;
+
+ // STALL the endpoint waiting for data
+ if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0) {
+
+ // Stall the OUT endpoint : host to device
+ // MSDD_Halt(MSDD_CASE_STALL_OUT);
+ commandState->postprocess = MSDD_CASE_STALL_OUT;
+ TRACE_INFO_WP("StaOUT ");
+ }
+ else {
+
+ // Stall the IN endpoint : device to host
+ // MSDD_Halt(MSDD_CASE_STALL_IN);
+ commandState->postprocess = MSDD_CASE_STALL_IN;
+ TRACE_INFO_WP("StaIN ");
+ }
+ }
+
+ // Reset command state
+ commandState->state = 0;
+ }
+
+ return isCommandComplete;
+}
+
+//-----------------------------------------------------------------------------
+/// State machine for the MSD %device driver
+/// \param pMsdDriver Pointer to a MSDDriver instance
+//-----------------------------------------------------------------------------
+void MSDD_StateMachine(MSDDriver * pMsdDriver)
+{
+ MSDCommandState *commandState = &(pMsdDriver->commandState);
+ MSCbw *cbw = &(commandState->cbw);
+ MSCsw *csw = &(commandState->csw);
+ MSDTransfer *transfer = &(commandState->transfer);
+ unsigned char status;
+
+ // Identify current driver state
+ switch (pMsdDriver->state) {
+ //----------------------
+ case MSDD_STATE_READ_CBW:
+ //----------------------
+ // Start the CBW read operation
+ transfer->semaphore = 0;
+ status = MSDD_Read(cbw,
+ MSD_CBW_SIZE,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check operation result code
+ if (status == USBD_STATUS_SUCCESS) {
+
+ // If the command was successful, wait for transfer
+ pMsdDriver->state = MSDD_STATE_WAIT_CBW;
+ }
+ break;
+
+ //----------------------
+ case MSDD_STATE_WAIT_CBW:
+ //----------------------
+ // Check transfer semaphore
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and terminate transfer
+ transfer->semaphore--;
+
+ // Check if transfer was successful
+ if (transfer->status == USBD_STATUS_SUCCESS) {
+
+ TRACE_INFO_WP("------------------------------\n\r");
+
+ // Process received command
+ pMsdDriver->state = MSDD_STATE_PROCESS_CBW;
+ }
+ else if (transfer->status == USBD_STATUS_RESET) {
+
+ TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
+ pMsdDriver->state = MSDD_STATE_READ_CBW;
+ }
+ else {
+
+ TRACE_WARNING(
+ "MSDD_StateMachine: Failed to read CBW\n\r");
+ pMsdDriver->state = MSDD_STATE_READ_CBW;
+ }
+ }
+ break;
+
+ //-------------------------
+ case MSDD_STATE_PROCESS_CBW:
+ //-------------------------
+ // Check if this is a new command
+ if (commandState->state == 0) {
+
+ // Copy the CBW tag
+ csw->dCSWTag = cbw->dCBWTag;
+
+ // Check that the CBW is 31 bytes long
+ if ((transfer->transferred != MSD_CBW_SIZE) ||
+ (transfer->remaining != 0)) {
+
+ TRACE_WARNING(
+ "MSDD_StateMachine: Invalid CBW (len %d)\n\r",
+ (int)transfer->transferred);
+
+ // Wait for a reset recovery
+ pMsdDriver->waitResetRecovery = 1;
+
+ // Halt the Bulk-IN and Bulk-OUT pipes
+ MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);
+
+ csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
+ pMsdDriver->state = MSDD_STATE_READ_CBW;
+
+ }
+ // Check the CBW Signature
+ else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) {
+
+ TRACE_WARNING(
+ "MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r");
+
+ // Wait for a reset recovery
+ pMsdDriver->waitResetRecovery = 1;
+
+ // Halt the Bulk-IN and Bulk-OUT pipes
+ MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);
+
+ csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
+ pMsdDriver->state = MSDD_STATE_READ_CBW;
+ }
+ else {
+
+ // Pre-process command
+ MSDD_PreProcessCommand(pMsdDriver);
+ }
+ }
+
+ // Process command
+ if (csw->bCSWStatus == MSDD_STATUS_SUCCESS) {
+
+ if (MSDD_ProcessCommand(pMsdDriver)) {
+
+ // Post-process command if it is finished
+ if (MSDD_PostProcessCommand(pMsdDriver)) {
+
+ TRACE_INFO_WP("WaitHALT ");
+ pMsdDriver->state = MSDD_STATE_WAIT_HALT;
+ }
+ else {
+
+ pMsdDriver->state = MSDD_STATE_SEND_CSW;
+ }
+ }
+ TRACE_INFO_WP("\n\r");
+ }
+
+ break;
+
+ //----------------------
+ case MSDD_STATE_SEND_CSW:
+ //----------------------
+ // Set signature
+ csw->dCSWSignature = MSD_CSW_SIGNATURE;
+
+ // Start the CSW write operation
+ status = MSDD_Write(csw,
+ MSD_CSW_SIZE,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check operation result code
+ if (status == USBD_STATUS_SUCCESS) {
+
+ TRACE_INFO_WP("SendCSW ");
+
+ // Wait for end of transfer
+ pMsdDriver->state = MSDD_STATE_WAIT_CSW;
+ }
+ break;
+
+ //----------------------
+ case MSDD_STATE_WAIT_CSW:
+ //----------------------
+ // Check transfer semaphore
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and terminate transfer
+ transfer->semaphore--;
+
+ // Check if transfer was successful
+ if (transfer->status == USBD_STATUS_RESET) {
+
+ TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
+ }
+ else if (transfer->status == USBD_STATUS_ABORTED) {
+
+ TRACE_WARNING(
+ "MSDD_StateMachine: Failed to send CSW\n\r");
+ }
+ else {
+
+ TRACE_INFO_WP("ok");
+ }
+
+ // Read new CBW
+ pMsdDriver->state = MSDD_STATE_READ_CBW;
+ }
+ break;
+
+ //----------------------
+ case MSDD_STATE_WAIT_HALT:
+ //----------------------
+ if (MSDD_IsHalted() == 0) {
+
+ pMsdDriver->state = MSDD_STATE_SEND_CSW;
+ }
+ break;
+ }
+}
diff --git a/usb/device/massstorage/MSDDStateMachine.h b/usb/device/massstorage/MSDDStateMachine.h new file mode 100644 index 0000000..77e5cc8 --- /dev/null +++ b/usb/device/massstorage/MSDDStateMachine.h @@ -0,0 +1,264 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//-----------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Definitions, structs, functions required by a Mass Storage device driver
+/// state machine..
+///
+/// !Usage
+///
+/// - For a USB device:
+/// -# MSDD_Write, MSDD_Read, MSDD_Halt should be defined for
+/// usage in the state machine procedure.
+///
+/// -# MSDD_StateMachine is invoked to run the MSD state machine.
+///
+//-----------------------------------------------------------------------------
+
+#ifndef MSDDSTATEMACHINE_H
+#define MSDDSTATEMACHINE_H
+
+//-----------------------------------------------------------------------------
+// Headers
+//-----------------------------------------------------------------------------
+
+#include "MSD.h"
+#include "MSDLun.h"
+#include <utility/trace.h>
+
+//-----------------------------------------------------------------------------
+// Definitions
+//-----------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Driver Possible states"
+/// ...
+///
+/// !States
+/// - MSDD_STATE_READ_CBW
+/// - MSDD_STATE_WAIT_CBW
+/// - MSDD_STATE_PROCESS_CBW
+/// - MSDD_STATE_WAIT_HALT
+/// - MSDD_STATE_SEND_CSW
+/// - MSDD_STATE_WAIT_CSW
+/// - MSDD_STATE_WAIT_RESET
+
+//! \brief Driver is expecting a command block wrapper
+#define MSDD_STATE_READ_CBW (1 << 0)
+
+//! \brief Driver is waiting for the transfer to finish
+#define MSDD_STATE_WAIT_CBW (1 << 1)
+
+//! \brief Driver is processing the received command
+#define MSDD_STATE_PROCESS_CBW (1 << 2)
+
+//! \brief Driver is halted because pipe halt or wait reset
+#define MSDD_STATE_WAIT_HALT (1 << 3)
+
+//! \brief Driver is starting the transmission of a command status wrapper
+#define MSDD_STATE_SEND_CSW (1 << 4)
+
+//! \brief Driver is waiting for the CSW transmission to finish
+#define MSDD_STATE_WAIT_CSW (1 << 5)
+
+//! \brief Driver is waiting for the MassStorageReset
+#define MSDD_STATE_WAIT_RESET (1 << 6)
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Driver Result Codes"
+/// This page lists result codes for MSD functions.
+///
+/// !Codes
+/// - MSDD_STATUS_SUCCESS
+/// - MSDD_STATUS_ERROR
+/// - MSDD_STATUS_INCOMPLETE
+/// - MSDD_STATUS_PARAMETER
+/// - MSDD_STATUS_RW
+
+//! \brief Method was successful
+#define MSDD_STATUS_SUCCESS 0x00
+
+//! \brief There was an error when trying to perform a method
+#define MSDD_STATUS_ERROR 0x01
+
+//! \brief No error was encountered but the application should call the
+//! method again to continue the operation
+#define MSDD_STATUS_INCOMPLETE 0x02
+
+//! \brief A wrong parameter has been passed to the method
+#define MSDD_STATUS_PARAMETER 0x03
+
+//! \brief An error when reading/writing disk (protected or not present)
+#define MSDD_STATUS_RW 0x04
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Driver Action Cases"
+/// This page lists actions to perform during the post-processing phase of a
+/// command.
+///
+/// !Actions
+/// - MSDD_CASE_PHASE_ERROR
+/// - MSDD_CASE_STALL_IN
+/// - MSDD_CASE_STALL_OUT
+
+//! \brief Indicates that the CSW should report a phase error
+#define MSDD_CASE_PHASE_ERROR (1 << 0)
+
+//! \brief The driver should halt the Bulk IN pipe after the transfer
+#define MSDD_CASE_STALL_IN (1 << 1)
+
+//! \brief The driver should halt the Bulk OUT pipe after the transfer
+#define MSDD_CASE_STALL_OUT (1 << 2)
+
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Driver Xfr Directions"
+/// This page lists possible direction values for a data transfer
+///
+/// !Directions
+/// - MSDD_DEVICE_TO_HOST
+/// - MSDD_HOST_TO_DEVICE
+/// - MSDD_NO_TRANSFER
+
+#define MSDD_DEVICE_TO_HOST 0
+#define MSDD_HOST_TO_DEVICE 1
+#define MSDD_NO_TRANSFER 2
+//------------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//! \brief Structure for holding the result of a USB transfer
+//! \see MSDDriver_Callback
+//------------------------------------------------------------------------------
+typedef struct {
+
+ volatile unsigned int transferred; /// Number of bytes transferred
+ volatile unsigned int remaining; /// Number of bytes not transferred
+ volatile unsigned short semaphore; /// Semaphore to indicate transfer completion
+ volatile unsigned short status; /// Operation result code
+
+} MSDTransfer;
+
+//------------------------------------------------------------------------------
+//! \brief Status of an executing command
+//! \see MSDCbw
+//! \see MSDCsw
+//! \see MSDTransfer
+//------------------------------------------------------------------------------
+typedef struct {
+
+ MSDTransfer transfer; /// Current transfer status (USB)
+ MSDTransfer disktransfer;/// Current transfer status (Disk)
+ unsigned int length; /// Remaining length of command
+ MSCbw cbw; /// Received CBW (31 bytes)
+ unsigned char state; /// Current command state
+ MSCsw csw; /// CSW to send (13 bytes)
+ unsigned char postprocess; /// Actions to perform when command is complete
+
+} MSDCommandState;
+
+//------------------------------------------------------------------------------
+/// \brief MSD driver state variables
+/// \see MSDCommandState
+/// \see MSDLun
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// LUN list for the %device.
+ MSDLun *luns;
+ /// State of the currently executing command
+ MSDCommandState commandState;
+ /// Maximum LUN index
+ unsigned char maxLun;
+ /// Current state of the driver
+ unsigned char state;
+ /// Indicates if the driver is waiting for a reset recovery
+ unsigned char waitResetRecovery;
+
+} MSDDriver;
+
+//-----------------------------------------------------------------------------
+// Inline functions
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// This function is to be used as a callback for USB or LUN transfers.
+/// \param transfer Pointer to the transfer structure to update
+/// \param status Operation result code
+/// \param transferred Number of bytes transferred by the command
+/// \param remaining Number of bytes not transferred
+//-----------------------------------------------------------------------------
+static inline void MSDDriver_Callback(MSDTransfer *transfer,
+ unsigned char status,
+ unsigned int transferred,
+ unsigned int remaining)
+{
+ TRACE_DEBUG("Cbk ");
+ transfer->semaphore++;
+ transfer->status = status;
+ transfer->transferred = transferred;
+ transfer->remaining = remaining;
+}
+
+//-----------------------------------------------------------------------------
+// Driver functions
+//-----------------------------------------------------------------------------
+//- MSD General support function
+extern char MSDD_Read(
+ void* pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void* pArgument);
+
+extern char MSDD_Write(
+ void* pData,
+ unsigned int dLength,
+ TransferCallback fCallback,
+ void* pArgument);
+
+extern void MSDD_Halt(unsigned int stallCase);
+
+extern unsigned int MSDD_IsHalted(void);
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+extern void MSDD_StateMachine(MSDDriver * pMsdDriver);
+
+#endif // #define MSDDSTATEMACHINE_H
+
diff --git a/usb/device/massstorage/MSDDriver.c b/usb/device/massstorage/MSDDriver.c new file mode 100644 index 0000000..fbaebb0 --- /dev/null +++ b/usb/device/massstorage/MSDDriver.c @@ -0,0 +1,343 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+
+#include <memories/Media.h>
+#include "MSDDriver.h"
+#include "MSDDriverDescriptors.h"
+#include "SBCMethods.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDCallbacks.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/device/core/USBDDriverCallbacks.h>
+
+//-----------------------------------------------------------------------------
+// Internal variables
+//-----------------------------------------------------------------------------
+
+/// Mass storage device driver instance.
+static MSDDriver msdDriver;
+
+/// Standard device driver instance.
+static USBDDriver usbdDriver;
+
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Resets the state of the MSD driver
+//-----------------------------------------------------------------------------
+static void MSDDriver_Reset(void)
+{
+ TRACE_INFO_WP("MSDReset ");
+
+ msdDriver.state = MSDD_STATE_READ_CBW;
+ msdDriver.waitResetRecovery = 0;
+ msdDriver.commandState.state = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Callback re-implementation
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Invoked when a new SETUP request is received from the host. Forwards the
+/// request to the Mass Storage device driver handler function.
+/// \param request Pointer to a USBGenericRequest instance.
+//-----------------------------------------------------------------------------
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ MSDDriver_RequestHandler(request);
+}
+
+//-----------------------------------------------------------------------------
+/// Invoked when the configuration of the device changes. Resets the mass
+/// storage driver.
+/// \param cfgnum New configuration number.
+//-----------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ MSDDriver_Reset();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Driver functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Reads from host through MSD defined bulk OUT pipe. Act as USBD_Read but by
+/// a fixed OUT endpoint.
+/// \param data Pointer to the data buffer that contains data read from host.
+/// \param size The number of bytes should be read (buffer size).
+/// \param callback Pointer to the function invoked on end of reading.
+/// \param argument Pointer to additional argument data struct.
+//-----------------------------------------------------------------------------
+char MSDD_Read(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+
+{
+ return USBD_Read(MSDDriverDescriptors_BULKOUT,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// Writes to host through MSD defined bulk IN pipe. Act as USBD_Write but by
+/// a fixed IN endpoint.
+/// \param data Pointer to the data that writes to the host.
+/// \param size The number of bytes should be write.
+/// \param callback Pointer to the function invoked on end of writing.
+/// \param argument Pointer to additional argument data struct.
+//-----------------------------------------------------------------------------
+char MSDD_Write(void *data,
+ unsigned int size,
+ TransferCallback callback,
+ void *argument)
+{
+ return USBD_Write(MSDDriverDescriptors_BULKIN,
+ data,
+ size,
+ callback,
+ argument);
+}
+
+//-----------------------------------------------------------------------------
+/// HALT Specified USB pipe.
+/// \param stallCASE Case of the stall condition (Bulk In/Out/Both).
+//-----------------------------------------------------------------------------
+void MSDD_Halt(unsigned int stallCASE)
+{
+ if (stallCASE & MSDD_CASE_STALL_OUT) {
+
+ USBD_Halt(MSDDriverDescriptors_BULKOUT);
+ }
+
+ if (stallCASE & MSDD_CASE_STALL_IN) {
+
+ USBD_Halt(MSDDriverDescriptors_BULKIN);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// Return halted status
+/// \return stallCASE bitmap, case of the stall condition
+/// (bit: MSDD_CASE_STALL_OUT or MSDD_CASE_STALL_IN)
+//-----------------------------------------------------------------------------
+unsigned int MSDD_IsHalted(void)
+{
+ unsigned int stallCASE = 0;
+ if (USBD_IsHalted(MSDDriverDescriptors_BULKOUT)) {
+
+ stallCASE |= MSDD_CASE_STALL_OUT;
+ }
+ if (USBD_IsHalted(MSDDriverDescriptors_BULKIN)) {
+
+ stallCASE |= MSDD_CASE_STALL_IN;
+ }
+ return stallCASE;
+}
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/// Initializes the MSD driver and the associated USB driver.
+/// \param luns Pointer to a list of LUNs
+/// \param numLuns Number of LUN in list
+/// \see MSDLun
+//-----------------------------------------------------------------------------
+void MSDDriver_Initialize(MSDLun *defLuns, unsigned char numLuns)
+{
+
+ TRACE_INFO("MSD init\n\r");
+
+ // Command state initialization
+ msdDriver.commandState.state = 0;
+ msdDriver.commandState.postprocess = 0;
+ msdDriver.commandState.length = 0;
+ msdDriver.commandState.transfer.semaphore = 0;
+
+ // LUNs
+ msdDriver.luns = defLuns;
+ msdDriver.maxLun = (unsigned char) (numLuns - 1);
+
+ // Reset BOT driver
+ MSDDriver_Reset();
+
+ // Init the USB driver
+ USBDDriver_Initialize(&usbdDriver, &msdDriverDescriptors, 0);
+ USBD_Init();
+}
+
+//-----------------------------------------------------------------------------
+/// Handler for incoming SETUP requests on default Control endpoint 0.
+///
+/// Standard requests are forwarded to the USBDDriver_RequestHandler
+/// method.
+/// \param request Pointer to a USBGenericRequest instance
+//-----------------------------------------------------------------------------
+void MSDDriver_RequestHandler(const USBGenericRequest *request)
+{
+ TRACE_INFO_WP("NewReq ");
+
+ // Handle requests
+ switch (USBGenericRequest_GetRequest(request)) {
+ //---------------------
+ case USBGenericRequest_CLEARFEATURE:
+ //---------------------
+ TRACE_INFO_WP("ClrFeat ");
+
+ switch (USBFeatureRequest_GetFeatureSelector(request)) {
+
+ //---------------------
+ case USBFeatureRequest_ENDPOINTHALT:
+ //---------------------
+ TRACE_INFO_WP("Hlt ");
+
+ // Do not clear the endpoint halt status if the device is waiting
+ // for a reset recovery sequence
+ if (!msdDriver.waitResetRecovery) {
+
+ // Forward the request to the standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+ }
+ else {
+
+ TRACE_INFO_WP("No ");
+ }
+
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ //------
+ default:
+ //------
+ // Forward the request to the standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+ }
+ break;
+
+ //-------------------
+ case MSD_GET_MAX_LUN:
+ //-------------------
+ TRACE_INFO_WP("gMaxLun ");
+
+ // Check request parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == 0)
+ && (request->wLength == 1)) {
+
+ USBD_Write(0, &(msdDriver.maxLun), 1, 0, 0);
+
+ }
+ else {
+
+ TRACE_WARNING(
+ "MSDDriver_RequestHandler: GetMaxLUN(%d,%d,%d)\n\r",
+ request->wValue, request->wIndex, request->wLength);
+ USBD_Stall(0);
+ }
+ break;
+
+ //-----------------------
+ case MSD_BULK_ONLY_RESET:
+ //-----------------------
+ TRACE_INFO_WP("Rst ");
+
+ // Check parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == 0)
+ && (request->wLength == 0)) {
+
+ // Reset the MSD driver
+ MSDDriver_Reset();
+ USBD_Write(0, 0, 0, 0, 0);
+ }
+ else {
+
+ TRACE_WARNING(
+ "MSDDriver_RequestHandler: Reset(%d,%d,%d)\n\r",
+ request->wValue, request->wIndex, request->wLength);
+ USBD_Stall(0);
+ }
+ break;
+
+ //------
+ default:
+ //------
+ // Forward request to standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+/// State machine for the MSD driver
+//-----------------------------------------------------------------------------
+void MSDDriver_StateMachine(void)
+{
+ if (USBD_GetState() < USBD_STATE_CONFIGURED){}
+ else MSDD_StateMachine(&msdDriver);
+
+}
+
+//-----------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//-----------------------------------------------------------------------------
+void MSDDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
+
+ USBD_RemoteWakeUp();
+ }
+ // Remote wake-up NOT enabled
+ else {
+
+ TRACE_WARNING(
+ "MSD..RemoteWakeUp: Host has not enabled remote wake-up\n\r");
+ }
+}
+
diff --git a/usb/device/massstorage/MSDDriver.h b/usb/device/massstorage/MSDDriver.h new file mode 100644 index 0000000..0a8738a --- /dev/null +++ b/usb/device/massstorage/MSDDriver.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Mass storage %device driver implementation.
+///
+/// !Usage
+///
+/// -# Enable and setup USB related pins (see pio & board.h).
+/// -# Configure the memory interfaces used for Mass Storage LUNs
+/// (see memories, MSDLun.h).
+/// -# Configure the USB MSD %driver using MSDDriver_Initialize.
+/// -# Invoke MSDDriver_StateMachine in main loop to handle all Mass Storage
+/// operations.
+//------------------------------------------------------------------------------
+
+#ifndef MSDDRIVER_H
+#define MSDDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "MSD.h"
+#include "MSDLun.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+// Global functions
+//------------------------------------------------------------------------------
+
+extern void MSDDriver_Initialize(MSDLun *luns, unsigned char numLuns);
+
+extern void MSDDriver_RequestHandler(const USBGenericRequest *request);
+
+extern void MSDDriver_StateMachine(void);
+
+extern void MSDDriver_RemoteWakeUp(void);
+
+extern void MSDDriver_DataCallback(unsigned char isRead,
+ unsigned int dataLength,
+ unsigned int nullCnt,
+ unsigned int fullCnt);
+
+#endif // #ifndef MSDDRIVER_H
+
diff --git a/usb/device/massstorage/MSDDriverArch.png b/usb/device/massstorage/MSDDriverArch.png Binary files differnew file mode 100644 index 0000000..4063440 --- /dev/null +++ b/usb/device/massstorage/MSDDriverArch.png diff --git a/usb/device/massstorage/MSDDriverClasses.png b/usb/device/massstorage/MSDDriverClasses.png Binary files differnew file mode 100644 index 0000000..3fd68d1 --- /dev/null +++ b/usb/device/massstorage/MSDDriverClasses.png diff --git a/usb/device/massstorage/MSDDriverDescriptors.c b/usb/device/massstorage/MSDDriverDescriptors.c new file mode 100644 index 0000000..1d8a073 --- /dev/null +++ b/usb/device/massstorage/MSDDriverDescriptors.c @@ -0,0 +1,475 @@ +/* ----------------------------------------------------------------------------
+ * 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 "MSDDriverDescriptors.h"
+#include <board.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/massstorage/MSDeviceDescriptor.h>
+#include <usb/common/massstorage/MSInterfaceDescriptor.h>
+
+//------------------------------------------------------------------------------
+// Internal definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Device Descriptor IDs"
+/// ...
+/// !IDs
+/// - MSDDriverDescriptors_VENDORID
+/// - MSDDriverDescriptors_PRODUCTID
+/// - MSDDriverDescriptors_RELEASE
+
+/// Vendor ID for the Mass Storage device driver.
+#define MSDDriverDescriptors_VENDORID 0x03EB
+/// Product ID for the Mass Storage device driver.
+#define MSDDriverDescriptors_PRODUCTID 0x6129
+/// Device release number for the Mass Storage device driver.
+#define MSDDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+/// Returns the minimum between two values.
+#define MIN(a, b) ((a < b) ? a : b)
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// List of configuration descriptors used by a Mass Storage device driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard configuration descriptor.
+ USBConfigurationDescriptor configuration;
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ USBOtgDescriptor otgDescriptor;
+#endif
+ /// Mass storage interface descriptor.
+ USBInterfaceDescriptor interface;
+ /// Bulk-out endpoint descriptor.
+ USBEndpointDescriptor bulkOut;
+ /// Bulk-in endpoint descriptor.
+ USBEndpointDescriptor bulkIn;
+
+} __attribute__ ((packed)) MSDConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+// Local variables
+//------------------------------------------------------------------------------
+
+/// Mass storage driver device descriptor.
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ MSDeviceDescriptor_CLASS,
+ MSDeviceDescriptor_SUBCLASS,
+ MSDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ MSDDriverDescriptors_VENDORID,
+ MSDDriverDescriptors_PRODUCTID,
+ MSDDriverDescriptors_RELEASE,
+ 1, // Manufacturer string descriptor index.
+ 2, // Product string descriptor index.
+ 3, // Serial number string descriptor index.
+ 1 // Device has one possible configuration.
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Device qualifier descriptor.
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ USBDeviceDescriptor_USB2_00,
+ MSDeviceDescriptor_CLASS,
+ MSDeviceDescriptor_SUBCLASS,
+ MSDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // Device has one possible configuration.
+ 0x00
+};
+#endif
+
+/// Full-speed configuration descriptor.
+static const MSDConfigurationDescriptors configurationDescriptorsFS = {
+
+ // Standard configuration descriptor.
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(MSDConfigurationDescriptors),
+ 1, // Configuration has one interface.
+ 1, // This is configuration #1.
+ 0, // No string descriptor for configuration.
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0.
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed Bulk endpoints.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // Must be 0 for full-speed Bulk endpoints.
+ }
+};
+
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Full-speed other speed configuration descriptor.
+static const MSDConfigurationDescriptors otherSpeedDescriptorsFS = {
+
+ // Standard configuration descriptor.
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(MSDConfigurationDescriptors),
+ 1, // Configuration has one interface.
+ 1, // This is configuration #1.
+ 0, // No string descriptor for configuration.
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0.
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ }
+};
+
+/// High-speed configuration descriptor.
+static const MSDConfigurationDescriptors configurationDescriptorsHS = {
+
+ // Standard configuration descriptor.
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(MSDConfigurationDescriptors),
+ 1, // Configuration has one interface.
+ 1, // This is configuration #1.
+ 0, // No string descriptor for configuration.
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0.
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_HS),
+ 0 // No string descriptor for endpoint.
+ }
+};
+
+/// High-speed other speed configuration descriptor.
+static const MSDConfigurationDescriptors otherSpeedDescriptorsHS = {
+
+ // Standard configuration descriptor.
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(MSDConfigurationDescriptors),
+ 1, // Configuration has one interface.
+ 1, // This is configuration #1.
+ 0, // No string descriptor for configuration.
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+#if defined(CHIP_USB_OTGHS)
+ // OTG descriptor
+ {
+ sizeof(USBOtgDescriptor),
+ USBGenericDescriptor_OTG,
+ USBOTGDescriptor_HNP_SRP
+ },
+#endif
+ // Mass Storage interface descriptor.
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0.
+ 0, // This is alternate setting #0.
+ 2, // Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS,
+ MSInterfaceDescriptor_SCSI,
+ MSInterfaceDescriptor_BULKONLY,
+ 0 // No string descriptor for interface.
+ },
+ // Bulk-OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ },
+ // Bulk-IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_BULK,
+ MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS),
+ 0 // No string descriptor for endpoint.
+ }
+};
+#endif
+
+/// Language ID string descriptor.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer string descriptor.
+static 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 string descriptor.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(14),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('S'),
+ USBStringDescriptor_UNICODE('D')
+};
+
+/// Serial number string descriptor. The serial number must be at least 12
+/// characters long and made up of only letters & numbers to be compliant with
+/// the MSD specification.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(12),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('B')
+};
+
+/// List of all string descriptors used.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor
+};
+
+//------------------------------------------------------------------------------
+// Global variables
+//------------------------------------------------------------------------------
+
+/// List of the standard descriptors used by the Mass Storage driver.
+const USBDDriverDescriptors msdDriverDescriptors = {
+
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptorsFS,
+#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptorsFS,
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptorsHS,
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptorsHS,
+#else
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration
+ 0, // No high-speed device descriptor
+ 0, // No high-speed configuration descriptor
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+#endif
+ stringDescriptors,
+ 4 // Four string descriptors in array
+};
+
diff --git a/usb/device/massstorage/MSDDriverDescriptors.h b/usb/device/massstorage/MSDDriverDescriptors.h new file mode 100644 index 0000000..be046a9 --- /dev/null +++ b/usb/device/massstorage/MSDDriverDescriptors.h @@ -0,0 +1,83 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Definitions of the descriptors required by a Mass Storage device driver.
+///
+/// !Usage
+///
+/// - For a USB %device:
+/// -# When initializing a USBDDriver instance, use msdDriverDescriptors as
+/// the list of standard descriptors.
+//------------------------------------------------------------------------------
+
+#ifndef MSDDRIVERDESCRIPTORS_H
+#define MSDDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD endpoint addresses"
+/// This page lists the addresses used by the Mass Storage driver %endpoints.
+///
+/// !Addresses
+///
+/// - MSDDriverDescriptors_BULKOUT
+/// - MSDDriverDescriptors_BULKIN
+
+/// Address of the Mass Storage bulk-out endpoint.
+#define MSDDriverDescriptors_BULKOUT 1
+
+/// Address of the Mass Storage bulk-in endpoint.
+#if defined(at91sam9m10)
+ #define MSDDriverDescriptors_BULKIN 6
+#else
+ #define MSDDriverDescriptors_BULKIN 2
+#endif
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+extern const USBDDriverDescriptors msdDriverDescriptors;
+
+#endif //#ifndef MSDDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/massstorage/MSDDriverStates.png b/usb/device/massstorage/MSDDriverStates.png Binary files differnew file mode 100644 index 0000000..a0c55c8 --- /dev/null +++ b/usb/device/massstorage/MSDDriverStates.png diff --git a/usb/device/massstorage/MSDIOFifo.c b/usb/device/massstorage/MSDIOFifo.c new file mode 100644 index 0000000..03f09a6 --- /dev/null +++ b/usb/device/massstorage/MSDIOFifo.c @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------------
+ * 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 "MSDIOFifo.h"
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//! \brief Initializes a MSDIOFifo instance.
+//! \param pFifo Pointer to the MSDIOFifo instance to initialize
+//! \param pBuffer Pointer to a buffer used for read/write operation and
+//! which must be blockSize bytes aligned.
+//! \param bufferSize Total size of the buffer in bytes
+//------------------------------------------------------------------------------
+void MSDIOFifo_Init(MSDIOFifo *pFifo,
+ void * pBuffer, unsigned short bufferSize)
+{
+ pFifo->pBuffer = pBuffer;
+ pFifo->bufferSize = bufferSize;
+
+ pFifo->inputNdx = 0;
+ pFifo->outputNdx = 0;
+ pFifo->inputTotal = 0;
+ pFifo->outputTotal = 0;
+
+ pFifo->inputState = MSDIO_IDLE;
+ pFifo->outputState = MSDIO_IDLE;
+
+ pFifo->fullCnt = 0;
+ pFifo->nullCnt = 0;
+}
diff --git a/usb/device/massstorage/MSDIOFifo.h b/usb/device/massstorage/MSDIOFifo.h new file mode 100644 index 0000000..efe204d --- /dev/null +++ b/usb/device/massstorage/MSDIOFifo.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef _MSDIOFIFO_H
+#define _MSDIOFIFO_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Idle state, do nothing
+#define MSDIO_IDLE 0
+/// Start, to start IO operation
+#define MSDIO_START 1
+/// Wait, waiting for IO operation done
+#define MSDIO_WAIT 2
+/// Next, to check if the next block can be performed
+#define MSDIO_NEXT 3
+/// Pause, to pause the process for buffer full or null
+#define MSDIO_PAUSE 4
+/// Abort, to abort the process
+#define MSDIO_ABORT 5
+/// Done, finish without error
+#define MSDIO_DONE 6
+/// Error, any error happens
+#define MSDIO_ERROR 7
+
+/// FIFO offset before USB transmit start
+//#define MSDIO_FIFO_OFFSET (4*512)
+
+/// FIFO trunk size (in each transfer, large amount of data)
+#define MSDIO_READ10_CHUNK_SIZE (4*512)
+#define MSDIO_WRITE10_CHUNK_SIZE (4*512)
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+/// FIFO buffer for READ/WRITE (disk) operation of a mass storage device
+typedef struct _MSDIOFifo {
+
+ /// Pointer to the ring buffer allocated for read/write
+ unsigned char * pBuffer;
+ /// The size of the buffer allocated
+ unsigned int bufferSize;
+#ifdef MSDIO_FIFO_OFFSET
+ /// The offset to start USB transfer (READ10)
+ unsigned int bufferOffset;
+#endif
+ /// The index of input data (loaded to fifo buffer)
+ unsigned int inputNdx;
+ /// The total size of the loaded data
+ unsigned int inputTotal;
+ /// The index of output data (sent from the fifo buffer)
+ unsigned int outputNdx;
+ /// The total size of the output data
+ unsigned int outputTotal;
+
+ /// The total size of the data
+ unsigned int dataTotal;
+ /// The size of the block in bytes
+ unsigned short blockSize;
+#if defined(MSDIO_READ10_CHUNK_SIZE) || defined(MSDIO_WRITE10_CHUNK_SIZE)
+ /// The size of one chunk
+ /// (1 block, or several blocks for large amount data R/W)
+ unsigned int chunkSize;
+#endif
+ /// State of input & output
+ unsigned char inputState;
+ unsigned char outputState;
+
+ //- Statistics
+ /// Times when fifo has no data to send
+ unsigned short nullCnt;
+ /// Times when fifo can not load more input data
+ unsigned short fullCnt;
+} MSDIOFifo, *PMSDIOFifo;
+
+//------------------------------------------------------------------------------
+// MACROS
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Increase the index, by defined block size, in the ring buffer
+/// \param ndx The index to be increased
+/// \param sectSize The defined block size
+/// \param bufSize The ring buffer size
+//------------------------------------------------------------------------------
+#define MSDIOFifo_IncNdx(ndx, sectSize, bufSize) \
+ if ((ndx) >= (bufSize) - (sectSize)) (ndx) = 0; \
+ else (ndx) += (sectSize)
+
+
+//------------------------------------------------------------------------------
+// Exported Functions
+//------------------------------------------------------------------------------
+
+
+extern void MSDIOFifo_Init(MSDIOFifo *pFifo,
+ void * pBuffer, unsigned short bufferSize);
+
+#endif // _MSDIOFIFO_H
+
diff --git a/usb/device/massstorage/MSDLun.c b/usb/device/massstorage/MSDLun.c new file mode 100644 index 0000000..42999d7 --- /dev/null +++ b/usb/device/massstorage/MSDLun.c @@ -0,0 +1,366 @@ +/* ----------------------------------------------------------------------------
+ * 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 "MSDLun.h"
+#include <utility/trace.h>
+#include <usb/device/core/USBD.h>
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+/// Default LUN block size in bytes
+#define DEFAULT_LUN_BLOCK_SIZE 512
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Inquiry data to return to the host for the Lun.
+static SBCInquiryData inquiryData = {
+
+ SBC_DIRECT_ACCESS_BLOCK_DEVICE, // Direct-access block device
+ SBC_PERIPHERAL_DEVICE_CONNECTED,// Peripheral device is connected
+ 0x00, // Reserved bits
+ 0x01, // Media is removable
+ SBC_SPC_VERSION_4, // SPC-4 supported
+ 0x2, // Response data format, must be 0x2
+ 0, // Hierarchical addressing not supported
+ 0, // ACA not supported
+ 0x0, // Obsolete bits
+ sizeof(SBCInquiryData) - 5, // Additional length
+ 0, // No embedded SCC
+ 0, // No access control coordinator
+ SBC_TPGS_NONE, // No target port support group
+ 0, // Third-party copy not supported
+ 0x0, // Reserved bits
+ 0, // Protection information not supported
+ 0x0, // Obsolete bit
+ 0, // No embedded enclosure service component
+ 0x0, // ???
+ 0, // Device is not multi-port
+ 0x0, // Obsolete bits
+ 0x0, // Unused feature
+ 0x0, // Unused features
+ 0, // Task management model not supported
+ 0x0, // ???
+ {'A','T','M','E','L',' ',' ',' '},
+ {'M','a','s','s',' ',
+ 'S','t','o','r','a','g','e',' ',
+ 'M','S','D'},
+ {'0','.','0','1'},
+ {'M','a','s','s',' ',
+ 'S','t','o','r','a','g','e',' ',
+ 'E','x','a','m','p','l','e'},
+ 0x00, // Unused features
+ 0x00, // Reserved bits
+ {SBC_VERSION_DESCRIPTOR_SBC_3}, // SBC-3 compliant device
+ {0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0} // Reserved
+};
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//! \brief Initializes a LUN instance. Must be invoked at least once even no
+//! Media is linked.
+//! \param lun Pointer to the MSDLun instance to initialize
+//! \param media Media on which the LUN is constructed, set to 0 to
+//! disconnect the Media or initialize an ejected LUN.
+//! \param ioBuffer Pointer to a buffer used for read/write operation and
+//! which must be blockSize bytes long.
+//! \param ioBufferSize Size of the allocated IO buffer.
+//! \param baseAddress Base address of the LUN in number of media blocks
+//! \param size Total size of the LUN in number of media blocks
+//! \param blockSize One block of the LUN in number of media blocks
+//! \param protected The LUN area is forced to readonly even the media
+//! is writable
+//! \param dataMonitor Pointer to a Monitor Function to analyze the flow of
+//! this LUN.
+//------------------------------------------------------------------------------
+void LUN_Init(MSDLun *lun,
+ Media *media,
+ unsigned char *ioBuffer,
+ unsigned int ioBufferSize,
+ unsigned int baseAddress,
+ unsigned int size,
+ unsigned short blockSize,
+ unsigned char protected,
+ void (*dataMonitor)(unsigned char flowDirection,
+ unsigned int dataLength,
+ unsigned int fifoNullCount,
+ unsigned int fifoFullCount))
+{
+ unsigned int logicalBlockAddress;
+ TRACE_INFO("LUN init\n\r");
+
+ // Initialize inquiry data
+ lun->inquiryData = &inquiryData;
+
+ // Initialize request sense data
+ lun->requestSenseData.bResponseCode = SBC_SENSE_DATA_FIXED_CURRENT;
+ lun->requestSenseData.isValid = 1;
+ lun->requestSenseData.bObsolete1 = 0;
+ lun->requestSenseData.bSenseKey = SBC_SENSE_KEY_NO_SENSE;
+ lun->requestSenseData.bReserved1 = 0;
+ lun->requestSenseData.isILI = 0;
+ lun->requestSenseData.isEOM = 0;
+ lun->requestSenseData.isFilemark = 0;
+ lun->requestSenseData.pInformation[0] = 0;
+ lun->requestSenseData.pInformation[1] = 0;
+ lun->requestSenseData.pInformation[2] = 0;
+ lun->requestSenseData.pInformation[3] = 0;
+ lun->requestSenseData.bAdditionalSenseLength
+ = sizeof(SBCRequestSenseData) - 8;
+ lun->requestSenseData.bAdditionalSenseCode = 0;
+ lun->requestSenseData.bAdditionalSenseCodeQualifier = 0;
+ lun->requestSenseData.bFieldReplaceableUnitCode = 0;
+ lun->requestSenseData.bSenseKeySpecific = 0;
+ lun->requestSenseData.pSenseKeySpecific[0] = 0;
+ lun->requestSenseData.pSenseKeySpecific[0] = 0;
+ lun->requestSenseData.isSKSV = 0;
+
+ STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockAddress);
+ STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockLength);
+
+ // Initialize LUN
+ lun->media = media;
+ if (media == 0) {
+ lun->status = LUN_NOT_PRESENT;
+ return;
+ }
+
+ lun->baseAddress = baseAddress;
+
+ // Customized block size
+ if (blockSize) {
+ lun->blockSize = blockSize;
+ }
+ else {
+ if (media->blockSize < DEFAULT_LUN_BLOCK_SIZE)
+ lun->blockSize = DEFAULT_LUN_BLOCK_SIZE / media->blockSize;
+ else
+ lun->blockSize = 1;
+ }
+
+ if (size) {
+ lun->size = size;
+ }
+ else {
+ lun->size = media->size;
+ //if (blockSize)
+ // lun->size = media->size / blockSize;
+ //else {
+ // if (media->blockSize < DEFAULT_LUN_BLOCK_SIZE)
+ // lun->size = media->size / lun->blockSize;
+ // else
+ // lun->size = media->size;
+ //}
+ }
+
+ TRACE_INFO("LUN: blkSize %d, size %d\n\r", (int)lun->blockSize, (int)lun->size);
+ if (protected) lun->protected = 1;
+ else lun->protected = media->protected;
+
+ lun->ioFifo.pBuffer = ioBuffer;
+ lun->ioFifo.bufferSize = ioBufferSize;
+
+ lun->dataMonitor = dataMonitor;
+
+ // Initialize read capacity data
+ logicalBlockAddress = lun->size / lun->blockSize - 1;
+ STORE_DWORDB(logicalBlockAddress,
+ lun->readCapacityData.pLogicalBlockAddress);
+ STORE_DWORDB(lun->blockSize * media->blockSize,
+ lun->readCapacityData.pLogicalBlockLength);
+
+ // Indicate media change
+ lun->status = LUN_CHANGED;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Eject the media from a LUN
+//! \param lun Pointer to the MSDLun instance to initialize
+//! \return Operation result code
+//------------------------------------------------------------------------------
+unsigned char LUN_Eject(MSDLun *lun)
+{
+ if (lun->media) {
+
+ // Avoid any LUN R/W in progress
+ if (lun->media->state == MED_STATE_BUSY) {
+
+ return USBD_STATUS_LOCKED;
+ }
+
+ // Remove the link of the media
+ lun->media = 0;
+ }
+ // LUN is removed
+ lun->status = LUN_NOT_PRESENT;
+
+ return USBD_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Writes data on the a LUN starting at the specified block address.
+//! \param lun Pointer to a MSDLun instance
+//! \param blockAddress First block address to write
+//! \param data Pointer to the data to write
+//! \param length Number of blocks to write
+//! \param callback Optional callback to invoke when the write finishes
+//! \return Operation result code
+//------------------------------------------------------------------------------
+unsigned char LUN_Write(MSDLun *lun,
+ unsigned int blockAddress,
+ void *data,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument)
+{
+ unsigned int medBlk, medLen;
+ unsigned char status;
+
+ TRACE_INFO_WP("LUNWrite(%u) ", blockAddress);
+
+ // Check that the data is not too big
+ if ((length + blockAddress) * lun->blockSize > lun->size) {
+
+ TRACE_WARNING("LUN_Write: Data too big\n\r");
+ status = USBD_STATUS_ABORTED;
+ }
+ else if (lun->media == 0 || lun->status != LUN_READY) {
+
+ TRACE_WARNING("LUN_Write: Media not ready\n\r");
+ status = USBD_STATUS_ABORTED;
+ }
+ else if (lun->protected) {
+ TRACE_WARNING("LUN_Write: LUN is readonly\n\r");
+ status = USBD_STATUS_ABORTED;
+ }
+ else {
+
+ // Compute write start address
+ medBlk = lun->baseAddress + blockAddress * lun->blockSize;
+ medLen = length * lun->blockSize;
+
+ // Start write operation
+ status = MED_Write(lun->media,
+ medBlk,
+ data,
+ medLen,
+ (MediaCallback) callback,
+ argument);
+
+ // Check operation result code
+ if (status == MED_STATUS_SUCCESS) {
+
+ status = USBD_STATUS_SUCCESS;
+ }
+ else {
+
+ TRACE_WARNING("LUN_Write: Cannot write media\n\r");
+ status = USBD_STATUS_ABORTED;
+ }
+ }
+
+ return status;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Reads data from a LUN, starting at the specified block address.
+//! \param lun Pointer to a MSDLun instance
+//! \param blockAddress First block address to read
+//! \param data Pointer to a data buffer in which to store the data
+//! \param length Number of blocks to read
+//! \param callback Optional callback to invoke when the read finishes
+//! \return Operation result code
+//------------------------------------------------------------------------------
+unsigned char LUN_Read(MSDLun *lun,
+ unsigned int blockAddress,
+ void *data,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument)
+{
+ unsigned int medBlk, medLen;
+ unsigned char status;
+
+ // Check that the data is not too big
+ if ((length + blockAddress) * lun->blockSize > lun->size) {
+
+ TRACE_WARNING("LUN_Read: Area: (%d + %d)*%d > %d\n\r",
+ (int)length, (int)blockAddress, (int)lun->blockSize, (int)lun->size);
+ status = USBD_STATUS_ABORTED;
+ }
+ else if (lun->media == 0 || lun->status != LUN_READY) {
+
+ TRACE_WARNING("LUN_Read: Media not present\n\r");
+ status = USBD_STATUS_ABORTED;
+ }
+ else {
+
+ TRACE_INFO_WP("LUNRead(%u) ", blockAddress);
+
+ // Compute read start address
+ medBlk = lun->baseAddress + (blockAddress * lun->blockSize);
+ medLen = length * lun->blockSize;
+
+ // Start write operation
+ status = MED_Read(lun->media,
+ medBlk,
+ data,
+ medLen,
+ (MediaCallback) callback,
+ argument);
+
+ // Check result code
+ if (status == MED_STATUS_SUCCESS) {
+
+ status = USBD_STATUS_SUCCESS;
+ }
+ else {
+
+ TRACE_WARNING("LUN_Read: Cannot read media\n\r");
+ status = USBD_STATUS_ABORTED;
+ }
+ }
+
+ return status;
+}
diff --git a/usb/device/massstorage/MSDLun.h b/usb/device/massstorage/MSDLun.h new file mode 100644 index 0000000..52eea4c --- /dev/null +++ b/usb/device/massstorage/MSDLun.h @@ -0,0 +1,152 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// Logical Unit Number (LUN) used by the Mass Storage driver and the SCSI
+/// protocol. Represents a logical hard-drive.
+///
+/// !Usage
+/// -# Initialize Memory related pins (see pio & board.h).
+/// -# Initialize a Media instance for the LUN (see memories).
+/// -# Initlalize the LUN with LUN_Init, and link to the initialized Media.
+/// -# To read data from the LUN linked media, uses LUN_Read.
+/// -# To write data to the LUN linked media, uses LUN_Write.
+/// -# To unlink the media, uses LUN_Eject.
+//------------------------------------------------------------------------------
+
+#ifndef MSDLUN_H
+#define MSDLUN_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "SBC.h"
+#include <memories/Media.h>
+#include <usb/device/massstorage/MSDIOFifo.h>
+#include <usb/device/core/USBD.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// LUN RC: success
+#define LUN_STATUS_SUCCESS 0x00
+/// LUN RC: error
+#define LUN_STATUS_ERROR 0x02
+
+/// Media of LUN is removed
+#define LUN_NOT_PRESENT 0x00
+/// LUN is ejected by host
+#define LUN_EJECTED 0x01
+/// Media of LUN is changed
+#define LUN_CHANGED 0x10
+/// LUN Not Ready to Ready transition
+#define LUN_TRANS_READY LUN_CHANGED
+/// Media of LUN is ready
+#define LUN_READY 0x11
+
+//------------------------------------------------------------------------------
+// Structures
+//------------------------------------------------------------------------------
+
+/// LUN structure
+typedef struct {
+
+ /// Pointer to a SBCInquiryData instance.
+ SBCInquiryData *inquiryData;
+ /// Fifo for USB transfer, must be assigned.
+ MSDIOFifo ioFifo;
+ /// Pointer to Media instance for the LUN.
+ Media *media;
+ /// Pointer to a Monitor Function to analyze the flow of LUN.
+ /// \param flowDirection 1 - device to host (READ10)
+ /// 0 - host to device (WRITE10)
+ /// \param dataLength Length of data transferred in bytes.
+ /// \param fifoNullCount Times that FIFO is NULL to wait
+ /// \param fifoFullCount Times that FIFO is filled to wait
+ void (*dataMonitor)(unsigned char flowDirection,
+ unsigned int dataLength,
+ unsigned int fifoNullCount,
+ unsigned int fifoFullCount);
+ /// The start position of the media (blocks) allocated to the LUN.
+ unsigned int baseAddress;
+ /// The size of the media (blocks) allocated to the LUN.
+ unsigned int size;
+ /// Sector size of the media in number of media blocks
+ unsigned short blockSize;
+ /// The LUN can be readonly even the media is writable
+ unsigned char protected;
+ /// The LUN status (Ejected/Changed/)
+ unsigned char status;
+
+ /// Data for the RequestSense command.
+ SBCRequestSenseData requestSenseData;
+ /// Data for the ReadCapacity command.
+ SBCReadCapacity10Data readCapacityData;
+
+} MSDLun;
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+extern void LUN_Init(MSDLun *lun,
+ Media *media,
+ unsigned char *ioBuffer,
+ unsigned int ioBufferSize,
+ unsigned int baseAddress,
+ unsigned int size,
+ unsigned short blockSize,
+ unsigned char protected,
+ void (*dataMonitor)(unsigned char flowDirection,
+ unsigned int dataLength,
+ unsigned int fifoNullCount,
+ unsigned int fifoFullCount));
+
+extern unsigned char LUN_Eject(MSDLun *lun);
+
+extern unsigned char LUN_Write(MSDLun *lun,
+ unsigned int blockAddress,
+ void *data,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument);
+
+extern unsigned char LUN_Read(MSDLun *lun,
+ unsigned int blockAddress,
+ void *data,
+ unsigned int length,
+ TransferCallback callback,
+ void *argument);
+
+#endif //#ifndef MSDLUN_H
+
diff --git a/usb/device/massstorage/MSDMediaArch.png b/usb/device/massstorage/MSDMediaArch.png Binary files differnew file mode 100644 index 0000000..b641e97 --- /dev/null +++ b/usb/device/massstorage/MSDMediaArch.png diff --git a/usb/device/massstorage/SBC.h b/usb/device/massstorage/SBC.h new file mode 100644 index 0000000..7c64844 --- /dev/null +++ b/usb/device/massstorage/SBC.h @@ -0,0 +1,653 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// SCSI definitions.
+///
+/// !Usage
+///
+/// -# After command block received, Access and decode the SCSI command block
+/// with SBCCommand structure.
+//------------------------------------------------------------------------------
+
+#ifndef SBC_H
+#define SBC_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "SBC Operation Codes"
+/// This page lists operation codes of commands described in the SBC-3
+/// standard.
+///
+/// \note That most commands are actually defined in other standards,
+/// like SPC-4. Optional commands are not included here.
+///
+/// \see sbc3r07.pdf - Section 5.1 - Table 12
+/// \see spc4r06.pdf
+/// \see SBCCommand
+///
+/// !Codes
+/// - SBC_INQUIRY
+/// - SBC_READ_10
+/// - SBC_READ_CAPACITY_10
+/// - SBC_REQUEST_SENSE
+/// - SBC_TEST_UNIT_READY
+/// - SBC_WRITE_10
+///
+/// !Optional Codes but required by Windows
+/// - SBC_PREVENT_ALLOW_MEDIUM_REMOVAL
+/// - SBC_MODE_SENSE_6
+/// - SBC_VERIFY_10
+/// - SBC_READ_FORMAT_CAPACITIES
+
+/// Request information regarding parameters of the target and Logical Unit.
+#define SBC_INQUIRY 0x12
+/// Request the transfer data to the host.
+#define SBC_READ_10 0x28
+/// Request capacities of the currently installed medium.
+#define SBC_READ_CAPACITY_10 0x25
+/// Request that the device server transfer sense data.
+#define SBC_REQUEST_SENSE 0x03
+/// Check if the LUN is ready
+#define SBC_TEST_UNIT_READY 0x00
+/// Request that the device write the data transferred by the host.
+#define SBC_WRITE_10 0x2A
+
+/// Request that the target enable or disable the removal of the medium in
+/// the Logical Unit.
+#define SBC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
+/// Report parameters.
+#define SBC_MODE_SENSE_6 0x1A
+/// Request that the %device verify the data on the medium.
+#define SBC_VERIFY_10 0x2F
+/// Request a list of the possible capacities that can be formatted on medium
+#define SBC_READ_FORMAT_CAPACITIES 0x23
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "SBC Periph. Qualifiers"
+/// This page lists the peripheral qualifier values specified in the INQUIRY
+/// data
+/// \see spc4r06.pdf - Section 6.4.2 - Table 83
+/// \see SBCInquiryData
+///
+/// !Qualifiers
+/// - SBC_PERIPHERAL_DEVICE_CONNECTED
+/// - SBC_PERIPHERAL_DEVICE_NOT_CONNECTED
+/// - SBC_PERIPHERAL_DEVICE_NOT_SUPPORTED
+
+#define SBC_PERIPHERAL_DEVICE_CONNECTED 0x00
+#define SBC_PERIPHERAL_DEVICE_NOT_CONNECTED 0x01
+#define SBC_PERIPHERAL_DEVICE_NOT_SUPPORTED 0x03
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "SBC Periph. Types"
+/// This page lists peripheral device types specified in the INQUIRY data
+/// \see spc4r06.pdf - Section 6.4.2 - Table 84
+/// \see SBCInquiryData
+///
+/// !Types
+/// - SBC_DIRECT_ACCESS_BLOCK_DEVICE
+/// - SBC_SEQUENTIAL_ACCESS_DEVICE
+/// - SBC_PRINTER_DEVICE
+/// - SBC_PROCESSOR_DEVICE
+/// - SBC_WRITE_ONCE_DEVICE
+/// - SBC_CD_DVD_DEVICE
+/// - SBC_SCANNER_DEVICE
+/// - SBC_OPTICAL_MEMORY_DEVICE
+/// - SBC_MEDIA_CHANGER_DEVICE
+/// - SBC_COMMUNICATION_DEVICE
+/// - SBC_STORAGE_ARRAY_CONTROLLER_DEVICE
+/// - SBC_ENCLOSURE_SERVICES_DEVICE
+/// - SBC_SIMPLIFIED_DIRECT_ACCESS_DEVICE
+/// - SBC_OPTICAL_CARD_READER_WRITER_DEVICE
+/// - SBC_BRIDGE_CONTROLLER_COMMANDS
+/// - SBC_OBJECT_BASED_STORAGE_DEVICE
+
+#define SBC_DIRECT_ACCESS_BLOCK_DEVICE 0x00
+#define SBC_SEQUENTIAL_ACCESS_DEVICE 0x01
+#define SBC_PRINTER_DEVICE 0x02
+#define SBC_PROCESSOR_DEVICE 0x03
+#define SBC_WRITE_ONCE_DEVICE 0x04
+#define SBC_CD_DVD_DEVICE 0x05
+#define SBC_SCANNER_DEVICE 0x06
+#define SBC_OPTICAL_MEMORY_DEVICE 0x07
+#define SBC_MEDIA_CHANGER_DEVICE 0x08
+#define SBC_COMMUNICATION_DEVICE 0x09
+#define SBC_STORAGE_ARRAY_CONTROLLER_DEVICE 0x0C
+#define SBC_ENCLOSURE_SERVICES_DEVICE 0x0D
+#define SBC_SIMPLIFIED_DIRECT_ACCESS_DEVICE 0x0E
+#define SBC_OPTICAL_CARD_READER_WRITER_DEVICE 0x0F
+#define SBC_BRIDGE_CONTROLLER_COMMANDS 0x10
+#define SBC_OBJECT_BASED_STORAGE_DEVICE 0x11
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \brief Version value for the SBC-3 specification
+/// \see spc4r06.pdf - Section 6.4.2 - Table 85
+#define SBC_SPC_VERSION_4 0x06
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \brief Values for the TPGS field returned in INQUIRY data
+/// \see spc4r06.pdf - Section 6.4.2 - Table 86
+#define SBC_TPGS_NONE 0x0
+#define SBC_TPGS_ASYMMETRIC 0x1
+#define SBC_TPGS_SYMMETRIC 0x2
+#define SBC_TPGS_BOTH 0x3
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \brief Version descriptor value for the SBC-3 specification
+/// \see spc4r06.pdf - Section 6.4.2 - Table 87
+#define SBC_VERSION_DESCRIPTOR_SBC_3 0x04C0
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "SBC Sense Response Codes"
+/// This page lists sense data response codes returned in REQUEST SENSE data
+/// \see spc4r06.pdf - Section 4.5.1 - Table 12
+///
+/// !Codes
+/// - SBC_SENSE_DATA_FIXED_CURRENT
+/// - SBC_SENSE_DATA_FIXED_DEFERRED
+/// - SBC_SENSE_DATA_DESCRIPTOR_CURRENT
+/// - SBC_SENSE_DATA_DESCRIPTOR_DEFERRED
+
+#define SBC_SENSE_DATA_FIXED_CURRENT 0x70
+#define SBC_SENSE_DATA_FIXED_DEFERRED 0x71
+#define SBC_SENSE_DATA_DESCRIPTOR_CURRENT 0x72
+#define SBC_SENSE_DATA_DESCRIPTOR_DEFERRED 0x73
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "SBC Sense Keys"
+/// This page lists sense key values returned in the REQUEST SENSE data
+/// \see spc4r06.pdf - Section 4.5.6 - Table 27
+///
+/// !Keys
+/// - SBC_SENSE_KEY_NO_SENSE
+/// - SBC_SENSE_KEY_RECOVERED_ERROR
+/// - SBC_SENSE_KEY_NOT_READY
+/// - SBC_SENSE_KEY_MEDIUM_ERROR
+/// - SBC_SENSE_KEY_HARDWARE_ERROR
+/// - SBC_SENSE_KEY_ILLEGAL_REQUEST
+/// - SBC_SENSE_KEY_UNIT_ATTENTION
+/// - SBC_SENSE_KEY_DATA_PROTECT
+/// - SBC_SENSE_KEY_BLANK_CHECK
+/// - SBC_SENSE_KEY_VENDOR_SPECIFIC
+/// - SBC_SENSE_KEY_COPY_ABORTED
+/// - SBC_SENSE_KEY_ABORTED_COMMAND
+/// - SBC_SENSE_KEY_VOLUME_OVERFLOW
+/// - SBC_SENSE_KEY_MISCOMPARE
+
+/// No specific sense key. Successful command.
+#define SBC_SENSE_KEY_NO_SENSE 0x00
+/// Command completed succesfully with some recovery action by the %device.
+#define SBC_SENSE_KEY_RECOVERED_ERROR 0x01
+/// The device can not be accessed.
+#define SBC_SENSE_KEY_NOT_READY 0x02
+/// Command terminated with a error condition that was probably caused by a
+/// flaw in the medium or an error in the recorded data.
+#define SBC_SENSE_KEY_MEDIUM_ERROR 0x03
+/// Hardware failure while performing the command or during a self test.
+#define SBC_SENSE_KEY_HARDWARE_ERROR 0x04
+/// Illegal parameter found in the command or additional parameters.
+#define SBC_SENSE_KEY_ILLEGAL_REQUEST 0x05
+/// Removable medium may have been changed or the %device has been reset.
+#define SBC_SENSE_KEY_UNIT_ATTENTION 0x06
+/// Write on a block that is protected.
+#define SBC_SENSE_KEY_DATA_PROTECT 0x07
+/// Indicates that a write-once device or a sequential-access device
+/// encountered blank medium or format-defined end-of-data indication while
+/// reading or a write-once device encountered a non-blank medium while writing.
+#define SBC_SENSE_KEY_BLANK_CHECK 0x08
+/// Reporting vendor specific conditions.
+#define SBC_SENSE_KEY_VENDOR_SPECIFIC 0x09
+/// EXTENDED COPY command was aborted.
+#define SBC_SENSE_KEY_COPY_ABORTED 0x0A
+/// Device aborted the command.
+#define SBC_SENSE_KEY_ABORTED_COMMAND 0x0B
+/// A buffered peripheral device is overflow.
+#define SBC_SENSE_KEY_VOLUME_OVERFLOW 0x0D
+/// The source data did not match the data read from the medium.
+#define SBC_SENSE_KEY_MISCOMPARE 0x0E
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "SBC Sense Additionals"
+/// This page lists additional sense code values returned in REQUEST SENSE data
+/// \see spc4r06.pdf - Section 4.5.6 - Table 28
+///
+/// !Additional Codes
+/// - SBC_ASC_LOGICAL_UNIT_NOT_READY
+/// - SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE
+/// - SBC_ASC_INVALID_FIELD_IN_CDB
+/// - SBC_ASC_WRITE_PROTECTED
+/// - SBC_ASC_FORMAT_CORRUPTED
+/// - SBC_ASC_INVALID_COMMAND_OPERATION_CODE
+/// - SBC_ASC_TOO_MUCH_WRITE_DATA
+/// - SBC_ASC_NOT_READY_TO_READY_CHANGE
+/// - SBC_ASC_MEDIUM_NOT_PRESENT
+
+#define SBC_ASC_LOGICAL_UNIT_NOT_READY 0x04
+#define SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
+#define SBC_ASC_INVALID_FIELD_IN_CDB 0x24
+#define SBC_ASC_WRITE_PROTECTED 0x27
+#define SBC_ASC_FORMAT_CORRUPTED 0x31
+#define SBC_ASC_INVALID_COMMAND_OPERATION_CODE 0x20
+#define SBC_ASC_TOO_MUCH_WRITE_DATA 0x26
+#define SBC_ASC_NOT_READY_TO_READY_CHANGE 0x28
+#define SBC_ASC_MEDIUM_NOT_PRESENT 0x3A
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \brief MEDIUM TYPE field value for direct-access block devices
+/// \see sbc3r06.pdf - Section 6.3.1
+#define SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE 0x00
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \brief MRIE field values
+/// \see sbc3r06.pdf - Section 7.4.11 - Table 286
+#define SBC_MRIE_NO_REPORTING 0x00
+#define SBC_MRIE_ASYNCHRONOUS 0x01
+#define SBC_MRIE_GENERATE_UNIT_ATTENTION 0x02
+#define SBC_MRIE_COND_GENERATE_RECOVERED_ERROR 0x03
+#define SBC_MRIE_UNCOND_GENERATE_RECOVERED_ERROR 0x04
+#define SBC_MRIE_GENERATE_NO_SENSE 0x05
+#define SBC_MRIE_ON_REQUEST 0x06
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \brief Supported mode pages
+/// \see sbc3r06.pdf - Section 6.3.1 - Table 115
+#define SBC_PAGE_READ_WRITE_ERROR_RECOVERY 0x01
+#define SBC_PAGE_INFORMATIONAL_EXCEPTIONS_CONTROL 0x1C
+#define SBC_PAGE_RETURN_ALL 0x3F
+#define SBC_PAGE_VENDOR_SPECIFIC 0x00
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "MSD Endian Macros"
+/// This page lists the macros for endianness conversion.
+///
+/// !Macros
+/// - WORDB
+/// - DWORDB
+/// - STORE_DWORDB
+/// - STORE_WORDB
+/// \brief Converts a byte array to a word value using the big endian format
+#define WORDB(bytes) ((unsigned short) ((bytes[0] << 8) | bytes[1]))
+
+/// \brief Converts a byte array to a dword value using the big endian format
+#define DWORDB(bytes) ((unsigned int) ((bytes[0] << 24) | (bytes[1] << 16) \
+ | (bytes[2] << 8) | bytes[3]))
+
+/// \brief Stores a dword value in a byte array, in big endian format
+#define STORE_DWORDB(dword, bytes) \
+ bytes[0] = (unsigned char) (((dword) >> 24) & 0xFF); \
+ bytes[1] = (unsigned char) (((dword) >> 16) & 0xFF); \
+ bytes[2] = (unsigned char) (((dword) >> 8) & 0xFF); \
+ bytes[3] = (unsigned char) ((dword) & 0xFF);
+
+/// \brief Stores a word value in a byte array, in big endian format
+#define STORE_WORDB(word, bytes) \
+ bytes[0] = (unsigned char) (((word) >> 8) & 0xFF); \
+ bytes[1] = (unsigned char) ((word) & 0xFF);
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Structures
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// \brief Structure for the INQUIRY command
+/// \see spc4r06.pdf - Section 6.4.1 - Table 81
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x12 : SBC_INQUIRY
+ unsigned char isEVPD:1, //!< Type of requested data
+ bReserved1:7; //!< Reserved bits
+ unsigned char bPageCode; //!< Specifies the VPD to return
+ unsigned char pAllocationLength[2]; //!< Size of host buffer
+ unsigned char bControl; //!< 0x00
+
+} __attribute__ ((packed)) SBCInquiry; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Standard INQUIRY data format returned by the device
+/// \see spc4r06.pdf - Section 6.4.2 - Table 82
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bPeripheralDeviceType:5, //!< Peripheral device type
+ bPeripheralQualifier :3; //!< Peripheral qualifier
+ unsigned char bReserved1:7, //!< Reserved bits
+ isRMB :1; //!< Is media removable ?
+ unsigned char bVersion; //!< SPC version used
+ unsigned char bResponseDataFormat:4, //!< Must be 0x2
+ isHIGHSUP :1, //!< Hierarchical addressing used ?
+ isNORMACA :1, //!< ACA attribute supported ?
+ bObsolete1 :2; //!< Obsolete bits
+ unsigned char bAdditionalLength; //!< Length of remaining INQUIRY data
+ unsigned char isSCCS :1, //!< Embedded SCC ?
+ isACC :1, //!< Access control coordinator ?
+ bTPGS :2, //!< Target port support group
+ is3PC :1, //!< Third-party copy supported ?
+ bReserved2:2, //!< Reserved bits
+ isProtect :1; //!< Protection info supported ?
+ unsigned char bObsolete2:1, //!< Obsolete bit
+ isEncServ :1, //!< Embedded enclosure service comp?
+ isVS :1, //!< ???
+ isMultiP :1, //!< Multi-port device ?
+ bObsolete3:3, //!< Obsolete bits
+ bUnused1 :1; //!< Unused feature
+ unsigned char bUnused2:6, //!< Unused features
+ isCmdQue:1, //!< Task management model supported ?
+ isVS2 :1; //!< ???
+ unsigned char pVendorID[8]; //!< T10 vendor identification
+ unsigned char pProductID[16]; //!< Vendor-defined product ID
+ unsigned char pProductRevisionLevel[4];//!< Vendor-defined product revision
+ unsigned char pVendorSpecific[20]; //!< Vendor-specific data
+ unsigned char bUnused3; //!< Unused features
+ unsigned char bReserved3; //!< Reserved bits
+ unsigned short pVersionDescriptors[8]; //!< Standards the device complies to
+ unsigned char pReserved4[22]; //!< Reserved bytes
+
+} __attribute__ ((packed)) SBCInquiryData; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Data structure for the READ (10) command
+/// \see sbc3r07.pdf - Section 5.7 - Table 34
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x28 : SBC_READ_10
+ unsigned char bObsolete1:1, //!< Obsolete bit
+ isFUA_NV:1, //!< Cache control bit
+ bReserved1:1, //!< Reserved bit
+ isFUA:1, //!< Cache control bit
+ isDPO:1, //!< Cache control bit
+ bRdProtect:3; //!< Protection information to send
+ unsigned char pLogicalBlockAddress[4]; //!< Index of first block to read
+ unsigned char bGroupNumber:5, //!< Information grouping
+ bReserved2:3; //!< Reserved bits
+ unsigned char pTransferLength[2]; //!< Number of blocks to transmit
+ unsigned char bControl; //!< 0x00
+
+} __attribute__ ((packed)) SBCRead10; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Structure for the READ CAPACITY (10) command
+/// \see sbc3r07.pdf - Section 5.11.1 - Table 40
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x25 : RBC_READ_CAPACITY
+ unsigned char bObsolete1:1, //!< Obsolete bit
+ bReserved1:7; //!< Reserved bits
+ unsigned char pLogicalBlockAddress[4]; //!< Block to evaluate if PMI is set
+ unsigned char pReserved2[2]; //!< Reserved bytes
+ unsigned char isPMI:1, //!< Partial medium indicator bit
+ bReserved3:7; //!< Reserved bits
+ unsigned char bControl; //!< 0x00
+
+} SBCReadCapacity10;
+
+//------------------------------------------------------------------------------
+/// \brief Data returned by the device after a READ CAPACITY (10) command
+/// \see sbc3r07.pdf - Section 5.11.2 - Table 41
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char pLogicalBlockAddress[4]; //!< Address of last logical block
+ unsigned char pLogicalBlockLength[4]; //!< Length of each logical block
+
+} SBCReadCapacity10Data;
+
+//------------------------------------------------------------------------------
+/// \brief Structure for the REQUEST SENSE command
+/// \see spc4r06.pdf - Section 6.26 - Table 170
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x03 : SBC_REQUEST_SENSE
+ unsigned char isDesc :1, //!< Type of information expected
+ bReserved1:7; //!< Reserved bits
+ unsigned char pReserved2[2]; //!< Reserved bytes
+ unsigned char bAllocationLength; //!< Size of host buffer
+ unsigned char bControl; //!< 0x00
+
+} SBCRequestSense;
+
+//------------------------------------------------------------------------------
+/// \brief Fixed format sense data returned after a REQUEST SENSE command has
+/// been received with a DESC bit cleared.
+/// \see spc4r06.pdf - Section 4.5.3 - Table 26
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bResponseCode:7, //!< Sense data format
+ isValid :1; //!< Information field is standard
+ unsigned char bObsolete1; //!< Obsolete byte
+ unsigned char bSenseKey :4, //!< Generic error information
+ bReserved1:1, //!< Reserved bit
+ isILI :1, //!< SSC
+ isEOM :1, //!< SSC
+ isFilemark:1; //!< SSC
+ unsigned char pInformation[4]; //!< Command-specific
+ unsigned char bAdditionalSenseLength; //!< sizeof(SBCRequestSense_data)-8
+ unsigned char pCommandSpecificInformation[4]; //!< Command-specific
+ unsigned char bAdditionalSenseCode; //!< Additional error information
+ unsigned char bAdditionalSenseCodeQualifier; //!< Further error information
+ unsigned char bFieldReplaceableUnitCode; //!< Specific component code
+ unsigned char bSenseKeySpecific:7, //!< Additional exception info
+ isSKSV :1; //!< Is sense key specific valid?
+ unsigned char pSenseKeySpecific[2]; //!< Additional exception info
+
+} SBCRequestSenseData;
+
+//------------------------------------------------------------------------------
+/// \brief Data structure for the TEST UNIT READY command
+/// \see spc4r06.pdf - Section 6.34 - Table 192
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x00 : SBC_TEST_UNIT_READY
+ unsigned char pReserved1[4]; //!< Reserved bits
+ unsigned char bControl; //!< 0x00
+
+} __attribute__ ((packed)) SBCTestUnitReady; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Structure for the WRITE (10) command
+/// \see sbc3r07.pdf - Section 5.26 - Table 70
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x2A : SBC_WRITE_10
+ unsigned char bObsolete1:1, //!< Obsolete bit
+ isFUA_NV:1, //!< Cache control bit
+ bReserved1:1, //!< Reserved bit
+ isFUA:1, //!< Cache control bit
+ isDPO:1, //!< Cache control bit
+ bWrProtect:3; //!< Protection information to send
+ unsigned char pLogicalBlockAddress[4]; //!< First block to write
+ unsigned char bGroupNumber:5, //!< Information grouping
+ bReserved2:3; //!< Reserved bits
+ unsigned char pTransferLength[2]; //!< Number of blocks to write
+ unsigned char bControl; //!< 0x00
+
+} SBCWrite10;
+
+//------------------------------------------------------------------------------
+/// \brief Structure for the PREVENT/ALLOW MEDIUM REMOVAL command
+/// \see sbc3r07.pdf - Section 5.5 - Table 30
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x1E : SBC_PREVENT_ALLOW_MEDIUM_REMOVAL
+ unsigned char pReserved1[3]; //!< Reserved bytes
+ unsigned char bPrevent:2, //!< Accept/prohibit removal
+ bReserved2:6; //!< Reserved bits
+ unsigned char bControl; //!< 0x00
+
+} __attribute__ ((packed)) SBCMediumRemoval; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Structure for the MODE SENSE (6) command
+/// \see spc4r06 - Section 6.9.1 - Table 98
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bOperationCode; //!< 0x1A : SBC_MODE_SENSE_6
+ unsigned char bReserved1:3, //!< Reserved bits
+ isDBD:1, //!< Disable block descriptors bit
+ bReserved2:4; //!< Reserved bits
+ unsigned char bPageCode:6, //!< Mode page to return
+ bPC:2; //!< Type of parameter values to return
+ unsigned char bSubpageCode; //!< Mode subpage to return
+ unsigned char bAllocationLength; //!< Host buffer allocated size
+ unsigned char bControl; //!< 0x00
+
+} __attribute__ ((packed)) SBCModeSense6; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Header for the data returned after a MODE SENSE (6) command
+/// \see spc4r06.pdf - Section 7.4.3 - Table 268
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bModeDataLength; //!< Length of mode data to follow
+ unsigned char bMediumType; //!< Type of medium (SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE)
+ unsigned char bReserved1:4, //!< Reserved bits
+ isDPOFUA:1, //!< DPO/FUA bits supported ?
+ bReserved2:2, //!< Reserved bits
+ isWP:1; //!< Is medium write-protected ?
+ unsigned char bBlockDescriptorLength; //!< Length of all block descriptors
+
+} __attribute__ ((packed)) SBCModeParameterHeader6; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Informational exceptions control mode page
+/// \see spc4r06.pdf - Section 7.4.11 - Table 285
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bPageCode:6, //!< 0x1C : SBC_PAGE_INFORMATIONAL_EXCEPTIONS_CONTROL
+ isSPF:1, //!< Page or subpage data format
+ isPS:1; //!< Parameters saveable ?
+ unsigned char bPageLength; //!< Length of page data (0x0A)
+ unsigned char isLogErr:1, //!< Should informational exceptions be logged ?
+ isEBackErr:1, //!< Enable background error bit
+ isTest:1, //!< Create a device test failure ?
+ isDExcpt:1, //!< Disable exception control bit
+ isEWasc:1, //!< Report warnings ?
+ isEBF:1, //!< Enable background function bit
+ bReserved1:1, //!< Reserved bit
+ isPerf:1; //!< Delay acceptable when treating exceptions ?
+ unsigned char bMRIE:4, //!< Method of reporting informational exceptions
+ bReserved2:4; //!< Reserved bits
+ unsigned char pIntervalTimer[4]; //!< Error reporting period
+ unsigned char pReportCount[4]; //!< Maximum number of time a report can be issued
+
+} __attribute__ ((packed)) SBCInformationalExceptionsControl; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Read/write error recovery mode page
+/// \see sbc3r07.pdf - Section 6.3.5 - Table 122
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char bPageCode:6, //!< 0x01 : SBC_PAGE_READ_WRITE_ERROR_RECOVERY
+ isSPF:1, //!< Page or subpage data format
+ isPS:1; //!< Parameters saveable ?
+ unsigned char bPageLength; //!< Length of page data (0x0A)
+ unsigned char isDCR:1, //!< Disable correction bit
+ isDTE:1, //!< Data terminate on error bit
+ isPER:1, //!< Post error bit
+ isEER:1, //!< Enable early recovery bit
+ isRC:1, //!< Read continuous bit
+ isTB:1, //!< Transfer block bit
+ isARRE:1, //!< Automatic read reallocation enabled bit
+ isAWRE:1; //!< Automatic write reallocation enabled bit
+ unsigned char bReadRetryCount; //!< Number of retries when reading
+ unsigned char pObsolete1[3]; //!< Obsolete bytes
+ unsigned char bReserved1; //!< Reserved byte
+ unsigned char bWriteRetryCount; //!< Number of retries when writing
+ unsigned char bReserved2; //!< Reserved byte
+ unsigned char pRecoveryTimeLimit[2]; //!< Maximum time duration for error recovery
+
+} __attribute__ ((packed)) SBCReadWriteErrorRecovery; // GCC
+
+//------------------------------------------------------------------------------
+/// \brief Generic structure for holding information about SBC commands
+/// \see SBCInquiry
+/// \see SBCRead10
+/// \see SBCReadCapacity10
+/// \see SBCRequestSense
+/// \see SBCTestUnitReady
+/// \see SBCWrite10
+/// \see SBCMediumRemoval
+/// \see SBCModeSense6
+//------------------------------------------------------------------------------
+typedef union {
+
+ unsigned char bOperationCode; //!< Operation code of the command
+ SBCInquiry inquiry; //!< INQUIRY command
+ SBCRead10 read10; //!< READ (10) command
+ SBCReadCapacity10 readCapacity10; //!< READ CAPACITY (10) command
+ SBCRequestSense requestSense; //!< REQUEST SENSE command
+ SBCTestUnitReady testUnitReady; //!< TEST UNIT READY command
+ SBCWrite10 write10; //!< WRITE (10) command
+ SBCMediumRemoval mediumRemoval; //!< PREVENT/ALLOW MEDIUM REMOVAL command
+ SBCModeSense6 modeSense6; //!< MODE SENSE (6) command
+
+} SBCCommand;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+#endif //#ifndef SBC_H
+
diff --git a/usb/device/massstorage/SBCMethods.c b/usb/device/massstorage/SBCMethods.c new file mode 100644 index 0000000..cd7a87a --- /dev/null +++ b/usb/device/massstorage/SBCMethods.c @@ -0,0 +1,1611 @@ +/* ----------------------------------------------------------------------------
+ * 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 "SBCMethods.h"
+#include "MSDDStateMachine.h"
+#include <usb/device/core/USBD.h>
+
+#include "MSDIOFifo.h"
+
+//------------------------------------------------------------------------------
+// Global variables
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+#ifdef MSDIO_READ10_CHUNK_SIZE
+/// READ10 - Read data from specific LUN to FIFO
+#define SBC_READ_CHUNK(pLun, lba, pFifo, pCb, pArg) \
+ LUN_Read((pLun), (lba), \
+ &(pFifo)->pBuffer[(pFifo)->inputNdx], \
+ ((pFifo)->chunkSize/(pFifo)->blockSize), \
+ (TransferCallback)(pCb), (void*)pArg)
+/// READ10 - Transfer data from FIFO to USB
+#define SBC_TX_CHUNK(pFifo, pCb, pArg) \
+ MSDD_Write(&(pFifo)->pBuffer[(pFifo)->outputNdx], \
+ (pFifo)->chunkSize, \
+ (TransferCallback)(pCb), (void*)(pArg))
+#endif
+
+#ifdef MSDIO_WRITE10_CHUNK_SIZE
+/// WRITE10 - Read data from USB to FIFO
+#define SBC_RX_CHUNK(pFifo,pCb,pArg) \
+ MSDD_Read(&(pFifo)->pBuffer[(pFifo)->inputNdx], \
+ (pFifo)->chunkSize, \
+ (TransferCallback)(pCb), (void*)(pArg))
+/// WRITE10 - Write data from FIFO to LUN
+#define SBC_WRITE_CHUNK(pLun, lba, pFifo, pCb, pArg) \
+ LUN_Write((pLun), (lba), \
+ &(pFifo)->pBuffer[(pFifo)->outputNdx], \
+ ((pFifo)->chunkSize/(pFifo)->blockSize), \
+ (TransferCallback)(pCb), (void*)(pArg))
+#endif
+
+
+//------------------------------------------------------------------------------
+//! \brief Header for the mode pages data
+//! \see SBCModeParameterHeader6
+//------------------------------------------------------------------------------
+static const SBCModeParameterHeader6 modeParameterHeader6 = {
+
+ sizeof(SBCModeParameterHeader6) - 1, //! Length is 0x03
+ SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE, //! Direct-access block device
+ 0, //! Reserved bits
+ 0, //! DPO/FUA not supported
+ 0, //! Reserved bits
+ 0, //! not write-protected
+ 0 //! No block descriptor
+};
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//! \brief Check if the LUN is ready.
+//! \param lun Pointer to the LUN affected by the command
+//! \return 1 if the LUN is ready to be written
+//! \see MSDLun
+//------------------------------------------------------------------------------
+static unsigned char SBCLunIsReady(MSDLun *lun)
+{
+ unsigned char lunIsReady = 0;
+
+ if (lun->media == 0 || lun->status < LUN_CHANGED) {
+ TRACE_INFO("SBCLunIsReady: Not Present!\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_NOT_READY,
+ SBC_ASC_MEDIUM_NOT_PRESENT,
+ 0);
+
+ }
+ else if (lun->status < LUN_READY) {
+ TRACE_INFO("SBCLunIsReady: Changing!\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_UNIT_ATTENTION,
+ SBC_ASC_NOT_READY_TO_READY_CHANGE,
+ 0);
+ lun->status = LUN_READY;
+ }
+ else {
+
+ lunIsReady = 1;
+ }
+
+ return lunIsReady;
+}
+//------------------------------------------------------------------------------
+//! \brief Check if the LUN can write.
+//! \param lun Pointer to the LUN affected by the command
+//! \return 1 if the LUN is ready to be written
+//! \see MSDLun
+//------------------------------------------------------------------------------
+static unsigned char SBCLunCanBeWritten(MSDLun *lun)
+{
+ unsigned char canBeWritten = 0;
+
+ if (!SBCLunIsReady(lun)) {
+
+ TRACE_WARNING("SBCLunCanBeWritten: Not Ready!\n\r");
+ }
+ else if (lun->protected) {
+
+ TRACE_WARNING("SBCLunCanBeWritten: Protected!\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_DATA_PROTECT,
+ SBC_ASC_WRITE_PROTECTED,
+ 0);
+ }
+ else {
+
+ canBeWritten = 1;
+ }
+
+ return canBeWritten;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Performs a WRITE (10) command on the specified LUN.
+//!
+//! The data to write is first received from the USB host and then
+//! actually written on the media.
+//! This function operates asynchronously and must be called multiple
+//! times to complete. A result code of MSDDriver_STATUS_INCOMPLETE
+//! indicates that at least another call of the method is necessary.
+//! \param lun Pointer to the LUN affected by the command
+//! \param commandState Current state of the command
+//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
+//! \see MSDLun
+//! \see MSDCommandState
+//------------------------------------------------------------------------------
+static unsigned char SBC_Write10(MSDLun *lun,
+ MSDCommandState *commandState)
+{
+ unsigned char status;
+ unsigned char result = MSDD_STATUS_INCOMPLETE;
+ SBCRead10 *command = (SBCRead10 *) commandState->cbw.pCommand;
+ MSDTransfer *transfer = &(commandState->transfer);
+ MSDTransfer *disktransfer = &(commandState->disktransfer);
+ MSDIOFifo *fifo = &lun->ioFifo;
+
+ // Init command state
+ if (commandState->state == 0) {
+
+ commandState->state = SBC_STATE_WRITE;
+
+ // The command should not be proceeded if READONLY
+ if (!SBCLunCanBeWritten(lun)) {
+
+ return MSDD_STATUS_RW;
+ }
+ else {
+
+
+ // Initialize FIFO
+ fifo->dataTotal = commandState->length;
+ fifo->blockSize = lun->blockSize * lun->media->blockSize;
+ #ifdef MSDIO_WRITE10_CHUNK_SIZE
+ if ( fifo->dataTotal >= 64 * 1024
+ && fifo->blockSize < MSDIO_WRITE10_CHUNK_SIZE)
+ fifo->chunkSize = MSDIO_WRITE10_CHUNK_SIZE;
+ else
+ fifo->chunkSize = fifo->blockSize;
+ #endif
+ fifo->fullCnt = 0;
+ fifo->nullCnt = 0;
+
+ // Initialize FIFO output (Disk)
+ fifo->outputNdx = 0;
+ fifo->outputTotal = 0;
+ fifo->outputState = MSDIO_IDLE;
+ transfer->semaphore = 0;
+
+ // Initialize FIFO input (USB)
+ fifo->inputNdx = 0;
+ fifo->inputTotal = 0;
+ fifo->inputState = MSDIO_START;
+ disktransfer->semaphore = 0;
+ }
+
+ }
+
+ if (commandState->length == 0) {
+
+ // Perform the callback!
+ if (lun->dataMonitor) {
+
+ lun->dataMonitor(0, fifo->dataTotal, fifo->nullCnt, fifo->fullCnt);
+ }
+ return MSDD_STATUS_SUCCESS;
+ }
+
+ // USB receive task
+ switch(fifo->inputState) {
+
+ //------------------
+ case MSDIO_IDLE:
+ //------------------
+ if (fifo->inputTotal < fifo->dataTotal &&
+ fifo->inputTotal - fifo->outputTotal < fifo->bufferSize) {
+
+ fifo->inputState = MSDIO_START;
+ }
+ break;
+
+ //------------------
+ case MSDIO_START:
+ //------------------
+ // Should not start if there is any disk error
+ if (fifo->outputState == MSDIO_ERROR) {
+
+ TRACE_INFO_WP("udErr ");
+ fifo->inputState = MSDIO_ERROR;
+ break;
+ }
+
+ // Read one block of data sent by the host
+ if (lun->media->mappedWR) {
+
+ // Directly read to memory
+ status = MSDD_Read((void*)
+ ((lun->media->baseAddress
+ + (lun->baseAddress
+ + DWORDB(command->pLogicalBlockAddress)
+ * lun->blockSize
+ )
+ ) * lun->media->blockSize
+ ),
+ fifo->dataTotal,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+ }
+ else {
+ #ifdef MSDIO_WRITE10_CHUNK_SIZE
+ status = SBC_RX_CHUNK(fifo, MSDDriver_Callback, transfer);
+ #else
+ // Read block to buffer
+ status = MSDD_Read((void*)&fifo->pBuffer[fifo->inputNdx],
+ fifo->blockSize,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+ #endif
+ }
+
+ // Check operation result code
+ if (status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_Write10: Failed to start receiving\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_HARDWARE_ERROR,
+ 0,
+ 0);
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("uRx ");
+
+ // Prepare next device state
+ fifo->inputState = MSDIO_WAIT;
+ }
+ break; // MSDIO_START
+
+ //------------------
+ case MSDIO_WAIT:
+ //------------------
+ TRACE_INFO_WP("uWait ");
+
+ // Check semaphore
+ if (transfer->semaphore > 0) {
+
+ transfer->semaphore--;
+ fifo->inputState = MSDIO_NEXT;
+ }
+ break;
+
+ //------------------
+ case MSDIO_NEXT:
+ //------------------
+ // Check the result code of the read operation
+ if (transfer->status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_Write10: Failed to received\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_HARDWARE_ERROR,
+ 0,
+ 0);
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("uNxt ");
+
+ // Mapped read, all data done
+ if (lun->media->mappedWR) {
+
+ fifo->inputTotal = fifo->dataTotal;
+ fifo->inputState = MSDIO_IDLE;
+ }
+ else {
+
+ // Update input index
+ #ifdef MSDIO_WRITE10_CHUNK_SIZE
+ MSDIOFifo_IncNdx(fifo->inputNdx,
+ fifo->chunkSize,
+ fifo->bufferSize);
+ fifo->inputTotal += fifo->chunkSize;
+ #else
+ MSDIOFifo_IncNdx(fifo->inputNdx,
+ fifo->blockSize,
+ fifo->bufferSize);
+ fifo->inputTotal += fifo->blockSize;
+ #endif
+
+ // Start Next block
+ // - All Data done?
+ if (fifo->inputTotal >= fifo->dataTotal) {
+
+ fifo->inputState = MSDIO_IDLE;
+ }
+ // - Buffer full?
+ else if (fifo->inputNdx == fifo->outputNdx) {
+ fifo->inputState = MSDIO_IDLE;
+ fifo->fullCnt ++;
+
+ TRACE_DEBUG_WP("ufFull%d ", fifo->inputNdx);
+ }
+ // - More data to transfer?
+ else if (fifo->inputTotal < fifo->dataTotal) {
+ fifo->inputState = MSDIO_START;
+
+ TRACE_INFO_WP("uStart ");
+ }
+ // never executed !
+ //else {
+ // fifo->inputState = MSDIO_IDLE;
+ // TRACE_INFO_WP("uDone ");
+ //}
+ }
+
+ }
+ break; // MSDIO_NEXT
+
+ //------------------
+ case MSDIO_ERROR:
+ //------------------
+
+ TRACE_WARNING_WP("uErr ");
+ commandState->length -= fifo->inputTotal;
+ return MSDD_STATUS_RW;
+
+ }
+
+ // Disk write task
+ switch(fifo->outputState) {
+
+ //------------------
+ case MSDIO_IDLE:
+ //------------------
+ if (fifo->outputTotal < fifo->inputTotal) {
+
+ fifo->outputState = MSDIO_START;
+ }
+ break;
+
+ //------------------
+ case MSDIO_START:
+ //------------------
+
+ // Write the block to the media
+ if (lun->media->mappedWR) {
+
+ MSDDriver_Callback(disktransfer, MED_STATUS_SUCCESS, 0, 0);
+ status = LUN_STATUS_SUCCESS;
+ }
+ else {
+ #ifdef MSDIO_WRITE10_CHUNK_SIZE
+ status = SBC_WRITE_CHUNK(lun, DWORDB(command->pLogicalBlockAddress),
+ fifo, MSDDriver_Callback, disktransfer);
+ #else
+ status = LUN_Write(lun,
+ DWORDB(command->pLogicalBlockAddress),
+ &fifo->pBuffer[fifo->outputNdx],
+ 1,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) disktransfer);
+ #endif
+ }
+
+ // Check operation result code
+ if (status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_Write10: Failed to start write - ");
+
+ if (!SBCLunCanBeWritten(lun)) {
+
+ TRACE_WARNING("?\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_NOT_READY,
+ 0,
+ 0);
+ }
+
+ fifo->outputState = MSDIO_ERROR;
+ }
+ else {
+
+ // Prepare next state
+ fifo->outputState = MSDIO_WAIT;
+ }
+ break; // MSDIO_START
+
+ //------------------
+ case MSDIO_WAIT:
+ //------------------
+ TRACE_INFO_WP("dWait ");
+
+ // Check semaphore value
+ if (disktransfer->semaphore > 0) {
+
+ // Take semaphore and move to next state
+ disktransfer->semaphore--;
+ fifo->outputState = MSDIO_NEXT;
+ }
+ break;
+
+ //------------------
+ case MSDIO_NEXT:
+ //------------------
+ // Check operation result code
+ if (transfer->status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_Write10: Failed to write\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_RECOVERED_ERROR,
+ SBC_ASC_TOO_MUCH_WRITE_DATA,
+ 0);
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("dNxt ");
+
+ // Update transfer length and block address
+
+ // Mapped memory, done
+ if (lun->media->mappedWR) {
+
+ commandState->length = 0;
+ fifo->outputState = MSDIO_IDLE;
+ }
+ else {
+
+ // Update output index
+ #ifdef MSDIO_WRITE10_CHUNK_SIZE
+ STORE_DWORDB(DWORDB(command->pLogicalBlockAddress)
+ + fifo->chunkSize/fifo->blockSize,
+ command->pLogicalBlockAddress);
+ MSDIOFifo_IncNdx(fifo->outputNdx,
+ fifo->chunkSize,
+ fifo->bufferSize);
+ fifo->outputTotal += fifo->chunkSize;
+ #else
+ STORE_DWORDB(DWORDB(command->pLogicalBlockAddress) + 1,
+ command->pLogicalBlockAddress);
+ MSDIOFifo_IncNdx(fifo->outputNdx,
+ fifo->blockSize,
+ fifo->bufferSize);
+ fifo->outputTotal += fifo->blockSize;
+ #endif
+
+ // Start Next block
+ // - All data done?
+ if (fifo->outputTotal >= fifo->dataTotal) {
+
+ fifo->outputState = MSDIO_IDLE;
+ commandState->length = 0;
+ TRACE_INFO_WP("dDone ");
+ }
+ // - Send next?
+ else if (fifo->outputTotal < fifo->inputTotal) {
+
+ fifo->outputState = MSDIO_START;
+ TRACE_INFO_WP("dStart ");
+ }
+ // - Buffer Null?
+ else {
+ fifo->outputState = MSDIO_IDLE;
+ fifo->nullCnt ++;
+
+ TRACE_DEBUG_WP("dfNull%d ", fifo->outputNdx);
+ }
+ }
+ }
+ break; // MSDIO_NEXT
+
+ //------------------
+ case MSDIO_ERROR:
+ //------------------
+ break;
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Performs a READ (10) command on specified LUN.
+//!
+//! The data is first read from the media and then sent to the USB host.
+//! This function operates asynchronously and must be called multiple
+//! times to complete. A result code of MSDDriver_STATUS_INCOMPLETE
+//! indicates that at least another call of the method is necessary.
+//! \param lun Pointer to the LUN affected by the command
+//! \param commandState Current state of the command
+//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
+//! \see MSDLun
+//! \see MSDCommandState
+//------------------------------------------------------------------------------
+static unsigned char SBC_Read10(MSDLun *lun,
+ MSDCommandState *commandState)
+{
+ unsigned char status;
+ unsigned char result = MSDD_STATUS_INCOMPLETE;
+ SBCRead10 *command = (SBCRead10 *) commandState->cbw.pCommand;
+ MSDTransfer *transfer = &(commandState->transfer);
+ MSDTransfer *disktransfer = &(commandState->disktransfer);
+ MSDIOFifo *fifo = &lun->ioFifo;
+
+ // Init command state
+ if (commandState->state == 0) {
+
+ commandState->state = SBC_STATE_READ;
+
+ if (!SBCLunIsReady(lun)) {
+
+ return MSDD_STATUS_RW;
+ }
+ else {
+
+ // Initialize FIFO
+ fifo->dataTotal = commandState->length;
+ fifo->blockSize = lun->blockSize * lun->media->blockSize;
+ #ifdef MSDIO_READ10_CHUNK_SIZE
+ if ( fifo->dataTotal >= 64*1024
+ && fifo->blockSize < MSDIO_READ10_CHUNK_SIZE)
+ fifo->chunkSize = MSDIO_READ10_CHUNK_SIZE;
+ else
+ fifo->chunkSize = fifo->blockSize;
+ #endif
+ fifo->fullCnt = 0;
+ fifo->nullCnt = 0;
+
+ #ifdef MSDIO_FIFO_OFFSET
+ // Enable offset if total size >= 2*bufferSize
+ if (fifo->dataTotal / fifo->bufferSize >= 2)
+ fifo->bufferOffset = MSDIO_FIFO_OFFSET;
+ else
+ fifo->bufferOffset = 0;
+ #endif
+
+ // Initialize FIFO output (USB)
+ fifo->outputNdx = 0;
+ fifo->outputTotal = 0;
+ fifo->outputState = MSDIO_IDLE;
+ transfer->semaphore = 0;
+
+ // Initialize FIFO input (Disk)
+ fifo->inputNdx = 0;
+ fifo->inputTotal = 0;
+ fifo->inputState = MSDIO_START;
+ disktransfer->semaphore = 0;
+ }
+ }
+
+ // Check length
+ if (commandState->length == 0) {
+
+ // Perform the callback!
+ if (lun->dataMonitor) {
+
+ lun->dataMonitor(1, fifo->dataTotal, fifo->nullCnt, fifo->fullCnt);
+ }
+ return MSDD_STATUS_SUCCESS;
+ }
+
+ // Disk reading task
+ switch(fifo->inputState) {
+
+ //------------------
+ case MSDIO_IDLE:
+ //------------------
+ if (fifo->inputTotal < fifo->dataTotal &&
+ fifo->inputTotal - fifo->outputTotal < fifo->bufferSize) {
+
+ fifo->inputState = MSDIO_START;
+ }
+ break;
+
+ //------------------
+ case MSDIO_START:
+ //------------------
+ // Read one block of data from the media
+ if (lun->media->mappedRD) {
+
+ // Directly write, no read needed
+ MSDDriver_Callback(disktransfer, MED_STATUS_SUCCESS, 0, 0);
+ status = LUN_STATUS_SUCCESS;
+ }
+ else {
+ #ifdef MSDIO_READ10_CHUNK_SIZE
+ status = SBC_READ_CHUNK(lun, DWORDB(command->pLogicalBlockAddress),
+ fifo, MSDDriver_Callback, disktransfer);
+ #else
+ status = LUN_Read(lun,
+ DWORDB(command->pLogicalBlockAddress),
+ &fifo->pBuffer[fifo->inputNdx],
+ 1,
+ (TransferCallback) MSDDriver_Callback,
+ (void *)disktransfer);
+ #endif
+ }
+
+ // Check operation result code
+ if (status != LUN_STATUS_SUCCESS) {
+
+ TRACE_WARNING("RBC_Read10: Failed to start reading\n\r");
+
+ if (SBCLunIsReady(lun)) {
+
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_NOT_READY,
+ SBC_ASC_LOGICAL_UNIT_NOT_READY,
+ 0);
+ }
+
+ fifo->inputState = MSDIO_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("dRd ");
+
+ // Move to next command state
+ fifo->inputState = MSDIO_WAIT;
+ }
+ break; // MSDIO_START
+
+ //------------------
+ case MSDIO_WAIT:
+ //------------------
+ // Check semaphore value
+ if (disktransfer->semaphore > 0) {
+
+ TRACE_INFO_WP("dOk ");
+
+ // Take semaphore and move to next state
+ disktransfer->semaphore--;
+ fifo->inputState = MSDIO_NEXT;
+ }
+ break;
+
+ //------------------
+ case MSDIO_NEXT:
+ //------------------
+ // Check the operation result code
+ if (disktransfer->status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_Read10: Failed to read media\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_RECOVERED_ERROR,
+ SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
+ 0);
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("dNxt ");
+
+ if (lun->media->mappedRD) {
+
+ // All data is ready
+ fifo->inputState = MSDIO_IDLE;
+ fifo->inputTotal = fifo->dataTotal;
+ }
+ else {
+
+ // Update block address
+ #ifdef MSDIO_READ10_CHUNK_SIZE
+ STORE_DWORDB(DWORDB(command->pLogicalBlockAddress)
+ + fifo->chunkSize/fifo->blockSize,
+ command->pLogicalBlockAddress);
+
+ // Update input index
+ MSDIOFifo_IncNdx(fifo->inputNdx,
+ fifo->chunkSize,
+ fifo->bufferSize);
+ fifo->inputTotal += fifo->chunkSize;
+ #else
+ // Update block address
+ STORE_DWORDB(DWORDB(command->pLogicalBlockAddress) + 1,
+ command->pLogicalBlockAddress);
+
+ // Update input index
+ MSDIOFifo_IncNdx(fifo->inputNdx,
+ fifo->blockSize,
+ fifo->bufferSize);
+ fifo->inputTotal += fifo->blockSize;
+ #endif
+
+ // Start Next block
+ // - All Data done?
+ if (fifo->inputTotal >= fifo->dataTotal) {
+
+ TRACE_INFO_WP("dDone ");
+ fifo->inputState = MSDIO_IDLE;
+ }
+ // - Buffer full?
+ else if (fifo->inputNdx == fifo->outputNdx) {
+
+ TRACE_INFO_WP("dfFull%d ", (int)fifo->inputNdx);
+ fifo->inputState = MSDIO_IDLE;
+ fifo->fullCnt ++;
+ }
+ // - More data to transfer?
+ else if (fifo->inputTotal < fifo->dataTotal) {
+
+ TRACE_DEBUG_WP("dStart ");
+ fifo->inputState = MSDIO_START;
+ }
+ }
+
+ }
+
+ break;
+
+ //------------------
+ case MSDIO_ERROR:
+ //------------------
+ break;
+ }
+
+ // USB sending task
+ switch(fifo->outputState) {
+
+ //------------------
+ case MSDIO_IDLE:
+ //------------------
+ if (fifo->outputTotal < fifo->inputTotal) {
+
+ #ifdef MSDIO_FIFO_OFFSET
+ // Offset buffer the input data
+ if (fifo->bufferOffset) {
+ if (fifo->inputTotal < fifo->bufferOffset) {
+ break;
+ }
+ fifo->bufferOffset = 0;
+ }
+ #endif
+ fifo->outputState = MSDIO_START;
+ }
+ break;
+
+ //------------------
+ case MSDIO_START:
+ //------------------
+ // Should not start if there is any disk error
+ if (fifo->outputState == MSDIO_ERROR) {
+
+ fifo->inputState = MSDIO_ERROR;
+ break;
+ }
+
+ // Send the block to the host
+ if (lun->media->mappedRD) {
+
+ status = MSDD_Write((void*)
+ ((lun->media->baseAddress
+ + (lun->baseAddress
+ + DWORDB(command->pLogicalBlockAddress)
+ * lun->blockSize
+ )
+ ) * lun->media->blockSize
+ ),
+ commandState->length,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+ }
+ else {
+ #ifdef MSDIO_READ10_CHUNK_SIZE
+ status = SBC_TX_CHUNK(fifo, MSDDriver_Callback, transfer);
+ #else
+ status = MSDD_Write(&fifo->pBuffer[fifo->outputNdx],
+ fifo->blockSize,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+ #endif
+ }
+ // Check operation result code
+ if (status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_Read10: Failed to start to send\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_HARDWARE_ERROR,
+ 0,
+ 0);
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("uTx ");
+
+ // Move to next command state
+ fifo->outputState = MSDIO_WAIT;
+ }
+ break; // MSDIO_START
+
+ //------------------
+ case MSDIO_WAIT:
+ //------------------
+ // Check semaphore value
+ if (transfer->semaphore > 0) {
+
+ TRACE_INFO_WP("uOk ");
+
+ // Take semaphore and move to next state
+ transfer->semaphore--;
+ fifo->outputState = MSDIO_NEXT;
+ }
+ break;
+
+ //------------------
+ case MSDIO_NEXT:
+ //------------------
+ // Check operation result code
+ if (transfer->status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_Read10: Failed to send data\n\r");
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ SBC_SENSE_KEY_HARDWARE_ERROR,
+ 0,
+ 0);
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("uNxt ");
+
+ if (lun->media->mappedRD) {
+
+ commandState->length = 0;
+ }
+ else {
+
+ // Update output index
+ #ifdef MSDIO_READ10_CHUNK_SIZE
+ MSDIOFifo_IncNdx(fifo->outputNdx,
+ fifo->chunkSize,
+ fifo->bufferSize);
+ fifo->outputTotal += fifo->chunkSize;
+ #else
+ MSDIOFifo_IncNdx(fifo->outputNdx,
+ fifo->blockSize,
+ fifo->bufferSize);
+ fifo->outputTotal += fifo->blockSize;
+ #endif
+
+ // Start Next block
+ // - All data done?
+ if (fifo->outputTotal >= fifo->dataTotal) {
+
+ fifo->outputState = MSDIO_IDLE;
+ commandState->length = 0;
+ TRACE_INFO_WP("uDone ");
+ }
+ // - Buffer Null?
+ else if (fifo->inputNdx == fifo->outputNdx) {
+
+ TRACE_INFO_WP("ufNull%d ", (int)fifo->outputNdx);
+ fifo->outputState = MSDIO_IDLE;
+ fifo->nullCnt ++;
+ }
+ // - Send next?
+ else if (fifo->outputTotal < fifo->inputTotal) {
+
+ TRACE_DEBUG_WP("uStart ");
+ fifo->outputState = MSDIO_START;
+ }
+ }
+
+ }
+ break;
+
+ //------------------
+ case MSDIO_ERROR:
+ //------------------
+ break;
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Performs a READ CAPACITY (10) command.
+//!
+//! This function operates asynchronously and must be called multiple
+//! times to complete. A result code of MSDD_STATUS_INCOMPLETE
+//! indicates that at least another call of the method is necessary.
+//! \param lun Pointer to the LUN affected by the command
+//! \param commandState Current state of the command
+//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
+//! \see MSDLun
+//! \see MSDCommandState
+//------------------------------------------------------------------------------
+static unsigned char SBC_ReadCapacity10(MSDLun *lun,
+ MSDCommandState *commandState)
+{
+ unsigned char result = MSDD_STATUS_INCOMPLETE;
+ unsigned char status;
+ MSDTransfer *transfer = &(commandState->transfer);
+
+ if (!SBCLunIsReady(lun)) {
+
+ TRACE_INFO("SBC_ReadCapacity10: Not Ready!\n\r");
+ return MSDD_STATUS_RW;
+ }
+
+ // Initialize command state if needed
+ if (commandState->state == 0) {
+
+ commandState->state = SBC_STATE_WRITE;
+ }
+
+ // Identify current command state
+ switch (commandState->state) {
+ //-------------------
+ case SBC_STATE_WRITE:
+ //-------------------
+ // Start the write operation
+ status = MSDD_Write(&(lun->readCapacityData),
+ commandState->length,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check operation result code
+ if (status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_ReadCapacity: Cannot start sending data\n\r");
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ // Proceed to next command state
+ TRACE_INFO_WP("Sending ");
+ commandState->state = SBC_STATE_WAIT_WRITE;
+ }
+ break;
+
+ //------------------------
+ case SBC_STATE_WAIT_WRITE:
+ //------------------------
+ // Check semaphore value
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and terminate command
+ transfer->semaphore--;
+
+ if (transfer->status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING("RBC_ReadCapacity: Cannot send data\n\r");
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("Sent ");
+ result = MSDD_STATUS_SUCCESS;
+ }
+ commandState->length -= transfer->transferred;
+ }
+ break;
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Handles an INQUIRY command.
+//!
+//! This function operates asynchronously and must be called multiple
+//! times to complete. A result code of MSDDriver_STATUS_INCOMPLETE
+//! indicates that at least another call of the method is necessary.
+//! \param lun Pointer to the LUN affected by the command
+//! \param commandState Current state of the command
+//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
+//! \see MSDLun
+//! \see MSDCommandState
+//------------------------------------------------------------------------------
+static unsigned char SBC_Inquiry(MSDLun *lun,
+ MSDCommandState *commandState)
+{
+ unsigned char result = MSDD_STATUS_INCOMPLETE;
+ unsigned char status;
+ MSDTransfer *transfer = &(commandState->transfer);
+
+ // Check if required length is 0
+ if (commandState->length == 0) {
+
+ // Nothing to do
+ result = MSDD_STATUS_SUCCESS;
+ }
+ // Initialize command state if needed
+ else if (commandState->state == 0) {
+
+ commandState->state = SBC_STATE_WRITE;
+
+ // Change additional length field of inquiry data
+ lun->inquiryData->bAdditionalLength
+ = (unsigned char) (commandState->length - 5);
+ }
+
+ // Identify current command state
+ switch (commandState->state) {
+ //-------------------
+ case SBC_STATE_WRITE:
+ //-------------------
+ // Start write operation
+ status = MSDD_Write((void *) lun->inquiryData,
+ commandState->length,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check operation result code
+ if (status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "SPC_Inquiry: Cannot start sending data\n\r");
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ // Proceed to next state
+ TRACE_INFO_WP("Sending ");
+ commandState->state = SBC_STATE_WAIT_WRITE;
+ }
+ break;
+
+ //------------------------
+ case SBC_STATE_WAIT_WRITE:
+ //------------------------
+ // Check the semaphore value
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and terminate command
+ transfer->semaphore--;
+
+ if (transfer->status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "SPC_Inquiry: Data transfer failed\n\r");
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ TRACE_INFO_WP("Sent ");
+ result = MSDD_STATUS_SUCCESS;
+ }
+
+ // Update length field
+ commandState->length -= transfer->transferred;
+ }
+ break;
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Performs a REQUEST SENSE command.
+//!
+//! This function operates asynchronously and must be called multiple
+//! times to complete. A result code of MSDDriver_STATUS_INCOMPLETE
+//! indicates that at least another call of the method is necessary.
+//! \param lun Pointer to the LUN affected by the command
+//! \param commandState Current state of the command
+//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
+//! \see MSDLun
+//! \see MSDCommandState
+//------------------------------------------------------------------------------
+static unsigned char SBC_RequestSense(MSDLun *lun,
+ MSDCommandState *commandState)
+{
+ unsigned char result = MSDD_STATUS_INCOMPLETE;
+ unsigned char status;
+ MSDTransfer *transfer = &(commandState->transfer);
+
+ // Check if requested length is zero
+ if (commandState->length == 0) {
+
+ // Nothing to do
+ result = MSDD_STATUS_SUCCESS;
+ }
+ // Initialize command state if needed
+ else if (commandState->state == 0) {
+
+ commandState->state = SBC_STATE_WRITE;
+ }
+
+ // Identify current command state
+ switch (commandState->state) {
+ //-------------------
+ case SBC_STATE_WRITE:
+ //-------------------
+ // Start transfer
+ status = MSDD_Write(&(lun->requestSenseData),
+ commandState->length,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check result code
+ if (status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "RBC_RequestSense: Cannot start sending data\n\r");
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ // Change state
+ commandState->state = SBC_STATE_WAIT_WRITE;
+ }
+ break;
+
+ //------------------------
+ case SBC_STATE_WAIT_WRITE:
+ //------------------------
+ // Check the transfer semaphore
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and finish command
+ transfer->semaphore--;
+
+ if (transfer->status != USBD_STATUS_SUCCESS) {
+
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ result = MSDD_STATUS_SUCCESS;
+ }
+
+ // Update length
+ commandState->length -= transfer->transferred;
+ }
+ break;
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Performs a MODE SENSE (6) command.
+//!
+//! This function operates asynchronously and must be called multiple
+//! times to complete. A result code of MSDDriver_STATUS_INCOMPLETE
+//! indicates that at least another call of the method is necessary.
+//! \param lun Pointer to the LUN affected by the command
+//! \param commandState Current state of the command
+//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
+//! \see MSDLun
+//! \see MSDCommandState
+//------------------------------------------------------------------------------
+static unsigned char SBC_ModeSense6(MSDLun *lun, MSDCommandState *commandState)
+{
+ unsigned char result = MSDD_STATUS_INCOMPLETE;
+ unsigned char status;
+ MSDTransfer *transfer = &(commandState->transfer);
+
+ if (!SBCLunIsReady(lun)) {
+
+ TRACE_INFO("SBC_ModeSense6: Not Ready!\n\r");
+ return MSDD_STATUS_RW;
+ }
+
+ // Check if mode page is supported
+ if (((SBCCommand *) commandState->cbw.pCommand)->modeSense6.bPageCode
+ != SBC_PAGE_RETURN_ALL) {
+
+ return MSDD_STATUS_PARAMETER;
+ }
+
+ // Initialize command state if needed
+ if (commandState->state == 0) {
+
+ commandState->state = SBC_STATE_WRITE;
+ }
+
+ // Check current command state
+ switch (commandState->state) {
+ //-------------------
+ case SBC_STATE_WRITE:
+ //-------------------
+ // Start transfer
+ status = MSDD_Write((void *) &modeParameterHeader6,
+ commandState->length,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check operation result code
+ if (status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "SPC_ModeSense6: Cannot start data transfer\n\r");
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ // Proceed to next state
+ commandState->state = SBC_STATE_WAIT_WRITE;
+ }
+ break;
+
+ //------------------------
+ case SBC_STATE_WAIT_WRITE:
+ //------------------------
+ TRACE_INFO_WP("Wait ");
+
+ // Check semaphore value
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and terminate command
+ transfer->semaphore--;
+
+ if (transfer->status != USBD_STATUS_SUCCESS) {
+
+ TRACE_WARNING(
+ "SPC_ModeSense6: Data transfer failed\n\r");
+ result = MSDD_STATUS_ERROR;
+ }
+ else {
+
+ result = MSDD_STATUS_SUCCESS;
+ }
+
+ // Update length field
+ commandState->length -= transfer->transferred;
+
+ }
+ break;
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Performs a TEST UNIT READY COMMAND command.
+//! \param lun Pointer to the LUN affected by the command
+//! \return Operation result code (SUCCESS, ERROR, INCOMPLETE or PARAMETER)
+//! \see MSDLun
+//------------------------------------------------------------------------------
+static unsigned char SBC_TestUnitReady(MSDLun *lun)
+{
+ unsigned char result = MSDD_STATUS_RW;
+ unsigned char senseKey = SBC_SENSE_KEY_NO_SENSE,
+ addSenseCode = 0,
+ addSenseCodeQual = 0;
+
+ // Check current media state
+ if (lun->status < LUN_CHANGED) {
+
+ TRACE_INFO_WP("Ejc ");
+ senseKey = SBC_SENSE_KEY_NOT_READY;
+ addSenseCode = SBC_ASC_MEDIUM_NOT_PRESENT;
+ }
+ else if (lun->status == LUN_CHANGED) {
+
+ TRACE_INFO_WP("Chg ");
+ senseKey = SBC_SENSE_KEY_UNIT_ATTENTION;
+ addSenseCode = SBC_ASC_NOT_READY_TO_READY_CHANGE;
+ lun->status = LUN_READY;
+ }
+ else {
+
+ switch(lun->media->state) {
+ //-------------------
+ case MED_STATE_READY:
+ //-------------------
+ // Nothing to do
+ TRACE_INFO_WP("Rdy ");
+ result = MSDD_STATUS_SUCCESS;
+ break;
+
+ //------------------
+ case MED_STATE_BUSY:
+ //------------------
+ TRACE_INFO_WP("Bsy ");
+ senseKey = SBC_SENSE_KEY_NOT_READY;
+ break;
+
+ //------
+ default:
+ //------
+ TRACE_INFO_WP("? ");
+ senseKey = SBC_SENSE_KEY_NOT_READY;
+ addSenseCode = SBC_ASC_MEDIUM_NOT_PRESENT;
+ break;
+ }
+ }
+ SBC_UpdateSenseData(&(lun->requestSenseData),
+ senseKey,
+ addSenseCode,
+ addSenseCodeQual);
+
+ return result;
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//! \brief Updates the sense data of a LUN with the given key and codes
+//! \param requestSenseData Pointer to the sense data to update
+//! \param senseKey Sense key
+//! \param additionalSenseCode Additional sense code
+//! \param additionalSenseCodeQualifier Additional sense code qualifier
+//------------------------------------------------------------------------------
+void SBC_UpdateSenseData(SBCRequestSenseData *requestSenseData,
+ unsigned char senseKey,
+ unsigned char additionalSenseCode,
+ unsigned char additionalSenseCodeQualifier)
+{
+ requestSenseData->bSenseKey = senseKey;
+ requestSenseData->bAdditionalSenseCode = additionalSenseCode;
+ requestSenseData->bAdditionalSenseCodeQualifier
+ = additionalSenseCodeQualifier;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Return information about the transfer length and direction expected
+//! by the device for a particular command.
+//! \param command Pointer to a buffer holding the command to evaluate
+//! \param length Expected length of the data transfer
+//! \param type Expected direction of data transfer
+//! \param lun Pointer to the LUN affected by the command
+//------------------------------------------------------------------------------
+unsigned char SBC_GetCommandInformation(void *command,
+ unsigned int *length,
+ unsigned char *type,
+ MSDLun *lun)
+{
+ SBCCommand *sbcCommand = (SBCCommand *) command;
+ unsigned char isCommandSupported = 1;
+
+ // Identify command
+ switch (sbcCommand->bOperationCode) {
+ //---------------
+ case SBC_INQUIRY:
+ //---------------
+ (*type) = MSDD_DEVICE_TO_HOST;
+
+ // Allocation length is stored in big-endian format
+ (*length) = WORDB(sbcCommand->inquiry.pAllocationLength);
+ break;
+
+ //--------------------
+ case SBC_MODE_SENSE_6:
+ //--------------------
+ (*type) = MSDD_DEVICE_TO_HOST;
+ if (sbcCommand->modeSense6.bAllocationLength >
+ sizeof(SBCModeParameterHeader6)) {
+
+ *length = sizeof(SBCModeParameterHeader6);
+ }
+ else {
+
+ *length = sbcCommand->modeSense6.bAllocationLength;
+ }
+ break;
+
+ //------------------------------------
+ case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ //------------------------------------
+ (*type) = MSDD_NO_TRANSFER;
+ break;
+
+ //---------------------
+ case SBC_REQUEST_SENSE:
+ //---------------------
+ (*type) = MSDD_DEVICE_TO_HOST;
+ (*length) = sbcCommand->requestSense.bAllocationLength;
+ break;
+
+ //-----------------------
+ case SBC_TEST_UNIT_READY:
+ //-----------------------
+ (*type) = MSDD_NO_TRANSFER;
+ break;
+
+ //---------------------
+ case SBC_READ_CAPACITY_10:
+ //---------------------
+ (*type) = MSDD_DEVICE_TO_HOST;
+ (*length) = sizeof(SBCReadCapacity10Data);
+ break;
+
+ //---------------
+ case SBC_READ_10:
+ //---------------
+ (*type) = MSDD_DEVICE_TO_HOST;
+ (*length) = WORDB(sbcCommand->read10.pTransferLength)
+ * lun->blockSize * lun->media->blockSize;
+ break;
+
+ //----------------
+ case SBC_WRITE_10:
+ //----------------
+ (*type) = MSDD_HOST_TO_DEVICE;
+ (*length) = WORDB(sbcCommand->write10.pTransferLength)
+ * lun->blockSize * lun->media->blockSize;
+ break;
+
+ //-----------------
+ case SBC_VERIFY_10:
+ //-----------------
+ (*type) = MSDD_NO_TRANSFER;
+ break;
+ #if 0
+ //---------------------
+ case SBC_READ_FORMAT_CAPACITIES:
+ //---------------------
+ (*type) = MSDD_DEVICE_TO_HOST;
+ (*length) = 1;
+ break;
+ #endif
+ //------
+ default:
+ //------
+ isCommandSupported = 0;
+ }
+
+ // If length is 0, no transfer is expected
+ if ((*length) == 0) {
+
+ (*type) = MSDD_NO_TRANSFER;
+ }
+
+ return isCommandSupported;
+}
+
+//------------------------------------------------------------------------------
+//! \brief Processes a SBC command by dispatching it to a subfunction.
+//! \param lun Pointer to the affected LUN
+//! \param commandState Pointer to the current command state
+//! \return Operation result code
+//------------------------------------------------------------------------------
+unsigned char SBC_ProcessCommand(MSDLun *lun,
+ MSDCommandState *commandState)
+{
+ unsigned char result = MSDD_STATUS_INCOMPLETE;
+ SBCCommand *command = (SBCCommand *) commandState->cbw.pCommand;
+
+ // Identify command
+ switch (command->bOperationCode) {
+ //---------------
+ case SBC_READ_10:
+ //---------------
+ TRACE_DEBUG_WP("Read(10) ");
+
+ // Perform the Read10 command
+ result = SBC_Read10(lun, commandState);
+ break;
+
+ //----------------
+ case SBC_WRITE_10:
+ //----------------
+ TRACE_DEBUG_WP("Write(10) ");
+
+ // Perform the Write10 command
+ result = SBC_Write10(lun, commandState);
+ break;
+
+ //---------------------
+ case SBC_READ_CAPACITY_10:
+ //---------------------
+ TRACE_INFO_WP("RdCapacity(10) ");
+
+ // Perform the ReadCapacity command
+ result = SBC_ReadCapacity10(lun, commandState);
+ break;
+
+ //---------------------
+ case SBC_VERIFY_10:
+ //---------------------
+ TRACE_INFO_WP("Verify(10) ");
+
+ // Flush media
+ MED_Flush(lun->media);
+ result = MSDD_STATUS_SUCCESS;
+ break;
+
+ //---------------
+ case SBC_INQUIRY:
+ //---------------
+ TRACE_INFO_WP("Inquiry ");
+
+ // Process Inquiry command
+ result = SBC_Inquiry(lun, commandState);
+ break;
+
+ //--------------------
+ case SBC_MODE_SENSE_6:
+ //--------------------
+ TRACE_INFO_WP("ModeSense(6) ");
+
+ // Process ModeSense6 command
+ result = SBC_ModeSense6(lun, commandState);
+ break;
+
+ //-----------------------
+ case SBC_TEST_UNIT_READY:
+ //-----------------------
+ TRACE_INFO_WP("TstUnitRdy ");
+
+ // Process TestUnitReady command
+ //MED_Flush(lun->media);
+ result = SBC_TestUnitReady(lun);
+ break;
+
+ //---------------------
+ case SBC_REQUEST_SENSE:
+ //---------------------
+ TRACE_INFO_WP("ReqSense ");
+
+ // Perform the RequestSense command
+ result = SBC_RequestSense(lun, commandState);
+ break;
+
+ //------------------------------------
+ case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ //------------------------------------
+ TRACE_INFO_WP("PrevAllowRem ");
+
+ // Check parameter
+ result = command->mediumRemoval.bPrevent ?
+ MSDD_STATUS_PARAMETER : MSDD_STATUS_SUCCESS;
+ break;
+ #if 0
+ //------------------------------------
+ case SBC_READ_FORMAT_CAPACITIES:
+ //------------------------------------
+ TRACE_INFO_WP("RdFmtCap ");
+ if (!SBCLunIsReady(lun)) {
+
+ result = MSDD_STATUS_RW;
+ break;
+ }
+ #endif
+ //------
+ default:
+ //------
+ result = MSDD_STATUS_PARAMETER;
+ }
+
+ return result;
+}
diff --git a/usb/device/massstorage/SBCMethods.h b/usb/device/massstorage/SBCMethods.h new file mode 100644 index 0000000..1ef199e --- /dev/null +++ b/usb/device/massstorage/SBCMethods.h @@ -0,0 +1,111 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+/// !Purpose
+///
+/// SCSI commands implementation.
+///
+/// !Usage
+///
+/// -# After a CBW is received from host, use SBC_GetCommandInformation to check
+/// if the command is supported, and get the command length and type
+/// information before processing it.
+/// -# Then SBC_ProcessCommand can be used to handle a valid command, to
+/// perform the command operations.
+/// -# SBC_UpdateSenseData is used to update the sense data that will be sent
+/// to host.
+//------------------------------------------------------------------------------
+
+#ifndef SBCMETHODS_H
+#define SBCMETHODS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "SBC.h"
+#include "MSDLun.h"
+#include "MSDDStateMachine.h"
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "SBC Command States"
+/// This page lists the possible states of a SBC command.
+///
+/// !States
+/// - SBC_STATE_READ
+/// - SBC_STATE_WAIT_READ
+/// - SBC_STATE_WRITE
+/// - SBC_STATE_WAIT_WRITE
+/// - SBC_STATE_NEXT_BLOCK
+
+/// Start of reading bulk data
+#define SBC_STATE_READ 0x01
+/// Waiting for the bulk data reading complete
+#define SBC_STATE_WAIT_READ 0x02
+/// Read error state
+#define SBC_STATE_READ_ERROR 0x03
+/// Start next read block
+#define SBC_STATE_NEXT_READ 0x04
+/// Start writing bulk data to host
+#define SBC_STATE_WRITE 0x05
+/// Waiting for the bulk data sending complete
+#define SBC_STATE_WAIT_WRITE 0x06
+/// Write error state
+#define SBC_STATE_WRITE_ERROR 0x07
+/// Start next write block
+#define SBC_STATE_NEXT_WRITE 0x08
+/// Start next command block
+#define SBC_STATE_NEXT_BLOCK 0x09
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+void SBC_UpdateSenseData(SBCRequestSenseData *requestSenseData,
+ unsigned char senseKey,
+ unsigned char additionalSenseCode,
+ unsigned char additionalSenseCodeQualifier);
+
+unsigned char SBC_GetCommandInformation(void *command,
+ unsigned int *length,
+ unsigned char *type,
+ MSDLun *lun);
+
+unsigned char SBC_ProcessCommand(MSDLun *lun,
+ MSDCommandState *commandState);
+
+#endif //#ifndef SBCMETHODS_H
+
diff --git a/usb/device/massstorage/massstorage.dir b/usb/device/massstorage/massstorage.dir new file mode 100644 index 0000000..bc793c5 --- /dev/null +++ b/usb/device/massstorage/massstorage.dir @@ -0,0 +1,1005 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB Mass
+/// Storage %device (MSD) - USB Mass Storage demo.
+///
+/// !!!Contents
+///
+/// There are four things for the implement of the USB MSD driver:
+/// - Implement the MSD driver structs and functions for the %device,
+/// to initialize, to handle MSD-specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// %endpoints,
+/// - Create the MSD device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the %device as a USB Mass Storage %device.
+/// - Implement state machine for MSD command/data/status handling.
+/// - Implement storage media interface for MSD disk accessing.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB MSD Driver".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB MSD Driver"
+ This page describes how to use the USB framework to produce a USB MSD driver,
+ which appears as a USB Disk on host.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf">
+ Mass Storage Overview 1.2</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf">
+ Mass Storage Bulk Only 1.0</a>
+ - <a href="http://www.t10.org/scsi-3.htm">SCSI Standards</a>
+ - SCSI Block Commands - 3 (SBC-3)
+ - SCSI Primary Commands - 4 (SPC-4)
+
+ !!!Mass Storage Class Basic
+ This section gives generic details on the MSD class.
+
+ See "USB MSD Basic".
+
+ !!!Mass Storage SCSI Disk
+
+ This section describes how to implement a USB disk by using the MSD class with
+ the SCSI transparent command set and the AT91 USB Framework. For more
+ information about the framework, please refer to the "AT91 USB device
+ framework" application note; details about the USB and the Mass Storage class
+ can be found in the USB specification 2.0 and the MSC Bulk-Only Transport
+ specification 1.0 documents, respectively.
+
+ The software example provided with this document uses the ram disk of the chip
+ as its storage medium, but has been designed in a modular way to allow easy
+ modification for any medium, e.g. internal flash, DataFlash, SD card, external
+ Flash chip.
+
+ !!Architecture
+ The MSD driver is based on framework, See "USB Device Framework Architecture".
+
+ The internal architecture of the Application layer is extended for the
+ following factors:
+ - The Command/Data/Status flow described in "USB MSD Basic" requires the use
+ of a #state machine# for non-blocking operation.
+ - The example software has been designed to be easily extended with support
+ for other media.
+ - The example software has been designed to support multiple LUNs on one or
+ more media.
+
+ \image MSDAppArch.png "Application Layer Architecture"
+
+ !!Descriptors
+ There are no class-specific descriptors for a device using the MSD class with
+ the Bulk-only transport protocol. This section thus only details the values
+ which must be set in the standard descriptors.
+
+ !Device Descriptor
+\code
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor), // bLength: Size of descriptor (18 bytes)
+ USBGenericDescriptor_DEVICE, // bDescriptorType: Device descriptor
+ USBDeviceDescriptor_USB2_00, // bcdUSB: USB 2.00
+ MSDeviceDescriptor_CLASS, // bDeviceClass: 0
+ MSDeviceDescriptor_SUBCLASS, // bDeviceSubClass: 0
+ MSDeviceDescriptor_PROTOCOL, // bDeviceProtocol: 0
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0), // bMaxPacketSize0: Max Size EP0
+ MSDDriverDescriptors_VENDORID, // idVendor: Vendor ID ATMEL (0x03eb)
+ MSDDriverDescriptors_PRODUCTID,// idProduct: Product ID (0x6202)
+ MSDDriverDescriptors_RELEASE, // bcdDevice: 0x0001, Version 0.01
+ 1, // iManufacturer: Manufacturer string (manufacturerDescriptor) index.
+ 2, // iProduct: Product string (productDescriptor) index.
+ 3, // iSerialNumber: Serial number string (serialNumberDescriptor) index.
+ 1 // bNumConfigurations: Device has one possible configuration.
+};
+\endcode
+ Note that the Vendor ID is a special value attributed by the USB-IF
+ organization. The product ID can be chosen freely by the vendor.
+
+ !Configuration Descriptor
+ The descriptors are defined as:
+\code
+const MSDConfigurationDescriptors configurationDescriptorsFS;
+\endcode
+
+ Configuration descriptor
+\code
+// Standard configuration descriptor.
+{
+ sizeof(USBConfigurationDescriptor), // bLength: 9 bytes
+ USBGenericDescriptor_CONFIGURATION, // bDescriptorType: Configuration
+ sizeof(MSDConfigurationDescriptors),// wTotalLength: Length of all
+ 1, // bNumInterface: Configuration has one interface.
+ 1, // bConfigurationValue: This is configuration #1.
+ 0, // iConfiguration: No string descriptor for configuration.
+ BOARD_USB_BMATTRIBUTES, // bmAttributes: Power and remote wakeup
+ USBConfigurationDescriptor_POWER(100) // 100mA max power
+},
+\endcode
+
+ !Interface Descriptor
+ The interface descriptor must indicate several features:
+ - #Mass Storage Device# class code (08h) in the }bInterfaceClass} field
+ - #Data Transport Protocol# code in the }bInterfaceSubclass} field
+ - #Bulk-Only Transport# protocol code (50h) in the }bInterfaceProtocol} field
+ This example uses the SCSI transparent command set (code 06h). This is the
+ most appropriate setting for a Flash %device, given that the RBC command set
+ is not supported by Microsoft Windows.
+\code
+// Mass Storage interface descriptor.
+{
+ sizeof(USBInterfaceDescriptor), // bLength: Size of descriptor(9 bytes)
+ USBGenericDescriptor_INTERFACE, // bDescriptorType: Interface descriptor
+ 0, // bInterfaceNumber: This is interface #0.
+ 0, // bAlternateSetting: This is alternate setting #0.
+ 2, // bNumEndpoints: Interface uses two endpoints.
+ MSInterfaceDescriptor_CLASS, // bInterfaceClass: Mass Storage Device Class
+ MSInterfaceDescriptor_SCSI, // bInterfaceSubClass: SCSI transparent command
+ MSInterfaceDescriptor_BULKONLY,// bInterfaceProtocol: Bulk-Only transport
+ 0 // iInterface: No string descriptor for interface.
+},
+\endcode
+
+ !Endpoint Descriptors
+ No special requirements on these apart from being Bulk-IN and Bulk-OUT.
+\code
+// Bulk-OUT endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor), // bLength: 7 bytes
+ USBGenericDescriptor_ENDPOINT, // bDescriptorType: Endpoint descriptor
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ MSDDriverDescriptors_BULKOUT), // bEndpointAddress: OUT 0x01
+ USBEndpointDescriptor_BULK, // bmAttributes: Bulk endpoint
+ MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
+ USBEndpointDescriptor_MAXBULKSIZE_FS), // wMaxPacketSize: 64 bytes
+ 0 // bInterval: Must be 0 for full-speed Bulk endpoints.
+},
+// Bulk-IN endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor), // bLength: 7 bytes
+ USBGenericDescriptor_ENDPOINT, // bDescriptorType: Endpoint descriptor
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ MSDDriverDescriptors_BULKIN), // bEndpointAddress: IN 0x82
+ USBEndpointDescriptor_BULK, // bmAttributes: Bulk endpoint
+ MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
+ USBEndpointDescriptor_MAXBULKSIZE_FS), // wMaxPacketSize: 64
+ 0 // bInterval: Must be 0 for full-speed Bulk endpoints.
+}
+\endcode
+
+ !String descriptors
+ Several descriptors can be commented with a String descriptor. The latter are
+ completely optional and do not influence the detection of the device by the
+ operating system. Whether or not to include them is entirely up to the
+ programmer.
+
+ There is one exception to this rule when using the MSD class. According to the
+ specification, there must be a Serial Number string. It must contains at least
+ 12 characters, and these characters must only be either letters (a-z, A-Z) or
+ numbers (0-9). This cause no problem for the driver in practice, but this is a
+ strict requirement for certification. Also remember that string descriptors
+ use the Unicode format.
+
+ See manufacturerDescriptor, productDescriptor, serialNumberDescriptor.
+
+ !!Class-specific Requests
+ There are two Mass Storage-specific requests:
+ - GetMaxLUN
+ - Bulk-Only Mass Storage Reset
+
+ Standard requests can be forwarded to the USBDDriver_RequestHandler, with one
+ exception: #CLEAR_FEATURE#. This is necessary for Reset Recovery sequence.
+
+ !ClearFeature
+ As previously stated, the CLEAR_FEATURE request must be handled in a
+ particular way, depending on whether or not the device is waiting for a Reset
+ Recovery sequence. If it is, then CLEAR_FEATURE requests to unhalt a Bulk
+ endpoint must be discarded.
+
+ In the example software, this behavior is indicated by a boolean field in the
+ driver structure, named waitResetRecovery. The handler only has to check this
+ field value to decide whether to forward the request to the standard handler
+ or to discard it.
+\code
+// Handle requests
+switch (USBGenericRequest_GetRequest(request)) {
+//---------------------
+case USBGenericRequest_CLEARFEATURE:
+//---------------------
+
+ switch (USBFeatureRequest_GetFeatureSelector(request)) {
+
+ //---------------------
+ case USBFeatureRequest_ENDPOINTHALT:
+ //---------------------
+
+ // Do not clear the endpoint halt status if the device is waiting
+ // for a reset recovery sequence
+ if (!msdDriver.waitResetRecovery) {
+
+ // Forward the request to the standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+ }
+
+ USBD_Write(0, 0, 0, 0, 0);
+ break;
+
+ //------
+ default:
+ //------
+ // Forward the request to the standard handler
+ USBDDriver_RequestHandler(&usbdDriver, request);
+ }
+ break;
+}
+\endcode
+
+ !GetMaxLUN
+ Usually, the first request issued by the host right after the enumeration
+ phase will be a GET_MAX_LUN request. It enables it to discover how many
+ different logical units the device has; each of these LUNs can then be queried
+ in turn by the host when needed.
+
+ After the request is received by the device, it should return one byte of data
+ indicating the maximum Logical Unit Number (LUN). It is equal to the number of
+ LUNs used by the device minus one. For example, a device with three LUNs shall
+ return a GET_MAX_LUN value of two.
+
+ Sending this byte is done by calling the USBD_Write method on Control endpoint
+ 0. Note that the data must be held in a permanent buffer (since the transfer
+ is asynchronous); in the software provided with this application note, a
+ dedicated field is used in the driver structure (MSDDriver) to store this
+ value.
+
+ In addition due to the }Mass Storage Bulk-Only Transport} specification the
+ }wValue} should be 0, }wLength} should be 1, }wIndex} should be the interface
+ number also 0. A request which does not comply to these requirements must be
+ STALLed.
+\code
+//-------------------
+case MSD_GET_MAX_LUN:
+//-------------------
+ // Check request parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == 0)
+ && (request->wLength == 1)) {
+ USBD_Write(0, &(msdDriver.maxLun), 1, 0, 0);
+ }
+ else {
+ USBD_Stall(0);
+ }
+ break;
+\endcode
+
+ !Bulk-Only Mass Storage Reset
+ The host issues #RESET# requests to return the MSD driver of the device to its
+ initial state, i.e., ready to receive a new command. However, this request
+ does not impact the USB controller state; in particular, endpoints must not be
+ reset. This means the data toggle bit must not be altered, and Halted endpoint
+ must not be returned to a normal state. After processing the reset, the device
+ must return a Zero-Length Packet (ZLP) to acknowledge the SETUP transfer.
+
+ Like GET_MAX_LUN, this request must be issued with specific parameters -
+ wValue, wIndex and wLength should be zero. A request which does not have valid
+ values in its field must be acknowledged with a STALL handshake from the
+ %device.
+
+ The handler for this request must return the state machine to its initial state.
+\code
+//-----------------------
+case MSD_BULK_ONLY_RESET:
+//-----------------------
+ // Check parameters
+ if ((request->wValue == 0)
+ && (request->wIndex == 0)
+ && (request->wLength == 0)) {
+
+ // Reset the MSD driver
+ MSDDriver_Reset();
+ USBD_Write(0, 0, 0, 0, 0);
+ }
+ else {
+ USBD_Stall(0);
+ }
+ break;
+\endcode
+
+ !!State Machine
+ ...
+
+ !Rationale
+ A state machine is necessary for #non-blocking# operation of the driver. As
+ previously stated, there are three steps when processing a command:
+ - Reception of the CBW
+ - Processing of the command (with data transfers if required)
+ - Emission of the CSW
+
+ Without a state machine, the program execution would be stopped at each step
+ to wait for transfers completion or command processing. For example, reception
+ of a CBW does not always happen immediately (the host does not have to issue
+ commands regularly) and can block the system for a long time.
+
+ Developing an asynchronous design based on a state machine is made easier when
+ using Atmel "AT91 USB device framework", as most methods are asynchronous. For
+ example, a write operation (using the USBD_Write function) returns
+ immediately; a callback function can then be invoked when the transfer
+ actually completes.
+
+ !States
+ Apart from the three states corresponding to the command processing flow (CBW,
+ command processing and CSW), two more can be identified. The
+ reception/emission of CBW/CSW will be broken down into two different states:
+ the first state is used to issue the read/write operation, while the second
+ one waits for the transfer to finish. This can be done by monitoring a
+ "transfer complete" flag which is set using a callback function.
+
+ In addition, some commands can be quite complicated to process: they may
+ require several consecutive data transfers mixed with media access. Each
+ command thus has its own second-tier state machine. During execution of a
+ command, the main state machine remains in the "processing" state, and
+ proceeds to the next one (CSW emission) only when the command is complete.
+
+ Here is the states list:
+ - MSDDriver_STATE_READ_CBW: Start of CBW reception
+ (initial state after reset)
+ - MSDDriver_STATE_WAIT_CBW: Waiting for CBW reception
+ - MSDDriver_STATE_PROCESS_CBW: Command processing
+ - MSDDriver_STATE_SEND_CSW: Start of CSW emission
+ - MSDDriver_STATE_WAIT_CSW: Waiting for CSW emission
+
+ A single function, named MSDDriver_StateMachine, is provided by the driver. It
+ must be called regularly during the program execution. The following
+ subsections describe the actions that must be performed during each state.
+
+ \image MSDDriverStates.png "MSD Driver State Machine"
+
+ #MSDDriver_STATE_READ_CBW#
+
+ As said previously, this state is used to start the reception of a new Command
+ Block Wrapper. This is done using the USB_Read method of the USB framework.
+ The result code of the function is checked for any error; the
+ USB_STATUS_SUCCESS code indicates that the transfer has been successfully
+ started.
+\code
+//----------------------
+case MSDDriver_STATE_READ_CBW:
+//----------------------
+ // Start the CBW read operation
+ transfer->semaphore = 0;
+ status = USBD_Read(MSDDriverDescriptors_BULKOUT,
+ cbw,
+ MSD_CBW_SIZE,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check operation result code
+ if (status == USBD_STATUS_SUCCESS) {
+
+ // If the command was successful, wait for transfer
+ msdDriver.state = MSDDriver_STATE_WAIT_CBW;
+ }
+ break;
+\endcode
+ A callback function to invoke when the transfer is complete is provided to the
+ USBD_Read method, to update a MSDTransfer structure. This structure
+ indicates the transfer completion, the returned result code and the number of
+ transferred and remaining bytes.
+\code
+typedef struct {
+ unsigned int transferred; //!< Number of bytes transferred
+ unsigned int remaining; //!< Number of bytes not transferred
+ unsigned char semaphore; //!< Semaphore to indicate transfer completion
+ unsigned char status; //!< Operation result code
+} MSDTransfer;
+\endcode
+ The callback function is trivial and thus not listed here.
+
+ #MSDDriver_STATE_WAIT_CBW#
+
+ The first step here is to monitor the }semaphore} field of the MSDTransfer
+ structure (see above); this will enable detection of the transfer end. Please
+ note that this field must be declared as volatile in C, or accesses to it
+ might get optimized by the compiler; this can result in endless loops.
+
+ If the transfer is complete, then the result code must be checked to see if
+ there was an error. If the operation is successful, the state machine can
+ proceed to command processing. Otherwise, it returns to the READ_CBW state.
+\code
+//----------------------
+case MSDDriver_STATE_WAIT_CBW:
+//----------------------
+ // Check transfer semaphore
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and terminate transfer
+ transfer->semaphore--;
+
+ // Check if transfer was successful
+ if (transfer->status == USBD_STATUS_SUCCESS) {
+
+ // Process received command
+ msdDriver.state = MSDDriver_STATE_PROCESS_CBW;
+ }
+ else if (transfer->status == USBD_STATUS_RESET) {
+
+ msdDriver.state = MSDDriver_STATE_READ_CBW;
+ }
+ else {
+
+ msdDriver.state = MSDDriver_STATE_READ_CBW;
+ }
+ }
+ break;
+\endcode
+
+ #MSDDriver_STATE_PROCESS_CBW#
+
+ Once the CBW has been received, its validity must be checked. A CBW is not
+ valid if:
+ - it has not been received right after a CSW was sent or a reset occured or
+ - it is not exactly 31 bytes long or
+ - its signature field is not equal to 43425355h
+
+ The state machine prevents the first case from happening, so only the two
+ other cases have to be verified.
+
+ The number of bytes transferred during a USBD_Read operation is passed as an
+ argument to the callback function, if one has been specified. As stated
+ previously, such a function is used to fill a MSDTransfer structure.
+ Therefore, it is trivial to check that the CBW is indeed 31 bytes by verifying
+ that the number of bytes transferred is 31, and that there are no remaining
+ bytes. The following table illustrates the three cases which may happen:
+||Number of bytes transferred||Number of bytes remaining||Meaning
+|transferred<31|remaining==0|CBW is too short
+|transferred==31|remaining>0|CBW is too long
+|transferred==31|remaining==0|CBW length is correct
+
+ Checking the signature is simply done by comparing the dCBWSignature field
+ with the expected value (43425355h).
+
+ If the CBW is not valid, then the device must immediately halt both Bulk
+ endpoints, to STALL further traffic from the host. In addition, it should stay
+ in this state until a Reset Recovery is performed by the host. This is done by
+ setting the waitResetRecovery flag in the MSDDriver structure. Finally, the
+ CSW status is set to report an error, and the state machine is returned to
+ MSDDriver_STATE_READ_CBW.
+
+ Otherwise, if the CBW is correct, then the command can be processed. Remember
+ the CBW tag must be copied regardless of the validity of the CBW.
+
+ Note that these steps are only necessary for a new command (remember commands
+ are asynchronous and are carried out in several calls, so a check can be
+ performed to avoid useless processing. A value of zero for the internal
+ command state indicates a new command.
+\code
+//-------------------------
+case MSDDriver_STATE_PROCESS_CBW:
+//-------------------------
+ // Check if this is a new command
+ if (commandState->state == 0) {
+
+ // Copy the CBW tag
+ csw->dCSWTag = cbw->dCBWTag;
+
+ // Check that the CBW is 31 bytes long
+ if ((transfer->transferred != MSD_CBW_SIZE) ||
+ (transfer->remaining != 0)) {
+
+ // Wait for a reset recovery
+ msdDriver.waitResetRecovery = 1;
+
+ // Halt the Bulk-IN and Bulk-OUT pipes
+ USBD_Halt(MSDDriverDescriptors_BULKOUT);
+ USBD_Halt(MSDDriverDescriptors_BULKIN);
+
+ csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
+ msdDriver.state = MSDDriver_STATE_READ_CBW;
+
+ }
+ // Check the CBW Signature
+ else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) {
+
+ // Wait for a reset recovery
+ msdDriver.waitResetRecovery = 1;
+
+ // Halt the Bulk-IN and Bulk-OUT pipes
+ USBD_Halt(MSDDriverDescriptors_BULKOUT);
+ USBD_Halt(MSDDriverDescriptors_BULKIN);
+
+ csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
+ msdDriver.state = MSDDriver_STATE_READ_CBW;
+ }
+ else {
+
+ // Pre-process command
+ MSDDriver_PreProcessCommand();
+ }
+ }
+
+ // Process command
+ if (csw->bCSWStatus == MSDDriver_STATUS_SUCCESS) {
+
+ if (MSDDriver_ProcessCommand()) {
+
+ // Post-process command if it is finished
+ MSDDriver_PostProcessCommand();
+ msdDriver.state = MSDDriver_STATE_SEND_CSW;
+ }
+ }
+
+ break;
+\endcode
+
+ #MSDDriver_STATE_SEND_CSW#
+
+ This state is similar to MSDDriver_STATE_READ_CBW, except that a write
+ operation is performed instead of a read and the CSW is sent, not the CBW. The
+ same callback function is used to fill the transfer structure, which is
+ checked in the next state:
+\code
+//----------------------
+case MSDDriver_STATE_SEND_CSW:
+//----------------------
+ // Set signature
+ csw->dCSWSignature = MSD_CSW_SIGNATURE;
+
+ // Start the CSW write operation
+ status = USBD_Write(MSDDriverDescriptors_BULKIN,
+ csw,
+ MSD_CSW_SIZE,
+ (TransferCallback) MSDDriver_Callback,
+ (void *) transfer);
+
+ // Check operation result code
+ if (status == USBD_STATUS_SUCCESS) {
+
+ // Wait for end of transfer
+ msdDriver.state = MSDDriver_STATE_WAIT_CSW;
+ }
+ break;
+\endcode
+
+ #MSDDriver_STATE_WAIT_CSW#
+
+ Again, this state is very similar to MSDDriver_STATE_WAIT_CBW. The only
+ difference is that the state machine is set to MSDDriver_STATE_READ_CBW
+ regardless of the operation result code:
+\code
+//----------------------
+case MSDDriver_STATE_WAIT_CSW:
+//----------------------
+ // Check transfer semaphore
+ if (transfer->semaphore > 0) {
+
+ // Take semaphore and terminate transfer
+ transfer->semaphore--;
+
+ // Read new CBW
+ msdDriver.state = MSDDriver_STATE_READ_CBW;
+ }
+ break;
+\endcode
+
+ !!Media
+
+ USB MSD Media access is three-level abstraction.
+
+ \image MSDMediaArch.png "Media Architecture"
+
+ The bottom level is the specific driver for each media type (See memories).
+
+ In the middle, a structure Media is used to hide which specific driver a media
+ instance is using. This enables transparent use of any media driver once it
+ has been initialized (See _Media).
+
+ Finally, a LUN abstraction is made over the media structure to allow multiple
+ partitions over one media. This also makes it possible to place the LUN at any
+ address and use any block size. When performing a write or read operation on a
+ LUN, it forwards the operation to the underlying media while translating it to
+ the correct address and length.
+
+ !Media Drivers
+ A media driver must provide several functions for:
+ - Reading data from the media
+ - Writing data on the media
+ - Handling interrupts on the media
+ The last function may be empty if the media does not require interrupts for
+ asynchronous operation, or if synchronous operation produces an acceptable
+ delay.
+
+ In addition, it should also define a function for initializing a Media
+ structure with the correct values, as well as perform the necessary step for
+ the media to be useable.
+
+ For the drivers see:
+ - MEDSdram.h: }Internal Flash Driver}
+ - MEDFlash.h: }SDRAM disk driver}
+
+ !!SCSI Commands
+
+ The example software described in this application note uses SCSI commands
+ with the MSD class, since this is the most appropriate setting for a Flash
+ device. This section details how SCSI commands are processed.
+
+ !Documents
+
+ There are several documents covering SCSI commands. In this application note,
+ the reference document used is SCSI Block Commands - 3 (SBC-3). However, it
+ makes many references to another SCSI document, SCSI Primary Commands - 4
+ (SPC-4). Both are needed for full details on required commands.
+
+ !Endianness
+
+ SCSI commands use the big-endian format for storing word- and double word-
+ sized data. This means the Most Significant Bit (MSB) is stored at the
+ lowest address, and the Least Significant Bit (LSB) at the highest one.
+
+ On ARM Thumb microcontrollers, the endianness of the core is selectable.
+ However, the little-endian mode is most often used. Therefore, SCSI command
+ data must be converted before being usable. This is done by declaring
+ word- and dword-sized fields as byte arrays, and then using a macro for
+ loading or storing data. Several of them are available in the provided
+ software:
+ - Load
+ - WORDB: Converts a big-endian word value to little-endian
+ - DWORDB: Converts a big-endian double-word value to little-endian
+ - Store
+ - STORE_WORDB: Stores a little-endian word value in big-endian format
+ - STORE_DWORDB: Stores a little-endian double-word value in big-endian format
+
+ !Sense Data
+
+ When an error happens during the execution of a command, it is recorded by the
+ device. The host may then issue a Request Sense command to retrieve
+ #Sense Data#, i.e., information about previous errors.
+
+ While the sense data structure has many fields, only three are really
+ important. The first one is the Sense Key. It indicates the result of the last
+ command performed: success, media not ready, hardware error, etc. Two other
+ fields can then be specified to give a more accurate description of the
+ problem. They are named }Additional Sense Code} and }Additional Sense Code
+ Qualifier}.
+
+ In the example application, each LUN has its own sense data. It is updated
+ during command execution if there is any error.
+
+ !Commands
+
+ The SBC-3 specification gives a list of mandatory and optional commands that
+ are relevant for a block device (like a Flash drive). In practice, only a
+ subset of the mandatory commands is effectively used by operating systems;
+ conversely, several commands which are supposed to be optional are required.
+ The software provided with this application note implements the following list
+ of commands:
+ - SBC-3
+ - Prevent/Allow Medium Removal
+ - Read (10)
+ - Read Capacity (10)
+ - Verify (10)
+ - Write (10)
+ - SPC-4
+ - Inquiry
+ - Mode Sense (6)
+ - Request Sense
+ - Test Unit Ready
+ The commands are actually processed in SBC_ProcessCommand.
+
+ }Internal State Machine}
+
+ As previously stated, most commands have an internal state machine to prevent
+ blocking the whole system during a data transfer (on the USB or when accessing
+ a media). A result code is used to indicate that the corresponding function
+ must be called again for the command to complete (MSDDriver_STATUS_SUCCESS).
+
+ A command state structure is used by the driver to record several parameters
+ during command processing:
+\code
+typedef struct {
+
+ MSDTransfer transfer; //!< Current transfer status
+ MSCbw cbw; //!< Received CBW
+ MSCsw csw; //!< CSW to send
+ unsigned char state; //!< Current command state
+ unsigned char postprocess; //!< Actions to perform when command is complete
+ unsigned int length; //!< Remaining length of command
+
+} MSDCommandState;
+\endcode
+
+ Note that the }state} field must be initialized when the command is first
+ called. A value of 0 means that no command is currently being executed.
+
+ For the commands descriptions and implementation, please reffer to the SCSI
+ spec. and source code.
+
+ Functions to handle SCSI commands:
+ - SBC_Inquiry
+ - SBC_Read10
+ - SBC_ReadCapacity10
+ - SBC_RequestSense
+ - SBC_TestUnitReady
+ - SBC_Write10
+ - SBC_ModeSense6
+
+ !Command Processing
+
+ }Flow}
+
+ Command processing is actually divided into three phases in the example
+ software:
+ - Pre-processing: MSDDriver_PreProcessCommand
+ - Processing: MSDDriver_ProcessCommand
+ - Post-processing: MSDDriver_PostProcessCommand
+
+ }The Thirteen Cases}
+
+ There are basically three actions that should be performed depending on the
+ case:
+ - STALL the Bulk-IN endpoint
+ - STALL the Bulk-OUT endpoint
+ - Report a Phase Error in the CSW
+
+ The table below lists all cases along with the actions which must be taken
+ after the command, including the correct length/direction of the transfer. The
+ following notation is used to characterize host and %device expectations:
+
+ Data %Transfer Characterization
+||Notation||Meaning||Notation||Meaning
+|Hn|Host expects no data transfer|Dn|Device expects no data transfer
+|Hi|Host expects to #receive# data|Di|Device expects to #send# data
+|Ho|Host expects to #send# data|Do|Device expects to #receive# data
+|Lh|Length of data expected by the host|Ld|Length of data expected by the %device
+
+|Hx=Dx|Host and %device agree on transfer length and direction (x is either n, i or o)
+|Hx>Dx|Host and %device agree on transfer direction, host expects a larger transfer than %device
+|Hx<Dx|Host and %device agree on transfer direction, %device expects a larger transfer than host
+|Hx<>Dx|Host and %device disagree on transfer direction
+
+ The Thirteen Cases
+||\#||Case||Length||Residue||Direction||STALL IN?||STALL OUT?||Phase Error?
+|1|Hn = Dn|0|0|Irrelevant| | |
+|2|Hn < Di|0|Ld - Lh|Irrelevant| | |X
+|3|Hn < Do|0|Ld - Lh|Irrelevant| | |X
+|4|Hi > Dn|0|Lh|Irrelevant|X| |
+|5|Hi > Di|Ld|Lh - Ld|In|X| |
+|6|Hi = Di|Ld|0|In| | |
+|7|Hi < Di|Lh|Ld - Lh|In| | |X
+|8|Hi <> Do|0|0|Irrelevant|X| |X
+|9|Ho > Dn|0|Lh|Irrelevant| |X|
+|10|Ho <> Di|0|0|Irrelevant| |X|X
+|11|Ho > Do|Ld|Lh - Ld|Out| |X|
+|12|Ho = Do|Ld|0|Out| | |
+|13|Ho < Do|Lh|Lh - Ld|Out| | |X
+
+ !!Main Application
+ After the MSD driver and the media have been initialized using the
+ corresponding functions, the only requirement for the main application is to
+ regularly call the state machine function. This is necessary for processing
+ received commands in a fully asynchronous way.
+
+ The application is otherwise free of doing any other task; for example, it
+ could implement a filesystem and a serial port interface to be accessed with a
+ standard terminal. An MP3 player could also continue playing a song while its
+ memory is accessed like an external hard disk.
+
+ \image MSDDriverClasses.png "Driver Class Diagram"
+
+*/
+/**
+ \page "USB MSD Basic"
+
+ This page gives generic details on the MSD class.
+
+ !!!Purpose
+
+ The MSD class defines how devices such as a hard disk, a USB floppy disk drive
+ or a disk-on-key shall operate on the USB. These devices are referred to as
+ mass storage devices, since they usually offer a high storage capacity. When
+ plugged to a PC, a %device complying to the MSD specification is accessed like
+ any other disk on the system.
+
+ In practice, the specification only defines a way to wrap existing data
+ transfer protocols, such as SCSI or the Reduced Block Commands (RBC) set. A
+ list of the supported protocols and their uses will be given in the following
+ section.
+
+ !!!Data Transfer Protocols
+
+ The }Mass Storagae Class Specification Overview 1.2} supports the following
+ set of %devices:
+
+ Protocols for MSD %devices
+||Subclass Code||Command Block Spec.||Used by
+|01h|Reduced Block Commands(RBC)|Flash %devices
+|02h|SFF-8020i, MMC-2|CD & DVD %devices
+|03h|QIC-157|Tape %devices
+|04h|UFI|Floppy disk drives
+|05h|SFF-8070i|Floppy disk drives
+|06h|SCSI transparent command set|Any
+
+ The SCSI transparent command set comprises all SCSI-related specifications,
+ such as SCSI Primary Commands (SPC), SCSI Block Commands (SBC), and so on. A
+ command will be issued by the host to determine exactly with which standard
+ the %device is compliant.
+
+ The protocol used by the %device is specified in its Interface descriptor, in
+ the }bInterfaceSubclass} field.
+
+ !!!Transfer Protocols
+
+ There are actually two different transport protocols for the MSD class:
+ - Control/Bulk/Interface (CBI) transport
+ - Bulk-Only Transport (BOT)
+
+ These two methods are described in two separate stand-alone documents. CBI can
+ be considered obsolete and is being completely replaced by BOT. It was
+ originally targeted at full-speed floppy disk drives. Therefore, the rest of
+ this document will talk about Bulk-Only Transport exclusively.
+
+ Transport Protocol Codes
+||bInterfaceProtocol||Protocol Implementation
+|00h|Control/Bulk/Interrupt protocol (with command completion interrupt)
+|01h|Control/Bulk/Interrupt protocol (without command completion interrupt)
+|50h|Bulk-only transport
+
+ !!!Architecture
+ ...
+
+ !!Interfaces & Endpoints
+
+ An MSD %device only needs one single interface. The bInterfaceClass field of
+ the interface descriptor should be set to MSD class code (0x08), the
+ corresponding data transfer protocol code in the }bInterfaceSubclass} field
+ and transport protocol code in the }bInterfaceProtocol} field can be found in
+ the tables on above.
+
+ Exactly three %endpoints (when using the Bulk-Only Transport protocol) are
+ necessary for MSD %devices.
+
+ The first one is the Control endpoint 0, and is used for class-specific
+ requests and for clearing Halt conditions on the other two %endpoints.
+ Endpoints are halted in response to errors and host bad behavior during data
+ transfers, and the CLEAR_FEATURE request is consequently used to return them
+ to a functional state.
+
+ The other two %endpoints, which are of type Bulk, are used for transferring
+ commands and data over the bus. There must be one Bulk-IN and one Bulk-OUT
+ endpoint.
+
+ \image MSDDriverArch.png "Mass Storage Device Driver Architecture"
+
+ !!Class-Specific Descriptors
+ No class-specific descriptors for an MSD %device using the Bulk-only transfport
+ protocol.
+
+ !!Class-Specific Requests
+ Two class specific requests should be handled.
+
+ !GetMaxLUN
+ A %device can feature one or more Logical Unit (LU). Each of these units will
+ be treated as a separate disk when plugged to a computer. A %device can have up
+ to 15 logical units.
+
+ The GET_MAX_LUN request is issued by the host to determine the maximum Logical
+ Unit Number (LUN) supported by the %device. This is not equivalent to the
+ number of LU on the %device; since units are numbered starting from 0, a %device
+ with 5 LUs should report a value of 4, which will be the index of the fifth
+ unit.
+
+ Optionally, a %device with only one LUN may STALL this request instead of
+ returning a value of zero.
+
+ !Bulk-Only Mass Storage Reset
+ This request is used to reset the state of the %device and prepare it to
+ receive commands and data. Note that the data toggle bits must not be altered
+ by a RESET command; same for the Halt state of %endpoints, i.e., halted
+ %endpoints must not be reset to a normal state.
+
+ !!Command/Data/Status
+ Each MSD transaction is divided into three steps:
+ - Command stage
+ - Data stage (optional)
+ - Status stage
+
+ During the command stage, a Command Block Wrapper (CBW) is transmitted by the
+ host to the %device. The CBW describes several parameters of the transaction
+ (direction, length, LUN) and carries a variable-length command block. The
+ command block contains data in the format defined by the transfer protocol
+ used by the %device.
+
+ Command Block Wrapper Data Format
+||Offset||Field Name||Length||Comment
+|0|dCBWSignature|4 bytes|Signature to identify CBW, must be 43425355h
+|4|dCBWTag|4 bytes|Tag sent by the host, echoed in the CSW
+|8|dCBWTransferLength|4 bytes|Length of transfer during the data stage
+|12|bmCBWFlags|1 byte|Bits 0-6: Reserved/obsolete\n
+ Bit 7: Transfer direction (0 = OUT, 1 = IN)
+|13|bCBWLUN|1 byte|Bits 0-3: LUN to which the command is sent\n
+ Bits 4-7: Reserved
+|14|bCBWCBLength|1 byte|Bits 0-5: Length of command block in bytes\n
+ Bits 6-7: Reserved
+|15|CBWCB|0-16 bytes|Command block to be executed by the %device
+
+ After the %device has received and interpreted the command, an optional data
+ stage may take place if the command requires it. During this step, data is
+ transferred either to or from the %device depending on the command, in several
+ IN/OUT transfers.
+
+ Once the data stage is complete, the host issues a final IN request on the
+ Bulk-IN endpoint of the %device to request the Command Status Wrapper (CSW).
+ The CSW is used to report correct or incorrect execution of the command, as
+ well as indicating the length of remaining data that has not been transferred.
+
+ Command Status Wrapper
+||Offset||Field Name||Length||Comment
+|0|dCSWSignature|4 bytes|Signature to identify CSW, must be 53425355h
+|4|dCSWTag|4 bytes|Copy of previous CBW tag
+|8|dCSWDataResidue|4 bytes|Difference between expected and real transfer length
+|12|bCSWStatus|1 byte|Indicates the success or failure of the command
+
+ These steps are all performed on the two Bulk %endpoints, and do not involve
+ Control endpoint 0 at all.
+
+ !!Reset Recovery
+ When severe errors occur during command or data transfers (as defined in the
+ }Mass Storage Bulk-only Transport 1.0} document), the %device must halt both
+ Bulk %endpoints and wait for a #Reset Recovery# procedure. The Reset Recovery
+ sequence goes as follows:
+ - The host issues a Bulk-Only Mass Storage Reset request
+ - The host issues two #CLEAR_FEATURE# requests to unhalt each endpoint
+
+ A %device waiting for a Reset Recovery must not carry out CLEAR_FEATURE
+ requests trying to unhalt either Bulk endpoint until after a Reset request has
+ been received. This enables the host to distinguish between severe and minor
+ errors.
+
+ The only major error defined by the Bulk-Only Transport standard is when a CBW
+ is not valid. This means one or more of the following:
+ - The CBW is not received after a CSW has been sent or a reset.
+ - The CBW is not exactly 31 bytes in length.
+ - The dCBWSignature field of the CBW is not equal to 43425355h.
+
+ !!!Host Drivers
+ Almost all operating systems now provide a generic driver for the MSD class.
+ However, the set of supported data transfer protocols may vary. For example,
+ Microsoft Windows does not currently support the Reduced Block Command set.
+
+*/
diff --git a/usb/host/core/USBH.h b/usb/host/core/USBH.h new file mode 100644 index 0000000..7836619 --- /dev/null +++ b/usb/host/core/USBH.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \unit
+///
+/// !!!Purpose
+///
+/// Collection of methods for using the USB device controller on AT91
+/// microcontrollers.
+///
+/// !!!Usage
+///
+/// Please refer to the corresponding application note.
+/// - "AT91 USB device framework"
+/// - "USBD API" . "USBD API Methods"
+//------------------------------------------------------------------------------
+
+#ifndef USBH_H
+#define USBH_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <memories/Media.h>
+//#include <usb/common/core/USBEndpointDescriptor.h>
+//#include <usb/common/core/USBGenericRequest.h>
+#include <usb/host/ohci/ohci.h>
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void USBH_Init(OHCI_HCCA* pHCCA);
+extern void USBH_ResetPort(unsigned char portNumber);
+extern unsigned char USBH_IsDeviceConnectedOnPort(unsigned char portNumber);
+extern void USBH_program(unsigned int* pBHED, unsigned int* pBCED, OHCI_HCCA* pHCCA);
+extern void USBH_enablingPort(void);
+
+
+#endif //#ifndef USBD_H
+
diff --git a/usb/host/core/USB_UHP.c b/usb/host/core/USB_UHP.c new file mode 100644 index 0000000..59c3b4c --- /dev/null +++ b/usb/host/core/USB_UHP.c @@ -0,0 +1,223 @@ +/* ----------------------------------------------------------------------------
+ * 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 <board.h>
+#include <pio/pio.h>
+#include <utility/trace.h>
+#include <stdio.h>
+#include "USBH.h"
+#include <usb/host/ohci/ohci.h>
+
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// HcFmInterval Register:
+/// FrameInterval specifies the interval between 2 consecutive SOFs in bit times
+/// 1/12 = 0,08333333
+/// 1(ms) / 0,0833333 = 12
+/// FrameInterval = 12x1000 = 12000
+#define FRAMEINTERVAL 12000
+/// FSLargestDataPacket
+/// This field specifies a value which is loaded into the Largest
+/// Data Packet Counter at the beginning of each frame.
+
+/// overhead.
+/// The value of MAXIMUM_OVERHEAD below is 210 bit times.
+#define MAXIMUM_OVERHEAD 210
+/// FSLargestDataPacket initializes a counter within the Host Controller that is
+/// used to determine if a transaction on USB can be completed before EOF
+/// processing must start.
+/// It is a function of the new FrameInterval and is calculated by subtracting
+/// from FrameInterval the maximum number of bit times for transaction overhead
+/// on USB and the number of bit times needed for EOF processing, then
+/// multiplying the result by 6/7 to account for the worst case bit stuffing
+#define FSLARGESTDATAPACKET (((FRAMEINTERVAL-MAXIMUM_OVERHEAD) * 6) / 7)
+#define OHCI_FMINTERVAL ((FSLARGESTDATAPACKET << 16) | FRAMEINTERVAL)
+
+/// HcPeriodicStart Register
+// The HcPeriodicStart register has a 14-bit programmable value which
+// determines when is the earliest time HC should start processing the
+// periodic list.
+/// Set HcPeriodicStart to a value that is 90% of the value in FrameInterval
+/// field of the HcFmInterval register.
+#define OHCI_PRDSTRT (FRAMEINTERVAL*90/100)
+
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+#ifdef AT91C_BASE_UHPHS_OHCI
+#define AT91C_ID_UHP AT91C_ID_UHPHS
+#define AT91C_BASE_UHP AT91C_BASE_UHPHS_OHCI
+#define UHP_HcRhPortStatus UHPHS_OHCI_HcRhPortStatus
+#define UHP_HcControlHeadED UHPHS_OHCI_HcControlHeadED
+#define UHP_HcControlCurrentED UHPHS_OHCI_HcControlCurrentED
+#define UHP_HcBulkDoneHead UHPHS_OHCI_HcBulkDoneHead
+#define UHP_HcControl UHPHS_OHCI_HcControl
+#define UHP_HcRhStatus UHPHS_OHCI_HcRhStatus
+#define UHP_HcHCCA UHPHS_OHCI_HcHCCA
+#define UHP_HcFmInterval UHPHS_OHCI_HcFmInterval
+#define UHP_HcPeriodicStart UHPHS_OHCI_HcPeriodicStart
+#endif
+
+//------------------------------------------------------------------------------
+/// Enable UHP clock
+//------------------------------------------------------------------------------
+static inline void UHP_EnablePeripheralClock(void)
+{
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UHP);
+}
+
+//------------------------------------------------------------------------------
+/// Disable UHP clock
+//------------------------------------------------------------------------------
+static inline void UHP_DisablePeripheralClock( void )
+{
+ AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_UHP);
+}
+
+//------------------------------------------------------------------------------
+/// Enables the 48MHz USB clock.
+//------------------------------------------------------------------------------
+static inline void UHP_EnableUsbClock(void)
+{
+#ifdef AT91C_PMC_USBS_USB_UPLL
+ AT91C_BASE_PMC->PMC_USB = AT91C_PMC_USBS_USB_UPLL | AT91C_PMC_USBDIV_10;
+#endif
+#ifdef AT91C_CKGR_UPLLEN_ENABLED
+ AT91C_BASE_PMC->PMC_UCKR = AT91C_CKGR_UPLLEN_ENABLED;
+#endif
+ AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UHP;
+}
+
+//------------------------------------------------------------------------------
+/// Disables the 48MHz USB clock.
+//------------------------------------------------------------------------------
+static inline void UHP_DisableUsbClock(void)
+{
+ AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_UHP;
+#ifdef AT91C_CKGR_UPLLEN_ENABLED
+ AT91C_BASE_PMC->PMC_UCKR = AT91C_CKGR_UPLLEN_ENABLED;
+#endif
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Detect a connected device
+//------------------------------------------------------------------------------
+unsigned char USBH_IsDeviceConnectedOnPort(unsigned char portNumber)
+{
+ return (AT91C_BASE_UHP->UHP_HcRhPortStatus[portNumber] & 0x01);
+}
+
+//------------------------------------------------------------------------------
+/// Reset the port number
+//------------------------------------------------------------------------------
+void USBH_ResetPort(unsigned char portNumber)
+{
+ // SetPortReset
+ AT91C_BASE_UHP->UHP_HcRhPortStatus[portNumber] = (1 << 4);
+ // Wait for the end of reset
+ while (AT91C_BASE_UHP->UHP_HcRhPortStatus[portNumber] & (1 << 4));
+ // SetPortEnable
+ AT91C_BASE_UHP->UHP_HcRhPortStatus[portNumber] = (1 << 1);
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void USBH_program(unsigned int* pBHED, unsigned int* pBCED, OHCI_HCCA* pHCCA)
+{
+ // Programming the BHED
+ // The HcBulkHeadED register contains the physical address of the first
+ // Endpoint Descriptor of the Bulk list.
+ AT91C_BASE_UHP->UHP_HcControlHeadED = (unsigned int) pBHED;
+
+ // Programming the BCED
+ // The HcBulkCurrentED register contains the physical address of the current
+ // endpoint of the Bulk list.
+ AT91C_BASE_UHP->UHP_HcControlCurrentED = (unsigned int) pBCED;
+
+ // Initializing the UHP_HcDoneHead
+ AT91C_BASE_UHP->UHP_HcBulkDoneHead = 0x00;
+ pHCCA->UHP_HccaDoneHead = 0x0000;
+
+ // Forcing UHP_Hc to Operational State
+ AT91C_BASE_UHP->UHP_HcControl = 0x80;
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void USBH_enablingPort(void)
+{
+ // Enabling port power
+ AT91C_BASE_UHP->UHP_HcRhPortStatus[0] = 0x00000100;
+ AT91C_BASE_UHP->UHP_HcRhPortStatus[1] = 0x00000100;
+ AT91C_BASE_UHP->UHP_HcRhStatus = 0x00010000;
+}
+
+//------------------------------------------------------------------------------
+/// Initializes the specified USB driver
+/// This function initializes the current FIFO bank of endpoints,
+/// configures the pull-up and VBus lines, disconnects the pull-up and
+/// then trigger the Init callback.
+//------------------------------------------------------------------------------
+void USBH_Init(OHCI_HCCA* pHCCA)
+{
+ TRACE_DEBUG_WP("USBH Init()\n\r");
+
+ UHP_EnablePeripheralClock();
+ UHP_EnableUsbClock();
+
+ // Forcing UHP_Hc to reset
+ AT91C_BASE_UHP->UHP_HcControl = 0;
+
+ // Writing the UHP_HCCA
+ AT91C_BASE_UHP->UHP_HcHCCA = (unsigned int) &pHCCA;
+
+ // Enabling list processing
+ AT91C_BASE_UHP->UHP_HcControl = 0;
+
+ // HcFmInterval register is used to control the length of USB frames
+ AT91C_BASE_UHP->UHP_HcFmInterval = OHCI_FMINTERVAL;
+ // The HcPeriodicStart register has a 14-bit programmable value which
+ // determines when is the earliest time HC should start processing the
+ // periodic list.
+ AT91C_BASE_UHP->UHP_HcPeriodicStart = OHCI_PRDSTRT;
+}
+
diff --git a/usb/host/ohci/ohci.c b/usb/host/ohci/ohci.c new file mode 100644 index 0000000..d125559 --- /dev/null +++ b/usb/host/ohci/ohci.c @@ -0,0 +1,124 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/// OHCI ED, TD HCCA definitions + inlined functions
+
+
+#include "ohci.h"
+
+
+//------------------------------------------------------------------------------
+/// Init a pre-allocated endpoint descriptor
+/// TD must be aligned on a 16 bytes boundary
+//------------------------------------------------------------------------------
+void OHCI_CreateEd( unsigned int EDAddr,
+ unsigned int MaxPacket,
+ unsigned int TDFormat,
+ unsigned int Skip,
+ unsigned int Speed,
+ unsigned int Direction,
+ unsigned int EndPt,
+ unsigned int FuncAddress,
+ unsigned int TDQTailPntr,
+ unsigned int TDQHeadPntr,
+ unsigned int ToggleCarry,
+ unsigned int NextED )
+{
+ OHCIEndpointDescriptor *pED = (OHCIEndpointDescriptor*) EDAddr;
+
+ pED->Control = (MaxPacket << 16) | (TDFormat << 15) |
+ (Skip << 14) | (Speed << 13) | (Direction << 11) |
+ (EndPt << 7) | FuncAddress;
+ pED->TailP = (TDQTailPntr & 0xFFFFFFF0);
+ pED->HeadP = (TDQHeadPntr & 0xFFFFFFF0) | (ToggleCarry << 1);
+ pED->NextEd = (NextED & 0xFFFFFFF0);
+}
+
+//------------------------------------------------------------------------------
+/// Init a pre-allocated transfer descriptor
+/// TD must be aligned on a 16 bytes boundary
+//------------------------------------------------------------------------------
+void OHCI_CreateGenTd( unsigned int GenTdAddr,
+ unsigned int DataToggle,
+ unsigned int DelayInterrupt,
+ unsigned int Direction,
+ unsigned int BufRnding,
+ unsigned int CurBufPtr,
+ unsigned int NextTD,
+ unsigned int BuffLen)
+{
+ OHCITransferDescriptor *pTD = (OHCITransferDescriptor*) GenTdAddr;
+
+ pTD->Control = (DataToggle << 24) | (DelayInterrupt << 21)
+ | (Direction << 19) | (BufRnding << 18);
+ pTD->CBP = CurBufPtr;
+ pTD->NextTD = (NextTD & 0xFFFFFFF0);
+ pTD->BE = (BuffLen) ? (CurBufPtr + BuffLen - 1) : CurBufPtr;
+}
+
+//------------------------------------------------------------------------------
+/// Init a pre-allocated periodic transfer descriptor
+/// TD must be aligned on a 16 bytes boundary
+//------------------------------------------------------------------------------
+void OHCI_CreateGenITd( unsigned int GenTdAddr,
+ unsigned int CondCode,
+ unsigned int FrameCount,
+ unsigned int DelayInterrupt,
+ unsigned int StartFrame,
+ unsigned int BuffPage0,
+ unsigned int NextTD,
+ unsigned int BufEnd,
+ unsigned int PswOffset0,
+ unsigned int PswOffset1,
+ unsigned int PswOffset2,
+ unsigned int PswOffset3,
+ unsigned int PswOffset4,
+ unsigned int PswOffset5,
+ unsigned int PswOffset6,
+ unsigned int PswOffset7)
+{
+ OHCIPeriodicTransferDescriptor *pITD = (OHCIPeriodicTransferDescriptor*) GenTdAddr;
+
+ pITD->Control = (CondCode << 28) | (FrameCount << 24)
+ | (DelayInterrupt << 21) | StartFrame;
+ pITD->BP0 = (BuffPage0 << 12);
+ pITD->NextTD = (NextTD << 4);
+ pITD->BE = BufEnd;
+ pITD->PSW0 = PswOffset0;
+ pITD->PSW1 = PswOffset1;
+ pITD->PSW2 = PswOffset2;
+ pITD->PSW3 = PswOffset3;
+ pITD->PSW4 = PswOffset4;
+ pITD->PSW5 = PswOffset5;
+ pITD->PSW6 = PswOffset6;
+ pITD->PSW7 = PswOffset7;
+
+}
+
+
diff --git a/usb/host/ohci/ohci.h b/usb/host/ohci/ohci.h new file mode 100644 index 0000000..804d75b --- /dev/null +++ b/usb/host/ohci/ohci.h @@ -0,0 +1,139 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/// OHCI ED, TD HCCA definitions + inlined functions
+
+#ifndef _OHCI_H
+#define _OHCI_H
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(8)
+#define __attribute__(...) // IAR
+#endif // IAR
+// Endpoint Descriptor Field Definitions
+typedef struct {
+ // FunctionAddress | EndpointNumber | Direction | Speed | sKip | Format
+ // MaximumPacketSize
+ volatile unsigned int Control;
+ // TailP: TDQueueTailPointer
+ // If TailP and HeadP are the same, then the list contains no TD that the HC
+ // can process. If TailP and HeadP are different, then the list contains a TD to be
+ // processed.
+ volatile unsigned int TailP;
+ // HeadP: TDQueueHeadPointer Points to the next TD to be processed for this
+ // endpoint.
+ volatile unsigned int HeadP;
+ // NextED: If nonzero, then this entry points to the next ED on the list
+ volatile unsigned int NextEd;
+} __attribute__((aligned(16))) OHCIEndpointDescriptor;
+
+/// General Transfer Descriptor Format
+typedef struct {
+ volatile unsigned int Control; // bufferRounding | Direction/PID | DelayInterrupt
+ // DataToggle | ErrorCount | ConditionCode
+ volatile unsigned int CBP; // Current Buffer Pointer
+ volatile unsigned int NextTD; // Next TD
+ volatile unsigned int BE; // Buffer End
+} __attribute__((aligned(16))) OHCITransferDescriptor;
+
+typedef struct {
+ volatile unsigned int Control; // StartingFrame | DelayInterrupt | FrameCount
+ // ConditionCode
+ volatile unsigned int BP0; // Buffer Page 0
+ volatile unsigned int NextTD; // NextTD
+ volatile unsigned int BE; // Buffer End
+ volatile unsigned int PSW0; // Offset0/PSW0
+ volatile unsigned int PSW1; // Offset1/PSW1
+ volatile unsigned int PSW2; // Offset2/PSW2
+ volatile unsigned int PSW3; // Offset3/PSW3
+ volatile unsigned int PSW4; // Offset4/PSW4
+ volatile unsigned int PSW5; // Offset5/PSW5
+ volatile unsigned int PSW6; // Offset6/PSW6
+ volatile unsigned int PSW7; // Offset7/PSW7
+} __attribute__((aligned(8))) OHCIPeriodicTransferDescriptor;
+
+//Host Controller Communications Area Description
+typedef struct {
+ // pointers to an Interrupt List each of which is a list of EDs
+ volatile unsigned int UHP_HccaInterruptTable[32];
+ // This 16-bit value is updated by the Host Controller on each frame.
+ volatile unsigned short UHP_HccaFrameNumber; // current frame number
+ // When the HC updates HccaFrameNumber, it sets this word to 0.
+ volatile unsigned short UHP_HccaPad1;
+ // When a TD is complete (with or without an error) it is unlinked from the
+ // queue that it is on and linked to the Done Queue
+ volatile unsigned int UHP_HccaDoneHead;
+ // Reserved for use by HC
+ volatile unsigned char reserved[116];
+} __attribute__((aligned(8))) OHCI_HCCA;
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+
+extern void OHCI_CreateEd( unsigned int EDAddr,
+ unsigned int MaxPacket,
+ unsigned int TDFormat,
+ unsigned int Skip,
+ unsigned int Speed,
+ unsigned int Direction,
+ unsigned int EndPt,
+ unsigned int FuncAddress,
+ unsigned int TDQTailPntr,
+ unsigned int TDQHeadPntr,
+ unsigned int ToggleCarry,
+ unsigned int NextED );
+extern void OHCI_CreateGenTd( unsigned int GenTdAddr,
+ unsigned int DataToggle,
+ unsigned int DelayInterrupt,
+ unsigned int Direction,
+ unsigned int BufRnding,
+ unsigned int CurBufPtr,
+ unsigned int NextTD,
+ unsigned int BuffLen);
+extern void OHCI_CreateGenITd( unsigned int GenTdAddr,
+ unsigned int CondCode,
+ unsigned int FrameCount,
+ unsigned int DelayInterrupt,
+ unsigned int StartFrame,
+ unsigned int BuffPage0,
+ unsigned int NextTD,
+ unsigned int BufEnd,
+ unsigned int PswOffset0,
+ unsigned int PswOffset1,
+ unsigned int PswOffset2,
+ unsigned int PswOffset3,
+ unsigned int PswOffset4,
+ unsigned int PswOffset5,
+ unsigned int PswOffset6,
+ unsigned int PswOffset7);
+#endif //_OHCI_H
+
+
diff --git a/usb/otg/compiler.h b/usb/otg/compiler.h new file mode 100644 index 0000000..b85521b --- /dev/null +++ b/usb/otg/compiler.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef _COMPILER_H_
+#define _COMPILER_H_
+
+typedef float Float16;
+typedef unsigned char U8 ;
+typedef unsigned short U16;
+typedef unsigned long U32;
+typedef unsigned char Bool;
+
+typedef unsigned char Byte;
+
+typedef char bit;
+
+#define MSB0(u32) (((U8* )&u32)[3])
+#define MSB1(u32) (((U8* )&u32)[2])
+#define MSB2(u32) (((U8* )&u32)[1])
+#define MSB3(u32) (((U8* )&u32)[0])
+#define LSB0(u32) MSB3(u32)
+#define LSB1(u32) MSB2(u32)
+#define LSB2(u32) MSB1(u32)
+#define LSB3(u32) MSB0(u32)
+#define MSB(u16) (((U8* )&u16)[1])
+#define LSB(u16) (((U8* )&u16)[0])
+#define MSW(u32) (((U16*)&u32)[1])
+#define LSW(u32) (((U16*)&u32)[0])
+
+
+// Constants
+#define DISABLE 0
+#define ENABLE 1
+
+#define TRUE (1 == 1)
+#define FALSE (0 == 1)
+
+#endif /* _COMPILER_H_ */
+
diff --git a/usb/otg/usb_drv.c b/usb/otg/usb_drv.c new file mode 100644 index 0000000..c29689c --- /dev/null +++ b/usb/otg/usb_drv.c @@ -0,0 +1,246 @@ +/* ----------------------------------------------------------------------------
+ * 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 <conf_usb.h>
+#include "usb_drv.h"
+#include <utility/trace.h>
+
+U8 global_pipe_nb=0;
+U8 global_endpoint_nb=0;
+unsigned char dBytes=0;
+char* pFifo;
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//! This function configures an endpoint with the selected type.
+U8 dev_configure_endpoint(U8 ept, U8 type, U8 dir, U8 size, U8 bank, U8 nyet)
+{
+ unsigned char status=0;
+
+ // Enable endpoint
+ AT91C_BASE_OTGHS->OTGHS_DEVEPT |= (1<<ept);
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[ept] = (bank<<2)|(size<<4)|(dir<<8)
+ |AT91C_OTGHS_AUTOSW |(type<<11);
+
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTCFG[ept] |= AT91C_OTGHS_ALLOC;
+ if(!(AT91C_BASE_OTGHS->OTGHS_DEVEPTISR[ept]&AT91C_OTGHS_CFGOK)) {
+ TRACE_ERROR("Bad endpoint configuration\n\r");
+ status = 1;
+ }
+ if(nyet == NYET_ENABLED) {
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIDR[ept] = AT91C_OTGHS_NYETDIS;
+ }
+ else {
+ AT91C_BASE_OTGHS->OTGHS_DEVEPTIER[ept] = AT91C_OTGHS_NYETDIS;
+ }
+ return status;
+}
+
+
+
+
+//------------------------------------------------------------------------------
+// HOST
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//! This function configures a pipe with the selected type.
+//! @param config0
+//! @param config1
+//! @return Is_endpoint_configured.
+//------------------------------------------------------------------------------
+U8 host_config_pipe(U8 config0, U8 config1)
+{
+ TRACE_DEBUG("host_config_pipe\n\r");
+ Host_enable_pipe();
+// UPCFG0X = config0;
+// UPCFG1X = config1;
+ Host_allocate_memory();
+ return (Is_pipe_configured());
+}
+
+//------------------------------------------------------------------------------
+//! This function returns the size configuration register value according
+//! to the endpint size detected inthe device enumeration process.
+//! @return pipe size register value.
+//------------------------------------------------------------------------------
+U8 host_determine_pipe_size(U16 size)
+{
+ //TRACE_DEBUG("host_determine_pipe_size\n\r");
+ if(size <= 8 ) {return (SIZE_8 );}
+ else if(size <= 16 ) {return (SIZE_16 );}
+ else if(size <= 32 ) {return (SIZE_32 );}
+ else if(size <= 64 ) {return (SIZE_64 );}
+ else if(size <= 128) {return (SIZE_128 );}
+ else if(size <= 256) {return (SIZE_256 );}
+ else if(size <= 512) {return (SIZE_512 );}
+ else {return (SIZE_1024);}
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+U16 host_get_pipe_length(void)
+{
+ unsigned int size;
+
+ size = (AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb]&AT91C_OTGHS_PSIZE)>>4;
+ //TRACE_DEBUG("host_get_pipe_length = %d\n\r", (int)size);
+
+ if(size == SIZE_8 ) {return (8 );}
+ else if(size == SIZE_16 ) {return (16 );}
+ else if(size == SIZE_32 ) {return (32 );}
+ else if(size == SIZE_64 ) {return (64 );}
+ else if(size == SIZE_128) {return (128);}
+ else if(size == SIZE_256) {return (256);}
+ else if(size == SIZE_512) {return (512);}
+ else if(size == SIZE_1024){return (1024);}
+ else {TRACE_ERROR("Error size\n\r");return 0;}
+}
+
+
+//------------------------------------------------------------------------------
+//! host_disable_all_pipe.
+//!
+//! This function disable all pipes for the host controller
+//! Usefull to execute upon device disconnection.
+//!
+//! @return none.
+//------------------------------------------------------------------------------
+void host_disable_all_pipe(void)
+{
+ U8 i;
+
+ TRACE_DEBUG("host_disable_all_pipe\n\r");
+ for (i=0; i<7; i++) {
+ Host_reset_pipe(i);
+ Host_select_pipe(i);
+ Host_unallocate_memory();
+ Host_disable_pipe();
+ }
+}
+
+//------------------------------------------------------------------------------
+//! @brief Returns the pipe number that generates a USB communication interrupt
+//!
+//! This function sould be called only when an interrupt has been detected. Otherwize
+//! the return value is incorect
+//!
+//! @param none
+//!
+//! @return pipe_number
+//------------------------------------------------------------------------------
+U8 host_get_nb_pipe_interrupt(void)
+{
+ U8 interrupt_flags;
+ U8 i;
+
+ TRACE_DEBUG("host_get_nb_pipe_interrupt\n\r");
+ interrupt_flags = Host_get_pipe_interrupt();
+ for(i=0; i<MAX_EP_NB; i++) {
+ if (interrupt_flags & (1<<i)) {
+ return (i);
+ }
+ }
+ // This return should never occurs ....
+ TRACE_ERROR("Error\n\r");
+ return MAX_EP_NB+1;
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void host_configure_address( unsigned char pipe, unsigned char addr)
+{
+ if( pipe == 0 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P0;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 |= ((addr<<0) & AT91C_OTGHS_UHADDR_P0);
+ }
+ else if( pipe == 1 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P1;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 |= ((addr<<8) & AT91C_OTGHS_UHADDR_P1);
+ }
+ else if( pipe == 2 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P2;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 |= ((addr<<16) & AT91C_OTGHS_UHADDR_P2);
+ }
+ else if( pipe == 3 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P3;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR1 |= ((addr<<24) & AT91C_OTGHS_UHADDR_P3);
+ }
+ else if( pipe == 4 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P4;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 |= ((addr<<0) & AT91C_OTGHS_UHADDR_P4);
+ }
+ else if( pipe == 5 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P5;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 |= ((addr<<8) & AT91C_OTGHS_UHADDR_P5);
+ }
+ else if( pipe == 6 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P6;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 |= ((addr<<16) & AT91C_OTGHS_UHADDR_P6);
+ }
+ else if( pipe == 7 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P7;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR2 |= ((addr<<24) & AT91C_OTGHS_UHADDR_P7);
+ }
+ else if( pipe == 8 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR3 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P8;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR3 |= ((addr<<0) & AT91C_OTGHS_UHADDR_P8);
+ }
+ else if( pipe == 9 ) {
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR3 &= ~(unsigned int)AT91C_OTGHS_UHADDR_P9;
+ AT91C_BASE_OTGHS->OTGHS_HSTADDR3 |= ((addr<<8) & AT91C_OTGHS_UHADDR_P9);
+ }
+ else {
+ TRACE_ERROR("pipe not defined\n\r");
+ }
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void host_configure_pipe(U8 pip, U8 type, U8 token, U8 ep_num, U8 size, U8 bank, U8 freq)
+{
+ AT91C_BASE_OTGHS->OTGHS_HSTPIP |= (1<<pip);
+
+ if((type & AT91C_OTGHS_PTYPE_INT_PIP)==0) {
+ freq =0;
+ }
+
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[pip] = (bank<< 2) | (size << 4) | (token<< 8)
+ | (type<<12) |(ep_num<<16)| (freq <<24);
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[pip] |= AT91C_OTGHS_ALLOC;
+}
+
+
diff --git a/usb/otg/usb_drv.h b/usb/otg/usb_drv.h new file mode 100644 index 0000000..c9276fe --- /dev/null +++ b/usb/otg/usb_drv.h @@ -0,0 +1,859 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/// This file contains the USB low level driver definition
+
+
+#ifndef _USB_DRV_H
+#define _USB_DRV_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include "board.h"
+
+extern unsigned char dBytes;
+extern char* pFifo_ctrl;
+extern char* pFifo;
+
+//#define Address_fifo_endpoint(ep) (char*)&(AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0[EPT_VIRTUAL_SIZE*ep])
+#define Address_fifochar_endpoint(ep) pFifo = (char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO + (EPT_VIRTUAL_SIZE * ep));dBytes=0
+//#define Address_fifochar_endpoint(ep) (char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO + (EPT_VIRTUAL_SIZE * ep))
+#define Address_fifo_endpoint(ep) (int*) ((int)(AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0) + (EPT_VIRTUAL_SIZE*(ep)))
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// USB_low_level_drivers USB low level drivers module
+
+#define MAX_EP_NB 7
+
+#define EPT_VIRTUAL_SIZE 8192
+
+#define EP_CONTROL 0
+#define PIPE_CONTROL 0
+
+// USB EndPoint
+#define MSK_EP_DIR 0x7F
+
+// Parameters for endpoint configuration
+// These define are the values used to enable and configure an endpoint.
+#define TYPE_CONTROL 0
+#define TYPE_ISOCHRONOUS 1
+#define TYPE_BULK 2
+#define TYPE_INTERRUPT 3
+
+#define DIRECTION_OUT 0
+#define DIRECTION_IN 1
+
+#define SIZE_8 0
+#define SIZE_16 1
+#define SIZE_32 2
+#define SIZE_64 3
+#define SIZE_128 4
+#define SIZE_256 5
+#define SIZE_512 6
+#define SIZE_1024 7
+
+#define ONE_BANK 0
+#define TWO_BANKS 1
+#define TREE_BANKS 2
+
+#define NYET_ENABLED 0
+#define NYET_DISABLED 1
+
+#define TOKEN_SETUP 0
+#define TOKEN_IN 1
+#define TOKEN_OUT 2
+
+#define Is_ep_addr_in(x) (x & 0x80)
+
+//Set_bits(AVR32_USB_uatst1,AVR32_USB_UATST1_LOADCNTA_MASK);
+#define Usb_load_tsta1_countMask() AT91C_BASE_OTGHS->OTGHS_TSTA1 &= ~(unsigned int)AT91C_OTGHS_COUNTERA
+
+//#define AVR32_USB_UATST1_LOADCNTA_MASK_NONZERO 0x00008001
+#define Usb_load_tsta1_counta() AT91C_BASE_OTGHS->OTGHS_TSTA1 = AT91C_OTGHS_LOADCNTA | (AT91C_OTGHS_COUNTERA&0x01)
+
+//#define AVR32_USB_UATST2_FORCE_51MS_RESETHS_MASK 0x00000080
+#define USb_ForceHSRst_50ms() AT91C_BASE_OTGHS->OTGHS_TSTA2 |= AT91C_OTGHS_FORCHSRST
+
+//#define AVR32_USB_UATST2_FORCE_RESET_UTMI 0x00000100
+#define Usb_SetForceResetUTMI() AT91C_BASE_OTGHS->OTGHS_TSTA2 |= AT91C_OTGHS_UTMIRESET
+#define Usb_ClrForceResetUTMI() AT91C_BASE_OTGHS->OTGHS_TSTA2 &= ~(unsigned int)AT91C_OTGHS_UTMIRESET
+
+//#define AVR32_USB_UATST2_HOSTHSDISCONNECTDISABLE_MASK
+#define Usb_SetHSTDiconnectDisableMask() AT91C_BASE_OTGHS->OTGHS_TSTA2 |= AT91C_OTGHS_HSTHSDISCDIS
+#define Usb_ClrHSTDiconnectDisableMask() AT91C_BASE_OTGHS->OTGHS_TSTA2 &= ~(unsigned int)AT91C_OTGHS_HSTHSDISCDIS
+
+#define Usb_enable_vbus_error_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_VBERR
+
+#define Is_Usb_InHighSpeed() (AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_SPEED_SR) == AT91C_OTGHS_SPEED_SR_HS
+
+/// OTG Timers customizing
+// HOST : Minimum delay after Vbus requested to get it > Va_vbus_valid (otherwise => error)
+//#define VBUSRISE_20MS 0x00
+//#define VBUSRISE_50MS 0x01
+#define VBUSRISE_70MS 0x02
+//#define VBUSRISE_100MS 0x03
+// DEVICE : Duration of Vbus pulse during SRP protocol
+//#define VBUSPULSE_15MS 0x20
+//#define VBUSPULSE_23MS 0x21
+//#define VBUSPULSE_31MS 0x22
+#define VBUSPULSE_40MS 0x23
+// DEVICE : Minimum delay after Vbus < Vb_sess_end to enable SRP
+//#define VFALLTMOUT_93MS 0x40
+//#define VFALLTMOUT_105MS 0x41
+//#define VFALLTMOUT_118MS 0x42
+#define VFALLTMOUT_131MS 0x43
+// HOST : Minimum pulse duration accepted as SRP pulse
+//#define SRPMINDET_10US 0x60
+#define SRPMINDET_100US 0x61
+//#define SRPMINDET_1MS 0x62
+//#define SRPMINDET_11MS 0x63
+
+//------------------------------------------------------------------------------
+// A R B I T R E R
+//------------------------------------------------------------------------------
+
+/// gen_usb USB common management drivers
+/// These macros manage the USB controller
+
+/// Enable external UID pin
+//#define Usb_enable_uid_pin() (UHWCON |= (1<<UIDE))
+#define Usb_enable_uid_pin() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_UIDE
+/// Disable external UID pin
+//#define Usb_disable_uid_pin() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~AT91C_OTGHS_UIDE
+/// Disable external UID pin and force device mode
+//#define Usb_force_device_mode() //{AT91C_BASE_OTGHS->OTGHS_CTRL &= ~AT91C_OTGHS_UIDE;
+ // AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_UIMOD;}
+/// Disable external UID pin and force host mode
+//#define Usb_force_host_mode() //{AT91C_BASE_OTGHS->OTGHS_CTRL &= ~AT91C_OTGHS_UIDE;
+ // AT91C_BASE_OTGHS->OTGHS_CTRL &= ~AT91C_OTGHS_UIMOD;}
+/// Enable external UVCON pin
+//#define Usb_enable_uvcon_pin() // (UHWCON |= (1<<UVCONE))
+#define Usb_enable_uvcon_pin()
+//#define Usb_enable_uvcon_pin() { const Pin pinDRVVUS = PIN_USB_DRV_VBUS;PIO_Set(&pinDRVVUS); }
+//jcb
+/// Use device full speed mode (default mode)
+//#define Usb_full_speed_mode() (UDCON &= ~(1<<LSM))
+/// For device mode, force low speed mode
+//#define Usb_low_speed_mode() (UDCON |= (1<<LSM))
+#define Usb_low_speed_mode() AT91C_BASE_OTGHS->OTGHS_DEVCTRL |= AT91C_OTGHS_LS
+
+#define Usb_enable() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_USBECTRL
+#define Usb_disable() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_USBECTRL
+
+/// Enable VBUS pad
+//#define Usb_enable_vbus_pad() (USBCON |= (1<<OTGPADE))
+#define Usb_enable_vbus_pad() {AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_USBECTRL;\
+ AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_OTGPADE;\
+ AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_FRZCLKCTRL;}
+/// Disable VBUS pad
+//#define Usb_disable_vbus_pad() (USBCON &= ~(1<<OTGPADE))
+#define Usb_disable_vbus_pad() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_OTGPADE
+
+#define Usb_select_device() Usb_enable_uid_pin()
+#define Usb_select_host() Usb_enable_uid_pin()
+#define Is_usb_device_enabled() (AT91C_BASE_OTGHS->OTGHS_SR & AT91C_OTGHS_ID)
+#define Is_usb_host_enabled() !Is_usb_device_enabled()
+/// Stop internal USB clock in interface (freeze the interface register)
+//#define Usb_freeze_clock() (USBCON |= (1<<FRZCLK))
+#define Usb_freeze_clock() // AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_FRZCLKCTRL
+//jcb
+//#define Usb_unfreeze_clock() (USBCON &= ~(1<<FRZCLK))
+#define Usb_unfreeze_clock() // AT91C_BASE_OTGHS->OTGHS_CTRL &= ~AT91C_OTGHS_FRZCLKCTRL
+//#define Is_usb_clock_freezed() ((USBCON & (1<<FRZCLK)) ? TRUE : FALSE)
+#define Is_usb_clock_freezed() (AT91C_BASE_OTGHS->OTGHS_CTRL & AT91C_OTGHS_FRZCLKCTRL)
+
+//#define Usb_enable_id_interrupt() (USBCON |= (1<<IDTE))
+#define Usb_enable_id_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_IDT
+//#define Usb_disable_id_interrupt() (USBCON &= ~(1<<IDTE))
+#define Usb_disable_id_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_IDT
+//#define Is_usb_id_interrupt_enabled() ((USBCON & (1<<IDTE)) ? TRUE : FALSE)
+#define Is_usb_id_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_CTRL & AT91C_OTGHS_IDT)
+//#define Is_usb_id_device() ((USBSTA & (1<<ID)) ? TRUE : FALSE)
+#define Is_usb_id_device() (AT91C_BASE_OTGHS->OTGHS_SR & AT91C_OTGHS_ID)
+//#define Is_usb_id_host() ((USBSTA & (1<<ID)) ? FALSE : TRUE)
+#define Is_usb_id_host() !Is_usb_id_device()
+//#define Usb_ack_id_transition() (USBINT = ~(1<<IDTI))
+#define Usb_ack_id_transition() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_IDT
+//#define Is_usb_id_transition() ((USBINT & (1<<IDTI)) ? TRUE : FALSE)
+#define Is_usb_id_transition() (AT91C_BASE_OTGHS->OTGHS_SR & AT91C_OTGHS_IDT)
+
+//#define Usb_enable_vbus_interrupt() (USBCON |= (1<<VBUSTE))
+//#define Usb_enable_vbus_interrupt() (Set_bits(AVR32_USB_usbcon, AVR32_USB_USBCON_VBUSTE_MASK))
+#define Usb_enable_vbus_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_VBUSTI
+//#define Usb_disable_vbus_interrupt() (USBCON &= ~(1<<VBUSTE))
+#define Usb_disable_vbus_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_VBUSTI
+//#define Is_usb_vbus_interrupt_enabled() ((USBCON & (1<<VBUSTE)) ? TRUE : FALSE)
+#define Is_usb_vbus_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_CTRL & AT91C_OTGHS_VBUSTI)
+//#define Is_usb_vbus_high() ((USBSTA & (1<<VBUS)) ? TRUE : FALSE)
+
+#define Is_usb_vbus_high() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_VBUSSR)==AT91C_OTGHS_VBUSSR)
+//#define Is_usb_vbus_low() ((USBSTA & (1<<VBUS)) ? FALSE : TRUE)
+#define Is_usb_vbus_low() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_VBUSSR)!=AT91C_OTGHS_VBUSSR)
+//#define Usb_ack_vbus_transition() (USBINT = ~(1<<VBUSTI))
+#define Usb_ack_vbus_transition() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_VBUSTI
+//#define Is_usb_vbus_transition() ((USBINT & (1<<VBUSTI)) ? TRUE : FALSE)
+#define Is_usb_vbus_transition() (AT91C_BASE_OTGHS->OTGHS_CTRL & AT91C_OTGHS_VBUSTI)
+
+/// requests for VBus activation
+//#define Usb_enable_vbus() (OTGCON |= (1<<VBUSREQ))
+#define Usb_enable_vbus() AT91C_BASE_OTGHS->OTGHS_SFR = AT91C_OTGHS_VBUSRQ //JCB
+/// requests for VBus desactivation
+#define Usb_disable_vbus() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_VBUSRQ //JCB
+/// Manually request VBUS without UVCON signal from USB interface
+//#define Usb_disable_uvcon_pin() (UHWCON &= ~(1<<UVCONE))
+//#define Usb_enable_manual_vbus() (PORTE|=0x80,DDRE|=0x80,Usb_disable_uvcon_pin())
+#define Usb_enable_manual_vbus() AT91C_BASE_OTGHS->OTGHS_SFR = AT91C_OTGHS_VBUSRQ //JCB
+/// Manually request VBUS OFF without UVCON signal from USB interface
+//#define Usb_disable_manual_vbus() (PORTE&=~0x80,DDRE|=0x80,Usb_enable_uvcon_pin())
+#define Usb_disable_manual_vbus() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_VBUSRQ //JCB
+
+/// initiates a Host Negociation Protocol
+//#define Usb_device_initiate_hnp() (OTGCON |= (1<<HNPREQ))
+#define Usb_device_initiate_hnp() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_HNPREQ
+/// stops a Host Negociation Protocol
+//#define Usb_device_stop_hnp() (OTGCON &= ~(1<<HNPREQ))
+#define Usb_device_stop_hnp() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_HNPREQ
+/// accepts a Host Negociation Protocol
+//#define Usb_host_accept_hnp() (OTGCON |= (1<<HNPREQ))
+#define Usb_host_accept_hnp() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_HNPREQ
+/// rejects a Host Negociation Protocol
+//#define Usb_host_reject_hnp() (OTGCON &= ~(1<<HNPREQ))
+#define Usb_host_reject_hnp() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_HNPREQ
+/// initiates a Session Request Protocol
+//#define Usb_device_initiate_srp() (OTGCON |= (1<<SRPREQ))
+#define Usb_device_initiate_srp() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_SRPREQ
+/// selects VBus as SRP method
+//#define Usb_select_vbus_srp_method() (OTGCON |= (1<<SRPSEL))
+#define Usb_select_vbus_srp_method() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_SRPSEL
+/// selects data line as SRP method
+//#define Usb_select_data_srp_method() (OTGCON &= ~(1<<SRPSEL))
+#define Usb_select_data_srp_method() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_SRPSEL
+
+
+/// enables hardware control on VBus
+#define Usb_enable_vbus_hw_control() // AT91C_BASE_OTGHS->OTGHS_CTRL &= ~AT91C_OTGHS_VBUSHWC
+/// disables hardware control on VBus
+#define Usb_disable_vbus_hw_control() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_VBUSHWC
+/// tests if VBus has been requested
+//#define Is_usb_vbus_enabled() ((OTGCON & (1<<VBUSREQ)) ? TRUE : FALSE)
+/// tests if a HNP occurs
+//#define Is_usb_hnp() ((OTGCON & (1<<HNPREQ)) ? TRUE : FALSE)
+#define Is_usb_hnp() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_ROLEEX) == AT91C_OTGHS_ROLEEX)
+/// tests if a SRP from device occurs
+//#define Is_usb_device_srp() ((OTGCON & (1<<SRPREQ)) ? TRUE : FALSE)
+/// tests if device is initiating SRP
+//#define Is_usb_device_initiating_srp() ((OTGCON & (1<<SRPREQ)) ? TRUE : FALSE)
+#define Is_usb_device_initiating_srp() (AT91C_BASE_OTGHS->OTGHS_CTRL&AT91C_OTGHS_SRPREQ)
+
+/// acks suspend time out interrupt
+//#define Usb_ack_suspend_time_out_interrupt() (OTGINT &= ~(1<<STOI))
+#define Usb_ack_suspend_time_out_interrupt() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_STO
+/// enables suspend time out interrupt
+//#define Usb_enable_suspend_time_out_interrupt() (OTGIEN |= (1<<STOE))
+#define Usb_enable_suspend_time_out_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_STO
+/// disables suspend time out interrupt
+//#define Usb_disable_suspend_time_out_interrupt() (OTGIEN &= ~(1<<STOE))
+#define Usb_disable_suspend_time_out_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_STO
+//#define Is_suspend_time_out_interrupt_enabled() ((OTGIEN & (1<<STOE)) ? TRUE : FALSE)
+#define Is_suspend_time_out_interrupt_enabled() ((AT91C_BASE_OTGHS->OTGHS_CTRL&AT91C_OTGHS_STO)==AT91C_OTGHS_STO)
+/// tests if a suspend time out occurs
+//#define Is_usb_suspend_time_out_interrupt() ((OTGINT & (1<<STOI)) ? TRUE : FALSE)
+#define Is_usb_suspend_time_out_interrupt() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_STO)==AT91C_OTGHS_STO)
+
+/// enables HNP error interrupt
+//#define Usb_enable_hnp_error_interrupt() (OTGIEN |= (1<<HNPERRE))
+#define Usb_enable_hnp_error_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_HNPERR
+/// disables HNP error interrupt
+//#define Usb_disable_hnp_error_interrupt() (OTGIEN &= ~(1<<HNPERRE))
+#define Usb_disable_hnp_error_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_HNPERR
+//#define Is_hnp_error_interrupt_enabled() ((OTGIEN & (1<<HNPERRE)) ? TRUE : FALSE)
+#define Is_hnp_error_interrupt_enabled() ((AT91C_BASE_OTGHS->OTGHS_CTRL&AT91C_OTGHS_HNPERR)==AT91C_OTGHS_HNPERR)
+/// acks HNP error interrupt
+//#define Usb_ack_hnp_error_interrupt() (OTGINT &= ~(1<<HNPERRI))
+#define Usb_ack_hnp_error_interrupt() AT91C_BASE_OTGHS->OTGHS_SCR |= AT91C_OTGHS_HNPERR
+/// tests if a HNP error occurs
+//#define Is_usb_hnp_error_interrupt() ((OTGINT & (1<<HNPERRI)) ? TRUE : FALSE)
+#define Is_usb_hnp_error_interrupt() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_HNPERR) == AT91C_OTGHS_HNPERR)
+
+/// enables role exchange interrupt
+//#define Usb_enable_role_exchange_interrupt() (OTGIEN |= (1<<ROLEEXE))
+#define Usb_enable_role_exchange_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_ROLEEX
+/// disables role exchange interrupt
+//#define Usb_disable_role_exchange_interrupt() (OTGIEN &= ~(1<<ROLEEXE))
+#define Usb_disable_role_exchange_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_ROLEEX
+//#define Is_role_exchange_interrupt_enabled() ((OTGIEN & (1<<ROLEEXE)) ? TRUE : FALSE)
+#define Is_role_exchange_interrupt_enabled() ((AT91C_BASE_OTGHS->OTGHS_CTRL&AT91C_OTGHS_ROLEEX)==AT91C_OTGHS_ROLEEX)
+/// acks role exchange interrupt
+//#define Usb_ack_role_exchange_interrupt() (OTGINT &= ~(1<<ROLEEXI))
+#define Usb_ack_role_exchange_interrupt() AT91C_BASE_OTGHS->OTGHS_SCR |= AT91C_OTGHS_ROLEEX
+/// tests if a role exchange occurs
+//#define Is_usb_role_exchange_interrupt() ((OTGINT & (1<<ROLEEXI)) ? TRUE : FALSE)
+#define Is_usb_role_exchange_interrupt() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_ROLEEX)==AT91C_OTGHS_ROLEEX)
+
+/// enables B device connection error interrupt
+//#define Usb_enable_bconnection_error_interrupt() (OTGIEN |= (1<<BCERRE))
+#define Usb_enable_bconnection_error_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_BCERR
+/// disables B device connection error interrupt
+//#define Usb_disable_bconnection_error_interrupt() (OTGIEN &= ~(1<<BCERRE))
+#define Usb_disable_bconnection_error_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_BCERR
+//#define Is_bconnection_error_interrupt_enabled() ((OTGIEN & (1<<BCERRE)) ? TRUE : FALSE)
+/// acks B device connection error interrupt
+#define Usb_ack_bconnection_error_interrupt() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_BCERR
+/// tests if a B device connection error occurs
+#define Is_usb_bconnection_error_interrupt() FALSE//jcb (AT91C_BASE_OTGHS->OTGHS_SR & AT91C_OTGHS_BCERR)
+
+/// enables VBus error interrupt
+//#define Usb_enable_vbus_error_interrupt() (OTGIEN |= (1<<VBERRE))
+/// disables VBus error interrupt
+//#define Usb_disable_vbus_error_interrupt() (OTGIEN &= ~(1<<VBERRE))
+//#define Is_vbus_error_interrupt_enabled() ((OTGIEN & (1<<VBERRE)) ? TRUE : FALSE)
+/// acks VBus error interrupt
+#define Usb_ack_vbus_error_interrupt() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_VBERR
+/// tests if a VBus error occurs
+#define Is_usb_vbus_error_interrupt() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_VBERR)==AT91C_OTGHS_VBERR)
+
+/// enables SRP interrupt
+//#define Usb_enable_srp_interrupt() (OTGIEN |= (1<<SRPE))
+#define Usb_enable_srp_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL |= AT91C_OTGHS_SRP
+/// disables SRP interrupt
+//#define Usb_disable_srp_interrupt() (OTGIEN &= ~(1<<SRPE))
+#define Usb_disable_srp_interrupt() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_SRP
+//#define Is_srp_interrupt_enabled() ((OTGIEN & (1<<SRPE)) ? TRUE : FALSE)
+#define Is_usb_srp_interrupt_enabled() ((AT91C_BASE_OTGHS->OTGHS_CTRL&AT91C_OTGHS_SRP)==AT91C_OTGHS_SRP)
+/// acks SRP interrupt
+#define Usb_ack_srp_interrupt() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_SRP
+/// tests if a SRP occurs
+#define Is_usb_srp_interrupt() ((AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_SRP)==AT91C_OTGHS_SRP)
+
+
+//------------------------------------------------------------------------------
+// D E V I C E
+//------------------------------------------------------------------------------
+
+/// USB_device_driver USB device controller drivers
+/// These macros manage the USB Device controller.
+
+/// test if remote wake-up still running
+//#define Is_usb_pending_remote_wake_up() ((UDCON & (1<<RMWKUP)) ? TRUE : FALSE)
+#define Is_usb_pending_remote_wake_up() (AT91C_BASE_OTGHS->OTGHS_DEVCTRL | AT91C_OTGHS_RMWKUP)
+/// acks remote wake-up
+//#define Usb_ack_remote_wake_up_start() (UDINT = ~(1<<UPRSMI))
+#define Usb_ack_remote_wake_up_start() AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_UPRSM
+
+/// enables resume interrupt
+//#define Usb_enable_resume_interrupt() (UDIEN |= (1<<EORSME))
+/// disables resume interrupt
+#define Usb_disable_resume_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIDR = AT91C_OTGHS_EORSM
+#define Is_resume_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_OTGHS_EORSM)
+/// acks resume
+#define Usb_ack_resume() AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_EORSM
+/// tests if resume occurs
+#define Is_usb_resume() (AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_OTGHS_EORSM)
+
+/// enables wake-up interrupt
+#define Usb_enable_wake_up_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIER = AT91C_OTGHS_WAKEUP
+/// disables wake-up interrupt
+#define Usb_disable_wake_up_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIDR = AT91C_OTGHS_WAKEUP
+#define Is_swake_up_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_DEVIMR & AT91C_OTGHS_WAKEUP)
+/// acks wake-up
+#define Usb_ack_wake_up() AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_WAKEUP
+/// tests if wake-up occurs
+#define Is_usb_wake_up() (AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_OTGHS_WAKEUP)
+
+/// enables USB reset interrupt
+#define Usb_enable_reset_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIER = AT91C_OTGHS_EORST
+/// disables USB reset interrupt
+//#define Usb_disable_reset_interrupt() (UDIEN &= ~(1<<EORSTE))
+#define Is_reset_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_DEVIMR & AT91C_OTGHS_EORST)
+/// acks USB reset
+#define Usb_ack_reset() AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_EORST
+/// tests if USB reset occurs
+#define Is_usb_reset() (AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_OTGHS_EORST)
+
+/// enables Start Of Frame Interrupt
+#define Usb_enable_sof_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIER = AT91C_OTGHS_SOF
+/// disables Start Of Frame Interrupt
+//#define Usb_disable_sof_interrupt() (UDIEN &= ~(1<<SOFE))
+#define Usb_disable_sof_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIDR = AT91C_OTGHS_SOF
+#define Is_sof_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_DEVIMR & AT91C_OTGHS_SOF)
+/// acks Start Of Frame
+#define Usb_ack_sof() AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_SOF
+/// tests if Start Of Frame occurs
+#define Is_usb_sof() (AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_OTGHS_SOF)
+
+/// enables suspend state interrupt
+#define Usb_enable_suspend_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIER = AT91C_OTGHS_SUSP
+/// disables suspend state interrupt
+//#define Usb_disable_suspend_interrupt() (UDIEN &= ~(1<<SUSPE))
+#define Usb_disable_suspend_interrupt() AT91C_BASE_OTGHS->OTGHS_DEVIDR = AT91C_OTGHS_SUSP
+#define Is_suspend_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_DEVIMR & AT91C_OTGHS_SUSP)
+/// acks Suspend
+#define Usb_ack_suspend() AT91C_BASE_OTGHS->OTGHS_DEVICR = AT91C_OTGHS_SUSP
+/// tests if Suspend state detected
+#define Is_usb_suspend() (AT91C_BASE_OTGHS->OTGHS_DEVISR & AT91C_OTGHS_SUSP)
+
+/// returns the last frame number
+//#define Usb_frame_number() ((unsigned short)((((unsigned short)UDFNUMH) << 8) | ((unsigned short)UDFNUML)))
+/// tests if a crc error occurs in frame number
+//#define Is_usb_frame_number_crc_error() ((UDMFN & (1<<FNCERR)) ? TRUE : FALSE)
+/// @}
+#define UDFNUML ((AT91C_BASE_OTGHS->OTGHS_DEVFNUM&AT91C_OTGHS_FRAME_NUMBER)>>3)
+
+
+// ****************************************************************************
+// ****************************************************************************
+// H O S T
+// ****************************************************************************
+// ****************************************************************************
+
+/// @defgroup host_management USB host controller drivers
+/// These macros manage the USB Host controller.
+/// @{
+/// allocates the current configuration in DPRAM memory
+//#define Host_allocate_memory() (UPCFG1X |= (1<<ALLOC))
+#define Host_allocate_memory()
+/// un-allocates the current configuration in DPRAM memory
+//#define Host_unallocate_memory() (UPCFG1X &= ~(1<<ALLOC))
+#define Host_unallocate_memory()
+
+extern void host_configure_pipe(U8 pip, U8 type, U8 token, U8 ep_num, U8 size, U8 bank, U8 freq);
+
+#define Is_usb_pipe_configured(pip) \
+ ((0 == (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[pip] & AT91C_OTGHS_CFGOK))?FALSE:TRUE)
+
+/// enables SOF generation
+//#define Host_enable_sof() (UHCON |= (1<<SOFEN))
+#define Host_enable_sof() AT91C_BASE_OTGHS->OTGHS_HSTCTRL |= AT91C_OTGHS_SOFHST
+
+/// disables SOF generation
+#define Host_disable_sof() AT91C_BASE_OTGHS->OTGHS_HSTCTRL &= ~(unsigned int)AT91C_OTGHS_SOFHST
+
+/// sends a USB Reset to the device
+#define Host_send_reset() AT91C_BASE_OTGHS->OTGHS_HSTCTRL |= AT91C_OTGHS_RESET
+// *AT91C_OTGHS_TSTA2 |= AT91C_OTGHS_FORCHSRST;
+// *AT91C_OTGHS_TSTA2 |= AT91C_OTGHS_UTMIRESET;
+// *AT91C_OTGHS_TSTA2 &= ~AT91C_OTGHS_UTMIRESET
+
+/// tests if USB Reset running
+#define Is_host_sending_reset() (AT91C_BASE_OTGHS->OTGHS_HSTCTRL&AT91C_OTGHS_RESET)
+//#define Host_is_reset() ((UHCON & (1<<RESET)) ? TRUE : FALSE)
+#define Host_is_reset() (AT91C_BASE_OTGHS->OTGHS_HSTCTRL&AT91C_OTGHS_RESET)
+#define Is_host_reset() (AT91C_BASE_OTGHS->OTGHS_HSTCTRL&AT91C_OTGHS_RESET)
+
+/// sends a USB Resume to the device
+#define Host_send_resume() AT91C_BASE_OTGHS->OTGHS_HSTCTRL |= AT91C_OTGHS_RESUME
+/// tests if USB Resume running
+//#define Host_is_resume() ((UHCON & (1<<RESUME)) ? TRUE : FALSE)
+#define Host_is_resume() (AT91C_BASE_OTGHS->OTGHS_HSTCTRL&AT91C_OTGHS_RESUME)
+
+/// enables host start of frame interrupt
+//#define Host_enable_sof_interrupt() (UHIEN |= (1<<HSOFE))
+#define Host_enable_sof_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIER = AT91C_OTGHS_HSOFI
+/// enables host start of frame interrupt
+#define Host_disable_sof_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_HSOFI
+#define Is_host_sof_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_HSTIMR&AT91C_OTGHS_HSOFI)
+/// tests if SOF detected
+//#define Host_is_sof() ((UHINT & (1<<HSOFI)) ? TRUE : FALSE)
+#define Is_host_sof() (AT91C_BASE_OTGHS->OTGHS_HSTISR&AT91C_OTGHS_HSOFI)
+#define Host_ack_sof() AT91C_BASE_OTGHS->OTGHS_HSTICR = AT91C_OTGHS_HSOFI
+
+/// enables host wake up interrupt detection
+#define Host_enable_hwup_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIER = AT91C_OTGHS_HWUPI
+/// disables host wake up interrupt detection
+#define Host_disable_hwup_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_HWUPI
+#define Is_host_hwup_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_HSTIMR&AT91C_OTGHS_HWUPI)
+/// tests if host wake up detected
+//#define Host_is_hwup() ((UHINT & (1<<HWUPI)) ? TRUE : FALSE)
+/// Ack host wake up detection
+#define Is_host_hwup() (AT91C_BASE_OTGHS->OTGHS_HSTISR&AT91C_OTGHS_HWUPI)
+#define Host_ack_hwup() AT91C_BASE_OTGHS->OTGHS_HSTICR = AT91C_OTGHS_HWUPI
+
+
+/// enables host down stream rsm sent interrupt detection
+#define Host_enable_down_stream_resume_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIER = AT91C_OTGHS_RSMEDI
+/// disables host down stream rsm sent interrupt detection
+#define Host_disable_down_stream_resume_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_RSMEDI
+//#define Is_host_down_stream_resume_interrupt_enabled() ((UHIEN & (1<<RSMEDE)) ? TRUE : FALSE)
+/// Ack host down stream resume sent
+//#define Is_host_down_stream_resume() ((UHINT & (1<<RSMEDI)) ? TRUE : FALSE)
+#define Is_host_down_stream_resume() (AT91C_BASE_OTGHS->OTGHS_HSTISR&AT91C_OTGHS_RSMEDI)
+//#define Host_ack_down_stream_resume() (UHINT &= ~(1<<RSMEDI))
+#define Host_ack_down_stream_resume() AT91C_BASE_OTGHS->OTGHS_HSTICR = AT91C_OTGHS_RSMEDI
+
+/// enables host remote wake up interrupt detection
+//#define Host_enable_remote_wakeup_interrupt() (UHIEN |= (1<<RXRSME))
+#define Host_enable_remote_wakeup_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIER = AT91C_OTGHS_RXRSMI
+/// disables host remote wake up interrupt detection
+//#define Host_disable_remote_wakeup_interrupt() (UHIEN &= ~(1<<RXRSME))
+#define Host_disable_remote_wakeup_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_RXRSMI
+//#define Is_host_remote_wakeup_interrupt_enabled() ((UHIEN & (1<<RXRSME)) ? TRUE : FALSE)
+#define Is_host_remote_wakeup_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_HSTISR&AT91C_OTGHS_RXRSMI)
+/// tests if host wake up detected
+//#define Host_is_remote_wakeup() ((UHINT & (1<<RXRSMI)) ? TRUE : FALSE)
+/// Ack host wake up detection
+//#define Is_host_remote_wakeup() ((UHINT & (1<<RXRSMI)) ? TRUE : FALSE)
+#define Is_host_remote_wakeup() ((AT91C_BASE_OTGHS->OTGHS_HSTISR&AT91C_OTGHS_RXRSMI) == AT91C_OTGHS_RXRSMI)
+#define Host_ack_remote_wakeup() AT91C_BASE_OTGHS->OTGHS_HSTICR = AT91C_OTGHS_RXRSMI
+
+#define Host_disable_device_connection_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_DCONN
+/// enables host device connection interrupt
+//#define Host_enable_device_connection_interrupt() (UHIEN |= (1<<DCONNE))
+#define Host_enable_device_connection_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIER = AT91C_OTGHS_DCONN
+/// disables USB device connection interrupt
+//#define Host_disable_device_connection_interrupt() (UHIEN &= ~(1<<DCONNE))
+#define Is_host_device_connection_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_HSTIMR & AT91C_OTGHS_DCONN)
+/// tests if a USB device has been detected
+//#define Is_device_connection() (UHINT & (1<<DCONNI))
+#define Is_device_connection() (AT91C_BASE_OTGHS->OTGHS_HSTISR & AT91C_OTGHS_DCONN)
+#define Is_host_device_connection() (AT91C_BASE_OTGHS->OTGHS_HSTISR & AT91C_OTGHS_DCONN)
+/// acks device connection
+//#define Host_ack_device_connection() (UHINT = ~(1<<DCONNI))
+#define Host_ack_device_connection() AT91C_BASE_OTGHS->OTGHS_HSTICR = AT91C_OTGHS_DCONN
+
+/// tests if a USB device has been removed
+//#define Is_device_disconnection() (UHINT & (1<<DDISCI) ? TRUE : FALSE)
+#define Is_device_disconnection() (AT91C_BASE_OTGHS->OTGHS_HSTISR & AT91C_OTGHS_DDIS)
+/// enables host device disconnection interrupt
+//#define Host_enable_device_disconnection_interrupt() (UHIEN |= (1<<DDISCE))
+#define Host_enable_device_disconnection_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIER = AT91C_OTGHS_DDIS
+/// disables USB device connection interrupt
+//#define Host_disable_device_disconnection_interrupt() (UHIEN &= ~(1<<DDISCE))
+#define Host_disable_device_disconnection_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_DDIS
+//#define Is_host_device_disconnection_interrupt_enabled() ((UHIEN & (1<<DDISCE)) ? TRUE : FALSE)
+#define Is_host_device_disconnection_interrupt_enabled() (AT91C_BASE_OTGHS->OTGHS_HSTIMR & AT91C_OTGHS_DDIS)
+/// tests if a USB device has been removed
+//#define Is_device_disconnection() (UHINT & (1<<DDISCI) ? TRUE : FALSE)
+//#define Is_host_device_disconnection() (AT91C_BASE_OTGHS->OTGHS_HSTISR & AT91C_OTGHS_DDIS)
+/// acks device disconnection
+//#define Host_ack_device_disconnection() (UHINT = ~(1<<DDISCI))
+#define Host_ack_device_disconnection() AT91C_BASE_OTGHS->OTGHS_HSTICR = AT91C_OTGHS_DDIS
+
+#define host_get_device_descriptor_incomplete() (usb_request.uncomplete_read == TRUE)
+#define Host_enable_reset_sent_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIER = AT91C_OTGHS_RSTI
+
+
+#define Host_disable_reset_sent_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_RSTI
+/// enables host USB reset interrupt
+//#define Host_enable_reset_interrupt() (UHIEN |= (1<<RSTE))
+/// disables host USB reset interrupt
+//#define Host_disable_reset_interrupt() (UHIEN &= ~(1<<RSTE))
+#define Host_disable_reset_interrupt() (AT91C_BASE_OTGHS->OTGHS_HSTIDR = AT91C_OTGHS_RSTI)
+//#define Is_host_reset_interrupt_enabled() ((UHIEN & (1<<RSTE)) ? TRUE : FALSE)
+/// acks host USB reset sent
+//#define Host_ack_reset() (UHINT = ~(1<<RSTI))
+#define Host_ack_reset() AT91C_BASE_OTGHS->OTGHS_HSTICR = AT91C_OTGHS_RSTI
+/// tests if USB reset has been sent
+
+
+/// switches on VBus
+//#define Host_vbus_request() (OTGCON |= (1<<VBUSREQ))
+/// switches off VBus
+//#define Host_clear_vbus_request() (OTGCON |= (1<<VBUSRQC))
+#define Host_clear_vbus_request() AT91C_BASE_OTGHS->OTGHS_SCR = AT91C_OTGHS_VBUSRQ //JCB
+/// configures the address to use for the device
+//#define Host_configure_address(addr) (UHADDR = addr & MSK_HADDR)
+//#define Host_configure_address(addr) AT91C_BASE_OTGHS->OTGHS_HSTCTRL |= addr & 0x3F
+//#define Host_configure_address(addr) AT91C_BASE_OTGHS->OTGHS_HSTADDR1 &= ~AT91C_OTGHS_UHADDR_P0;
+// AT91C_BASE_OTGHS->OTGHS_HSTADDR1 |= (addr & AT91C_OTGHS_UHADDR_P0)
+
+/// Get connected device speed, returns TRUE when in full speed mode
+#define Is_host_full_speed() (AT91C_BASE_OTGHS->OTGHS_SR&AT91C_OTGHS_SPEED)
+/// @}
+
+#define Usb_disable_otg_pad() AT91C_BASE_OTGHS->OTGHS_CTRL &= ~(unsigned int)AT91C_OTGHS_OTGPADE
+
+
+
+/// @defgroup general_pipe USB pipe drivers
+/// These macros manage the common features of the pipes.
+/// @{
+/// selects pipe for CPU interface
+//#define Host_select_pipe(p) (UPNUM = (unsigned char)p)
+#define Host_select_pipe(p) global_pipe_nb = p
+
+/// get the currently selected pipe number
+//#define Host_get_selected_pipe() (UPNUM )
+#define Host_get_selected_pipe() (global_pipe_nb)
+
+/// enables pipe
+//#define Host_enable_pipe() (UPCONX |= (1<<PEN))
+#define Host_enable_pipe() AT91C_BASE_OTGHS->OTGHS_HSTPIP |= (1<<global_pipe_nb)
+/// disables pipe
+//#define Host_disable_pipe() (UPCONX &= ~(1<<PEN))
+#define Host_disable_pipe() AT91C_BASE_OTGHS->OTGHS_HSTPIP &= ~(unsigned int)(1<<global_pipe_nb)
+
+/// sets SETUP token
+//#define Host_set_token_setup() (UPCFG0X = UPCFG0X & ~MSK_TOKEN_SETUP) AT91C_OTGHS_PTOKEN
+#define Host_set_token_setup() AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb] &= ~(unsigned int)AT91C_OTGHS_PTOKEN;\
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb] |= AT91C_OTGHS_PTOKEN_SETUP
+/// sets IN token
+//#define Host_set_token_in() (UPCFG0X = (UPCFG0X & ~MSK_TOKEN_SETUP) | MSK_TOKEN_IN)
+#define Host_set_token_in() AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb] &= ~(unsigned int)AT91C_OTGHS_PTOKEN;\
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb] |= AT91C_OTGHS_PTOKEN_IN
+/// sets OUT token
+//#define Host_set_token_out() (UPCFG0X = (UPCFG0X & ~MSK_TOKEN_SETUP) | MSK_TOKEN_OUT)
+#define Host_set_token_out() AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb] &= ~(unsigned int)AT91C_OTGHS_PTOKEN;\
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb] |= AT91C_OTGHS_PTOKEN_OUT
+
+/// returns the number of the endpoint associated to the current pipe
+//#define Host_get_endpoint_number() (UPCFG0X & (1<<MSK_PEPNUM))
+//#define Host_get_endpoint_number() (UPCFG0X & (MSK_PEPNUM))
+#define Host_get_endpoint_number() (unsigned char)((AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb]&AT91C_OTGHS_PEPNUM)>>16)
+
+/// returns pipe interrupt register
+#define Host_get_pipe_interrupt() ((AT91C_BASE_OTGHS->OTGHS_HSTISR>>8)&0x7F)
+
+/// sets the interrupt frequency
+//#define Host_set_interrupt_frequency(pip, frq) (AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[pip]|=AT91C_OTGHS_INTFRQ&(frq<<24))
+
+/// tests if current pipe is configured
+#define Is_pipe_configured() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb]&AT91C_OTGHS_CFGOK)
+/// tests if at least one bank is busy
+//#define Is_host_one_bank_busy() ((UPSTAX & (1<<MSK_NBUSYBK)) != 0)
+#define Is_host_one_bank_busy(pip) ((AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[pip]&AT91C_OTGHS_NBUSYBK)!=0)
+/// returns the number of busy banks
+//#define Host_number_of_busy_bank() (UPSTAX & (1<<MSK_NBUSYBK))
+
+/// resets the pipe
+//#define Host_reset_pipe(p) (UPRST = 1<<p , UPRST = 0)
+#define Host_reset_pipe(pip) AT91C_BASE_OTGHS->OTGHS_HSTPIP|=(1<<16<<pip);\
+ AT91C_BASE_OTGHS->OTGHS_HSTPIP&=~(unsigned int)(1<<16<<pip)
+
+/// writes a byte into the pipe FIFO
+//#define Host_write_byte(dat) (UPDATX = dat)
+//#define Host_write_byte(data) AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0[global_pipe_nb << 14]=data
+//#define Host_write_byte(data) (((char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0))[dBytes++])=data
+#define Host_write_byte(data) pFifo[dBytes++]=data
+
+#define Host_write_32(data) AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0[0]=data
+/// reads a byte from the pipe FIFO
+//#define Host_read_byte() (UPDATX)
+//#define Host_read_byte() (U8)(((char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0))[dBytes++])
+#define Host_read_byte() pFifo[dBytes++]
+//#define Host_read_byte_index(pip, index) pfifo[index] = pEndpoint->pData[index++];
+//#define Host_read_32(pip) AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0[pip << 14]
+
+/// freezes the pipe
+//#define Host_freeze_pipe() (UPCONX |= (1<<PFREEZE))
+//#define Host_freeze_pipe() TRACE_DEBUG("freeze\n\r");AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[global_pipe_nb] = AT91C_OTGHS_FREEZE
+#define Host_freeze_pipe() AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[global_pipe_nb] = AT91C_OTGHS_FREEZE
+/// un-freezees the pipe
+//#define Host_unfreeze_pipe() (UPCONX &= ~(1<<PFREEZE))
+//#define Host_unfreeze_pipe() TRACE_DEBUG("unfreeze\n\r");while(!(AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[global_pipe_nb] & AT91C_OTGHS_FREEZE));
+// AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_FREEZE
+#define Host_unfreeze_pipe() while(!(AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[global_pipe_nb] & AT91C_OTGHS_FREEZE));\
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_FREEZE
+/// tests if the current pipe is frozen
+//#define Is_host_pipe_freeze() (UPCONX & (1<<PFREEZE))
+#define Is_host_pipe_freeze() (AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[global_pipe_nb] & AT91C_OTGHS_FREEZE)
+
+/// resets data toggle
+#define Host_reset_pipe_data_toggle(pip) AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[pip] = AT91C_OTGHS_RSTDT
+
+/// tests if SETUP has been sent
+#define Is_host_setup_sent() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[0] & AT91C_OTGHS_TXSTPI)
+/// tests if control IN has been received
+#define Is_host_control_in_received() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[0] & AT91C_OTGHS_RXINI)
+/// tests if control OUT has been sent
+//#define Is_host_control_out_sent() ((UPINTX & (1<<TXOUTI)) ? TRUE : FALSE)
+#define Is_host_control_out_sent() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[0] & AT91C_OTGHS_TXOUT)
+/// tests if a STALL has been received
+//#define Is_host_stall() ((UPINTX & (1<<RXSTALLI)) ? TRUE : FALSE)
+#define Is_host_stall() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb] & AT91C_OTGHS_RXSTALL)
+/// tests if an error occurs on current pipe
+//#define Is_host_pipe_error() ((UPINTX & (1<<PERRI)) ? TRUE : FALSE)
+#define Is_host_pipe_error() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb] & AT91C_OTGHS_PERR)
+
+/// sends a setup
+//#define Host_send_setup() (UPINTX &= ~(1<<FIFOCON))
+#define Host_send_setup() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[0] = AT91C_OTGHS_FIFOCON
+/// sends a control IN
+//#define Host_send_control_in() (UPINTX &= ~(1<<FIFOCON))
+#define Host_send_control_in() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[0] = AT91C_OTGHS_FIFOCON
+#define Host_send_control() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[0] = AT91C_OTGHS_FIFOCON
+/// sends a control OUT
+//#define Host_send_control_out() (UPINTX &= ~(1<<FIFOCON))
+#define Host_send_control_out() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[0] = AT91C_OTGHS_FIFOCON
+
+/// acks control OUT
+//#define Host_ack_control_out() (UPINTX &= ~(1<<TXOUTI))
+#define Host_ack_control_out() AT91C_BASE_OTGHS->OTGHS_HSTPIPICR[0] = AT91C_OTGHS_TXOUT
+/// acks control IN
+//#define Host_ack_control_in() (UPINTX &= ~(1<<RXINI))
+#define Host_ack_control_in() AT91C_BASE_OTGHS->OTGHS_HSTPIPICR[0] = AT91C_OTGHS_RXINI
+/// acks setup
+//#define Host_ack_setup() (UPINTX &= ~(1<<TXSTPI))
+#define Host_ack_setup() AT91C_BASE_OTGHS->OTGHS_HSTPIPICR[0] = AT91C_OTGHS_TXSTPI
+/// acks STALL reception
+//#define Host_ack_stall() (UPINTX &= ~(1<<RXSTALLI))
+#define Host_ack_stall() AT91C_BASE_OTGHS->OTGHS_HSTPIPICR[global_pipe_nb] = AT91C_OTGHS_RXSTALL
+
+/// sends a OUT
+//#define Host_send_out() (UPINTX &= ~(1<<FIFOCON))
+#define Host_send_out() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_FIFOCON
+/// tests if OUT has been sent
+//#define Is_host_out_sent() ((UPINTX & (1<<TXOUTI)) ? TRUE : FALSE)
+#define Is_host_out_sent() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb] & AT91C_OTGHS_TXOUT)
+/// acks OUT sent
+//#define Host_ack_out_sent() (UPINTX &= ~(1<<TXOUTI))
+#define Host_ack_out_sent() AT91C_BASE_OTGHS->OTGHS_HSTPIPICR[global_pipe_nb] = AT91C_OTGHS_TXOUT
+
+/// tests if IN received
+//#define Is_host_in_received() ((UPINTX & (1<<RXINI)) ? TRUE : FALSE)
+#define Is_host_in_received() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb] & AT91C_OTGHS_RXINI)
+/// acks IN reception
+//#define Host_ack_in_received() (UPINTX &= ~(1<<RXINI))
+#define Host_ack_in_received() AT91C_BASE_OTGHS->OTGHS_HSTPIPICR[global_pipe_nb] = AT91C_OTGHS_RXINI
+/// sends a IN
+//#define Host_send_in() (UPINTX &= ~(1<<FIFOCON))
+#define Host_send_in() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_FIFOCON
+/// tests if nak handshake has been received
+//#define Is_host_nak_received() ((UPINTX & (1<<NAKEDI)) ? TRUE : FALSE)
+#define Is_host_nak_received() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb] & AT91C_OTGHS_NAKEDI)
+/// acks NAk received sent
+//#define Host_ack_nak_received() (UPINTX &= ~(1<<NAKEDI))
+#define Host_ack_nak_received() AT91C_BASE_OTGHS->OTGHS_HSTPIPICR[global_pipe_nb] = AT91C_OTGHS_NAKEDI
+
+/// tests if endpoint read allowed
+//#define Is_host_read_enabled() (UPINTX&(1<<RWAL))
+#define Is_host_read_enabled() (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb] & AT91C_OTGHS_RWALL)
+/// tests if endpoint read allowed
+//#define Is_host_write_enabled() (UPINTX&(1<<RWAL))
+
+/// sets IN in standard mode
+//#define Host_standard_in_mode() (UPCONX &= ~(1<<INMODE))
+#define Host_standard_in_mode() AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[global_pipe_nb] &= ~(unsigned int)AT91C_OTGHS_INMOD
+/// sets IN in continuous mode
+//#define Host_continuous_in_mode() (UPCONX |= (1<<INMODE))
+#define Host_continuous_in_mode() AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[global_pipe_nb] |= AT91C_OTGHS_INMOD
+
+/// sets number of IN requests to perform before freeze
+//#define Host_in_request_number(in_num) (UPINRQX = (unsigned char)in_num)
+#define Host_in_request_number(pip, in_num) AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[pip] &= ~(unsigned int)AT91C_OTGHS_INMOD;\
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[pip] &= ~(unsigned int)AT91C_OTGHS_INRQ;\
+ AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[pip] |= in_num
+/// returns number of remaining IN requests
+//#define Host_get_in_request_number() (UPINRQX)
+
+/// returns number of bytes (8 bits)
+//#define Host_data_length_U8() (UPBCLX)
+#define Host_data_length_U8() (unsigned short)((AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb]&AT91C_OTGHS_PBYCT)>>20)
+#define UPBCLX (unsigned short)((AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb]&AT91C_OTGHS_PBYCT)>>20)
+
+/// returns number of bytes (16 bits)
+//#define Host_data_length_U16() ((((unsigned short)UPBCHX)<<8) | UPBCLX)
+#define Host_data_length_U16() (unsigned short)((AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[global_pipe_nb]&AT91C_OTGHS_PBYCT)>>20)
+/// for device compatibility
+//#define Host_byte_counter() Host_data_length_U16()
+#define Host_byte_counter() Host_data_length_U16()
+/// for device compatibility
+//#define Host_byte_counter_8() Host_data_length_U8()
+
+/// returns the size of the current pipe
+//#define Host_get_pipe_length() ((unsigned short)0x08 << ((UPCFG1X & MSK_PSIZE)>>4))
+//#define Host_get_pipe_length() (unsigned short)(((AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb]&AT91C_OTGHS_PSIZE)>>4)?
+// (8<<((AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb]&AT91C_OTGHS_PSIZE)>>4)):8)
+
+/// returns the type of the current pipe
+//#define Host_get_pipe_type() (UPCFG0X>>6)
+#define Host_get_pipe_type() ((AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[global_pipe_nb]&AT91C_OTGHS_PTYPE)>>12)
+
+/// tests if error occurs on pipe
+//#define Host_error_status() (UPERRX & MSK_ERROR)
+#define Host_error_status() (unsigned long)(AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[global_pipe_nb])
+/// acks all pipe error
+//#define Host_ack_all_errors() (UPERRX = 0x00)
+#define Host_ack_all_errors() AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[global_pipe_nb] = 0
+
+/// Enable pipe end transmission interrupt
+//#define Host_enable_transmit_interrupt() (UPIENX |= (1<<TXOUTE))
+#define Host_enable_transmit_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[global_pipe_nb] = AT91C_OTGHS_TXOUT
+/// Disable pipe end transmission interrupt
+//#define Host_disable_transmit_interrupt() (UPIENX &= ~(1<<TXOUTE))
+#define Host_disable_transmit_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_TXOUT
+
+/// Enable pipe reception interrupt
+//#define Host_enable_receive_interrupt() (UPIENX |= (1<<RXINE))
+#define Host_enable_receive_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[global_pipe_nb] = AT91C_OTGHS_RXINI
+/// Disable pipe recption interrupt
+//#define Host_disable_receive_interrupt() (UPIENX &= ~(1<<RXINE))
+#define Host_disable_receive_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_RXINI
+
+/// Enable pipe stall interrupt
+//#define Host_enable_stall_interrupt() (UPIENX |= (1<<RXSTALLE))
+#define Host_enable_stall_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[global_pipe_nb] = AT91C_OTGHS_RXSTALL
+/// Disable pipe stall interrupt
+//#define Host_disable_stall_interrupt() (UPIENX &= ~(1<<RXSTALLE))
+#define Host_disable_stall_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_RXSTALL
+
+/// Enable pipe error interrupt
+//#define Host_enable_error_interrupt() (UPIENX |= (1<<PERRE))
+#define Host_enable_error_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[global_pipe_nb] = AT91C_OTGHS_PERR
+/// Disable pipe error interrupt
+//#define Host_disable_error_interrupt() (UPIENX &= ~(1<<PERRE))
+#define Host_disable_error_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_PERR
+
+/// Enable pipe NAK interrupt
+//#define Host_enable_nak_interrupt() (UPIENX |= (1<<NAKEDE))
+#define Host_enable_nak_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIER[global_pipe_nb] = AT91C_OTGHS_NAKEDI
+/// Disable pipe NAK interrupt
+//#define Host_disable_nak_interrupt() (UPIENX &= ~(1<<NAKEDE))
+#define Host_disable_nak_interrupt() AT91C_BASE_OTGHS->OTGHS_HSTPIPIDR[global_pipe_nb] = AT91C_OTGHS_NAKEDI
+
+//#define Get_pipe_token(x) ((x & (0x80)) ? TOKEN_IN : TOKEN_OUT)
+#define Get_pipe_token(x) ((x & (0x80)) ? TOKEN_IN : TOKEN_OUT)
+
+
+//_____ D E C L A R A T I O N ______________________________________________
+
+extern unsigned char dev_configure_endpoint(unsigned char ept,
+ unsigned char type,
+ unsigned char dir,
+ unsigned char size,
+ unsigned char bank,
+ unsigned char nyet);
+
+
+extern unsigned char usb_select_enpoint_interrupt (void);
+extern unsigned char usb_send_packet(unsigned char, unsigned char*, unsigned char);
+extern unsigned char usb_read_packet(unsigned char, unsigned char*, unsigned char);
+
+extern unsigned char host_config_pipe(unsigned char, unsigned char);
+extern unsigned char host_determine_pipe_size(unsigned short);
+extern void host_disable_all_pipe(void);
+extern unsigned char host_get_nb_pipe_interrupt(void);
+extern U16 host_get_pipe_length(void);
+extern void host_configure_address( unsigned char pipe, unsigned char addr);
+
+#endif // _USB_DRV_H
+
diff --git a/usb/otg/usb_host_enum.c b/usb/otg/usb_host_enum.c new file mode 100644 index 0000000..69c9ba5 --- /dev/null +++ b/usb/otg/usb_host_enum.c @@ -0,0 +1,670 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/// This file manages the host enumeration process
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <conf_usb.h>
+#include "usb/otg/usb_drv.h"
+#include "usb_host_enum.h"
+#include "usb/otg/usb_task.h"
+#include "usb_host_task.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+#if (MAX_INTERFACE_SUPPORTED<1)
+#error MAX_INTERFACE_SUPPORTED<1 : The host controller should support at least one interface...
+#endif
+
+#ifndef VID_PID_TABLE
+ #error VID_PID_TABLE should be defined somewhere (conf_usb.h)
+ // VID_PID_TABLE format definition:
+ // #define VID_PID_TABLE {VID1, number_of_pid_for_this_VID1, PID11_value,..., PID1X_Value
+ // ...
+ // ,VIDz, number_of_pid_for_this_VIDz, PIDz1_value,..., PIDzX_Value}
+#endif
+
+#ifndef CLASS_SUBCLASS_PROTOCOL
+ #error CLASS_SUBCLASS_PROTOCOL shoud be defined somewhere (conf_usb.h)
+ // CLASS_SUBCLASS_PROTOCOL format definition:
+ // #define CLASS_SUBCLASS_PROTOCOL {CLASS1, SUB_CLASS1,PROTOCOL1,
+ // ...
+ // CLASSz, SUB_CLASSz,PROTOCOLz}
+#endif
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+//! Const table of known devices (see conf_usb.h for table content)
+U16 registered_VID_PID[] = VID_PID_TABLE;
+
+//! Const table of known class (see conf_usb.h for table content)
+U8 registered_class[] = CLASS_SUBCLASS_PROTOCOL;
+
+//! Physical EP to address device endpoints look-up table
+// This table is dynamically built with the "host_configure_endpoint_class" function
+U8 ep_table[MAX_EP_NB]={0,0,0,0,0,0,0};
+
+//! The number of interface the host is able to support in the device connected
+U8 nb_interface_supported=0;
+
+S_interface interface_supported[MAX_INTERFACE_SUPPORTED];
+
+//! PID of device connected
+U16 device_PID;
+//! VID of device connected
+U16 device_VID;
+//! bmAttributes byte of the connected device
+U8 bmattributes;
+//! maxpower byte of the connected device (Caution, unit is 2mA)
+U8 maxpower;
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// checks if the VID and the PID are supported
+/// (if the VID/PID belongs to the VID_PID table)
+//------------------------------------------------------------------------------
+U8 host_check_VID_PID(void)
+{
+ U8 nb_of_vid;
+ U8 nb_of_pid;
+
+ TRACE_DEBUG("host_check_VID_PID\n\r");
+ // Rebuild VID PID from data stage
+ LSB(device_VID) = data_stage[OFFSET_FIELD_LSB_VID];
+ MSB(device_VID) = data_stage[OFFSET_FIELD_MSB_VID];
+ LSB(device_PID) = data_stage[OFFSET_FIELD_LSB_PID];
+ MSB(device_PID) = data_stage[OFFSET_FIELD_MSB_PID];
+
+ // Compare detected VID PID with supported table
+ nb_of_vid=0;
+ while (nb_of_vid< sizeof(registered_VID_PID)/2) // /2 because registered_VID_PID table is U16...
+ {
+ TRACE_DEBUG("registered_VID_PID[%d]: 0x%X\n\r", nb_of_vid, registered_VID_PID[nb_of_vid]);
+ TRACE_DEBUG("device_VID: 0x%X\n\r", device_VID);
+ if (registered_VID_PID[nb_of_vid] == device_VID) // VID is correct
+ {
+ TRACE_DEBUG("Good VID\n\r");
+ nb_of_pid = (U8)registered_VID_PID[nb_of_vid+1]; // store nb of PID for this VID
+ while (nb_of_pid != 0)
+ {
+ TRACE_DEBUG("registered_VID_PID[%d]: 0x%X\n\r", nb_of_vid+nb_of_pid+1, registered_VID_PID[nb_of_vid+nb_of_pid+1]);
+ TRACE_DEBUG("device_PID: 0x%X\n\r", device_PID);
+ if (registered_VID_PID[nb_of_vid+nb_of_pid+1] == device_PID)
+ {
+ TRACE_DEBUG("Good PID\n\r");
+ return HOST_TRUE;
+ }
+ nb_of_pid--;
+ }
+ }
+ nb_of_vid+=registered_VID_PID[nb_of_vid+1]+2;
+ }
+ return HOST_FALSE;
+}
+
+
+//------------------------------------------------------------------------------
+/// checks if the device class is supported.
+/// The function looks in all interface declared in the received dewcriptors, if
+/// one of them match with the CLASS/SUB_CLASS/PROTOCOL table
+//------------------------------------------------------------------------------
+U8 host_check_class(void)
+{
+ U8 class_table;
+ T_DESC_OFFSET descriptor_offset;
+ T_DESC_OFFSET conf_offset_end;
+ U16 config_size;
+ U8 device_class;
+ U8 device_subclass;
+ U8 device_protocol;
+
+ TRACE_DEBUG("host_check_class\n\r");
+ nb_interface_supported=0; //First asumes ,no interface is supported!
+ if (data_stage[OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_CONFIGURATION) // check if configuration descriptor
+ {
+ TRACE_DEBUG("host_check_class problem\n\r");
+ return HOST_FALSE;
+ }
+ LSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT];
+ MSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT+1];
+ bmattributes = data_stage[OFFSET_FIELD_BMATTRIBUTES];
+ maxpower = data_stage[OFFSET_FIELD_MAXPOWER];
+ descriptor_offset = 0;
+ conf_offset_end = descriptor_offset + config_size;
+
+ // Look in all interfaces declared in the configuration
+ while(descriptor_offset < conf_offset_end)
+ {
+ // Find next interface descriptor
+ while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_INTERFACE)
+ {
+ descriptor_offset += data_stage[descriptor_offset];
+ if(descriptor_offset >= conf_offset_end)
+ {
+ if(nb_interface_supported)
+ {
+ TRACE_DEBUG("host_check_class ok\n\r");
+ return HOST_TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG("host_check_class problem2\n\r");
+ return HOST_FALSE;
+ }
+ }
+ }
+ // Found an interface descriptor
+ // Get charateristics of this interface
+ device_class = data_stage[descriptor_offset + OFFSET_FIELD_CLASS];
+ device_subclass = data_stage[descriptor_offset + OFFSET_FIELD_SUB_CLASS];
+ device_protocol = data_stage[descriptor_offset + OFFSET_FIELD_PROTOCOL];
+ // Look in registered class table for match
+ class_table=0;
+ while (class_table< sizeof(registered_class))
+ {
+ if (registered_class[class_table] == device_class) // class is correct!
+ {
+ if (registered_class[class_table+1] == device_subclass) // sub class is correct!
+ {
+ if (registered_class[class_table+2] == device_protocol) // protocol is correct!
+ {
+ // Prepare for another item CLASS/SUB_CLASS/PROTOCOL in table
+ class_table+=3;
+ // Store this interface as supported interface
+ // Memorize its interface nb
+ interface_supported[nb_interface_supported].interface_nb=data_stage[descriptor_offset+OFFSET_FIELD_INTERFACE_NB];
+ // its alternate setting
+ interface_supported[nb_interface_supported].altset_nb=data_stage[descriptor_offset+OFFSET_FIELD_ALT];
+ // its USB class
+ interface_supported[nb_interface_supported].class=device_class;
+ // its USB subclass
+ interface_supported[nb_interface_supported].subclass=device_subclass;
+ // its USB protocol
+ interface_supported[nb_interface_supported].protocol=device_protocol;
+ // the number of endpoints associated to this interface
+ // Note: The associated endpoints addresses are stored during pipe attribution...
+ interface_supported[nb_interface_supported].nb_ep=data_stage[descriptor_offset+OFFSET_FIELS_NB_OF_EP];
+ // Update the number of interface supported
+ nb_interface_supported++;
+ // Check the maximum number of interfaces we can support
+ if(nb_interface_supported>=MAX_INTERFACE_SUPPORTED)
+ {
+ TRACE_DEBUG("host_check_class ok1\n\r");
+ return HOST_TRUE;
+ }
+ }
+ }
+ }
+ class_table+=3; // Check other item CLASS/SUB_CLASS/PROTOCOL in table
+ }
+ descriptor_offset += data_stage[descriptor_offset]; // Next descriptor
+ if(descriptor_offset > SIZEOF_DATA_STAGE) // Check overflow
+ {
+ if(nb_interface_supported)
+ {
+ TRACE_DEBUG("host_check_class ok3\n\r");
+ return HOST_TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG("host_check_class problem3\n\r");
+ return HOST_FALSE;
+ }
+ }
+ }
+ if(nb_interface_supported)
+ {
+ TRACE_DEBUG("host_check_class ok4\n\r");
+ return HOST_TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG("host_check_class problem4\n\r");
+ return HOST_FALSE;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// configures the pipe according to the device class of the
+//------------------------------------------------------------------------------
+U8 host_auto_configure_endpoint(void)
+{
+ U8 nb_endpoint_to_configure;
+ T_DESC_OFFSET descriptor_offset;
+ U8 physical_pipe=1; // =1 cause lookup table assumes that physiacl pipe 0 is reserved for control
+ U8 i;
+ U8 ep_index;
+
+ TRACE_DEBUG("host_auto_configure_endpoint\n\r");
+ // For all interfaces to configure...
+ for(i=0;i<nb_interface_supported;i++)
+ {
+ ep_index=0;
+ // First look for the target interface descriptor offset
+ descriptor_offset = get_interface_descriptor_offset(interface_supported[i].interface_nb,interface_supported[i].altset_nb);
+ // Get the number of endpoint to configure for this interface
+ nb_endpoint_to_configure = data_stage[descriptor_offset+OFFSET_FIELS_NB_OF_EP];
+ // Get the first Endpoint descriptor offset to configure
+ descriptor_offset += data_stage[descriptor_offset+OFFSET_DESCRIPTOR_LENGHT]; // pointing on endpoint descriptor
+
+ // While there is at least one pipe to configure
+ while (nb_endpoint_to_configure)
+ {
+ // Check and look for an Endpoint descriptor
+ while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_ENDPOINT)
+ {
+ descriptor_offset += data_stage[descriptor_offset];
+ if(descriptor_offset > SIZEOF_DATA_STAGE) // No more endpoint descriptor found -> Errror !
+ {
+ TRACE_DEBUG("PB\n\r");
+ return HOST_FALSE;
+ }
+ }
+
+ // Select the new physical pipe to configure and get ride of any previous configuration for this physical pipe
+ Host_select_pipe(physical_pipe);
+ Host_disable_pipe();
+ Host_enable_pipe();
+
+ // Build the pipe configuration according to the endpoint descriptors fields received
+ //
+ // host_configure_pipe(
+ // physical_pipe, // pipe nb in USB interface
+ // data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE], // pipe type (interrupt/BULK/ISO)
+ // Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]), // pipe addr
+ // (data_stage[descriptor_offset+2] & MSK_EP_DIR), // pipe dir (IN/OUT)
+ // host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),// pipe size
+ // ONE_BANK, // bumber of bank to allocate for pipe
+ // data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL] // interrupt period (for interrupt pipe)
+ // );
+
+ host_configure_pipe(
+ physical_pipe,
+ data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],
+ Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),
+ (data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR] & MSK_EP_DIR),
+ host_determine_pipe_size(
+ (U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE_LOW]
+ + (((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE_HIGH])<<8)),
+ ONE_BANK,
+ data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL] );
+
+ host_configure_address(physical_pipe, DEVICE_ADDRESS);
+
+ // Update Physical Pipe lookup table with device enpoint address
+ ep_table[physical_pipe]=data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR];
+ physical_pipe++;
+ // Update endpoint addr table in supported interface structure
+ interface_supported[i].ep_addr[ep_index++]=data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR];
+ descriptor_offset += data_stage[descriptor_offset]; // pointing on next descriptor
+
+ // All target endpoints configured ?
+ nb_endpoint_to_configure--;
+ } //for(i=0;i<nb_interface_supported;i++)
+ }
+ Host_set_configured();
+ return HOST_TRUE;
+}
+
+//------------------------------------------------------------------------------
+/// returns the offset in data_stage where to find the interface descriptor
+/// whose number and alternate setting values are passed as parameters
+//------------------------------------------------------------------------------
+T_DESC_OFFSET get_interface_descriptor_offset(U8 interface, U8 alt)
+{
+ T_DESC_OFFSET descriptor_offset;
+
+ TRACE_DEBUG("get_interface_descriptor_offset\n\r");
+ //nb_interface = data_stage[OFFSET_FIELD_NB_INTERFACE]; // Detects the number of interfaces in this configuration
+ descriptor_offset = data_stage[OFFSET_DESCRIPTOR_LENGHT]; // now pointing on next descriptor
+
+ while(descriptor_offset < SIZEOF_DATA_STAGE) // Look in all interfaces declared in the configuration
+ {
+ while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_INTERFACE)
+ {
+ descriptor_offset += data_stage[descriptor_offset];
+ if(descriptor_offset > SIZEOF_DATA_STAGE)
+ {
+ return HOST_FALSE;
+ }
+ }
+ if (data_stage[descriptor_offset+OFFSET_FIELD_INTERFACE_NB]==interface
+ && data_stage[descriptor_offset+OFFSET_FIELD_ALT]==alt)
+ {
+ return descriptor_offset;
+ }
+ descriptor_offset += data_stage[descriptor_offset];
+ }
+ return descriptor_offset;
+}
+
+//------------------------------------------------------------------------------
+/// returns the physical pipe number linked to a logical endpoint address.
+//------------------------------------------------------------------------------
+U8 host_get_hwd_pipe_nb(U8 ep_addr)
+{
+ U8 i;
+
+ for(i=0; i<MAX_EP_NB; i++)
+ {
+ if(ep_table[i] == ep_addr)
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+/// generic Pipe 0 management function
+/// used to send and receive control request over pipe 0
+//------------------------------------------------------------------------------
+U8 host_send_control(U8* data_pointer)
+{
+ U16 data_length;
+ U8 sav_int_sof_enable;
+ U16 status;
+ int *pFifoInt;
+
+ Usb_ack_event(EVT_HOST_SOF);
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt(); // SOF software detection is in interrupt sub-routine
+ while(Is_not_usb_event(EVT_HOST_SOF)) // Wait 1 sof
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ TRACE_DEBUG("Is_host_emergency_exit\n\r");
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ }
+ if (sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt(); // enter in suspend mode
+ }
+
+ Host_select_pipe(0);
+ Host_set_token_setup();
+ Host_ack_setup();
+ Host_unfreeze_pipe();
+
+ // Send the setup request fields
+ pFifoInt = (int*)&usb_request;
+ Host_write_32(*pFifoInt);
+ pFifoInt++;
+ Host_write_32(*pFifoInt);
+
+ Host_send_setup();
+
+ while(Is_host_setup_sent() == FALSE) // wait for SETUP ack
+ {
+ if (Is_host_emergency_exit())
+ {
+ status = CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error()) // Any error ?
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end; // Send error status
+ }
+ }
+
+ // Setup token sent now send In or OUT token
+ // Before just wait one SOF
+ Usb_ack_event(EVT_HOST_SOF);
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+ Host_freeze_pipe();
+ data_length = usb_request.wLength;
+ while(Is_not_usb_event(EVT_HOST_SOF)) // Wait 1 sof
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ }
+ if (sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt();
+ } // Restore SOF interrupt enable
+
+ // IN request management ---------------------------------------------
+ if(usb_request.bmRequestType & 0x80) // bmRequestType : Data stage IN (bmRequestType==1)
+ {
+ Host_standard_in_mode();
+ //jcb // We send 1 IN
+ // Host_in_request_number(0, 0);
+ Host_set_token_in();
+ while(data_length != 0)
+ {
+ Host_unfreeze_pipe();
+ while(!Is_host_control_in_received())
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+ status = Host_data_length_U8();
+ if (status == host_get_pipe_length())
+ {
+ data_length -= status;
+ if (usb_request.uncomplete_read == TRUE) // uncomplete_read
+ {
+ data_length = 0;
+ }
+ }
+ else
+ {
+ data_length = 0;
+ }
+ Address_fifochar_endpoint(0);
+
+ while (status!=0)
+ {
+ *data_pointer = Host_read_byte();
+ data_pointer++;
+ status--;
+ }
+ Host_freeze_pipe();
+ Host_ack_control_in();
+ Host_send_control_in();
+ //jcb
+ // if( 0 != data_length )
+ // {
+ // Host_unfreeze_pipe();
+ // }
+ } // end of IN data stage
+ Host_set_token_out();
+ Host_unfreeze_pipe();
+ Host_ack_control_out();
+ Host_send_control_out();
+
+ while(!Is_host_control_out_sent())
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+
+ // Test Low Speed
+ if( AT91C_OTGHS_SPEED_SR_LS == (*AT91C_OTGHS_SR & AT91C_OTGHS_SPEED_SR_LS)) {
+ TRACE_DEBUG("LOW SPEED\n\r");
+ // Reset UTMI
+ *AT91C_OTGHS_TSTA2 |= AT91C_OTGHS_UTMIRESET;
+ *AT91C_OTGHS_TSTA2 &= ~(unsigned int)AT91C_OTGHS_UTMIRESET;
+ }
+ Host_ack_control_out();
+ // Wait end of transfer
+ while( (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[0] & AT91C_OTGHS_TXSTPI) != 0);
+ // Freeze the pipe
+ Host_freeze_pipe();
+
+ status=(CONTROL_GOOD);
+ goto host_send_control_end;
+ }
+
+ // OUT request management ---------------------------------------------
+ else // Data stage OUT (bmRequestType==0)
+ {
+ Host_set_token_out();
+ Host_ack_control_out();
+ while(data_length != 0)
+ {
+ Host_unfreeze_pipe();
+ status = host_get_pipe_length();
+ if ( (U16)status > data_length)
+ {
+ status = (U8)data_length;
+ data_length = 0;
+ }
+ else
+ {
+ data_length -= status;
+ }
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (status!=0)
+ {
+ Host_write_byte(*data_pointer);
+ data_pointer++;
+ status--;
+ }
+ Host_send_control_out();
+ while (!Is_host_control_out_sent())
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+ Host_ack_control_out();
+ } // end of OUT data stage
+ Host_freeze_pipe();
+ Host_set_token_in();
+ Host_unfreeze_pipe();
+ while(!Is_host_control_in_received())
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+ Host_ack_control_in();
+ Host_freeze_pipe();
+ Host_send_control_in();
+ status=(CONTROL_GOOD);
+ goto host_send_control_end;
+ }
+
+host_send_control_end:
+ return ((U8)status);
+}
+
+
diff --git a/usb/otg/usb_host_enum.h b/usb/otg/usb_host_enum.h new file mode 100644 index 0000000..959cb52 --- /dev/null +++ b/usb/otg/usb_host_enum.h @@ -0,0 +1,329 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef _USB_HOST_ENUM_H_
+#define _USB_HOST_ENUM_H_
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <usb/common/core/USBFeatureRequest.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/otg/usb_task.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+#ifndef SIZEOF_DATA_STAGE
+ #error SIZEOF_DATA_STAGE should be defined in conf_usb.h
+#endif
+
+#if (SIZEOF_DATA_STAGE<0xFF) //! Optimize descriptor offset index according to data_stage[] size
+ #define T_DESC_OFFSET U8 //! U8 is enought and faster
+#else
+ #define T_DESC_OFFSET U16 //! U16 required !
+#endif
+
+#ifndef MAX_EP_PER_INTERFACE
+ #define MAX_EP_PER_INTERFACE 4
+#endif
+
+
+
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+typedef struct
+{
+ U8 bmRequestType; //!< Characteristics of the request
+ U8 bRequest; //!< Specific request
+ U16 wValue; //!< field that varies according to request
+ U16 wIndex; //!< field that varies according to request
+ U16 wLength; //!< Number of bytes to transfer if Data
+ U8 uncomplete_read; //!< 1 = only one read
+} S_usb_setup_data;
+
+
+typedef struct
+{
+ U8 interface_nb;
+ U8 altset_nb;
+ U16 class;
+ U16 subclass;
+ U16 protocol;
+ U8 nb_ep;
+ U8 ep_addr[MAX_EP_PER_INTERFACE];
+} S_interface;
+
+#define CONTROL_GOOD 0
+#define CONTROL_TIMEOUT 0x08
+#define CONTROL_STALL 0x20
+
+
+//!< Set of defines for offset in data stage
+#define OFFSET_FIELD_MAXPACKETSIZE 7
+#define OFFSET_FIELD_MSB_VID 9
+#define OFFSET_FIELD_LSB_VID 8
+#define OFFSET_FIELD_MSB_PID 11
+#define OFFSET_FIELD_LSB_PID 10
+
+#define OFFSET_DESCRIPTOR_LENGHT 0
+#define OFFSET_FIELD_DESCRIPTOR_TYPE 1
+#define OFFSET_FIELD_TOTAL_LENGHT 2
+#define OFFSET_FIELD_BMATTRIBUTES 7
+#define OFFSET_FIELD_MAXPOWER 8
+
+#define OFFSET_FIELD_OTG_FEATURES 2
+#define OTG_DESCRIPTOR_bLength 0x03
+
+//! OFFSET for INTERFACE DESCRIPTORS
+#define OFFSET_FIELD_INTERFACE_NB 2
+#define OFFSET_FIELD_ALT 3
+#define OFFSET_FIELS_NB_OF_EP 4
+#define OFFSET_FIELD_NB_INTERFACE 4 // Nb of endpoint used by this interface
+#define OFFSET_FIELD_CLASS 5
+#define OFFSET_FIELD_SUB_CLASS 6
+#define OFFSET_FIELD_PROTOCOL 7
+
+
+#define OFFSET_FIELD_EP_ADDR 2
+#define OFFSET_FIELD_EP_TYPE 3
+#define OFFSET_FIELD_EP_SIZE_LOW 4
+#define OFFSET_FIELD_EP_SIZE_HIGH 5
+#define OFFSET_FIELD_EP_INTERVAL 6
+
+//! defines for Hub detection
+#define OFFSET_DEV_DESC_CLASS 4 // offset for the CLASS field in the Device Descriptor
+#define HUB_CLASS_CODE 9 // value of Hub CLASS
+
+
+#define HOST_FALSE 0
+#define HOST_TRUE 1
+
+
+//-----------------------------------------------------------------------------
+// Exported macro
+//-----------------------------------------------------------------------------
+
+/// send a clear endpoint request
+#define host_clear_endpoint_feature(ep) (usb_request.bmRequestType = 0x02,\
+ usb_request.bRequest = USBGenericRequest_CLEARFEATURE,\
+ usb_request.wValue = USBFeatureRequest_ENDPOINTHALT << 8,\
+ usb_request.wIndex = ep,\
+ usb_request.wLength = 0,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+/// send a get configuration request
+#define host_get_configuration() (usb_request.bmRequestType = 0x80,\
+ usb_request.bRequest = USBGenericRequest_GETCONFIGURATION,\
+ usb_request.wValue = 0,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 1,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+/// send a set configuration request
+#define host_set_configuration(cfg_nb) (usb_request.bmRequestType = 0x00,\
+ usb_request.bRequest = USBGenericRequest_SETCONFIGURATION,\
+ usb_request.wValue = cfg_nb,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 0,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+/// send a set interface request to specify a specific alt setting for an
+/// interface
+#define host_set_interface(interface_nb,alt_setting) \
+ (usb_request.bmRequestType = 0x00,\
+ usb_request.bRequest = USBGenericRequest_SETINTERFACE,\
+ usb_request.wValue = alt_setting,\
+ usb_request.wIndex = interface_nb,\
+ usb_request.wLength = 0,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+
+/// send a get device desriptor request.
+/// The descriptor table received is stored in data_stage array.
+/// The received descriptors is limited to the control pipe lenght
+#define host_get_device_descriptor_uncomplete() \
+ (usb_request.bmRequestType = 0x80,\
+ usb_request.bRequest = USBGenericRequest_GETDESCRIPTOR,\
+ usb_request.wValue = USBGenericDescriptor_DEVICE << 8,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 64,\
+ usb_request.uncomplete_read = TRUE,\
+ host_send_control(data_stage))
+
+/// send a get device desriptor request.
+/// The descriptor table received is stored in data_stage array.
+#define host_get_device_descriptor() (usb_request.bmRequestType = 0x80,\
+ usb_request.bRequest = USBGenericRequest_GETDESCRIPTOR,\
+ usb_request.wValue = USBGenericDescriptor_DEVICE << 8,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 18,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+/// send a get device configuration request.
+/// The configuration descriptor table received is stored in data_stage array.
+#define host_get_configuration_descriptor()(usb_request.bmRequestType = 0x80,\
+ usb_request.bRequest = USBGenericRequest_GETDESCRIPTOR,\
+ usb_request.wValue = USBGenericDescriptor_CONFIGURATION << 8,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 255,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+
+#define host_get_descriptor_uncomplete() (usb_request.bmRequestType = 0x80,\
+ usb_request.bRequest = USBGenericRequest_GETDESCRIPTOR,\
+ usb_request.wValue = 0,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 64,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+/// send a set address request.
+#define host_set_address(addr) (usb_request.bmRequestType = 0x00,\
+ usb_request.bRequest = USBGenericRequest_SETADDRESS,\
+ usb_request.wValue = (U16)addr,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 0,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+
+/// send a set feature device remote wakeup
+#define host_set_feature_remote_wakeup() (usb_request.bmRequestType = 0x00,\
+ usb_request.bRequest = USBGenericRequest_SETFEATURE,\
+ usb_request.wValue = 1,\
+ usb_request.wIndex = 1,\
+ usb_request.wLength = 0,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+
+/// send a set feature "a_hnp_support" to tell to B-Device that A-Device support HNP
+#define host_set_feature_a_hnp_support() (usb_request.bmRequestType = 0x00,\
+ usb_request.bRequest = USBGenericRequest_SETFEATURE,\
+ usb_request.wValue = 4,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 0,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+
+/// send a set feature "b_hnp_enable" to make B-Device initiating a HNP
+#define host_set_feature_b_hnp_enable() (usb_request.bmRequestType = 0x00,\
+ usb_request.bRequest = USBGenericRequest_SETFEATURE,\
+ usb_request.wValue = 3,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 0,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+
+/// send the mass storage specific request "get max lun"
+#define host_ms_get_max_lun() (usb_request.bmRequestType = 0xA1,\
+ usb_request.bRequest = MS_GET_MAX_LUN,\
+ usb_request.wValue = 0,\
+ usb_request.wIndex = 0,\
+ usb_request.wLength = 1,\
+ usb_request.uncomplete_read = FALSE,\
+ host_send_control(data_stage))
+/// returns the VID of the device connected
+#define Get_VID() (device_VID)
+
+/// returns the PID of the device connected
+#define Get_PID() (device_PID)
+
+/// returns the maximum power consumption ot hte connected device (unit is 2mA)
+#define Get_maxpower() (maxpower)
+
+/// returns the USB class associated to the specified interface
+#define Get_class(s_interface) (interface_supported[s_interface].class)
+
+/// returns the USB subclass associated to the specified interface
+#define Get_subclass(s_interface) (interface_supported[s_interface].subclass)
+
+/// returns the USB protocol associated to the specified interface
+#define Get_protocol(s_interface) (interface_supported[s_interface].protocol)
+
+/// returns endpoint address associated to the specified interface and
+/// endpoint number in this interface.
+#define Get_ep_addr(s_interface,n_ep) (interface_supported[s_interface].ep_addr[n_ep])
+
+/// returns number of endpoints associated to
+#define Get_nb_ep(s_interface) (interface_supported[s_interface].nb_ep)
+
+/// returns number of the alternate setting field associated to
+#define Get_alts_s(s_interface) (interface_supported[s_interface].altset_nb)
+
+/// returns number of the interface number associated to
+#define Get_interface_number(s_interface) (interface_supported[s_interface].interface_nb)
+
+/// returns the number of interface supported in the device connected
+#define Get_nb_supported_interface() (nb_interface_supported)
+
+#define BIT_SELF_POWERED 6 // offset
+/// returns true if the device connected is self powered
+#define Is_device_self_powered() ((bmattributes & (1<<BIT_SELF_POWERED)) ? TRUE : FALSE)
+
+#define BIT_REMOTE_WAKEUP 5 // offset
+/// returns true if the device supports remote wake_up
+#define Is_device_supports_remote_wakeup() ((bmattributes & (1<<BIT_REMOTE_WAKEUP)) ? TRUE : FALSE)
+
+#define BIT_SRP_SUPPORT 0 // offset
+/// returns true if the device supports SRP
+#define Is_device_supports_srp() ((otg_features_supported & (1<<BIT_SRP_SUPPORT)) ? TRUE : FALSE)
+
+#define BIT_HNP_SUPPORT 1 // offset
+/// returns true if the device supports HNP
+#define Is_device_supports_hnp() ((otg_features_supported & (1<<BIT_HNP_SUPPORT)) ? TRUE : FALSE)
+
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+extern U8 ep_table[];
+extern U8 nb_interface_supported;
+extern S_interface interface_supported[MAX_INTERFACE_SUPPORTED];
+extern U16 device_PID;
+extern U16 device_VID;
+extern U8 bmattributes;
+extern U8 maxpower;
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+extern U8 host_check_VID_PID(void);
+extern U8 host_check_OTG_features(void);
+extern U8 host_check_class (void);
+extern U8 host_auto_configure_endpoint(void);
+extern T_DESC_OFFSET get_interface_descriptor_offset(U8 interface, U8 alt);
+extern U8 host_get_hwd_pipe_nb(U8 ep_addr);
+extern U8 host_send_control(U8*);
+
+
+#endif // _USB_HOST_ENUM_H_
+
diff --git a/usb/otg/usb_host_enum_with_srp_hnp.c b/usb/otg/usb_host_enum_with_srp_hnp.c new file mode 100644 index 0000000..0220515 --- /dev/null +++ b/usb/otg/usb_host_enum_with_srp_hnp.c @@ -0,0 +1,754 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+/// This file manages the host enumeration process
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <conf_usb.h>
+#include "usb/otg/usb_drv.h"
+#include "usb_host_enum.h"
+#include "usb/otg/usb_task.h"
+#include "usb_host_task.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGenericDescriptor.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+#if (MAX_INTERFACE_SUPPORTED<1)
+#error MAX_INTERFACE_SUPPORTED<1 : The host controller should support at least one interface...
+#endif
+
+#ifndef VID_PID_TABLE
+ #error VID_PID_TABLE should be defined somewhere (conf_usb.h)
+ // VID_PID_TABLE format definition:
+ // #define VID_PID_TABLE {VID1, number_of_pid_for_this_VID1, PID11_value,..., PID1X_Value
+ // ...
+ // ,VIDz, number_of_pid_for_this_VIDz, PIDz1_value,..., PIDzX_Value}
+#endif
+
+#ifndef CLASS_SUBCLASS_PROTOCOL
+ #error CLASS_SUBCLASS_PROTOCOL shoud be defined somewhere (conf_usb.h)
+ // CLASS_SUBCLASS_PROTOCOL format definition:
+ // #define CLASS_SUBCLASS_PROTOCOL {CLASS1, SUB_CLASS1,PROTOCOL1,
+ // ...
+ // CLASSz, SUB_CLASSz,PROTOCOLz}
+#endif
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+//! Const table of known devices (see conf_usb.h for table content)
+U16 registered_VID_PID[] = VID_PID_TABLE;
+
+//! Const table of known class (see conf_usb.h for table content)
+U8 registered_class[] = CLASS_SUBCLASS_PROTOCOL;
+
+//! Physical EP to address device endpoints look-up table
+// This table is dynamically built with the "host_configure_endpoint_class" function
+U8 ep_table[MAX_EP_NB]={0,0,0,0,0,0,0};
+
+//! The number of interface the host is able to support in the device connected
+U8 nb_interface_supported=0;
+
+S_interface interface_supported[MAX_INTERFACE_SUPPORTED];
+
+//! PID of device connected
+U16 device_PID;
+//! VID of device connected
+U16 device_VID;
+//! bmAttributes byte of the connected device
+U8 bmattributes;
+//! maxpower byte of the connected device (Caution, unit is 2mA)
+U8 maxpower;
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// checks if the VID and the PID are supported
+/// (if the VID/PID belongs to the VID_PID table)
+//------------------------------------------------------------------------------
+U8 host_check_VID_PID(void)
+{
+ U8 nb_of_vid;
+ U8 nb_of_pid;
+
+ TRACE_DEBUG("host_check_VID_PID\n\r");
+ // Rebuild VID PID from data stage
+ LSB(device_VID) = data_stage[OFFSET_FIELD_LSB_VID];
+ MSB(device_VID) = data_stage[OFFSET_FIELD_MSB_VID];
+ LSB(device_PID) = data_stage[OFFSET_FIELD_LSB_PID];
+ MSB(device_PID) = data_stage[OFFSET_FIELD_MSB_PID];
+
+ // Compare detected VID PID with supported table
+ nb_of_vid=0;
+ while (nb_of_vid< sizeof(registered_VID_PID)/2) // /2 because registered_VID_PID table is U16...
+ {
+ TRACE_DEBUG("registered_VID_PID[%d]: 0x%X\n\r", nb_of_vid, registered_VID_PID[nb_of_vid]);
+ TRACE_DEBUG("device_VID: 0x%X\n\r", device_VID);
+ if (registered_VID_PID[nb_of_vid] == device_VID) // VID is correct
+ {
+ TRACE_DEBUG("Good VID\n\r");
+ nb_of_pid = (U8)registered_VID_PID[nb_of_vid+1]; // store nb of PID for this VID
+ while (nb_of_pid != 0)
+ {
+ TRACE_DEBUG("registered_VID_PID[%d]: 0x%X\n\r", nb_of_vid+nb_of_pid+1, registered_VID_PID[nb_of_vid+nb_of_pid+1]);
+ TRACE_DEBUG("device_PID: 0x%X\n\r", device_PID);
+ if (registered_VID_PID[nb_of_vid+nb_of_pid+1] == device_PID)
+ {
+ TRACE_DEBUG("Good PID\n\r");
+ return HOST_TRUE;
+ }
+ nb_of_pid--;
+ }
+ }
+ nb_of_vid+=registered_VID_PID[nb_of_vid+1]+2;
+ }
+ return HOST_FALSE;
+}
+
+//------------------------------------------------------------------------------
+/// checks if the OTG descriptor has been received and
+/// indicates which features are supported
+//------------------------------------------------------------------------------
+U8 host_check_OTG_features(void)
+{
+ U8 index; // variable offset used to search the OTG descriptor
+ U8 nb_bytes; // number of bytes of the config descriptor
+
+ TRACE_DEBUG("host_check_OTG_features\n\r");
+ Peripheral_is_not_otg_device(); // init
+ otg_features_supported = 0;
+
+ nb_bytes = data_stage[OFFSET_FIELD_TOTAL_LENGHT];
+ index = 0;
+ if (nb_bytes > 0x09) // check this is not a reduced/uncomplete config descriptor
+ {
+ while (index < nb_bytes) // search in the descriptors
+ {
+ if (data_stage[index+OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_OTG) // IS the pointed descriptor THE OTG DESCRIPTOR ?
+ {
+ index += data_stage[index+OFFSET_DESCRIPTOR_LENGHT]; // NO, skip to next descriptor
+ }
+ else
+ {
+ if (data_stage[index+OFFSET_DESCRIPTOR_LENGHT] == OTG_DESCRIPTOR_bLength) // YES, check descriptor length
+ {
+ Peripheral_is_otg_device(); // an OTG descriptor has been found
+ otg_features_supported = data_stage[index+OFFSET_FIELD_OTG_FEATURES]; // load otg features supported
+ TRACE_DEBUG("OK\n\r");
+ return HOST_TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG("PB\n\r");
+ return HOST_FALSE; // bad descriptor length
+ }
+ }
+ }
+ }
+ else
+ {
+ TRACE_DEBUG("PB1\n\r");
+ return HOST_FALSE; // this was only a reduced/uncomplete configuration descriptor
+ }
+ TRACE_DEBUG("OK1\n\r");
+ return HOST_TRUE;
+}
+
+
+//------------------------------------------------------------------------------
+/// checks if the device class is supported.
+/// The function looks in all interface declared in the received dewcriptors, if
+/// one of them match with the CLASS/SUB_CLASS/PROTOCOL table
+//------------------------------------------------------------------------------
+U8 host_check_class(void)
+{
+ U8 class_table;
+ T_DESC_OFFSET descriptor_offset;
+ T_DESC_OFFSET conf_offset_end;
+ U16 config_size;
+ U8 device_class;
+ U8 device_subclass;
+ U8 device_protocol;
+
+ TRACE_DEBUG("host_check_class\n\r");
+ nb_interface_supported=0; //First asumes ,no interface is supported!
+ if (data_stage[OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_CONFIGURATION) // check if configuration descriptor
+ {
+ TRACE_DEBUG("host_check_class problem\n\r");
+ return HOST_FALSE;
+ }
+ LSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT];
+ MSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT+1];
+ bmattributes = data_stage[OFFSET_FIELD_BMATTRIBUTES];
+ maxpower = data_stage[OFFSET_FIELD_MAXPOWER];
+ descriptor_offset = 0;
+ conf_offset_end = descriptor_offset + config_size;
+
+ // Look in all interfaces declared in the configuration
+ while(descriptor_offset < conf_offset_end)
+ {
+ // Find next interface descriptor
+ while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_INTERFACE)
+ {
+ descriptor_offset += data_stage[descriptor_offset];
+ if(descriptor_offset >= conf_offset_end)
+ {
+ if(nb_interface_supported)
+ {
+ TRACE_DEBUG("host_check_class ok\n\r");
+ return HOST_TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG("host_check_class problem2\n\r");
+ return HOST_FALSE;
+ }
+ }
+ }
+ // Found an interface descriptor
+ // Get charateristics of this interface
+ device_class = data_stage[descriptor_offset + OFFSET_FIELD_CLASS];
+ device_subclass = data_stage[descriptor_offset + OFFSET_FIELD_SUB_CLASS];
+ device_protocol = data_stage[descriptor_offset + OFFSET_FIELD_PROTOCOL];
+ // Look in registered class table for match
+ class_table=0;
+ while (class_table< sizeof(registered_class))
+ {
+ if (registered_class[class_table] == device_class) // class is correct!
+ {
+ if (registered_class[class_table+1] == device_subclass) // sub class is correct!
+ {
+ if (registered_class[class_table+2] == device_protocol) // protocol is correct!
+ {
+ // Prepare for another item CLASS/SUB_CLASS/PROTOCOL in table
+ class_table+=3;
+ // Store this interface as supported interface
+ // Memorize its interface nb
+ interface_supported[nb_interface_supported].interface_nb=data_stage[descriptor_offset+OFFSET_FIELD_INTERFACE_NB];
+ // its alternate setting
+ interface_supported[nb_interface_supported].altset_nb=data_stage[descriptor_offset+OFFSET_FIELD_ALT];
+ // its USB class
+ interface_supported[nb_interface_supported].class=device_class;
+ // its USB subclass
+ interface_supported[nb_interface_supported].subclass=device_subclass;
+ // its USB protocol
+ interface_supported[nb_interface_supported].protocol=device_protocol;
+ // the number of endpoints associated to this interface
+ // Note: The associated endpoints addresses are stored during pipe attribution...
+ interface_supported[nb_interface_supported].nb_ep=data_stage[descriptor_offset+OFFSET_FIELS_NB_OF_EP];
+ // Update the number of interface supported
+ nb_interface_supported++;
+ // Check the maximum number of interfaces we can support
+ if(nb_interface_supported>=MAX_INTERFACE_SUPPORTED)
+ {
+ TRACE_DEBUG("host_check_class ok1\n\r");
+ return HOST_TRUE;
+ }
+ }
+ }
+ }
+ class_table+=3; // Check other item CLASS/SUB_CLASS/PROTOCOL in table
+ }
+ descriptor_offset += data_stage[descriptor_offset]; // Next descriptor
+ if(descriptor_offset > SIZEOF_DATA_STAGE) // Check overflow
+ {
+ if(nb_interface_supported)
+ {
+ TRACE_DEBUG("host_check_class ok3\n\r");
+ return HOST_TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG("host_check_class problem3\n\r");
+ return HOST_FALSE;
+ }
+ }
+ }
+ if(nb_interface_supported)
+ {
+ TRACE_DEBUG("host_check_class ok4\n\r");
+ return HOST_TRUE;
+ }
+ else
+ {
+ TRACE_DEBUG("host_check_class problem4\n\r");
+ return HOST_FALSE;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// configures the pipe according to the device class of the
+//------------------------------------------------------------------------------
+U8 host_auto_configure_endpoint(void)
+{
+ U8 nb_endpoint_to_configure;
+ T_DESC_OFFSET descriptor_offset;
+ U8 physical_pipe=1; // =1 cause lookup table assumes that physiacl pipe 0 is reserved for control
+ U8 i;
+ U8 ep_index;
+
+ TRACE_DEBUG("host_auto_configure_endpoint\n\r");
+ // For all interfaces to configure...
+ for(i=0;i<nb_interface_supported;i++)
+ {
+ ep_index=0;
+ // First look for the target interface descriptor offset
+ descriptor_offset = get_interface_descriptor_offset(interface_supported[i].interface_nb,interface_supported[i].altset_nb);
+ // Get the number of endpoint to configure for this interface
+ nb_endpoint_to_configure = data_stage[descriptor_offset+OFFSET_FIELS_NB_OF_EP];
+ // Get the first Endpoint descriptor offset to configure
+ descriptor_offset += data_stage[descriptor_offset+OFFSET_DESCRIPTOR_LENGHT]; // pointing on endpoint descriptor
+
+ // While there is at least one pipe to configure
+ while (nb_endpoint_to_configure)
+ {
+ // Check and look for an Endpoint descriptor
+ while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_ENDPOINT)
+ {
+ descriptor_offset += data_stage[descriptor_offset];
+ if(descriptor_offset > SIZEOF_DATA_STAGE) // No more endpoint descriptor found -> Errror !
+ {
+ TRACE_DEBUG("PB\n\r");
+ return HOST_FALSE;
+ }
+ }
+
+ // Select the new physical pipe to configure and get ride of any previous configuration for this physical pipe
+ Host_select_pipe(physical_pipe);
+ Host_disable_pipe();
+ Host_enable_pipe();
+
+ // Build the pipe configuration according to the endpoint descriptors fields received
+ //
+ // host_configure_pipe(
+ // physical_pipe, // pipe nb in USB interface
+ // data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE], // pipe type (interrupt/BULK/ISO)
+ // Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]), // pipe addr
+ // (data_stage[descriptor_offset+2] & MSK_EP_DIR), // pipe dir (IN/OUT)
+ // host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),// pipe size
+ // ONE_BANK, // bumber of bank to allocate for pipe
+ // data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL] // interrupt period (for interrupt pipe)
+ // );
+
+ host_configure_pipe(
+ physical_pipe,
+ data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],
+ Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),
+ (data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR] & MSK_EP_DIR),
+ host_determine_pipe_size(
+ (U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE_LOW]
+ + (((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE_HIGH])<<8)),
+ ONE_BANK,
+ data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL] );
+
+ host_configure_address(physical_pipe, DEVICE_ADDRESS);
+
+ // Update Physical Pipe lookup table with device enpoint address
+ ep_table[physical_pipe]=data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR];
+ physical_pipe++;
+ // Update endpoint addr table in supported interface structure
+ interface_supported[i].ep_addr[ep_index++]=data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR];
+ descriptor_offset += data_stage[descriptor_offset]; // pointing on next descriptor
+
+ // All target endpoints configured ?
+ nb_endpoint_to_configure--;
+ } //for(i=0;i<nb_interface_supported;i++)
+ }
+ Host_set_configured();
+ return HOST_TRUE;
+}
+
+//------------------------------------------------------------------------------
+/// returns the offset in data_stage where to find the interface descriptor
+/// whose number and alternate setting values are passed as parameters
+//------------------------------------------------------------------------------
+T_DESC_OFFSET get_interface_descriptor_offset(U8 interface, U8 alt)
+{
+ T_DESC_OFFSET descriptor_offset;
+
+ TRACE_DEBUG("get_interface_descriptor_offset\n\r");
+ //nb_interface = data_stage[OFFSET_FIELD_NB_INTERFACE]; // Detects the number of interfaces in this configuration
+ descriptor_offset = data_stage[OFFSET_DESCRIPTOR_LENGHT]; // now pointing on next descriptor
+
+ while(descriptor_offset < SIZEOF_DATA_STAGE) // Look in all interfaces declared in the configuration
+ {
+ while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != USBGenericDescriptor_INTERFACE)
+ {
+ descriptor_offset += data_stage[descriptor_offset];
+ if(descriptor_offset > SIZEOF_DATA_STAGE)
+ {
+ return HOST_FALSE;
+ }
+ }
+ if (data_stage[descriptor_offset+OFFSET_FIELD_INTERFACE_NB]==interface
+ && data_stage[descriptor_offset+OFFSET_FIELD_ALT]==alt)
+ {
+ return descriptor_offset;
+ }
+ descriptor_offset += data_stage[descriptor_offset];
+ }
+ return descriptor_offset;
+}
+
+//------------------------------------------------------------------------------
+/// returns the physical pipe number linked to a logical endpoint address.
+//------------------------------------------------------------------------------
+U8 host_get_hwd_pipe_nb(U8 ep_addr)
+{
+ U8 i;
+
+ for(i=0; i<MAX_EP_NB; i++)
+ {
+ if(ep_table[i] == ep_addr)
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+/// generic Pipe 0 management function
+/// used to send and receive control request over pipe 0
+//------------------------------------------------------------------------------
+U8 host_send_control(U8* data_pointer)
+{
+ U16 data_length;
+ U8 sav_int_sof_enable;
+ U16 status;
+ int *pFifoInt;
+
+ Usb_ack_event(EVT_HOST_SOF);
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt(); // SOF software detection is in interrupt sub-routine
+ while(Is_not_usb_event(EVT_HOST_SOF)) // Wait 1 sof
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ TRACE_DEBUG("Is_host_emergency_exit\n\r");
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ }
+ if (sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt(); // enter in suspend mode
+ }
+
+ Host_select_pipe(0);
+ Host_set_token_setup();
+ Host_ack_setup();
+ Host_unfreeze_pipe();
+
+ // Send the setup request fields
+ pFifoInt = (int*)&usb_request;
+ Host_write_32(*pFifoInt);
+ pFifoInt++;
+ Host_write_32(*pFifoInt);
+
+ Host_send_setup();
+
+ while(Is_host_setup_sent() == FALSE) // wait for SETUP ack
+ {
+ if (Is_timeout_bdev_response_overflow())
+ {
+ Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC);
+ status = CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if (Is_host_emergency_exit())
+ {
+ status = CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error()) // Any error ?
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end; // Send error status
+ }
+ }
+
+ // Setup token sent now send In or OUT token
+ // Before just wait one SOF
+ Usb_ack_event(EVT_HOST_SOF);
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+ Host_freeze_pipe();
+ data_length = usb_request.wLength;
+ while(Is_not_usb_event(EVT_HOST_SOF)) // Wait 1 sof
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ }
+ if (sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt();
+ } // Restore SOF interrupt enable
+
+ // IN request management ---------------------------------------------
+ if(usb_request.bmRequestType & 0x80) // bmRequestType : Data stage IN (bmRequestType==1)
+ {
+ Host_standard_in_mode();
+ //jcb // We send 1 IN
+ // Host_in_request_number(0, 0);
+ Host_set_token_in();
+ while(data_length != 0)
+ {
+ Host_unfreeze_pipe();
+ while(!Is_host_control_in_received())
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if (Is_timeout_bdev_response_overflow())
+ {
+ Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC);
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+ status = Host_data_length_U8();
+ if (status == host_get_pipe_length())
+ {
+ data_length -= status;
+ if (usb_request.uncomplete_read == TRUE) // uncomplete_read
+ {
+ data_length = 0;
+ }
+ }
+ else
+ {
+ data_length = 0;
+ }
+ Address_fifochar_endpoint(0);
+
+ while (status!=0)
+ {
+ *data_pointer = Host_read_byte();
+ data_pointer++;
+ status--;
+ }
+ Host_freeze_pipe();
+ Host_ack_control_in();
+ Host_send_control_in();
+ } // end of IN data stage
+ Host_set_token_out();
+ Host_unfreeze_pipe();
+ Host_ack_control_out();
+ Host_send_control_out();
+
+ while(!Is_host_control_out_sent())
+ {
+ if (Is_timeout_bdev_response_overflow())
+ {
+ Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC);
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+
+ // Test Low Speed
+ if( AT91C_OTGHS_SPEED_SR_LS == (*AT91C_OTGHS_SR & AT91C_OTGHS_SPEED_SR_LS)) {
+ TRACE_DEBUG("LOW SPEED\n\r");
+ // Reset UTMI
+ *AT91C_OTGHS_TSTA2 |= AT91C_OTGHS_UTMIRESET;
+ *AT91C_OTGHS_TSTA2 &= ~(unsigned int)AT91C_OTGHS_UTMIRESET;
+ }
+ Host_ack_control_out();
+ // Wait end of transfer
+ while( (AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[0] & AT91C_OTGHS_TXSTPI) != 0);
+ // Freeze the pipe
+ Host_freeze_pipe();
+
+ status=(CONTROL_GOOD);
+ goto host_send_control_end;
+ }
+
+ // OUT request management ---------------------------------------------
+ else // Data stage OUT (bmRequestType==0)
+ {
+ Host_set_token_out();
+ Host_ack_control_out();
+ while(data_length != 0)
+ {
+ Host_unfreeze_pipe();
+ status = host_get_pipe_length();
+ if ( (U16)status > data_length)
+ {
+ status = (U8)data_length;
+ data_length = 0;
+ }
+ else
+ {
+ data_length -= status;
+ }
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (status!=0)
+ {
+ Host_write_byte(*data_pointer);
+ data_pointer++;
+ status--;
+ }
+ Host_send_control_out();
+ while (!Is_host_control_out_sent())
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if (Is_timeout_bdev_response_overflow())
+ {
+ Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC);
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+ Host_ack_control_out();
+ } // end of OUT data stage
+ Host_freeze_pipe();
+ Host_set_token_in();
+ Host_unfreeze_pipe();
+ while(!Is_host_control_in_received())
+ {
+ if (Is_host_emergency_exit())
+ {
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if (Is_timeout_bdev_response_overflow())
+ {
+ Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC);
+ status=CONTROL_TIMEOUT;
+ Host_freeze_pipe();
+ Host_reset_pipe(0);
+ goto host_send_control_end;
+ }
+ if(Is_host_pipe_error())
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_control_end;
+ }
+ if(Is_host_stall())
+ {
+ status=CONTROL_STALL;
+ Host_ack_stall();
+ goto host_send_control_end;
+ }
+ }
+ Host_ack_control_in();
+ Host_freeze_pipe();
+ Host_send_control_in();
+ status=(CONTROL_GOOD);
+ goto host_send_control_end;
+ }
+
+host_send_control_end:
+ return ((U8)status);
+}
+
+
diff --git a/usb/otg/usb_host_task.c b/usb/otg/usb_host_task.c new file mode 100644 index 0000000..6d38400 --- /dev/null +++ b/usb/otg/usb_host_task.c @@ -0,0 +1,1260 @@ +/* ----------------------------------------------------------------------------
+ * 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 <memories/Media.h>
+#include "conf_usb.h"
+#include <usb/common/core/USBConfigurationOTG.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/massstorage/MSDDriver.h>
+#include "usb/otg/usb_task.h"
+#include "usb_host_task.h"
+#include "usb/otg/usb_drv.h"
+#include "usb/otg/usb_host_enum.h"
+#include <utility/trace.h>
+#include "main.h"
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+//jcb #define WAIT_100MS 100
+// Wait 100 x 125 us = 12,5 ms before USB reset
+//#define WAIT_100MS 800
+#define WAIT_100MS 100
+
+#ifndef DEVICE_ADDRESS
+#error DEVICE_ADDRESS should be defined somewhere in config files (conf_usb.h)
+#endif
+
+#ifndef SIZEOF_DATA_STAGE
+#error SIZEOF_DATA_STAGE should be defined in conf_usb.h
+#endif
+
+#ifndef HOST_CONTINUOUS_SOF_INTERRUPT
+#error HOST_CONTINUOUS_SOF_INTERRUPT should be defined as ENABLE or DISABLE in conf_usb.h
+#endif
+
+#ifndef Usb_id_transition_action
+#define Usb_id_transition_action()
+#endif
+#ifndef Host_device_disconnection_action
+#define Host_device_disconnection_action()
+#endif
+#ifndef Host_device_connection_action
+#define Host_device_connection_action()
+#endif
+#ifndef Host_sof_action
+#define Host_sof_action()
+#endif
+#ifndef Host_suspend_action
+#define Host_suspend_action()
+#endif
+#ifndef Host_hwup_action
+#define Host_hwup_action()
+#endif
+#ifndef Host_device_not_supported_action
+#define Host_device_not_supported_action()
+#endif
+#ifndef Host_device_class_not_supported_action
+#define Host_device_class_not_supported_action()
+#endif
+#ifndef Host_device_supported_action
+#define Host_device_supported_action()
+#endif
+#ifndef Host_device_error_action
+#define Host_device_error_action()
+#endif
+
+extern U8 id_changed_to_host_event;
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+volatile S_pipe_int it_pipe_str[MAX_EP_NB];
+volatile U8 pipe_nb_save;
+U8 g_sav_int_sof_enable;
+
+//! Its value represent the current state of the
+//! device connected to the usb host controller
+//! Value can be:
+//! - DEVICE_ATTACHED
+//! - DEVICE_POWERED
+//! - DEVICE_SUSPENDED
+//! - DEVICE_DEFAULT
+//! - DEVICE_ADDRESSED
+//! - DEVICE_CONFIGURED
+//! - DEVICE_ERROR
+//! - DEVICE_UNATTACHED
+//! - DEVICE_READY
+//! - DEVICE_WAIT_RESUME
+//! - DEVICE_DISCONNECTED
+//! - DEVICE_DISCONNECTED_ACK
+//! - and these have been added for OTG :
+//! - A_PERIPHERAL
+//! - A_INIT_HNP
+//! - A_SUSPEND
+//! - A_END_HNP_WAIT_VFALL
+U8 device_state;
+
+//! For control requests management over pipe 0
+S_usb_setup_data usb_request;
+
+//! Internal RAM buffer for USB data stage content
+//! This buffer is required to setup host enumeration process
+//! Its contains the device descriptors received.
+//! Depending on the device descriptors lenght, its size can be optimized
+//! with the SIZEOF_DATA_STAGE define of conf_usb.h file
+U8 data_stage[SIZEOF_DATA_STAGE];
+
+U8 device_status;
+U8 request_resume;
+
+
+U8 new_device_connected=0;
+
+//------------------------------------------------------------------------------
+// Local Variables
+//------------------------------------------------------------------------------
+static U16 hostSOFCounter; // As internal host start of frame counter
+
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// This function initializes the USB controller in host mode and the associated
+/// variables.
+/// This function enables the USB controller for host mode operation.
+//------------------------------------------------------------------------------
+void usb_host_task_init(void)
+{
+ unsigned int i;
+
+ TRACE_DEBUG("usb_host_task_init\n\r");
+
+ for( i=0; i<SIZEOF_DATA_STAGE; i++ ) {
+ data_stage[i] = 0;
+ }
+ Usb_disable();
+ Usb_enable();
+ Usb_unfreeze_clock();
+ USBD_Connect();
+ Usb_enable_uvcon_pin();
+ Usb_select_host();
+ Usb_disable_vbus_hw_control(); // Force Vbus generation without timeout
+ Host_enable_device_disconnection_interrupt();
+ device_state=DEVICE_UNATTACHED;
+}
+
+//------------------------------------------------------------------------------
+/// Entry point of the USB host management
+/// The aim is to manage the device target connection and enumeration
+/// depending on the device_state, the function performs the required operations
+/// to get the device enumerated and configured
+/// Once the device is operationnal, the device_state value is DEVICE_READY
+/// This state should be tested by the host task application before performing
+/// any applicative requests to the device.
+//------------------------------------------------------------------------------
+void usb_host_task(void)
+{
+ U32 dec;
+
+ //TRACE_DEBUG("host_task ");
+ switch (device_state) {
+ case DEVICE_UNATTACHED:
+ // DEVICE_UNATTACHED state
+ // - Default init state
+ // - Try to give device power supply
+ //TRACE_DEBUG("DEVICE_UNATTACHED\n\r");
+ for (hostSOFCounter=0; hostSOFCounter<MAX_EP_NB; hostSOFCounter++) {
+ ep_table[hostSOFCounter]=0;
+ }// Reset PIPE lookup table with device EP addr
+ nb_interface_supported=0;
+ Host_clear_device_supported(); // Reset Device status
+ Host_clear_configured();
+ Host_clear_device_ready();
+ Usb_clear_all_event(); // Clear all software events
+ new_device_connected=0;
+ if (Is_usb_id_host()) {
+ if(pOTGDescriptor->bOTGSoftwareVbusCtrl == ENABLE) {
+ if( Is_usb_bconnection_error_interrupt()||Is_usb_vbus_error_interrupt())
+ {
+ Usb_ack_bconnection_error_interrupt();
+ Usb_ack_vbus_error_interrupt();
+ Host_clear_vbus_request();
+ }
+ if (Is_usb_id_host()) {
+ Host_ack_device_connection();
+ // Usb_enable_manual_vbus();
+ Usb_ack_bconnection_error_interrupt();
+ Usb_enable_vbus_pad();
+ Usb_enable_vbus();
+ Host_vbus_action();
+ }
+
+ Usb_disable_vbus_pad();
+ Usb_enable_manual_vbus();
+
+ if(Is_usb_srp_interrupt()) {
+ Usb_ack_srp_interrupt();
+ // if Vbus was not already delivered, it is really an SRP (OTG B-Device)
+ device_state=DEVICE_ATTACHED;
+ Usb_ack_bconnection_error_interrupt();
+ Usb_enable_vbus_pad();
+ Usb_enable_vbus();
+ Host_vbus_action();
+ }
+ }
+ else {
+ Usb_enable_vbus(); // Give at least device power supply!!!
+ Host_vbus_action();
+ if(Is_usb_vbus_high()) {
+ device_state=DEVICE_ATTACHED;
+ } // If VBUS ok goto to device connection expectation
+ }
+ }
+ break;
+
+ case DEVICE_ATTACHED :
+ // DEVICE_ATTACHED state
+ // - Vbus is on
+ // - Try to detect device connection
+ if (Is_device_connection()) { // Device pull-up detected
+ //TRACE_DEBUG("Is_device_connection\n\r");
+ Host_ack_device_connection();
+ // Now device is connected, enable disconnection interrupt
+ Host_enable_device_disconnection_interrupt();
+ // Reset device status
+ Host_clear_device_supported();
+ Host_clear_configured();
+ Host_clear_device_ready();
+ Host_ack_sof();
+
+ TRACE_DEBUG("begin timer\n\r");
+ gSystemTick = 0;
+ DelayMS(200);
+ TRACE_DEBUG("end timer\n\r");
+ // Clear bad VBUS error
+ Usb_ack_vbus_error_interrupt();
+ Host_disable_device_disconnection_interrupt();
+
+ Host_send_reset(); // First USB reset
+ Host_enable_sof(); // Start Start Of Frame generation
+ Host_enable_sof_interrupt(); // SOF will be detected under interrupt
+
+ Usb_ack_event(EVT_HOST_SOF);
+ while (Is_host_reset()) {
+ } // Active wait of end of reset send
+ Host_ack_reset();
+ //Workaround for some bugly devices with powerless pull up
+ //usually low speed where data line rise slowly and can be interpretaded as disconnection
+ for(hostSOFCounter=0;hostSOFCounter!=0xFFFF;hostSOFCounter++) { // Basic Timeout counter
+ if(Is_usb_event(EVT_HOST_SOF)) { //If we detect SOF, device is still alive and connected, just clear false disconnect flag
+ if(Is_device_disconnection()) {
+ Host_ack_device_connection();
+ Host_ack_device_disconnection();
+ break;
+ }
+ }
+ }
+ Host_enable_device_disconnection_interrupt();
+ hostSOFCounter = 0;
+ while (hostSOFCounter<WAIT_100MS) { // wait 100ms after USB reset
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ hostSOFCounter++;
+ }// Count Start Of frame
+ if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {
+ TRACE_DEBUG("goto error 2\n\r");
+ goto device_attached_error;
+ }
+ }
+ device_state = DEVICE_POWERED;
+ hostSOFCounter=0;
+
+ }
+
+
+device_attached_error:
+ // Device connection error, or vbus pb -> Retry the connection process from the begining
+ if( Is_usb_bconnection_error_interrupt()||Is_usb_vbus_error_interrupt()||Is_usb_vbus_low()) {
+ TRACE_DEBUG("HOST device_attached_error\n\r");
+ TRACE_DEBUG("Is_usb_bconnection_error_interrupt: 0x%X\n\r", Is_usb_bconnection_error_interrupt());
+ TRACE_DEBUG("Is_usb_vbus_error_interrupt: 0x%X\n\r", Is_usb_vbus_error_interrupt());
+ TRACE_DEBUG("Is_usb_vbus_low: 0x%X\n\r", Is_usb_vbus_low());
+ //while(1); //JCB for test, to be removed.
+ if (Is_usb_id_host()) {
+ Usb_ack_bconnection_error_interrupt();
+ Usb_enable_vbus_hw_control();
+ device_state=DEVICE_UNATTACHED;
+ Usb_disable_vbus();
+ Usb_disable_vbus_pad();
+ Usb_enable_vbus_pad();
+ Usb_ack_vbus_error_interrupt();
+ Usb_enable_vbus();
+ Usb_disable_vbus_hw_control();
+ Host_disable_sof();
+ Host_vbus_action();
+ }
+ else {
+ device_state = DEVICE_UNATTACHED;
+ }
+ }
+ break;
+
+ case DEVICE_POWERED :
+ // DEVICE_POWERED state
+ //
+ // - Device connection (attach) as been detected,
+ // - Wait 100ms and configure default control pipe
+ //
+ //TRACE_INFO("Device Connection\n\r");
+ Host_device_connection_action();
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ if (hostSOFCounter++ >= WAIT_100MS) {
+ device_state = DEVICE_DEFAULT;
+ Host_select_pipe(PIPE_CONTROL);
+ Host_enable_pipe();
+ host_configure_pipe(PIPE_CONTROL,
+ TYPE_CONTROL,
+ TOKEN_SETUP,
+ EP_CONTROL,
+ SIZE_64,
+ ONE_BANK,
+ 0 );
+ device_state = DEVICE_DEFAULT;
+ }
+ }
+ break;
+
+ case DEVICE_DEFAULT :
+ // DEVICE_DEFAULT state
+ // - Get device descriptor
+ // - Reconfigure Pipe 0 according to Device EP0
+ // - Attribute device address
+ TRACE_DEBUG("DEVICE_DEFAULT\n\r");
+ // Get first device descriptor
+
+ if( CONTROL_GOOD == host_get_device_descriptor_uncomplete()) {
+ hostSOFCounter = 0;
+ while(hostSOFCounter<20) { // wait 20ms before USB reset (special buggly devices...)
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ hostSOFCounter++;
+ }
+ if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {
+ break;
+ }
+ }
+ Host_disable_device_disconnection_interrupt();
+ Host_send_reset(); // First USB reset
+ Usb_ack_event(EVT_HOST_SOF);
+ while (Is_host_reset()); // Active wait of end of reset send
+ Host_ack_reset();
+
+
+ //Workaround for some bugly devices with powerless pull up
+ //usually low speed where data line rise slowly and can be interpretaded as disconnection
+ for(hostSOFCounter=0;hostSOFCounter!=0xFFFF;hostSOFCounter++) { // Basic Timeout counter
+ if(Is_usb_event(EVT_HOST_SOF)) { //If we detect SOF, device is still alive and connected, just clear false disconnect flag
+ if(Is_device_disconnection()) {
+ Host_ack_device_connection();
+ Host_ack_device_disconnection();
+ break;
+ }
+ }
+ }
+ Host_enable_device_disconnection_interrupt();
+ hostSOFCounter = 0;
+ while(hostSOFCounter<200) { // wait 200ms after USB reset
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ hostSOFCounter++;
+ }
+ if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {
+ break;
+ }
+ }
+
+ Host_select_pipe(PIPE_CONTROL);
+ Host_disable_pipe();
+ Host_unallocate_memory();
+ Host_enable_pipe();
+ // Re-Configure the Ctrl Pipe according to the device ctrl EP
+
+ TRACE_DEBUG("Size: 0x%X\n\r", (U16)data_stage[OFFSET_FIELD_MAXPACKETSIZE]);
+ TRACE_DEBUG("Size Pipe: 0x%X\n\r", host_determine_pipe_size((U16)data_stage[OFFSET_FIELD_MAXPACKETSIZE]));
+
+ host_configure_pipe(PIPE_CONTROL,
+ TYPE_CONTROL,
+ TOKEN_SETUP,
+ EP_CONTROL,
+ host_determine_pipe_size((U16)data_stage[OFFSET_FIELD_MAXPACKETSIZE]),
+ ONE_BANK,
+ 0 );
+ // Give an absolute device address
+ host_set_address(DEVICE_ADDRESS);
+ host_configure_address(PIPE_CONTROL, DEVICE_ADDRESS);
+ device_state = DEVICE_ADDRESSED;
+ }
+ else {
+ device_state = DEVICE_ERROR;
+ }
+ break;
+
+ case DEVICE_ADDRESSED :
+ // DEVICE_ADDRESSED state
+ // - Check if VID PID is in supported list
+ TRACE_DEBUG("DEVICE_ADDRESSED\n\r");
+ if (CONTROL_GOOD == host_get_device_descriptor()) {
+ // Detect if the device connected belongs to the supported devices table
+ if (HOST_TRUE == host_check_VID_PID()) {
+ Host_set_device_supported();
+ Host_device_supported_action();
+ device_state = DEVICE_CONFIGURED;
+ }
+ else
+ {
+ }
+
+ }
+ else {// Can not get device descriptor
+ device_state = DEVICE_ERROR;
+ }
+ break;
+
+ case DEVICE_CONFIGURED :
+ // DEVICE_CONFIGURED state
+ // - Configure pipes for the supported interface
+ // - Send Set_configuration() request
+ // - Goto full operating mode (device ready)
+ TRACE_DEBUG("DEVICE_CONFIGURED\n\r");
+ if (CONTROL_GOOD == host_get_configuration_descriptor()) {
+ if (HOST_FALSE != host_check_class()) { // Class support OK?
+ host_auto_configure_endpoint();
+
+ if (Is_host_configured()) {
+ if (CONTROL_GOOD== host_set_configuration(1)) { // Send Set_configuration
+ // host_set_interface(interface_bound,interface_bound_alt_set);
+ // device and host are now fully configured
+ // goto DEVICE READY normal operation
+ device_state = DEVICE_READY;
+ // monitor device disconnection under interrupt
+ Host_enable_device_disconnection_interrupt();
+ // If user host application requires SOF interrupt event
+ // Keep SOF interrupt enable otherwize, disable this interrupt
+#if (HOST_CONTINUOUS_SOF_INTERRUPT==DISABLE)
+ Host_disable_sof_interrupt();
+#endif
+ new_device_connected=TRUE;
+ TRACE_INFO("Device Enumerated\n\r");
+ }
+ else { // Problem during Set_configuration request...
+ device_state = DEVICE_ERROR;
+ }
+ }
+ }
+ else { // device class not supported...
+ device_state = DEVICE_ERROR;
+ TRACE_INFO("Unsupported Device\n\r");
+ Host_device_class_not_supported_action();
+ }
+ }
+ else { // Can not get configuration descriptors...
+ device_state = DEVICE_ERROR;
+ }
+ break;
+
+ case DEVICE_READY :
+ // DEVICE_READY state
+ // - Full standard operating mode
+ // - Nothing to do...
+ // Host full std operating mode!
+ new_device_connected=FALSE;
+
+ // Handles user requests : "stop Vbus" and "suspend"
+ break;
+
+ case DEVICE_ERROR :
+ //------------------------------------------------------
+ // DEVICE_ERROR state
+ // - Error state
+ // - Do custom action call (probably go to default mode...)
+ TRACE_DEBUG("DEVICE_ERROR\n\r");
+ Host_device_error_action();
+ break;
+
+ case DEVICE_SUSPENDED :
+ // DEVICE_SUSPENDED state
+ // - Host application request to suspend the device activity
+ // - State machine comes here thanks to Host_request_suspend()
+ TRACE_DEBUG("DEVICE_SUSPENDED\n\r");
+ device_state=DEVICE_WAIT_RESUME; // wait for device resume event
+ if(Is_device_supports_remote_wakeup()) { // If the connected device supports remote wake up
+ if (CONTROL_GOOD != host_set_feature_remote_wakeup()) {
+ device_state = DEVICE_DISCONNECTED; // stop connexion because device has not accepted the feature
+ }
+ }
+ TRACE_INFO("Usb suspend\n\r");
+ hostSOFCounter = Is_host_sof_interrupt_enabled(); //Save current sof interrupt enable state
+ Host_disable_sof_interrupt();
+ Host_ack_sof();
+ Host_disable_sof(); // Stop start of frame generation, this generates the suspend state
+ Host_ack_remote_wakeup();
+ Host_enable_remote_wakeup_interrupt();
+ Host_ack_hwup();
+ Host_enable_hwup_interrupt(); // Enable host wake-up interrupt
+ // (this is the unique USB interrupt able to wake up the CPU core from power-down mode)
+ Usb_freeze_clock();
+ Host_suspend_action(); // Custom action here! (for example go to power-save mode...)
+ }
+ break;
+
+ case DEVICE_WAIT_RESUME :
+ // DEVICE_WAIT_RESUME state
+ // - Wait in this state till the host receives an upstream resume from the device
+ // - or the host software request the device to resume
+ TRACE_DEBUG("DEVICE_WAIT_RESUME\n\r");
+ if(Is_usb_event(EVT_HOST_REMOTE_WAKEUP)|| Is_host_request_resume()) { // Remote wake up has been detected
+ // or Local resume request has been received
+ if(Is_host_request_resume()) { // Not a remote wakeup, but an host application request
+ Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up !
+ // CAUTION HWUP can be cleared only when USB clock is active
+ // Pll_start_auto(); // First Restart the PLL for USB operation
+ // Wait_pll_ready(); // Get sure pll is lock
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ }
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Host_enable_sof();
+
+ if (Is_usb_event(EVT_HOST_REMOTE_WAKEUP)) {
+ Usb_ack_event(EVT_HOST_REMOTE_WAKEUP); // Ack software event
+ Host_disable_sof_interrupt();
+ Host_ack_device_disconnection();
+ Host_disable_device_disconnection_interrupt();
+
+ Host_send_resume(); // this other downstream resume is done to ensure min. 20ms of HOST DRIVING RESUME (not Device)
+ while (!Is_device_disconnection() && Host_is_resume());
+ hostSOFCounter = 0;
+ Host_ack_sof();
+ while (!Is_device_disconnection() && (hostSOFCounter != 12)) { // wait for min. 10ms of device recovery time
+ if (Is_host_sof()) {
+ Host_ack_sof();
+ hostSOFCounter++;
+ }
+ }
+ if (Is_device_disconnection()) {
+ usb_host_task_init();
+ device_state = DEVICE_DISCONNECTED;
+ Host_ack_remote_wakeup(); // Ack remote wake-up reception
+ Host_ack_request_resume(); // Ack software request
+ Host_ack_down_stream_resume(); // Ack down stream resume sent
+ }
+ else {
+ device_state = DEVICE_READY;
+ Host_ack_remote_wakeup(); // Ack remote wake-up reception
+ Host_ack_request_resume(); // Ack software request
+ Host_ack_down_stream_resume(); // Ack down stream resume sent
+ }
+ Host_enable_device_disconnection_interrupt();
+ Host_ack_sof();
+ }
+ else {
+ Host_send_resume(); // Send down stream resume
+ //-----------------------
+ // Work-around for case of Device disconnection during Suspend
+ // The disconnection is never detected and the Resume bit remains high (and RSMEDI flag never set)
+ // If the timeout elapses, it implies that the device has disconnected => macro is reset (to reset the Resume bit)
+ dec = 0;
+ while (dec < 0x4FFFF) { // several hundreds of ms
+ if (Is_host_down_stream_resume()) { // Wait Down stream resume sent
+ Host_ack_remote_wakeup(); // Ack remote wake-up reception
+ Host_ack_request_resume(); // Ack software request
+ Host_ack_down_stream_resume(); // Ack down stream resume sent
+ if(hostSOFCounter) {
+ Host_enable_sof_interrupt();
+ } // Restore SOF interrupt enable state before suspend
+ device_state=DEVICE_READY; // Come back to full operating mode
+ TRACE_INFO("Usb resumed\n\r");
+ dec = 0x3FFFFE; // will cause a loop end
+ }
+ dec++;
+ }
+ if (dec != 0x3FFFFF) { // if resume failed
+ usb_host_task_init();
+ device_state = DEVICE_DISCONNECTED;
+ }
+ else
+ {
+ hostSOFCounter = 0;
+ Host_ack_sof();
+ while (!Is_device_disconnection() && (hostSOFCounter != 12)) { // wait for min. 10ms of device recovery time
+ if (Is_host_sof()) {
+ Host_ack_sof();
+ hostSOFCounter++;
+ }
+ }
+ }
+ //-----------------------End of Work Around
+ }
+ }
+ break;
+
+ case DEVICE_DISCONNECTED :
+ // DEVICE_DISCONNECTED state
+ // - Device disconnection has been detected
+ // - Run scheduler in this state at least two times to get sure event is detected by all host application tasks
+ // - Go to DEVICE_DISCONNECTED_ACK state before DEVICE_UNATTACHED, to get sure scheduler calls all app tasks...
+ TRACE_DEBUG("DEVICE_DISCONNECTED\n\r");
+ device_state = DEVICE_DISCONNECTED_ACK;
+ break;
+
+ case DEVICE_DISCONNECTED_ACK :
+ // DEVICE_DISCONNECTED_ACK state
+ // - Device disconnection has been detected and managed bu applicatives tasks
+ // - Go to DEVICE_UNATTACHED state
+ TRACE_DEBUG("DEVICE_DISCONNECTED_ACK\n\r");
+ host_disable_all_pipe();
+ device_state = DEVICE_UNATTACHED;
+ break;
+
+
+ default :
+ // default state
+ // - Default case: ERROR
+ // - Goto no device state
+ TRACE_DEBUG("default\n\r");
+ device_state = DEVICE_UNATTACHED;
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// This function send nb_data pointed with *buf with the pipe number specified
+/// This function will activate the host sof interrupt to detect timeout. The
+/// interrupt enable sof will be restore.
+//------------------------------------------------------------------------------
+U8 host_send_data(U8 pipe, U16 nb_data, U8 *buf)
+{
+ U16 length;
+ U8 status=PIPE_GOOD;
+ U8 sav_int_sof_enable;
+ U8 nak_timeout;
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ U16 cpt_nak;
+#endif
+ U16 nb_data_loaded;
+
+ TRACE_DEBUG("host_send_data[]%d: %d\n\r", pipe, nb_data);
+
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled(); // Save state of enable sof interrupt
+ Host_enable_sof_interrupt();
+ Host_select_pipe(pipe);
+
+ Host_set_token_in();
+
+ Host_set_token_out();
+ Host_ack_out_sent();
+ /*
+ TRACE_DEBUG("CTRL: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_CTRL);
+ TRACE_DEBUG("SR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_SR);
+ TRACE_DEBUG("DEVCTRL: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVCTRL);
+ TRACE_DEBUG("DEVISR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVISR);
+ TRACE_DEBUG("DEVIMR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVIMR);
+ TRACE_DEBUG("DEVEPTISR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVEPTISR[0]);
+ TRACE_DEBUG("HSTCTRL: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTCTRL);
+ TRACE_DEBUG("HSTISR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTISR);
+ TRACE_DEBUG("HSTIMR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTIMR);
+ TRACE_DEBUG("HSTPIP: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIP);
+ TRACE_DEBUG("HSTPIPCFG[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[0]);
+ TRACE_DEBUG("HSTPIPCFG[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[1]);
+ TRACE_DEBUG("HSTPIPCFG[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[2]);
+ TRACE_DEBUG("HSTPIPINRQ[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[0]);
+ TRACE_DEBUG("HSTPIPINRQ[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[1]);
+ TRACE_DEBUG("HSTPIPINRQ[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[2]);
+ TRACE_DEBUG("HSTPIPERR[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[0]);
+ TRACE_DEBUG("HSTPIPERR[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[1]);
+ TRACE_DEBUG("HSTPIPERR[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[2]);
+ TRACE_DEBUG("HSTPIPISR[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[0]);
+ TRACE_DEBUG("HSTPIPISR[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[1]);
+ TRACE_DEBUG("HSTPIPISR[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[2]);
+ TRACE_DEBUG("HSTPIPIMR[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[0]);
+ TRACE_DEBUG("HSTPIPIMR[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[1]);
+ TRACE_DEBUG("HSTPIPIMR[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[2]);
+ */
+ while (nb_data != 0) { // While there is something to send...
+ Host_unfreeze_pipe();
+ // Prepare data to be sent
+ length = host_get_pipe_length();
+ TRACE_DEBUG("size=%d\n\r", length);
+
+ if ( length > nb_data) {
+ nb_data_loaded = nb_data;
+ length = nb_data;
+ }
+ else {
+ nb_data_loaded = length;
+ }
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (length!=0) { // Load Pipe buffer
+ Host_write_byte(*buf++);
+ //(((char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0))[dBytes++])=*(buf++);
+ //pFifo[dBytes++] = *buf;
+ //buf++;
+ length--;
+ }
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ cpt_nak=0;
+#endif
+ nak_timeout=0;
+ Host_ack_out_sent();
+ Host_send_out();
+ while (!Is_host_out_sent()) {
+ if (Is_host_emergency_exit()) { // Async disconnection or role change detected under interrupt
+ TRACE_DEBUG("Emergency exit\n\r");
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_send_data_end;
+ }
+ if (private_sof_counter>=250) { // Count 250ms (250sof)
+ TRACE_DEBUG("TimeOut Send Data\n\r");
+ private_sof_counter=0;
+ if (nak_timeout++>=TIMEOUT_DELAY) { // Inc timeout and check for overflow
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_send_data_end;
+ }
+ }
+ if (Is_host_pipe_error()) { // Any error ?
+ TRACE_DEBUG("pipe error\n\r");
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_data_end;
+ }
+ if (Is_host_stall()) { // Stall management
+ TRACE_DEBUG("stall\n\r");
+ status =PIPE_STALL;
+ Host_ack_stall();
+ goto host_send_data_end;
+ }
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ if(Is_host_nak_received()) { //NAK received
+ Host_ack_nak_received();
+ if (cpt_nak++>NAK_SEND_TIMEOUT) {
+ TRACE_DEBUG("NAK timeout\n\r");
+ status = PIPE_NAK_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_send_data_end;
+ }
+ }
+#endif
+ }
+ // Here OUT sent
+ nb_data -= nb_data_loaded;
+ status=PIPE_GOOD; // Frame correctly sent
+ Host_ack_out_sent();
+ }
+ Host_freeze_pipe();
+
+host_send_data_end:
+ // Restore sof interrupt enable state
+ if (sav_int_sof_enable==FALSE) {
+ Host_disable_sof_interrupt();
+ }
+ // And return...
+ return ((U8)status);
+}
+
+
+
+//------------------------------------------------------------------------------
+/// This function receives nb_data pointed with *buf with the pipe number specified
+/// The nb_data parameter is passed as a U16 pointer, thus the data pointed by this pointer
+/// is updated with the final number of data byte received.
+//------------------------------------------------------------------------------
+U8 host_get_data(U8 pipe, U16 *nb_data, U8 *buf)
+{
+ U8 status=PIPE_GOOD;
+ U8 sav_int_sof_enable;
+ U8 nak_timeout;
+ U16 n;
+ U16 i;
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ U16 cpt_nak;
+#endif
+
+ // TRACE_DEBUG("host_get_data[%d]\n\r", pipe);
+ n=*nb_data;
+ *nb_data=0;
+
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+
+ Host_select_pipe(pipe);
+ Host_set_token_in();
+ Host_continuous_in_mode();
+ // Host_ack_in_received();
+
+ while (n) { // While missing data...
+ // start IN request generation
+ Host_unfreeze_pipe();
+ Host_send_in();
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ nak_timeout=0;
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ cpt_nak=0;
+#endif
+ while (!Is_host_in_received())
+ {
+ if (Is_host_emergency_exit()) // Async disconnection or role change detected under interrupt
+ {
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_get_data_end;
+ }
+ if (private_sof_counter>=250) // Timeout management
+ {
+ private_sof_counter=0; // Done in host SOF interrupt
+ if (nak_timeout++>=TIMEOUT_DELAY)// Check for local timeout
+ {
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_get_data_end;
+ }
+ }
+ if(Is_host_pipe_error()) // Error management
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_get_data_end;
+ }
+ if(Is_host_stall()) // STALL management
+ {
+ status =PIPE_STALL;
+ Host_reset_pipe(pipe);
+ Host_ack_stall();
+ goto host_get_data_end;
+ }
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ if(Is_host_nak_received()) //NAK received
+ {
+ Host_ack_nak_received();
+ if (cpt_nak++>NAK_RECEIVE_TIMEOUT)
+ {
+ status = PIPE_NAK_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_get_data_end;
+ }
+ }
+#endif
+ }
+ status=PIPE_GOOD;
+ Host_freeze_pipe();
+ if (Host_byte_counter()<=n)
+ {
+ if ((Host_byte_counter() < n)&&(Host_byte_counter()<host_get_pipe_length()))
+ {
+ n = 0;
+ }
+ else
+ {
+ n -= Host_byte_counter();
+ }
+ (*nb_data) += Host_byte_counter(); // Update nb of byte received
+
+ Address_fifochar_endpoint(global_pipe_nb);
+ for (i=Host_byte_counter(); i; i--)
+ {
+ *buf = Host_read_byte();
+ buf++;
+ }
+ }
+ else // more bytes received than expected
+ { // TODO error code management
+ *nb_data += n;
+ Address_fifochar_endpoint(global_pipe_nb);
+ for (i=n; i; i--) // Byte number limited to the initial request (limit tab over pb)
+ {
+ *buf = Host_read_byte();
+ buf++;
+ }
+ n=0;
+ }
+ Host_ack_in_received();
+ }
+
+ Host_freeze_pipe();
+
+host_get_data_end:
+ if (sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt();
+ }
+ return ((U8)status);
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void reset_it_pipe_str(void)
+{
+ U8 i;
+ TRACE_DEBUG("reset_it_pipe_str\n\r");
+ for(i=0;i<MAX_EP_NB;i++)
+ {
+ it_pipe_str[i].enable=DISABLE;
+ it_pipe_str[i].timeout=0;
+ }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+U8 is_any_interrupt_pipe_active(void)
+{
+ U8 i;
+ TRACE_DEBUG("is_any_interrupt_pipe_active\n\r");
+ for(i=0;i<MAX_EP_NB;i++)
+ {
+ if(it_pipe_str[i].enable==ENABLE) return TRUE;
+ }
+ return FALSE;
+}
+
+//------------------------------------------------------------------------------
+/// This function receives nb_data pointed with *buf with the pipe number specified
+/// The nb_data parameter is passed as a U16 pointer, thus the data pointed by this pointer
+/// is updated with the final number of data byte received.
+//------------------------------------------------------------------------------
+U8 host_get_data_interrupt(U8 pipe, U16 nb_data, U8 *buf,void(*handle)(U8 status, U16 nb_byte))
+{
+ TRACE_DEBUG("host_get_data_interrupt\n\r");
+ Host_select_pipe(pipe);
+ if(it_pipe_str[pipe].enable==ENABLE)
+ {
+ return HOST_FALSE;
+ }
+ else
+ {
+ if(is_any_interrupt_pipe_active()==FALSE)
+ {
+ g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+ }
+ it_pipe_str[pipe].enable=ENABLE;
+ it_pipe_str[pipe].nb_byte_to_process=nb_data;
+ it_pipe_str[pipe].nb_byte_processed=0;
+ it_pipe_str[pipe].ptr_buf=buf;
+ it_pipe_str[pipe].handle=handle;
+ it_pipe_str[pipe].timeout=0;
+ it_pipe_str[pipe].nak_timeout=NAK_RECEIVE_TIMEOUT;
+
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ Host_reset_pipe(pipe);
+ Host_enable_stall_interrupt();
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ Host_enable_nak_interrupt();
+#endif
+ Host_enable_error_interrupt();
+ Host_enable_receive_interrupt();
+ Host_ack_stall();
+ Host_ack_nak_received();
+
+ Host_continuous_in_mode();
+ Host_set_token_in();
+ Host_unfreeze_pipe();
+ return HOST_TRUE;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// This function send nb_data pointed with *buf with the pipe number specified
+//------------------------------------------------------------------------------
+U8 host_send_data_interrupt(U8 pipe,
+ U16 nb_data,
+ U8 *buf,
+ void(*handle)(U8 status, U16 nb_byte))
+{
+ U16 i;
+ U8 *ptr_buf=buf;
+
+ TRACE_DEBUG("host_send_data_interrupt\n\r");
+ Host_select_pipe(pipe);
+ if(it_pipe_str[pipe].enable==ENABLE)
+ {
+ return HOST_FALSE;
+ }
+ else
+ {
+ if(is_any_interrupt_pipe_active()==FALSE)
+ {
+ g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+ }
+ it_pipe_str[pipe].enable=ENABLE;
+ it_pipe_str[pipe].nb_byte_to_process=nb_data;
+ it_pipe_str[pipe].nb_byte_processed=0;
+ it_pipe_str[pipe].ptr_buf=buf;
+ it_pipe_str[pipe].handle=handle;
+
+ it_pipe_str[pipe].timeout=0;
+ it_pipe_str[pipe].nak_timeout=NAK_SEND_TIMEOUT;
+ it_pipe_str[pipe].nb_byte_on_going=0;
+
+ Host_reset_pipe(pipe);
+ Host_unfreeze_pipe();
+ // Prepare data to be sent
+ i = host_get_pipe_length();
+ if ( i > nb_data) // Pipe size> remaining data
+ {
+ i = nb_data;
+ nb_data = 0;
+ }
+ else // Pipe size < remaining data
+ {
+ nb_data -= i;
+ }
+ it_pipe_str[pipe].nb_byte_on_going+=i; // Update nb data processed
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (i!=0) // Load Pipe buffer
+ {
+ Host_write_byte(*ptr_buf++);
+ i--;
+ }
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ it_pipe_str[pipe].timeout=0; // Refresh timeout counter
+ Host_ack_out_sent();
+ Host_ack_stall();
+ Host_ack_nak_received();
+
+ Host_enable_stall_interrupt();
+ Host_enable_error_interrupt();
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ Host_enable_nak_interrupt();
+#endif
+ Host_enable_transmit_interrupt();
+ Host_send_out(); // Send the USB frame
+ return HOST_TRUE;
+ }
+}
+
+//------------------------------------------------------------------------------
+//! @brief USB pipe interrupt subroutine
+//!
+//! @param none
+//!
+//! @return none
+//------------------------------------------------------------------------------
+void usb_pipe_interrupt(void)
+{
+ U8 pipe_nb;
+ U8 *ptr_buf;
+ void (*fct_handle)(U8 status,U16 nb_byte);
+ U16 n;
+ U8 i;
+ U8 do_call_back=FALSE;
+
+ TRACE_DEBUG("usb_pipe_interrupt\n\r");
+
+ if(Host_get_pipe_interrupt()) {
+
+ pipe_nb_save = Host_get_selected_pipe(); // Important! Save here working pipe number
+ pipe_nb=host_get_nb_pipe_interrupt(); // work with the correct pipe number that generates the interrupt
+ Host_select_pipe(pipe_nb); // Select this pipe
+ fct_handle=*(it_pipe_str[pipe_nb].handle);
+
+ // Now try to detect what event generate an interrupt...
+ if (Is_host_pipe_error()) // Any error ?
+ {
+ TRACE_DEBUG("host_pipe_error\n\r");
+ it_pipe_str[pipe_nb].status = Host_error_status();
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ Host_stop_pipe_interrupt(pipe_nb);
+ Host_ack_all_errors();
+ do_call_back=TRUE;
+ goto usb_pipe_interrupt_end;
+ }
+
+ if (Is_host_stall()) // Stall handshake received ?
+ {
+ TRACE_DEBUG("host_stall\n\r");
+ it_pipe_str[pipe_nb].status=PIPE_STALL;
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ goto usb_pipe_interrupt_end;
+ }
+
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ if (Is_host_nak_received()) // NAK ?
+ {
+ Host_ack_nak_received();
+ // check if number of NAK timeout error occurs (not for interrupt type pipe)
+ if((--it_pipe_str[pipe_nb].nak_timeout==0) && (Host_get_pipe_type()!=TYPE_INTERRUPT))
+ {
+ it_pipe_str[pipe_nb].status=PIPE_NAK_TIMEOUT;
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ goto usb_pipe_interrupt_end;
+ }
+ }
+#endif
+
+ if (Is_host_in_received()) // Pipe IN reception ?
+ {
+ TRACE_DEBUG("host_in received\n\r");
+ ptr_buf = it_pipe_str[pipe_nb].ptr_buf;
+ ptr_buf += it_pipe_str[pipe_nb].nb_byte_processed; // Build pointer to data buffer
+ n = it_pipe_str[pipe_nb].nb_byte_to_process;
+ n -= it_pipe_str[pipe_nb].nb_byte_processed; // Remaining data bytes
+ Host_freeze_pipe();
+ if (Host_byte_counter()<=n)
+ {
+ if ((Host_byte_counter() < n)&&(Host_byte_counter()<host_get_pipe_length())) //Received less than remaining, but less than pipe capacity
+ {
+ n=0;
+ }
+ else
+ {
+ n-=Host_byte_counter();
+ }
+ it_pipe_str[pipe_nb].nb_byte_processed += Host_byte_counter(); // Update nb of byte received
+
+ Address_fifochar_endpoint(global_pipe_nb);
+ for (i=Host_byte_counter();i;i--)
+ {
+ *ptr_buf = Host_read_byte();
+ ptr_buf++;
+ }
+ }
+ else // more bytes received than expected
+ { // TODO error code management
+ it_pipe_str[pipe_nb].nb_byte_processed+=n;
+ Address_fifochar_endpoint(global_pipe_nb);
+ for ( i=n; i; i-- ) // Byte number limited to the initial request (limit tab over pb)
+ {
+ *ptr_buf = Host_read_byte();
+ ptr_buf++;
+ }
+ n=0;
+ }
+ Host_ack_in_received();
+ if(n>0) //still something to process
+ {
+ Host_unfreeze_pipe(); // Request another IN transfer
+ Host_send_in();
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ it_pipe_str[pipe_nb].timeout=0; // Reset timeout
+ it_pipe_str[pipe_nb].nak_timeout=NAK_RECEIVE_TIMEOUT;
+ }
+ else //end of transfer
+ {
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ it_pipe_str[pipe_nb].status=PIPE_GOOD;
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ }
+ }
+
+ if(Is_host_out_sent()) // Pipe OUT sent ?
+ {
+ TRACE_DEBUG("host_out send\n\r");
+ Host_ack_out_sent();
+ it_pipe_str[pipe_nb].nb_byte_processed+=it_pipe_str[pipe_nb].nb_byte_on_going;
+ it_pipe_str[pipe_nb].nb_byte_on_going=0;
+ ptr_buf = it_pipe_str[pipe_nb].ptr_buf;
+ ptr_buf += it_pipe_str[pipe_nb].nb_byte_processed; // Build pointer to data buffer
+ n = it_pipe_str[pipe_nb].nb_byte_to_process;
+ n -= it_pipe_str[pipe_nb].nb_byte_processed; // Remaining data bytes
+ if(n>0) // Still data to process...
+ {
+ Host_unfreeze_pipe();
+ // Prepare data to be sent
+ i = host_get_pipe_length();
+ if ( i > n) // Pipe size> remaining data
+ {
+ i = n;
+ n = 0;
+ }
+ else // Pipe size < remaining data
+ {
+ n -= i;
+ }
+ it_pipe_str[pipe_nb].nb_byte_on_going+=i; // Update nb data processed
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (i!=0) // Load Pipe buffer
+ {
+ Host_write_byte(*ptr_buf++); i--;
+ }
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ it_pipe_str[pipe_nb].timeout=0; // Refresh timeout counter
+ it_pipe_str[pipe_nb].nak_timeout=NAK_SEND_TIMEOUT;
+ Host_send_out(); // Send the USB frame
+ }
+ else //n==0 Transfer is finished
+ {
+ it_pipe_str[pipe_nb].enable=DISABLE; // Tranfer end
+ it_pipe_str[pipe_nb].status=PIPE_GOOD; // Status OK
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ }
+ }
+
+usb_pipe_interrupt_end:
+ Host_select_pipe(pipe_nb_save); // Restore pipe number !!!!
+ if (is_any_interrupt_pipe_active()==FALSE) // If no more transfer is armed
+ {
+ if (g_sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt();
+ }
+ }
+ if(do_call_back) // Any callback functions to perform ?
+ {
+ fct_handle(it_pipe_str[pipe_nb].status,it_pipe_str[pipe_nb].nb_byte_processed);
+ }
+
+ }
+
+}
+
+
+
diff --git a/usb/otg/usb_host_task.h b/usb/otg/usb_host_task.h new file mode 100644 index 0000000..af752ec --- /dev/null +++ b/usb/otg/usb_host_task.h @@ -0,0 +1,230 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+#ifndef _USB_HOST_TASK_H_
+#define _USB_HOST_TASK_H_
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <conf_usb.h>
+#include <usb/otg/usb_host_enum.h>
+
+#include "main.h"
+
+//! @brief Selects the Reset Length (x11ms)
+//! This value is the number of consecutives Reset sent by the Host
+#define OTG_RESET_LENGTH 1
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+typedef struct
+{
+ bit enable;
+ U16 nb_byte_to_process;
+ U16 nb_byte_processed;
+ U16 nb_byte_on_going;
+ U8 *ptr_buf;
+ void(*handle)(U8 status, U16 nb_byte);
+ U8 status;
+ U8 timeout;
+ U16 nak_timeout;
+} S_pipe_int;
+
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+#define PIPE_GOOD 0
+//#define PIPE_DATA_TOGGLE 0x01
+//#define PIPE_DATA_PID 0x02
+//#define PIPE_PID 0x04
+//#define PIPE_TIMEOUT 0x08
+//#define PIPE_CRC16 0x10
+#define PIPE_STALL 0x20
+#define PIPE_NAK_TIMEOUT 0x40
+#define PIPE_DELAY_TIMEOUT 0x80
+
+// usb_host_task USB host task module
+// Returns true when device connected and correctly enumerated.
+// The host high level application should tests this before performing any applicative requests
+// to the device connected
+#define Is_host_ready() ((device_state==DEVICE_READY) ? TRUE : FALSE)
+
+/// Check if host controller is in suspend mode
+#define Is_host_suspended() (((device_state==DEVICE_WAIT_RESUME) ||(device_state==DEVICE_SUSPENDED)) ? TRUE : FALSE)
+
+/// Check if host controller is not suspend mode
+#define Is_host_not_suspended() (((device_state==DEVICE_WAIT_RESUME) ||(device_state==DEVICE_SUSPENDED)) ? FALSE : TRUE)
+
+/// This function should be called to make the host controller enter USB suspend mode
+#define Host_request_suspend() (device_state=DEVICE_SUSPENDED)
+
+/// This function should be called to request the host controller to resume the USB bus
+#define Host_request_resume() (request_resume=TRUE)
+
+/// Private ack for software event
+#define Host_ack_request_resume() (request_resume=FALSE)
+
+/// Private check for resume sequence
+#define Is_host_request_resume() ((request_resume==TRUE) ? TRUE : FALSE)
+
+/// Returns true when a new device is enumerated
+#define Is_new_device_connection_event() (new_device_connected ? TRUE : FALSE)
+
+/// Returns true when the device disconnects from the host
+#define Is_device_disconnection_event() ((device_state==DEVICE_DISCONNECTED_ACK || device_state==DEVICE_DISCONNECTED) ? TRUE : FALSE)
+
+/// Stop all interrupt attached to a pipe
+#define Host_stop_pipe_interrupt(i) {Host_disable_transmit_interrupt();\
+ Host_disable_receive_interrupt();\
+ Host_disable_stall_interrupt();\
+ Host_disable_error_interrupt();\
+ Host_disable_nak_interrupt();\
+ Host_reset_pipe(i); }
+
+/// device_state_value Host controller states
+/// Defines for device state coding
+#define DEVICE_UNATTACHED 0
+#define DEVICE_ATTACHED 1
+#define DEVICE_POWERED 2
+#define DEVICE_DEFAULT 3
+#define DEVICE_ADDRESSED 4
+#define DEVICE_CONFIGURED 5
+#define DEVICE_READY 6
+#define DEVICE_ERROR 7
+#define DEVICE_SUSPENDED 8
+#define DEVICE_WAIT_RESUME 9
+#define DEVICE_DISCONNECTED 10
+#define DEVICE_DISCONNECTED_ACK 11
+#define A_PERIPHERAL 12 // used for A-Device in OTG mode
+#define A_INIT_HNP 13
+#define A_SUSPEND 14
+#define A_END_HNP_WAIT_VFALL 15
+#define A_TEMPO_VBUS_DISCHARGE 16
+
+
+#define Host_set_device_supported() (device_status |= 0x01)
+#define Host_clear_device_supported() (device_status &= ~0x01)
+
+#define Host_set_device_ready() (device_status |= 0x02)
+#define Host_clear_device_ready() (device_status &= ~0x02)
+
+#define Host_set_configured() (device_status |= 0x04)
+#define Host_clear_configured() (device_status &= ~0x04)
+#define Is_host_configured() (device_status & 0x04)
+
+
+
+
+/// Has a SRP been received, and waiting for a connect of B-Device (Vbus delivered)
+#define Srp_received_and_waiting_connect() (otg_a_device_srp |= 0x01)
+#define Ack_srp_received_and_connect() (otg_a_device_srp &= ~0x01)
+#define Is_srp_received_and_waiting_connect() (((otg_a_device_srp&0x01) != 0) ? TRUE : FALSE)
+/// Is the current session has been started with SRP
+#define Host_session_started_srp() (otg_a_device_srp |= 0x02)
+#define Host_end_session_started_srp() (otg_a_device_srp &= ~0x02)
+#define Is_host_session_started_srp() (((otg_a_device_srp&0x02) != 0) ? TRUE : FALSE)
+
+/// Is the current peripheral is an OTG device ?
+#define Peripheral_is_not_otg_device() (otg_device_connected = 0x00)
+#define Peripheral_is_otg_device() (otg_device_connected = 0x11)
+#define Is_peripheral_otg_device() ((otg_device_connected != 0) ? TRUE : FALSE)
+
+/// Check if counter of Vbus delivery time after SRP is elapsed
+// 0xDAC = 3500, 3500x2 = 7000 => 7s
+#define T_VBUS_DELIV_AFTER_SRP 0xDAC // minimum time (x2ms) with Vbus ON once a SRP has been received (5s<t<30s)
+#define Init_ta_srp_counter() (otg_ta_srp_wait_connect = 0)
+#define Is_ta_srp_counter_overflow() ((otg_ta_srp_wait_connect > T_VBUS_DELIV_AFTER_SRP) ? TRUE : FALSE)
+
+/// Check if counter of A-Suspend delay is elapsed
+/// Max. delay for a B-DEVICE to disconnect once the A-HOST has set suspend mode
+// Min 200 ms
+// 0x96 = 150 ,150x2 = 300 => 300 ms
+#define TA_AIDL_BDIS 0x96 // minimum time (x2ms) in A_suspend state before stop Vbus (must be > 200ms)
+ // if value = 0, this is an infinite delay
+#define Init_ta_aidl_bdis_counter() (otg_ta_aidl_bdis_tmr = TA_AIDL_BDIS)
+#define Is_ta_aidl_bdis_counter_overflow() ((otg_ta_aidl_bdis_tmr == 0x0001) ? TRUE : FALSE)
+
+/// Check if counter otg_timeout_bdev_respond is elapsed
+// 0xD00 = 3328, 3328x2 = 6656 => 6s
+#define TM_OUT_MAX_BDEV_RESPONSE 0xD00 // maximum delay for the A-Device waiting for a response from B-Device once attached
+#define Init_timeout_bdev_response() (otg_timeout_bdev_respond = TM_OUT_MAX_BDEV_RESPONSE)
+#define Is_timeout_bdev_response_overflow() ((otg_timeout_bdev_respond == 0) ? TRUE : FALSE)
+
+/// Check if counter otg_ta_vbus_rise is elapsed
+// 0x28 = 40, 40x2 = 80 => 80ms
+#define TA_VBUS_RISE 0x28 // maximum delay for Vbus to reach the Va_vbus_valid threshold after being requested (must be < 100ms)
+#define Init_ta_vbus_rise_counter() (otg_ta_vbus_rise = TA_VBUS_RISE)
+#define Is_ta_vbus_rise_counter_overflow() ((otg_ta_vbus_rise == 0) ? TRUE : FALSE)
+
+/// Check if counter otg_ta_vbus_fall is elapsed
+// 50x2 = 100 => 100ms
+#define TA_VBUS_FALL 50
+#define Init_ta_vbus_fall_counter() (otg_end_hnp_vbus_delay = TA_VBUS_FALL)
+#define Is_ta_vbus_fall_counter_overflow() ((otg_end_hnp_vbus_delay == 0) ? TRUE : FALSE)
+
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+extern U8 g_sav_int_sof_enable;
+extern U8 device_state;
+extern U8 request_resume;
+extern U8 new_device_connected;
+
+// OTG Defines, Variables and Macros
+// See "usb_host_task.c" file for description of variables role and use
+extern U16 otg_ta_srp_wait_connect;
+extern U16 otg_ta_aidl_bdis_tmr;
+extern U8 otg_ta_vbus_rise;
+extern U16 otg_timeout_bdev_respond;
+extern U16 otg_end_hnp_vbus_delay;
+
+extern U8 otg_a_device_srp;
+extern U8 otg_device_connected;
+extern S_usb_setup_data usb_request;
+extern U8 device_status;
+extern U8 data_stage[SIZEOF_DATA_STAGE];
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+extern void usb_host_task_init(void);
+extern void usb_host_task(void);
+extern U8 host_send_data(U8 pipe, U16 nb_data, U8 *buf);
+extern U8 host_get_data(U8 pipe, U16 *nb_data, U8 *buf);
+extern void reset_it_pipe_str(void);
+extern U8 is_any_interrupt_pipe_active(void);
+extern U8 host_get_data_interrupt(U8 pipe, U16 nb_data, U8 *buf, void (*handle)(U8 status, U16 nb_byte));
+extern U8 host_send_data_interrupt(U8 pipe, U16 nb_data, U8 *buf, void (*handle)(U8 status, U16 nb_byte));
+extern void usb_pipe_interrupt(void);
+
+#endif // _USB_HOST_TASK_H_
+
diff --git a/usb/otg/usb_host_task_with_srp_hnp.c b/usb/otg/usb_host_task_with_srp_hnp.c new file mode 100644 index 0000000..4cf02b7 --- /dev/null +++ b/usb/otg/usb_host_task_with_srp_hnp.c @@ -0,0 +1,1493 @@ +/* ----------------------------------------------------------------------------
+ * 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 <memories/Media.h>
+#include "conf_usb.h"
+#include <conf_scheduler.h>
+#include <usb/common/core/USBConfigurationOTG.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/massstorage/MSDDriver.h>
+#include "usb/otg/usb_task.h"
+#include "usb_host_task.h"
+#include "usb/otg/usb_drv.h"
+#include "usb/otg/usb_host_enum.h"
+#include <utility/trace.h>
+#include "main.h"
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+//jcb #define WAIT_100MS 100
+// Wait 100 x 125 us = 12,5 ms before USB reset
+//#define WAIT_100MS 800
+#define WAIT_100MS 100
+
+#if (HOST_STRICT_VID_PID_TABLE != ENABLE)
+#warning HOST_STRICT_VID_PID_TABLE must be defined to ENABLE to comply with Targeted Peripheral List requirements
+#endif
+
+
+#ifndef DEVICE_ADDRESS
+#error DEVICE_ADDRESS should be defined somewhere in config files (conf_usb.h)
+#endif
+
+#ifndef SIZEOF_DATA_STAGE
+#error SIZEOF_DATA_STAGE should be defined in conf_usb.h
+#endif
+
+#ifndef HOST_CONTINUOUS_SOF_INTERRUPT
+#error HOST_CONTINUOUS_SOF_INTERRUPT should be defined as ENABLE or DISABLE in conf_usb.h
+#endif
+
+#ifndef Usb_id_transition_action
+#define Usb_id_transition_action()
+#endif
+#ifndef Host_device_disconnection_action
+#define Host_device_disconnection_action()
+#endif
+#ifndef Host_device_connection_action
+#define Host_device_connection_action()
+#endif
+#ifndef Host_sof_action
+#define Host_sof_action()
+#endif
+#ifndef Host_suspend_action
+#define Host_suspend_action()
+#endif
+#ifndef Host_hwup_action
+#define Host_hwup_action()
+#endif
+#ifndef Host_device_not_supported_action
+#define Host_device_not_supported_action()
+#endif
+#ifndef Host_device_class_not_supported_action
+#define Host_device_class_not_supported_action()
+#endif
+#ifndef Host_device_supported_action
+#define Host_device_supported_action()
+#endif
+#ifndef Host_device_error_action
+#define Host_device_error_action()
+#endif
+
+extern U8 id_changed_to_host_event;
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+volatile S_pipe_int it_pipe_str[MAX_EP_NB];
+volatile U8 pipe_nb_save;
+U8 g_sav_int_sof_enable;
+
+//! Min. delay after an SRP received, with VBUS delivered ON (waiting for a B-DEV connect)
+U16 otg_ta_srp_wait_connect;
+//! Max. delay for a B-DEVICE to disconnect once the A-HOST has set suspend mode
+U16 otg_ta_aidl_bdis_tmr;
+//! Max. delay for vbus to reach Va_vbus_valid threshold
+U8 otg_ta_vbus_rise;
+//! Max. delay once B-Device attached to respond to the first A-Device requests
+U16 otg_timeout_bdev_respond;
+//! Indicates if the connected peripheral is an OTG Device or not
+U8 otg_device_connected;
+//! Stores special events about SRP in A-Device mode
+U8 otg_a_device_srp;
+//! Variable used for timing Vbus discharge to avoid bounces around vbus_valid threshold
+U16 otg_end_hnp_vbus_delay;
+
+//! Its value represent the current state of the
+//! device connected to the usb host controller
+//! Value can be:
+//! - DEVICE_ATTACHED
+//! - DEVICE_POWERED
+//! - DEVICE_SUSPENDED
+//! - DEVICE_DEFAULT
+//! - DEVICE_ADDRESSED
+//! - DEVICE_CONFIGURED
+//! - DEVICE_ERROR
+//! - DEVICE_UNATTACHED
+//! - DEVICE_READY
+//! - DEVICE_WAIT_RESUME
+//! - DEVICE_DISCONNECTED
+//! - DEVICE_DISCONNECTED_ACK
+//! - and these have been added for OTG :
+//! - A_PERIPHERAL
+//! - A_INIT_HNP
+//! - A_SUSPEND
+//! - A_END_HNP_WAIT_VFALL
+U8 device_state;
+
+//! For control requests management over pipe 0
+S_usb_setup_data usb_request;
+
+//! Internal RAM buffer for USB data stage content
+//! This buffer is required to setup host enumeration process
+//! Its contains the device descriptors received.
+//! Depending on the device descriptors lenght, its size can be optimized
+//! with the SIZEOF_DATA_STAGE define of conf_usb.h file
+U8 data_stage[SIZEOF_DATA_STAGE];
+
+U8 device_status;
+U8 request_resume;
+
+
+U8 new_device_connected=0;
+
+//------------------------------------------------------------------------------
+// Local Variables
+//------------------------------------------------------------------------------
+static U16 hostSOFCounter; // As internal host start of frame counter
+
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// This function initializes the USB controller in host mode and the associated
+/// variables.
+/// This function enables the USB controller for host mode operation.
+//------------------------------------------------------------------------------
+void usb_host_task_init(void)
+{
+ unsigned int i;
+
+ TRACE_DEBUG("usb_host_task_init\n\r");
+
+ for( i=0; i<SIZEOF_DATA_STAGE; i++ ) {
+ data_stage[i] = 0;
+ }
+ Usb_disable();
+ Usb_enable();
+ Usb_unfreeze_clock();
+ USBD_Connect();
+ Usb_enable_uvcon_pin();
+ Usb_select_host();
+ Usb_disable_vbus_hw_control(); // Force Vbus generation without timeout
+ Host_enable_device_disconnection_interrupt();
+ Usb_enable_id_interrupt();
+ if( pOTGDescriptor->bOTGADevSRPReaction == VBUS_PULSE) {
+ Usb_select_vbus_srp_method();
+ }
+ else {
+ Usb_select_data_srp_method();
+ }
+ device_state=DEVICE_UNATTACHED;
+}
+
+//------------------------------------------------------------------------------
+/// Entry point of the USB host management
+/// The aim is to manage the device target connection and enumeration
+/// depending on the device_state, the function performs the required operations
+/// to get the device enumerated and configured
+/// Once the device is operationnal, the device_state value is DEVICE_READY
+/// This state should be tested by the host task application before performing
+/// any applicative requests to the device.
+//------------------------------------------------------------------------------
+void usb_host_task(void)
+{
+ U32 dec;
+ U8 desc_temp;
+
+ //TRACE_DEBUG("host_task ");
+ switch (device_state) {
+ case DEVICE_UNATTACHED:
+ // DEVICE_UNATTACHED state
+ // - Default init state
+ // - Try to give device power supply
+ //TRACE_DEBUG("DEVICE_UNATTACHED\n\r");
+ for (hostSOFCounter=0; hostSOFCounter<MAX_EP_NB; hostSOFCounter++) {
+ ep_table[hostSOFCounter]=0;
+ }// Reset PIPE lookup table with device EP addr
+ nb_interface_supported=0;
+ Host_clear_device_supported(); // Reset Device status
+ Host_clear_configured();
+ Host_clear_device_ready();
+ Usb_clear_all_event(); // Clear all software events
+ new_device_connected=0;
+ Host_end_session_started_srp();
+ Peripheral_is_not_otg_device();
+ Usb_host_reject_hnp();
+ Usb_disable_role_exchange_interrupt();
+ Usb_disable_hnp_error_interrupt();
+ if (Is_usb_id_host()) {
+ if(pOTGDescriptor->bOTGSoftwareVbusCtrl == ENABLE) {
+ if( Is_usb_bconnection_error_interrupt()||Is_usb_vbus_error_interrupt())
+ {
+ Usb_ack_bconnection_error_interrupt();
+ Usb_ack_vbus_error_interrupt();
+ Host_clear_vbus_request();
+ }
+
+ if(Is_usb_srp_interrupt()) {
+ Usb_ack_srp_interrupt();
+ // if Vbus was not already delivered, it is really an SRP (OTG B-Device)
+ Otg_print_new_event_message(OTGMSG_SRP_RECEIVED,OTG_TEMPO_2SEC);
+ Host_session_started_srp();
+ Init_ta_srp_counter();
+ Srp_received_and_waiting_connect();
+ Init_ta_vbus_rise_counter();
+ device_state=DEVICE_ATTACHED;
+ Usb_ack_bconnection_error_interrupt();
+ Usb_enable_vbus_pad();
+ Usb_enable_vbus();
+ Host_vbus_action();
+ }
+ }
+ else {
+ Usb_enable_vbus(); // Give at least device power supply!!!
+ Host_vbus_action();
+ if(Is_usb_vbus_high()) {
+ device_state=DEVICE_ATTACHED;
+ } // If VBUS ok goto to device connection expectation
+ }
+ }
+ else if (b_uut_device_state == B_HOST) {
+ device_state = DEVICE_ATTACHED;
+ }
+ break;
+
+ case DEVICE_ATTACHED :
+ // DEVICE_ATTACHED state
+ // - Vbus is on
+ // - Try to detect device connection
+ if (Is_device_connection() || (Is_usb_id_device() && (b_uut_device_state == B_HOST))) {
+ //TRACE_DEBUG("Is_device_connection\n\r");
+ Host_ack_device_connection();
+ Ack_srp_received_and_connect(); // connection might have been requested by SRP
+ // Now device is connected, enable disconnection interrupt
+ Host_enable_device_disconnection_interrupt();
+ // Reset device status
+ Host_clear_device_supported();
+ Host_clear_configured();
+ Host_clear_device_ready();
+ Host_ack_sof();
+
+ TRACE_DEBUG("begin timer\n\r");
+ gSystemTick = 0;
+ DelayMS(200);
+ TRACE_DEBUG("end timer\n\r");
+ // Clear bad VBUS error
+ Usb_ack_vbus_error_interrupt();
+ Host_disable_device_disconnection_interrupt();
+
+ Host_send_reset(); // First USB reset
+ Host_enable_sof(); // Start Start Of Frame generation
+ Host_enable_sof_interrupt(); // SOF will be detected under interrupt
+
+ Usb_ack_event(EVT_HOST_SOF);
+ while (Is_host_reset()) {
+ if (Is_usb_device_enabled()) {
+ break;
+ }
+ } // Active wait of end of reset send
+ Host_ack_reset();
+ // User can choose the number of consecutive resets sent
+ hostSOFCounter = 1;
+ while (hostSOFCounter != OTG_RESET_LENGTH ) {
+ Host_send_reset();
+ Usb_ack_event(EVT_HOST_SOF);
+ while (Is_host_reset()) {
+ if (Is_usb_device_enabled()) {
+ break;
+ }
+ }// Active wait of end of reset send
+ Host_ack_reset();
+ hostSOFCounter++;
+ }
+
+ //Workaround for some bugly devices with powerless pull up
+ //usually low speed where data line rise slowly and can be interpretaded as disconnection
+ for(hostSOFCounter=0;hostSOFCounter!=0xFFFF;hostSOFCounter++) { // Basic Timeout counter
+ if(Is_usb_event(EVT_HOST_SOF)) { //If we detect SOF, device is still alive and connected, just clear false disconnect flag
+ if(Is_device_disconnection()) {
+ Host_ack_device_connection();
+ Host_ack_device_disconnection();
+ break;
+ }
+ }
+ }
+ Host_enable_device_disconnection_interrupt();
+ hostSOFCounter = 0;
+ while (hostSOFCounter<WAIT_100MS) { // wait 100ms after USB reset
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ hostSOFCounter++;
+ }// Count Start Of frame
+ if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {
+ TRACE_DEBUG("goto error 2\n\r");
+ goto device_attached_error;
+ }
+ if (Is_usb_device_enabled()) {
+ break;
+ }
+ }
+ device_state = DEVICE_POWERED;
+ hostSOFCounter=0;
+
+ }
+
+
+ device_attached_error:
+ break;
+
+ case DEVICE_POWERED :
+ // DEVICE_POWERED state
+ //
+ // - Device connection (attach) as been detected,
+ // - Wait 100ms and configure default control pipe
+ //
+ //TRACE_INFO("Device Connection\n\r");
+ Host_device_connection_action();
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ if (hostSOFCounter++ >= WAIT_100MS) {
+ device_state = DEVICE_DEFAULT;
+ Host_select_pipe(PIPE_CONTROL);
+ Host_enable_pipe();
+ host_configure_pipe(PIPE_CONTROL,
+ TYPE_CONTROL,
+ TOKEN_SETUP,
+ EP_CONTROL,
+ SIZE_64,
+ ONE_BANK,
+ 0 );
+ device_state = DEVICE_DEFAULT;
+ }
+ }
+ break;
+
+ case DEVICE_DEFAULT :
+ // DEVICE_DEFAULT state
+ // - Get device descriptor
+ // - Reconfigure Pipe 0 according to Device EP0
+ // - Attribute device address
+ TRACE_DEBUG("DEVICE_DEFAULT\n\r");
+ // Get first device descriptor
+ Peripheral_is_not_otg_device(); // init status variable
+ Init_timeout_bdev_response(); // init B-Device "waiting response" delay (handled by timer interrupt in usb_task.c)
+
+ if( CONTROL_GOOD == host_get_device_descriptor_uncomplete()) {
+ hostSOFCounter = 0;
+ while(hostSOFCounter<20) { // wait 20ms before USB reset (special buggly devices...)
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ hostSOFCounter++;
+ }
+ if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {
+ break;
+ }
+ }
+ Host_disable_device_disconnection_interrupt();
+ Host_send_reset(); // First USB reset
+ Usb_ack_event(EVT_HOST_SOF);
+ while (Is_host_reset()); // Active wait of end of reset send
+ Host_ack_reset();
+ hostSOFCounter = 1;
+ while (hostSOFCounter != OTG_RESET_LENGTH) {
+ Host_send_reset();
+ Usb_ack_event(EVT_HOST_SOF);
+ while (Is_host_reset()); // Active wait of end of reset send
+ Host_ack_reset();
+ hostSOFCounter++;
+ }
+
+ //Workaround for some bugly devices with powerless pull up
+ //usually low speed where data line rise slowly and can be interpretaded as disconnection
+ for(hostSOFCounter=0;hostSOFCounter!=0xFFFF;hostSOFCounter++) { // Basic Timeout counter
+ if(Is_usb_event(EVT_HOST_SOF)) { //If we detect SOF, device is still alive and connected, just clear false disconnect flag
+ if(Is_device_disconnection()) {
+ Host_ack_device_connection();
+ Host_ack_device_disconnection();
+ break;
+ }
+ }
+ }
+ Host_enable_device_disconnection_interrupt();
+ hostSOFCounter = 0;
+ while(hostSOFCounter<200) { // wait 200ms after USB reset
+ if (Is_usb_event(EVT_HOST_SOF)) {
+ Usb_ack_event(EVT_HOST_SOF);
+ hostSOFCounter++;
+ }
+ if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {
+ break;
+ }
+ }
+
+ Host_select_pipe(PIPE_CONTROL);
+ Host_disable_pipe();
+ Host_unallocate_memory();
+ Host_enable_pipe();
+ // Re-Configure the Ctrl Pipe according to the device ctrl EP
+
+ TRACE_DEBUG("Size: 0x%X\n\r", (U16)data_stage[OFFSET_FIELD_MAXPACKETSIZE]);
+ TRACE_DEBUG("Size Pipe: 0x%X\n\r", host_determine_pipe_size((U16)data_stage[OFFSET_FIELD_MAXPACKETSIZE]));
+
+ host_configure_pipe(PIPE_CONTROL,
+ TYPE_CONTROL,
+ TOKEN_SETUP,
+ EP_CONTROL,
+ host_determine_pipe_size((U16)data_stage[OFFSET_FIELD_MAXPACKETSIZE]),
+ ONE_BANK,
+ 0 );
+ // Give an absolute device address
+ host_set_address(DEVICE_ADDRESS);
+ host_configure_address(PIPE_CONTROL, DEVICE_ADDRESS);
+ device_state = DEVICE_ADDRESSED;
+ }
+ else {
+ device_state = DEVICE_ERROR;
+ }
+ break;
+
+ case DEVICE_ADDRESSED :
+ // DEVICE_ADDRESSED state
+ // - Check if VID PID is in supported list
+ TRACE_DEBUG("DEVICE_ADDRESSED\n\r");
+ if (CONTROL_GOOD == host_get_device_descriptor()) {
+ // Detect if the device connected belongs to the supported devices table
+ if (HOST_TRUE == host_check_VID_PID()) {
+ Host_set_device_supported();
+ Host_device_supported_action();
+ device_state = DEVICE_CONFIGURED;
+ // In OTG A-HOST state, initiate a HNP if the OTG B-DEVICE has requested this session with a SRP
+ if ((pOTGDescriptor->bOTGEnableHNPAfterSRP == ENABLE) && Is_host_session_started_srp() && Is_usb_id_host()) {
+ device_state = A_INIT_HNP;
+ }
+ else {
+ if (Is_device_supports_hnp()) {
+ if (CONTROL_GOOD != host_set_feature_a_hnp_support()) {
+ device_state = A_END_HNP_WAIT_VFALL; // end session if Device STALLs the request
+ }
+ }
+ }
+ }
+ else
+ {
+ // In OTG, if the B-DEVICE VID/PID does not match the Target Peripheral List, it is seen as "Unsupported"
+ // - a HNP must be initiated if the device supports it
+ // - an error message must be displayed (and difference must be made between "Std device" and "Hub")
+ desc_temp = data_stage[OFFSET_DEV_DESC_CLASS]; // store the device class (for future hub check)
+ if (b_uut_device_state != B_HOST) {
+ if (Is_host_session_started_srp()) {
+ if (CONTROL_GOOD == host_get_configuration_descriptor()) {
+ host_check_OTG_features();
+ if (Is_device_supports_hnp()) {
+ device_state = A_INIT_HNP; // unsupported (or test) device will cause a HNP request
+ }
+ else {
+ device_state = A_END_HNP_WAIT_VFALL;
+ if (desc_temp == HUB_CLASS_CODE) {
+ // Display "Hub unsupported" message
+ Otg_print_new_failure_message(OTGMSG_UNSUPPORTED_HUB,OTG_TEMPO_4SEC);
+ }
+ else {
+ // Display "Class unsupported" message
+ TRACE_DEBUG("Class unsupported\n\r");
+ Otg_print_new_failure_message(OTGMSG_UNSUPPORTED,OTG_TEMPO_4SEC);
+ }
+ }
+ }
+ else {
+ device_state = A_END_HNP_WAIT_VFALL;
+ }
+ }
+ else {
+ device_state = A_INIT_HNP;
+ }
+ }
+ else
+ {
+ TRACE_DEBUG("VID/PID does not match the Target Peripheral List\n\r");
+ Otg_print_new_failure_message(OTGMSG_UNSUPPORTED,OTG_TEMPO_4SEC);
+ Set_user_request_disc(); // ask end of session now
+ Set_user_request_suspend();
+ }
+ }
+
+ }
+ else {// Can not get device descriptor
+ device_state = DEVICE_ERROR;
+ }
+ break;
+
+ case DEVICE_CONFIGURED :
+ // DEVICE_CONFIGURED state
+ // - Configure pipes for the supported interface
+ // - Send Set_configuration() request
+ // - Goto full operating mode (device ready)
+ TRACE_DEBUG("DEVICE_CONFIGURED\n\r");
+ if (CONTROL_GOOD == host_get_configuration_descriptor()) {
+ if (HOST_FALSE != host_check_class()) { // Class support OK?
+ // Collect information about peripheral OTG descriptor if present
+ host_check_OTG_features();
+ host_auto_configure_endpoint();
+
+ if (Is_host_configured()) {
+ if (CONTROL_GOOD== host_set_configuration(1)) { // Send Set_configuration
+ // host_set_interface(interface_bound,interface_bound_alt_set);
+ // device and host are now fully configured
+ // goto DEVICE READY normal operation
+ device_state = DEVICE_READY;
+ // monitor device disconnection under interrupt
+ Host_enable_device_disconnection_interrupt();
+ // If user host application requires SOF interrupt event
+ // Keep SOF interrupt enable otherwize, disable this interrupt
+#if (HOST_CONTINUOUS_SOF_INTERRUPT==DISABLE)
+ Host_disable_sof_interrupt();
+#endif
+ new_device_connected=TRUE;
+ TRACE_INFO("Device Enumerated\n\r");
+ }
+ else { // Problem during Set_configuration request...
+ device_state = DEVICE_ERROR;
+ }
+ }
+ }
+ else { // device class not supported...
+ device_state = DEVICE_ERROR;
+ TRACE_INFO("Unsupported Device\n\r");
+ Host_device_class_not_supported_action();
+ }
+ }
+ else { // Can not get configuration descriptors...
+ device_state = DEVICE_ERROR;
+ }
+ break;
+
+ case DEVICE_READY :
+ // DEVICE_READY state
+ // - Full standard operating mode
+ // - Nothing to do...
+ // Host full std operating mode!
+ new_device_connected=FALSE;
+
+ // Handles user requests : "stop Vbus" and "suspend"
+ if (Is_usb_id_host()) {
+ if (Is_user_requested_suspend() || Is_user_requested_hnp()) {
+ // Before entering suspend mode, A-Host must send a SetFeature(b_hnp_enable) if supported by the B-Periph
+ Ack_user_request_hnp();
+ Ack_user_request_suspend();
+ device_state = A_INIT_HNP;
+ }
+ }
+ break;
+
+ case DEVICE_ERROR :
+ //------------------------------------------------------
+ // DEVICE_ERROR state
+ // - Error state
+ // - Do custom action call (probably go to default mode...)
+ TRACE_DEBUG("DEVICE_ERROR\n\r");
+ device_state=DEVICE_UNATTACHED;
+ Host_device_error_action();
+ break;
+
+ case DEVICE_SUSPENDED :
+ // DEVICE_SUSPENDED state
+ // - Host application request to suspend the device activity
+ // - State machine comes here thanks to Host_request_suspend()
+ TRACE_DEBUG("DEVICE_SUSPENDED\n\r");
+ // If OTG device, initiate a HNP process (go to specific state)
+ if (Is_peripheral_otg_device()) {
+ device_state = A_INIT_HNP;
+ }
+ else {
+ device_state=DEVICE_WAIT_RESUME; // wait for device resume event
+ if(Is_device_supports_remote_wakeup()) { // If the connected device supports remote wake up
+ if (CONTROL_GOOD != host_set_feature_remote_wakeup()) {
+ device_state = DEVICE_DISCONNECTED; // stop connexion because device has not accepted the feature
+ }
+ }
+ TRACE_INFO("Usb suspend\n\r");
+ hostSOFCounter = Is_host_sof_interrupt_enabled(); //Save current sof interrupt enable state
+ Host_disable_sof_interrupt();
+ Host_ack_sof();
+ Host_disable_sof(); // Stop start of frame generation, this generates the suspend state
+ Host_ack_remote_wakeup();
+ Host_enable_remote_wakeup_interrupt();
+ Host_ack_hwup();
+ Host_enable_hwup_interrupt(); // Enable host wake-up interrupt
+ // (this is the unique USB interrupt able to wake up the CPU core from power-down mode)
+ Usb_freeze_clock();
+ Host_suspend_action(); // Custom action here! (for example go to power-save mode...)
+ }
+ break;
+
+ case DEVICE_WAIT_RESUME :
+ // DEVICE_WAIT_RESUME state
+ // - Wait in this state till the host receives an upstream resume from the device
+ // - or the host software request the device to resume
+ TRACE_DEBUG("DEVICE_WAIT_RESUME\n\r");
+ if(Is_usb_event(EVT_HOST_REMOTE_WAKEUP)|| Is_host_request_resume()) { // Remote wake up has been detected
+ // or Local resume request has been received
+ if(Is_host_request_resume()) { // Not a remote wakeup, but an host application request
+ Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up !
+ // CAUTION HWUP can be cleared only when USB clock is active
+ // Pll_start_auto(); // First Restart the PLL for USB operation
+ // Wait_pll_ready(); // Get sure pll is lock
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ }
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Host_enable_sof();
+
+ if (Is_usb_event(EVT_HOST_REMOTE_WAKEUP)) {
+ Usb_ack_event(EVT_HOST_REMOTE_WAKEUP); // Ack software event
+ Host_disable_sof_interrupt();
+ Host_ack_device_disconnection();
+ Host_disable_device_disconnection_interrupt();
+
+ Host_send_resume(); // this other downstream resume is done to ensure min. 20ms of HOST DRIVING RESUME (not Device)
+ while (!Is_device_disconnection() && Host_is_resume());
+ hostSOFCounter = 0;
+ Host_ack_sof();
+ while (!Is_device_disconnection() && (hostSOFCounter != 12)) { // wait for min. 10ms of device recovery time
+ if (Is_host_sof()) {
+ Host_ack_sof();
+ hostSOFCounter++;
+ }
+ }
+ if (Is_device_disconnection()) {
+ usb_host_task_init();
+ device_state = DEVICE_DISCONNECTED;
+ Host_ack_remote_wakeup(); // Ack remote wake-up reception
+ Host_ack_request_resume(); // Ack software request
+ Host_ack_down_stream_resume(); // Ack down stream resume sent
+ }
+ else {
+ device_state = DEVICE_READY;
+ Host_ack_remote_wakeup(); // Ack remote wake-up reception
+ Host_ack_request_resume(); // Ack software request
+ Host_ack_down_stream_resume(); // Ack down stream resume sent
+ }
+ Host_enable_device_disconnection_interrupt();
+ Host_ack_sof();
+ }
+ else {
+ Host_send_resume(); // Send down stream resume
+ //-----------------------
+ // Work-around for case of Device disconnection during Suspend
+ // The disconnection is never detected and the Resume bit remains high (and RSMEDI flag never set)
+ // If the timeout elapses, it implies that the device has disconnected => macro is reset (to reset the Resume bit)
+ dec = 0;
+ while (dec < 0x4FFFF) { // several hundreds of ms
+ if (Is_host_down_stream_resume()) { // Wait Down stream resume sent
+ Host_ack_remote_wakeup(); // Ack remote wake-up reception
+ Host_ack_request_resume(); // Ack software request
+ Host_ack_down_stream_resume(); // Ack down stream resume sent
+ if(hostSOFCounter) {
+ Host_enable_sof_interrupt();
+ } // Restore SOF interrupt enable state before suspend
+ device_state=DEVICE_READY; // Come back to full operating mode
+ TRACE_INFO("Usb resumed\n\r");
+ dec = 0x3FFFFE; // will cause a loop end
+ }
+ dec++;
+ }
+ if (dec != 0x3FFFFF) { // if resume failed
+ usb_host_task_init();
+ device_state = DEVICE_DISCONNECTED;
+ }
+ else
+ {
+ hostSOFCounter = 0;
+ Host_ack_sof();
+ while (!Is_device_disconnection() && (hostSOFCounter != 12)) { // wait for min. 10ms of device recovery time
+ if (Is_host_sof()) {
+ Host_ack_sof();
+ hostSOFCounter++;
+ }
+ }
+ }
+ //-----------------------End of Work Around
+ }
+ }
+ break;
+
+ case DEVICE_DISCONNECTED :
+ // DEVICE_DISCONNECTED state
+ // - Device disconnection has been detected
+ // - Run scheduler in this state at least two times to get sure event is detected by all host application tasks
+ // - Go to DEVICE_DISCONNECTED_ACK state before DEVICE_UNATTACHED, to get sure scheduler calls all app tasks...
+ TRACE_DEBUG("DEVICE_DISCONNECTED\n\r");
+ device_state = DEVICE_DISCONNECTED_ACK;
+ break;
+
+ case DEVICE_DISCONNECTED_ACK :
+ // DEVICE_DISCONNECTED_ACK state
+ // - Device disconnection has been detected and managed bu applicatives tasks
+ // - Go to DEVICE_UNATTACHED state
+ TRACE_DEBUG("DEVICE_DISCONNECTED_ACK\n\r");
+ host_disable_all_pipe();
+ device_state = DEVICE_UNATTACHED;
+ End_session_with_srp();
+ Usb_ack_srp_interrupt();
+ break;
+
+ case A_PERIPHERAL:
+ // OTG Specific states : A_PERIPHERAL (A-Host has been turned into a Device after a HNP)
+ // - End session (and stop driving Vbus) when detecting suspend condition
+ // - Disconnect on user request
+ // - Call standard (non-OTG) device task to handle the Endpoint 0 requests
+ TRACE_DEBUG("A_PERIPHERAL\n\r");
+ // End of role exchange : A_PERIPH go into DEVICE_DISCONNECTED mode : stop supplying VBUS
+ if (Is_usb_event(EVT_USB_SUSPEND)) {
+ Clear_all_user_request();
+ Usb_ack_event(EVT_USB_SUSPEND);
+ Usb_disable_wake_up_interrupt();
+ Usb_ack_role_exchange_interrupt();
+ Usb_select_host();
+ USBD_Connect();//Usb_attach();
+ Usb_unfreeze_clock();
+ b_uut_device_state = B_IDLE;
+ device_state = A_END_HNP_WAIT_VFALL;
+ Usb_ack_srp_interrupt();
+ }
+ if (Is_user_requested_disc() || Is_user_requested_vbus()) {
+ Clear_all_user_request();
+ Usb_disable_suspend_interrupt();
+ Usb_ack_role_exchange_interrupt();
+ Usb_select_host();
+ Usb_unfreeze_clock();
+ b_uut_device_state = B_IDLE;
+ device_state = A_END_HNP_WAIT_VFALL;
+ }
+ if (!Is_device_disconnection_event() && (device_state != A_END_HNP_WAIT_VFALL)) {
+ //usb_device_task();
+ //MSDDriver_StateMachine();
+ Scheduler_task_3();
+ }
+ break;
+
+ case A_INIT_HNP:
+ // OTG Specific states : A_INIT_HNP
+ // - Software enters this state when it has been requested to initiate a HNP
+ // - Handle "set feature" commands such as B_HNP_ENABLE or REMOTE_WAKE_UP
+ // - Handle failures
+ TRACE_DEBUG("A_INIT_HNP\n\r");
+ Ack_user_request_hnp();
+ Ack_user_request_suspend();
+ if (Is_peripheral_otg_device() || !Is_host_configured()) {
+ device_state = A_SUSPEND;
+ if(Is_device_supports_remote_wakeup() && Is_host_configured()) { // If the connected device supports remote wake up
+ if (CONTROL_GOOD == host_set_feature_remote_wakeup()) {
+ Host_ack_remote_wakeup();
+ Host_enable_remote_wakeup_interrupt();
+ Host_ack_hwup();
+ Host_enable_hwup_interrupt(); // Enable host wake-up interrupt
+ }
+ else {
+ device_state = A_END_HNP_WAIT_VFALL; // stop connection because device has STALLed the feature
+ }
+ }
+ if (Is_device_supports_hnp() || !Is_host_configured()) {
+ if (CONTROL_GOOD == host_set_feature_b_hnp_enable()) {
+ // B-Device has not STALLed the SetFeature
+ Usb_host_accept_hnp();
+ Usb_ack_role_exchange_interrupt();
+ Usb_ack_hnp_error_interrupt();
+ Usb_enable_role_exchange_interrupt();
+ Usb_enable_hnp_error_interrupt();
+ Host_disable_device_disconnection_interrupt();
+ Host_disable_device_connection_interrupt();
+ }
+ else {
+ Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC);
+ device_state = A_END_HNP_WAIT_VFALL;
+ }
+ }
+ Host_ack_remote_wakeup();
+ Host_enable_remote_wakeup_interrupt();
+ Init_ta_aidl_bdis_counter();
+ Host_disable_sof_interrupt();
+ Host_ack_sof();
+ Host_disable_sof(); // Stop start of frame generation, this generates the suspend state
+ Usb_disable_suspend_interrupt();
+ }
+ else {
+ device_state = DEVICE_SUSPENDED;
+ }
+ break;
+
+ case A_SUSPEND:
+ // OTG Specific states : A_SUSPEND
+ // - A-Host enters this state when it has requested the B-DEVICE to start HNP, and have entered Suspend mode
+ // - Detects device silences (with HNP time-out management) and Resume condition
+ TRACE_DEBUG("A_SUSPEND\n\r");
+ Usb_ack_suspend();
+ // HNP is managed by interrupt (HNPERRI/ROLEEXI)
+ if (Is_ta_aidl_bdis_counter_overflow()) {
+ device_state = A_END_HNP_WAIT_VFALL; // stop Vbus = end of current session
+ }
+ if (Is_usb_event(EVT_HOST_HWUP)|| Is_host_request_resume()) {
+ device_state = DEVICE_WAIT_RESUME;
+ }
+ break;
+
+ case A_END_HNP_WAIT_VFALL:
+ // OTG Specific states : A_END_HNP_WAIT_VFALL
+ // - A-PERIPH enters this state when it has detected a Suspend from the B-Host
+ // - It stop Vbus delivery and waits line discharge (to avoid spurious SRP detection)
+ TRACE_DEBUG("A_END_HNP_WAIT_VFALL\n\r");
+ Usb_disable_manual_vbus();
+ Usb_disable_vbus();
+ usb_configuration_nb = 0;
+ Host_vbus_action();
+ Clear_all_user_request();
+ device_state = DEVICE_DISCONNECTED;
+ usb_host_task_init();
+ break;
+
+ case A_TEMPO_VBUS_DISCHARGE:
+ // OTG Specific states : A_TEMPO_VBUS_DISCHARGE
+ // - State entered from A_END_HNP_WAIT_VFALL, when Vbus has just reached the vbus_valid threshold
+ // - In this state we wait long enough (50ms) to be sure that Vbus is not valid on the other device (if still connected)
+ // - When delay is elapsed, go to reset state
+ TRACE_DEBUG("A_TEMPO_VBUS_DISCHARGE\n\r");
+ if (otg_end_hnp_vbus_delay == 0) {
+ Host_ack_device_connection();
+ Host_ack_device_disconnection();
+ Usb_ack_role_exchange_interrupt();
+ Usb_ack_srp_interrupt();
+ device_state = DEVICE_DISCONNECTED;
+ }
+ break;
+
+ default :
+ // default state
+ // - Default case: ERROR
+ // - Goto no device state
+ TRACE_DEBUG("default\n\r");
+ device_state = DEVICE_UNATTACHED;
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// This function send nb_data pointed with *buf with the pipe number specified
+/// This function will activate the host sof interrupt to detect timeout. The
+/// interrupt enable sof will be restore.
+//------------------------------------------------------------------------------
+U8 host_send_data(U8 pipe, U16 nb_data, U8 *buf)
+{
+ U16 length;
+ U8 status=PIPE_GOOD;
+ U8 sav_int_sof_enable;
+ U8 nak_timeout;
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ U16 cpt_nak;
+#endif
+ U16 nb_data_loaded;
+
+ TRACE_DEBUG("host_send_data[]%d: %d\n\r", pipe, nb_data);
+
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled(); // Save state of enable sof interrupt
+ Host_enable_sof_interrupt();
+ Host_select_pipe(pipe);
+
+ Host_set_token_in();
+
+ Host_set_token_out();
+ Host_ack_out_sent();
+ /*
+ TRACE_DEBUG("CTRL: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_CTRL);
+ TRACE_DEBUG("SR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_SR);
+ TRACE_DEBUG("DEVCTRL: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVCTRL);
+ TRACE_DEBUG("DEVISR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVISR);
+ TRACE_DEBUG("DEVIMR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVIMR);
+ TRACE_DEBUG("DEVEPTISR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_DEVEPTISR[0]);
+ TRACE_DEBUG("HSTCTRL: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTCTRL);
+ TRACE_DEBUG("HSTISR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTISR);
+ TRACE_DEBUG("HSTIMR: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTIMR);
+ TRACE_DEBUG("HSTPIP: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIP);
+ TRACE_DEBUG("HSTPIPCFG[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[0]);
+ TRACE_DEBUG("HSTPIPCFG[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[1]);
+ TRACE_DEBUG("HSTPIPCFG[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPCFG[2]);
+ TRACE_DEBUG("HSTPIPINRQ[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[0]);
+ TRACE_DEBUG("HSTPIPINRQ[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[1]);
+ TRACE_DEBUG("HSTPIPINRQ[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPINRQ[2]);
+ TRACE_DEBUG("HSTPIPERR[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[0]);
+ TRACE_DEBUG("HSTPIPERR[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[1]);
+ TRACE_DEBUG("HSTPIPERR[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPERR[2]);
+ TRACE_DEBUG("HSTPIPISR[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[0]);
+ TRACE_DEBUG("HSTPIPISR[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[1]);
+ TRACE_DEBUG("HSTPIPISR[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPISR[2]);
+ TRACE_DEBUG("HSTPIPIMR[0]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[0]);
+ TRACE_DEBUG("HSTPIPIMR[1]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[1]);
+ TRACE_DEBUG("HSTPIPIMR[2]: 0x%X\n\r",AT91C_BASE_OTGHS->OTGHS_HSTPIPIMR[2]);
+ */
+ while (nb_data != 0) { // While there is something to send...
+ Host_unfreeze_pipe();
+ // Prepare data to be sent
+ length = host_get_pipe_length();
+ TRACE_DEBUG("size=%d\n\r", length);
+
+ if ( length > nb_data) {
+ nb_data_loaded = nb_data;
+ length = nb_data;
+ }
+ else {
+ nb_data_loaded = length;
+ }
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (length!=0) { // Load Pipe buffer
+ Host_write_byte(*buf++);
+ //(((char*)((unsigned int *)AT91C_BASE_OTGHS_EPTFIFO->OTGHS_READEPT0))[dBytes++])=*(buf++);
+ //pFifo[dBytes++] = *buf;
+ //buf++;
+ length--;
+ }
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ cpt_nak=0;
+#endif
+ nak_timeout=0;
+ Host_ack_out_sent();
+ Host_send_out();
+ while (!Is_host_out_sent()) {
+ if (Is_host_emergency_exit()) { // Async disconnection or role change detected under interrupt
+ TRACE_DEBUG("Emergency exit\n\r");
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_send_data_end;
+ }
+ if (private_sof_counter>=250) { // Count 250ms (250sof)
+ TRACE_DEBUG("TimeOut Send Data\n\r");
+ private_sof_counter=0;
+ if (nak_timeout++>=TIMEOUT_DELAY) { // Inc timeout and check for overflow
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_send_data_end;
+ }
+ }
+ if (Is_host_pipe_error()) { // Any error ?
+ TRACE_DEBUG("pipe error\n\r");
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_send_data_end;
+ }
+ if (Is_host_stall()) { // Stall management
+ TRACE_DEBUG("stall\n\r");
+ status =PIPE_STALL;
+ Host_ack_stall();
+ goto host_send_data_end;
+ }
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ if(Is_host_nak_received()) { //NAK received
+ Host_ack_nak_received();
+ if (cpt_nak++>NAK_SEND_TIMEOUT) {
+ TRACE_DEBUG("NAK timeout\n\r");
+ status = PIPE_NAK_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_send_data_end;
+ }
+ }
+#endif
+ }
+ // Here OUT sent
+ nb_data -= nb_data_loaded;
+ status=PIPE_GOOD; // Frame correctly sent
+ Host_ack_out_sent();
+ }
+ Host_freeze_pipe();
+
+host_send_data_end:
+ // Restore sof interrupt enable state
+ if (sav_int_sof_enable==FALSE) {
+ Host_disable_sof_interrupt();
+ }
+ // And return...
+ return ((U8)status);
+}
+
+
+
+//------------------------------------------------------------------------------
+/// This function receives nb_data pointed with *buf with the pipe number specified
+/// The nb_data parameter is passed as a U16 pointer, thus the data pointed by this pointer
+/// is updated with the final number of data byte received.
+//------------------------------------------------------------------------------
+U8 host_get_data(U8 pipe, U16 *nb_data, U8 *buf)
+{
+ U8 status=PIPE_GOOD;
+ U8 sav_int_sof_enable;
+ U8 nak_timeout;
+ U16 n;
+ U16 i;
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ U16 cpt_nak;
+#endif
+
+ // TRACE_DEBUG("host_get_data[%d]\n\r", pipe);
+ n=*nb_data;
+ *nb_data=0;
+
+ sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+
+ Host_select_pipe(pipe);
+ Host_set_token_in();
+ Host_continuous_in_mode();
+ // Host_ack_in_received();
+
+ while (n) { // While missing data...
+ // start IN request generation
+ Host_unfreeze_pipe();
+ Host_send_in();
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ nak_timeout=0;
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ cpt_nak=0;
+#endif
+ while (!Is_host_in_received())
+ {
+ if (Is_host_emergency_exit()) // Async disconnection or role change detected under interrupt
+ {
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_get_data_end;
+ }
+ if (private_sof_counter>=250) // Timeout management
+ {
+ private_sof_counter=0; // Done in host SOF interrupt
+ if (nak_timeout++>=TIMEOUT_DELAY)// Check for local timeout
+ {
+ status=PIPE_DELAY_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_get_data_end;
+ }
+ }
+ if(Is_host_pipe_error()) // Error management
+ {
+ status = Host_error_status();
+ Host_ack_all_errors();
+ goto host_get_data_end;
+ }
+ if(Is_host_stall()) // STALL management
+ {
+ status =PIPE_STALL;
+ Host_reset_pipe(pipe);
+ Host_ack_stall();
+ goto host_get_data_end;
+ }
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ if(Is_host_nak_received()) //NAK received
+ {
+ Host_ack_nak_received();
+ if (cpt_nak++>NAK_RECEIVE_TIMEOUT)
+ {
+ status = PIPE_NAK_TIMEOUT;
+ Host_reset_pipe(pipe);
+ goto host_get_data_end;
+ }
+ }
+#endif
+ }
+ status=PIPE_GOOD;
+ Host_freeze_pipe();
+ if (Host_byte_counter()<=n)
+ {
+ if ((Host_byte_counter() < n)&&(Host_byte_counter()<host_get_pipe_length()))
+ {
+ n = 0;
+ }
+ else
+ {
+ n -= Host_byte_counter();
+ }
+ (*nb_data) += Host_byte_counter(); // Update nb of byte received
+
+ Address_fifochar_endpoint(global_pipe_nb);
+ for (i=Host_byte_counter(); i; i--)
+ {
+ *buf = Host_read_byte();
+ buf++;
+ }
+ }
+ else // more bytes received than expected
+ { // TODO error code management
+ *nb_data += n;
+ Address_fifochar_endpoint(global_pipe_nb);
+ for (i=n; i; i--) // Byte number limited to the initial request (limit tab over pb)
+ {
+ *buf = Host_read_byte();
+ buf++;
+ }
+ n=0;
+ }
+ Host_ack_in_received();
+ }
+
+ Host_freeze_pipe();
+
+host_get_data_end:
+ if (sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt();
+ }
+ return ((U8)status);
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void reset_it_pipe_str(void)
+{
+ U8 i;
+ TRACE_DEBUG("reset_it_pipe_str\n\r");
+ for(i=0;i<MAX_EP_NB;i++)
+ {
+ it_pipe_str[i].enable=DISABLE;
+ it_pipe_str[i].timeout=0;
+ }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+U8 is_any_interrupt_pipe_active(void)
+{
+ U8 i;
+ TRACE_DEBUG("is_any_interrupt_pipe_active\n\r");
+ for(i=0;i<MAX_EP_NB;i++)
+ {
+ if(it_pipe_str[i].enable==ENABLE) return TRUE;
+ }
+ return FALSE;
+}
+
+//------------------------------------------------------------------------------
+/// This function receives nb_data pointed with *buf with the pipe number specified
+/// The nb_data parameter is passed as a U16 pointer, thus the data pointed by this pointer
+/// is updated with the final number of data byte received.
+//------------------------------------------------------------------------------
+U8 host_get_data_interrupt(U8 pipe, U16 nb_data, U8 *buf,void(*handle)(U8 status, U16 nb_byte))
+{
+ TRACE_DEBUG("host_get_data_interrupt\n\r");
+ Host_select_pipe(pipe);
+ if(it_pipe_str[pipe].enable==ENABLE)
+ {
+ return HOST_FALSE;
+ }
+ else
+ {
+ if(is_any_interrupt_pipe_active()==FALSE)
+ {
+ g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+ }
+ it_pipe_str[pipe].enable=ENABLE;
+ it_pipe_str[pipe].nb_byte_to_process=nb_data;
+ it_pipe_str[pipe].nb_byte_processed=0;
+ it_pipe_str[pipe].ptr_buf=buf;
+ it_pipe_str[pipe].handle=handle;
+ it_pipe_str[pipe].timeout=0;
+ it_pipe_str[pipe].nak_timeout=NAK_RECEIVE_TIMEOUT;
+
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ Host_reset_pipe(pipe);
+ Host_enable_stall_interrupt();
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ Host_enable_nak_interrupt();
+#endif
+ Host_enable_error_interrupt();
+ Host_enable_receive_interrupt();
+ Host_ack_stall();
+ Host_ack_nak_received();
+
+ Host_continuous_in_mode();
+ Host_set_token_in();
+ Host_unfreeze_pipe();
+ return HOST_TRUE;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// This function send nb_data pointed with *buf with the pipe number specified
+//------------------------------------------------------------------------------
+U8 host_send_data_interrupt(U8 pipe,
+ U16 nb_data,
+ U8 *buf,
+ void(*handle)(U8 status, U16 nb_byte))
+{
+ U16 i;
+ U8 *ptr_buf=buf;
+
+ TRACE_DEBUG("host_send_data_interrupt\n\r");
+ Host_select_pipe(pipe);
+ if(it_pipe_str[pipe].enable==ENABLE)
+ {
+ return HOST_FALSE;
+ }
+ else
+ {
+ if(is_any_interrupt_pipe_active()==FALSE)
+ {
+ g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
+ Host_enable_sof_interrupt();
+ }
+ it_pipe_str[pipe].enable=ENABLE;
+ it_pipe_str[pipe].nb_byte_to_process=nb_data;
+ it_pipe_str[pipe].nb_byte_processed=0;
+ it_pipe_str[pipe].ptr_buf=buf;
+ it_pipe_str[pipe].handle=handle;
+
+ it_pipe_str[pipe].timeout=0;
+ it_pipe_str[pipe].nak_timeout=NAK_SEND_TIMEOUT;
+ it_pipe_str[pipe].nb_byte_on_going=0;
+
+ Host_reset_pipe(pipe);
+ Host_unfreeze_pipe();
+ // Prepare data to be sent
+ i = host_get_pipe_length();
+ if ( i > nb_data) // Pipe size> remaining data
+ {
+ i = nb_data;
+ nb_data = 0;
+ }
+ else // Pipe size < remaining data
+ {
+ nb_data -= i;
+ }
+ it_pipe_str[pipe].nb_byte_on_going+=i; // Update nb data processed
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (i!=0) // Load Pipe buffer
+ {
+ Host_write_byte(*ptr_buf++);
+ i--;
+ }
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ it_pipe_str[pipe].timeout=0; // Refresh timeout counter
+ Host_ack_out_sent();
+ Host_ack_stall();
+ Host_ack_nak_received();
+
+ Host_enable_stall_interrupt();
+ Host_enable_error_interrupt();
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ Host_enable_nak_interrupt();
+#endif
+ Host_enable_transmit_interrupt();
+ Host_send_out(); // Send the USB frame
+ return HOST_TRUE;
+ }
+}
+
+//------------------------------------------------------------------------------
+//! @brief USB pipe interrupt subroutine
+//!
+//! @param none
+//!
+//! @return none
+//------------------------------------------------------------------------------
+void usb_pipe_interrupt(void)
+{
+ U8 pipe_nb;
+ U8 *ptr_buf;
+ void (*fct_handle)(U8 status,U16 nb_byte);
+ U16 n;
+ U8 i;
+ U8 do_call_back=FALSE;
+
+ TRACE_DEBUG("usb_pipe_interrupt\n\r");
+
+ if(Host_get_pipe_interrupt()) {
+
+ pipe_nb_save = Host_get_selected_pipe(); // Important! Save here working pipe number
+ pipe_nb=host_get_nb_pipe_interrupt(); // work with the correct pipe number that generates the interrupt
+ Host_select_pipe(pipe_nb); // Select this pipe
+ fct_handle=*(it_pipe_str[pipe_nb].handle);
+
+ // Now try to detect what event generate an interrupt...
+ if (Is_host_pipe_error()) // Any error ?
+ {
+ TRACE_DEBUG("host_pipe_error\n\r");
+ it_pipe_str[pipe_nb].status = Host_error_status();
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ Host_stop_pipe_interrupt(pipe_nb);
+ Host_ack_all_errors();
+ do_call_back=TRUE;
+ goto usb_pipe_interrupt_end;
+ }
+
+ if (Is_host_stall()) // Stall handshake received ?
+ {
+ TRACE_DEBUG("host_stall\n\r");
+ it_pipe_str[pipe_nb].status=PIPE_STALL;
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ goto usb_pipe_interrupt_end;
+ }
+
+#if (NAK_TIMEOUT_ENABLE==ENABLE)
+ if (Is_host_nak_received()) // NAK ?
+ {
+ Host_ack_nak_received();
+ // check if number of NAK timeout error occurs (not for interrupt type pipe)
+ if((--it_pipe_str[pipe_nb].nak_timeout==0) && (Host_get_pipe_type()!=TYPE_INTERRUPT))
+ {
+ it_pipe_str[pipe_nb].status=PIPE_NAK_TIMEOUT;
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ goto usb_pipe_interrupt_end;
+ }
+ }
+#endif
+
+ if (Is_host_in_received()) // Pipe IN reception ?
+ {
+ TRACE_DEBUG("host_in received\n\r");
+ ptr_buf = it_pipe_str[pipe_nb].ptr_buf;
+ ptr_buf += it_pipe_str[pipe_nb].nb_byte_processed; // Build pointer to data buffer
+ n = it_pipe_str[pipe_nb].nb_byte_to_process;
+ n -= it_pipe_str[pipe_nb].nb_byte_processed; // Remaining data bytes
+ Host_freeze_pipe();
+ if (Host_byte_counter()<=n)
+ {
+ if ((Host_byte_counter() < n)&&(Host_byte_counter()<host_get_pipe_length())) //Received less than remaining, but less than pipe capacity
+ {
+ n=0;
+ }
+ else
+ {
+ n-=Host_byte_counter();
+ }
+ it_pipe_str[pipe_nb].nb_byte_processed += Host_byte_counter(); // Update nb of byte received
+
+ Address_fifochar_endpoint(global_pipe_nb);
+ for (i=Host_byte_counter();i;i--)
+ {
+ *ptr_buf = Host_read_byte();
+ ptr_buf++;
+ }
+ }
+ else // more bytes received than expected
+ { // TODO error code management
+ it_pipe_str[pipe_nb].nb_byte_processed+=n;
+ Address_fifochar_endpoint(global_pipe_nb);
+ for ( i=n; i; i-- ) // Byte number limited to the initial request (limit tab over pb)
+ {
+ *ptr_buf = Host_read_byte();
+ ptr_buf++;
+ }
+ n=0;
+ }
+ Host_ack_in_received();
+ if(n>0) //still something to process
+ {
+ Host_unfreeze_pipe(); // Request another IN transfer
+ Host_send_in();
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ it_pipe_str[pipe_nb].timeout=0; // Reset timeout
+ it_pipe_str[pipe_nb].nak_timeout=NAK_RECEIVE_TIMEOUT;
+ }
+ else //end of transfer
+ {
+ it_pipe_str[pipe_nb].enable=DISABLE;
+ it_pipe_str[pipe_nb].status=PIPE_GOOD;
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ }
+ }
+
+ if(Is_host_out_sent()) // Pipe OUT sent ?
+ {
+ TRACE_DEBUG("host_out send\n\r");
+ Host_ack_out_sent();
+ it_pipe_str[pipe_nb].nb_byte_processed+=it_pipe_str[pipe_nb].nb_byte_on_going;
+ it_pipe_str[pipe_nb].nb_byte_on_going=0;
+ ptr_buf = it_pipe_str[pipe_nb].ptr_buf;
+ ptr_buf += it_pipe_str[pipe_nb].nb_byte_processed; // Build pointer to data buffer
+ n = it_pipe_str[pipe_nb].nb_byte_to_process;
+ n -= it_pipe_str[pipe_nb].nb_byte_processed; // Remaining data bytes
+ if(n>0) // Still data to process...
+ {
+ Host_unfreeze_pipe();
+ // Prepare data to be sent
+ i = host_get_pipe_length();
+ if ( i > n) // Pipe size> remaining data
+ {
+ i = n;
+ n = 0;
+ }
+ else // Pipe size < remaining data
+ {
+ n -= i;
+ }
+ it_pipe_str[pipe_nb].nb_byte_on_going+=i; // Update nb data processed
+ Address_fifochar_endpoint(global_pipe_nb);
+ while (i!=0) // Load Pipe buffer
+ {
+ Host_write_byte(*ptr_buf++); i--;
+ }
+ private_sof_counter=0; // Reset the counter in SOF detection sub-routine
+ it_pipe_str[pipe_nb].timeout=0; // Refresh timeout counter
+ it_pipe_str[pipe_nb].nak_timeout=NAK_SEND_TIMEOUT;
+ Host_send_out(); // Send the USB frame
+ }
+ else //n==0 Transfer is finished
+ {
+ it_pipe_str[pipe_nb].enable=DISABLE; // Tranfer end
+ it_pipe_str[pipe_nb].status=PIPE_GOOD; // Status OK
+ Host_stop_pipe_interrupt(pipe_nb);
+ do_call_back=TRUE;
+ }
+ }
+
+usb_pipe_interrupt_end:
+ Host_select_pipe(pipe_nb_save); // Restore pipe number !!!!
+ if (is_any_interrupt_pipe_active()==FALSE) // If no more transfer is armed
+ {
+ if (g_sav_int_sof_enable==FALSE)
+ {
+ Host_disable_sof_interrupt();
+ }
+ }
+ if(do_call_back) // Any callback functions to perform ?
+ {
+ fct_handle(it_pipe_str[pipe_nb].status,it_pipe_str[pipe_nb].nb_byte_processed);
+ }
+
+ }
+
+}
+
+
+
diff --git a/usb/otg/usb_task.c b/usb/otg/usb_task.c new file mode 100644 index 0000000..043879f --- /dev/null +++ b/usb/otg/usb_task.c @@ -0,0 +1,999 @@ +/* ----------------------------------------------------------------------------
+ * 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 <memories/Media.h>
+#include "main.h"
+#include <msd/conf_usb.h>
+#include <utility/trace.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/massstorage/MSDDriver.h>
+#include <usb/device/massstorage/MSDLun.h>
+#include <usb/device/core/USBDCallbacks.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include "otg_user_task.h"
+#include "usb_task.h"
+#include "usb/otg/usb_drv.h"
+
+#if ((USB_HOST_FEATURE == ENABLE))
+ #include "usb/otg/usb_host_task.h"
+#endif
+
+#if ((USB_DEVICE_FEATURE == ENABLE))
+#include <memories/Media.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/massstorage/MSDDriver.h>
+#include <usb/device/massstorage/MSDLun.h>
+#include <usb/device/core/USBDCallbacks.h>
+#include <usb/device/massstorage/MSD.h>
+#endif
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+
+
+extern volatile unsigned int timer_set_counter;
+#define Timer16_select(...)
+#define Timer16_set_counter(value) timer_set_counter = value
+#define Timer16_get_counter_low() (unsigned char)timer_set_counter
+
+
+/// Returns the OTG features sent by the host by a SetFeature
+/// Allow also to clear the features (only on a bus Reset or Session End)
+#define Is_host_requested_hnp() (((otg_features_supported&USBFeatureRequest_OTG_B_HNP_ENABLE) != 0) ? TRUE : FALSE)
+#define Clear_otg_features_from_host() (otg_features_supported = 0)
+
+#define Set_otg_custom_timer(ep) // STUB: todo
+
+#define USB_MODE_UNDEFINED 0x00
+#define USB_MODE_HOST 0x01
+#define USB_MODE_DEVICE 0x02
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+U8 otg_device_sessions;
+U8 b_uut_device_state;
+U16 otg_tb_srp_cpt;
+
+/// usb_connected is used to store USB events detected upon
+/// USB general interrupt subroutine
+/// Its value is managed by the following macros (See usb_task.h file)
+/// Usb_send_event(x)
+/// Usb_ack_event(x)
+/// Usb_clear_all_event()
+/// Is_usb_event(x)
+/// Is_not_usb_event(x)
+volatile U16 g_usb_event=0;
+
+
+#if (USB_DEVICE_FEATURE == ENABLE)
+///
+/// Public : (bit) usb_connected
+/// usb_connected is set to TRUE when VBUS has been detected
+/// usb_connected is set to FALSE otherwise
+/// Used with USB_DEVICE_FEATURE == ENABLE only
+////
+bit usb_connected;
+
+///
+/// Public : (U8) usb_configuration_nb
+/// Store the number of the USB configuration used by the USB device
+/// when its value is different from zero, it means the device mode is enumerated
+/// Used with USB_DEVICE_FEATURE == ENABLE only
+////
+U8 usb_configuration_nb;
+
+///
+/// Public : (U8) remote_wakeup_feature
+/// Store a host request for remote wake up (set feature received)
+////
+U8 remote_wakeup_feature;
+#endif
+
+
+#if (USB_HOST_FEATURE == ENABLE)
+///
+/// Private : (U8) private_sof_counter
+/// Incremented by host SOF interrupt subroutime
+/// This counter is used to detect timeout in host requests.
+/// It must not be modified by the user application tasks.
+////
+volatile U8 private_sof_counter=0;
+
+extern volatile S_pipe_int it_pipe_str[MAX_EP_NB];
+
+#endif
+
+#if ((USB_DEVICE_FEATURE == ENABLE)&& (USB_HOST_FEATURE == ENABLE))
+///
+/// Public : (U8) g_usb_mode
+/// Used in dual role application (both device/host) to store
+/// the current mode the usb controller is operating
+////
+ U8 g_usb_mode=USB_MODE_UNDEFINED;
+ U8 g_old_usb_mode;
+#endif
+
+
+#if (USB_OTG_FEATURE == ENABLE)
+ ///
+ /// Public : (U8) otg_features_supported;
+ /// -> A-Device side : indicates if the B-Device supports HNP and SRP (this is the bmAttributes field of OTG Decriptor)
+ /// -> B-Device side : indicates if the A-Device has enabled the "a_hnp_support" and "b_hnp_enable" features
+ volatile U8 otg_features_supported;
+
+ /// Public : (U8) otg_user_request;
+ /// Store the last request of the user (see usb_device_task.h)
+ U8 otg_user_request;
+
+ /// Public : (U16) otg_msg_event_delay;
+ /// Contains the current display duration of the OTG event message
+ U16 otg_msg_event_delay;
+
+ /// Public : (U16) otg_msg_failure_delay;
+ /// Contains the current display duration of the OTG failure message
+ U16 otg_msg_failure_delay;
+
+ /// Public : (U16) g_otg_event;
+ /// Contains several bits corresponding to differents OTG events (similar to g_usb_event)
+ volatile U16 g_otg_event;
+
+ /// Public : (U8) otg_device_nb_hnp_retry;
+ /// Counts the number of times a HNP fails, before aborting the operations
+ U8 otg_device_nb_hnp_retry;
+
+ U8 id_changed_to_host_event;
+
+ volatile U8 otg_last_sof_received; // last SOF received in SOF interrupt
+ volatile U8 otg_last_sof_stored; // last SOF value stored in OTG Timer interrupt
+ volatile U8 reset_received; // indicates if a reset has been received from B-Host after a HNP (used in A-Periph mode)
+
+ /// @brief VBUS Overload management
+ ///
+ /// Nothing to do ! If the condition is not defined in the board driver file
+ /// (i.e. if the board does not support Vbus overcurrent detection),
+ /// the macro is defined to false for firmware compatibility
+#define Is_vbus_overcurrent() (FALSE)
+
+ /// Private function prototypes
+ /// Tasks for OTG Messaging features
+ void Otg_message_task_init(void);
+ void Otg_message_task(void);
+#endif
+
+
+//------------------------------------------------------------------------------
+// Local Variables
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the USB process
+/// Depending on the mode supported (HOST/DEVICE/DUAL_ROLE) the function calls
+/// the coresponding USB mode initialization function
+//------------------------------------------------------------------------------
+void usb_task_init(void)
+{
+
+// ---- DUAL ROLE DEVICE USB MODE ---------------------------------------------
+#if (USB_OTG_FEATURE == ENABLE)
+ Otg_message_task_init(); // OTG program needs to display event messages to the user
+ b_uut_device_state = B_IDLE; // init state machines variables
+#if (USB_HOST_FEATURE == ENABLE)
+ device_state = DEVICE_UNATTACHED;
+#endif
+ otg_device_nb_hnp_retry = BDEV_HNP_NB_RETRY;
+ Clear_all_user_request();
+#endif
+
+#if (((USB_DEVICE_FEATURE == ENABLE) && (USB_HOST_FEATURE == ENABLE)) || (USB_OTG_FEATURE == ENABLE))
+#if (USB_OTG_FEATURE == ENABLE)
+ Usb_enable_uid_pin();
+#endif
+
+ // delay=PORTA;
+ g_usb_mode=USB_MODE_UNDEFINED;
+
+ if(Is_usb_id_device())
+ {
+ g_usb_mode=USB_MODE_DEVICE;
+ //usb_device_task_init();
+ MSDDriver_Initialize(luns, numMedias);
+
+#if (USB_OTG_FEATURE == ENABLE)
+ id_changed_to_host_event = DISABLE;
+#endif
+ }
+ else
+ {
+ Usb_send_event(EVT_USB_HOST_FUNCTION);
+ g_usb_mode=USB_MODE_HOST;
+ Usb_ack_id_transition(); // REQUIRED !!! Startup with ID=0, Ack ID pin transistion (default hwd start up is device mode)
+ Usb_enable_id_interrupt();
+ usb_host_task_init();
+#if (USB_OTG_FEATURE == ENABLE)
+ id_changed_to_host_event = ENABLE;
+#endif
+ }
+#if ((USB_DEVICE_FEATURE == ENABLE)&& (USB_HOST_FEATURE == ENABLE))
+ g_old_usb_mode = g_usb_mode; // Store current usb mode, for mode change detection
+#endif
+ // -------------------------------------------------------------------------
+
+ // ---- DEVICE ONLY USB MODE -----------------------------------------------
+#elif ((USB_DEVICE_FEATURE == ENABLE)&& (USB_HOST_FEATURE == DISABLE))
+ //jcbUsb_force_device_mode();
+ //usb_device_task_init();
+ MSDDriver_Initialize(luns, numMedias);
+ // -------------------------------------------------------------------------
+
+ // ---- REDUCED HOST ONLY USB MODE -----------------------------------------
+#elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLE))
+ //jcbUsb_force_host_mode();
+ usb_host_task_init();
+#elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE))
+#error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled
+#endif
+ // -------------------------------------------------------------------------
+
+}
+
+
+//------------------------------------------------------------------------------
+/// Entry point of the USB mamnagement
+/// Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function
+/// calls the coresponding USB management function
+//------------------------------------------------------------------------------
+void usb_task(void)
+{
+ // ---- DUAL ROLE DEVICE USB MODE ---------------------------------------------
+#if ((USB_DEVICE_FEATURE == ENABLE) && (USB_HOST_FEATURE == ENABLE))
+ if(Is_usb_id_device()) {
+ g_usb_mode = USB_MODE_DEVICE;
+ }
+ else {
+ g_usb_mode = USB_MODE_HOST;
+ }
+ g_old_usb_mode = g_usb_mode; // Store current usb mode, for mode change detection
+ // Depending on current usb mode, launch the correct usb task (device or host)
+
+#if (USB_OTG_FEATURE == ENABLE)
+ // Configure OTG timers
+ Set_otg_custom_timer(VBUSRISE_70MS);
+ Set_otg_custom_timer(VBUSPULSE_40MS);
+ Set_otg_custom_timer(VFALLTMOUT_131MS);
+ Set_otg_custom_timer(SRPMINDET_100US);
+#endif
+
+ switch(g_usb_mode) {
+ case USB_MODE_DEVICE:
+ //usb_device_task();
+ MSDDriver_StateMachine();
+ break;
+
+ case USB_MODE_HOST:
+ if( pOTGDescriptor.bOTGADevSRPReaction == VBUS_PULSE) {
+ Usb_select_vbus_srp_method();
+ }
+ else {
+ Usb_select_data_srp_method();
+ }
+ usb_host_task();
+ // Handle Vbus overcurrent error (auto-disabled if not supported or not defined in board driver file)
+#if (USB_OTG_FEATURE == ENABLE)
+ if (Is_vbus_overcurrent()) {
+ Otg_print_new_event_message(OTGMSG_VBUS_SURCHARGE,OTG_TEMPO_3SEC);
+ }
+#endif
+ break;
+
+ case USB_MODE_UNDEFINED: // No break !
+ default:
+ break;
+ }
+ // -------------------------------------------------------------------------
+ // ---- DEVICE ONLY USB MODE -----------------------------------------------
+#elif ((USB_DEVICE_FEATURE == ENABLE)&& (USB_HOST_FEATURE == DISABLE))
+ //usb_device_task();
+ MSDDriver_StateMachine();
+ // -------------------------------------------------------------------------
+
+ // ---- REDUCED HOST ONLY USB MODE -----------------------------------------
+#elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLE))
+ usb_host_task();
+ // -------------------------------------------------------------------------
+
+ /// ---- ERROR, NO MODE ENABLE ---------------------------------------------
+#elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE))
+#error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled
+#error otherwise the usb task has nothing to do ...
+#endif
+ // -------------------------------------------------------------------------
+
+#if (USB_OTG_FEATURE == ENABLE)
+ Otg_message_task();
+#endif
+}
+
+
+
+//------------------------------------------------------------------------------
+/// USB interrupt subroutine
+///
+/// This function is called each time a USB interrupt occurs.
+/// The following USB DEVICE events are taken in charge:
+/// - VBus On / Off
+/// - Start Of Frame
+/// - Suspend
+/// - Wake-Up
+/// - Resume
+/// - Reset
+/// - Start of frame
+///
+/// The following USB HOST events are taken in charge:
+/// - Device connection
+/// - Device Disconnection
+/// - Start Of Frame
+/// - ID pin change
+/// - SOF (or Keep alive in low speed) sent
+/// - Wake up on USB line detected
+///
+/// The following USB HOST events are taken in charge:
+/// - HNP success (Role Exchange)
+/// - HNP failure (HNP Error)
+///
+/// For each event, the user can launch an action by completing
+/// the associate define (See conf_usb.h file to add action upon events)
+///
+/// Note: Only interrupts events that are enabled are processed
+//------------------------------------------------------------------------------
+void usb_general_interrupt(void)
+{
+ U8 i;
+ U8 save_pipe_nb;
+
+ // ---------- DEVICE events management -----------------------------------
+ // -----------------------------------------------------------------------
+#if ((USB_DEVICE_FEATURE == ENABLE) || (USB_OTG_FEATURE == ENABLE))
+
+ //- VBUS state detection
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()
+ && Is_usb_id_device()) {
+ Usb_ack_vbus_transition();
+
+ if (Is_usb_vbus_high()) {
+ usb_connected = TRUE;
+ Usb_vbus_on_action();
+ Usb_send_event(EVT_USB_POWERED);
+ //jcb Usb_enable_reset_interrupt();
+ //usb_start_device();
+ USBD_Connect();//Usb_attach();
+ }
+ else {
+ TRACE_DEBUG("VBUS low\n\r");
+ USBD_Disconnect();
+#if (USB_OTG_FEATURE == ENABLE)
+ Usb_device_stop_hnp();
+ TRACE_DEBUG("Usb_select_device4\n\r");
+ Usb_select_device();
+ Clear_all_user_request();
+#endif
+ Usb_vbus_off_action();
+ usb_connected = FALSE;
+ usb_configuration_nb = 0;
+ Usb_send_event(EVT_USB_UNPOWERED);
+ }
+
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Device start of frame received
+ if (Is_usb_sof() && Is_sof_interrupt_enabled()) {
+ // TRACE_DEBUG_WP("F"); // device
+ Usb_ack_sof();
+ Usb_sof_action();
+#if (USB_OTG_FEATURE == ENABLE)
+ //sof_seen_in_session = TRUE;
+ otg_last_sof_received = UDFNUML; // store last frame number received
+#endif
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Device Suspend event (no more USB activity detected)
+ if (Is_usb_suspend()) { //&& Is_suspend_interrupt_enabled()) {
+ //TRACE_DEBUG_WP("D\n\r");
+#if (USB_OTG_FEATURE == ENABLE)
+ // 1st : B-PERIPH mode ?
+ if (Is_usb_id_device()) {
+ // HNP Handler
+ TRACE_DEBUG("HNP Handler\n\r");
+ //TRACE_DEBUG("device_state = %d\n\r", device_state);
+ //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
+ if (Is_host_requested_hnp() // "b_hnp_enable" feature received
+ && (Is_session_started_with_srp() || Is_user_requested_hnp() {
+ if (otg_device_nb_hnp_retry == 0) {
+ otg_features_supported &= ~USBFeatureRequest_OTG_B_HNP_ENABLE;
+ }
+ else {
+ Ack_user_request_hnp();
+ Usb_ack_hnp_error_interrupt();
+ Usb_ack_role_exchange_interrupt();
+ Usb_enable_role_exchange_interrupt();
+ Usb_enable_hnp_error_interrupt();
+ Usb_device_initiate_hnp();
+ otg_device_nb_hnp_retry--;
+ }
+ }
+ else
+ {
+ // Remote wake-up handler
+ //TRACE_DEBUG("Remote wake-up handler\n\r");
+ //TRACE_DEBUG("device_state = %d\n\r", device_state);
+ //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
+ if ((remote_wakeup_feature == ENABLE) && (usb_configuration_nb != 0))
+ {
+ //TRACE_DEBUG("enabled\n\r");
+ // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up
+ // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume
+ // So the SUSPE enable bit must be cleared to avoid redundant interrupt
+ // ****************
+ // Please note also that is Vbus is lost during an upstream resume (Host disconnection),
+ // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent)
+ // remains set after the event, so that a good way to handle this feature is :
+ // Usb_initiate_remote_wake_up();
+ // while (Is_usb_pending_remote_wake_up())
+ // {
+ // if (Is_usb_vbus_low())
+ // {
+ // // Emergency action (reset macro, etc.) if Vbus lost during resuming
+ // break;
+ // }
+ // }
+ // Usb_ack_remote_wake_up_start();
+ // ****************
+ }
+ else {
+ //TRACE_DEBUG("disabled: %d %d\n\r", usb_configuration_nb, remote_wakeup_feature);
+ // No remote wake-up supported
+ Usb_send_event(EVT_USB_SUSPEND);
+ }
+ }
+ }
+ else
+ {
+ //TRACE_DEBUG("ici\n\r");
+ // A-PERIPH mode (will cause a session end, handled in usb_host_task.c)
+ Usb_send_event(EVT_USB_SUSPEND);
+ Usb_suspend_action();
+ //jcb Usb_ack_suspend();
+ }
+#else
+ // Remote wake-up handler
+ if ((remote_wakeup_feature == ENABLE) && (usb_configuration_nb != 0)) {
+ TRACE_DEBUG("Remote wake-up handler\n\r");
+ Usb_disable_suspend_interrupt();
+ Usb_ack_wake_up();
+ Usb_enable_wake_up_interrupt();
+ Usb_suspend_action();
+ Usb_freeze_clock();
+ // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up
+ // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume
+ // So the SUSPE enable bit must be cleared to avoid redundant interrupt
+ // ****************
+ // Please note also that is Vbus is lost during an upstream resume (Host disconnection),
+ // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent)
+ // remains set after the event, so that a good way to handle this feature is :
+ // Usb_unfreeze_clock();
+ // Usb_initiate_remote_wake_up();
+ // while (Is_usb_pending_remote_wake_up())
+ // {
+ // if (Is_usb_vbus_low())
+ // {
+ // // Emergency action (reset macro, etc.) if Vbus lost during resuming
+ // break;
+ // }
+ // }
+ // Usb_ack_remote_wake_up_start();
+ // ****************
+ }
+ else {
+ // No remote wake-up supported
+ Usb_send_event(EVT_USB_SUSPEND);
+ Usb_suspend_action();
+ Usb_ack_suspend();
+ Usb_ack_wake_up(); // clear wake up to detect next event
+ Usb_enable_wake_up_interrupt();
+ Usb_freeze_clock();
+ }
+#endif
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Wake up event (USB activity detected): Used to resume
+ if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled()) {
+ TRACE_DEBUG("W\n\r");
+ Usb_unfreeze_clock();
+ Usb_send_event(EVT_USB_WAKE_UP);
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Resume state bus detection
+ if (Is_usb_resume() && Is_resume_interrupt_enabled()) {
+ TRACE_DEBUG("Resume state bus detect\n\r");
+ Usb_send_event(EVT_USB_RESUME);
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - USB bus reset detection
+ if (Is_usb_reset()&& Is_reset_interrupt_enabled()) {
+ TRACE_DEBUG_WP("B\n\r");
+#if (USB_OTG_FEATURE == ENABLE)
+ if (Is_usb_id_host()) {
+ //TRACE_DEBUG_WP("id_host\n\r");
+ dev_configure_endpoint(EP_CONTROL,
+ TYPE_CONTROL,
+ DIRECTION_OUT,
+ SIZE_64,
+ ONE_BANK,
+ NYET_DISABLED);
+ }
+ // First initialization is important to be synchronized
+ // A reset must first have been received
+ if (device_state == A_PERIPHERAL) {
+ //TRACE_DEBUG_WP("r A_PERIPHERAL\n\r");
+ otg_last_sof_received = UDFNUML;
+ otg_last_sof_stored = UDFNUML;
+ Usb_ack_sof();
+ Usb_enable_sof_interrupt();
+ reset_received = TRUE;
+ Timer16_set_counter(0);
+ }
+#endif
+ Usb_reset_action();
+ Usb_send_event(EVT_USB_RESET);
+ }
+
+ // ---------- OTG events management ------------------------------------
+ // ---------------------------------------------------------------------
+#if (USB_OTG_FEATURE == ENABLE) && (USB_HOST_FEATURE == ENABLE)
+
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ // - OTG HNP Success detection
+ if (Is_usb_role_exchange_interrupt() && Is_role_exchange_interrupt_enabled()) {
+ // TRACE_DEBUG("OTG HNP detect\n\r");
+ Usb_ack_role_exchange_interrupt();
+ Host_ack_device_connection();
+ Host_ack_device_disconnection();
+ Otg_send_event(EVT_OTG_HNP_SUCCESS);
+ End_session_with_srp();
+ Clear_otg_features_from_host();
+ if (Is_usb_id_host()) {
+ // HOST (A- or B-) mode
+ if ((device_state != A_PERIPHERAL) && (device_state != A_END_HNP_WAIT_VFALL)) {
+ static volatile unsigned int jcb;
+ // Current mode is A-HOST, device will take the A-PERIPHERAL role
+ b_uut_device_state = B_PERIPHERAL;
+ device_state = A_PERIPHERAL;
+ usb_connected = FALSE;
+ usb_configuration_nb = 0;
+ Usb_select_device();
+ USBD_Connect();//Usb_attach();
+ Usb_unfreeze_clock();
+ Usb_disable_role_exchange_interrupt();
+ Usb_disable_hnp_error_interrupt();
+ Usb_device_stop_hnp();
+ Usb_ack_reset();
+ Timer16_set_counter(0);
+ Usb_freeze_clock(); // USB clock can be freezed to slow down events and condition detection
+ //jcb while (Timer16_get_counter_low() != 20);
+ jcb=0;
+ while( jcb <100000){ jcb++; }
+
+ Usb_unfreeze_clock();
+ reset_received = FALSE;
+ Usb_disable_sof_interrupt(); // will be set in the next OTG Timer IT (mandatory)
+
+ Usb_enable_suspend_interrupt();
+ Usb_enable_reset_interrupt();
+ dev_configure_endpoint(EP_CONTROL,
+ TYPE_CONTROL,
+ DIRECTION_OUT,
+ SIZE_64,
+ ONE_BANK,
+ NYET_DISABLED);
+ }
+ }
+ else {
+ // In B_HOST mode, the HNPREQ bit must not be cleared because it releases the bus in suspend mode (and sof can't start)
+ if ((b_uut_device_state != B_HOST) && (b_uut_device_state != B_END_HNP_SUSPEND)) {
+ static volatile unsigned int jcb2;
+ // Current mode is B-PERIPHERAL, device will go into B-HOST role
+ End_session_with_srp();
+ Clear_otg_features_from_host();
+ b_uut_device_state = B_HOST;
+ device_state = DEVICE_ATTACHED;
+ usb_connected = FALSE;
+ usb_configuration_nb = 0;
+ TRACE_DEBUG("Select host 3\n\r");
+ Usb_select_host();
+
+ TRACE_DEBUG("Send reset\n\r");
+ Host_send_reset(); // send the first RESET
+ while (Host_is_reset());
+ TRACE_DEBUG("Reset passed\n\r");
+
+ jcb2=0;
+ while( jcb2 <1000000){ jcb2++; }
+ Host_enable_sof(); // start Host (sof)
+ Usb_disable_role_exchange_interrupt();
+ Usb_disable_hnp_error_interrupt();
+ Clear_all_user_request();
+
+ TRACE_DEBUG("Select host 3\n\r");
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ // - OTG HNP Failure detection
+ if (Is_usb_hnp() && Is_usb_hnp_error_interrupt()&& Is_hnp_error_interrupt_enabled()) {
+ TRACE_DEBUG("OTG HNP failure\n\r");
+ Usb_device_stop_hnp();
+ Usb_disable_role_exchange_interrupt();
+ Usb_disable_hnp_error_interrupt();
+ Usb_ack_hnp_error_interrupt();
+ if (Is_usb_id_device()) {
+ Otg_send_event(EVT_OTG_HNP_ERROR);
+ Clear_all_user_request();
+ }
+ }
+#endif
+#endif// End DEVICE FEATURE MODE && USB_HOST_FEATURE
+
+ // ---------- HOST events management -----------------------------------
+ // ---------------------------------------------------------------------
+#if (((USB_HOST_FEATURE == ENABLE) && (USB_DEVICE_FEATURE == ENABLE)) || (USB_OTG_FEATURE == ENABLE))
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ // - ID pin change detection
+ if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled()) {
+ TRACE_DEBUG("ID pin change\n\r");
+ TRACE_DEBUG("device_state = %d\n\r", device_state);
+ TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
+ Usb_device_stop_hnp();
+#if (USB_OTG_FEATURE == ENABLE)
+ Clear_all_user_request();
+#endif
+ if(Is_usb_id_device()) {
+ g_usb_mode = USB_MODE_DEVICE;
+ }
+ else {
+ g_usb_mode = USB_MODE_HOST;
+ }
+ Usb_ack_id_transition();
+ if( g_usb_mode != g_old_usb_mode) { // Basic Debounce
+ if(Is_usb_id_device()) { // Going into device mode
+ Usb_send_event(EVT_USB_DEVICE_FUNCTION);
+#if (USB_OTG_FEATURE == ENABLE)
+ b_uut_device_state = B_IDLE;
+#endif
+ device_state = DEVICE_UNATTACHED;
+#if (USB_OTG_FEATURE == ENABLE)
+ id_changed_to_host_event = DISABLE;
+#endif
+ }
+ else { // Going into host mode
+#if (USB_OTG_FEATURE == ENABLE)
+ b_uut_device_state = B_IDLE;
+#endif
+ device_state = DEVICE_UNATTACHED;
+ Usb_send_event(EVT_USB_HOST_FUNCTION);
+#if (USB_OTG_FEATURE == ENABLE)
+ id_changed_to_host_event = ENABLE;
+#endif
+ }
+ Usb_id_transition_action();
+ TRACE_INFO("Pin Id changed\n\r");
+#if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE)
+ // Hot ID transition generates wdt reset
+#endif
+ }
+ }
+
+#endif
+#if ((USB_HOST_FEATURE == ENABLE) || (USB_OTG_FEATURE == ENABLE))
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - The device has been disconnected
+ // JCB to be fix
+ if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) {
+ TRACE_DEBUG("device disconnect\n\r");
+ host_disable_all_pipe();
+ Host_ack_device_disconnection();
+ device_state=DEVICE_DISCONNECTED;
+ Usb_send_event(EVT_HOST_DISCONNECTION);
+ TRACE_INFO("Device disconnected\n\r");
+ Host_device_disconnection_action();
+#if (USB_OTG_FEATURE == ENABLE)
+ Clear_all_user_request();
+#endif
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Device connection
+ if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) {
+ TRACE_DEBUG("device connect\n\r");
+ Host_ack_device_connection();
+ host_disable_all_pipe();
+ Host_device_connection_action();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Host Start of frame has been sent
+ if (Is_host_sof() && Is_host_sof_interrupt_enabled()) {
+ //TRACE_DEBUG_WP("_"); // host
+ Host_ack_sof();
+ Usb_send_event(EVT_HOST_SOF);
+ private_sof_counter++;
+
+ // delay timeout management for interrupt tranfer mode in host mode
+ if (private_sof_counter>=250) { // Count 1/4 sec
+ private_sof_counter=0;
+ for(i=0;i<MAX_EP_NB;i++) {
+ if(it_pipe_str[i].enable==ENABLE) {
+ save_pipe_nb=Host_get_selected_pipe();
+ Host_select_pipe(i);
+ if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) {
+ it_pipe_str[i].enable=DISABLE;
+ it_pipe_str[i].status=PIPE_DELAY_TIMEOUT;
+ Host_stop_pipe_interrupt(i);
+ if (is_any_interrupt_pipe_active()==FALSE) { // If no more transfer is armed
+ if (g_sav_int_sof_enable==FALSE) {
+ Host_disable_sof_interrupt();
+ }
+ }
+ it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed);
+ }
+ Host_select_pipe(save_pipe_nb);
+ }
+ }
+ }
+ Host_sof_action();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Host Wake-up has been received
+ if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) {
+ TRACE_DEBUG("Host wake up\n\r");
+ Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up !
+ Host_disable_remote_wakeup_interrupt();
+ // CAUTION HWUP can be cleared only when USB clock is active (not frozen)!
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ Host_enable_sof(); // start sending SOF
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Host_ack_remote_wakeup();
+ Usb_send_event(EVT_HOST_HWUP); // Send software event
+ Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
+ Host_hwup_action(); // Map custom action
+#if (USB_OTG_FEATURE == ENABLE)
+ if (Is_usb_hnp()) {
+ Usb_host_reject_hnp();
+ Usb_disable_hnp_error_interrupt();
+ Usb_disable_role_exchange_interrupt();
+ }
+#endif
+ Host_send_resume();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // Remote Wake Up has been received
+ if (Is_host_remote_wakeup_interrupt_enabled() && Is_host_remote_wakeup()) {
+ TRACE_DEBUG("Remote wake up\n\r");
+ Host_disable_remote_wakeup_interrupt();
+ Host_disable_hwup_interrupt();
+ Host_ack_remote_wakeup();
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ Host_enable_sof(); // start sending SOF
+ Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
+ Usb_send_event(EVT_HOST_HWUP); // Send software event
+#if (USB_OTG_FEATURE == ENABLE)
+ if (Is_usb_hnp()) {
+ Usb_host_reject_hnp();
+ Usb_disable_hnp_error_interrupt();
+ Usb_disable_role_exchange_interrupt();
+ }
+#endif
+ Host_send_resume();
+ }
+#endif // End HOST FEATURE MODE
+}
+
+
+#if (USB_OTG_FEATURE == ENABLE)
+
+//------------------------------------------------------------------------------
+/// OTG TIMER interrupt subroutine
+/// This function is called each time a OTG Timer interrupt occurs
+/// Function decrements the variables required by OTG program
+void otg_timer_interrupt(void)
+{
+ /// OTG Messaging timer
+ if( (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL)
+ || (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_FAIL)) {
+ if ((Get_failure_msg_delay() != 0x0000) && (Get_failure_msg_delay() != 0xFFFF)) {
+ Decrement_failure_msg_delay();
+ }
+ if( (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL) {
+ if ((Get_event_msg_delay() != 0x0000) && (Get_event_msg_delay() != 0xFFFF)) {
+ Decrement_event_msg_delay();
+ }
+ }
+ }
+ /// Increments Tb_Srp counter if needed
+ if (Is_srp_sent_and_waiting_answer()) {
+ otg_tb_srp_cpt++;
+ }
+ /// Increments T_vbus_wait_connect if needed
+ if (Is_srp_received_and_waiting_connect()) {
+ otg_ta_srp_wait_connect++;
+ }
+ /// Decrements Ta_aidl_bdis timer if needed (A_suspend state)
+ if ((device_state == A_SUSPEND) && (otg_ta_aidl_bdis_tmr > 1)) {
+ otg_ta_aidl_bdis_tmr--;
+ }
+ /// Decrements Timeout_bdev_respond timer if needed
+ if ((device_state == DEVICE_DEFAULT) && (!Is_timeout_bdev_response_overflow())) {
+ otg_timeout_bdev_respond--;
+ }
+ /// Decrements Ta_vbus_rise timer if needed
+ if (!Is_ta_vbus_rise_counter_overflow()) {
+ otg_ta_vbus_rise--;
+ }
+ /// Decrements Ta_vbus_fall timer if needed
+ if (!Is_ta_vbus_fall_counter_overflow()) {
+ otg_end_hnp_vbus_delay--;
+ }
+
+ /// Needed for compliance only
+ if (device_state == A_PERIPHERAL) {
+ if (Is_sof_interrupt_enabled() && (reset_received == TRUE)) {
+ if (otg_last_sof_stored != otg_last_sof_received) {
+ // No SOF is missing
+ otg_last_sof_received = otg_last_sof_stored;
+ }
+ else {
+ // SOF seems to be missing..
+ Usb_freeze_clock();
+ Usb_disable_sof_interrupt();
+ reset_received = FALSE;
+ //jcb while (Timer16_get_counter_low() != 20); // overflow set to 62 in usb_task.h
+ Usb_unfreeze_clock();
+ }
+ otg_last_sof_received = UDFNUML;
+ otg_last_sof_stored = UDFNUML;
+ }
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// OTG Messaging task initialization
+/// Initializes variables and screen to prepare next messages to be handled
+//------------------------------------------------------------------------------
+void Otg_message_task_init(void)
+{
+ TRACE_DEBUG("Otg_message_task_init\n\r");
+ Otg_messaging_init();
+ otg_msg_event_delay = 0;
+ otg_msg_failure_delay = 0;
+}
+
+
+//------------------------------------------------------------------------------
+/// OTG Messaging main task
+/// OTG specifies that user must be kept informed of several events
+/// This task allows user to display two kinds of messages : EVENT or FAILURE
+/// For each new message, it can specify if the message remains displayed all
+/// the time or only during a specified delay
+//------------------------------------------------------------------------------
+void Otg_message_task(void)
+{
+ // Check if an OTG message must be erased (if it was set up for a specified delay)
+ if( (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL)
+ || (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_FAIL)) {
+ if (Get_failure_msg_delay() == 0) {
+ Otg_clear_failure_message();
+ }
+ if( (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL) {
+ if (Get_event_msg_delay() == 0) {
+ Otg_clear_event_message();
+ }
+ }
+ }
+}
+#endif // #if (USB_OTG_FEATURE == ENABLE)
+
+
+//------------------------------------------------------------------------------
+/// Message "OTG not supported"
+//------------------------------------------------------------------------------
+void otg_not_supported_device(void)
+{
+ TRACE_DEBUG("otg_not_supported_device\n\r");
+ Otg_send_event(EVT_OTG_DEV_UNSUPPORTED);
+}
+
+
diff --git a/usb/otg/usb_task.h b/usb/otg/usb_task.h new file mode 100644 index 0000000..0ad2529 --- /dev/null +++ b/usb/otg/usb_task.h @@ -0,0 +1,232 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+
+//! @brief This file manages the USB task either device/host or both.
+//!
+//! The USB task selects the correct USB task (usb_device task or usb_host task
+//! to be executed depending on the current mode available.
+//!
+//! This module also contains the general USB interrupt subroutine. This subroutine is used
+//! to detect asynchronous USB events.
+//!
+//! Note:
+//! - The usb_task belongs to the scheduler, the usb_device_task and usb_host do not, they are called
+//! from the general usb_task
+//! - See conf_usb.h file for more details about the configuration of this module
+
+#ifndef _USB_TASK_H_
+#define _USB_TASK_H_
+
+#include <otg_user_task.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Definitions of B-Device states
+#define B_IDLE 0
+//#define B_SRP_INIT 1
+#define B_PERIPHERAL 2
+//#define B_WAIT_ACON 3
+#define B_HOST 4
+#define B_END_HNP_SUSPEND 5
+
+// OTG B-Device SRP protocole specific states or events
+
+//! Is the current session a result of a SRP ?
+//#define Start_session_with_srp() (otg_device_sessions |= 0x01)
+#define End_session_with_srp() (otg_device_sessions &= ~0x01)
+#define Is_session_started_with_srp() (((otg_device_sessions&0x01) != 0) ? TRUE : FALSE)
+
+//! Has a SRP been sent, and waiting for an answer
+//#define Srp_sent_and_waiting_answer() (otg_device_sessions |= 0x02)
+//#define Ack_srp_sent_and_answer() (otg_device_sessions &= ~0x02)
+#define Is_srp_sent_and_waiting_answer() (((otg_device_sessions&0x02) != 0) ? TRUE : FALSE)
+
+//! Is the Tb_Srp counter enabled ? Cleared by timer if Tb_Srp_Fail elapsed
+//! Tb_Srp_Fail must be between 5 and 6 sec. With an interrupt routine executed each 2ms, its value becomes 2500 (used:5.2sec)
+// 0x0A28 = 2600, 2600x2 = 5200 => 5s
+//#define TB_SRP_FAIL_MIN 0x0A28
+//extern U16 otg_tb_srp_cpt;
+//#define Init_tb_srp_counter() (otg_tb_srp_cpt = 0)
+//#define Is_tb_srp_counter_overflow() ((otg_tb_srp_cpt > TB_SRP_FAIL_MIN) ? TRUE : FALSE)
+
+// usb_task USB task entry point module
+
+//! usb_software_evts USB software Events Management
+//! Macros to manage USB events detected under interrupt
+#define Usb_send_event(x) g_usb_event |= (1<<x)
+#define Usb_ack_event(x) g_usb_event &= ~(1<<x)
+#define Usb_clear_all_event() g_usb_event = 0
+#define Is_usb_event(x) ((g_usb_event & (1<<x)) ? TRUE : FALSE)
+#define Is_not_usb_event(x) ((g_usb_event & (1<<x)) ? FALSE: TRUE)
+
+#define Is_host_emergency_exit() (Is_usb_event(EVT_HOST_DISCONNECTION) || Is_usb_event(EVT_USB_DEVICE_FUNCTION))
+//#define Is_usb_device() ((g_usb_mode==USB_MODE_DEVICE) ? TRUE : FALSE)
+//#define Is_usb_host() ((g_usb_mode==USB_MODE_HOST) ? TRUE : FALSE)
+
+#define Otg_send_event(x) g_otg_event |= (1<<x)
+//#define Otg_ack_event(x) g_otg_event &= ~(1<<x)
+//#define Otg_clear_all_event() g_otg_event = 0
+//#define Is_otg_event(x) ((g_otg_event & (1<<x)) ? TRUE : FALSE)
+//#define Is_not_otg_event(x) ((g_otg_event & (1<<x)) ? FALSE: TRUE)
+
+#define EVT_USB_POWERED 1 // USB plugged
+#define EVT_USB_UNPOWERED 2 // USB un-plugged
+#define EVT_USB_DEVICE_FUNCTION 3 // USB in device
+#define EVT_USB_HOST_FUNCTION 4 // USB in host
+#define EVT_USB_SUSPEND 5 // USB suspend
+#define EVT_USB_WAKE_UP 6 // USB wake up
+#define EVT_USB_RESUME 7 // USB resume
+#define EVT_USB_RESET 8 // USB reset
+#define EVT_HOST_SOF 9 // Host start of frame sent
+#define EVT_HOST_HWUP 10 // Host wakeup detected
+#define EVT_HOST_DISCONNECTION 11 // The target device is disconnected
+#define EVT_HOST_REMOTE_WAKEUP 12 // Remote WakeUp has been received (Host)
+
+
+#define EVT_OTG_HNP_ERROR 1 // The HNP has failed (A has not responded)
+#define EVT_OTG_HNP_SUCCESS 2 // The HNP has succedeed
+//#define EVT_OTG_SRP_RECEIVED 3 // A-Device received a SRP
+#define EVT_OTG_DEV_UNSUPPORTED 4 // An error occured while the device was enumerated
+//#define EVT_OTG_DEVICE_CONNECTED 5 // B-Device has been configured
+
+
+
+#define BDEV_HNP_NB_RETRY 3 // number of times that a B-Device retries a HNP with a failure as a result
+ // after "n" failures, the "b_hnp_enable" feature is cancelled
+
+//!
+//! @brief Definitions of OTG user requests (user software requests)
+//!
+#define USER_RQST_SRP 0x01
+#define USER_RQST_SUSPEND 0x02
+#define USER_RQST_VBUS 0x04 // Vbus TOGGLE
+#define USER_RQST_HNP 0x08
+//#define USER_RQST_RESUME 0x10
+//#define USER_RQST_RESET 0x20
+#define USER_RQST_DISCONNECT 0x40
+
+// Ask for the B-PERIPH to generate a SRP
+//#define Is_user_requested_srp() (((otg_user_request&USER_RQST_SRP) != 0) ? TRUE : FALSE)
+#define Set_user_request_srp() otg_user_request |= USER_RQST_SRP
+//#define Ack_user_request_srp() otg_user_request &= ~USER_RQST_SRP
+
+// Ask for the A-HOST to enter suspend
+#define Is_user_requested_suspend() (((otg_user_request&USER_RQST_SUSPEND) != 0) ? TRUE : FALSE)
+#define Set_user_request_suspend() otg_user_request |= USER_RQST_SUSPEND
+#define Ack_user_request_suspend() otg_user_request &= ~USER_RQST_SUSPEND
+
+// Ask for the A-HOST to toggle Vbus
+#define Is_user_requested_vbus() (((otg_user_request&USER_RQST_VBUS) != 0) ? TRUE : FALSE)
+#define Set_user_request_vbus() otg_user_request |= USER_RQST_VBUS
+#define Ack_user_request_vbus() otg_user_request &= ~USER_RQST_VBUS
+
+// Ask for an HNP initiation on both devices
+#define Is_user_requested_hnp() (((otg_user_request&USER_RQST_HNP) != 0) ? TRUE : FALSE)
+#define Set_user_request_hnp() otg_user_request |= USER_RQST_HNP
+#define Ack_user_request_hnp() otg_user_request &= ~USER_RQST_HNP
+
+// Ask for the B-PERIPH or the A-PERIPH to disconnect from the bus
+#define Is_user_requested_disc() (((otg_user_request&USER_RQST_DISCONNECT) != 0) ? TRUE : FALSE)
+#define Set_user_request_disc() otg_user_request |= USER_RQST_DISCONNECT
+//#define Ack_user_request_disc() otg_user_request &= ~USER_RQST_DISCONNECT
+
+
+#define Clear_all_user_request() otg_user_request = 0
+
+
+
+//! @brief OTG Messaging definitions
+//! "No Silent Failure" rule makes any OTG compliant device handle messaging functions
+//! Differents means are supported : LCD display, LEDs, etc.
+
+//#define MSG_DISPLAY_NODELAY 0xFFFF
+//#define OTG_TEMPO_1SEC 0x01F4 // 500 (x2ms)
+#define OTG_TEMPO_2SEC 0x03E8 // 1000
+#define OTG_TEMPO_3SEC 0x05DC // 1500
+#define OTG_TEMPO_4SEC 0x07D0 // 2000
+//#define OTR_TEMPO_5SEC 0x09C4 // 2500
+
+// These messages ID numbers must be used with the OTG messaging functions
+//#define OTGMSG_SRP_STARTED 1 // Event
+#define OTGMSG_SRP_A_NO_RESP 2 // FAILURE msg
+//#define OTGMSG_A_RESPONDED 3 // Event
+//#define OTGMSG_CONNECTED_TO_A 4 // Event
+#define OTGMSG_UNSUPPORTED 5 // FAILURE msg
+#define OTGMSG_UNSUPPORTED_HUB 6 // FAILURE msg
+#define OTGMSG_SRP_RECEIVED 7 // Event
+#define OTGMSG_DEVICE_NO_RESP 8 // FAILURE msg
+#define OTGMSG_VBUS_SURCHARGE 9 // Event
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+extern U8 usb_configuration_nb;
+extern U8 otg_device_sessions;
+extern U8 b_uut_device_state;
+extern volatile U8 otg_features_supported;
+extern U8 otg_user_request;
+extern U8 g_usb_mode;
+extern volatile U8 private_sof_counter;
+extern volatile U16 g_usb_event;
+extern U16 otg_msg_event_delay;
+extern U16 otg_msg_failure_delay;
+
+extern void Otg_messaging_init(void);
+extern void Otg_output_failure_msg(U8);
+extern void Otg_output_failure_clear(void);
+//! Otg_print_new_event_message(str,tm) displays the "str" message on the EVENT line during the "tm" delay (x2ms)
+#define Otg_print_new_event_message(str,tm) (Otg_output_event_msg(str), otg_msg_event_delay = tm)
+#define Otg_clear_event_message() Otg_output_event_clear()
+#define Get_event_msg_delay() (otg_msg_event_delay)
+#define Decrement_event_msg_delay() (otg_msg_event_delay--)
+//! Otg_print_new_failure_message(str,tm) displays the "str" message on the FAILURE line during the "tm" delay (x2ms)
+#define Otg_print_new_failure_message(str,tm) (Otg_output_failure_msg(str), otg_msg_failure_delay = tm)
+#define Otg_clear_failure_message() Otg_output_failure_clear()
+#define Get_failure_msg_delay() (otg_msg_failure_delay)
+#define Decrement_failure_msg_delay() (otg_msg_failure_delay--)
+
+
+
+//-----------------------------------------------------------------------------
+// Exported functions
+//-----------------------------------------------------------------------------
+extern void usb_task_init(void);
+extern void usb_task(void);
+extern void usb_general_interrupt(void);
+extern void otg_timer_interrupt(void);
+extern void Otg_message_task_init(void);
+extern void Otg_message_task(void);
+extern void otg_not_supported_device(void);
+
+#endif /* _USB_TASK_H_ */
+
diff --git a/usb/otg/usb_task_host_only.c b/usb/otg/usb_task_host_only.c new file mode 100644 index 0000000..bdeed82 --- /dev/null +++ b/usb/otg/usb_task_host_only.c @@ -0,0 +1,287 @@ +/* ----------------------------------------------------------------------------
+ * 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 <memories/Media.h>
+#include "main.h"
+#include <conf_usb.h>
+#include <utility/trace.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/massstorage/MSDDriver.h>
+#include <usb/device/massstorage/MSDLun.h>
+#include <usb/device/core/USBDCallbacks.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include "otg_user_task.h"
+#include "usb_task.h"
+#include "usb/otg/usb_drv.h"
+#include "usb/otg/usb_host_task.h"
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+
+
+extern volatile unsigned int timer_set_counter;
+#define Timer16_select(...)
+#define Timer16_set_counter(value) timer_set_counter = value
+#define Timer16_get_counter_low() (unsigned char)timer_set_counter
+
+
+/// Returns the OTG features sent by the host by a SetFeature
+/// Allow also to clear the features (only on a bus Reset or Session End)
+#define Is_host_requested_hnp() (((otg_features_supported&USBFeatureRequest_OTG_B_HNP_ENABLE) != 0) ? TRUE : FALSE)
+#define Clear_otg_features_from_host() (otg_features_supported = 0)
+
+#define Set_otg_custom_timer(ep) // STUB: todo
+
+#define USB_MODE_UNDEFINED 0x00
+#define USB_MODE_HOST 0x01
+#define USB_MODE_DEVICE 0x02
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+U8 otg_device_sessions;
+U8 b_uut_device_state;
+U16 otg_tb_srp_cpt;
+
+/// usb_connected is used to store USB events detected upon
+/// USB general interrupt subroutine
+/// Its value is managed by the following macros (See usb_task.h file)
+/// Usb_send_event(x)
+/// Usb_ack_event(x)
+/// Usb_clear_all_event()
+/// Is_usb_event(x)
+/// Is_not_usb_event(x)
+volatile U16 g_usb_event=0;
+
+
+///
+/// Private : (U8) private_sof_counter
+/// Incremented by host SOF interrupt subroutime
+/// This counter is used to detect timeout in host requests.
+/// It must not be modified by the user application tasks.
+////
+volatile U8 private_sof_counter=0;
+extern volatile S_pipe_int it_pipe_str[MAX_EP_NB];
+
+//------------------------------------------------------------------------------
+// Local Variables
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the USB process
+/// Depending on the mode supported (HOST/DEVICE/DUAL_ROLE) the function calls
+/// the coresponding USB mode initialization function
+//------------------------------------------------------------------------------
+void usb_task_init(void)
+{
+ // ---- REDUCED HOST ONLY USB MODE -----------------------------------------
+ //jcbUsb_force_host_mode();
+ usb_host_task_init();
+}
+
+
+//------------------------------------------------------------------------------
+/// Entry point of the USB mamnagement
+/// Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function
+/// calls the coresponding USB management function
+//------------------------------------------------------------------------------
+void usb_task(void)
+{
+ // ---- REDUCED HOST ONLY USB MODE -----------------------------------------
+ usb_host_task();
+}
+
+
+
+//------------------------------------------------------------------------------
+/// USB interrupt subroutine
+///
+/// This function is called each time a USB interrupt occurs.
+/// The following USB DEVICE events are taken in charge:
+/// - VBus On / Off
+/// - Start Of Frame
+/// - Suspend
+/// - Wake-Up
+/// - Resume
+/// - Reset
+/// - Start of frame
+///
+/// The following USB HOST events are taken in charge:
+/// - Device connection
+/// - Device Disconnection
+/// - Start Of Frame
+/// - ID pin change
+/// - SOF (or Keep alive in low speed) sent
+/// - Wake up on USB line detected
+///
+/// The following USB HOST events are taken in charge:
+/// - HNP success (Role Exchange)
+/// - HNP failure (HNP Error)
+///
+/// For each event, the user can launch an action by completing
+/// the associate define (See conf_usb.h file to add action upon events)
+///
+/// Note: Only interrupts events that are enabled are processed
+//------------------------------------------------------------------------------
+void usb_general_interrupt(void)
+{
+ //TRACE_DEBUG("usb_general_interrupt\n\r");
+ U8 i;
+ U8 save_pipe_nb;
+
+ // ---------- HOST events management -----------------------------------
+ // ---------------------------------------------------------------------
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - The device has been disconnected
+ if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) {
+ TRACE_DEBUG("device disconnect\n\r");
+ host_disable_all_pipe();
+ Host_ack_device_disconnection();
+ device_state=DEVICE_DISCONNECTED;
+ Usb_send_event(EVT_HOST_DISCONNECTION);
+ TRACE_INFO("Device disconnected\n\r");
+ Host_device_disconnection_action();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Device connection
+ if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) {
+ TRACE_DEBUG("device connect\n\r");
+ Host_ack_device_connection();
+ host_disable_all_pipe();
+ Host_device_connection_action();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Host Start of frame has been sent
+ if (Is_host_sof() && Is_host_sof_interrupt_enabled()) {
+ //TRACE_DEBUG_WP("_"); // host
+ Host_ack_sof();
+ Usb_send_event(EVT_HOST_SOF);
+ private_sof_counter++;
+
+ // delay timeout management for interrupt tranfer mode in host mode
+#if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
+ if (private_sof_counter>=250) { // Count 1/4 sec
+ private_sof_counter=0;
+ for(i=0;i<MAX_EP_NB;i++) {
+ if(it_pipe_str[i].enable==ENABLE) {
+ save_pipe_nb=Host_get_selected_pipe();
+ Host_select_pipe(i);
+ if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) {
+ it_pipe_str[i].enable=DISABLE;
+ it_pipe_str[i].status=PIPE_DELAY_TIMEOUT;
+ Host_stop_pipe_interrupt(i);
+ if (is_any_interrupt_pipe_active()==FALSE) { // If no more transfer is armed
+ if (g_sav_int_sof_enable==FALSE) {
+ Host_disable_sof_interrupt();
+ }
+ }
+ it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed);
+ }
+ Host_select_pipe(save_pipe_nb);
+ }
+ }
+ }
+#endif // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
+ Host_sof_action();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Host Wake-up has been received
+ if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) {
+ TRACE_DEBUG("Host wake up\n\r");
+ Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up !
+ Host_disable_remote_wakeup_interrupt();
+ // CAUTION HWUP can be cleared only when USB clock is active (not frozen)!
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ Host_enable_sof(); // start sending SOF
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Host_ack_remote_wakeup();
+ Usb_send_event(EVT_HOST_HWUP); // Send software event
+ Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
+ Host_hwup_action(); // Map custom action
+ Host_send_resume();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // Remote Wake Up has been received
+ if (Is_host_remote_wakeup_interrupt_enabled() && Is_host_remote_wakeup()) {
+ TRACE_DEBUG("Remote wake up\n\r");
+ Host_disable_remote_wakeup_interrupt();
+ Host_disable_hwup_interrupt();
+ Host_ack_remote_wakeup();
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ Host_enable_sof(); // start sending SOF
+ Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
+ Usb_send_event(EVT_HOST_HWUP); // Send software event
+ Host_send_resume();
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Message "OTG not supported"
+//------------------------------------------------------------------------------
+void otg_not_supported_device(void)
+{
+ TRACE_DEBUG("otg_not_supported_device\n\r");
+ Otg_send_event(EVT_OTG_DEV_UNSUPPORTED);
+}
+
+
diff --git a/usb/otg/usb_task_with_SRP_HNP.c b/usb/otg/usb_task_with_SRP_HNP.c new file mode 100644 index 0000000..e5204de --- /dev/null +++ b/usb/otg/usb_task_with_SRP_HNP.c @@ -0,0 +1,852 @@ +/* ----------------------------------------------------------------------------
+ * 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 <memories/Media.h>
+#include "main.h"
+#include <conf_usb.h>
+#include <conf_scheduler.h>
+#include <utility/trace.h>
+#include <usb/common/core/USBConfigurationOTG.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/massstorage/MSDDriver.h>
+#include <usb/device/massstorage/MSDLun.h>
+#include <usb/device/core/USBDCallbacks.h>
+#include <usb/common/core/USBFeatureRequest.h>
+#include "otg_user_task.h"
+#include "usb_task.h"
+#include "usb/otg/usb_drv.h"
+#include "usb/otg/usb_host_task.h"
+
+#include <memories/Media.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/massstorage/MSDDriver.h>
+#include <usb/device/massstorage/MSDLun.h>
+#include <usb/device/core/USBDCallbacks.h>
+#include <usb/device/massstorage/MSD.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+
+
+extern volatile unsigned int timer_set_counter;
+#define Timer16_select(...)
+#define Timer16_set_counter(value) timer_set_counter = value
+#define Timer16_get_counter_low() (unsigned char)timer_set_counter
+
+
+/// Returns the OTG features sent by the host by a SetFeature
+/// Allow also to clear the features (only on a bus Reset or Session End)
+#define Is_host_requested_hnp() (((otg_features_supported&USBFeatureRequest_OTG_B_HNP_ENABLE) != 0) ? TRUE : FALSE)
+#define Clear_otg_features_from_host() (otg_features_supported = 0)
+
+#define Set_otg_custom_timer(ep) // STUB: todo
+
+#define USB_MODE_UNDEFINED 0x00
+#define USB_MODE_HOST 0x01
+#define USB_MODE_DEVICE 0x02
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+U8 otg_device_sessions;
+U8 b_uut_device_state;
+U16 otg_tb_srp_cpt;
+
+/// usb_connected is used to store USB events detected upon
+/// USB general interrupt subroutine
+/// Its value is managed by the following macros (See usb_task.h file)
+/// Usb_send_event(x)
+/// Usb_ack_event(x)
+/// Usb_clear_all_event()
+/// Is_usb_event(x)
+/// Is_not_usb_event(x)
+volatile U16 g_usb_event=0;
+
+///
+/// Public : (bit) usb_connected
+/// usb_connected is set to TRUE when VBUS has been detected
+/// usb_connected is set to FALSE otherwise
+bit usb_connected;
+
+///
+/// Public : (U8) usb_configuration_nb
+/// Store the number of the USB configuration used by the USB device
+/// when its value is different from zero, it means the device mode is enumerated
+U8 usb_configuration_nb;
+
+///
+/// Public : (U8) remote_wakeup_feature
+/// Store a host request for remote wake up (set feature received)
+////
+U8 remote_wakeup_feature;
+
+///
+/// Private : (U8) private_sof_counter
+/// Incremented by host SOF interrupt subroutime
+/// This counter is used to detect timeout in host requests.
+/// It must not be modified by the user application tasks.
+////
+volatile U8 private_sof_counter=0;
+
+extern volatile S_pipe_int it_pipe_str[MAX_EP_NB];
+
+
+///
+/// Public : (U8) g_usb_mode
+/// Used in dual role application (both device/host) to store
+/// the current mode the usb controller is operating
+////
+U8 g_usb_mode=USB_MODE_UNDEFINED;
+U8 g_old_usb_mode;
+
+
+///
+/// Public : (U8) otg_features_supported;
+/// -> A-Device side : indicates if the B-Device supports HNP and SRP (this is the bmAttributes field of OTG Decriptor)
+/// -> B-Device side : indicates if the A-Device has enabled the "a_hnp_support" and "b_hnp_enable" features
+volatile U8 otg_features_supported;
+
+/// Public : (U8) otg_user_request;
+/// Store the last request of the user (see usb_device_task.h)
+U8 otg_user_request;
+
+/// Public : (U16) otg_msg_event_delay;
+/// Contains the current display duration of the OTG event message
+U16 otg_msg_event_delay;
+
+/// Public : (U16) otg_msg_failure_delay;
+/// Contains the current display duration of the OTG failure message
+U16 otg_msg_failure_delay;
+
+/// Public : (U16) g_otg_event;
+/// Contains several bits corresponding to differents OTG events (similar to g_usb_event)
+volatile U16 g_otg_event;
+
+/// Public : (U8) otg_device_nb_hnp_retry;
+/// Counts the number of times a HNP fails, before aborting the operations
+U8 otg_device_nb_hnp_retry;
+
+U8 id_changed_to_host_event;
+
+volatile U8 otg_last_sof_received; // last SOF received in SOF interrupt
+volatile U8 otg_last_sof_stored; // last SOF value stored in OTG Timer interrupt
+volatile U8 reset_received; // indicates if a reset has been received from B-Host after a HNP (used in A-Periph mode)
+
+/// @brief VBUS Overload management
+///
+/// Nothing to do ! If the condition is not defined in the board driver file
+/// (i.e. if the board does not support Vbus overcurrent detection),
+/// the macro is defined to false for firmware compatibility
+#define Is_vbus_overcurrent() (FALSE)
+
+/// Private function prototypes
+/// Tasks for OTG Messaging features
+void Otg_message_task_init(void);
+void Otg_message_task(void);
+
+
+//------------------------------------------------------------------------------
+// Local Variables
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal Functions
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes the USB process
+/// Depending on the mode supported (HOST/DEVICE/DUAL_ROLE) the function calls
+/// the coresponding USB mode initialization function
+//------------------------------------------------------------------------------
+void usb_task_init(void)
+{
+ // DUAL ROLE DEVICE USB MODE
+ Otg_message_task_init(); // OTG program needs to display event messages to the user
+ b_uut_device_state = B_IDLE; // init state machines variables
+ device_state = DEVICE_UNATTACHED;
+ otg_device_nb_hnp_retry = BDEV_HNP_NB_RETRY;
+ Clear_all_user_request();
+ Usb_enable_uid_pin();
+
+ g_usb_mode=USB_MODE_UNDEFINED;
+
+ if(Is_usb_id_device()) {
+ g_usb_mode=USB_MODE_DEVICE;
+#ifdef MSD_PROJECT
+ MSDDriver_Initialize(luns, numMedias);
+#else
+ // HID
+ HIDDMouseDriver_Initialize();
+#endif
+ id_changed_to_host_event = DISABLE;
+ }
+ else {
+ Usb_send_event(EVT_USB_HOST_FUNCTION);
+ g_usb_mode=USB_MODE_HOST;
+ // Startup with ID=0, Ack ID pin transistion (default hwd start up is device mode)
+ Usb_ack_id_transition();
+ Usb_enable_id_interrupt();
+ usb_host_task_init();
+ id_changed_to_host_event = ENABLE;
+ }
+ // Store current usb mode, for mode change detection
+ g_old_usb_mode = g_usb_mode;
+}
+
+
+//------------------------------------------------------------------------------
+/// Entry point of the USB mamnagement
+/// Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function
+/// calls the coresponding USB management function
+//------------------------------------------------------------------------------
+void usb_task(void)
+{
+ // DUAL ROLE DEVICE USB MODE
+ if(Is_usb_id_device()) {
+ g_usb_mode = USB_MODE_DEVICE;
+ }
+ else {
+ g_usb_mode = USB_MODE_HOST;
+ }
+ g_old_usb_mode = g_usb_mode; // Store current usb mode, for mode change detection
+ // Depending on current usb mode, launch the correct usb task (device or host)
+
+ // Configure OTG timers
+ Set_otg_custom_timer(VBUSRISE_70MS);
+ Set_otg_custom_timer(VBUSPULSE_40MS);
+ Set_otg_custom_timer(VFALLTMOUT_131MS);
+ Set_otg_custom_timer(SRPMINDET_100US);
+
+ switch(g_usb_mode) {
+ case USB_MODE_DEVICE:
+ //usb_device_task();
+ //MSDDriver_StateMachine();
+ Scheduler_task_3();
+ break;
+
+ case USB_MODE_HOST:
+ if( pOTGDescriptor->bOTGADevSRPReaction == VBUS_PULSE) {
+ Usb_select_vbus_srp_method();
+ }
+ else {
+ Usb_select_data_srp_method();
+ }
+ usb_host_task();
+ // Handle Vbus overcurrent error (auto-disabled if not supported or not defined in board driver file)
+ if (Is_vbus_overcurrent()) {
+ Otg_print_new_event_message(OTGMSG_VBUS_SURCHARGE,OTG_TEMPO_3SEC);
+ }
+ break;
+
+ case USB_MODE_UNDEFINED: // No break !
+ default:
+ break;
+ }
+ Otg_message_task();
+}
+
+
+
+//------------------------------------------------------------------------------
+/// USB interrupt subroutine
+///
+/// This function is called each time a USB interrupt occurs.
+/// The following USB DEVICE events are taken in charge:
+/// - VBus On / Off
+/// - Start Of Frame
+/// - Suspend
+/// - Wake-Up
+/// - Resume
+/// - Reset
+/// - Start of frame
+///
+/// The following USB HOST events are taken in charge:
+/// - Device connection
+/// - Device Disconnection
+/// - Start Of Frame
+/// - ID pin change
+/// - SOF (or Keep alive in low speed) sent
+/// - Wake up on USB line detected
+///
+/// The following USB HOST events are taken in charge:
+/// - HNP success (Role Exchange)
+/// - HNP failure (HNP Error)
+///
+/// For each event, the user can launch an action by completing
+/// the associate define (See conf_usb.h file to add action upon events)
+///
+/// Note: Only interrupts events that are enabled are processed
+//------------------------------------------------------------------------------
+void usb_general_interrupt(void)
+{
+ //TRACE_DEBUG("usb_general_interrupt\n\r");
+
+ // ---------- DEVICE events management -----------------------------------
+ // -----------------------------------------------------------------------
+
+ //- VBUS state detection
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()
+ && Is_usb_id_device()) {
+ Usb_ack_vbus_transition();
+
+ if (Is_usb_vbus_high()) {
+ usb_connected = TRUE;
+ Usb_vbus_on_action();
+ Usb_send_event(EVT_USB_POWERED);
+ //jcb Usb_enable_reset_interrupt();
+ //usb_start_device();
+ USBD_Connect();//Usb_attach();
+ }
+ else {
+ TRACE_DEBUG("VBUS low\n\r");
+ USBD_Disconnect();
+ Usb_device_stop_hnp();
+ TRACE_DEBUG("Usb_select_device4\n\r");
+ Usb_select_device();
+ Clear_all_user_request();
+ Usb_vbus_off_action();
+ usb_connected = FALSE;
+ usb_configuration_nb = 0;
+ Usb_send_event(EVT_USB_UNPOWERED);
+ }
+
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Device start of frame received
+ if (Is_usb_sof() && Is_sof_interrupt_enabled()) {
+ // TRACE_DEBUG_WP("F"); // device
+ Usb_ack_sof();
+ Usb_sof_action();
+ //sof_seen_in_session = TRUE;
+ otg_last_sof_received = UDFNUML; // store last frame number received
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Device Suspend event (no more USB activity detected)
+ if (Is_usb_suspend()) { //&& Is_suspend_interrupt_enabled()) {
+ //TRACE_DEBUG_WP("D\n\r");
+ // 1st : B-PERIPH mode ?
+ if (Is_usb_id_device()) {
+ // HNP Handler
+ TRACE_DEBUG("HNP Handler\n\r");
+ //TRACE_DEBUG("device_state = %d\n\r", device_state);
+ //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
+ if (Is_host_requested_hnp() // "b_hnp_enable" feature received
+ && (Is_session_started_with_srp() || Is_user_requested_hnp() )) {
+ if (otg_device_nb_hnp_retry == 0) {
+ otg_features_supported &= ~USBFeatureRequest_OTG_B_HNP_ENABLE;
+ }
+ else {
+ Ack_user_request_hnp();
+ Usb_ack_hnp_error_interrupt();
+ Usb_ack_role_exchange_interrupt();
+ Usb_enable_role_exchange_interrupt();
+ Usb_enable_hnp_error_interrupt();
+ Usb_device_initiate_hnp();
+ otg_device_nb_hnp_retry--;
+ }
+ }
+ else
+ {
+ // Remote wake-up handler
+ //TRACE_DEBUG("Remote wake-up handler\n\r");
+ //TRACE_DEBUG("device_state = %d\n\r", device_state);
+ //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
+ if ((remote_wakeup_feature == ENABLE) && (usb_configuration_nb != 0))
+ {
+ //TRACE_DEBUG("enabled\n\r");
+ // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up
+ // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume
+ // So the SUSPE enable bit must be cleared to avoid redundant interrupt
+ // ****************
+ // Please note also that is Vbus is lost during an upstream resume (Host disconnection),
+ // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent)
+ // remains set after the event, so that a good way to handle this feature is :
+ // Usb_initiate_remote_wake_up();
+ // while (Is_usb_pending_remote_wake_up())
+ // {
+ // if (Is_usb_vbus_low())
+ // {
+ // // Emergency action (reset macro, etc.) if Vbus lost during resuming
+ // break;
+ // }
+ // }
+ // Usb_ack_remote_wake_up_start();
+ // ****************
+ }
+ else {
+ //TRACE_DEBUG("disabled: %d %d\n\r", usb_configuration_nb, remote_wakeup_feature);
+ // No remote wake-up supported
+ Usb_send_event(EVT_USB_SUSPEND);
+ }
+ }
+ }
+ else
+ {
+ //TRACE_DEBUG("ici\n\r");
+ // A-PERIPH mode (will cause a session end, handled in usb_host_task.c)
+ Usb_send_event(EVT_USB_SUSPEND);
+ Usb_suspend_action();
+ //jcb Usb_ack_suspend();
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Wake up event (USB activity detected): Used to resume
+ if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled()) {
+ TRACE_DEBUG("W\n\r");
+ Usb_unfreeze_clock();
+ Usb_send_event(EVT_USB_WAKE_UP);
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - Resume state bus detection
+ if (Is_usb_resume() && Is_resume_interrupt_enabled()) {
+ TRACE_DEBUG("Resume state bus detect\n\r");
+ Usb_send_event(EVT_USB_RESUME);
+ }
+
+ // -----------------------------------------------------------------------
+ /// Device
+ // -----------------------------------------------------------------------
+ // - USB bus reset detection
+ if (Is_usb_reset()&& Is_reset_interrupt_enabled()) {
+ TRACE_DEBUG_WP("B\n\r");
+ if (Is_usb_id_host()) {
+ //TRACE_DEBUG_WP("id_host\n\r");
+ dev_configure_endpoint(EP_CONTROL,
+ TYPE_CONTROL,
+ DIRECTION_OUT,
+ SIZE_64,
+ ONE_BANK,
+ NYET_DISABLED);
+ }
+ // First initialization is important to be synchronized
+ // A reset must first have been received
+ if (device_state == A_PERIPHERAL) {
+ //TRACE_DEBUG_WP("r A_PERIPHERAL\n\r");
+ otg_last_sof_received = UDFNUML;
+ otg_last_sof_stored = UDFNUML;
+ Usb_ack_sof();
+ Usb_enable_sof_interrupt();
+ reset_received = TRUE;
+ Timer16_set_counter(0);
+ }
+ Usb_reset_action();
+ Usb_send_event(EVT_USB_RESET);
+ }
+
+ // ---------- OTG events management ------------------------------------
+ // ---------------------------------------------------------------------
+
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ // - OTG HNP Success detection
+ if (Is_usb_role_exchange_interrupt() && Is_role_exchange_interrupt_enabled()) {
+ // TRACE_DEBUG("OTG HNP detect\n\r");
+ Usb_ack_role_exchange_interrupt();
+ Host_ack_device_connection();
+ Host_ack_device_disconnection();
+ Otg_send_event(EVT_OTG_HNP_SUCCESS);
+ End_session_with_srp();
+ Clear_otg_features_from_host();
+ if (Is_usb_id_host()) {
+ // HOST (A- or B-) mode
+ if ((device_state != A_PERIPHERAL) && (device_state != A_END_HNP_WAIT_VFALL)) {
+ static volatile unsigned int jcb;
+ // Current mode is A-HOST, device will take the A-PERIPHERAL role
+ b_uut_device_state = B_PERIPHERAL;
+ device_state = A_PERIPHERAL;
+ usb_connected = FALSE;
+ usb_configuration_nb = 0;
+ Usb_select_device();
+ USBD_Connect();//Usb_attach();
+ Usb_unfreeze_clock();
+ Usb_disable_role_exchange_interrupt();
+ Usb_disable_hnp_error_interrupt();
+ Usb_device_stop_hnp();
+ Usb_ack_reset();
+ Timer16_set_counter(0);
+ Usb_freeze_clock(); // USB clock can be freezed to slow down events and condition detection
+ //jcb while (Timer16_get_counter_low() != 20);
+ jcb=0;
+ while( jcb <100000){ jcb++; }
+
+ Usb_unfreeze_clock();
+ reset_received = FALSE;
+ Usb_disable_sof_interrupt(); // will be set in the next OTG Timer IT (mandatory)
+
+ Usb_enable_suspend_interrupt();
+ Usb_enable_reset_interrupt();
+ dev_configure_endpoint(EP_CONTROL,
+ TYPE_CONTROL,
+ DIRECTION_OUT,
+ SIZE_64,
+ ONE_BANK,
+ NYET_DISABLED);
+ }
+ }
+ else {
+ // In B_HOST mode, the HNPREQ bit must not be cleared because it releases the bus in suspend mode (and sof can't start)
+ if ((b_uut_device_state != B_HOST) && (b_uut_device_state != B_END_HNP_SUSPEND)) {
+ static volatile unsigned int jcb2;
+ // Current mode is B-PERIPHERAL, device will go into B-HOST role
+ End_session_with_srp();
+ Clear_otg_features_from_host();
+ b_uut_device_state = B_HOST;
+ device_state = DEVICE_ATTACHED;
+ usb_connected = FALSE;
+ usb_configuration_nb = 0;
+ TRACE_DEBUG("Select host 3\n\r");
+ Usb_select_host();
+
+ TRACE_DEBUG("Send reset\n\r");
+ Host_send_reset(); // send the first RESET
+ while (Host_is_reset());
+ TRACE_DEBUG("Reset passed\n\r");
+
+ jcb2=0;
+ while( jcb2 <1000000){ jcb2++; }
+ Host_enable_sof(); // start Host (sof)
+ Usb_disable_role_exchange_interrupt();
+ Usb_disable_hnp_error_interrupt();
+ Clear_all_user_request();
+
+ TRACE_DEBUG("Select host 3\n\r");
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ // - OTG HNP Failure detection
+ if (Is_usb_hnp() && Is_usb_hnp_error_interrupt()&& Is_hnp_error_interrupt_enabled()) {
+ TRACE_DEBUG("OTG HNP failure\n\r");
+ Usb_device_stop_hnp();
+ Usb_disable_role_exchange_interrupt();
+ Usb_disable_hnp_error_interrupt();
+ Usb_ack_hnp_error_interrupt();
+ if (Is_usb_id_device()) {
+ Otg_send_event(EVT_OTG_HNP_ERROR);
+ Clear_all_user_request();
+ }
+ }
+
+ // ---------- HOST events management -----------------------------------
+ // ---------------------------------------------------------------------
+
+ // -----------------------------------------------------------------------
+ /// Arbitrer
+ // -----------------------------------------------------------------------
+ // - ID pin change detection
+ if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled()) {
+ TRACE_DEBUG("ID pin change\n\r");
+ TRACE_DEBUG("device_state = %d\n\r", device_state);
+ TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
+ Usb_device_stop_hnp();
+ Clear_all_user_request();
+ if(Is_usb_id_device()) {
+ g_usb_mode = USB_MODE_DEVICE;
+ }
+ else {
+ g_usb_mode = USB_MODE_HOST;
+ }
+ Usb_ack_id_transition();
+ if( g_usb_mode != g_old_usb_mode) { // Basic Debounce
+ if(Is_usb_id_device()) { // Going into device mode
+ Usb_send_event(EVT_USB_DEVICE_FUNCTION);
+ b_uut_device_state = B_IDLE;
+ device_state = DEVICE_UNATTACHED;
+ id_changed_to_host_event = DISABLE;
+ }
+ else { // Going into host mode
+ b_uut_device_state = B_IDLE;
+ device_state = DEVICE_UNATTACHED;
+ Usb_send_event(EVT_USB_HOST_FUNCTION);
+ id_changed_to_host_event = ENABLE;
+ }
+ Usb_id_transition_action();
+ TRACE_INFO("Pin Id changed\n\r");
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - The device has been disconnected
+ // JCB to be fix
+ if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) {
+ TRACE_DEBUG("device disconnect\n\r");
+ host_disable_all_pipe();
+ Host_ack_device_disconnection();
+ device_state=DEVICE_DISCONNECTED;
+ Usb_send_event(EVT_HOST_DISCONNECTION);
+ TRACE_INFO("Device disconnected\n\r");
+ Host_device_disconnection_action();
+ Clear_all_user_request();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Device connection
+ if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) {
+ TRACE_DEBUG("device connect\n\r");
+ Host_ack_device_connection();
+ host_disable_all_pipe();
+ Host_device_connection_action();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Host Start of frame has been sent
+ if (Is_host_sof() && Is_host_sof_interrupt_enabled()) {
+ //TRACE_DEBUG_WP("_"); // host
+ Host_ack_sof();
+ Usb_send_event(EVT_HOST_SOF);
+ private_sof_counter++;
+
+ // delay timeout management for interrupt tranfer mode in host mode
+#if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
+ if (private_sof_counter>=250) { // Count 1/4 sec
+ private_sof_counter=0;
+ for(i=0;i<MAX_EP_NB;i++) {
+ if(it_pipe_str[i].enable==ENABLE) {
+ save_pipe_nb=Host_get_selected_pipe();
+ Host_select_pipe(i);
+ if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) {
+ it_pipe_str[i].enable=DISABLE;
+ it_pipe_str[i].status=PIPE_DELAY_TIMEOUT;
+ Host_stop_pipe_interrupt(i);
+ if (is_any_interrupt_pipe_active()==FALSE) { // If no more transfer is armed
+ if (g_sav_int_sof_enable==FALSE) {
+ Host_disable_sof_interrupt();
+ }
+ }
+ it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed);
+ }
+ Host_select_pipe(save_pipe_nb);
+ }
+ }
+ }
+#endif // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
+ Host_sof_action();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // - Host Wake-up has been received
+ if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) {
+ TRACE_DEBUG("Host wake up\n\r");
+ Host_disable_hwup_interrupt(); // Wake up interrupt should be disable host is now wake up !
+ Host_disable_remote_wakeup_interrupt();
+ // CAUTION HWUP can be cleared only when USB clock is active (not frozen)!
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ Host_enable_sof(); // start sending SOF
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Host_ack_remote_wakeup();
+ Usb_send_event(EVT_HOST_HWUP); // Send software event
+ Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
+ Host_hwup_action(); // Map custom action
+ if (Is_usb_hnp()) {
+ Usb_host_reject_hnp();
+ Usb_disable_hnp_error_interrupt();
+ Usb_disable_role_exchange_interrupt();
+ }
+ Host_send_resume();
+ }
+
+ // -----------------------------------------------------------------------
+ /// Host
+ // -----------------------------------------------------------------------
+ // Remote Wake Up has been received
+ if (Is_host_remote_wakeup_interrupt_enabled() && Is_host_remote_wakeup()) {
+ TRACE_DEBUG("Remote wake up\n\r");
+ Host_disable_remote_wakeup_interrupt();
+ Host_disable_hwup_interrupt();
+ Host_ack_remote_wakeup();
+ Host_ack_hwup(); // Clear HWUP interrupt flag
+ Usb_unfreeze_clock(); // Enable clock on USB interface
+ Host_enable_sof(); // start sending SOF
+ Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
+ Usb_send_event(EVT_HOST_HWUP); // Send software event
+ if (Is_usb_hnp()) {
+ Usb_host_reject_hnp();
+ Usb_disable_hnp_error_interrupt();
+ Usb_disable_role_exchange_interrupt();
+ }
+ Host_send_resume();
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// OTG TIMER interrupt subroutine
+/// This function is called each time a OTG Timer interrupt occurs
+/// Function decrements the variables required by OTG program
+void otg_timer_interrupt(void)
+{
+ /// OTG Messaging timer
+ if( (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL)
+ || (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_FAIL)) {
+ if ((Get_failure_msg_delay() != 0x0000) && (Get_failure_msg_delay() != 0xFFFF)) {
+ Decrement_failure_msg_delay();
+ }
+ if(pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL) {
+ if ((Get_event_msg_delay() != 0x0000) && (Get_event_msg_delay() != 0xFFFF)) {
+ Decrement_event_msg_delay();
+ }
+ }
+ }
+ /// Increments Tb_Srp counter if needed
+ if (Is_srp_sent_and_waiting_answer()) {
+ otg_tb_srp_cpt++;
+ }
+ /// Increments T_vbus_wait_connect if needed
+ if (Is_srp_received_and_waiting_connect()) {
+ otg_ta_srp_wait_connect++;
+ }
+ /// Decrements Ta_aidl_bdis timer if needed (A_suspend state)
+ if ((device_state == A_SUSPEND) && (otg_ta_aidl_bdis_tmr > 1)) {
+ otg_ta_aidl_bdis_tmr--;
+ }
+ /// Decrements Timeout_bdev_respond timer if needed
+ if ((device_state == DEVICE_DEFAULT) && (!Is_timeout_bdev_response_overflow())) {
+ otg_timeout_bdev_respond--;
+ }
+ /// Decrements Ta_vbus_rise timer if needed
+ if (!Is_ta_vbus_rise_counter_overflow()) {
+ otg_ta_vbus_rise--;
+ }
+ /// Decrements Ta_vbus_fall timer if needed
+ if (!Is_ta_vbus_fall_counter_overflow()) {
+ otg_end_hnp_vbus_delay--;
+ }
+
+ /// Needed for compliance only
+ if (device_state == A_PERIPHERAL) {
+ if (Is_sof_interrupt_enabled() && (reset_received == TRUE)) {
+ if (otg_last_sof_stored != otg_last_sof_received) {
+ // No SOF is missing
+ otg_last_sof_received = otg_last_sof_stored;
+ }
+ else {
+ // SOF seems to be missing..
+ Usb_freeze_clock();
+ Usb_disable_sof_interrupt();
+ reset_received = FALSE;
+ //jcb while (Timer16_get_counter_low() != 20); // overflow set to 62 in usb_task.h
+ Usb_unfreeze_clock();
+ }
+ otg_last_sof_received = UDFNUML;
+ otg_last_sof_stored = UDFNUML;
+ }
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// OTG Messaging task initialization
+/// Initializes variables and screen to prepare next messages to be handled
+//------------------------------------------------------------------------------
+void Otg_message_task_init(void)
+{
+ TRACE_DEBUG("Otg_message_task_init\n\r");
+ Otg_messaging_init();
+ otg_msg_event_delay = 0;
+ otg_msg_failure_delay = 0;
+}
+
+
+//------------------------------------------------------------------------------
+/// OTG Messaging main task
+/// OTG specifies that user must be kept informed of several events
+/// This task allows user to display two kinds of messages : EVENT or FAILURE
+/// For each new message, it can specify if the message remains displayed all
+/// the time or only during a specified delay
+//------------------------------------------------------------------------------
+void Otg_message_task(void)
+{
+ // Check if an OTG message must be erased (if it was set up for a specified delay)
+ if( (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL)
+ || (pOTGDescriptor->bOTGMessagingOutput == OTGMSG_FAIL)) {
+ if (Get_failure_msg_delay() == 0) {
+ Otg_clear_failure_message();
+ }
+ if(pOTGDescriptor->bOTGMessagingOutput == OTGMSG_ALL) {
+ if (Get_event_msg_delay() == 0) {
+ Otg_clear_event_message();
+ }
+ }
+ }
+}
+
+
+//------------------------------------------------------------------------------
+/// Message "OTG not supported"
+//------------------------------------------------------------------------------
+void otg_not_supported_device(void)
+{
+ TRACE_DEBUG("otg_not_supported_device\n\r");
+ Otg_send_event(EVT_OTG_DEV_UNSUPPORTED);
+}
+
+
diff --git a/usb/usb.dir b/usb/usb.dir new file mode 100644 index 0000000..bd207b1 --- /dev/null +++ b/usb/usb.dir @@ -0,0 +1,532 @@ +/* ----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+/// !!!Purpose
+///
+/// This directory provides a library of highly re-usable code to build
+/// USB applications with Atmel AT91 microcontrollers.
+///
+/// !!!Contents
+/// The directory can basically be divided into three sections for their usage:
+/// - common: %common USB definitions and routines, including standard USB
+/// spec. and the following classes: audio, cdc, hid, massstorage;
+/// - device: re-usable & portable software USB %device modules, including
+/// general UDP driver for AT91 microcontroller and the following
+/// devices: audio-speaker, ccid, cdc-serial, hid-keyboard,
+/// massstorage;
+/// - host: re-usable & portable software USB host modules
+///
+/// !!!AT91 USB device framework
+/// "AT91 USB device framework" is architectured as following:
+/// - #Hardware layer#: low-level operations on the USB UDP controller
+/// - device/core, suffixed with UDP, UDPHS, OTGHS
+/// - #USB %device API#: offers hardware-independent methods and structures
+/// - device/core, other files: driver, events and callbacks
+/// - common/core: general USB descriptors and requests
+/// - common/, other directories: general USB class descriptors and requests
+/// - #Applicatioin layer#: the USB class driver and user/demo applicaiton
+/// - device/, other directories, named with the class driver function
+/// - project directory, with main.c
+///
+/// "USB Device Framework Architecture"
+/// \image USBFrameworkArchitecture.png "USB Framework Architecture"
+///
+/// ---
+///
+/// For more information about what a particular group contains, please refer to
+/// its documentation page.
+///
+/// \note
+/// Depending on the project, not all the subdirectories will be available
+/// (i.e. the #host# directory will not be in projects without USB host).
+//------------------------------------------------------------------------------
+
+/**
+ \page "AT91 USB device framework"
+
+ AT91 USB %device framework is a device-side USB framework. It enables rapid
+ development of USB-compliant class drivers such as the Mass Storage Device
+ (MSD) or the Communication Device Class (CDC) and etc.
+
+ This page shows the index to describe the AT91 USB %device framework.
+ - USBD: USB Device
+
+ -# "USB Device Framework Architecture"
+ -# "USB Device Framework Description"
+ -# "Standard USB Structures"
+ -# "USBD API"
+ -# "USBD Callback API"
+ -# "USBD Standard Request Handler"
+ -# "USB Device Framework Usage"
+ -# "USBD File Architecture"
+ -# "USBD Headers"
+ -# "Building the Framework"
+ -# "USB Device Enumeration"
+
+*/
+
+/**
+ \page "USB Device Framework Architecture"
+
+ !!!Framework Architecture
+
+ The following three-tiered structure is used:
+ - A #hardware layer# which performs low-level operations on the USB controller.
+ - The #USB API# offers hardware-independent methods and structures.
+ - The #application layer#, made up of a USB class driver and the user
+ application.
+
+ The framework includes the USBD API and the hardware layer as well as a standard
+ request handler. The application layer is build on top of that to provide the
+ %device functionalty.
+
+ There are also callbacks automatically called by the USBD API to perform
+ specific operations, to perform communication between the USBD API and the
+ application layer.
+
+ \image USBFrameworkArchitecture.png "USB Framework Architecture"
+
+*/
+
+/* (Image Link Backup)
+<img src="USBFrameworkArchitecture.png" border="0" alt="USBFrameworkArchitecture.png" usemap="#usb_fm_arch">
+<map name="usb_fm_arch">
+<area shape="poly" coords="150,239,346,239,346,275,150,275,150,239" onmouseover="link('_dir','device/core/core0',this);overLibDiagram();return overlib('UDP controller driver');" onmouseout="return nd();">
+<area shape="poly" coords="343,131,451,131,451,167,343,167,343,131" onmouseover="link('_page','device/USBDCallbackAPI0',this);overLibDiagram();return overlib('USBD Callback API<BR>Callbacks');" onmouseout="return nd();">
+<area shape="poly" coords="194,131,303,131,303,167,194,167,194,131" onmouseover="link('_page','device/USBDCallbackAPI0',this);overLibDiagram();return overlib('USBD Callback API<BR>Interrupt handler for events');" onmouseout="return nd();">
+<area shape="poly" coords="25,131,134,131,134,167,25,167,25,131" onmouseover="link('_page','device/USBDApiMethods0',this);overLibDiagram();return overlib('USBD API, USBD_');" onmouseout="return nd();">
+<area shape="poly" coords="5,31,113,31,113,67,5,67,5,31" onmouseover="link('_page','common/core/StandardUSBStructures0',this);overLibDiagram();return overlib('Standard USB structures and methods');" onmouseout="return nd();">
+<area shape="poly" coords="139,30,256,30,256,68,139,68,139,30" onmouseover="link('_dir','device/device0',this);overLibDiagram();return overlib('Current implemented class-specific drivers');" onmouseout="return nd();">
+</map>
+*/
+
+/**
+ \page "USB Device Framework Description"
+
+ !!!Framework Discription
+
+ The framework is comprised of serveral components:
+ -# "Standard USB Structures"
+ -# "USBD API"
+ - Structures
+ - Methods
+ -# "USBD Callback API"
+ -# "USBD Standard Request Handler"
+*/
+
+/**
+ \page "USB Device Framework Usage"
+
+ !!!File Architecture
+
+ The USB framework is made up of the following files:
+ at91lib\\boards: %device register definition, board-related code and
+ %device startup code in assembly language\n
+ at91lib\\utility: debug methods and definitions\n
+ at91lib\\peripherals\\dbgu: DBGU port usage for debug\n
+ at91lib\\peripherals\\pio: PIO interface usage for Vbus ...\n
+ at91lib\\peripherals\\aic: Interrupt configurationi functions\n
+ at91lib\\usb\\common\\core: structures and methods of standard descriptors
+ and requests\n
+ at91lib\\usb\\device\\core: UDP controller driver methods and USBD API
+ definitions\n
+ usb-device-core-project: basic enumeration program, with main.c and
+ Makefile to build the project\n
+
+ !!!Headers
+
+ When programming your own application, most if not all the headers described
+ in the file architecture of the framework must be included. However, since
+ each header has its own dependencies, they must be included in a particular
+ order.
+
+ Here is the standard inclusion order:
+\code
+#include <usb/common/core/USBGenericDescriptor.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBGenericRequest.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+#include <usb/device/core/USBDCallbacks.h>
+\endcode
+ If a custom class driver has been added, then its header must probably be
+ linked last.
+
+ !!!Building the Framework
+
+ A Makefile is provided to make it easier to compile the framework. The }make}
+ program and arm-elf-gcc is necessary to use it.
+
+ Several options are available to build the framework in different ways:
+ - CHIP
+ - Target chip for which to build the program.
+ - Possible values: at91sam7s64, at91sam7s128, at91sam7s256, at91sam7s512,
+ at91sam7s321, at91sam7se32, at91sam7se256, at91sam7se512, at91sam7x128,
+ at91sam7x256, at91sam7s512, at91sam7xc128, at91sam7xc256, at91sam7xc512,
+ at91sam9260, at91sam9261, at91sam9263
+ - Default: at91sam7s256
+ - BOARD
+ - Board used with the chip.
+ - Possible values: at91sam7s-ek, at91sam7se-ek, at91sam7x-ek,
+ at91sam7xc-ek, at91sam7a3-ek, at91sam9260-ek, at91sam9261-ek,
+ at91sam9263-ek
+ - Default: at91sam7s-ek
+
+*/
+
+/**
+ \page "USB Device Enumeration"
+
+ This page is a step-by-step guide on how to use the USB Device framework
+ to produce a simple program that performs USB enumeration. In this example,
+ everything is put into a single file. You can look at the main.c file provided
+ with the framework to view the end result.
+
+ !!!Including the Necessary Headers
+
+ Prior to using the framework, several header files have to be included. Please
+ refer to "USB Device Framework Usage" for more information.
+
+ !!!Declaring Global Varibles
+
+ Several object instances are necessary to use the various functions and methods
+ of the USB framework. As following.
+
+ !!USBD Driver
+ The very first step is declare the USB driver which is then used by the Class
+ driver. The USBDDriver structure is used as a container for several variables,
+ which must therefore be created first.
+
+ !Endpoints
+ Depending on the application, a particular number of endpoints have to be
+ defined. For example, an MSD driver needs three endpoints whereas a CDC driver
+ needs four. Refer to the corresponding specification for more information
+ about the required number of endpoints. Since this example should only perform
+ the USB enumeration, it will declare only one endpoint: Control endpoint 0.
+
+ Endpoints is configrued by USBEndpointDescriptor in USBDDriverDescriptors for
+ the driver. The FIFO banks is automatically set to its maximum value.
+
+ !Callbacks
+ To replace the default callback, you should remove the default callback file
+ from makefile and add your own function defintion.
+
+||callback function file||callback function
+|USBDCallbacks_Initialized.o|USBDCallbacks_Initialized
+|USBDCallbacks_Reset.o|USBDCallbacks_Reset
+|USBDCallbacks_Suspended.o|USBDCallbacks_Suspended
+|USBDCallbacks_Resumed.o|USBDCallbacks_Resumed
+|- #MUST# be defined|USBDCallbacks_RequestReceived
+
+ !Driver
+ Depending on the chip used, there may or may not be a need to declare a low-
+ level driver variable.
+
+ The default driver global variable is simply called usbdDriver, and will
+ sufficient for this example.
+ \code
+USBDDriver usbdDriver;
+ \endcode
+
+ !!Descriptors
+ The USB specification 2.0 defines a set of descriptors used to give
+ information about the %device. Depending on the USB class implemented,
+ different descriptors have to be used with varying values.
+
+ In this example program, only a few descriptors are required,. The %device
+ descriptor is always mandatory, so it will have to be defined. At least one
+ configuration descriptor is required, so one is implemented. The described
+ configuration must have at least one interface, so one more descriptor is
+ needed. Finally, no string descriptors are used:
+
+ !Device Descriptor
+ The device descriptor used by this example looks like this:
+ \code
+/// Device descriptor.
+const USBDeviceDescriptor usbDeviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ 0, // No device class code
+ 0, // No device subclass code
+ 0, // No device protocol code
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 0x03EB, // Atmel vendor ID
+ 0x0001, // Product ID
+ 0x0001, // Product release 0.01
+ 0, // No manufacturer string descriptor
+ 0, // No product string descriptor
+ 0, // No serial number string descriptor
+ 1 // One possible configuration
+};
+ \endcode
+ The values are nothing special here. Note that the first three fields have the
+ same data in them (unless using USB 1.1). It is also very common to define the
+ class, subclass and protocol values at the interface level.
+
+ - Note: The }vendor ID} value is provided by the USB-IF organization. The
+ }product ID} is vendor-specific and can be assigned any value.
+
+ !Configuration & Interface
+ When the configuration descriptor is requested by the host, via the
+ GET_DESCRIPTOR command, the device must not only transmit this descriptor but
+ also all the necessary interface and endpoint descriptors.
+
+ In order to do that easily, a structure must be defined for holding all the
+ information. This way, the data to send is contiguous, making the request
+ much simpler to fulfill. In the current example, the configuration descriptor
+ must be followed by the first interface descriptor. The following structure is
+ declared for that:
+ \code
+// Configuration descriptors with one interface.
+struct SimpleConfigurationDescriptors {
+
+ USBConfigurationDescriptor configuration;
+ USBInterfaceDescriptor interface;
+};
+ \endcode
+ Now, the actual descriptors can be declared:
+ \code
+// Configuration descriptors.
+const struct SimpleConfigurationDescriptors configurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(struct SimpleConfigurationDescriptors),
+ 0, // No interface in this configuration
+ 1, // This is configuration #1
+ 0, // No string descriptor for this configuration
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is setting #0 for interface
+ 0, // Interface has no endpoint
+ 0, // No interface class code
+ 0, // No interface subclass code
+ 0, // No interface protocol code
+ 0, // No string descriptor
+ }
+};
+ \endcode
+ Again, those are very generic values. For the interface descriptor, most of
+ them are zeroed. This is because this example does not implement any
+ functionality other than doing the USB enumeration.
+
+ !!Class Driver
+ The demonstration program is going to use the standard request handler
+ discussed in "USBD Standard Request Handler" to perform the USB enumeration.
+ To be able to do that, several structures must be declared.
+
+ !Descriptors List
+ The USBDDriver object needs a pointer to a list of descriptors. This is
+ necessary to be able to answer the GET_DESCRIPTOR request. A
+ USBDDriverDescriptors can be used to do that.
+
+ The actual descriptors list can be instantiated:
+ \code
+// List of descriptors used by the device.
+const USBDDriverDescriptors usbdDriverDescriptors = {
+
+ &usbDeviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptors,
+#ifdef BOARD_USB_UDPHS
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration descriptor
+ &usbDeviceDescriptor,
+ (const USBConfigurationDescriptor *) &configurationDescriptors,
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+#else
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration descriptor
+ 0, // No high-speed device descriptor
+ 0, // No high-speed configuration descriptor
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+#endif
+ 0, // No string descriptor
+ 0 // No string descriptor
+};
+ \endcode
+ The core configuration descriptor, which is actually made up of the
+ configuation descriptor and the first interface descriptor, has to be cast to
+ the USBConfigurationDescriptor type.
+
+ !!!Interrupt Service Routines
+
+ .
+
+ !!USB Controller Interrupt
+ The USB controller peripheral generates an interrupt when an event occurs.
+ Since that event must be forwarded to the USBD_IrqHandler method, an
+ interrupt service routine must be installed to do that.
+ \code
+ void ISR_Usb()
+ {
+ USBD_IrqHandler();
+ }
+ \endcode
+ Currently the default USBDCallbacks_Initialized will initialize the
+ interrupt service routine automatically:
+ \code
+void USBDCallbacks_Initialized()
+{
+ AIC_ConfigureIT(AT91C_ID_UDP, 0, USBD_IrqHandler);
+ AIC_EnableIT(AT91C_ID_UDP);
+}
+ \endcode
+ So the only thing you should do to initialize the interrupt service is to call
+ USBD_Init() in main().
+
+ !!VBus PIO Interrupt
+ The Vbus power line can be monitored (if a PIO pin is connected to it) by the
+ user application to enable or disable the USB controller peripheral when the
+ %device is connected/disconnected. To do that, an interrupt must be programmed
+ when the status of Vbus changes. The ISR should call the USBD_Connect or
+ USBD_Disconnect function as follows:
+ \code
+void ISR_Vbus(const Pin *pPin)
+{
+ // Check current level on VBus
+ if (PIO_Get(&pinVbus)) {
+ USBD_Connect();
+ }
+ else {
+ USBD_Disconnect();
+ }
+}
+ \endcode
+
+ !!!Callbacks
+ A typical application based on this USB framework needs to instantiate most of
+ the callbacks available. This section describes how to do that for a simple
+ enumeration program.
+
+ !!Init
+ When an OS is not being used, the primary function that the {Init{ callback
+ must perform is interrupt handler installation. The previously defined ISR
+ is thus configured and enabled:
+ \code
+void USBDCallbacks_Initialized()
+{
+ // Configure and enable the UDP interrupt
+ AIC_ConfigureIT(AT91C_ID_UDP, 0, USBD_IrqHandler);
+ AIC_EnableIT(AT91C_ID_UDP);
+}
+ \endcode
+ The default callback is defined in USBDCallbacks_Initialized.c.
+
+ !!Suspend & Resume
+ The Suspend callback is used by the USBD API to notify the device that it
+ should enter low-power mode if required. The default callback is defined
+ in USBDCallbacks_Suspended.c.
+ \code
+void USBDCallbacks_Suspended(void)
+{
+ // Turn off LEDs
+ LED_Clear(USBD_LEDPOWER);
+ LED_Clear(USBD_LEDUSB);
+}
+ \endcode
+ The Resume callback has to perform the reverse operation. The default callback
+ is defined in USBDCallbacks_Resumed.c.
+ \code
+void USBDCallbacks_Resumed(void)
+{
+ // Initialize LEDs
+ LED_Configure(USBD_LEDPOWER);
+ LED_Set(USBD_LEDPOWER);
+ LED_Configure(USBD_LEDUSB);
+ LED_Clear(USBD_LEDUSB);
+}
+ \endcode
+
+ - Note: }It is not necessary to disable the USB controller logic (transceiver,
+ clocks, %peripheral) here. This is done directly by the USBD_IrqHandler
+ function prior to triggering the callback. Typically, the callback must carry
+ out the following operations:
+ - Disable the PLL
+ - Switch to the slow 32 KHz clock
+ - Turn off the clocks of used peripherals}
+
+ !!NewRequest
+ Since this example software should only perform the USB enumeration, the
+ NewRequest callback can simply forward the call to the standard request
+ handler method:
+ \code
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ USBDDriver_RequestHandler(&usbdDriver, request);
+}
+ \endcode
+
+ !!!Main
+ The Main function of the program is used for PIO and driver (Class and USB)
+ initialization, software connections of the device (by using USBD_Connect),
+ and implementation of the product functionality.
+
+ In this case, the Main performs the first two steps. After that, since the
+ enumeration is done through the event handler and the device does not do
+ anything, it can simply enter an infinite loop:
+
+ \code
+int main()
+{
+ // If they are present, configure Vbus & Wake-up pins
+ PIO_InitializeInterrupts(0);
+
+ // USB initialization
+ USBDDriver_Initialize(&usbdDriver, &usbdDriverDescriptors, 0);
+ USBD_Init();
+
+ // connect if needed
+ VBUS_CONFIGURE();
+ while (USBD_GetState() < USBD_STATE_CONFIGURED);
+
+ // Main loop
+ while(1)
+ {
+ // Put USB class driver implementaion here
+ }
+}
+ \endcode
+*/
\ No newline at end of file |