From b123d740e08a5084d9b536e867a1f52a327597db Mon Sep 17 00:00:00 2001 From: Christina Quast Date: Tue, 23 Dec 2014 13:03:36 +0100 Subject: [PATCH] atmel_softpack_libraries usb dir --- .../usb/USBFrameworkArchitecture.png | Bin 0 -> 5288 bytes .../usb/common/audio/AUDFeatureUnitRequest.c | 70 + .../usb/common/audio/AUDGenericRequest.c | 67 + .../usb/common/cdc/CDCLineCoding.c | 71 + .../cdc/CDCSetControlLineStateRequest.c | 87 + .../usb/common/core/USBDescriptors.c | 310 +++ .../usb/common/core/USBRequests.c | 244 +++ .../usb/common/hid/HIDIdleRequest.c | 73 + .../usb/common/hid/HIDKeypad.c | 61 + .../usb/common/hid/HIDReportRequest.c | 73 + .../USBDCallbackInvocationFlowchart.png | Bin 0 -> 11380 bytes .../usb/device/USBDeviceStateDiagram.png | Bin 0 -> 8827 bytes .../device/audio-speaker/AUDDSpeakerDriver.c | 234 +++ .../AUDDSpeakerDriver_Callbacks.c | 74 + .../device/audio-speaker/USBAudioSpeaker.png | Bin 0 -> 3711 bytes .../USBAudioSpeakerDescriptors.png | Bin 0 -> 8026 bytes .../audio-speaker/USBAudioSpeakerRecorder.png | Bin 0 -> 5053 bytes .../USBAudioSpeakerRecorderDescriptors.png | Bin 0 -> 10906 bytes .../AUDDSpeakerPhoneDriver.c | 468 +++++ .../AUDDSpeakerPhoneDriver_Callbacks.c | 76 + .../device/audio-speakerphone/AUDDStream.c | 770 +++++++ .../usb/device/ccid/cciddriver.c | 1657 +++++++++++++++ .../usb/device/ccid/cciddriver.h | 420 ++++ .../usb/device/ccid/cciddriverdescriptors.h | 182 ++ .../usb/device/cdc-serial/CDCDSerial.c | 237 +++ .../usb/device/cdc-serial/CDCDSerialDriver.c | 116 ++ .../cdc-serial/CDCDSerialDriver_Callbacks.c | 67 + .../usb/device/cdc-serial/CDCDSerialPort.c | 455 ++++ .../usb/device/cdc-serial/CDCarchitecture.png | Bin 0 -> 28223 bytes .../device/cdc-serial/USB-SerialConverter.png | Bin 0 -> 10177 bytes .../usb/device/cdc-serial/drv/6119.inf | 45 + .../usb/device/composite/AUDDFunction.c | 235 +++ .../usb/device/composite/CDCAUDDDriver.c | 139 ++ .../usb/device/composite/CDCHIDDDriver.c | 138 ++ .../usb/device/composite/CDCMSDDriver.c | 128 ++ .../usb/device/composite/DUALCDCDDriver.c | 194 ++ .../usb/device/composite/HIDAUDDDriver.c | 139 ++ .../usb/device/composite/HIDMSDDriver.c | 153 ++ .../composite/UsbCompositeCdcAudioArch.png | Bin 0 -> 50020 bytes .../composite/UsbCompositeCdcCdcArch.png | Bin 0 -> 55600 bytes .../composite/UsbCompositeCdcHidArch.png | Bin 0 -> 48500 bytes .../composite/UsbCompositeCdcMsdArch.png | Bin 0 -> 50918 bytes .../composite/UsbCompositeComposition.png | Bin 0 -> 65583 bytes .../composite/UsbCompositeHidAudioArch.png | Bin 0 -> 42582 bytes .../composite/UsbCompositeHidMsdArch.png | Bin 0 -> 42038 bytes .../device/composite/UsbCompositeMultiIF.png | Bin 0 -> 34463 bytes .../composite/UsbCompositeRequestHandler.png | Bin 0 -> 59411 bytes .../device/composite/UsbCompositeSWArch.png | Bin 0 -> 44871 bytes .../device/composite/UsbCompositeSingleIF.png | Bin 0 -> 39451 bytes .../composite/drv/CompositeCDCSerial.inf | 57 + .../usb/device/core/USBD.c | 380 ++++ .../usb/device/core/USBDCallbacks.c | 89 + .../usb/device/core/USBDDriver.c | 699 +++++++ .../usb/device/core/USBDDriverCallbacks.c | 79 + .../usb/device/hid-keyboard/HIDClassArch.png | Bin 0 -> 3495 bytes .../usb/device/hid-keyboard/HIDDKeyboard.c | 374 ++++ .../HIDDKeyboardCallbacks_LedsChanged.c | 66 + .../device/hid-keyboard/HIDDKeyboardDriver.c | 123 ++ .../hid-keyboard/HIDDKeyboardInputReport.c | 147 ++ .../hid-keyboard/HIDDKeyboardOutputReport.c | 96 + .../usb/device/hid-mouse/HIDDMouseDriver.c | 277 +++ .../usb/device/hid-transfer/HIDDFunction.c | 695 ++++++ .../device/hid-transfer/HIDDTransferDriver.c | 481 +++++ .../usb/device/massstorage/MSDAppArch.png | Bin 0 -> 7248 bytes .../usb/device/massstorage/MSDDStateMachine.c | 637 ++++++ .../usb/device/massstorage/MSDDriver.c | 113 + .../usb/device/massstorage/MSDDriverArch.png | Bin 0 -> 4889 bytes .../device/massstorage/MSDDriverClasses.png | Bin 0 -> 12031 bytes .../device/massstorage/MSDDriverStates.png | Bin 0 -> 7920 bytes .../usb/device/massstorage/MSDFunction.c | 311 +++ .../usb/device/massstorage/MSDIOFifo.c | 75 + .../usb/device/massstorage/MSDLun.c | 389 ++++ .../usb/device/massstorage/MSDMediaArch.png | Bin 0 -> 3622 bytes .../usb/device/massstorage/SBCMethods.c | 1855 +++++++++++++++++ .../usb/include/AUDDFunction.h | 109 + .../usb/include/AUDDSpeakerDriver.h | 256 +++ .../usb/include/AUDDSpeakerPhone.h | 156 ++ .../usb/include/AUDDSpeakerPhoneDriver.h | 311 +++ .../usb/include/AUDDStream.h | 149 ++ .../usb/include/AUDDescriptors.h | 546 +++++ .../usb/include/AUDRequests.h | 123 ++ .../usb/include/CDCAUDDDriver.h | 307 +++ .../usb/include/CDCDSerial.h | 106 + .../usb/include/CDCDSerialDriver.h | 245 +++ .../usb/include/CDCDSerialPort.h | 167 ++ .../usb/include/CDCDescriptors.h | 275 +++ .../usb/include/CDCHIDDDriver.h | 152 ++ .../usb/include/CDCMSDDriver.h | 155 ++ .../usb/include/CDCNotifications.h | 111 + .../usb/include/CDCRequests.h | 182 ++ .../usb/include/DUALCDCDDriver.h | 157 ++ .../usb/include/HIDAUDDDriver.h | 191 ++ .../usb/include/HIDDFunction.h | 210 ++ .../usb/include/HIDDKeyboard.h | 216 ++ .../usb/include/HIDDKeyboardDriver.h | 125 ++ .../usb/include/HIDDMouseDriver.h | 151 ++ .../usb/include/HIDDTransferDriver.h | 141 ++ .../usb/include/HIDDescriptors.h | 229 ++ .../usb/include/HIDMSDDriver.h | 140 ++ .../usb/include/HIDReports.h | 299 +++ .../usb/include/HIDRequests.h | 154 ++ .../usb/include/HIDUsages.h | 393 ++++ .../usb/include/MSD.h | 245 +++ .../usb/include/MSDDStateMachine.h | 256 +++ .../usb/include/MSDDriver.h | 141 ++ .../usb/include/MSDFunction.h | 74 + .../usb/include/MSDIOFifo.h | 145 ++ .../usb/include/MSDLun.h | 176 ++ .../usb/include/MSDescriptors.h | 109 + .../usb/include/SBC.h | 678 ++++++ .../usb/include/SBCMethods.h | 118 ++ .../usb/include/USBD.h | 276 +++ .../usb/include/USBDDriver.h | 148 ++ .../usb/include/USBD_HAL.h | 107 + .../usb/include/USBDescriptors.h | 552 +++++ .../usb/include/USBLib_Trace.h | 209 ++ .../usb/include/USBLib_Types.h | 65 + .../usb/include/USBRequests.h | 354 ++++ .../usb/lib/libusb_sam3s_gcc_dbg.a | Bin 0 -> 434082 bytes .../usb/lib/libusb_sam3s_gcc_rel.a | Bin 0 -> 119116 bytes .../atmel_softpack_libraries/usb/usb.h | 99 + 121 files changed, 23434 insertions(+) create mode 100644 sam3s_example/atmel_softpack_libraries/usb/USBFrameworkArchitecture.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDFeatureUnitRequest.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDGenericRequest.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCLineCoding.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCSetControlLineStateRequest.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/core/USBDescriptors.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/core/USBRequests.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDIdleRequest.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDKeypad.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDReportRequest.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/USBDCallbackInvocationFlowchart.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/USBDeviceStateDiagram.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/AUDDSpeakerDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/AUDDSpeakerDriver_Callbacks.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeaker.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeakerDescriptors.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeakerRecorder.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeakerRecorderDescriptors.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver_Callbacks.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDStream.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriverdescriptors.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerial.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver_Callbacks.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialPort.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCarchitecture.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/USB-SerialConverter.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/drv/6119.inf create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/AUDDFunction.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCAUDDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCHIDDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCMSDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/DUALCDCDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDAUDDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDMSDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcAudioArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcCdcArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcHidArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcMsdArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeComposition.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeHidAudioArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeHidMsdArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeMultiIF.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeRequestHandler.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeSWArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeSingleIF.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/composite/drv/CompositeCDCSerial.inf create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/core/USBD.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/core/USBDCallbacks.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriverCallbacks.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDClassArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboard.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardInputReport.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-mouse/HIDDMouseDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDFunction.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDTransferDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDAppArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDStateMachine.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriver.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverClasses.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverStates.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDFunction.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDIOFifo.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDLun.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDMediaArch.png create mode 100644 sam3s_example/atmel_softpack_libraries/usb/device/massstorage/SBCMethods.c create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/AUDDFunction.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhone.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhoneDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/AUDDStream.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/AUDDescriptors.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/AUDRequests.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCAUDDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerial.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialPort.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCDescriptors.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCHIDDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCMSDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCNotifications.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/CDCRequests.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/DUALCDCDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDAUDDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDDFunction.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboard.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboardDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDDMouseDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDDTransferDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDDescriptors.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDMSDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDReports.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDRequests.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/HIDUsages.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/MSD.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/MSDDStateMachine.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/MSDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/MSDFunction.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/MSDIOFifo.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/MSDLun.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/MSDescriptors.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/SBC.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/SBCMethods.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/USBD.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/USBDDriver.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/USBD_HAL.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/USBDescriptors.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Trace.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Types.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/include/USBRequests.h create mode 100644 sam3s_example/atmel_softpack_libraries/usb/lib/libusb_sam3s_gcc_dbg.a create mode 100644 sam3s_example/atmel_softpack_libraries/usb/lib/libusb_sam3s_gcc_rel.a create mode 100644 sam3s_example/atmel_softpack_libraries/usb/usb.h diff --git a/sam3s_example/atmel_softpack_libraries/usb/USBFrameworkArchitecture.png b/sam3s_example/atmel_softpack_libraries/usb/USBFrameworkArchitecture.png new file mode 100644 index 0000000000000000000000000000000000000000..83e77eb6534ed26df2f1fdee5ac3f120e35b343e GIT binary patch literal 5288 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 A%K!iX literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDFeatureUnitRequest.c b/sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDFeatureUnitRequest.c new file mode 100644 index 00000000..7911cb8a --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDFeatureUnitRequest.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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * This file implements functions for USB AUDIO class feature unit requests. + */ + +/** \addtogroup usb_audio + *@{ + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "AUDRequests.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_ctrl_sel USB Audio Control selector values + */ +uint8_t 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. + */ +uint8_t AUDFeatureUnitRequest_GetChannel(const USBGenericRequest *request) +{ + return (USBGenericRequest_GetValue(request) & 0xFF); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDGenericRequest.c b/sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDGenericRequest.c new file mode 100644 index 00000000..4a691afd --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/audio/AUDGenericRequest.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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * This file implements functions for USB AUDIO class requests. + */ + +/** \addtogroup usb_audio + *@{ + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "AUDRequests.h" + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * Returns the ID of the unit or terminal targetted by an USB audio request. + * \param request Pointer to a USBGenericRequest instance. + */ +uint8_t 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. + */ +uint8_t AUDGenericRequest_GetInterface(const USBGenericRequest *request) +{ + return (USBGenericRequest_GetIndex(request) & 0xFF); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCLineCoding.c b/sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCLineCoding.c new file mode 100644 index 00000000..0f28220d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCLineCoding.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/** \file + Implementation of the CDCLineCoding class. + */ +/** \addtogroup usb_cdc + *@{ + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------- + * 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 + * (\ref usb_cdc_stop CDC LineCoding StopBits). + * \param parity Parity check type + * (\ref usb_cdc_parity CDC LineCoding ParityChecking). + * \param databits Number of data bits. + */ +void CDCLineCoding_Initialize(CDCLineCoding *lineCoding, + uint32_t bitrate, + uint8_t stopbits, + uint8_t parity, + uint8_t databits) +{ + lineCoding->dwDTERate = bitrate; + lineCoding->bCharFormat = stopbits; + lineCoding->bParityType = parity; + lineCoding->bDataBits = databits; +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCSetControlLineStateRequest.c b/sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCSetControlLineStateRequest.c new file mode 100644 index 00000000..f11db275 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/cdc/CDCSetControlLineStateRequest.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * Implementation of the CDCSetControlLineStateRequest class. + */ + +/** \addtogroup usb_cdc + *@{ + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------- + * 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. + */ +uint8_t 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. + */ +uint8_t CDCSetControlLineStateRequest_ActivateCarrier( + const USBGenericRequest *request) +{ + if ((USBGenericRequest_GetValue(request) & 0x0002) != 0) { + + return 1; + } + else { + + return 0; + } +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/core/USBDescriptors.c b/sam3s_example/atmel_softpack_libraries/usb/common/core/USBDescriptors.c new file mode 100644 index 00000000..3811b5bb --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/core/USBDescriptors.c @@ -0,0 +1,310 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * Implements for USB descriptor methods described by the USB specification. + */ + +/** \addtogroup usb_descriptor + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "USBDescriptors.h" + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Returns the length of a descriptor. + * \param descriptor Pointer to a USBGenericDescriptor instance. + * \return Length of descriptor in bytes. + */ +uint32_t 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. + */ +uint8_t 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)); +} + +/** Parses the given descriptor list via costomized function. + * \param descriptor Pointer to the start of the whole descriptors list. + * \param totalLength Total size of descriptors in bytes. + * \param parseFunction Function to parse each descriptor scanned. + * Return 0 to continue parsing. + * \param parseArg Argument passed to parse function. + * \return Pointer to USBGenericDescriptor instance for next descriptor. + */ +USBGenericDescriptor *USBGenericDescriptor_Parse( + const USBGenericDescriptor *descriptor, + uint32_t totalLength, + USBDescriptorParseFunction parseFunction, + void *parseArg) +{ + int32_t size = totalLength; + + if (size == 0) + return 0; + + /* Start parsing descriptors */ + while (1) { + + uint32_t parseRC = 0; + + /* Parse current descriptor */ + if (parseFunction) { + + parseRC = parseFunction((void*)descriptor, parseArg); + } + + /* Get next descriptor */ + size -= USBGenericDescriptor_GetLength(descriptor); + descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor); + + if (size) { + if (parseRC != 0) { + + return (USBGenericDescriptor *)descriptor; + } + } + else + break; + } + /* No descriptors remaining */ + return 0; +} + + +/** + * Returns the number of an endpoint given its descriptor. + * \param endpoint Pointer to a USBEndpointDescriptor instance. + * \return Endpoint number. + */ +uint8_t 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 \ref usb_ep_dir). + */ +uint8_t 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 \ref usb_ep_type). + */ +uint8_t 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. + */ +uint16_t 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. + */ +uint8_t USBEndpointDescriptor_GetInterval( + const USBEndpointDescriptor *endpoint) +{ + return endpoint->bInterval; +} + + + +/** 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. + */ +uint32_t 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/sam3s_example/atmel_softpack_libraries/usb/common/core/USBRequests.c b/sam3s_example/atmel_softpack_libraries/usb/common/core/USBRequests.c new file mode 100644 index 00000000..b70d68eb --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/core/USBRequests.c @@ -0,0 +1,244 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * Implements for USB requests described by the USB specification. + */ + +/** \addtogroup usb_request + * @{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Returns the type of the given request. + * \param request Pointer to a USBGenericRequest instance. + * \return "USB Request Types" + */ +extern uint8_t 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" + */ +uint8_t 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. + */ +uint16_t 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; + */ +uint16_t 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. + */ +uint16_t 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. + */ +uint8_t 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" + */ +uint8_t 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" + */ +uint8_t 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; + } +} + + +/** + * 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. + */ +uint8_t 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. + */ +uint8_t USBGetDescriptorRequest_GetDescriptorIndex( + const USBGenericRequest *request) +{ + /* Requested descriptor index if in the low byte of the wValue field */ + return USBGenericRequest_GetValue(request) & 0xFF; +} + + +/** + * 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. + */ +uint8_t USBSetAddressRequest_GetAddress(const USBGenericRequest *request) +{ + return USBGenericRequest_GetValue(request) & 0x7F; +} + + +/** + * 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. + */ +uint8_t USBSetConfigurationRequest_GetConfiguration( + const USBGenericRequest *request) +{ + return USBGenericRequest_GetValue(request); +} + + +/** + * Indicates which interface is targetted by a GET_INTERFACE or + * SET_INTERFACE request. + * \param request Pointer to a USBGenericRequest instance. + * \return Interface number. + */ +uint8_t 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. + */ +uint8_t USBInterfaceRequest_GetAlternateSetting( + const USBGenericRequest *request) +{ + return (USBGenericRequest_GetValue(request) & 0xFF); +} + + +/** + * Returns the feature selector of a given CLEAR_FEATURE or SET_FEATURE + * request. + * \param request Pointer to a USBGenericRequest instance. + * \return Feature selector. + */ +uint8_t 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. + */ +uint8_t USBFeatureRequest_GetTestSelector( + const USBGenericRequest *request) +{ + return (USBGenericRequest_GetIndex(request) >> 8) & 0xFF; +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDIdleRequest.c b/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDIdleRequest.c new file mode 100644 index 00000000..c4e83e13 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDIdleRequest.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/**\file + Title: HIDIdleRequest implementation + + About: Purpose + Implementation of the HIDIdleRequest methods. +*/ + +/**\addtogroup usb_hid + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "HIDRequests.h" + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Indicates the ID of the report targetted by a SET_IDLE or GET_IDLE + * request. This value should be 0 if report IDs are not used. + * \param request Pointer to a USBGenericRequest instance. + * \return Requested report ID. + */ +uint8_t HIDIdleRequest_GetReportId(const USBGenericRequest *request) +{ + return (USBGenericRequest_GetValue(request) & 0xFF); +} + +/** + * 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. + */ +uint8_t HIDIdleRequest_GetIdleRate(const USBGenericRequest *request) +{ + return ((USBGenericRequest_GetValue(request) >> 8) & 0xFF); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDKeypad.c b/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDKeypad.c new file mode 100644 index 00000000..898c1a6c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDKeypad.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/**\file + Title: HIDKeypad implementation + + About: Purpose + Implementation of HID keypad usage page methods. +*/ + +/**\addtogroup usb_hid + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "HIDUsages.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. + */ +uint8_t HIDKeypad_IsModifierKey(uint8_t key) +{ + return ((key >= HIDKeypad_LEFTCONTROL) && (key <= HIDKeypad_RIGHTGUI)); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDReportRequest.c b/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDReportRequest.c new file mode 100644 index 00000000..4f1e8e99 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/common/hid/HIDReportRequest.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/**\file + Title: HIDReportRequest implementation + + About: Purpose + Implementation of the HIDReportRequest methods. +*/ + +/**\addtogroup usb_hid + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "HIDRequests.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"). + */ +uint8_t 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. + */ +uint8_t HIDReportRequest_GetReportId(const USBGenericRequest *request) +{ + return (USBGenericRequest_GetValue(request) & 0xFF); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/USBDCallbackInvocationFlowchart.png b/sam3s_example/atmel_softpack_libraries/usb/device/USBDCallbackInvocationFlowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..af8028e16a1e8fb8e10b4984637cb78b5fa63a90 GIT binary patch literal 11380 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/USBDeviceStateDiagram.png b/sam3s_example/atmel_softpack_libraries/usb/device/USBDeviceStateDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..eacdd41d40bc3d6ecf8460cf5910841dc5a257a2 GIT binary patch literal 8827 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 + +#include + +#include + +#include + +#include +#include +#include + +/*---------------------------------------------------------------------------- + * Internal types + *----------------------------------------------------------------------------*/ + +/** + * \brief Audio speaker driver struct. + */ +typedef struct _AUDDSpeakerDriver { + /** Speaker & Phone function */ + AUDDSpeakerPhone fun; + /** Stream instance for speaker */ + AUDDStream speaker; + /** Array for storing the current setting of each interface */ + uint8_t bAltInterfaces[AUDDSpeakerDriver_NUMINTERFACES]; +} AUDDSpeakerDriver; + +/*---------------------------------------------------------------------------- + * Internal variables + *----------------------------------------------------------------------------*/ + +/** Global USB audio speaker driver instance. */ +static AUDDSpeakerDriver auddSpeakerDriver; + +/*---------------------------------------------------------------------------- + * Dummy callbacks + *----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Internal functions + *----------------------------------------------------------------------------*/ + +/** + * Callback triggerred after the mute or volume status of the channel has been + * changed. + * \param ec Event code. + * \param channel Channel number. + * \param pArg Pointer to AUDDStream instance. + */ +static void AUDDSpeaker_EventCallback(uint32_t ec, + uint8_t channel, + AUDDStream *pArg) +{ + if (ec == AUDD_EC_MuteChanged) { + if (AUDDSpeakerDriver_MuteChanged) + AUDDSpeakerDriver_MuteChanged(channel, pArg->bmMute); + } + else if (ec == AUDD_EC_VolumeChanged) { + /* Not supported now */ + } +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * Initializes an USB audio speaker device driver, as well as the underlying + * USB controller. + */ +void AUDDSpeakerDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + AUDDSpeakerDriver *pAudd = &auddSpeakerDriver; + AUDDSpeakerPhone *pAudf = &pAudd->fun; + AUDDStream *pAuds = &pAudd->speaker; + USBDDriver *pUsbd = USBD_GetDriver(); + + AUDDSpeakerPhone_InitializeStream( + pAuds, AUDDSpeakerDriver_NUMCHANNELS, 0, + (AUDDStreamEventCallback)AUDDSpeaker_EventCallback, pAuds); + + AUDDSpeakerPhone_Initialize( + pAudf, pUsbd, pAuds, 0); + + /* Initialize the USB driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + pAudd->bAltInterfaces); + USBD_Init(); +} + +/** + * Invoked whenever the active configuration of device is changed by the + * host. + * \param cfgnum Configuration number. + */ +void AUDDSpeakerDriver_ConfigurationChangeHandler(uint8_t cfgnum) +{ + AUDDSpeakerDriver *pAudd = &auddSpeakerDriver; + AUDDSpeakerPhone *pAudf = &pAudd->fun; + const USBDDriverDescriptors *pDescriptors = pAudf->pUsbd->pDescriptors; + USBConfigurationDescriptor *pDesc; + + if (cfgnum > 0) { + + /* Parse endpoints for data & notification */ + if (USBD_HAL_IsHighSpeed() && pDescriptors->pHsConfiguration) + pDesc = (USBConfigurationDescriptor*)pDescriptors->pHsConfiguration; + else + pDesc = (USBConfigurationDescriptor*)pDescriptors->pFsConfiguration; + + AUDDSpeakerPhone_ParseInterfaces(pAudf, + (USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * 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 AUDDSpeakerDriver_InterfaceSettingChangedHandler(uint8_t interface, + uint8_t setting) +{ + AUDDSpeakerDriver *pSpeakerd = &auddSpeakerDriver; + AUDDSpeakerPhone *pAudf = &pSpeakerd->fun; + + if (setting == 0) { + AUDDSpeakerPhone_CloseStream(pAudf, interface); + } + + if (AUDDSpeakerDriver_StreamSettingChanged) + AUDDSpeakerDriver_StreamSettingChanged(setting); +} + +/** + * 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) +{ + AUDDSpeakerDriver *pAudd = &auddSpeakerDriver; + AUDDSpeakerPhone *pAudf = &pAudd->fun; + USBDDriver *pUsbd = pAudf->pUsbd; + + TRACE_INFO_WP("NewReq "); + + /* Handle Audio Class requests */ + if (AUDDSpeakerPhone_RequestHandler(pAudf, request) == USBRC_SUCCESS) { + return; + } + + /* Handle STD requests */ + if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) { + + USBDDriver_RequestHandler(pUsbd, request); + } + /* Unsupported request */ + else { + + TRACE_WARNING( + "AUDDSpeakerDriver_RequestHandler: Unsupported request (%d,%x)\n\r", + USBGenericRequest_GetType(request), + USBGenericRequest_GetRequest(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. + */ +uint8_t AUDDSpeakerDriver_Read(void *buffer, + uint32_t length, + TransferCallback callback, + void *argument) +{ + AUDDSpeakerDriver *pAudd = &auddSpeakerDriver; + AUDDSpeakerPhone *pAudf = &pAudd->fun; + return USBD_Read(pAudf->pSpeaker->bEndpointOut, + buffer, length, + callback, argument); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/AUDDSpeakerDriver_Callbacks.c b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/AUDDSpeakerDriver_Callbacks.c new file mode 100644 index 00000000..5f2cec73 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/AUDDSpeakerDriver_Callbacks.c @@ -0,0 +1,74 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Default callbacks implement for Audio Speaker Driver. + */ + +/** \addtogroup usbd_audio_speaker + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 + by working group ISO/IEC JTC1/SC22/WG14. */ +#include + +#include "AUDDSpeakerDriver.h" + +/*------------------------------------------------------------------------------ + * Default WEAK Callbacks + *------------------------------------------------------------------------------*/ + +/** + * Invoked when an audio channel get muted or unmuted. Mutes/unmutes the + * channel at the DAC level. + * \param channel Channel number that changed. + * \param muted Indicates the new mute status of the channel. + */ +WEAK void AUDDSpeakerDriver_MuteChanged(uint8_t channel,uint8_t muted) +{ + /* Do nothing */ +} + +/** + * Invoked when an audio streaming interface setting changed. Actually control + * streaming rate. + * \param newSetting New stream (interface) setting. + */ +WEAK void AUDDSpeakerDriver_StreamSettingChanged(uint8_t newSetting) +{ + /* Do nothing */ +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeaker.png b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeaker.png new file mode 100644 index 0000000000000000000000000000000000000000..bcae3009ebab2b8a9a90690f58cb7f0401e70510 GIT binary patch literal 3711 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeakerDescriptors.png b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeakerDescriptors.png new file mode 100644 index 0000000000000000000000000000000000000000..251a2d1c579e1a501493ea4eef7b68b6fd552cb8 GIT binary patch literal 8026 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 Dxl7dB literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeakerRecorder.png b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speaker/USBAudioSpeakerRecorder.png new file mode 100644 index 0000000000000000000000000000000000000000..ddbd2349a649ab367f1bcb74694c3da44aba551c GIT binary patch literal 5053 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 Ab^rhX literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver.c new file mode 100644 index 00000000..e2893fb9 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver.c @@ -0,0 +1,468 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_audio_speakerphone + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include + +#include + +/*------------------------------------------------------------------------------ + * Internal types + *------------------------------------------------------------------------------*/ + +/** + * Structs of USB Audio Stream Function Interface. + */ +typedef struct _AUDDStream { + + /* -- USB Interface settings -- */ + /** Audio Control Interface Number */ + uint8_t bAcInterface; + /** Audio Streaming Interface Number */ + uint8_t bAsInterface; + /** Audio Streaming endpoint address */ + uint8_t bEpNum; + /** Audio Control Unit ID */ + uint8_t bUnitID; + + /* -- Channel settings -- */ + /** Number of channels (including master 0, max 32) */ + uint16_t bNumChannels; + /** Mute Controls bitmap */ + uint16_t bmMuteControls; + /** Volume Controls (Master,L,R..) array */ + uint16_t *pVolumes; +} AUDDStream; + +/** + * \brief Audio SpeakerPhone driver internal state. + */ +typedef struct _AUDDSpeakerPhoneDriver { + + /** Pointer to USBDDriver instance */ + USBDDriver * pUsbd; + /** Intermediate storage variable for the mute status of a stream */ + uint8_t muted; + /** Array for storing the current setting of each interface. */ + uint8_t interfaces[3]; + /** Audio Speaker interface */ + AUDDStream speaker; + /** Audio Microphone interface */ + AUDDStream mic; +} AUDDSpeakerPhoneDriver; + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/** Global USB audio SpeakerPhone driver instance. */ +static AUDDSpeakerPhoneDriver auddSpeakerPhoneDriver; + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/** + * Parse descriptors: Interrupt IN, Bulk EP IN/OUT. + * \param desc Pointer to descriptor. + * \param arg Argument, pointer to AUDDSpeakerPhoneDriver instance. + */ +static uint32_t AUDDSpeakerPhone_Parse(USBGenericDescriptor* desc, + AUDDSpeakerPhoneDriver* arg) +{ + /* Not a valid descriptor */ + if (desc->bLength == 0) { + return USBD_STATUS_INVALID_PARAMETER; + } + /* Parse endpoint descriptor */ + if (desc->bDescriptorType == USBGenericDescriptor_ENDPOINT) { + USBEndpointDescriptor *pEP = (USBEndpointDescriptor*)desc; + if (pEP->bmAttributes == USBEndpointDescriptor_ISOCHRONOUS) { + if (pEP->bEndpointAddress & 0x80) + arg->mic.bEpNum = pEP->bEndpointAddress & 0x7F; + else + arg->speaker.bEpNum = pEP->bEndpointAddress; + } + } + return 0; +} + +/** + * Callback triggered after the new mute status of a channel has been read + * by AUDDSpeakerPhoneDriver_SetFeatureCurrentValue. Changes the mute status + * of the given channel accordingly. + * \param channel Number of the channel whose mute status has changed. + */ +static void AUDDSpeakerPhone_MuteReceived(uint32_t channel) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + AUDDStream *pAuds; + + if ((uint8_t)(channel >> 8) == + AUDDSpeakerPhoneDriverDescriptors_OUTPUTTERMINAL_REC) { + pAuds = &pAudd->mic; + } + else { + pAuds = &pAudd->speaker; + } + + if (pAudd->muted != pAuds->bmMuteControls) { + pAuds->bmMuteControls = pAudd->muted; + AUDDSpeakerPhoneDriver_MuteChanged(0, channel, pAudd->muted); + } + USBD_Write(0, 0, 0, 0, 0); +} + +/** + * Handle the SET_CUR request. + * \param pReq Pointer to USBGenericRequest instance. + */ +static void AUDDSpeakerPhone_SetCUR(const USBGenericRequest* pReq) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + uint8_t bIf = AUDGenericRequest_GetInterface(pReq); + uint8_t bEntity = AUDGenericRequest_GetEntity(pReq); + uint8_t bLength = USBGenericRequest_GetLength(pReq); + uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq); + uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq); + uint8_t bSet = 0; + AUDDStream *pAuds = 0; + + TRACE_INFO_WP("sCUR "); + TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength); + /* Only AC.FeatureUnit accepted */ + if (bCtrl == AUDFeatureUnitRequest_MUTE + && bLength == 1) { + + if (bEntity == pAudd->speaker.bUnitID) + pAuds = &pAudd->speaker; + else if (bEntity == pAudd->mic.bUnitID) + pAuds = &pAudd->mic; + + if (pAuds != 0 + && bIf == pAuds->bAcInterface + && bCh <= pAuds->bNumChannels) { + bSet = 1; + } + } + + if (bSet) { + + uint32_t argument = bCh | (bEntity << 8); + USBD_Read(0, /* Endpoint #0 */ + &pAudd->muted, + sizeof(uint8_t), + (TransferCallback) AUDDSpeakerPhone_MuteReceived, + (void *) argument); + } + else { + + USBD_Stall(0); + } + +} + +/** + * Handle the GET_CUR request. + * \param pReq Pointer to USBGenericRequest instance. + */ +static void AUDDSpeakerPhone_GetCUR(const USBGenericRequest *pReq) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + uint8_t bIf = AUDGenericRequest_GetInterface(pReq); + uint8_t bEntity = AUDGenericRequest_GetEntity(pReq); + uint8_t bLength = USBGenericRequest_GetLength(pReq); + uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq); + uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq); + uint8_t bGet = 0; + AUDDStream *pAuds = 0; + + TRACE_INFO_WP("gCUR "); + TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength); + /* Only AC.FeatureUnit accepted */ + if (bCtrl == AUDFeatureUnitRequest_MUTE + && bLength == 1) { + + if (bEntity == pAudd->speaker.bUnitID) + pAuds = &pAudd->speaker; + else if (bEntity == pAudd->mic.bUnitID) + pAuds = &pAudd->mic; + + if (pAuds != 0 + && bIf == pAuds->bAcInterface + && bCh <= pAuds->bNumChannels) { + bGet = 1; + } + } + + if (bGet) { + + pAudd->muted = pAuds->bmMuteControls; + USBD_Write(0, &pAudd->muted, sizeof(uint8_t), 0, 0); + } + else { + + USBD_Stall(0); + } +} + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes an USB audio SpeakerPhone device driver, as well as the underlying + * USB controller. + */ +void AUDDSpeakerPhoneDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + USBDDriver *pUsbd = USBD_GetDriver(); + + pAudd->pUsbd = pUsbd; + + /* Initialize SpeakerPhone channels */ + pAudd->speaker.bNumChannels = 3; + pAudd->speaker.bmMuteControls = 0; + pAudd->speaker.pVolumes = 0; + + pAudd->mic.bNumChannels = 1; + pAudd->mic.bmMuteControls = 0; + pAudd->mic.pVolumes = 0; + + pAudd->mic.bAcInterface = AUDDSpeakerPhoneDriverDescriptors_CONTROL; + pAudd->mic.bAsInterface = AUDDSpeakerPhoneDriverDescriptors_STREAMINGIN; + pAudd->mic.bEpNum = 5;//AUDDSpeakerPhoneDriverDescriptors_DATAIN; + pAudd->mic.bUnitID = AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT_REC; + + pAudd->speaker.bAcInterface = AUDDSpeakerPhoneDriverDescriptors_CONTROL; + pAudd->speaker.bAsInterface = AUDDSpeakerPhoneDriverDescriptors_STREAMING; + pAudd->speaker.bEpNum = 4;//AUDDSpeakerPhoneDriverDescriptors_DATAOUT; + pAudd->speaker.bUnitID = AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT; + + /* Initialize the USB driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + pAudd->interfaces); + USBD_Init(); + +} + +/** + * Invoked whenever the active configuration of device is changed by the + * host. + * \param cfgnum Configuration number. + */ +void AUDDSpeakerPhoneDriver_ConfigurationChangeHandler(uint8_t cfgnum) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + const USBDDriverDescriptors *pDescriptors = pAudd->pUsbd->pDescriptors; + USBConfigurationDescriptor *pDesc; + + if (cfgnum > 0) { + + /* Parse endpoints for data & notification */ + if (USBD_HAL_IsHighSpeed() && pDescriptors->pHsConfiguration) + pDesc = (USBConfigurationDescriptor*)pDescriptors->pHsConfiguration; + else + pDesc = (USBConfigurationDescriptor*)pDescriptors->pFsConfiguration; + + USBGenericDescriptor_Parse((USBGenericDescriptor*)pDesc, pDesc->wTotalLength, + (USBDescriptorParseFunction)AUDDSpeakerPhone_Parse, pAudd); + } +} + +/** + * 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 AUDDSpeakerPhoneDriver_InterfaceSettingChangedHandler(uint8_t interface, + uint8_t setting) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + + if (interface == pAudd->speaker.bAsInterface) { + /* reset ISO OUT ep */ + if (setting == 0 && pAudd->speaker.bEpNum) { + USBD_HAL_ResetEPs(1 << pAudd->speaker.bEpNum, + USBD_STATUS_CANCELED, 1); + } + AUDDSpeakerPhoneDriver_StreamSettingChanged(0, setting); + } + if (interface == pAudd->mic.bAsInterface) { + /* reset ISO IN ep */ + if (setting == 0 && pAudd->mic.bEpNum) { + USBD_HAL_ResetEPs(1 << pAudd->mic.bEpNum, + USBD_STATUS_CANCELED, 1); + } + AUDDSpeakerPhoneDriver_StreamSettingChanged(1, setting); + } +} + + +/** + * 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 AUDDSpeakerPhoneDriver_RequestHandler(const USBGenericRequest *request) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + USBDDriver *pUsbd = pAudd->pUsbd; + + 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: + + AUDDSpeakerPhone_SetCUR(request); + break; + + case AUDGenericRequest_GETCUR: + + AUDDSpeakerPhone_GetCUR(request); + break; + + default: + + TRACE_WARNING( + "AUDDSpeakerPhoneDriver_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(pUsbd, request); + } + /* Unsupported request type */ + else { + + TRACE_WARNING( + "AUDDSpeakerPhoneDriver_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. + */ +uint8_t AUDDSpeakerPhoneDriver_Read(void *buffer, + uint32_t length, + TransferCallback callback, + void *argument) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + return USBD_Read(pAudd->speaker.bEpNum, + buffer, + length, + callback, + argument); +} + +/** + * Initialize Frame List for sending audio data. + * + * \param pListInit Pointer to the allocated list for audio write. + * \param pDmaInit Pointer to the allocated DMA descriptors for autio write + * (if DMA supported). + * \param listSize Circular list size. + * \param delaySize Start transfer after delaySize frames filled in. + * \param callback Optional callback function for transfer. + * \param argument Optional callback argument. + * \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code. + */ +uint8_t AUDDSpeakerPhoneDriver_SetupWrite(void * pListInit, + void * pDmaInit, + uint16_t listSize, + uint16_t delaySize, + TransferCallback callback, + void * argument) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + uint8_t error; + + if (pAudd->mic.bEpNum == 0) + return USBRC_STATE_ERR; + + error = USBD_HAL_SetupMblTransfer(pAudd->mic.bEpNum, + pListInit, + listSize, + delaySize); + if (error) return error; + error = USBD_HAL_SetTransferCallback( + pAudd->mic.bEpNum, + callback, argument); + return error; +} + +/** + * Add frame buffer to audio sending list. + * \buffer Pointer to data frame to send. + * \length Frame size in bytes. + * \return USBD_STATUS_SUCCESS if the transfer is started successfully; + * otherwise an error code. + */ +uint8_t AUDDSpeakerPhoneDriver_Write(void* buffer, uint16_t length) +{ + AUDDSpeakerPhoneDriver *pAudd = &auddSpeakerPhoneDriver; + + return USBD_HAL_Write(pAudd->mic.bEpNum, + buffer, length); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver_Callbacks.c b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver_Callbacks.c new file mode 100644 index 00000000..ee061f92 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDSpeakerPhoneDriver_Callbacks.c @@ -0,0 +1,76 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Default callbacks implement for Audio SpeakerPhone Driver. + */ + +/** \addtogroup usbd_audio_speakerphone + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 + by working group ISO/IEC JTC1/SC22/WG14. */ +#include + +#include "AUDDSpeakerPhoneDriver.h" + +/*------------------------------------------------------------------------------ + * Default WEAK Callbacks + *------------------------------------------------------------------------------*/ + +/** + * Invoked when an audio channel get muted or unmuted. Mutes/unmutes the + * channel at the DAC level. + * \param mic Microphone/Speaker stream changed. + * \param channel Channel number that changed. + * \param muted Indicates the new mute status of the channel. + */ +WEAK void AUDDSpeakerPhoneDriver_MuteChanged(uint8_t mic,uint8_t channel,uint8_t muted) +{ + /* Do nothing */ +} + +/** + * Invoked when an audio streaming interface setting changed. Actually control + * streaming rate. + * \param mic Microphone/Speaker stream changed. + * \param newSetting New stream (interface) setting. + */ +WEAK void AUDDSpeakerPhoneDriver_StreamSettingChanged(uint8_t mic,uint8_t newSetting) +{ + /* Do nothing */ +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDStream.c b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDStream.c new file mode 100644 index 00000000..07c76ca8 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/audio-speakerphone/AUDDStream.c @@ -0,0 +1,770 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * USB Audio Device Streaming interface with controls. + * (3 channels supported). + */ + +/** \addtogroup usbd_audio_speakerphone + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include +#include +#include +#include + +#include + +#include + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** Parse data extention for descriptor parsing */ +typedef struct _AUDDParseData { + /** Pointer to AUDDSpeakerPhone instance */ + AUDDSpeakerPhone * pAudf; + /** Pointer to found interface descriptor */ + USBInterfaceDescriptor * pIfDesc; + +} AUDDParseData; + +/** Transfer callback extention */ +typedef struct _AUDDXfrExt { + /** Pointer to AUDDStream instance */ + AUDDStream *pStream; + /** Buffer for USB device to get data from host */ + uint16_t usbBuffer; + /** Additional information: Entity */ + uint8_t bEntity; + /** Additional information: Channel */ + uint8_t bCh; +} AUDDXfrExt; + +/*------------------------------------------------------------------------------ + * Internal Variable + *------------------------------------------------------------------------------*/ + +/** Transfer data extension */ +static AUDDXfrExt auddXfrData; + +/*------------------------------------------------------------------------------ + * Internal Functions + *------------------------------------------------------------------------------*/ + +/** + * Parse descriptors: Interface, ISO IN/OUT, Feature Unit IDs. + * \param desc Pointer to descriptor list. + * \param arg Argument, pointer to AUDDParseData instance. + */ +static uint32_t AUDDSpeakerPhone_Parse(USBGenericDescriptor *pDesc, + AUDDParseData * pArg) +{ + AUDDStream *pSpeaker = pArg->pAudf->pSpeaker; + AUDDStream *pMic = pArg->pAudf->pMicrophone; + USBEndpointDescriptor* pEp = (USBEndpointDescriptor*)pDesc; + uint8_t bSpeakerDone = 0, bMicDone = 0; + + /* Validate descriptor */ + if (pDesc->bLength == 0) + return USBRC_PARAM_ERR; + + /* Log current interface */ + if (pDesc->bDescriptorType == USBGenericDescriptor_INTERFACE) { + USBInterfaceDescriptor* pIf = (USBInterfaceDescriptor*)pDesc; + /* AudioControl interface */ + if (pIf->bInterfaceClass == + AUDControlInterfaceDescriptor_CLASS + && pIf->bInterfaceSubClass == + AUDControlInterfaceDescriptor_SUBCLASS) { + pArg->pIfDesc = pIf; + + if (pSpeaker) pSpeaker->bAcInterface = pIf->bInterfaceNumber; + if (pMic) pMic->bAcInterface = pIf->bInterfaceNumber; + } + /* AudioStreaming interface with endpoint */ + else if (pIf->bInterfaceClass == + AUDStreamingInterfaceDescriptor_CLASS + && pIf->bInterfaceSubClass == + AUDStreamingInterfaceDescriptor_SUBCLASS) { + pArg->pIfDesc = pIf; + } + /* Not Audio interface, force end */ + else if (pArg->pIfDesc){ + return USBRC_PARTIAL_DONE; + } + } + + if (pArg->pIfDesc) { + /* Find Control Interface */ + /* Find Entities */ + /* Find Streaming Interface & Endpoints */ + if (pDesc->bDescriptorType == USBGenericDescriptor_ENDPOINT + && (pEp->bmAttributes & 0x3) == USBEndpointDescriptor_ISOCHRONOUS) { + if (pEp->bEndpointAddress & 0x80 + && pMic) { + pMic->bEndpointIn = pEp->bEndpointAddress & 0x7F; + pMic->bAsInterface = pArg->pIfDesc->bInterfaceNumber; + /* Fixed FU */ + pMic->bFeatureUnitIn = AUDD_ID_MicrophoneFU; + } + else if (pSpeaker) { + pSpeaker->bEndpointOut = pEp->bEndpointAddress; + pSpeaker->bAsInterface = pArg->pIfDesc->bInterfaceNumber; + /* Fixed FU */ + pSpeaker->bFeatureUnitOut = AUDD_ID_SpeakerFU; + } + } + } + + if (pSpeaker) { + if (pSpeaker->bAcInterface != 0xFF + && pSpeaker->bAsInterface != 0xFF + && pSpeaker->bFeatureUnitOut != 0xFF + && pSpeaker->bEndpointOut != 0) { + bSpeakerDone = 1; + } + } + else bSpeakerDone = 1; + + if (pMic) { + if (pMic->bAcInterface != 0xFF + && pMic->bAsInterface != 0xFF + && pMic->bFeatureUnitIn != 0xFF + && pMic->bEndpointIn != 0) { + bMicDone = 1; + } + } + else bMicDone = 1; + + if (bSpeakerDone && bMicDone) + return USBRC_FINISHED; + + return USBRC_SUCCESS; +} + +/** + * Callback triggered after the new mute status of a channel has been read. + * Changes the mute status of the given channel accordingly. + * \param pData Pointer to AUDDXfrExt (transfer extension data). + */ +static void AUDD_MuteReceived(AUDDXfrExt *pData) +{ + AUDDStream_ChangeMute(pData->pStream, + pData->bCh, + (uint8_t)pData->usbBuffer); + USBD_Write(0, 0, 0, 0, 0); +} + +/** + * Callback triggered after the new volume status of a channel has been read. + * Changes the volume status of the given channel accordingly. + * \param pData Pointer to AUDDXfrExt (transfer extension data). + */ +static void AUDD_VolumeReceived(AUDDXfrExt *pData) +{ + AUDDStream_SetVolume(pData->pStream, + pData->bCh, + pData->usbBuffer); + USBD_Write(0, 0, 0, 0, 0); +} + +/** + * Get Target AUDDStream for control + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param bAcInterface Interface number + * \param bEntity Entity ID + * \param bChannel Channel number + * \return Pointer to AUDDStream instance + */ +static AUDDStream *AUDD_GetCtlStream( + AUDDSpeakerPhone *pAudf, + uint8_t bAcInterface, + uint8_t bEntity, + uint8_t bChannel) +{ + AUDDStream *pAuds = 0; + + if (bEntity == pAudf->pSpeaker->bFeatureUnitOut + || bEntity == pAudf->pSpeaker->bFeatureUnitIn) + pAuds = pAudf->pSpeaker; + else if (bEntity == pAudf->pMicrophone->bFeatureUnitIn + || bEntity == pAudf->pMicrophone->bFeatureUnitOut) + pAuds = pAudf->pMicrophone; + + if (pAuds != 0 + && bAcInterface == pAuds->bAcInterface + && bChannel <= pAuds->bNumChannels) { + return pAuds; + } + + return 0; +} + +/** + * Handle the SET_CUR request. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pReq Pointer to USBGenericRequest instance. + */ +static void AUDD_SetCUR( + AUDDSpeakerPhone *pAudf, + const USBGenericRequest* pReq) +{ + uint8_t bIf = AUDGenericRequest_GetInterface(pReq); + uint8_t bEntity = AUDGenericRequest_GetEntity(pReq); + uint8_t bLength = USBGenericRequest_GetLength(pReq); + uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq); + uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq); + uint8_t bSet = 1; + AUDDStream *pAuds = AUDD_GetCtlStream(pAudf, bIf, bEntity, bCh); + TransferCallback fCallback; + + TRACE_INFO_WP("sCUR "); + TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength); + + /* Set Mute to AC, 1 byte */ + if (bCtrl == AUDFeatureUnitRequest_MUTE + && bLength == 1 + && pAuds) { + fCallback = (TransferCallback) AUDD_MuteReceived; + } + else if (bCtrl == AUDFeatureUnitRequest_VOLUME + && bLength == 2 + && pAuds && pAuds->pwVolumes) { + fCallback = (TransferCallback) AUDD_VolumeReceived; + } + else + bSet = 0; + + if (bSet) { + + auddXfrData.pStream = pAuds; + auddXfrData.bEntity = bEntity; + auddXfrData.bCh = bCh; + USBD_Read(0, + &auddXfrData.usbBuffer, + bLength, + fCallback, + (void *) &auddXfrData); + } + else { + + USBD_Stall(0); + } + +} + +/** + * Handle the GET_CUR request. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pReq Pointer to USBGenericRequest instance. + */ +static void AUDD_GetCUR( + AUDDSpeakerPhone *pAudf, + const USBGenericRequest *pReq) +{ + uint8_t bIf = AUDGenericRequest_GetInterface(pReq); + uint8_t bEntity = AUDGenericRequest_GetEntity(pReq); + uint8_t bLength = USBGenericRequest_GetLength(pReq); + uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq); + uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq); + uint8_t bGet = 1; + AUDDStream *pAuds = AUDD_GetCtlStream(pAudf, bIf, bEntity, bCh); + + TRACE_INFO_WP("gCUR "); + TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength); + + /* Get Mute 1 byte */ + if (bCtrl == AUDFeatureUnitRequest_MUTE + && bLength == 1 + && pAuds) { + auddXfrData.usbBuffer = ((pAuds->bmMute & (1< 0); + } + else if (bCtrl == AUDFeatureUnitRequest_VOLUME + && bLength == 2 + && pAuds && pAuds->pwVolumes) { + auddXfrData.usbBuffer = pAuds->pwVolumes[bCh]; + } + else + bGet = 0; + + if (bGet) { + + USBD_Write(0, &auddXfrData.usbBuffer, bLength, 0, 0); + } + else { + + USBD_Stall(0); + } +} + +/*------------------------------------------------------------------------------ + * Exported Functions + *------------------------------------------------------------------------------*/ + +/** + * Initialize AUDDStream instance. + * Note the number of channels excludes the master control, so + * actual volume array size should be (1 + numChannels). + * \param pAuds Pointer to AUDDStream instance. + * \param numChannels Number of channels in the stream (<31). + * \param wChannelVolumes Data array for channel volume values. + * \param fCallback Callback function for stream events. + * \param pArg Pointer to event handler arguments. + */ +void AUDDStream_Initialize(AUDDStream *pAuds, + uint8_t numChannels, + uint16_t wChannelVolumes[], + AUDDStreamEventCallback fCallback, + void* pArg) +{ + pAuds->bAcInterface = 0xFF; + pAuds->bFeatureUnitOut = 0xFF; + pAuds->bFeatureUnitIn = 0xFF; + pAuds->bAsInterface = 0xFF; + pAuds->bEndpointOut = 0; + pAuds->bEndpointIn = 0; + + pAuds->bNumChannels = numChannels; + pAuds->bmMute = 0; + pAuds->pwVolumes = wChannelVolumes; + + pAuds->fCallback = fCallback; + pAuds->pArg = pArg; +} + +/** + * Check if the request is accepted. + * \param pAuds Pointer to AUDDStream instance. + * \param pReq Pointer to a USBGenericRequest instance. + * \return 1 if accepted. + */ +uint32_t AUDDStream_IsRequestAccepted( + AUDDStream *pAuds, + const USBGenericRequest *pReq) +{ + uint8_t bIf = AUDGenericRequest_GetInterface(pReq); + uint8_t bEntity = AUDGenericRequest_GetEntity(pReq); + uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq); + /* AudioControl Interface */ + if (bIf == pAuds->bAcInterface) { + if (bCh > pAuds->bNumChannels) + return 0; + if (bEntity != pAuds->bFeatureUnitIn + && bEntity != pAuds->bFeatureUnitOut) + return 0; + } + /* AudioStream Interface not handled */ + else { + return 0; + } + return 1; +} + +/** + * Change Stream Mute status. + * \param pAuds Pointer to AUDDStream instance. + * \param bChannel Channel number. + * \param bmMute 1 to mute, 0 to unmute. + */ +uint32_t AUDDStream_ChangeMute(AUDDStream *pAuds, + uint8_t bChannel, + uint8_t bMute) +{ + uint8_t bmMute = (bMute << bChannel); + + if (pAuds->bNumChannels < bChannel) + return USBRC_PARAM_ERR; + + if (bMute) + pAuds->bmMute |= bmMute; + else + pAuds->bmMute &= ~bmMute; + + if (pAuds->fCallback) + pAuds->fCallback(AUDD_EC_MuteChanged, + bChannel, + pAuds->pArg); + + return USBRC_SUCCESS; +} + +/** + * Set Stream Volume status. + * \param pAuds Pointer to AUDDStream instance. + * \param bChannel Channel number. + * \param wVolume New volume value. + */ +uint32_t AUDDStream_SetVolume(AUDDStream *pAuds, + uint8_t bChannel, + uint16_t wVolume) +{ + if (pAuds->pwVolumes == 0) + return USBRC_PARAM_ERR; + if (bChannel > pAuds->bNumChannels) + return USBRC_PARAM_ERR; + + pAuds->pwVolumes[bChannel] = wVolume; + if (pAuds->fCallback) { + pAuds->fCallback(AUDD_EC_VolumeChanged, + bChannel, + pAuds->pArg); + } + + return USBRC_SUCCESS; +} + +/** + * Receives data from the host through the audio function (as speaker). + * This function behaves like USBD_Read. + * \param pAuds Pointer to AUDDStream instance. + * \param pData Pointer to the data buffer to put received data. + * \param dwSize Size of the data buffer in bytes. + * \param fCallback Optional callback function to invoke when the transfer + * finishes. + * \param pArg Optional argument to the callback function. + * \return USBD_STATUS_SUCCESS if the read operation has been started normally; + * otherwise, the corresponding error code. + */ +uint32_t AUDDStream_Read( + AUDDStream *pAuds, + void * pData,uint32_t dwSize, + TransferCallback fCallback,void * pArg) +{ + if (pAuds->bEndpointOut == 0) + return USBRC_PARAM_ERR; + return USBD_Read(pAuds->bEndpointOut, + pData, dwSize, + fCallback, pArg); +} + +/** + * Initialize Frame List for sending audio data. + * \param pAuds Pointer to AUDDStream instance. + * \param pListInit Pointer to the allocated list for audio write. + * \param pDmaInit Pointer to the allocated DMA descriptors for autio write + * (if DMA supported). + * \param listSize Circular list size. + * \param delaySize Start transfer after delaySize frames filled in. + * \param callback Optional callback function for transfer. + * \param argument Optional callback argument. + * \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code. + */ +uint32_t AUDDStream_SetupWrite( + AUDDStream *pAuds, + void * pListInit, + void * pDmaInit, + uint16_t listSize, + uint16_t delaySize, + TransferCallback callback, + void * argument) +{ + uint32_t error; + + if (pAuds->bEndpointIn == 0) + return USBRC_STATE_ERR; + + error = USBD_HAL_SetupMblTransfer(pAuds->bEndpointIn, + pListInit, + listSize, + delaySize); + if (error) return error; + + error = USBD_HAL_SetTransferCallback(pAuds->bEndpointIn, + callback, argument); + return error; +} + + +/** + * Add frame buffer to audio sending list. + * \param pAuds Pointer to AUDDStream instance. + * \param pBuffer Pointer to data frame to send. + * \param wLength Frame size in bytes. + * \return USBD_STATUS_SUCCESS if the transfer is started successfully; + * otherwise an error code. + */ +uint32_t AUDDStream_Write(AUDDStream *pAuds, void* pBuffer, uint16_t wLength) +{ + if (pAuds->bEndpointIn == 0) + return USBRC_STATE_ERR; + + return USBD_HAL_Write(pAuds->bEndpointIn, + pBuffer, wLength); +} + +/** + * Close the stream. All pending transfers are canceled. + * \param pStream Pointer to AUDDStream instance. + */ +uint32_t AUDDStream_Close(AUDDStream *pStream) +{ + uint32_t bmEPs = 0; + + /* Close output stream */ + if (pStream->bEndpointIn) { + bmEPs |= 1 << pStream->bEndpointIn; + } + /* Close input stream */ + if (pStream->bEndpointOut) { + bmEPs |= 1 << pStream->bEndpointOut; + } + USBD_HAL_ResetEPs(bmEPs, USBRC_CANCELED, 1); + + return USBRC_SUCCESS; +} + +/* + * Audio Speakerphone functions + */ + +/** + * Initialize AUDDStream instance. + * Note the number of channels excludes the master control, so + * actual volume array size should be (1 + numChannels). + * \param pAuds Pointer to AUDDStream instance. + * \param numChannels Number of channels in the stream (excluding master,<31). + * \param wChannelVolumes Data array for channel volume values, + * must include master (1 + numChannels). + * \param fCallback Callback function for stream control events. + * \param pArg Pointer to event handler arguments. + */ +void AUDDSpeakerPhone_InitializeStream( + AUDDStream *pAuds, + uint8_t numChannels, + uint16_t wChannelVolumes[], + AUDDStreamEventCallback fCallback, + void* pArg) +{ + pAuds->bAcInterface = 0xFF; + pAuds->bFeatureUnitOut = 0xFF; + pAuds->bFeatureUnitIn = 0xFF; + pAuds->bAsInterface = 0xFF; + pAuds->bEndpointOut = 0; + pAuds->bEndpointIn = 0; + + pAuds->bNumChannels = numChannels; + pAuds->bmMute = 0; + pAuds->pwVolumes = wChannelVolumes; + + pAuds->fCallback = fCallback; + pAuds->pArg = pArg; +} + +/** + * Initialize AUDDSpeakerPhone instance. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pUsbd Pointer to USBDDriver instance. + * \param pSpeaker Pointer to speaker streaming interface. + * \param pMicrophone Pointer to microphone streaming interface. + */ +void AUDDSpeakerPhone_Initialize( + AUDDSpeakerPhone *pAudf, + USBDDriver *pUsbd, + AUDDStream *pSpeaker, + AUDDStream *pMicrophone) +{ + pAudf->pUsbd = pUsbd; + pAudf->pSpeaker = pSpeaker; + pAudf->pMicrophone = pMicrophone; +} + +/** + * Parse USB Audio streaming information for AUDDStream instance. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pDescriptors Pointer to descriptor list. + * \param dwLength Descriptor list size in bytes. + */ +USBGenericDescriptor *AUDDSpeakerPhone_ParseInterfaces( + AUDDSpeakerPhone *pAudf, + USBGenericDescriptor *pDescriptors, + uint32_t dwLength) +{ + AUDDParseData data; + + data.pAudf = pAudf; + data.pIfDesc = 0; + + return USBGenericDescriptor_Parse(pDescriptors, + dwLength, + (USBDescriptorParseFunction)AUDDSpeakerPhone_Parse, + (void*)&data); +} + +/** + * Close the stream. All pending transfers are canceled. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param bInterface Stream interface number + */ +uint32_t AUDDSpeakerPhone_CloseStream( + AUDDSpeakerPhone *pAudf, + uint32_t bInterface) +{ + if (pAudf->pSpeaker->bAsInterface == bInterface) { + USBD_HAL_ResetEPs(1 << pAudf->pSpeaker->bEndpointOut, + USBRC_CANCELED, + 1); + } + else if (pAudf->pMicrophone->bAsInterface == bInterface) { + USBD_HAL_ResetEPs(1 << pAudf->pMicrophone->bEndpointIn, + USBRC_CANCELED, + 1); + } + + return USBRC_SUCCESS; +} + +/** + * Handles audio-specific USB requests sent by the host + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pRequest Pointer to a USBGenericRequest instance. + * \return USBRC_PARAM_ERR if not handled. + */ +uint32_t AUDDSpeakerPhone_RequestHandler( + AUDDSpeakerPhone *pAudf, + const USBGenericRequest* pRequest) +{ + //USBDDriver *pUsbd = pAudf->pUsbd; + + if (USBGenericRequest_GetType(pRequest) != USBGenericRequest_CLASS) + return USBRC_PARAM_ERR; + + TRACE_INFO_WP("Aud "); + switch (USBGenericRequest_GetRequest(pRequest)) { + case AUDGenericRequest_SETCUR: + AUDD_SetCUR(pAudf, pRequest); + break; + case AUDGenericRequest_GETCUR: + AUDD_GetCUR(pAudf, pRequest); + break; + + default: + return USBRC_PARAM_ERR; + } + + return USBRC_SUCCESS; +} + +/** + * Receives data from the host through the audio function (as speaker). + * This function behaves like USBD_Read. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pData Pointer to the data buffer to put received data. + * \param dwSize Size of the data buffer in bytes. + * \param fCallback Optional callback function to invoke when the transfer + * finishes. + * \param pArg Optional argument to the callback function. + * \return USBD_STATUS_SUCCESS if the read operation has been started normally; + * otherwise, the corresponding error code. + */ +uint32_t AUDDSpeakerPhone_Read( + AUDDSpeakerPhone *pAudf, + void * pData,uint32_t dwSize, + TransferCallback fCallback,void * pArg) +{ + if (pAudf->pSpeaker == 0) + return USBRC_PARAM_ERR; + if (pAudf->pSpeaker->bEndpointOut == 0) + return USBRC_PARAM_ERR; + return USBD_Read(pAudf->pSpeaker->bEndpointOut, + pData, dwSize, + fCallback, pArg); +} + +/** + * Initialize Frame List for sending audio data. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pListInit Pointer to the allocated list for audio write. + * \param pDmaInit Pointer to the allocated DMA descriptors for autio write + * (if DMA supported). + * \param listSize Circular list size. + * \param delaySize Start transfer after delaySize frames filled in. + * \param callback Optional callback function for transfer. + * \param argument Optional callback argument. + * \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code. + */ +uint32_t AUDDSpeakerPhone_SetupWrite( + AUDDSpeakerPhone *pAudf, + void * pListInit, + void * pDmaInit, + uint16_t listSize, + uint16_t delaySize, + TransferCallback callback, + void * argument) +{ + uint32_t error; + + if (pAudf->pMicrophone == 0) + return USBRC_PARAM_ERR; + if (pAudf->pMicrophone->bEndpointIn == 0) + return USBRC_STATE_ERR; + + error = USBD_HAL_SetupMblTransfer(pAudf->pMicrophone->bEndpointIn, + pListInit, + listSize, + delaySize); + if (error) return error; + + error = USBD_HAL_SetTransferCallback( + pAudf->pMicrophone->bEndpointIn, + callback, argument); + return error; +} + + +/** + * Add frame buffer to audio sending list. + * \param pAudf Pointer to AUDDSpeakerPhone instance. + * \param pBuffer Pointer to data frame to send. + * \param wLength Frame size in bytes. + * \return USBD_STATUS_SUCCESS if the transfer is started successfully; + * otherwise an error code. + */ +uint32_t AUDDSpeakerPhone_Write(AUDDSpeakerPhone *pAudf, void* pBuffer, uint16_t wLength) +{ + if (pAudf->pSpeaker == 0) + return USBRC_PARAM_ERR; + if (pAudf->pSpeaker->bEndpointIn == 0) + return USBRC_STATE_ERR; + + return USBD_HAL_Write(pAudf->pSpeaker->bEndpointIn, + pBuffer, wLength); +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.c new file mode 100644 index 00000000..86567a09 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.c @@ -0,0 +1,1657 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * CCID driver + * + * \section Usage + * + * Explanation on the usage of the code made available through the header file. + * \addtogroup usbd_ccid + * @{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ +#include "board.h" + + +#include "USBLib_Trace.h" +#include "USBD.h" +#include "USBDDriver.h" +#include "USBRequests.h" +//#include "USBStringDescriptor.h" +#include "cciddriver.h" +#include "cciddriverdescriptors.h" +#include "iso7816_4.h" +#include + +/*------------------------------------------------------------------------------ + * 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 + *------------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef CCIDDriverConfigurationDescriptors + * \brief List of descriptors that make up the configuration descriptors of a + * device using the CCID driver. + */ + +typedef struct _CCIDDriverConfigurationDescriptors +{ + + /** 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; + +#ifdef __ICCARM__ /* IAR*/ +#pragma pack() /* IAR*/ +#endif /* IAR*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** \brief 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 */ + USBD_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 */ + USBD_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 */ + USBD_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 */ + USBD_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 (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/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.h b/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.h new file mode 100644 index 00000000..53455ee6 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriver.h @@ -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. + * ---------------------------------------------------------------------------- + */ + +/**------------------------------------------------------------------------------ + * \file + * + * \section Purpose + * + * Definition of methods for using a CCID device driver. + * + * \section Usage + * + * -# CCIDDriver_Initialize + * -# CCID_Read + * -# CCID_Write + * -# CCID_SmartCardRequest + * -# CCID_Insertion + * -# CCID_Removal + * -# RDRtoPCHardwareError + */ + +#ifndef CCID_DRIVER_H +#define CCID_DRIVER_H + +/** \addtogroup usbd_ccid + *@{ + */ +/** 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 + + *------------------------------------------------------------------------------*/ + +/** + * \typedef S_ccid_bulk_in_header + * \brief Bulk CCID Message header structure + */ +typedef struct _S_ccid_bulk_in_header +{ + 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; + +/** + * \typedef S_ccid_bulk_out_header + * \brief 6.1 Bulk Transfers + */ +typedef struct _S_ccid_bulk_out_header +{ + 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; + + +/** + * \typedef S_ccid_PIN_Verification + * \brief 6.1.11.2 PIN Verification Data Structure + */ +typedef struct _S_ccid_PIN_Verification +{ + /** 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; + + +/** + * \typedef S_ccid_PIN_Modification + * \brief 6.1.11.7 PIN Modification Data Structure + */ +typedef struct _S_ccid_PIN_Modification +{ + /** 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; + +/** + * \typedef S_ccid_protocol_t0 + * \brief Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h) + */ +typedef struct _S_ccid_protocol_t0 +{ + /** 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; + + +/** + * \typedef S_ccid_protocol_t1 + * \brief Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h) + */ +typedef struct _S_ccid_protocol_t1 +{ + /** 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; + + +/** + * \typedef CCIDDescriptor + * \brief Identifies the length of type of subordinate descriptors of a CCID device + * Table 5.1-1 Smart Card Device Class descriptors + */ +typedef struct _CCIDDescriptor +{ + /** 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 *request); +#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/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriverdescriptors.h b/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriverdescriptors.h new file mode 100644 index 00000000..db3bf8fd --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/ccid/cciddriverdescriptors.h @@ -0,0 +1,182 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Title: cciddriverdescriptors.h + * + * \section 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 + +/** \addtogroup usbd_ccid + *@{ + */ + +/*------------------------------------------------------------------------------ + * 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/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerial.c b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerial.c new file mode 100644 index 00000000..1b72d63f --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerial.c @@ -0,0 +1,237 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * Implementation of a single CDC serial port function for USB device. + */ + +/** \addtogroup usbd_cdc + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "CDCDSerial.h" + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/** Serial Port instance list */ +static CDCDSerialPort cdcdSerial; + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/** + * USB CDC Serial Port Event Handler. + * \param event Event code. + * \param param Event parameter. + */ +static uint32_t CDCDSerial_EventHandler(uint32_t event, + uint32_t param) +{ + switch (event) { + case CDCDSerialPortEvent_SETCONTROLLINESTATE: + { + if (CDCDSerial_ControlLineStateChanged) { + CDCDSerial_ControlLineStateChanged( + (param & CDCControlLineState_DTR) > 0, + (param & CDCControlLineState_RTS) > 0); + } + } + break; + case CDCDSerialPortEvent_SETLINECODING: + { + if (CDCDSerial_LineCodingIsToChange) { + event = CDCDSerial_LineCodingIsToChange( + (CDCLineCoding*)param); + if (event != USBRC_SUCCESS) + return event; + } + } + break; + default: + return USBRC_SUCCESS; + } + + return USBRC_SUCCESS; +} + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes the USB Device CDC serial driver & USBD Driver. + * \param pUsbd Pointer to USBDDriver instance. + * \param bInterfaceNb Interface number for the function. + */ +void CDCDSerial_Initialize( + USBDDriver *pUsbd, uint8_t bInterfaceNb) +{ + CDCDSerialPort *pCdcd = &cdcdSerial; + + TRACE_INFO("CDCDSerial_Initialize\n\r"); + + /* Initialize serial port function */ + CDCDSerialPort_Initialize( + pCdcd, pUsbd, + (CDCDSerialPortEventHandler)CDCDSerial_EventHandler, + 0, + bInterfaceNb, 2); +} + +/** + * Invoked whenever the device is changed by the + * host. + * \pDescriptors Pointer to the descriptors for function configure. + * \wLength Length of descriptors in number of bytes. + */ +void CDCDSerial_ConfigureFunction(USBGenericDescriptor *pDescriptors, + uint16_t wLength) +{ + CDCDSerialPort *pCdcd = &cdcdSerial; + CDCDSerialPort_ParseInterfaces(pCdcd, + (USBGenericDescriptor*)pDescriptors, + wLength); +} + +/** + * Handles CDC-specific SETUP requests. Should be called from a + * re-implementation of USBDCallbacks_RequestReceived() method. + * \param request Pointer to a USBGenericRequest instance. + */ +uint32_t CDCDSerial_RequestHandler(const USBGenericRequest *request) +{ + CDCDSerialPort * pCdcd = &cdcdSerial; + + TRACE_INFO_WP("Cdcf "); + return CDCDSerialPort_RequestHandler(pCdcd, request); +} + +/** + * 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. + */ +uint32_t CDCDSerial_Read(void *data, + uint32_t size, + TransferCallback callback, + void *argument) +{ + CDCDSerialPort * pCdcd = &cdcdSerial; + return CDCDSerialPort_Read(pCdcd, 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. + */ +uint32_t CDCDSerial_Write(void *data, + uint32_t size, + TransferCallback callback, + void *argument) +{ + CDCDSerialPort * pCdcd = &cdcdSerial; + return CDCDSerialPort_Write(pCdcd, data, size, callback, argument); +} + +/** + * Returns the current control line state of the RS-232 line. + */ +uint8_t CDCDSerial_GetControlLineState(void) +{ + CDCDSerialPort * pCdcd = &cdcdSerial; + return CDCDSerialPort_GetControlLineState(pCdcd); +} + +/** + * Copy current line coding settings to pointered space. + * \param pLineCoding Pointer to CDCLineCoding instance. + */ +void CDCDSerial_GetLineCoding(CDCLineCoding* pLineCoding) +{ + CDCDSerialPort * pCdcd = &cdcdSerial; + CDCDSerialPort_GetLineCoding(pCdcd, pLineCoding); +} + +/** + * Returns the current status of the RS-232 line. + */ +uint16_t CDCDSerial_GetSerialState(void) +{ + CDCDSerialPort * pCdcd = &cdcdSerial; + return CDCDSerialPort_GetSerialState(pCdcd); +} + +/** + * Sets the current serial state of the device to the given value. + * \param serialState New device state. + */ +void CDCDSerial_SetSerialState(uint16_t serialState) +{ + CDCDSerialPort * pCdcd = &cdcdSerial; + CDCDSerialPort_SetSerialState(pCdcd, serialState); +} + +WEAK uint8_t CDCDSerial_LineCodingIsToChange(CDCLineCoding * pLineCoding) +{ + /* Nothing to do */ +} + +WEAK void CDCDSerial_ControlLineStateChanged(uint8_t DTR,uint8_t RTS) +{ + /* Nothing to do */ +} +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver.c new file mode 100644 index 00000000..b96ce856 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * Title: CDCDSerialDriver implementation + * + * About: Purpose + * Implementation of the CDCDSerialDriver class methods. + */ + +/** \addtogroup usbd_cdc + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "CDCDSerialDriver.h" + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes the USB Device CDC serial driver & USBD Driver. + * \param pDescriptors Pointer to Descriptors list for CDC Serial Device. + */ +void CDCDSerialDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Initialize the standard driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + 0); /* Multiple settings for interfaces not supported */ + + CDCDSerial_Initialize(pUsbd, CDCDSerialDriver_CC_INTERFACE); + + /* Initialize the USB driver */ + USBD_Init(); +} + +/** + * Invoked whenever the active configuration of device is changed by the + * host. + * \param cfgnum Configuration number. + */ +void CDCDSerialDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBConfigurationDescriptor *pDesc; + if (cfgnum) { + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + CDCDSerial_ConfigureFunction((USBGenericDescriptor *)pDesc, + pDesc->wTotalLength); + } +} + +/** + * Handles CDC-specific SETUP requests. Should be called from a + * re-implementation of USBDCallbacks_RequestReceived() method. + * \param request Pointer to a USBGenericRequest instance. + */ +void CDCDSerialDriver_RequestHandler(const USBGenericRequest *request) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + TRACE_INFO_WP("NewReq "); + if (CDCDSerial_RequestHandler(request)) + USBDDriver_RequestHandler(pUsbd, request); +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver_Callbacks.c b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver_Callbacks.c new file mode 100644 index 00000000..8821d04d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialDriver_Callbacks.c @@ -0,0 +1,67 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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 + *---------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 + by working group ISO/IEC JTC1/SC22/WG14. */ +#include + +#include "CDCDSerialDriver.h" + +/*--------------------------------------------------------------------------- + * Default callback functions + *---------------------------------------------------------------------------*/ + +/** + * Invoked when the CDC LineCoding is requested to changed + * \param port Port number. + * \param pLineCoding Pointer to new LineCoding settings. + */ +extern WEAK uint8_t CDCDSerialDriver_LineCodingIsToChange( + CDCLineCoding * pLineCoding) +{ + /* Accept any of linecoding settings */ + return USBD_STATUS_SUCCESS; +} + +/** + * Invoked when the CDC ControlLineState is changed + * \param port Port number. + * \param DTR New DTR value. + * \param RTS New RTS value. + */ +extern WEAK void CDCDSerialDriver_ControlLineStateChanged(uint8_t DTR, + uint8_t RTS) +{ + /* Do nothing */ +} + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialPort.c b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialPort.c new file mode 100644 index 00000000..e2b188a1 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCDSerialPort.c @@ -0,0 +1,455 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * Implementation of the CDCDSerialPort class methods. + */ + +/** \addtogroup usbd_cdc + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** Parse data extention for descriptor parsing */ +typedef struct _CDCDParseData { + /** Pointer to CDCDSerialPort instance */ + CDCDSerialPort * pCdcd; + /** Pointer to found interface descriptor */ + USBInterfaceDescriptor * pIfDesc; + +} CDCDParseData; + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/** Line coding values */ +static CDCLineCoding lineCoding; + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/** + * Parse descriptors: Interface, Bulk IN/OUT, Interrupt IN. + * \param desc Pointer to descriptor list. + * \param arg Argument, pointer to AUDDParseData instance. + */ +static uint32_t _Interfaces_Parse(USBGenericDescriptor *pDesc, + CDCDParseData * pArg) +{ + CDCDSerialPort *pCdcd = pArg->pCdcd; + + /* Not a valid descriptor */ + if (pDesc->bLength == 0) + return USBRC_PARAM_ERR; + + /* Find interface descriptor */ + if (pDesc->bDescriptorType == USBGenericDescriptor_INTERFACE) { + USBInterfaceDescriptor *pIf = (USBInterfaceDescriptor*)pDesc; + + /* Obtain interface from descriptor */ + if (pCdcd->bInterfaceNdx == 0xFF) { + /* First interface is communication */ + if (pIf->bInterfaceClass == + CDCCommunicationInterfaceDescriptor_CLASS) { + pCdcd->bInterfaceNdx = pIf->bInterfaceNumber; + pCdcd->bNumInterface = 2; + } + /* Only data interface */ + else if(pIf->bInterfaceClass == CDCDataInterfaceDescriptor_CLASS) { + pCdcd->bInterfaceNdx = pIf->bInterfaceNumber; + pCdcd->bNumInterface = 1; + } + pArg->pIfDesc = pIf; + } + else if (pCdcd->bInterfaceNdx <= pIf->bInterfaceNumber + && pCdcd->bInterfaceNdx + pCdcd->bNumInterface + > pIf->bInterfaceNumber) { + pArg->pIfDesc = pIf; + } + } + + /* Parse valid interfaces */ + if (pArg->pIfDesc == 0) + return 0; + + /* Find endpoint descriptors */ + if (pDesc->bDescriptorType == USBGenericDescriptor_ENDPOINT) { + USBEndpointDescriptor *pEp = (USBEndpointDescriptor*)pDesc; + switch(pEp->bmAttributes & 0x3) { + case USBEndpointDescriptor_INTERRUPT: + if (pEp->bEndpointAddress & 0x80) + pCdcd->bIntInPIPE = pEp->bEndpointAddress & 0x7F; + break; + case USBEndpointDescriptor_BULK: + if (pEp->bEndpointAddress & 0x80) + pCdcd->bBulkInPIPE = pEp->bEndpointAddress & 0x7F; + else + pCdcd->bBulkOutPIPE = pEp->bEndpointAddress; + } + } + + if ( pCdcd->bInterfaceNdx != 0xFF + && pCdcd->bBulkInPIPE != 0 + && pCdcd->bBulkOutPIPE != 0) + return USBRC_FINISHED; + + return 0; +} + +/** + * 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. + * \param pCdcd Pointer to CDCDSerialPort instance. + */ +static void _SetLineCodingCallback(CDCDSerialPort * pCdcd) +{ + uint32_t exec = 1; + if (pCdcd->fEventHandler) { + uint32_t rc = pCdcd->fEventHandler( + CDCDSerialPortEvent_SETLINECODING, + (uint32_t)(&lineCoding), + pCdcd->pArg); + if (rc == USBD_STATUS_SUCCESS) { + pCdcd->lineCoding.dwDTERate = lineCoding.dwDTERate; + pCdcd->lineCoding.bCharFormat = lineCoding.bCharFormat; + pCdcd->lineCoding.bParityType = lineCoding.bParityType; + pCdcd->lineCoding.bDataBits = lineCoding.bDataBits; + } + else + exec = 0; + } + if (exec) USBD_Write(0, 0, 0, 0, 0); + else USBD_Stall(0); +} + +/** + * Receives new line coding information from the USB host. + * \param pCdcd Pointer to CDCDSerialPort instance. + */ +static void _SetLineCoding(CDCDSerialPort * pCdcd) +{ + TRACE_INFO_WP("sLineCoding "); + + USBD_Read(0, + (void *) & (lineCoding), + sizeof(CDCLineCoding), + (TransferCallback)_SetLineCodingCallback, + (void*)pCdcd); +} + +/** + * Sends the current line coding information to the host through Control + * endpoint 0. + * \param pCdcd Pointer to CDCDSerialPort instance. + */ +static void _GetLineCoding(CDCDSerialPort * pCdcd) +{ + TRACE_INFO_WP("gLineCoding "); + + USBD_Write(0, + (void *) &(pCdcd->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 pCdcd Pointer to CDCDSerialPort instance. + * \param request Pointer to a USBGenericRequest instance. + */ +static void _SetControlLineState( + CDCDSerialPort * pCdcd, + const USBGenericRequest *request) +{ + uint8_t DTR, RTS; + + DTR = ((request->wValue & CDCControlLineState_DTR) > 0); + RTS = ((request->wValue & CDCControlLineState_RTS) > 0); + TRACE_INFO_WP("sControlLineState(%d, %d) ", DTR, RTS); + + pCdcd->bControlLineState = (uint8_t)request->wValue; + USBD_Write(0, 0, 0, 0, 0); + + if (pCdcd->fEventHandler) + pCdcd->fEventHandler(CDCDSerialPortEvent_SETCONTROLLINESTATE, + (uint32_t)pCdcd->bControlLineState, + pCdcd->pArg); +} + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes the USB Device CDC serial port function. + * \param pCdcd Pointer to CDCDSerialPort instance. + * \param pUsbd Pointer to USBDDriver instance. + * \param fEventHandler Pointer to event handler function. + * \param firstInterface First interface index for the function + * (0xFF to parse from descriptors). + * \param numInterface Number of interfaces for the function. + */ +void CDCDSerialPort_Initialize(CDCDSerialPort * pCdcd, + USBDDriver * pUsbd, + CDCDSerialPortEventHandler fEventHandler, + void * pArg, + uint8_t firstInterface,uint8_t numInterface) +{ + TRACE_INFO("CDCDSerialPort_Initialize\n\r"); + + /* Initialize event handler */ + pCdcd->fEventHandler = fEventHandler; + pCdcd->pArg = pArg; + + /* Initialize USB Device Driver interface */ + pCdcd->pUsbd = pUsbd; + pCdcd->bInterfaceNdx = firstInterface; + pCdcd->bNumInterface = numInterface; + pCdcd->bIntInPIPE = 0; + pCdcd->bBulkInPIPE = 0; + pCdcd->bBulkOutPIPE = 0; + + /* Initialize Abstract Control Model attributes */ + pCdcd->bControlLineState = 0; + pCdcd->wSerialState = 0; + CDCLineCoding_Initialize(&(pCdcd->lineCoding), + 115200, + CDCLineCoding_ONESTOPBIT, + CDCLineCoding_NOPARITY, + 8); +} + +/** + * Parse CDC Serial Port information for CDCDSerialPort instance. + * Accepted interfaces: + * - Communication Interface + Data Interface + * - Data Interface ONLY + * \param pCdcd Pointer to CDCDSerialPort instance. + * \param pDescriptors Pointer to descriptor list. + * \param dwLength Descriptor list size in bytes. + */ +USBGenericDescriptor *CDCDSerialPort_ParseInterfaces( + CDCDSerialPort *pCdcd, + USBGenericDescriptor *pDescriptors, + uint32_t dwLength) +{ + CDCDParseData parseData; + + parseData.pCdcd = pCdcd; + parseData.pIfDesc = 0; + + return USBGenericDescriptor_Parse( + pDescriptors, dwLength, + (USBDescriptorParseFunction)_Interfaces_Parse, + &parseData); +} + + +/** + * Handles CDC-specific SETUP requests. Should be called from a + * re-implementation of USBDCallbacks_RequestReceived() method. + * \param pCdcd Pointer to CDCDSerialPort instance. + * \param request Pointer to a USBGenericRequest instance. + * \return USBRC_SUCCESS if request handled, otherwise error. + */ +uint32_t CDCDSerialPort_RequestHandler( + CDCDSerialPort *pCdcd, + const USBGenericRequest *request) +{ + if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS) + return USBRC_PARAM_ERR; + + TRACE_INFO_WP("Cdcs "); + + /* Validate interface */ + if (request->wIndex >= pCdcd->bInterfaceNdx && + request->wIndex < pCdcd->bInterfaceNdx + pCdcd->bNumInterface) { + } + else { + return USBRC_PARAM_ERR; + } + + /* Handle the request */ + switch (USBGenericRequest_GetRequest(request)) { + + case CDCGenericRequest_SETLINECODING: + + _SetLineCoding(pCdcd); + break; + + case CDCGenericRequest_GETLINECODING: + + _GetLineCoding(pCdcd); + break; + + case CDCGenericRequest_SETCONTROLLINESTATE: + + _SetControlLineState(pCdcd, request); + break; + + default: + + return USBRC_PARAM_ERR; + } + + return USBRC_SUCCESS; +} + +/** + * Receives data from the host through the virtual COM port created by + * the CDC device serial driver. This function behaves like USBD_Read. + * \param pCdcd Pointer to CDCDSerialPort instance. + * \param pData Pointer to the data buffer to put received data. + * \param dwSize Size of the data buffer in bytes. + * \param fCallback Optional callback function to invoke when the transfer + * finishes. + * \param pArg Optional argument to the callback function. + * \return USBD_STATUS_SUCCESS if the read operation has been started normally; + * otherwise, the corresponding error code. + */ +uint32_t CDCDSerialPort_Read(const CDCDSerialPort * pCdcd, + void * pData,uint32_t dwSize, + TransferCallback fCallback,void * pArg) +{ + if (pCdcd->bBulkOutPIPE == 0) + return USBRC_PARAM_ERR; + + return USBD_Read(pCdcd->bBulkOutPIPE, + pData, dwSize, + fCallback, pArg); +} + +/** + * Sends a data buffer through the virtual COM port created by the CDC + * device serial driver. This function behaves exactly like USBD_Write. + * \param pCdcd Pointer to CDCDSerialPort instance. + * \param pData Pointer to the data buffer to send. + * \param dwSize Size of the data buffer in bytes. + * \param fCallback Optional callback function to invoke when the transfer + * finishes. + * \param pArg Optional argument to the callback function. + * \return USBD_STATUS_SUCCESS if the read operation has been started normally; + * otherwise, the corresponding error code. + */ +uint32_t CDCDSerialPort_Write(const CDCDSerialPort * pCdcd, + void * pData, uint32_t dwSize, + TransferCallback fCallback, void * pArg) +{ + if (pCdcd->bBulkInPIPE == 0) + return USBRC_PARAM_ERR; + + return USBD_Write(pCdcd->bBulkInPIPE, + pData, dwSize, + fCallback, pArg); +} + +/** + * Returns the current control line state of the RS-232 line. + * \param pCdcd Pointer to CDCDSerialPort instance. + */ +uint8_t CDCDSerialPort_GetControlLineState(const CDCDSerialPort * pCdcd) +{ + return pCdcd->bControlLineState; +} + +/** + * Copy current line coding settings to pointered space. + * \param pCdcd Pointer to CDCDSerialPort instance. + * \param pLineCoding Pointer to CDCLineCoding instance. + */ +void CDCDSerialPort_GetLineCoding(const CDCDSerialPort * pCdcd, + CDCLineCoding* pLineCoding) +{ + if (pLineCoding) { + pLineCoding->dwDTERate = pCdcd->lineCoding.dwDTERate; + pLineCoding->bCharFormat = pCdcd->lineCoding.bCharFormat; + pLineCoding->bParityType = pCdcd->lineCoding.bParityType; + pLineCoding->bDataBits = pCdcd->lineCoding.bDataBits; + } +} + +/** + * Returns the current status of the RS-232 line. + * \param pCdcd Pointer to CDCDSerialPort instance. + */ +uint16_t CDCDSerialPort_GetSerialState(const CDCDSerialPort * pCdcd) +{ + return pCdcd->wSerialState; +} + +/** + * Sets the current serial state of the device to the given value. + * \param pCdcd Pointer to CDCDSerialPort instance. + * \param wSerialState New device state. + */ +void CDCDSerialPort_SetSerialState(CDCDSerialPort * pCdcd, + uint16_t wSerialState) +{ + if (pCdcd->bIntInPIPE == 0) + return; + + /* If new state is different from previous one, send a notification to the + host */ + if (pCdcd->wSerialState != wSerialState) { + + pCdcd->wSerialState = wSerialState; + USBD_Write(pCdcd->bIntInPIPE, + &(pCdcd->wSerialState), + 2, + 0, + 0); + + /* Reset one-time flags */ + pCdcd->wSerialState &= ~(CDCSerialState_OVERRUN + | CDCSerialState_PARITY + | CDCSerialState_FRAMING + | CDCSerialState_RINGSIGNAL + | CDCSerialState_BREAK); + } +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCarchitecture.png b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/CDCarchitecture.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0e9243171a1671bd8d7a4186b2b414cd798af4 GIT binary patch literal 28223 zcmeAS@N?(olHy`uVBq!ia0y~yVEn?sz^KW=%)r19v_ip?fq|JJz$e6&0R%W07z7wN zI2bq-IXEOZI5ar~1ULi~IRrF01S~luoH!J{1Ox;GB)kM9f&>&b1r#j>6r%(blLa&_ z1vH}sG_wUXivNH_&a zIIWd%+NuZwnu?m5ikgOsnwE;1UW$g6ik41_mR^dML5h}9ik8WWmU9%Hq7yGN{KgXpUu6k7d*x%jBh&+5atzdz?V3f}FgfoT93olIJ)jFLg>@>y*9M zsb!8+%UY)?TfLl|yg(qxD=5e-DA_A2+bcQSE4#%jd#zXYUa#t7UOijArfl_^v(;

G$lV|Ff_CFV4;`Zs{qW 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/USB-SerialConverter.png b/sam3s_example/atmel_softpack_libraries/usb/device/cdc-serial/USB-SerialConverter.png new file mode 100644 index 0000000000000000000000000000000000000000..bc05c1fcbb4a974b916f5226a5c002c47501674f GIT binary patch literal 10177 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 TIXyETv=q + +#include +#include + +#include + +#include +#include +#include + +/*---------------------------------------------------------------------------- + * Internal types + *----------------------------------------------------------------------------*/ + +/** + * \brief Audio speaker driver struct. + */ +typedef struct _AUDDFunction { + /** Speaker & Phone function */ + AUDDSpeakerPhone drv; + /** Stream instance for speaker */ + AUDDStream speaker; + /** Stream instance for microphone */ + AUDDStream mic; +} AUDDFunction; + +/*---------------------------------------------------------------------------- + * Internal variables + *----------------------------------------------------------------------------*/ + +/** Global USB audio function driver instance. */ +static AUDDFunction auddFunction; + +/*---------------------------------------------------------------------------- + * Internal functions + *----------------------------------------------------------------------------*/ + +/** + * Callback triggerred after the mute or volume status of the channel has been + * changed. + * \param ec Event code. + * \param channel Channel number. + * \param pArg Pointer to AUDDStream instance. + */ +static void AUDDFunction_EventCallback(uint32_t ec, + uint8_t channel, + AUDDStream *pArg) +{ + AUDDFunction *pAudf = &auddFunction; + uint8_t mic = ((uint32_t)pArg == (uint32_t)(&pAudf->mic)); + if (ec == AUDD_EC_MuteChanged) { + if (AUDDFunction_MuteChanged) + AUDDFunction_MuteChanged(mic, channel, pArg->bmMute); + } + else if (ec == AUDD_EC_VolumeChanged) { + /* Not supported now */ + } +} + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Initializes an USB audio speaker device driver, as well as the underlying + * USB controller. + */ +void AUDDFunction_Initialize(USBDDriver *pUsbd, uint8_t bInterface) +{ + AUDDFunction *pAudf = &auddFunction; + AUDDSpeakerPhone *pDrv = &pAudf->drv; + AUDDStream *pSpk = &pAudf->speaker; + AUDDStream *pMic = &pAudf->mic; + + /* 0: Speaker */ + AUDDSpeakerPhone_InitializeStream( + pSpk, AUDDFunction_MaxNumSpeakerChannels, 0, + (AUDDStreamEventCallback)AUDDFunction_EventCallback, + (void*)pSpk); + /* 1: Mic */ + AUDDSpeakerPhone_InitializeStream( + pMic, AUDDFunction_MaxNumMicrophoneChannels, 0, + (AUDDStreamEventCallback)AUDDFunction_EventCallback, + (void*)pMic); + /* Audio Driver initialize */ + AUDDSpeakerPhone_Initialize(pDrv, pUsbd, pSpk, pMic); + +} + +/** + * Configure function with expected descriptors and start functionality. + * Usually invoked when device is configured. + * \pDescriptors Pointer to the descriptors for function configure. + * \wLength Length of descriptors in number of bytes. + */ +void AUDDFunction_Configure(USBGenericDescriptor *pDescriptors, + uint16_t wLength) +{ + AUDDFunction *pAudf = &auddFunction; + AUDDSpeakerPhone *pDrv = &pAudf->drv; + AUDDSpeakerPhone_ParseInterfaces(pDrv, pDescriptors, wLength); +} + +/** + * 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 AUDDFunction_InterfaceSettingChangedHandler(uint8_t interface, + uint8_t setting) +{ + AUDDFunction *pAudf = &auddFunction; + AUDDSpeakerPhone *pDrv = &pAudf->drv; + if (setting == 0) AUDDSpeakerPhone_CloseStream(pDrv, interface); + if (AUDDFunction_StreamSettingChanged) { + uint8_t mic = (interface == pDrv->pMicrophone->bAsInterface); + AUDDFunction_StreamSettingChanged(mic, setting); + } +} + +/** + * Handles AUDIO-specific USB requests sent by the host + * \param request Pointer to a USBGenericRequest instance. + * \return USBRC_SUCCESS if request is handled. + */ +uint32_t AUDDFunction_RequestHandler( + const USBGenericRequest *request) +{ + AUDDFunction *pAudf = &auddFunction; + AUDDSpeakerPhone *pDrv = &pAudf->drv; + return AUDDSpeakerPhone_RequestHandler(pDrv, request); +} + +/** + * 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 if the transfer is started successfully; + * otherwise an error code. + */ +uint8_t AUDDFunction_Read(void *buffer, + uint32_t length, + TransferCallback callback, + void *argument) +{ + AUDDFunction *pAudf = &auddFunction; + AUDDSpeakerPhone *pDrv = &pAudf->drv; + return AUDDSpeakerPhone_Read(pDrv, buffer, length, callback, argument); +} + +/** + * Initialize Frame List for sending audio data. + * + * \param pListInit Pointer to the allocated list for audio write. + * \param pDmaInit Pointer to the allocated DMA descriptors for autio write + * (if DMA supported). + * \param listSize Circular list size. + * \param delaySize Start transfer after delaySize frames filled in. + * \param callback Optional callback function for transfer. + * \param argument Optional callback argument. + * \return USBD_STATUS_SUCCESS if setup successfully; otherwise an error code. + */ +uint8_t AUDDFunction_SetupWrite(void * pListInit, + void * pDmaInit, + uint16_t listSize, + uint16_t delaySize, + TransferCallback callback, + void * argument) +{ + AUDDFunction *pAudf = &auddFunction; + AUDDSpeakerPhone *pDrv = &pAudf->drv; + return AUDDSpeakerPhone_SetupWrite(pDrv, + pListInit, pDmaInit, listSize, delaySize, + callback, argument); +} + +/** + * Add frame buffer to audio sending list. + * \buffer Pointer to data frame to send. + * \length Frame size in bytes. + * \return USBD_STATUS_SUCCESS if the transfer is started successfully; + * otherwise an error code. + */ +uint8_t AUDDFunction_Write(void* buffer, uint16_t length) +{ + AUDDFunction *pAudf = &auddFunction; + AUDDSpeakerPhone *pDrv = &pAudf->drv; + return AUDDSpeakerPhone_Write(pDrv, buffer, length); +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCAUDDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCAUDDDriver.c new file mode 100644 index 00000000..c146052d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCAUDDDriver.c @@ -0,0 +1,139 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup usbd_composite_cdcaud + *@{ + */ +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include + +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Defines + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/** Array for storing the current setting of each interface */ +static uint8_t bAltInterfaces[CDCAUDDDriverDescriptors_MaxNumInterfaces]; + +/*--------------------------------------------------------------------------- + * Internal functions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Initializes the USB device composite device driver. + */ +void CDCAUDDDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Initialize the standard USB driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + bAltInterfaces); + + /* CDC */ + CDCDSerial_Initialize(pUsbd, CDCAUDDDriverDescriptors_CDC_INTERFACE); + /* Audio */ + AUDDFunction_Initialize(pUsbd, CDCAUDDDriverDescriptors_AUD_INTERFACE); + + /* Initialize the USB driver */ + USBD_Init(); +} + +/** + * Invoked whenever the configuration value of a device is changed by the host + * \param cfgnum Configuration number. + */ +void CDCAUDDDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBConfigurationDescriptor *pDesc; + if (cfgnum > 0) { + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + /* CDC */ + CDCDSerial_ConfigureFunction((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + /* AUD */ + AUDDFunction_Configure((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * 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 CDCAUDDDriver_InterfaceSettingChangedHandler(uint8_t interface, + uint8_t setting) +{ + AUDDFunction_InterfaceSettingChangedHandler(interface, setting); +} + +/** + * 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 CDCAUDDDriver_RequestHandler(const USBGenericRequest *request) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + TRACE_INFO_WP("NewReq "); + + if (CDCDSerial_RequestHandler(request) == USBRC_SUCCESS) + return; + + if (AUDDFunction_RequestHandler(request) == USBRC_SUCCESS) + return; + + USBDDriver_RequestHandler(pUsbd, request); +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCHIDDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCHIDDDriver.c new file mode 100644 index 00000000..45509432 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCHIDDDriver.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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup usbd_composite_cdchid + *@{ + */ +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include + +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Defines + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal functions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Initializes the USB device composite device driver. + */ +void CDCHIDDDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Initialize the standard USB driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + 0); + + /* CDC */ + CDCDSerial_Initialize(pUsbd, CDCHIDDDriverDescriptors_CDC_INTERFACE); + /* HID */ + HIDDKeyboard_Initialize(pUsbd, CDCHIDDDriverDescriptors_HID_INTERFACE); + + /* Initialize the USB driver */ + USBD_Init(); +} + +/** + * Invoked whenever the configuration value of a device is changed by the host + * \param cfgnum Configuration number. + */ +void CDCHIDDDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBConfigurationDescriptor *pDesc; + if (cfgnum > 0) { + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + /* CDC */ + CDCDSerial_ConfigureFunction((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + /* HID */ + HIDDKeyboard_ConfigureFunction((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * 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) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + TRACE_INFO_WP("NewReq "); + + if (CDCDSerial_RequestHandler(request) == USBRC_SUCCESS) + return; + + if (HIDDKeyboard_RequestHandler(request) == USBRC_SUCCESS) + return; + + USBDDriver_RequestHandler(pUsbd, request); +} + +/** + * Starts a remote wake-up sequence if the host has explicitely enabled it + * by sending the appropriate SET_FEATURE request. + */ +void CDCHIDDDriver_RemoteWakeUp(void) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Remote wake-up has been enabled */ + if (USBDDriver_IsRemoteWakeUpEnabled(pUsbd)) { + + USBD_RemoteWakeUp(); + } +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCMSDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCMSDDriver.c new file mode 100644 index 00000000..55fe6fb5 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/composite/CDCMSDDriver.c @@ -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. + * ---------------------------------------------------------------------------- + */ +/** \file */ +/** \addtogroup usbd_composite_cdcmsd + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include + +#include + +#include +#include + +/*--------------------------------------------------------------------------- + * Defines + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal functions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Initializes the USB device CDCMSD device driver. + */ +void CDCMSDDriver_Initialize( + const USBDDriverDescriptors *pDescriptors, + MSDLun *pLuns, unsigned char numLuns) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Initialize the standard USB driver */ + USBDDriver_Initialize(pUsbd, pDescriptors, 0); + + /* CDC */ + CDCDSerial_Initialize(pUsbd, CDCMSDDriverDescriptors_CDC_INTERFACE); + + /* MSD */ + MSDFunction_Initialize(pUsbd, CDCMSDDriverDescriptors_MSD_INTERFACE, + pLuns, numLuns); + + /* Initialize the USB driver */ + USBD_Init(); +} + +/** + * Invoked whenever the configuration value of a device is changed by the host + * \param cfgnum Configuration number. + */ +void CDCMSDDriver_ConfigurationChangedHandler(unsigned char cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBConfigurationDescriptor *pDesc; + if (cfgnum > 0) { + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + /* CDC */ + CDCDSerial_ConfigureFunction((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + /* MSD */ + MSDFunction_Configure((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * 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 CDCMSDDriver_RequestHandler(const USBGenericRequest *request) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + TRACE_INFO_WP("NewReq "); + + if (CDCDSerial_RequestHandler(request) == USBRC_SUCCESS) + return; + + if (MSDFunction_RequestHandler(request) == USBRC_SUCCESS) + return; + + USBDDriver_RequestHandler(pUsbd, request); +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/DUALCDCDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/composite/DUALCDCDDriver.c new file mode 100644 index 00000000..7b441997 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/composite/DUALCDCDDriver.c @@ -0,0 +1,194 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ +/** \file */ +/** \addtogroup usbd_composite_cdccdc + *@{ + */ +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +/* GENERAL */ +#include + +/* USB */ +#include +#include +#include + +/* - DUALCDC */ +#include + +/*--------------------------------------------------------------------------- + * Defines + *---------------------------------------------------------------------------*/ + +/** Number of CDC serial ports */ +#define NUM_PORTS 2 + +/** Interface setting spaces (4 byte aligned) */ +#define NUM_INTERFACES ((DUALCDCDDriverDescriptors_NUMINTERFACE+3)&0xFC) + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/** Dual-CDC-Serial device driver struct */ +typedef struct _DualCdcdSerialDriver { + /** CDC Serial Port List */ + CDCDSerialPort cdcdSerialPort[NUM_PORTS]; +} DualCdcdSerialDriver; + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/** Dual CDC Serial device driver instance */ +DualCdcdSerialDriver dualcdcdDriver; + +/*--------------------------------------------------------------------------- + * Internal functions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Initializes the USB device composite device driver. + * \param pDescriptors Pointer to Descriptors list for CDC Serial Device. + */ +void DUALCDCDDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + CDCDSerialPort *pCdcd = &dualcdcdDriver.cdcdSerialPort[0]; + + TRACE_INFO("DUALCDCDDriver_Initialize\n\r"); + + pCdcd = &dualcdcdDriver.cdcdSerialPort[0]; + CDCDSerialPort_Initialize(pCdcd, pUsbd, + 0, + 0, + DUALCDCDDriverDescriptors_INTERFACENUM0, 2); + + pCdcd = &dualcdcdDriver.cdcdSerialPort[1]; + CDCDSerialPort_Initialize(pCdcd, pUsbd, + 0, + 0, + DUALCDCDDriverDescriptors_INTERFACENUM1, 2); + + /* Initialize the standard USB driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + 0); + /* Initialize the USB driver */ + USBD_Init(); +} + +/** + * Invoked whenever the active configuration of device is changed by the + * host. + * \param cfgnum Configuration number. + */ +void DUALCDCDDriver_ConfigurationChangeHandler(uint8_t cfgnum) +{ + CDCDSerialPort *pCdcd = &dualcdcdDriver.cdcdSerialPort[0]; + USBDDriver *pUsbd = pCdcd->pUsbd; + USBConfigurationDescriptor *pDesc; + USBGenericDescriptor *pD; + uint32_t i, len; + + if (cfgnum > 0) { + + /* Parse endpoints for data & notification */ + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + + pD = (USBGenericDescriptor *)pDesc; + len = pDesc->wTotalLength; + + for (i = 0; i < NUM_PORTS; i ++) { + pCdcd = &dualcdcdDriver.cdcdSerialPort[i]; + pD = CDCDSerialPort_ParseInterfaces(pCdcd, pD, len); + len = pDesc->wTotalLength - ((uint32_t)pD - (uint32_t)pDesc); + } + } +} + + +/** + * 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) +{ + CDCDSerialPort *pCdcd = 0; + USBDDriver *pUsbd = 0; + uint32_t rc, i; + + TRACE_INFO_WP("NewReq "); + + for (i = 0; i < NUM_PORTS; i ++) { + pCdcd = &dualcdcdDriver.cdcdSerialPort[i]; + rc = CDCDSerialPort_RequestHandler(pCdcd, request); + if (rc == USBRC_SUCCESS) + break; + } + + /* Not handled by CDC Serial */ + if (rc != USBRC_SUCCESS) { + if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) { + pUsbd = pCdcd->pUsbd; + USBDDriver_RequestHandler(pUsbd, request); + } + else { + TRACE_WARNING( + "DUALCDCDDriver_RequestHandler: Unsupported request (%d,%d)\n\r", + USBGenericRequest_GetType(request), + USBGenericRequest_GetRequest(request)); + USBD_Stall(0); + } + } + +} + +/** + * Return CDCDSerialPort for serial port operations. + * \param port Port number. + */ +CDCDSerialPort *DUALCDCDDriver_GetSerialPort(uint32_t port) +{ + if (port < NUM_PORTS) + return &dualcdcdDriver.cdcdSerialPort[port]; + + return 0; +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDAUDDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDAUDDDriver.c new file mode 100644 index 00000000..95d56258 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDAUDDDriver.c @@ -0,0 +1,139 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup usbd_composite_hidaud + *@{ + */ +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include + +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Defines + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/** Array for storing the current setting of each interface */ +static uint8_t bAltInterfaces[HIDAUDDDriverDescriptors_NUMINTERFACE]; + +/*--------------------------------------------------------------------------- + * Internal functions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Initializes the USB device composite device driver. + */ +void HIDAUDDDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Initialize the standard USB driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + bAltInterfaces); + + /* HID */ + HIDDKeyboard_Initialize(pUsbd, HIDAUDDDriverDescriptors_HID_INTERFACE); + /* Audio */ + AUDDFunction_Initialize(pUsbd, HIDAUDDDriverDescriptors_AUD_INTERFACE); + + /* Initialize the USB driver */ + USBD_Init(); +} + +/** + * Invoked whenever the configuration value of a device is changed by the host + * \param cfgnum Configuration number. + */ +void HIDAUDDDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBConfigurationDescriptor *pDesc; + if (cfgnum > 0) { + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + /* CDC */ + HIDDKeyboard_ConfigureFunction((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + /* AUD */ + AUDDFunction_Configure((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * 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 HIDAUDDDriver_InterfaceSettingChangedHandler(uint8_t interface, + uint8_t setting) +{ + AUDDFunction_InterfaceSettingChangedHandler(interface, setting); +} + +/** + * 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 HIDAUDDDriver_RequestHandler(const USBGenericRequest *request) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + TRACE_INFO_WP("NewReq "); + + if (HIDDKeyboard_RequestHandler(request) == USBRC_SUCCESS) + return; + + if (AUDDFunction_RequestHandler(request) == USBRC_SUCCESS) + return; + + USBDDriver_RequestHandler(pUsbd, request); +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDMSDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDMSDDriver.c new file mode 100644 index 00000000..18986220 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/composite/HIDMSDDriver.c @@ -0,0 +1,153 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + */ + +/** \addtogroup usbd_composite_hidmsd + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include + +#include + +#include +#include + +/*--------------------------------------------------------------------------- + * Defines + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal functions + *---------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Initializes the USB device HIDMSD device driver. + */ +void HIDMSDDriver_Initialize( + const USBDDriverDescriptors *pDescriptors, + MSDLun *pLuns, uint8_t numLuns) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Initialize the standard USB driver */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + 0); + + /* HID */ + HIDDKeyboard_Initialize(pUsbd, HIDMSDDriverDescriptors_HID_INTERFACE); + + /* MSD */ + MSDFunction_Initialize(pUsbd, HIDMSDDriverDescriptors_MSD_INTERFACE, + pLuns, numLuns); + + /* Initialize the USB driver */ + USBD_Init(); +} + +/** + * Invoked whenever the configuration value of a device is changed by the host + * \param cfgnum Configuration number. + */ +void HIDMSDDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBConfigurationDescriptor *pDesc; + if (cfgnum > 0) { + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + /* HID */ + HIDDKeyboard_ConfigureFunction((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + /* MSD */ + MSDFunction_Configure((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * 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 HIDMSDDriver_RequestHandler(const USBGenericRequest *request) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + TRACE_INFO_WP("NewReq "); + + if (HIDDKeyboard_RequestHandler(request) == USBRC_SUCCESS) + return; + + if (MSDFunction_RequestHandler(request) == USBRC_SUCCESS) + return; + + USBDDriver_RequestHandler(pUsbd, request); +} + +/** + * Starts a remote wake-up sequence if the host has explicitely enabled it + * by sending the appropriate SET_FEATURE request. + */ +void HIDMSDDriver_RemoteWakeUp(void) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + /* Remote wake-up has been enabled */ + if (USBDDriver_IsRemoteWakeUpEnabled(pUsbd)) { + + USBD_RemoteWakeUp(); + } + /* Remote wake-up NOT enabled */ + else { + + TRACE_WARNING("HIDMSDDDriver_RemoteWakeUp: not enabled\n\r"); + } +} +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcAudioArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcAudioArch.png new file mode 100644 index 0000000000000000000000000000000000000000..72bc9792aaeab41bab98e5f5660b026a6633e575 GIT binary patch literal 50020 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%0D?8=(3tIJ;a=;@yR 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 Ty3==Bf`Zi3)z4*}Q$iB}q&!jh literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcHidArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcHidArch.png new file mode 100644 index 0000000000000000000000000000000000000000..782312a6cae32e38fcfebbcdfe9993078cf072f4 GIT binary patch literal 48500 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ℜ9bEmSqx3eB|JI?*A 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

jU*M9G~tD`-0yP@9>feX3@XVMSrbtbuQ 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 F69D*oSmyu$ literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcMsdArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeCdcMsdArch.png new file mode 100644 index 0000000000000000000000000000000000000000..c51556ee9b45df933cc976b6712d5f735071c649 GIT binary patch literal 50918 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≻s@ane9%iJwZ_}Sz7=-kRp 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∾%xsYrZ})mZGTi*A6$I9iMgo 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeHidMsdArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeHidMsdArch.png new file mode 100644 index 0000000000000000000000000000000000000000..0d0e791d79ef8ee496909dab83f0f88477c309f8 GIT binary patch literal 42038 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

iqLt4r#8IesW`XdH)|Rv!`!0Go@u} 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

y^aI?{9F}KQDQi(?piD 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 Pz`)??>gTe~DWM4fS2+{r literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeMultiIF.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeMultiIF.png new file mode 100644 index 0000000000000000000000000000000000000000..7ad09c767fe5905a7e403aa7df13ccd1769e96c5 GIT binary patch literal 34463 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

gzj@0n|V^}3&v|4%(xiRJbo)A#;;9lP=I#?#8T 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeRequestHandler.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeRequestHandler.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa24b7f2912a72d171991b1f2a20ae064508cf6 GIT binary patch literal 59411 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»AT11)~}z>*ZS&`(4)Ods^vTH=6%*v zDN>Ae$~pMw&Yj)I`)0P+SpEGMy*>Z`?{@ipJF2&@+E!(3Y+PGgd#NaHXVKD~J9nnc z@zV{d{yJmMoGVJ(pBGuy+zCDsz-%F=>XEa*#_s;LYh@EI)d}BGzN2|Z|Bh+yMYZ1N ztGagEoac;5^3Sqqd|kBLK0e|>u0qQVz8C$)4?nzGf8E<6<+rfL!iyI#Zr!@|SDAQ& zhpe1j+oH8)5fveiUj}gKn@;yun_T{=aBs(cfzAiYbB#OR{*YbWAmH@P%WQJx^A~}> z&$nuwT7LO5s0MiS?(X3^b0@T(TeEYU%hCNSSFLK_c5m_Nw{kL4ReSdRJG=cp9}nNY zcSW97NA92O>(iOepf;tdMIh+-i6w7~L$8X+nJ`W{sOau@?)m495ob31xS=<5=FEwr zyHb#H{NJfUc=Lu}!RfsvqhzP4xl8y}%!bm5SUr?OKHw%A~mc?0nRuS5>eh zCf&E;*=;lPsE7#+r-h_=v?lPgZe--$)TFqOT~Co+eczTX`Tl3Rsvn%Py7f%NHLyl) zR#)NOaxE{-W4)JS;wM@PaJ(>fxT+X@xZD%B(XuK6^6W#muDR*~wcU0rAL#9t= zon74`e`NLcrvD21aeEH*H`Y5G5i1Dk7jP;&{c@4UMhl~lSspogd1n1v)~;FeAofwM z6w_%*Hty6bzG|U`BKLTOkEgz24XiMm-CAcOM|AZO(}fv zK-e*dG54#7>ho<8oGmvV1-7o6bo2JaiGmsi-{aC2J@vf5_qC_z_Q*LOKRrFIB(Tuv z_G$jBpvDKdVlKv3?2$!hBAscYZb%5qdrKby9F+cuNd?dnTYTia&G4^R5HgjZ@s;}r}X&zR=P{E+^&A`NK;pYYx%C-mHOEyZWc&1{eEB=1kIhV}qIe)cq>B7X7JI;YtaF|up+LfG^TY5P_+T_;ispobJ_kU+=ZgzHF z!|PPGXzPoh4@0&}Q;MoLG|Wp`!nk4Y+I#i$Z@WB- zv53(Sxlr2n$zk=Y0t*qoAK{MoR<4?LHcftM(CVYxCLPmjc_Va7EV_OFzMpFM_TRpf z5-Q+jYd!J&^ZavXb&o$jFZp2YF9*;0d~ED(Z84>`#V#JKi5D2U4eZU!6@?OyFgUGD zPfmH_d9Sixd(DSAetk29Hs#w{6g~>H`g`^7@0jpqVJXIv9C=>?<=3y@Yz8{2w`GFY zr1Q`3>-ovvi;DQb&a`I2tQR&p4!N86dr7t2-^j(G_~b%?)m#BdzU7}E&zraL^K(h_ z2L`U+uC82J-Y>iOoN_Ol`&SOdC2X4>$5`m}`R+Zq;QH&OXS2Ts6z?pt+B?fbgsb&& z-23O;+-q_{9Vx{nua*R_d|DBs!jZlBR>`lw%+Agx6IFOm{O2}c2%meWUC#UE0tN;K N22WQ%mvv4FO#tMJaPj~E literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeSWArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeSWArch.png new file mode 100644 index 0000000000000000000000000000000000000000..608824ab4340b1154c31afbfccdb15a7e8f1af51 GIT binary patch literal 44871 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 z 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 G5}E*ahHtq5 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeSingleIF.png b/sam3s_example/atmel_softpack_libraries/usb/device/composite/UsbCompositeSingleIF.png new file mode 100644 index 0000000000000000000000000000000000000000..61d47012292f9665740c36617bf1d5ef74e1b8b3 GIT binary patch literal 39451 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�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 FA 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/composite/drv/CompositeCDCSerial.inf b/sam3s_example/atmel_softpack_libraries/usb/device/composite/drv/CompositeCDCSerial.inf new file mode 100644 index 00000000..6716dc0b --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/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/sam3s_example/atmel_softpack_libraries/usb/device/core/USBD.c b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBD.c new file mode 100644 index 00000000..b0d155fe --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBD.c @@ -0,0 +1,380 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * \section Purpose + * + * Implementation of USB device functions on a UDP controller. + * + * See \ref usbd_api "USBD API Methods". + */ + +/** \addtogroup usbd_interface + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ +#include "board.h" +#include "USBD.h" +#include "USBD_HAL.h" + +//#include + +/*--------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/** Device current state. */ +static uint8_t deviceState; +/** Indicates the previous device state */ +static uint8_t previousDeviceState; + +/*--------------------------------------------------------------------------- + * Internal Functions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * USBD: Event handlers + *---------------------------------------------------------------------------*/ + +/** + * Handle the USB suspend event, should be invoked whenever + * HW reports a suspend signal. + */ +void USBD_SuspendHandler(void) +{ + /* Don't do anything if the device is already suspended */ + if (deviceState != USBD_STATE_SUSPENDED) { + + /* Switch to the Suspended state */ + previousDeviceState = deviceState; + deviceState = USBD_STATE_SUSPENDED; + + /* Suspend HW interface */ + USBD_HAL_Suspend(); + + /* Invoke the User Suspended callback (Suspend System?) */ + if (USBDCallbacks_Suspended) + USBDCallbacks_Suspended(); + } +} + +/** + * Handle the USB resume event, should be invoked whenever + * HW reports a resume signal. + */ +void USBD_ResumeHandler(void) +{ + /* Don't do anything if the device was not suspended */ + if (deviceState == USBD_STATE_SUSPENDED) { + /* Active the device */ + USBD_HAL_Activate(); + deviceState = previousDeviceState; + if (deviceState >= USBD_STATE_DEFAULT) { + /* Invoke the Resume callback */ + if (USBDCallbacks_Resumed) + USBDCallbacks_Resumed(); + } + } +} + +/** + * Handle the USB reset event, should be invoked whenever + * HW found USB reset signal on bus, which usually is called + * "end of bus reset" status. + */ +void USBD_ResetHandler() +{ + /* The device enters the Default state */ + deviceState = USBD_STATE_DEFAULT; + /* Active the USB HW */ + USBD_HAL_Activate(); + /* Only EP0 enabled */ + USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0); + USBD_ConfigureEndpoint(0); + /* Invoke the Reset callback */ + if (USBDCallbacks_Reset) + USBDCallbacks_Reset(); +} + +/** + * Handle the USB setup package received, should be invoked + * when an endpoint got a setup package as request. + * \param bEndpoint Endpoint number. + * \param pRequest Pointer to content of request. + */ +void USBD_RequestHandler(uint8_t bEndpoint, + const USBGenericRequest* pRequest) +{ + if (bEndpoint != 0) { + TRACE_WARNING("EP%d request not supported, default EP only", + bEndpoint); + } + else if (USBDCallbacks_RequestReceived) { + USBDCallbacks_RequestReceived(pRequest); + } +} + +/*--------------------------------------------------------------------------- + * USBD: Library interface + *---------------------------------------------------------------------------*/ + +/** + * Configures an endpoint according to its Endpoint Descriptor. + * \param pDescriptor Pointer to an Endpoint descriptor. + */ +void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor) +{ + USBD_HAL_ConfigureEP(pDescriptor); +} + +/** + * 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. + */ +uint8_t USBD_Write( uint8_t bEndpoint, + const void *pData, + uint32_t dLength, + TransferCallback fCallback, + void *pArgument ) +{ + USBD_HAL_SetTransferCallback(bEndpoint, fCallback, pArgument); + return USBD_HAL_Write(bEndpoint, pData, dLength); +} +/** + * 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. + */ +uint8_t USBD_Read(uint8_t bEndpoint, + void *pData, + uint32_t dLength, + TransferCallback fCallback, + void *pArgument) +{ + USBD_HAL_SetTransferCallback(bEndpoint, fCallback, pArgument); + return USBD_HAL_Read(bEndpoint, pData, dLength); +} +/** + * Sets the HALT feature on the given endpoint (if not already in this state). + * \param bEndpoint Endpoint number. + */ +void USBD_Halt(uint8_t bEndpoint) +{ + USBD_HAL_Halt(bEndpoint, 1); +} + +/** + * Clears the Halt feature on the given endpoint. + * \param bEndpoint Index of endpoint + */ +void USBD_Unhalt(uint8_t bEndpoint) +{ + USBD_HAL_Halt(bEndpoint, 0); +} + +/** + * Returns the current Halt status of an endpoint. + * \param bEndpoint Index of endpoint + * \return 1 if the endpoint is currently halted; otherwise 0 + */ +uint8_t USBD_IsHalted(uint8_t bEndpoint) +{ + return USBD_HAL_Halt(bEndpoint, 0xFF); +} + +/** + * Indicates if the device is running in high or full-speed. Always returns 0 + * since UDP does not support high-speed mode. + */ +uint8_t USBD_IsHighSpeed(void) +{ + return USBD_HAL_IsHighSpeed(); +} + +/** + * 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. + */ +uint8_t USBD_Stall(uint8_t bEndpoint) + +{ + return USBD_HAL_Stall(bEndpoint); +} + +/** + * Sets the device address to the given value. + * \param address New device address. + */ +void USBD_SetAddress(uint8_t address) +{ + TRACE_INFO_WP("SetAddr(%d) ", address); + + USBD_HAL_SetAddress(address); + if (address == 0) deviceState = USBD_STATE_DEFAULT; + else deviceState = USBD_STATE_ADDRESS; +} + +/** + * Sets the current device configuration. + * \param cfgnum - Configuration number to set. + */ +void USBD_SetConfiguration(uint8_t cfgnum) +{ + TRACE_INFO_WP("SetCfg(%d) ", cfgnum); + + USBD_HAL_SetConfiguration(cfgnum); + + if (cfgnum != 0) { + deviceState = USBD_STATE_CONFIGURED; + } + else { + deviceState = USBD_STATE_ADDRESS; + /* Reset all endpoints */ + USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0); + } +} + +/*--------------------------------------------------------------------------- + * USBD: Library API + *---------------------------------------------------------------------------*/ + +/** + * Starts a remote wake-up procedure. + */ +void USBD_RemoteWakeUp(void) +{ + /* Device is NOT suspended */ + if (deviceState != USBD_STATE_SUSPENDED) { + + TRACE_INFO("USBD_RemoteWakeUp: Device is not suspended\n\r"); + return; + } + USBD_HAL_Activate(); + USBD_HAL_RemoteWakeUp(); +} + +/** + * Connects the pull-up on the D+ line of the USB. + */ +void USBD_Connect(void) +{ + USBD_HAL_Connect(); +} + +/** + * Disconnects the pull-up from the D+ line of the USB. + */ +void USBD_Disconnect(void) +{ + USBD_HAL_Disconnect(); + + /* 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"); + + /* HW Layer Initialize */ + USBD_HAL_Init(); + + /* Device is in the Attached state */ + deviceState = USBD_STATE_SUSPENDED; + previousDeviceState = USBD_STATE_POWERED; + + /* Upper Layer Initialize */ + if (USBDCallbacks_Initialized) + USBDCallbacks_Initialized(); +} + +/** + * Returns the current state of the USB device. + * \return Device current state. + */ +uint8_t USBD_GetState(void) +{ + return deviceState; +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDCallbacks.c b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDCallbacks.c new file mode 100644 index 00000000..04aa5955 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDCallbacks.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * 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. + * + * \addtogroup usbd_interface + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "USBD.h" +#include "USBDDriver.h" + +/*------------------------------------------------------------------------------ + * Exported function + *------------------------------------------------------------------------------*/ + +/** + * Invoked after the USB driver has been initialized. By default, do nothing. + */ +WEAK void USBDCallbacks_Initialized(void) +{ + /* Does nothing */ +} + +/** + * Invoked when the USB driver is reset. Does nothing by default. + */ +WEAK void USBDCallbacks_Reset(void) +{ + /* Does nothing*/ +} + +/** + * Invoked when the USB device gets suspended. By default, do nothing. + */ +WEAK void USBDCallbacks_Suspended(void) {} + +/** + * Invoked when the USB device leaves the Suspended state. By default, + * Do nothing. + */ +WEAK void USBDCallbacks_Resumed(void) {} + +/** + * USBDCallbacks_RequestReceived - Invoked when a new SETUP request is + * received. Does nothing by default. + * \param request Pointer to the request to handle. + */ +WEAK void USBDCallbacks_RequestReceived(const USBGenericRequest *request) +{ + /* Does basic enumeration */ + USBDDriver_RequestHandler(USBD_GetDriver(), request); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriver.c new file mode 100644 index 00000000..689ae1f3 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriver.c @@ -0,0 +1,699 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_interface + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include "USBDDriver.h" +#include "USBD.h" +#include "USBD_HAL.h" + +#include + +/*------------------------------------------------------------------------------ + * Local variables + *------------------------------------------------------------------------------*/ + +/** Default device driver instance, for all class drivers in USB Lib. */ +static USBDDriver usbdDriver; + +/*------------------------------------------------------------------------------ + * Local functions + *------------------------------------------------------------------------------*/ + +/** + * Send a NULL packet + */ +static void TerminateCtrlInWithNull(void *pArg, + uint8_t status, + uint32_t transferred, + uint32_t 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, uint8_t cfgnum) +{ + USBEndpointDescriptor *pEndpoints[17]; + 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; + pDriver->isRemoteWakeUpEnabled = + ((pConfiguration->bmAttributes & 0x20) > 0); + + /* 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(uint8_t bEndpoint) +{ + static unsigned short data; + + data = 0; + + switch (USBD_HAL_Halt(bEndpoint, 0xFF)) { + + case USBD_STATUS_INVALID_PARAMETER: /* the endpoint not exists */ + USBD_Stall(0); + break; + + case 1: + data = 1; + case 0: + /* Send the endpoint status */ + USBD_Write(0, &data, 2, 0, 0); + break; + } +} + +/** + * 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, + uint8_t type, + uint8_t indexRDesc, + uint32_t length) +{ + const USBDeviceDescriptor *pDevice; + const USBConfigurationDescriptor *pConfiguration; + const USBDeviceQualifierDescriptor *pQualifier; + const USBConfigurationDescriptor *pOtherSpeed; + const USBGenericDescriptor **pStrings = + (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings; + const USBGenericDescriptor *pString; + uint8_t numStrings = pDriver->pDescriptors->numStrings; + uint8_t 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, + uint8_t infnum, + uint8_t 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, + uint8_t 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); + } +} +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Return USBDDriver instance pointer for global usage. + */ +USBDDriver *USBD_GetDriver(void) +{ + return &usbdDriver; +} + +/** + * 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, + uint8_t *pInterfaces) +{ + + pDriver->cfgnum = 0; + pDriver->isRemoteWakeUpEnabled = 0; + + pDriver->pDescriptors = pDescriptors; + pDriver->pInterfaces = pInterfaces; + + /* Initialize interfaces array if not null */ + + if (pInterfaces != 0) { + + memset(pInterfaces, sizeof(pInterfaces), 0); + } +} + +/** + * Returns configuration descriptor list. + * \param pDriver Pointer to a USBDDriver instance. + * \param cfgNum Reserved. + */ +USBConfigurationDescriptor *USBDDriver_GetCfgDescriptors( + USBDDriver *pDriver, uint8_t cfgNum) +{ + USBDDriverDescriptors *pDescList = (USBDDriverDescriptors *)pDriver->pDescriptors; + USBConfigurationDescriptor *pCfg; + + if (USBD_HAL_IsHighSpeed() && pDescList->pHsConfiguration) + pCfg = (USBConfigurationDescriptor *)pDescList->pHsConfiguration; + else + pCfg = (USBConfigurationDescriptor *)pDescList->pFsConfiguration; + + return pCfg; +} + +/** + * 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) +{ + uint8_t cfgnum; + uint8_t infnum; + uint8_t eptnum; + uint8_t setting; + uint8_t type; + uint8_t indexDesc; + uint32_t length; + uint32_t 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; + case USBFeatureRequest_OTG_B_HNP_ENABLE: + TRACE_INFO_WP("OTG_B_HNP_ENABLE "); + pDriver->otg_features_supported |= + 1<otg_features_supported |= + 1<otg_features_supported |= + 1<isRemoteWakeUpEnabled; +} + +/** + * Return OTG features supported + * \param pDriver Pointer to an USBDDriver instance. + * \return the OTG features + */ +uint8_t USBDDriver_returnOTGFeatures(const USBDDriver *pDriver) +{ + return pDriver->otg_features_supported; +} + +/** + * Clear OTG features supported + * \param pDriver Pointer to an USBDDriver instance. + * \return none + */ +void USBDDriver_clearOTGFeatures(USBDDriver *pDriver) +{ + pDriver->otg_features_supported = 0; +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriverCallbacks.c b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriverCallbacks.c new file mode 100644 index 00000000..da8958c2 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/core/USBDDriverCallbacks.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * \section Purpose + * + * Definition of several callbacks which are triggered by the USB software + * driver after receiving specific requests. + * + * \section 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. + * + * \addtogroup usbd_interface + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ +#include "board.h" +#include "USBDDriver.h" +/*------------------------------------------------------------------------------ + * Global functions + *------------------------------------------------------------------------------*/ + +/** + * Indicates that the current configuration of the device has changed. + * \param cfgnum New device configuration index. + */ +WEAK void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) +{ + TRACE_INFO_WP("cfgChanged%d ", cfgnum); +} + +/** + * 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. + */ +WEAK void USBDDriverCallbacks_InterfaceSettingChanged( + uint8_t interface, + uint8_t setting) +{ + TRACE_INFO_WP("ifSettingChanged%d.%d ", interface, setting); +} +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDClassArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDClassArch.png new file mode 100644 index 0000000000000000000000000000000000000000..6d0958075cd5c5eff5ac1874cac0786013bf4648 GIT binary patch literal 3495 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 Jmvv4FO#ro>ROkQz literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboard.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboard.c new file mode 100644 index 00000000..76a40a86 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboard.c @@ -0,0 +1,374 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_hid_key + *@{ + * Implement HID Keyboard Function For USB Device. + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Internal types + *------------------------------------------------------------------------------*/ + +/** + * Extended struct for an HID Keyboard Input report, for transfer driver to + * send reports. + */ +typedef struct _KBDInputReport { + /** Callback when report done */ + HIDDReportEventCallback fCallback; + /** Callback arguments */ + void* pArg; + + /** Report size (ID + DATA) */ + uint16_t wMaxSize; + /** Transfered size */ + uint16_t wTransferred; + /** Report idle rate */ + uint8_t bIdleRate; + /** Delay count for Idle */ + uint8_t bDelay; + /** Report ID */ + uint8_t bID; + /** Input Report Data Block */ + HIDDKeyboardInputReport sReport; +} KBDInputReport; + +/** + * Extended struct for an HID Keyboard Output report, for transfer driver to + * polling reports. + */ +typedef struct _KBDOutputReport { + /** Callback when report done */ + HIDDReportEventCallback fCallback; + /** Callback arguments */ + void* pArg; + + /** Report size (ID + DATA) */ + uint16_t wMaxSize; + /** Transfered size */ + uint16_t wTransferred; + /** Report idle rate */ + uint8_t bIdleRate; + /** Delay count for Idle */ + uint8_t bDelay; + /** Report ID */ + uint8_t bID; + /** Output Report Data Block */ + HIDDKeyboardOutputReport sReport; +} KBDOutputReport; + +/** + * Driver structure for an HID device implementing keyboard functionalities. + */ +typedef struct _HIDDKeyboard { + + /** USB HID Functionn */ + HIDDFunction hidDrv; + /** Input report list */ + HIDDReport *inputReports[1]; + /** Output report list */ + HIDDReport *outputReports[1]; +} HIDDKeyboard; + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/** HIDD Keyboard Input Report Instance */ +static KBDInputReport inputReport; + +/** HIDD Keyboard Output Report Instance */ +static KBDOutputReport outputReport; + +/** Static instance of the HIDD keyboard device driver. */ +static HIDDKeyboard hiddKeyboard; + +/** Report descriptor used by the driver. */ +const uint8_t hiddKeyboardReportDescriptor[] = { + + 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, + HIDDKeyboardDescriptors_FIRSTMODIFIERKEY, + HIDReport_LOCAL_USAGEMAXIMUM + 1, + HIDDKeyboardDescriptors_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, + HIDDKeyboardDescriptors_FIRSTSTANDARDKEY, + HIDReport_GLOBAL_LOGICALMAXIMUM + 1, + HIDDKeyboardDescriptors_LASTSTANDARDKEY, + HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID, + HIDReport_LOCAL_USAGEMINIMUM + 1, + HIDDKeyboardDescriptors_FIRSTSTANDARDKEY, + HIDReport_LOCAL_USAGEMAXIMUM + 1, + HIDDKeyboardDescriptors_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 +}; + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/** + * 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 HIDDKeyboard_ReportReceived(void) +{ + HIDDKeyboardOutputReport *pOut = &outputReport.sReport; + + /* Trigger callback */ + if (HIDDKeyboardCallbacks_LedsChanged) { + HIDDKeyboardCallbacks_LedsChanged( + pOut->numLockStatus, + pOut->capsLockStatus, + pOut->scrollLockStatus); + } +} + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes the HID keyboard device driver SW. + * (Init USBDDriver .., Init function driver .., Init USBD ...) + * \param pUsbd Pointer to USBDDriver instance. + * \param bInterfaceNb Interface number for the function. + */ +void HIDDKeyboard_Initialize(USBDDriver* pUsbd, uint8_t bInterfaceNb) +{ + HIDDKeyboard *pKbd = &hiddKeyboard; + HIDDFunction *pHidd = &pKbd->hidDrv; + + /* One input report */ + pKbd->inputReports[0] = (HIDDReport*)&inputReport; + HIDDFunction_InitializeReport(pKbd->inputReports[0], + sizeof(HIDDKeyboardInputReport), + 0, + 0, 0); + /* One output report */ + pKbd->outputReports[0] = (HIDDReport*)&outputReport; + HIDDFunction_InitializeReport( + pKbd->outputReports[0], + sizeof(HIDDKeyboardOutputReport), + 0, + (HIDDReportEventCallback)HIDDKeyboard_ReportReceived, 0); + + /* Function initialize */ + HIDDFunction_Initialize(pHidd, + pUsbd, bInterfaceNb, + hiddKeyboardReportDescriptor, + pKbd->inputReports, 1, + pKbd->outputReports, 1); +} + +/** + * Configure function with expected descriptors and start functionality. + * Usually invoked when device is configured. + * \pDescriptors Pointer to the descriptors for function configure. + * \wLength Length of descriptors in number of bytes. + */ +void HIDDKeyboard_ConfigureFunction(USBGenericDescriptor *pDescriptors, + uint16_t wLength) +{ + HIDDKeyboard *pKbd = &hiddKeyboard; + HIDDFunction *pHidd = &pKbd->hidDrv; + USBGenericDescriptor * pDesc = pDescriptors; + + pDesc = HIDDFunction_ParseInterface(pHidd, + pDescriptors, + wLength); + + /* Start receiving output reports */ + HIDDFunction_StartPollingOutputs(pHidd); +} + +/** + * Handles HID-specific SETUP request sent by the host. + * \param request Pointer to a USBGenericRequest instance. + * \return USBRC_SUCCESS if request is handled. + */ +uint32_t HIDDKeyboard_RequestHandler(const USBGenericRequest *request) +{ + HIDDKeyboard *pKbd = &hiddKeyboard; + HIDDFunction *pHidd = &pKbd->hidDrv; + + TRACE_INFO_WP("Kbd "); + + /* Process HID requests */ + return HIDDFunction_RequestHandler(pHidd, request); +} + +/** + * 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. + */ +uint32_t HIDDKeyboard_ChangeKeys(uint8_t *pressedKeys, + uint8_t pressedKeysSize, + uint8_t *releasedKeys, + uint8_t releasedKeysSize) +{ + HIDDKeyboard *pKbd = &hiddKeyboard; + HIDDFunction *pHidd = &pKbd->hidDrv; + HIDDKeyboardInputReport *pReport = + (HIDDKeyboardInputReport *)pKbd->inputReports[0]->bData; + + /* 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( + pReport, + *pressedKeys); + } + else { + + HIDDKeyboardInputReport_PressStandardKey( + pReport, + *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( + pReport, + *releasedKeys); + } + else { + + HIDDKeyboardInputReport_ReleaseStandardKey( + pReport, + *releasedKeys); + } + + releasedKeysSize--; + releasedKeys++; + } + + /* Send input report through the interrupt IN endpoint */ + return USBD_Write(pHidd->bPipeIN, + pReport, + 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 HIDDKeyboard_RemoteWakeUp(void) +{ + HIDDKeyboard *pKbd = &hiddKeyboard; + HIDDFunction *pHidd = &pKbd->hidDrv; + USBDDriver *pUsbd = pHidd->pUsbd; + + /* Remote wake-up has been enabled */ + if (USBDDriver_IsRemoteWakeUpEnabled(pUsbd)) { + + USBD_RemoteWakeUp(); + } +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c new file mode 100644 index 00000000..3aaed0ad --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_hid_key + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "HIDDKeyboardDriver.h" +#include + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * For HID Keyboard Function. + * 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. + */ +WEAK void HIDDKeyboardCallbacks_LedsChanged( + uint8_t numLockStatus, + uint8_t capsLockStatus, + uint8_t scrollLockStatus) +{ + TRACE_INFO( + "LEDs status: %d, %d, %d\n\r", + numLockStatus, + capsLockStatus, + scrollLockStatus); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardDriver.c new file mode 100644 index 00000000..a9aba272 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardDriver.c @@ -0,0 +1,123 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_hid_key + *@{ + * Implement a USB device that only have HID Keyboard Function. + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Internal types + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes the HID keyboard device driver. + */ +void HIDDKeyboardDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBDDriver_Initialize(pUsbd, pDescriptors, 0); + HIDDKeyboard_Initialize(pUsbd, 0); + USBD_Init(); +} + +/** + * Handles configureation changed event. + * \param cfgnum New configuration number + */ +void HIDDKeyboardDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + const USBDDriverDescriptors * pDescriptors = pUsbd->pDescriptors; + USBConfigurationDescriptor *pDesc; + + if (cfgnum > 0) { + if (USBD_HAL_IsHighSpeed() && pDescriptors->pHsConfiguration) + pDesc = (USBConfigurationDescriptor*)pDescriptors->pHsConfiguration; + else + pDesc = (USBConfigurationDescriptor*)pDescriptors->pFsConfiguration; + HIDDKeyboard_ConfigureFunction((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * Handles HID-specific SETUP request sent by the host. + * \param request Pointer to a USBGenericRequest instance. + */ +void HIDDKeyboardDriver_RequestHandler(const USBGenericRequest *request) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + + TRACE_INFO_WP("NewReq "); + + /* Process HID requests */ + if (USBRC_SUCCESS == HIDDKeyboard_RequestHandler(request)) { + return; + } + /* Process STD requests */ + else { + USBDDriver_RequestHandler(pUsbd, request); + } +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardInputReport.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardInputReport.c new file mode 100644 index 00000000..99c04fca --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardInputReport.c @@ -0,0 +1,147 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Implementation of the HIDDKeyboardInputReport class. + */ + +/** \addtogroup usbd_hid_key + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes a keyboard input report instance. + * \param report Pointer to a HIDDKeyboardInputReport instance. + */ +void HIDDKeyboardInputReport_Initialize(HIDDKeyboardInputReport *report) +{ + uint32_t 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, + uint8_t key) +{ + /* Find first available slot */ + uint32_t i = 0; + uint8_t 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, + uint8_t key) +{ + /* Look for key in array */ + uint32_t i = 0; + uint8_t 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, + uint8_t key) +{ + /* Set corresponding bit */ + uint8_t bit = key - HIDDKeyboardDescriptors_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, + uint8_t key) +{ + /* Clear corresponding bit */ + uint8_t bit = key - HIDDKeyboardDescriptors_FIRSTMODIFIERKEY; + report->bmModifierKeys &= ~(1 << bit); +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c new file mode 100644 index 00000000..adcd1037 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Implementation of the HIDDKeyboardOutputReport class. + */ + +/** \addtogroup usbd_hid_key + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +/*------------------------------------------------------------------------------ + * 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/sam3s_example/atmel_softpack_libraries/usb/device/hid-mouse/HIDDMouseDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-mouse/HIDDMouseDriver.c new file mode 100644 index 00000000..f42a8fa0 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-mouse/HIDDMouseDriver.c @@ -0,0 +1,277 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_hid_mouse + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include + +#include +#include +#include + +#include + +/*------------------------------------------------------------------------------ + * 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 + *------------------------------------------------------------------------------*/ + +/** + * Struct for an HID Mouse report. + */ +typedef struct _HIDDMouseReport { + /** Callback when report done */ + HIDDReportEventCallback fCallback; + /** Callback arguments */ + void* pArg; + + /** Report size (ID + DATA) */ + uint16_t wMaxSize; + /** Transfered size */ + uint16_t wTransferred; + /** Report idle rate */ + uint8_t bIdleRate; + /** Delay count for Idle */ + uint8_t bDelay; + /** Report ID */ + uint8_t bID; + /** Report data block */ + HIDDMouseInputReport report; +} HIDDMouseReport; + +/** + * Driver structure for an HID device implementing keyboard functionalities. + */ +typedef struct _HIDDMouseDriver { + + /** Mouse function instance */ + HIDDFunction hidDrv; + /** Mouse input report */ + HIDDReport *inputReports[1]; +} HIDDMouseDriver; + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/** Static instance of the HID mouse device driver. */ +static HIDDMouseDriver hiddMouseDriver; +/** Input report */ +static HIDDMouseReport hiddInputReport; + +/** Report descriptor used by the driver. */ +static const uint8_t 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, (uint8_t) -127, + HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 127, + HIDReport_INPUT + 1, HIDReport_VARIABLE | HIDReport_RELATIVE, + + HIDReport_ENDCOLLECTION, + HIDReport_ENDCOLLECTION +}; + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes the HID Mouse %device driver. + * \param pDescriptors Pointer to descriptor list for the HID Mouse. + */ +void HIDDMouseDriver_Initialize(const USBDDriverDescriptors *pDescriptors) +{ + HIDDMouseDriver* pMouse = &hiddMouseDriver; + HIDDFunction* pHidd = &pMouse->hidDrv; + USBDDriver* pUsbd = USBD_GetDriver(); + + /* One input report */ + pMouse->inputReports[0] = (HIDDReport*)&hiddInputReport; + HIDDFunction_InitializeReport(pMouse->inputReports[0], + HIDDMouseDriver_REPORTDESCRIPTORSIZE, + 0, + 0, 0); + + /* Initialize USBD Driver instance */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + 0); /* Multiple interface settings not supported */ + /* Function initialize */ + HIDDFunction_Initialize(pHidd, + pUsbd, 0, + hiddReportDescriptor, + (HIDDReport**)(&pMouse->inputReports), 1, + 0, 0); + USBD_Init(); +} + +/** + * Handles configureation changed event. + * \param cfgnum New configuration number + */ +void HIDDMouseDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + HIDDMouseDriver * pMouse = &hiddMouseDriver; + HIDDFunction * pHidd = &pMouse->hidDrv; + USBDDriver * pUsbd = pHidd->pUsbd; + USBConfigurationDescriptor *pDesc; + + if (cfgnum > 0) { + + /* Parse endpoints for reports */ + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + HIDDFunction_ParseInterface(pHidd, + (USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * Handles HID-specific SETUP request sent by the host. + * \param request Pointer to a USBGenericRequest instance + */ +void HIDDMouseDriver_RequestHandler(const USBGenericRequest *request) +{ + HIDDMouseDriver * pMouse = &hiddMouseDriver; + HIDDFunction * pHidd = &pMouse->hidDrv; + USBDDriver * pUsbd = pHidd->pUsbd; + + TRACE_INFO("NewReq "); + + /* Process HID requests */ + if (USBRC_SUCCESS == HIDDFunction_RequestHandler(pHidd, + request)) { + return; + } + /* Process STD requests */ + else { + + USBDDriver_RequestHandler(pUsbd, request); + } + +} + +/** + * 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 + */ +uint8_t HIDDMouseDriver_ChangePoints(uint8_t bmButtons, + int8_t deltaX, + int8_t deltaY) +{ + HIDDMouseDriver * pMouse = &hiddMouseDriver; + HIDDFunction * pHidd = &pMouse->hidDrv; + HIDDMouseInputReport * pReport = &hiddInputReport.report; + + pReport->bmButtons = (bmButtons & 0x07) | HIDDMouse_TAG; + pReport->bX = deltaX; + pReport->bY = deltaY; + + /* Send input report through the interrupt IN endpoint */ + return USBD_Write(pHidd->bPipeIN, + (void*)pReport, + 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) +{ + HIDDMouseDriver * pMouse = &hiddMouseDriver; + HIDDFunction * pHidd = &pMouse->hidDrv; + USBDDriver * pUsbd = pHidd->pUsbd; + + /* Remote wake-up has been enabled */ + if (USBDDriver_IsRemoteWakeUpEnabled(pUsbd)) { + + USBD_RemoteWakeUp(); + } +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDFunction.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDFunction.c new file mode 100644 index 00000000..10ddd961 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDFunction.c @@ -0,0 +1,695 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Implementation of the HIDDFunction class methods. + */ +/** \addtogroup usbd_hid + * @{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include +#include + +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Macros + *------------------------------------------------------------------------------*/ + +/** + * Get byte pointer + */ +#define _PU8(v) ((uint8_t*)&(v)) + +/** + * Get word from un-aligned value + */ +#define _Word(a) (_PU8(a)[0] + (_PU8(a)[1] << 8)) + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** Parse data extention for descriptor parsing */ +typedef struct _HIDDParseData { + HIDDFunction * pHidd; + USBInterfaceDescriptor * pIfDesc; +} HIDDParseData; + +/** Parse data extension for HID descriptor */ + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Internal functions + *------------------------------------------------------------------------------*/ + +/** + * Returns the descriptor requested by the host. + * \param pHidd Pointer to HIDDFunction instance + * \param bType Descriptor type. + * \param wLength Maximum number of bytes to send. + * \return USBRC_SUCCESS if the request has been handled by this function, + * otherwise USBRC_PARAM_ERR. + */ +static uint32_t HIDDFunction_GetDescriptor(HIDDFunction *pHidd, + uint8_t bType, + uint32_t wLength) +{ + HIDDescriptor1 *pHidDescriptor = (HIDDescriptor1 *)pHidd->pHidDescriptor; + uint16_t wDescriptorLength; + + TRACE_INFO_WP("gDesc{%x) ", bType); + + switch (bType) { + + case HIDGenericDescriptor_REPORT: + + /* Adjust length and send report descriptor */ + /* + wDescriptorLength = pHidDescriptor->bDescriptorLength0[0] + + pHidDescriptor->bDescriptorLength0[1]; + */ + wDescriptorLength = _Word(pHidDescriptor->wDescriptorLength0); + if (wLength > wDescriptorLength) + wLength = wDescriptorLength; + + TRACE_INFO_WP("Report(%d) ", wLength); + + USBD_Write(0, pHidd->pReportDescriptor, wLength, 0, 0); + break; + + case HIDGenericDescriptor_HID: + + /* Adjust length and send HID descriptor */ + if (wLength > sizeof(HIDDescriptor1)) + wLength = sizeof(HIDDescriptor1); + + TRACE_INFO_WP("HID(%d) ", wLength); + + USBD_Write(0, pHidDescriptor, wLength, 0, 0); + break; + + default: + return USBRC_PARAM_ERR; + } + + return USBRC_SUCCESS; +} + +/** + * Return expected report header pointer. + * \param pHidd Pointer to HIDDFunction instance + * \param bType Report type. + * \param bID Report ID. + */ +static HIDDReport* HIDDFunction_FindReport(const HIDDFunction *pHidd, + uint8_t bType, + uint8_t bID) +{ + HIDDReport** pReportList; + int32_t listSize, i; + switch(bType) { + case HIDReportRequest_INPUT: + pReportList = pHidd->pInputList; + listSize = pHidd->bInputListSize; + break; + case HIDReportRequest_OUTPUT: + pReportList = pHidd->pOutputList; + listSize = pHidd->bOutputListSize; + break; + /* No other reports supported */ + default: + TRACE_INFO("Report %x.%x not support\n\r", bType, bID); + return 0; + } + /* No list */ + if (pReportList == 0) + return 0; + /* Find report in the list */ + for (i = 0; i < listSize; i ++) { + if (bID == pReportList[i]->bID) + return pReportList[i]; + } + /* Not found */ + return 0; +} + +/** + * Sends the current Idle rate of the input report to the host. + * \param pHidd Pointer to HIDDFunction instance + * \param bID Report ID + */ +static void HIDDFunction_GetIdle(HIDDFunction *pHidd, + uint8_t bID) +{ + HIDDReport *pReport = HIDDFunction_FindReport(pHidd, + HIDReportRequest_INPUT, + bID); + TRACE_INFO_WP("gIdle(%x) ", bID); + if (pReport == 0) { + USBD_Stall(0); + return; + } + USBD_Write(0, &pReport->bIdleRate, 1, 0, 0); +} + +/** + * Retrieves the new idle rate of the input report from the USB host. + * \param pHidd Pointer to HIDDFunction instance + * \param bType Report type + * \param bID Report ID + * \param bIdleRate Report idle rate. + */ +static void HIDDFunction_SetIdle(HIDDFunction *pHidd, + uint8_t bID, + uint8_t bIdleRate) +{ + HIDDReport *pReport = HIDDFunction_FindReport(pHidd, + HIDReportRequest_INPUT, + bID); + TRACE_INFO_WP("sIdle(%x<%x) ", bID, bIdleRate); + if (pReport == 0) { + USBD_Stall(0); + return; + } + USBD_Write(0, 0, 0, 0, 0); +} + +/** + * Callback function when GetReport request data sent to host + * \param pReport Pointer to report information. + * \param status Result status + * \param transferred Number of bytes transferred + * \param remaining Number of bytes that are not transferred yet + */ +static void _GetReportCallback(HIDDReport *pReport, + uint8_t status, + uint32_t transferred, + uint32_t remaining) +{ + pReport->wTransferred = transferred; + if (pReport->fCallback) + pReport->fCallback(HIDD_EC_GETREPORT, pReport->pArg); + + USBD_Read(0, 0, 0, 0, 0); +} + +/** + * Sends the requested report to the host. + * \param pHidd Pointer to HIDDFunction instance + * \param bType Report type. + * \param bID Report ID. + * \param wLength Maximum number of bytes to send. + */ +static void HIDDFunction_GetReport(HIDDFunction *pHidd, + uint8_t bType, + uint8_t bID, + uint8_t wLength) +{ + HIDDReport *pReport = HIDDFunction_FindReport(pHidd, + bType, + bID); + TRACE_INFO_WP("gReport(%x.%x) ", bType, bID); + if (pReport == 0) { + USBD_Stall(0); + return; + } + if (wLength >= pReport->wMaxSize) { + wLength = pReport->wMaxSize; + } + USBD_Write(0, pReport->bData, wLength, + (TransferCallback)_GetReportCallback, pReport); +} + +/** + * Callback function when GetReport request data sent to host + * \param pReport Pointer to report information. + * \param status Result status + * \param transferred Number of bytes transferred + * \param remaining Number of bytes that are not transferred yet + */ +static void _SetReportCallback(HIDDReport *pReport, + uint8_t status, + uint32_t transferred, + uint32_t remaining) +{ + pReport->wTransferred = transferred; + if (pReport->fCallback) { + pReport->fCallback(HIDD_EC_SETREPORT, pReport->pArg); + } +} + +/** + * Reads the requested report from the host. + * \param pHidd Pointer to HIDDFunction instance + * \param bType Report type. + * \param bID Report ID. + * \param wLength Maximum number of bytes to read. + */ +static void HIDDFunction_SetReport(HIDDFunction *pHidd, + uint8_t bType, + uint8_t bID, + uint8_t wLength) +{ + HIDDReport *pReport = HIDDFunction_FindReport(pHidd, + bType, + bID); + TRACE_INFO_WP("sReport(%x.%x) ", bType, bID); + + if (pReport == 0) { + USBD_Stall(0); + return; + } + + if (wLength >= pReport->wMaxSize) { + wLength = pReport->wMaxSize; + } + USBD_Read(0, pReport->bData, wLength, + (TransferCallback)_SetReportCallback, pReport); +} + +/** + * Parse descriptors: Interface, Interrupt IN/OUT. + * \param desc Pointer to descriptor list. + * \param arg Argument, pointer to HIDDParseData instance. + */ +static uint32_t HIDDFunction_Parse(USBGenericDescriptor * pDesc, + HIDDParseData * pArg) +{ + /* Find HID Interface */ + if (pArg->pIfDesc == 0) { + if (pDesc->bDescriptorType == USBGenericDescriptor_INTERFACE) { + USBInterfaceDescriptor *pIf = (USBInterfaceDescriptor*)pDesc; + /* Right interface for HID: + HID Class + at least 1 endpoint */ + if (pIf->bInterfaceClass == HIDInterfaceDescriptor_CLASS + && pIf->bNumEndpoints >= 1) { + /* Obtain new interface setting */ + if (pArg->pHidd->bInterface == 0xFF) { + pArg->pHidd->bInterface = pIf->bInterfaceNumber; + pArg->pIfDesc = pIf; + } + /* Find specific interface setting */ + else if (pArg->pHidd->bInterface == pIf->bInterfaceNumber) { + pArg->pIfDesc = pIf; + } + } + } + } + /* Interface end */ + else { + /* Start another interface ? */ + if (pDesc->bDescriptorType == USBGenericDescriptor_INTERFACE) { + /* Terminate the parse */ + return USBRC_PARTIAL_DONE; + } + /* Parse HID descriptor */ + else if (pDesc->bDescriptorType == HIDGenericDescriptor_HID) { + pArg->pHidd->pHidDescriptor = (HIDDescriptor*)pDesc; + } + /* Parse endpoints */ + else if (pDesc->bDescriptorType == USBGenericDescriptor_ENDPOINT) { + USBEndpointDescriptor *pEp = (USBEndpointDescriptor*)pDesc; + if (pEp->bEndpointAddress & 0x80) + pArg->pHidd->bPipeIN = pEp->bEndpointAddress & 0x7F; + else + pArg->pHidd->bPipeOUT = pEp->bEndpointAddress; + } + + /* Check if all data is OK */ + if (pArg->pHidd->bInterface != 0xFF + && pArg->pHidd->bPipeIN != 0xFF + && pArg->pHidd->bPipeOUT != 0xFF) + return USBRC_FINISHED; + } + return 0; +} + +/** + * Callback function when interrupt OUT data received from host + * \param pHidd Pointer to HIDDFunction instance + * \param status Result status + * \param transferred Number of bytes transferred + * \param remaining Number of bytes that are not transferred yet + */ +static void HIDDFunction_ReportReceived(HIDDFunction *pHidd, + uint8_t status, + uint32_t transferred, + uint32_t remaining) +{ + HIDDReport *pOut = pHidd->pOutputList[pHidd->bCurrOutput]; + if (status != USBRC_SUCCESS) { + + TRACE_ERROR("HIDDFun::ReadReport: %x\n\r", status); + return; + } + + /* Transfered information */ + pOut->wTransferred = transferred; + + /* Data Change callback */ + if (pOut->fCallback) + pOut->fCallback(HIDD_EC_REPORTCHANGED, pOut->pArg); + + /* Proceed to next output report */ + pHidd->bCurrOutput ++; + if (pHidd->bCurrOutput >= pHidd->bOutputListSize) + pHidd->bCurrOutput = 0; + + /* Start reading a report */ + USBD_Read(pHidd->bPipeOUT, + pHidd->pOutputList[pHidd->bCurrOutput]->bData, + pHidd->pOutputList[pHidd->bCurrOutput]->wMaxSize, + (TransferCallback)HIDDFunction_ReportReceived, + (void*)pHidd); +} + +/** + * Callback function when interrupt IN data sent to host + * \param pHidd Pointer to HIDDFunction instance + * \param status Result status + * \param transferred Number of bytes transferred + * \param remaining Number of bytes that are not transferred yet + */ +static void HIDDFunction_ReportSent(HIDDFunction *pHidd, + uint8_t status, + uint32_t transferred, + uint32_t remaining) +{ + HIDDReport *pIn = pHidd->pInputList[pHidd->bCurrInput]; + if (status != USBRC_SUCCESS) { + + TRACE_ERROR("HIDDFun::WriteReport: %x\n\r", status); + return; + } + + /* Transfered information */ + pIn->wTransferred = transferred; + + /* Report Sent Callback */ + if (pIn->fCallback) + pIn->fCallback(HIDD_EC_REPORTSENT, pIn->pArg); + + /* Proceed to next output report */ + pHidd->bCurrInput ++; + if (pHidd->bCurrInput >= pHidd->bInputListSize) + pHidd->bCurrInput = 0; + + /* Start writing a report */ + USBD_Write(pHidd->bPipeIN, + pHidd->pInputList[pHidd->bCurrInput]->bData, + pHidd->pInputList[pHidd->bCurrInput]->wMaxSize, + (TransferCallback)HIDDFunction_ReportReceived, + (void*)pHidd); +} + + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initialize the USB Device HID function, for general HID device support. + * \param pHidd Pointer to HIDDFunction instance. + * \param pUsbd Pointer to USBDDriver instance. + * \param bInterfaceNb Interface number, + * can be 0xFF to obtain from descriptors. + * \param pReportDescriptor Pointer to report descriptor. + * \param pInputList Pointer to an HID input report list + * \param bInputListSize HID input report list size + * \param pOutputList Pointer to an HID output report list + * \param bOutputListSize HID output report list size + */ +void HIDDFunction_Initialize(HIDDFunction * pHidd, + USBDDriver * pUsbd, uint8_t bInterfaceNb, + const uint8_t * pReportDescriptor, + HIDDReport* pInputList[], uint8_t bInputListSize, + HIDDReport* pOutputList[], uint8_t bOutputListSize) +{ + TRACE_INFO("HIDDFunction_Initialize\n\r"); + + pHidd->pUsbd = pUsbd; + pHidd->pReportDescriptor = (uint8_t *)pReportDescriptor; + pHidd->pHidDescriptor = 0; + + pHidd->bInterface = bInterfaceNb; + pHidd->bPipeIN = 0xFF; + pHidd->bPipeOUT = 0xFF; + pHidd->bProtocol = HIDProtocol_REPORT; /* Non-boot protocol */ + + pHidd->pInputList = pInputList; + pHidd->pOutputList = pOutputList; + pHidd->bInputListSize = bInputListSize; + pHidd->bOutputListSize = bOutputListSize; + pHidd->bCurrInput = 0; + pHidd->bCurrOutput = 0; + +} + +/** + * Parse the USB HID Function Interface. + * Only first interface and its endpoints parsed. + * \param pHidd Pointer to HIDDFunction instance. + * \param pDescriptors Pointer to descriptor list. + * \param dwLength Descriptor list block length in bytes. + * \return Pointer to next descriptor. 0 means no other descriptor. + */ +USBGenericDescriptor *HIDDFunction_ParseInterface(HIDDFunction * pHidd, + USBGenericDescriptor * pDescriptors, + uint32_t dwLength) +{ + HIDDParseData data; + pHidd->bPipeIN = 0xFF; + pHidd->bPipeOUT = 0xFF; + data.pHidd = pHidd; + data.pIfDesc = 0; + return USBGenericDescriptor_Parse(pDescriptors, + dwLength, + (USBDescriptorParseFunction)HIDDFunction_Parse, + (void*)&data); +} + +/** + * Start polling interrupt OUT pipe + * (output report, host to device) if there is. + * \param pHidd Pointer to HIDDFunction instance. + */ +uint32_t HIDDFunction_StartPollingOutputs(HIDDFunction * pHidd) +{ + /* No report, do nothing */ + if (pHidd->bOutputListSize == 0 + || pHidd->pOutputList == 0) + return USBRC_PARAM_ERR; + + /* Start reading a report */ + return USBD_Read(pHidd->bPipeOUT, + pHidd->pOutputList[pHidd->bCurrOutput]->bData, + pHidd->pOutputList[pHidd->bCurrOutput]->wMaxSize, + (TransferCallback)HIDDFunction_ReportReceived, + (void*)pHidd); +} + +/** + * Start sending reports via interrupt IN pipe + * (input report, device to host) if there is. + * \param pHidd Pointer to HIDDFunction instance. + */ +uint32_t HIDDFunction_StartSendingInputs(HIDDFunction * pHidd) +{ + /* No report, do nothing */ + if (pHidd->bInputListSize == 0 + || pHidd->pInputList == 0) + return USBRC_PARAM_ERR; + /* Start sending a report */ + return USBD_Write(pHidd->bPipeIN, + pHidd->pInputList[pHidd->bCurrInput]->bData, + pHidd->pInputList[pHidd->bCurrInput]->wMaxSize, + (TransferCallback)HIDDFunction_ReportSent, + (void*)pHidd); +} + +/** + * Handles HID-specific SETUP request sent by the host. + * \param pHidd Pointer to HIDDFunction instance. + * \param request Pointer to a USBGenericRequest instance + */ +uint32_t HIDDFunction_RequestHandler(HIDDFunction *pHidd, + const USBGenericRequest *request) +{ + uint32_t reqCode = (request->bmRequestType << 8) + | (request->bRequest); + + switch (reqCode) { + /* Get_Descriptor */ + case USBGenericRequest_GETDESCRIPTOR|(0x81<<8): + return HIDDFunction_GetDescriptor( + pHidd, + USBGetDescriptorRequest_GetDescriptorType(request), + USBGenericRequest_GetLength(request)); + /* Clear_Feature (EP) */ + case USBGenericRequest_CLEARFEATURE|(0x02<<8): + if (USBFeatureRequest_GetFeatureSelector(request) + == USBFeatureRequest_ENDPOINTHALT) { + uint8_t ep = USBGenericRequest_GetEndpointNumber(request); + if (USBD_IsHalted(ep)) { + /* Unhalt EP */ + USBD_Unhalt(ep); + /* Restart Polling OUT */ + if (ep == pHidd->bPipeOUT) { + HIDDFunction_StartPollingOutputs(pHidd); + } + /* and send a zero-length packet */ + USBD_Write(0, 0, 0, 0, 0); + } + break; /* Handled success */ + } + return USBRC_PARAM_ERR; + /* Set_Descriptor */ + case USBGenericRequest_SETDESCRIPTOR|(0x01<<8): + /* Optional, not implemented */ + USBD_Stall(0); + break; + /* Get_Idle */ + case (0xa1<<8)|HIDGenericRequest_GETIDLE: + HIDDFunction_GetIdle(pHidd, + HIDReportRequest_GetReportId(request)); + break; + /* Set_Idle */ + case (0x21<<8)|HIDGenericRequest_SETIDLE: + HIDDFunction_SetIdle(pHidd, + HIDReportRequest_GetReportId(request), + HIDIdleRequest_GetIdleRate(request)); + break; + /* Get_Report */ + case (0xa1<<8)|HIDGenericRequest_GETREPORT: + HIDDFunction_GetReport(pHidd, + HIDReportRequest_GetReportType(request), + HIDReportRequest_GetReportId(request), + USBGenericRequest_GetLength(request)); + break; + /* Set_Report */ + case (0x21<<8)|HIDGenericRequest_SETREPORT: + HIDDFunction_SetReport(pHidd, + HIDReportRequest_GetReportType(request), + HIDReportRequest_GetReportId(request), + USBGenericRequest_GetLength(request)); + break; + /* Get_Protocol */ + case (0xa1<<8)|HIDGenericRequest_SETPROTOCOL: + pHidd->bProtocol = request->wValue; + USBD_Write(0, 0, 0, 0, 0); + break; + /* Set_Protocol */ + case (0x21<<8)|HIDGenericRequest_GETPROTOCOL: + USBD_Write(0, &pHidd->bProtocol, 1, 0, 0); + break; + + default: + return USBRC_PARAM_ERR; + } + return USBRC_SUCCESS; +} + +/** + * Read raw data through USB interrupt OUT EP. + * \param pHidd Pointer to HIDDFunction instance. + * \param pData Pointer to the data buffer. + * \param dwLength The data length. + * \param fCallback Callback function invoked when transferring done. + * \param pArg Pointer to additional arguments. + */ +uint32_t HIDDFunction_Read(const HIDDFunction *pHidd, + void* pData, + uint32_t dwLength, + TransferCallback fCallback, + void* pArg) +{ + return USBD_Read(pHidd->bPipeIN, + pData, dwLength, + fCallback, pArg); +} + +/** + * Write raw data through USB interrupt IN EP. + * \param pHidd Pointer to HIDDFunction instance. + * \param pData Pointer to the data sent. + * \param dwLength The data length. + * \param fCallback Callback function invoked when transferring done. + * \param pArg Pointer to additional arguments. + */ +uint32_t HIDDFunction_Write(const HIDDFunction *pHidd, + void* pData, + uint32_t dwLength, + TransferCallback fCallback, + void* pArg) +{ + return USBD_Write(pHidd->bPipeIN, + pData, dwLength, + fCallback, pArg); +} + +/** + * Initialize a report. + * \param pReport Pointer to HIDDReport instance. + * \param wSize Size of the report data. + * \param bID Report ID. + * \param fCallback Callback function for report events. + * \param pArg Pointer to event handler arguments. + */ +void HIDDFunction_InitializeReport(HIDDReport* pReport, + uint16_t wSize, + uint8_t bID, + HIDDReportEventCallback fCallback, + void* pArg) +{ + pReport->wMaxSize = wSize; + pReport->wTransferred = 0; + pReport->bIdleRate = 0; + pReport->bDelay = 0; + pReport->bID = bID; + + pReport->fCallback = fCallback; + pReport->pArg = pArg; +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDTransferDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDTransferDriver.c new file mode 100644 index 00000000..0466f401 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/hid-transfer/HIDDTransferDriver.c @@ -0,0 +1,481 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_hid_tran + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include "HIDDTransferDriver.h" +#include + +#include +#include +#include + +#include + +#include + +/*------------------------------------------------------------------------------ + * Internal types + *------------------------------------------------------------------------------*/ + +/** + * Report struct for HID transfer. + */ +typedef struct _HIDDTransferReport { + /** Callback when report done */ + HIDDReportEventCallback fCallback; + /** Callback arguments */ + void* pArg; + + /** Report size (ID + DATA) */ + uint16_t wMaxSize; + /** Transfered size */ + uint16_t wTransferred; + /** Report idle rate */ + uint8_t bIdleRate; + /** Delay count for Idle */ + uint8_t bDelay; + /** Report ID */ + uint8_t bID; + /** Report data address */ + uint8_t bData[HIDDTransferDriver_REPORTSIZE]; +} HIDDTransferReport; + +/** + * Driver structure for an HID device implementing simple transfer + * functionalities. + */ +typedef struct _HIDDTransferDriver { + + /** Standard HID function interface. */ + HIDDFunction hidFunction; + + /** HID Input report list */ + HIDDReport *inputReports[1]; + /** HID Output report list */ + HIDDReport *outputReports[1]; + + /* OUT Report - block input for SET_REPORT */ + /**< Output report block size */ + uint16_t iReportLen; + /**< Output report data buffer */ + uint8_t iReportBuf[HIDDTransferDriver_REPORTSIZE]; + +} HIDDTransferDriver; + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/** Input report buffers */ +static HIDDTransferReport inputReport; + +/** Output report buffers */ +static HIDDTransferReport outputReport; + +/** Static instance of the HID Transfer device driver. */ +static HIDDTransferDriver hiddTransferDriver; + +/** Report descriptor used by the driver. */ +static const uint8_t hiddTransferReportDescriptor[] = { + + /* 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, (uint8_t) -128, + HIDReport_GLOBAL_LOGICALMAXIMUM + 1, (uint8_t) 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, (uint8_t) -128, + HIDReport_GLOBAL_LOGICALMAXIMUM + 1, (uint8_t) 127, + HIDReport_OUTPUT + 1, 0, /* No Modifiers */ + HIDReport_ENDCOLLECTION +}; + +/*------------------------------------------------------------------------------ + * 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 uint8_t HIDDTransferDriver_GetDescriptor(uint8_t type, + uint8_t length) +{ + HIDDTransferDriver *pDrv = &hiddTransferDriver; + HIDDFunction *pHidd = &pDrv->hidFunction; + + const USBConfigurationDescriptor *pConfiguration; + HIDDescriptor *hidDescriptors[2]; + + switch (type) { + + case HIDGenericDescriptor_REPORT: + TRACE_INFO("Report "); + + /* Adjust length and send report descriptor */ + if (length > HIDDTransferDriver_REPORTDESCRIPTORSIZE) { + + length = HIDDTransferDriver_REPORTDESCRIPTORSIZE; + } + USBD_Write(0, &hiddTransferReportDescriptor, length, 0, 0); + break; + + case HIDGenericDescriptor_HID: + TRACE_INFO("HID "); + + /* Configuration descriptor is different depending on configuration */ + if (USBD_IsHighSpeed()) { + + pConfiguration = + pHidd->pUsbd->pDescriptors->pHsConfiguration; + } + else { + + pConfiguration = + pHidd->pUsbd->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; +} + +/** + * 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, + uint8_t status, + uint32_t transferred, + uint32_t remaining) +{ + HIDDTransferDriver *pDrv = &hiddTransferDriver; + pDrv->iReportLen = transferred; + USBD_Write(0, 0, 0, 0, 0); +} + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Initializes the HID Transfer %device driver. + * \param pDescriptors Pointer to USBDDriverDescriptors instance. + */ +void HIDDTransferDriver_Initialize(const USBDDriverDescriptors * pDescriptors) +{ + HIDDTransferDriver * pDrv = &hiddTransferDriver; + USBDDriver *pUsbd = USBD_GetDriver(); + + /* One input report */ + pDrv->inputReports[0] = (HIDDReport*)&inputReport; + HIDDFunction_InitializeReport((HIDDReport *)pDrv->inputReports[0], + HIDDTransferDriver_REPORTSIZE, + 0, + 0, 0); + /* One output report */ + pDrv->outputReports[0] = (HIDDReport*)&outputReport; + HIDDFunction_InitializeReport((HIDDReport *)pDrv->outputReports[0], + HIDDTransferDriver_REPORTSIZE, + 0, + 0, 0); + + /* Initialize USBD Driver instance */ + USBDDriver_Initialize(pUsbd, + pDescriptors, + 0); /* Multiple interface settings not supported */ + /* Function instance initialize */ + HIDDFunction_Initialize(&pDrv->hidFunction, + pUsbd, 0, + hiddTransferReportDescriptor, + (HIDDReport **)(&pDrv->inputReports), 1, + (HIDDReport **)(&pDrv->outputReports), 1); + /* Initialize USBD */ + USBD_Init(); +} + +/** + * Handles configureation changed event. + * \param cfgnum New configuration number + */ +void HIDDTransferDriver_ConfigurationChangedHandler(uint8_t cfgnum) +{ + const USBDDriverDescriptors * pDescriptors = USBD_GetDriver()->pDescriptors; + HIDDTransferDriver * pDrv = &hiddTransferDriver; + HIDDFunction * pHidd = &pDrv->hidFunction; + + USBConfigurationDescriptor *pDesc; + + if (cfgnum > 0) { + + /* Parse endpoints for reports */ + if (USBD_HAL_IsHighSpeed() && pDescriptors->pHsConfiguration) + pDesc = (USBConfigurationDescriptor*)pDescriptors->pHsConfiguration; + else + pDesc = (USBConfigurationDescriptor*)pDescriptors->pFsConfiguration; + HIDDFunction_ParseInterface(pHidd, + (USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + + /* Start polling for Output Reports */ + HIDDFunction_StartPollingOutputs(pHidd); + } +} + +/** + * Handles HID-specific SETUP request sent by the host. + * \param request Pointer to a USBGenericRequest instance + */ +void HIDDTransferDriver_RequestHandler(const USBGenericRequest *request) +{ + HIDDTransferDriver *pDrv = &hiddTransferDriver; + HIDDFunction *pHidd = &pDrv->hidFunction; + + 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(pHidd->pUsbd, + request); + } + return; /* Handled, no need to do others */ + + case USBGenericRequest_CLEARFEATURE: + + /* Check which is the requested feature */ + switch (USBFeatureRequest_GetFeatureSelector(request)) { + case USBFeatureRequest_ENDPOINTHALT: + { uint8_t ep = + USBGenericRequest_GetEndpointNumber(request); + if (USBD_IsHalted(ep)) { + /* Unhalt endpoint restart OUT EP + */ + USBD_Unhalt(ep); + if (ep == pHidd->bPipeOUT) { + HIDDFunction_StartPollingOutputs(pHidd); + } + } + /* and send a zero-length packet */ + USBD_Write(0, 0, 0, 0, 0); + return; /* Handled, no need to do others */ + } + } + break; + + } + } + /* We use different buffer for SetReport */ + else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) { + + switch (USBGenericRequest_GetRequest(request)) { + + case HIDGenericRequest_SETREPORT: + { + uint16_t length = USBGenericRequest_GetLength(request); + uint8_t type = HIDReportRequest_GetReportType(request); + if (type == HIDReportRequest_OUTPUT) { + if (length > HIDDTransferDriver_REPORTSIZE) + length = HIDDTransferDriver_REPORTSIZE; + USBD_Read(0, + pDrv->iReportBuf, + length, + HIDDTransferDriver_ReportReceived, + 0); /* No argument to the callback function */ + } + else { + + USBD_Stall(0); + } + } + return; /* Handled, no need do others */ + } + } + + + /* Process HID requests */ + if (USBRC_SUCCESS == HIDDFunction_RequestHandler(pHidd, + request)) { + return; + } + else + USBDDriver_RequestHandler(pHidd->pUsbd, request); +} + +/** + * Try to read request buffer of SetReport. + * Set pData to 0 to get current data length only. + * \param pData Pointer to data buffer + * \param dwLength Data buffer length + * \return Number of bytes read + */ +uint16_t HIDDTransferDriver_ReadReport(void *pData, + uint32_t dwLength) +{ + HIDDTransferDriver *pDrv = &hiddTransferDriver; + + if (pData == 0) { + + return pDrv->iReportLen; + } + + if (dwLength > HIDDTransferDriver_REPORTSIZE) { + + dwLength = HIDDTransferDriver_REPORTSIZE; + } + if (dwLength > pDrv->iReportLen) { + + dwLength = pDrv->iReportLen; + } + pDrv->iReportLen = 0; + memcpy(pData, pDrv->iReportBuf, dwLength); + + return dwLength; +} + +/** + * 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 + */ +uint16_t HIDDTransferDriver_Read(void *pData, + uint32_t dLength) +{ + HIDDTransferDriver *pDrv = &hiddTransferDriver; + if (pData == 0) { + + return pDrv->outputReports[0]->wTransferred; + } + + if (dLength > HIDDTransferDriver_REPORTSIZE) { + + dLength = HIDDTransferDriver_REPORTSIZE; + } + if (dLength > pDrv->outputReports[0]->wTransferred) { + + dLength = pDrv->outputReports[0]->wTransferred; + } + pDrv->outputReports[0]->wTransferred = 0; + memcpy(pData, pDrv->outputReports[0]->bData, dLength); + + return 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. + */ +uint8_t HIDDTransferDriver_Write(const void *pData, + uint32_t dLength, + TransferCallback fCallback, + void *pArg) +{ + HIDDTransferDriver *pDrv = &hiddTransferDriver; + if (dLength != HIDDTransferDriver_REPORTSIZE) { + + dLength = HIDDTransferDriver_REPORTSIZE; + } + return USBD_Write(pDrv->hidFunction.bPipeIN, + 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) +{ + HIDDTransferDriver *pDrv = &hiddTransferDriver; + + /* Remote wake-up has been enabled */ + if (USBDDriver_IsRemoteWakeUpEnabled(pDrv->hidFunction.pUsbd)) { + + USBD_RemoteWakeUp(); + } +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDAppArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDAppArch.png new file mode 100644 index 0000000000000000000000000000000000000000..eec0f15980d81e2d9ac86e44efe8e887056ee1f7 GIT binary patch literal 7248 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDStateMachine.c b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDStateMachine.c new file mode 100644 index 00000000..97774821 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDStateMachine.c @@ -0,0 +1,637 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_msd + *@{ + */ + +/*----------------------------------------------------------------------------- + * 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); + USBD_Halt(commandState->pipeIN); + haltStatus = 1; + } + + /* STALL Bulk OUT endpoint ? */ + if ((commandState->postprocess & MSDD_CASE_STALL_OUT) != 0) { + + TRACE_INFO_WP("StallOut "); + //MSDD_Halt(MSDD_CASE_STALL_OUT); + USBD_Halt(commandState->pipeOUT); + 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; + #if 1 + status = USBD_Read(commandState->pipeOUT, + cbw, + MSD_CBW_SIZE, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Read(cbw, + MSD_CBW_SIZE, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + + /* 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); + USBD_Halt(commandState->pipeIN); + USBD_Halt(commandState->pipeOUT); + + 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); + USBD_Halt(commandState->pipeIN); + USBD_Halt(commandState->pipeOUT); + + 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 */ + #if 1 + status = USBD_Write(commandState->pipeIN, + csw, + MSD_CSW_SIZE, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Write(csw, + MSD_CSW_SIZE, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + + /* 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) { + if (!USBD_IsHalted(commandState->pipeIN)) { + + pMsdDriver->state = MSDD_STATE_SEND_CSW; + } + break; + } +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriver.c b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriver.c new file mode 100644 index 00000000..660e30bb --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriver.c @@ -0,0 +1,113 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_msd + *@{ + * Implement a single interface device with single MS function in. + */ + +/*------------------------------------------------------------------------------ + * Includes + *------------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include + +/*----------------------------------------------------------------------------- + * Internal variables + *-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Internal functions + *-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Exported functions + *-----------------------------------------------------------------------------*/ + +/** + * Initializes the MSD driver and the associated USB driver. + * \param pDescriptors Pointer to Descriptors list for MSD Device. + * \param pLuns Pointer to a list of LUNs + * \param numLuns Number of LUN in list + * \see MSDLun + */ +void MSDDriver_Initialize( + const USBDDriverDescriptors *pDescriptors, + MSDLun *pLuns, unsigned char numLuns) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBDDriver_Initialize(pUsbd, pDescriptors, 0); + MSDFunction_Initialize(pUsbd, 0, pLuns, numLuns); + USBD_Init(); +} + +/** + * Invoked when the configuration of the device changes. Resets the mass + * storage driver. + * \param pMsdDriver Pointer to MSDDriver instance. + * \param cfgnum New configuration number. + */ +void MSDDriver_ConfigurationChangeHandler( + uint8_t cfgnum) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + USBConfigurationDescriptor *pDesc; + if (cfgnum) { + pDesc = USBDDriver_GetCfgDescriptors(pUsbd, cfgnum); + MSDFunction_Configure((USBGenericDescriptor*)pDesc, + pDesc->wTotalLength); + } +} + +/** + * Handler for incoming SETUP requests on default Control endpoint 0. + * + * Standard requests are forwarded to the USBDDriver_RequestHandler + * method. + * \param pMsdDriver Pointer to MSDDriver instance. + * \param request Pointer to a USBGenericRequest instance + */ +void MSDDriver_RequestHandler( + const USBGenericRequest *request) +{ + USBDDriver *pUsbd = USBD_GetDriver(); + TRACE_INFO_WP("NewReq "); + if (MSDFunction_RequestHandler(request)) { + USBDDriver_RequestHandler(pUsbd, request); + } +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverArch.png new file mode 100644 index 0000000000000000000000000000000000000000..4063440b3c91915e4f7dfe90d4faaec1a9aa0f36 GIT binary patch literal 4889 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverClasses.png b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverClasses.png new file mode 100644 index 0000000000000000000000000000000000000000..3fd68d14a5d37e210b5391e0a38b710938d39ae9 GIT binary patch literal 12031 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverStates.png b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDDriverStates.png new file mode 100644 index 0000000000000000000000000000000000000000..a0c55c80ebd9ccd15f5f518bf45c712972f5332f GIT binary patch literal 7920 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 Xpa0PYyS^F*1_lOCS3j3^P6 + +#include +#include +#include +#include +#include + +/*----------------------------------------------------------------------------- + * Internal Types + *-----------------------------------------------------------------------------*/ + +/** Parse data extension */ +typedef struct _MSDParseData { + /** Pointer to driver instance */ + MSDDriver *pMsdd; + /** Pointer to currently processed interface descriptor */ + USBInterfaceDescriptor *pIf; +} MSDParseData; + + +/*----------------------------------------------------------------------------- + * Internal variables + *-----------------------------------------------------------------------------*/ + +/** MSD Driver instance for device function */ +static MSDDriver msdFunction; + +/*----------------------------------------------------------------------------- + * Internal functions + *-----------------------------------------------------------------------------*/ + +/** + * Parse descriptors: Bulk EP IN/OUT. + * \param desc Pointer to current processed descriptor. + * \param arg Pointer to data extention struct for parsing. + */ +static uint8_t MSDFunction_Parse(USBGenericDescriptor* desc, MSDParseData* arg) +{ + MSDDriver *pMsdd = arg->pMsdd; + USBInterfaceDescriptor *pIf; + + /* Not a valid descriptor */ + if (desc->bLength == 0) { + return USBD_STATUS_INVALID_PARAMETER; + } + /* Find interface descriptor */ + if (desc->bDescriptorType == USBGenericDescriptor_INTERFACE) { + pIf = (USBInterfaceDescriptor*)desc; + if (pIf->bInterfaceClass == MSInterfaceDescriptor_CLASS) { + /* First found IF */ + if (pMsdd->interfaceNb == 0xFF) { + pMsdd->interfaceNb = pIf->bInterfaceNumber; + arg->pIf = pIf; + } + /* Specific IF */ + else if (pMsdd->interfaceNb == pIf->bInterfaceNumber) { + arg->pIf = pIf; + } + + } + } + /* Start parse endpoints */ + if (arg->pIf) { + if (desc->bDescriptorType == USBGenericDescriptor_ENDPOINT) { + USBEndpointDescriptor *pEP = (USBEndpointDescriptor*)desc; + if (pEP->bmAttributes == USBEndpointDescriptor_BULK) { + if (pEP->bEndpointAddress & 0x80) + pMsdd->commandState.pipeIN = pEP->bEndpointAddress & 0x7F; + else + pMsdd->commandState.pipeOUT = pEP->bEndpointAddress; + } + } + + /* Finish when found all pipes */ + if (pMsdd->commandState.pipeIN != 0 + && pMsdd->commandState.pipeOUT != 0) { + return USBRC_FINISHED; + } + } + return 0; +} + +/** + * Resets the state of the MSD driver + */ +static void MSDFunction_Reset(void) +{ + MSDDriver *pMsdd = &msdFunction; + + TRACE_INFO_WP("MSDReset "); + + pMsdd->state = MSDD_STATE_READ_CBW; + pMsdd->waitResetRecovery = 0; + pMsdd->commandState.state = 0; +} + +/*----------------------------------------------------------------------------- + * Exported functions + *-----------------------------------------------------------------------------*/ + +/** + * Initializes the MSD driver and the associated USB driver. + * \param pUsbd Pointer to USBDDriver instance. + * \param bInterfaceNb Interface number for the function. + * \param pLuns Pointer to a list of LUNs + * \param numLuns Number of LUN in list + * \see MSDLun + */ +void MSDFunction_Initialize( + USBDDriver *pUsbd, uint8_t bInterfaceNb, + MSDLun *pLuns, uint8_t numLuns) +{ + MSDDriver *pMsdDriver = &msdFunction; + + TRACE_INFO("MSDFun init\n\r"); + + /* Driver instance */ + pMsdDriver->pUsbd = pUsbd; + pMsdDriver->interfaceNb = bInterfaceNb; + + /* Command state initialization */ + pMsdDriver->commandState.state = 0; + pMsdDriver->commandState.postprocess = 0; + pMsdDriver->commandState.length = 0; + pMsdDriver->commandState.transfer.semaphore = 0; + + /* LUNs */ + pMsdDriver->luns = pLuns; + pMsdDriver->maxLun = (uint8_t) (numLuns - 1); + + /* Reset BOT driver */ + MSDFunction_Reset(); +} + +/** + * Invoked when the configuration of the device changes. + * Pass endpoints and resets the mass storage function. + * \pDescriptors Pointer to the descriptors for function configure. + * \wLength Length of descriptors in number of bytes. + */ +void MSDFunction_Configure(USBGenericDescriptor *pDescriptors, + uint16_t wLength) +{ + MSDDriver *pMsdDriver = &msdFunction; + MSDParseData parseData; + + TRACE_INFO_WP("MSDFunCfg "); + + pMsdDriver->state = MSDD_STATE_READ_CBW; + pMsdDriver->waitResetRecovery = 0; + pMsdDriver->commandState.state = 0; + + parseData.pIf = 0; + parseData.pMsdd = pMsdDriver; + USBGenericDescriptor_Parse((USBGenericDescriptor*)pDescriptors, wLength, + (USBDescriptorParseFunction)MSDFunction_Parse, &parseData); + + MSDFunction_Reset(); +} + +/** + * Handler for incoming SETUP requests on default Control endpoint 0. + * + * Standard requests are forwarded to the USBDDriver_RequestHandler + * method. + * \param pMsdDriver Pointer to MSDDriver instance. + * \param request Pointer to a USBGenericRequest instance + */ +uint32_t MSDFunction_RequestHandler( + const USBGenericRequest *request) +{ + MSDDriver *pMsdDriver = &msdFunction; + uint32_t reqCode = (USBGenericRequest_GetType(request) << 8) + | (USBGenericRequest_GetRequest(request)); + + TRACE_INFO_WP("Msdf "); + + /* Handle requests */ + switch (reqCode) { + /*--------------------- */ + 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 (!pMsdDriver->waitResetRecovery) { + + /* Forward the request to the standard handler */ + USBDDriver_RequestHandler(USBD_GetDriver(), request); + } + else { + + TRACE_INFO_WP("No "); + } + + USBD_Write(0, 0, 0, 0, 0); + + return USBRC_SUCCESS; /* Handled */ + + } + break; + + /*------------------- */ + case (USBGenericRequest_CLASS<<8)|MSD_GET_MAX_LUN: + /*------------------- */ + TRACE_INFO_WP("gMaxLun "); + + /* Check request parameters */ + if ((request->wValue == 0) + && (request->wIndex == pMsdDriver->interfaceNb) + && (request->wLength == 1)) { + + USBD_Write(0, &(pMsdDriver->maxLun), 1, 0, 0); + + } + else { + + TRACE_WARNING( + "MSDDriver_RequestHandler: GetMaxLUN(%d,%d,%d)\n\r", + request->wValue, request->wIndex, request->wLength); + USBD_Stall(0); + } + return USBRC_SUCCESS; /* Handled */ + + /*----------------------- */ + case (USBGenericRequest_CLASS<<8)|MSD_BULK_ONLY_RESET: + /*----------------------- */ + TRACE_INFO_WP("Rst "); + + /* Check parameters */ + if ((request->wValue == 0) + && (request->wIndex == pMsdDriver->interfaceNb) + && (request->wLength == 0)) { + + /* Reset the MSD driver */ + MSDFunction_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); + } + return USBRC_SUCCESS; /* Handled */ + } + + return USBRC_PARAM_ERR; +} + +/** + * State machine for the MSD driver + */ +void MSDFunction_StateMachine(void) +{ + if (USBD_GetState() < USBD_STATE_CONFIGURED){} + else MSDD_StateMachine(&msdFunction); + +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDIOFifo.c b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDIOFifo.c new file mode 100644 index 00000000..be742e4c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDIOFifo.c @@ -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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * 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/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDLun.c b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDLun.c new file mode 100644 index 00000000..66a4d335 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDLun.c @@ -0,0 +1,389 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + + +#include "MSDLun.h" +#include +#include + +/*------------------------------------------------------------------------------ + * 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, + uint8_t *ioBuffer, + uint32_t ioBufferSize, + uint32_t baseAddress, + uint32_t size, + uint16_t blockSize, + uint8_t protected, + void (*dataMonitor)(uint8_t flowDirection, + uint32_t dataLength, + uint32_t fifoNullCount, + uint32_t fifoFullCount)) +{ + uint32_t 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 + */ +uint32_t 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 + * \param argument Optional callback argument. + * \return Operation result code + */ +uint32_t LUN_Write(MSDLun *lun, + uint32_t blockAddress, + void *data, + uint32_t length, + TransferCallback callback, + void *argument) +{ + uint32_t medBlk, medLen; + uint8_t 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 + * \param argument Optional callback argument. + * \return Operation result code + */ +uint32_t LUN_Read(MSDLun *lun, + uint32_t blockAddress, + void *data, + uint32_t length, + TransferCallback callback, + void *argument) +{ + uint32_t medBlk, medLen; + uint8_t 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/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDMediaArch.png b/sam3s_example/atmel_softpack_libraries/usb/device/massstorage/MSDMediaArch.png new file mode 100644 index 0000000000000000000000000000000000000000..b641e97c31dea66e6cc4cd4b871797bafd88e423 GIT binary patch literal 3622 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 + +#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(ep, pFifo, pCb, pArg) \ + USBD_Write( (ep), \ + &(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(ep, pFifo,pCb,pArg) \ + USBD_Read( (ep), \ + &(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 */ + #if 1 + status = USBD_Read(commandState->pipeOUT, + (void*) + ((lun->media->baseAddress + + (lun->baseAddress + + DWORDB(command->pLogicalBlockAddress) + * lun->blockSize + ) + ) * lun->media->blockSize + ), + fifo->dataTotal, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Read((void*) + ((lun->media->baseAddress + + (lun->baseAddress + + DWORDB(command->pLogicalBlockAddress) + * lun->blockSize + ) + ) * lun->media->blockSize + ), + fifo->dataTotal, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + } + else { + #ifdef MSDIO_WRITE10_CHUNK_SIZE + status = SBC_RX_CHUNK(commandState->pipeOUT, + fifo, MSDDriver_Callback, transfer); + #else + /* Read block to buffer */ + #if 1 + status = USBD_Read(commandState->pipeOUT, + (void*)&fifo->pBuffer[fifo->inputNdx], + fifo->blockSize, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Read((void*)&fifo->pBuffer[fifo->inputNdx], + fifo->blockSize, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + #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) { + #if 1 + status = USBD_Write(commandState->pipeIN, + (void*) + ((lun->media->baseAddress + + (lun->baseAddress + + DWORDB(command->pLogicalBlockAddress) + * lun->blockSize + ) + ) * lun->media->blockSize + ), + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Write((void*) + ((lun->media->baseAddress + + (lun->baseAddress + + DWORDB(command->pLogicalBlockAddress) + * lun->blockSize + ) + ) * lun->media->blockSize + ), + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + } + else { + #ifdef MSDIO_READ10_CHUNK_SIZE + status = SBC_TX_CHUNK(commandState->pipeIN, + fifo, MSDDriver_Callback, transfer); + #else + #if 1 + status = USBD_Write(commandState->pipeIN, + &fifo->pBuffer[fifo->outputNdx], + fifo->blockSize, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Write(&fifo->pBuffer[fifo->outputNdx], + fifo->blockSize, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + #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 */ + #if 1 + status = USBD_Write(commandState->pipeIN, + &(lun->readCapacityData), + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Write(&(lun->readCapacityData), + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + + /* 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 */ + #if 1 + status = USBD_Write(commandState->pipeIN, + (void *) lun->inquiryData, + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Write((void *) lun->inquiryData, + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + + /* 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 */ + #if 1 + status = USBD_Write(commandState->pipeIN, + &(lun->requestSenseData), + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Write(&(lun->requestSenseData), + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + + /* 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 */ + #if 1 + status = USBD_Write(commandState->pipeIN, + (void *) &modeParameterHeader6, + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #else + status = MSDD_Write((void *) &modeParameterHeader6, + commandState->length, + (TransferCallback) MSDDriver_Callback, + (void *) transfer); + #endif + + /* 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; + /*------ */ + + 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; + /*------ */ + default: + /*------ */ + + result = MSDD_STATUS_PARAMETER; + } + + return result; +} + +/**@}*/ diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/AUDDFunction.h b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDFunction.h new file mode 100644 index 00000000..ed2482c6 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDFunction.h @@ -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. + * ---------------------------------------------------------------------------- + */ +/** \file */ +#ifndef AUDDFUNCTION_H +#define AUDDFUNCTION_H +/** \addtogroup usbd_aud_fun + *@{ + */ + +/*----------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +/*----------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/** \addtogroup audd_fun_desc USBD Audio Function definitions + * @{ + */ +/** ID for Speaker */ +#define AUDDFunction_Speaker 0 +/** ID for Microphone */ +#define AUDDFunction_Microhpone 1 +/** Max number of interfaces that supported by the function (AC + 2*AS) */ +#define AUDDFunction_MaxNumInterfaces 3 +/** Max number of channels supported by speaker stream (including master) */ +#define AUDDFunction_MaxNumSpeakerChannels 3 +/** Max number of channels supported by microphone stream (including master) */ +#define AUDDFunction_MaxNumMicrophoneChannels 3 + +/** Endpoint polling interval 2^(x-1) * 125us */ +#define AUDDFunction_HS_INTERVAL 0x04 +/** Endpoint polling interval 2^(x-1) * ms */ +#define AUDDFunction_FS_INTERVAL 0x01 + +/** Playback input terminal ID */ +#define AUDDFunction_INPUTTERMINAL AUDD_ID_SpeakerIT +/** Playback output terminal ID */ +#define AUDDFunction_OUTPUTTERMINAL AUDD_ID_SpeakerOT +/** Playback feature unit ID */ +#define AUDDFunction_FEATUREUNIT AUDD_ID_SpeakerFU +/** Record input terminal ID */ +#define AUDDFunction_INPUTTERMINAL_REC AUDD_ID_MicrophoneIT +/** Record output terminal ID */ +#define AUDDFunction_OUTPUTTERMINAL_REC AUDD_ID_MicrophoneOT +/** Record feature unit ID */ +#define AUDDFunction_FEATUREUNIT_REC AUDD_ID_MicrophoneFU + +/** @}*/ + +/*----------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +extern void AUDDFunction_Initialize( + USBDDriver *pUsbd, uint8_t bInterface); +extern void AUDDFunction_Configure( + USBGenericDescriptor * pDescriptors, uint16_t wLength); +extern void AUDDFunction_InterfaceSettingChangedHandler( + uint8_t interface,uint8_t setting); +extern uint32_t AUDDFunction_RequestHandler(const USBGenericRequest * request); +extern uint8_t AUDDFunction_Read( + void * buffer, uint32_t length, + TransferCallback callback, void * argument); +extern uint8_t AUDDFunction_SetupWrite( + void * pListInit, void * pDmaInit, uint16_t listSize, uint16_t delaySize, + TransferCallback callback,void * argument); +extern uint8_t AUDDFunction_Write(void * buffer, uint16_t length); + +extern void AUDDFunction_MuteChanged( + uint8_t idMic, uint8_t ch, uint8_t mute); +extern void AUDDFunction_StreamSettingChanged( + uint8_t idMic, uint8_t setting); + +/**@}*/ +#endif // #define AUDDFUNCTIONDRIVER_H + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerDriver.h new file mode 100644 index 00000000..87393f4c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerDriver.h @@ -0,0 +1,256 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definition of a USB Audio Speaker Driver with two playback channels. + * + * \section 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 + */ + +#ifndef AUDDSPEAKERDRIVER_H +#define AUDDSPEAKERDRIVER_H + +/** \addtogroup usbd_audio_speaker + *@{ + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include + +#include +#include +#include + +#include +#include + +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usbd_audio_ch USB Device Audio Speaker Channel Numbers + * @{ + * This page lists codes for USB Audio Speaker channel numbers. + * + * \par Playback channel numbers + * - \ref AUDDSpeakerDriver_MASTERCHANNEL + * - \ref AUDDSpeakerDriver_LEFTCHANNEL + * - \ref AUDDSpeakerDriver_RIGHTCHANNEL + * + * \par Record channel number + * - \ref 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 + +/** Max Number of channels in audio stream (excluding master). */ +#define AUDDSpeakerDriver_NUMCHANNELS 2 +/** @}*/ + +/** \addtogroup usbd_audio_speaker_if USB Device Audio Speaker Interface IDs + * @{ + * This page lists the interface numbers for USB Audio Speaker device. + * - \ref AUDDSpeakerDriverDescriptors_CONTROL + * - \ref AUDDSpeakerDriverDescriptors_STREAMING + * Total number of integrated interfaces + * - \ref AUDDSpeakerDriver_NUMINTERFACES + */ +/** Audio control interface ID. */ +#define AUDDSpeakerDriverDescriptors_CONTROL 0 +/** Audio streaming interface ID (OUT, for playback). */ +#define AUDDSpeakerDriverDescriptors_STREAMING 1 + +/** Audio speaker total number of interfaces */ +#define AUDDSpeakerDriver_NUMINTERFACES 2 +/** @}*/ + +/** \addtogroup usbd_audio_entity USB Device Audio Speaker Entity IDs + * @{ + * This page lists the entity IDs for USB Audio Speaker device. + * - \ref AUDDSpeakerDriverDescriptors_INPUTTERMINAL + * - \ref AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL + * - \ref AUDDSpeakerDriverDescriptors_FEATUREUNIT + */ +/** Playback input terminal ID. */ +#define AUDDSpeakerDriverDescriptors_INPUTTERMINAL AUDD_ID_SpeakerIT +/** Playback output terminal ID. */ +#define AUDDSpeakerDriverDescriptors_OUTPUTTERMINAL AUDD_ID_SpeakerOT +/** Playback feature unit ID. */ +#define AUDDSpeakerDriverDescriptors_FEATUREUNIT AUDD_ID_SpeakerFU +/** @}*/ + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR*/ +#pragma pack(1) /* IAR*/ +#define __attribute__(...) /* IAR*/ +#endif /* IAR*/ + +/** + * \typedef AUDHeaderDescriptor1 + * \brief Header descriptor with 1 interface. + */ +typedef struct _AUDHeaderDescriptor1 { + + /** Header descriptor. */ + AUDHeaderDescriptor header; + /** Id of the first grouped interface - Speaker. */ + uint8_t bInterface0; + +} __attribute__ ((packed)) AUDHeaderDescriptor1; /* GCC*/ + +/** + * \typedef AUDFeatureUnitDescriptor3 + * \brief Feature unit descriptor with 3 channel controls + * (master, right, left). + */ +typedef struct _AUDFeatureUnitDescriptor3 { + + /** Feature unit descriptor. */ + AUDFeatureUnitDescriptor feature; + /** Available controls for each channel. */ + uint8_t bmaControls[3]; + /** Index of a string descriptor for the feature unit. */ + uint8_t iFeature; + +} __attribute__ ((packed)) AUDFeatureUnitDescriptor3; /* GCC */ + +/** + * \typedef AUDDSpeakerDriverAudioControlDescriptors + * \brief List of descriptors for detailling the audio control interface of a + * device using a USB audio speaker driver. + */ +typedef struct _AUDDSpeakerDriverAudioControlDescriptors { + + /** 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*/ + +/** + * \typedef AUDFormatTypeOneDescriptor1 + * \brief Format type I descriptor with one discrete sampling frequency. + */ +typedef struct _AUDFormatTypeOneDescriptor1 { + + /** Format type I descriptor. */ + AUDFormatTypeOneDescriptor formatType; + /** Sampling frequency in Hz. */ + uint8_t tSamFreq[3]; + +} __attribute__ ((packed)) AUDFormatTypeOneDescriptor1; /* GCC*/ + +/** + * \typedef AUDDSpeakerDriverConfigurationDescriptors + * \brief Holds a list of descriptors returned as part of the configuration of + * a USB audio speaker device. + */ +typedef struct _AUDDSpeakerDriverConfigurationDescriptors { + + /** 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 functions + *----------------------------------------------------------------------------*/ + +extern void AUDDSpeakerDriver_Initialize( + const USBDDriverDescriptors *pDescriptors); + +extern void AUDDSpeakerDriver_ConfigurationChangeHandler(uint8_t cfgnum); + +extern void AUDDSpeakerDriver_InterfaceSettingChangedHandler( + uint8_t interface, uint8_t setting); + +extern void AUDDSpeakerDriver_RequestHandler(const USBGenericRequest *request); + +extern uint8_t AUDDSpeakerDriver_Read(void *buffer, + uint32_t length, + TransferCallback callback, + void *argument); + +extern void AUDDSpeakerDriver_MuteChanged(uint8_t channel,uint8_t muted); + +extern void AUDDSpeakerDriver_StreamSettingChanged(uint8_t newSetting); + +/**@}*/ +#endif /*#ifndef AUDDSPEAKERDRIVER_H */ + + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhone.h b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhone.h new file mode 100644 index 00000000..ae5a22a0 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhone.h @@ -0,0 +1,156 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * USB Audio Speaker & Microphone Function. + */ + +/** \addtogroup usbd_audio_speakerphone + *@{ + * Implement speakerphone function that combine 1 AC interface, 1 AS interface + * for speaker and 1 AS interface for microphone. + */ + +#ifndef _AUDD_SPEAKERPHONE_H_ +#define _AUDD_SPEAKERPHONE_H_ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include + +#include +#include + +/*------------------------------------------------------------------------------ + * Defines + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_audio_ids Audio Device IDs required by driver + * @{ + * The driver uses following fixed entity IDs, use them to define your + * descriptor. + * \ref AUDD_ID_SpeakerIT + * \ref AUDD_ID_SpeakerOT + * \ref AUDD_ID_SpeakerFU + * \ref AUDD_ID_MicrophoneIT + * \ref AUDD_ID_MicrophoneOT + * \ref AUDD_ID_MicrophoneFU + */ +/** Speaker input terminal ID */ +#define AUDD_ID_SpeakerIT 0x01 +/** Speaker output terminal ID */ +#define AUDD_ID_SpeakerOT 0x02 +/** Speaker feature unit ID */ +#define AUDD_ID_SpeakerFU 0x03 +/** Microphone input terminal ID */ +#define AUDD_ID_MicrophoneIT 0x04 +/** Microphone output terminal ID */ +#define AUDD_ID_MicrophoneOT 0x05 +/** Microphone feature unit ID */ +#define AUDD_ID_MicrophoneFU 0x06 +/** @}*/ + +/** \addtogroup usbd_audio_chs Audio Device Channels + * @{ + */ +/** Master channel ID */ +#define AUDD_CH_Master 0x0 +/** Left channel ID */ +#define AUDD_CH_L 0x1 +/** Right channel ID */ +#define AUDD_CH_R 0x2 +/** @}*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** + * Struct of USB Audio Speakerphone Function, with + * - 1 control interface for features, + * - 1 input stream for microphone (Audio IN), + * - 1 output stream for speaker (Audio OUT). + */ +typedef struct _AUDDSpeakerPhone { + /** Pointer to USBD Driver Interface */ + USBDDriver *pUsbd; + /** Pointer to AUDDStream Instance */ + AUDDStream *pSpeaker; + /** Pointer to AUDDStream Instance */ + AUDDStream *pMicrophone; +} AUDDSpeakerPhone; + +/*------------------------------------------------------------------------------ + * Functions + *------------------------------------------------------------------------------*/ + +extern void AUDDSpeakerPhone_InitializeStream( + AUDDStream * pAuds, + uint8_t numChannels,uint16_t wChannelVolumes [ ], + AUDDStreamEventCallback fCallback,void * pArg); + +extern void AUDDSpeakerPhone_Initialize( + AUDDSpeakerPhone * pAudf, + USBDDriver * pUsbd, + AUDDStream * pSpeaker,AUDDStream * pMicrophone); + +extern USBGenericDescriptor* AUDDSpeakerPhone_ParseInterfaces( + AUDDSpeakerPhone * pAudf, + USBGenericDescriptor * pDescriptors, + uint32_t dwLength); + +extern uint32_t AUDDSpeakerPhone_RequestHandler( + AUDDSpeakerPhone * pAudf, + const USBGenericRequest * pRequest); + +extern uint32_t AUDDSpeakerPhone_CloseStream( + AUDDSpeakerPhone * pAudf, + uint32_t bInterface); + +extern uint32_t AUDDSpeakerPhone_SetupWrite( + AUDDSpeakerPhone * pAudf, + void * pListInit, void * pDmaInit, uint16_t listSize, uint16_t delaySize, + TransferCallback callback,void * argument); + +extern uint32_t AUDDSpeakerPhone_Write( + AUDDSpeakerPhone * pAudf, + void * pBuffer,uint16_t wLength); + +extern uint32_t AUDDSpeakerPhone_Read( + AUDDSpeakerPhone * pAudf, + void * pData, uint32_t dwSize, + TransferCallback fCallback,void * pArg); + +/**@}*/ +#endif /* _AUDD_SPEAKERPHONE_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhoneDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhoneDriver.h new file mode 100644 index 00000000..32d84716 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDSpeakerPhoneDriver.h @@ -0,0 +1,311 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definition of a USB Audio Speakerphone Driver with two playback channels + * and one record channel. + * + * \section Usage + * + * -# Enable and setup USB related pins (see pio & board.h). + * -# Inplement a descriptor list using definitions + * - \ref usbd_audio_speakerphone_channel_num + * - \ref usbd_audio_speaker_interface_ids + * - \ref usbd_audio_speaker_entity_ids + * -# Configure the USB Audio Speakerphone driver using + * AUDDSpeakerPhoneDriver_Initialize + * -# To get %audio stream frames from host, use + * AUDDSpeakerPhoneDriver_Read + * -# To send %audio sampling stream to host, use + * AUDDSpeakerPhoneDriver_Write + * + */ + +#ifndef AUDDSpeakerPhoneDriver_H +#define AUDDSpeakerPhoneDriver_H + +/** \addtogroup usbd_audio_speakerphone + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_audio_speakerphone_channel_num Audio SpeakerPhone Channel Numbers + * @{ + * This page lists codes for USB Audio Speakerphone channel numbers. + * + * \section Playback channel numbers + * - AUDDSpeakerPhoneDriver_MASTERCHANNEL + * - AUDDSpeakerPhoneDriver_LEFTCHANNEL + * - AUDDSpeakerPhoneDriver_RIGHTCHANNEL + * + * \section Record channel number + * - AUDDSpeakerPhoneDriver_RECCHANNEL + */ + +/** Master channel of playback. */ +#define AUDDSpeakerPhoneDriver_MASTERCHANNEL 0 +/** Front left channel of playback. */ +#define AUDDSpeakerPhoneDriver_LEFTCHANNEL 1 +/** Front right channel of playback. */ +#define AUDDSpeakerPhoneDriver_RIGHTCHANNEL 2 +/** Channel of record. */ +#define AUDDSpeakerPhoneDriver_RECCHANNEL 0 +/** @}*/ + +/** \addtogroup usbd_audio_speaker_interface_ids Audio SpeakerPhone Interface IDs + * @{ + * This page lists the interface numbers for USB Audio Speakerphone device. + * + * \section Interfaces + * - AUDDSpeakerPhoneDriverDescriptors_CONTROL + * - AUDDSpeakerPhoneDriverDescriptors_STREAMING + * - AUDDSpeakerPhoneDriverDescriptors_STREAMINGIN + */ + +/** Audio control interface ID */ +#define AUDDSpeakerPhoneDriverDescriptors_CONTROL 0 +/** Audio streaming interface ID (OUT, for playback) */ +#define AUDDSpeakerPhoneDriverDescriptors_STREAMING 1 +/** Audio streaming interface ID (IN, for record) */ +#define AUDDSpeakerPhoneDriverDescriptors_STREAMINGIN 2 +/** @}*/ + +/** \addtogroup usbd_audio_speaker_entity_ids Audio SpeakerPhone Entity IDs + * @{ + * This page lists the entity IDs for USB Audio Speaker device. + * + * \section Entities + * - AUDDSpeakerPhoneDriverDescriptors_INPUTTERMINAL + * - AUDDSpeakerPhoneDriverDescriptors_OUTPUTTERMINAL + * - AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT + * - AUDDSpeakerPhoneDriverDescriptors_INPUTTERMINAL_REC + * - AUDDSpeakerPhoneDriverDescriptors_OUTPUTTERMINAL_REC + * - AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT_REC + */ + +/** Playback input terminal ID */ +#define AUDDSpeakerPhoneDriverDescriptors_INPUTTERMINAL 0 +/** Playback output terminal ID */ +#define AUDDSpeakerPhoneDriverDescriptors_OUTPUTTERMINAL 1 +/** Playback feature unit ID */ +#define AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT 2 +/** Record input terminal ID */ +#define AUDDSpeakerPhoneDriverDescriptors_INPUTTERMINAL_REC 3 +/** Record output terminal ID */ +#define AUDDSpeakerPhoneDriverDescriptors_OUTPUTTERMINAL_REC 4 +/** Record feature unit ID */ +#define AUDDSpeakerPhoneDriverDescriptors_FEATUREUNIT_REC 5 +/** @}*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Audio control header descriptor with one slave interface. + *------------------------------------------------------------------------------*/ +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef AUDHeaderDescriptor2 + * \brief Header descriptor with 1 interface. + */ +typedef struct _AUDHeaderDescriptor2 { + + /** 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 */ + +/** + * \typedef AUDFeatureUnitDescriptor3 + * \brief Feature unit descriptor with 3 channel controls (master, right, left). + */ +typedef struct _AUDFeatureUnitDescriptor3 { + + /** 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 */ + +/** + * \typedef AUDDSpeakerPhoneDriverAudioControlDescriptors + * \brief List of descriptors for detailling the audio control interface of a + * device using a USB Audio Speakerphoneer driver. + */ +typedef struct _AUDDSpeakerPhoneDriverAudioControlDescriptors { + + /** Header descriptor (with one slave interface). */ + AUDHeaderDescriptor2 header; + /** Input terminal descriptor. */ + AUDInputTerminalDescriptor inputSpeakerPhone; + /** Output terminal descriptor. */ + AUDOutputTerminalDescriptor outputSpeakerPhone; + /** Feature unit descriptor - SpeakerPhone. */ + AUDFeatureUnitDescriptor3 featureSpeakerPhone; + /** Input terminal descriptor. */ + AUDInputTerminalDescriptor inputRec; + /** Output terminal descriptor. */ + AUDOutputTerminalDescriptor outputRec; + /** Feature unit descriptor - SpeakerPhonephone. */ + AUDFeatureUnitDescriptor3 featureRec; + +} __attribute__ ((packed)) AUDDSpeakerPhoneDriverAudioControlDescriptors; /* GCC */ + +/** + * \typedef AUDFormatTypeOneDescriptor1 + * \brief Format type I descriptor with one discrete sampling frequency. + */ +typedef struct _AUDFormatTypeOneDescriptor1 { + + /** Format type I descriptor. */ + AUDFormatTypeOneDescriptor formatType; + /** Sampling frequency in Hz. */ + unsigned char tSamFreq[3]; + +} __attribute__ ((packed)) AUDFormatTypeOneDescriptor1; /* GCC */ + +/** + * \typedef AUDDSpeakerPhoneDriverConfigurationDescriptors + * \brief Holds a list of descriptors returned as part of the configuration of + * a USB Audio Speakerphone device. + */ +typedef struct _AUDDSpeakerPhoneDriverConfigurationDescriptors { + + /** Standard configuration. */ + USBConfigurationDescriptor configuration; + /** Audio control interface. */ + USBInterfaceDescriptor control; + /** Descriptors for the audio control interface. */ + AUDDSpeakerPhoneDriverAudioControlDescriptors 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)) AUDDSpeakerPhoneDriverConfigurationDescriptors; /* GCC */ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern void AUDDSpeakerPhoneDriver_Initialize( + const USBDDriverDescriptors *pDescriptors); + +extern void AUDDSpeakerPhoneDriver_ConfigurationChangeHandler(uint8_t cfgnum); + +extern void AUDDSpeakerPhoneDriver_InterfaceSettingChangedHandler( + uint8_t interface, + uint8_t setting); + +extern void AUDDSpeakerPhoneDriver_RequestHandler( + const USBGenericRequest *request); + +extern uint8_t AUDDSpeakerPhoneDriver_Read(void *buffer, + uint32_t length, + TransferCallback callback, + void *argument); + +extern uint8_t AUDDSpeakerPhoneDriver_SetupWrite(void * pListInit, + void * pDmaInit, + uint16_t listSize, + uint16_t delaySize, + TransferCallback callback, + void * argument); + +extern uint8_t AUDDSpeakerPhoneDriver_Write(void * buffer,uint16_t length); + + +extern void AUDDSpeakerPhoneDriver_MuteChanged(uint8_t mic, + uint8_t channel, + uint8_t muted); + +extern void AUDDSpeakerPhoneDriver_StreamSettingChanged(uint8_t mic, + uint8_t newSetting); + +/**@}*/ + +#endif /*#ifndef AUDDSpeakerPhoneDriver_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/AUDDStream.h b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDStream.h new file mode 100644 index 00000000..571711bc --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDStream.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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * USB Audio Device Streaming interface with controls. + * (3 channels (including master) supported). + */ + +/** \addtogroup usbd_audio_speakerphone + *@{ + * Implement speakerphone function that combine 1 AC interface, 1 AS interface + * for speaker and 1 AS interface for microphone. + */ + +#ifndef _AUDD_STREAM_H_ +#define _AUDD_STREAM_H_ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include +#include + +/*------------------------------------------------------------------------------ + * Defines + *------------------------------------------------------------------------------*/ + +/** \addtopage usbd_audio_ec Audio Device Event codes + * @{ + */ +/** Mute status changed */ +#define AUDD_EC_MuteChanged 1 +/** Volume status changed */ +#define AUDD_EC_VolumeChanged 2 +/** @}*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** Callback function for Audio Stream Event */ +typedef void (*AUDDStreamEventCallback)(uint32_t ec, + uint8_t channel, + void* pArg); + +/** + * Struct of USB Audio Stream Interface. + * Support 1 control interface, with I & O stream. + * Unit ID 0xFF is reserved for not implemented. + */ +typedef struct _AUDDStream { + /** AudioControl Interface number */ + uint8_t bAcInterface; + /** AudioControl Feature Unit ID for IN */ + uint8_t bFeatureUnitOut; + /** AudioControl Feature Unit ID for OUT */ + uint8_t bFeatureUnitIn; + /** AudioStreaming Interface number */ + uint8_t bAsInterface; + /** Streaming OUT endpoint address */ + uint8_t bEndpointOut; + /** Streaming IN endpoint address */ + uint8_t bEndpointIn; + /** Number of channels (<=8) */ + uint8_t bNumChannels; + /** Mute control bits (8b) */ + uint8_t bmMute; + /** Volume control data */ + uint16_t *pwVolumes; + + /** Audio Streaming Events Callback */ + AUDDStreamEventCallback fCallback; + /** Callback arguments */ + void* pArg; +} AUDDStream; + +/*------------------------------------------------------------------------------ + * Functions + *------------------------------------------------------------------------------*/ + +extern void AUDDStream_Initialize( + AUDDStream * pAuds, + uint8_t numChannels, + uint16_t wChannelVolumes [ ], + AUDDStreamEventCallback fCallback, + void * pArg); + +extern uint32_t AUDDStream_ChangeMute( + AUDDStream * pAuds, + uint8_t bChannel, + uint8_t bMute); + +extern uint32_t AUDDStream_SetVolume( + AUDDStream * pAuds, + uint8_t bChannel, + uint16_t wVolume); + +extern uint32_t AUDDStream_IsRequestAccepted( + AUDDStream *pAuds, + const USBGenericRequest *pReq); + +extern uint32_t AUDDStream_Read( + AUDDStream * pAuds, + void * pData, uint32_t dwSize, + TransferCallback fCallback,void * pArg); + +extern uint32_t AUDDStream_SetupWrite( + AUDDStream * pAuds, + void * pListInit, void * pDmaInit, uint16_t listSize, + uint16_t delaySize, + TransferCallback callback,void * argument); + +extern uint32_t AUDDStream_Write( + AUDDStream * pAuds, + void * pBuffer,uint16_t wLength); + +extern uint32_t AUDDStream_Close(AUDDStream * pStream); + +#endif /* _AUDD_STREAM_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/AUDDescriptors.h b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDescriptors.h new file mode 100644 index 00000000..43d5e6b2 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/AUDDescriptors.h @@ -0,0 +1,546 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * Definitions and classes for USB Audio class descriptors. + * + * - 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"). + * -# When declaring the %device descriptor of a USB %audio %device, use + * "USB Audio device descriptor values" defined here. + * -# Declare an AUDStreamingInterfaceDescriptor instance as part of the + * configuration descriptors returned by a USB %audio %device. + * -# Declare a AUDHeaderDescriptor as part of the configuration + * descriptors of the %device. + * -# Declare an AUDFeatureUnitDescriptor instance as part of the + * configuration descriptors returned by a USB %audio %device. + * -# Declare an instance of AUDFormatTypeOneDescriptor as part of the + * configuration descriptors of an audio device. + */ + +#ifndef _AUDDESCRIPTORS_H_ +#define _AUDDESCRIPTORS_H_ +/** \addtogroup usb_audio + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_audio_desc_type USB Audio descriptor types + * @{ + * This section lists the available types for USB audio-specific descriptors. + * - \ref AUDGenericDescriptor_DEVICE + * - \ref AUDGenericDescriptor_CONFIGURATION + * - \ref AUDGenericDescriptor_STRING + * - \ref AUDGenericDescriptor_INTERFACE + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_audio_desc_subtype USB Audio descriptor subtypes + * @{ + * This section lists the possible subtypes for USB audio-specific descriptors. + * - \ref AUDGenericDescriptor_HEADER + * - \ref AUDGenericDescriptor_INPUTTERMINAL + * - \ref AUDGenericDescriptor_OUTPUTTERMINAL + * - \ref AUDGenericDescriptor_MIXERUNIT + * - \ref AUDGenericDescriptor_SELECTORUNIT + * - \ref AUDGenericDescriptor_FEATUREUNIT + * - \ref AUDGenericDescriptor_PROCESSINGUNIT + * - \ref 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 +/** @}*/ + + +/** \addtogroup usb_audio_desc USB Audio Descriptors + * @{ + * USB Audio device descriptor values + * + * This section lists the class, subclass & protocol codes that a USB audio + * device should display in its device descriptor. + * - \ref AUDDeviceDescriptor_CLASS + * - \ref AUDDeviceDescriptor_SUBCLASS + * - \ref 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 +/** @}*/ + + +/** + * \addtogroup usb_audio_stream_if USB Audio streaming interface codes + * @{ + * This section lists the class, subclass and protocol codes that an Audio + * Streaming interface should display in its descriptor. + * - \ref AUDStreamingInterfaceDescriptor_CLASS + * - \ref AUDStreamingInterfaceDescriptor_SUBCLASS + * - \ref 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 +/** @}*/ + +/** + * \addtogroup usb_audio_stream_subtype USB Audio streaming descriptor subtypes + * @{ + * This section lists the possible subtypes for audio-specific descriptor + * appended to an Audio Streaming interface. + * - \ref AUDStreamingInterfaceDescriptor_GENERAL + * - \ref AUDStreamingInterfaceDescriptor_FORMATTYPE + * - \ref 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 +/** @}*/ + + +/** \addtogroup usb_audio_ctrl_if USB Audio Control Interface + * @{ + * This section lists the class, subclass and protocol codes that a USB Audio + * Control interface descriptor should display. + * - \ref AUDControlInterfaceDescriptor_CLASS + * - \ref AUDControlInterfaceDescriptor_SUBCLASS + * - \ref 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 +/** @}*/ + + +/** Descriptor subtype for an Audio data endpoint. */ +#define AUDDataEndpointDescriptor_SUBTYPE 0x01 + +/** \addtogroup usb_audio_lock_delay USB Audio Lock delay units + * @{ + * This section lists the valid lock delay unit types. + * - \ref AUDDataEndpointDescriptor_MILLISECONDS + * - \ref AUDDataEndpointDescriptor_PCMSAMPLES + */ +/** Lock delay is expressed in milliseconds. */ +#define AUDDataEndpointDescriptor_MILLISECONDS 1 +/** Lock delay is expressed in decoded PCM samples. */ +#define AUDDataEndpointDescriptor_PCMSAMPLES 2 +/** @}*/ + + +/** \addtogroup usb_audio_class_ver USB Audio class releases + * @{ + * This section lists the existing versions of the Audio class specification. + * - \ref AUDHeaderDescriptor_AUD1_00 + */ + +/** Indentifies the USB audio specification release 1.00.*/ +#define AUDHeaderDescriptor_AUD1_00 0x0100 +/** @}*/ + +#define AUDTerminalDescriptor_USBSTREAMING 0x0101 +#define AUDTerminalDescriptor_MICROPHONE 0x0201 +#define AUDTerminalDescriptor_HANDSETIN 0x0401 +#define AUDTerminalDescriptor_SPEAKERPHONE 0x0403 +#define AUDTerminalDescriptor_LINEIN 0x0501 + +/** \addtogroup usb_audio_in_term USB Audio Input terminal types + * @{ + * This section lists the available types for an Input terminal. + * - \ref AUDInputTerminalDescriptor_USBSTREAMING + * - \ref AUDInputTerminalDescriptor_MICROPHONE + * - \ref AUDInputTerminalDescriptor_SPEAKERPHONE + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_audio_ch_loc USB Audio Channel spatial locations + * @{ + * This section lists the possible spatial locations for audio channels. + * - \ref AUDInputTerminalDescriptor_LEFTFRONT + * - \ref AUDInputTerminalDescriptor_RIGHTFRONT + * - \ref 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) +/** @}*/ + + +/** \addtogroup usb_audio_out_term USB Audio Output terminal types + * @{ + * This section lists the available types for an output terminal. + * - \ref AUDOutputTerminalDescriptor_USBTREAMING + * - \ref AUDOutputTerminalDescriptor_SPEAKER + * - \ref AUDOutputTerminalDescriptor_HANDSETOUT + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_audio_ch_ctrl USB Audio Channel controls + * @{ + * This section 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. + * -# \ref AUDFeatureUnitDescriptor_MUTE + * -# \ref AUDFeatureUnitDescriptor_VOLUME + * -# \ref AUDFeatureUnitDescriptor_BASS + * -# \ref AUDFeatureUnitDescriptor_MID + * -# \ref 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) +/** @}*/ + + +/** 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 */ + +/** + * \typedef AUDStreamingInterfaceDescriptor + * \brief Provides additional information about an audio streaming interface to + * the USB host. + */ +typedef struct _AUDStreamingInterfaceDescriptor { + + /** Size of descriptor in bytes.*/ + uint8_t bLength; + /** Descriptor type (AUDGenericDescriptor_INTERFACE).*/ + uint8_t bDescriptorType; + /** Descriptor subtype (AUDStreamingInterfaceDescriptor_GENERAL).*/ + uint8_t bDescriptorSubType; + /** Terminal ID to which the interface is connected.*/ + uint8_t bTerminalLink; + /** Delay introduced by the data path, in number of frames.*/ + uint8_t bDelay; + /** Audio data format used by this interface.*/ + uint16_t wFormatTag; + +} __attribute__ ((packed)) AUDStreamingInterfaceDescriptor; /* GCC */ + +/** + * \typedef AUDEndpointDescriptor + * \brief Modified endpoint descriptor with two additional fields, with are + * USB audio specific. + */ +typedef struct _AUDEndpointDescriptor { + + /** Size of the descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (USBGenericDescriptor_ENDPOINT). */ + uint8_t bDescriptorType; + /** Address and direction of the endpoint. */ + uint8_t bEndpointAddress; + /** Endpoint type and additional characteristics (for isochronous endpoints). */ + uint8_t bmAttributes; + /** Maximum packet size (in bytes) of the endpoint. */ + uint16_t wMaxPacketSize; + /** Polling rate of the endpoint. */ + uint8_t bInterval; + /** Refresh rate for a feedback endpoint. */ + uint8_t bRefresh; + /** Address of the associated feedback endpoint if any. */ + uint8_t bSyncAddress; + +} __attribute__ ((packed)) AUDEndpointDescriptor; /* GCC */ + +/** + * \typedef AUDDataEndpointDescriptor + * \brief Gives additional information about an USB endpoint used to transmit audio + * data to or from the host. + */ +typedef struct _AUDDataEndpointDescriptor { + + /** Size of descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type + (\ref AUDGenericDescriptor_ENDPOINT). */ + uint8_t bDescriptorType; + /** Descriptor subtype + (\ref AUDDataEndpointDescriptor_SUBTYPE). */ + uint8_t bDescriptorSubType; + /** Indicates available controls and requirement on packet sizes. */ + uint8_t bmAttributes; + /** Indicates the units of the wLockDelay fields. + \sa usb_audio_lock_delay USB Audio Lock delay units */ + uint8_t bLockDelayUnits; + /** Time it takes for the endpoint to lock its internal clock circuitry. */ + uint16_t wLockDelay; + +} __attribute__ ((packed)) AUDDataEndpointDescriptor; /* GCC */ + +/** + * \typedef AUDHeaderDescriptor + * \brief 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 _AUDHeaderDescriptor { + + /** Size of descriptor in bytes.*/ + uint8_t bLength; + /** Descriptor type (\ref AUDGenericDescriptor_INTERFACE).*/ + uint8_t bDescriptorType; + /** Descriptor subtype (\ref AUDGenericDescriptor_HEADER).*/ + uint8_t bDescriptorSubType; + /** Audio class release number in BCD format + * \sa usb_audio_class_ver USB Audio class releases */ + uint16_t bcdADC; + /** Length of all descriptors used to qualify the Audio Control interface.*/ + uint16_t wTotalLength; + /** Number of Streaming interfaces contained in this collection.*/ + uint8_t bInCollection; + +} __attribute__ ((packed)) AUDHeaderDescriptor; /* GCC */ + +/** + * \typedef AUDInputTerminalDescriptor + * \brief Describes an input of a USB audio device. + */ +typedef struct _AUDInputTerminalDescriptor { + + /** Size of descriptor in bytes.*/ + uint8_t bLength; + /** Descriptor type (AUDGenericDescriptor_INTERFACE).*/ + uint8_t bDescriptorType; + /** Descriptor subtype (AUDGenericDescriptor_INPUTTERMINAL).*/ + uint8_t bDescriptorSubType; + /** ID of the terminal in the audio function.*/ + uint8_t bTerminalID; + /** Terminal type. + * \sa usb_audio_in_term USB Audio Input terminal types + */ + uint16_t wTerminalType; + /** ID of the output terminal to which this input terminal is associated.*/ + uint8_t bAssocTerminal; + /** Number of logical output channels in this terminal.*/ + uint8_t bNrChannels; + /** Spatial configuration of the logical channels.*/ + uint16_t wChannelConfig; + /** Index of a string descriptor for the first logical channel.*/ + uint8_t iChannelNames; + /** Index of a string descriptor for this terminal. */ + uint8_t iTerminal; + +} __attribute__ ((packed)) AUDInputTerminalDescriptor; /* GCC */ + +/** + * \typedef AUDOutputTerminalDescriptor + * \brief Describes an output of the USB audio function. + */ +typedef struct _AUDOutputTerminalDescriptor { + + /** Size of descriptor in bytes.*/ + uint8_t bLength; + /** Descriptor type (\ref AUDGenericDescriptor_INTERFACE).*/ + uint8_t bDescriptorType; + /** Descriptor subtype (\ref AUDGenericDescriptor_OUTPUTTERMINAL). */ + uint8_t bDescriptorSubType; + /** Identifier for this terminal.*/ + uint8_t bTerminalID; + /** Terminal type. + * \sa "USB Audio Output terminal types" */ + uint16_t wTerminalType; + /** Identifier of the associated input terminal.*/ + uint8_t bAssocTerminal; + /** Identifier of the unit or terminal to which this terminal + * is connected.*/ + uint8_t bSourceID; + /** Index of a string descriptor for this terminal.*/ + uint8_t iTerminal; + +} __attribute__ ((packed)) AUDOutputTerminalDescriptor; /* GCC */ + +/** + * \typedef AUDFeatureUnitDescriptor + * \brief 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 _AUDFeatureUnitDescriptor { + + /** Size of descriptor in bytes.*/ + uint8_t bLength; + /** Descriptor type (AUDGenericDescriptor_INTERFACE). */ + uint8_t bDescriptorType; + /** Descriptor subtype (AUDGenericDescriptor_FEATURE). */ + uint8_t bDescriptorSubType; + /** Identifier of this feature unit. */ + uint8_t bUnitID; + /** Identifier of the unit or terminal this feature unit is connected to. */ + uint8_t bSourceID; + /** Size in bytes of a channel controls field. */ + uint8_t bControlSize; + +} __attribute__ ((packed)) AUDFeatureUnitDescriptor; /* GCC */ + +/** + * \typedef AUDFormatTypeOneDescriptor + * \brief 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 = <\ref AUDFormatTypeOneDescriptor_CONTINUOUS>) + * or with an array containing the possible discrete frequencies. + */ +typedef struct _AUDFormatTypeOneDescriptor { + + /** Size of descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (\ref AUDGenericDescriptor_INTERFACE). */ + uint8_t bDescriptorType; + /** Descriptor subtype (\ref AUDStreamingInterfaceDescriptor_FORMATTYPE).*/ + uint8_t bDescriptorSubType; + /** Format type (\ref AUDFormatTypeOneDescriptor_FORMATTYPEONE).*/ + uint8_t bFormatType; + /** Number of physical channels in the audio stream.*/ + uint8_t bNrChannels; + /** Number of bytes occupied by one audio subframe.*/ + uint8_t bSubFrameSize; + /** Number of bits effectively used in an audio subframe.*/ + uint8_t bBitResolution; + /** Number of supported discrete sampling frequencies, or + * \ref AUDFormatTypeOneDescriptor_CONTINUOUS.*/ + uint8_t bSamFreqType; + +} __attribute__ ((packed)) AUDFormatTypeOneDescriptor; /* GCC */ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + + + +/**@}*/ +#endif /* _AUDDESCRIPTORS_H_ */ diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/AUDRequests.h b/sam3s_example/atmel_softpack_libraries/usb/include/AUDRequests.h new file mode 100644 index 00000000..93d16621 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/AUDRequests.h @@ -0,0 +1,123 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * Definitions and classes for USB Audio class requests. + * + * - 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. + * -# 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 _AUDREQUESTS_H_ +#define _AUDREQUESTS_H_ +/** \addtogroup usb_audio + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_audio_request USB Audio request codes + * @{ + * This section lists the codes of the existing Audio requests. + * - \ref AUDGenericRequest_SETCUR + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_audio_ctrl_sel USB Audio Control selector values + * @{ + * This section lists the available control selectors for a Feature Unit request. + * - \ref AUDFeatureUnitRequest_MUTE + */ +/** Mute control selector (MUTE_CONTROL). */ +#define AUDFeatureUnitRequest_MUTE 0x01 +/** Volume control selector (VOLUME_CONTROL). */ +#define AUDFeatureUnitRequest_VOLUME 0x02 +/** @}*/ + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + + + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + +extern uint8_t AUDGenericRequest_GetEntity( + const USBGenericRequest *request); + +extern uint8_t AUDGenericRequest_GetInterface( + const USBGenericRequest *request); + + +extern uint8_t AUDFeatureUnitRequest_GetControl( + const USBGenericRequest *request); + +extern uint8_t AUDFeatureUnitRequest_GetChannel( + const USBGenericRequest *request); + +/**@}*/ +#endif /* _AUDREQUESTS_H_ */ diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCAUDDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCAUDDDriver.h new file mode 100644 index 00000000..50ee688d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCAUDDDriver.h @@ -0,0 +1,307 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definitions and methods for USB composite device implement. + * + */ + +#ifndef CDCAUDDDRIVER_H +#define CDCAUDDDRIVER_H +/** \addtogroup usbd_cdc_aud + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/** \addtogroup usbd_cdc_aud_desc USB CDC(Serial) + AUD(Speaker) Definitions + * @{ + */ +/** Number of interfaces of the device (5, can be 4 if no mic support */ +#define CDCAUDDDriverDescriptors_MaxNumInterfaces 5 +/** Number of the CDC interface. */ +#define CDCAUDDDriverDescriptors_CDC_INTERFACE 0 +/** Number of the Audio interface. */ +#define CDCAUDDDriverDescriptors_AUD_INTERFACE 2 +/** Number of Audio function channels (M,L,R) */ +#define AUDD_NumChannels 3 +/** @}*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** Audio header descriptor with 1 interface */ +typedef struct _AUDHeaderDescriptor1{ + + /** Header descriptor.*/ + AUDHeaderDescriptor header; + /** Id of the first grouped interface.*/ + uint8_t bInterface0; + +} __attribute__ ((packed)) AUDHeaderDescriptor1; + +/** Audio header descriptor with 2 interface */ +typedef struct _AUDHeaderDescriptor2 { + + /** Header descriptor. */ + AUDHeaderDescriptor header; + /** Id of the first grouped interface - Speaker. */ + uint8_t bInterface0; + /** Id of the second grouped interface - Speakerphone. */ + uint8_t bInterface1; + +} __attribute__ ((packed)) AUDHeaderDescriptor2; /* GCC */ + +/** + * Feature unit descriptor with 3 channel controls (master, right, left). + */ +typedef struct _AUDFeatureUnitDescriptor3{ + + /** Feature unit descriptor.*/ + AUDFeatureUnitDescriptor feature; + /** Available controls for each channel.*/ + uint8_t bmaControls[AUDD_NumChannels]; + /** Index of a string descriptor for the feature unit.*/ + uint8_t iFeature; + +} __attribute__ ((packed)) AUDFeatureUnitDescriptor3; + +/** + * List of descriptors for detailling the audio control interface of a + * device using a USB audio speaker function. + */ +typedef struct _AUDDSpeakerAcDescriptors{ + + /** 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)) AUDDSpeakerAcDescriptors; + +/** + * List of descriptors for detailling the audio control interface of a + * device using a USB Audio Speakerphoneer function. + */ +typedef struct _AUDDSpeakerPhoneAcDescriptors { + + /** Header descriptor (with one slave interface). */ + AUDHeaderDescriptor2 header; + /** Input terminal descriptor. */ + AUDInputTerminalDescriptor inputSpeakerPhone; + /** Output terminal descriptor. */ + AUDOutputTerminalDescriptor outputSpeakerPhone; + /** Feature unit descriptor - SpeakerPhone. */ + AUDFeatureUnitDescriptor3 featureSpeakerPhone; + /** Input terminal descriptor. */ + AUDInputTerminalDescriptor inputRec; + /** Output terminal descriptor. */ + AUDOutputTerminalDescriptor outputRec; + /** Feature unit descriptor - SpeakerPhonephone. */ + AUDFeatureUnitDescriptor3 featureRec; + +} __attribute__ ((packed)) AUDDSpeakerPhoneAcDescriptors; + +/** + * Format type I descriptor with one discrete sampling frequency. + */ +typedef struct _AUDFormatTypeOneDescriptor1{ + + /** Format type I descriptor.*/ + AUDFormatTypeOneDescriptor formatType; + /** Sampling frequency in Hz.*/ + uint8_t tSamFreq[3]; + +} __attribute__ ((packed)) AUDFormatTypeOneDescriptor1; + +/** + * Configuration descriptor list for a device implementing + * CDC(Serial) + Audio(Speaker) composite driver. + */ +typedef struct _CdcAudspkdDriverConfigurationDescriptors { + + /** 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; + + /* --- AUDIO (AC) */ + /** IAD 1*/ + USBInterfaceAssociationDescriptor audIAD; + /** Audio control interface.*/ + USBInterfaceDescriptor audInterface; + /** Descriptors for the audio control interface.*/ + AUDDSpeakerAcDescriptors audControl; + /* -- AUDIO out (AS) */ + /** 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; + +} __attribute__ ((packed)) CdcAudspkdDriverConfigurationDescriptors; + +/** + * Configuration descriptor list for a device implementing + * CDC(Serial) + Audio(SpeakerPhone) composite driver. + */ +typedef struct _CdcAuddDriverConfigurationDescriptors { + + /** 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; + + /* --- AUDIO (AC) */ + /** IAD 1*/ + USBInterfaceAssociationDescriptor audIAD; + /** Audio control interface.*/ + USBInterfaceDescriptor audInterface; + /** Descriptors for the audio control interface.*/ + AUDDSpeakerPhoneAcDescriptors audControl; + /* -- AUDIO out (AS) */ + /** 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; + /*- 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)) CdcAuddDriverConfigurationDescriptors; + + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +extern void CDCAUDDDriver_Initialize(const USBDDriverDescriptors * pDescriptors); +extern void CDCAUDDDriver_ConfigurationChangedHandler(uint8_t cfgnum); +extern void CDCAUDDDriver_InterfaceSettingChangedHandler( + uint8_t interface, uint8_t setting); +extern void CDCAUDDDriver_RequestHandler(const USBGenericRequest *request); + +/**@}*/ +#endif //#ifndef CDCHIDDDRIVER_H + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerial.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerial.h new file mode 100644 index 00000000..4d1656c0 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerial.h @@ -0,0 +1,106 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Single CDC Serial Port Function for USB device & composite driver. + */ + +#ifndef CDCDSERIAL_H +#define CDCDSERIAL_H + +/** \addtogroup usbd_cdc + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 + by working group ISO/IEC JTC1/SC22/WG14. */ +#include + +#include + +#include +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern void CDCDSerial_Initialize( + USBDDriver * pUsbd, uint8_t bInterfaceNb); + +extern uint32_t CDCDSerial_RequestHandler( + const USBGenericRequest *request); + +extern void CDCDSerial_ConfigureFunction( + USBGenericDescriptor * pDescriptors, uint16_t wLength); + +extern uint32_t CDCDSerial_Write( + void *data, + uint32_t size, + TransferCallback callback, + void *argument); + +extern uint32_t CDCDSerial_Read( + void *data, + uint32_t size, + TransferCallback callback, + void *argument); + +extern void CDCDSerial_GetLineCoding(CDCLineCoding * pLineCoding); + +extern uint8_t CDCDSerial_GetControlLineState(void); + +extern uint16_t CDCDSerial_GetSerialState(void); + +extern void CDCDSerial_SetSerialState(uint16_t serialState); + +extern uint8_t CDCDSerial_LineCodingIsToChange( + CDCLineCoding * pLineCoding); + +extern void CDCDSerial_ControlLineStateChanged( + uint8_t DTR,uint8_t RTS); + +/**@}*/ + +#endif /*#ifndef CDCSERIAL_H*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialDriver.h new file mode 100644 index 00000000..41e0fda3 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialDriver.h @@ -0,0 +1,245 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definition of a class for implementing a USB device CDC serial driver. + * + * \section 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 + +/** \addtogroup usbd_cdc + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 + by working group ISO/IEC JTC1/SC22/WG14. */ +#include + +#include +#include +#include +#include + +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_cdc_if USB Device CDC Serial Interface IDs + * @{ + */ +/** Communication Class Interface ID */ +#define CDCDSerialDriver_CC_INTERFACE 0 +/** Data Class Interface ID */ +#define CDCDSerialDriver_DC_INTERFACE 1 +/** @}*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** + * \typedef CDCDSerialDriverConfigurationDescriptors + * \brief Configuration descriptor list for a device implementing a + * CDC serial driver. + */ +typedef struct _CDCDSerialDriverConfigurationDescriptors { + + /** Standard configuration descriptor. */ + USBConfigurationDescriptor configuration; + /** 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; + +/** + * \typedef CDCDSerialDriverConfigurationDescriptorsOTG + * \brief Configuration descriptor list for a device implementing a + * CDC serial OTG driver. + */ +typedef struct _CDCDSerialDriverConfigurationDescriptorsOTG { + + /** Standard configuration descriptor. */ + USBConfigurationDescriptor configuration; + /* OTG descriptor */ + USBOtgDescriptor otgDescriptor; + /** 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)) CDCDSerialDriverConfigurationDescriptorsOTG; + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern void CDCDSerialDriver_Initialize( + const USBDDriverDescriptors *pDescriptors); + +extern void CDCDSerialDriver_ConfigurationChangedHandler(uint8_t cfgnum); + +extern void CDCDSerialDriver_RequestHandler( + const USBGenericRequest *request); + +extern uint8_t CDCDSerialDriver_LineCodingIsToChange( + CDCLineCoding * pLineCoding); + +extern void CDCDSerialDriver_ControlLineStateChanged( + uint8_t DTR,uint8_t RTS); + +/** + * 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. + */ +static inline uint32_t CDCDSerialDriver_Write( + void *data, + uint32_t size, + TransferCallback callback, + void *argument) +{ + return CDCDSerial_Write(data, size, callback, argument); +} + +/** + * 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. + */ +static inline uint32_t CDCDSerialDriver_Read( + void *data, + uint32_t size, + TransferCallback callback, + void *argument) +{ + return CDCDSerial_Read(data, size, callback, argument); +} + +/** + * Copy current line coding settings to pointered space. + * \param pLineCoding Pointer to CDCLineCoding instance. + */ +static inline void CDCDSerialDriver_GetLineCoding(CDCLineCoding * pLineCoding) +{ + CDCDSerial_GetLineCoding(pLineCoding); +} + +/** + * Returns the current control line state of the RS-232 line. + */ +static inline uint8_t CDCDSerialDriver_GetControlLineState(void) +{ + return CDCDSerial_GetControlLineState(); +} + +/** + * Returns the current status of the RS-232 line. + */ +static inline uint16_t CDCDSerialDriver_GetSerialState(void) +{ + return CDCDSerial_GetSerialState(); +} + +/** + * Sets the current serial state of the device to the given value. + * \param serialState New device state. + */ +static inline void CDCDSerialDriver_SetSerialState(uint16_t serialState) +{ + CDCDSerial_SetSerialState(serialState); +} + +/**@}*/ + +#endif /*#ifndef CDCSERIALDRIVER_H*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialPort.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialPort.h new file mode 100644 index 00000000..6a6f2ea1 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDSerialPort.h @@ -0,0 +1,167 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Definition of a class for implementing a USB device + * CDC serial port function. + */ + +#ifndef _CDCDSERIALPORT_H_ +#define _CDCDSERIALPORT_H_ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 + by working group ISO/IEC JTC1/SC22/WG14. */ +#include + +#include +#include +#include +#include +#include +/** \addtogroup usbd_cdc + *@{ + */ + +/*------------------------------------------------------------------------------ + * Defines + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_cdc_serial_desc USB Device Serial Port Descriptor Values + * @{ + */ +/** Default CDC interrupt endpoints max packat size (8). */ +#define CDCDSerialPort_INTERRUPT_MAXPACKETSIZE 8 +/** Default CDC interrupt endpoint polling rate of High Speed (16ms). */ +#define CDCDSerialPort_INTERRUPT_INTERVAL_HS 8 +/** Default CDC interrupt endpoint polling rate of Full Speed (16ms). */ +#define CDCDSerialPort_INTERRUPT_INTERVAL_FS 16 +/** Default CDC bulk endpoints max packat size (512, for HS actually). */ +#define CDCDSerialPort_BULK_MAXPACKETSIZE_HS 512 +/** Default CDC bulk endpoints max packat size (64, for FS actually). */ +#define CDCDSerialPort_BULK_MAXPACKETSIZE_FS 64 +/** @}*/ + +/** \addtogroup usbd_cdc_serial_events USB Device Serial Port Events + * @{ + */ +/** SetControlLineState event, value is changed */ +#define CDCDSerialPortEvent_SETCONTROLLINESTATE 0 +/** SetLineCoding event, value is to changed according to return value */ +#define CDCDSerialPortEvent_SETLINECODING 1 +/** @}*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** Callback function for serial port events */ +typedef uint32_t (*CDCDSerialPortEventHandler)(uint32_t dwEvent, + uint32_t dwParam, + void * pArguments); + +/** + * Struct for USB CDC virtual COM serial port function. + */ +typedef struct _CDCDSerialPort { + /** USB Driver for the %device */ + USBDDriver *pUsbd; + /** Callback for serial port events */ + CDCDSerialPortEventHandler fEventHandler; + /** Callback arguments */ + void *pArg; + /** USB starting interface index */ + uint8_t bInterfaceNdx; + /** USB number of interfaces */ + uint8_t bNumInterface; + /** USB interrupt IN endpoint address */ + uint8_t bIntInPIPE; + /** USB bulk IN endpoint address */ + uint8_t bBulkInPIPE; + /** USB bulk OUT endpoint address */ + uint8_t bBulkOutPIPE; + + /** Serial port ControlLineState */ + uint8_t bControlLineState; + /** Serial port SerialState */ + uint16_t wSerialState; + /** Serial port linecoding */ + CDCLineCoding lineCoding; + + uint8_t bReserved; +} CDCDSerialPort; + +/*------------------------------------------------------------------------------ + * Functions + *------------------------------------------------------------------------------*/ + +extern void CDCDSerialPort_Initialize(CDCDSerialPort *pCdcd, + USBDDriver *pUsbd, + CDCDSerialPortEventHandler fCallback, + void *pArg, + uint8_t firstInterface, + uint8_t numInterface); + +extern USBGenericDescriptor * CDCDSerialPort_ParseInterfaces( + CDCDSerialPort * pCdcd, + USBGenericDescriptor * pDescriptors, uint32_t dwLength); + +extern uint32_t CDCDSerialPort_RequestHandler( + CDCDSerialPort *pCdcd, + const USBGenericRequest *pRequest); + +extern uint32_t CDCDSerialPort_Write( + const CDCDSerialPort *pCdcd, + void *pData, uint32_t dwSize, + TransferCallback fCallback, void* pArg); + +extern uint32_t CDCDSerialPort_Read( + const CDCDSerialPort *pCdcd, + void *pData, uint32_t dwSize, + TransferCallback fCallback, void* pArg); + +extern uint16_t CDCDSerialPort_GetSerialState( + const CDCDSerialPort *pCdcd); + +extern void CDCDSerialPort_SetSerialState( + CDCDSerialPort *pCdcd, + uint16_t wSerialState); + +extern uint8_t CDCDSerialPort_GetControlLineState( + const CDCDSerialPort * pCdcd); + +extern void CDCDSerialPort_GetLineCoding( + const CDCDSerialPort * pCdcd, + CDCLineCoding * pLineCoding); + +/**@}*/ +#endif /* #ifndef _CDCDSERIALPORT_H_ */ diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCDescriptors.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDescriptors.h new file mode 100644 index 00000000..b4719b8a --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCDescriptors.h @@ -0,0 +1,275 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * Definitions and classes for USB CDC class descriptors. + */ + +#ifndef _CDCDESCRIPTORS_H_ +#define _CDCDESCRIPTORS_H_ +/** \addtogroup usb_cdc + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_cdc_ver USB CDC Specification Release Numbers + * @{ + * This section list the CDC Spec. Release Numbers. + * - \ref CDCGenericDescriptor_CDC1_10 + */ + +/** Identify CDC specification version 1.10. */ +#define CDCGenericDescriptor_CDC1_10 0x0110 +/** @}*/ + +/** \addtogroup usb_cdc_desc_type CDC Descriptro Types + * @{ + * This section lists CDC descriptor types. + * - \ref CDCGenericDescriptor_INTERFACE + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_cdc_desc_subtype CDC Descriptor Subtypes + * @{ + * This section lists CDC descriptor sub types + * - \ref CDCGenericDescriptor_HEADER + * - \ref CDCGenericDescriptor_CALLMANAGEMENT + * - \ref CDCGenericDescriptor_ABSTRACTCONTROLMANAGEMENT + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_cdc_descriptor USB CDC Device Descriptor Values + * @{ + * This section lists the values for CDC Device Descriptor. + * - \ref CDCDeviceDescriptor_CLASS + * - \ref CDCDeviceDescriptor_SUBCLASS + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_cdc_if_desc USB CDC Communication Interface Descriptor + * @{ + * This section lists the values for CDC Communication Interface Descriptor. + * - \ref CDCCommunicationInterfaceDescriptor_CLASS + * - \ref CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_cdc_data_if USB CDC Data Interface Values + * @{ + * This section lists the values for CDC Data Interface Descriptor. + * - \ref CDCDataInterfaceDescriptor_CLASS + * - \ref CDCDataInterfaceDescriptor_SUBCLASS + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_cdc_cb_man_desc USB CDC CallManagement Capabilities + * @{ + * This section lists CDC CallManagement Capabilities. + * - \ref CDCCallManagementDescriptor_SELFCALLMANAGEMENT + * - \ref 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) +/** @}*/ + +/** \addtogroup usb_cdc_acm USB CDC ACM Capabilities + * @{ + * + * This section lists the capabilities of the CDC ACM. + * - \ref CDCAbstractControlManagementDescriptor_COMMFEATURE + * - \ref CDCAbstractControlManagementDescriptor_LINE + * - \ref CDCAbstractControlManagementDescriptor_SENDBREAK + * - \ref 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 */ + +/** + * \typedef CDCHeaderDescriptor + * \brief Marks the beginning of the concatenated set of functional descriptors + * for the interface. + */ +typedef struct _CDCHeaderDescriptor { + + /** Size of this descriptor in bytes. */ + uint8_t bFunctionLength; + /** Descriptor type . */ + uint8_t bDescriptorType; + /** Descriptor sub-type . */ + uint8_t bDescriptorSubtype; + /** USB CDC specification release number. */ + uint16_t bcdCDC; + +} __attribute__ ((packed)) CDCHeaderDescriptor; /* GCC */ + +/** + * \typedef CDCUnionDescriptor + * \brief Describes the relationship between a group of interfaces that can + * be considered to form a functional unit. + */ +typedef struct _CDCUnionDescriptor { + + /** Size of the descriptor in bytes. */ + uint8_t bFunctionLength; + /** Descriptor type . */ + uint8_t bDescriptorType; + /** Descriptor subtype . */ + uint8_t bDescriptorSubtype; + /** Number of the master interface for this union. */ + uint8_t bMasterInterface; + /** Number of the first slave interface for this union. */ + uint8_t bSlaveInterface0; + +} __attribute__ ((packed)) CDCUnionDescriptor; /* GCC */ + +/** + * \typedef CDCCallManagementDescriptor + * \brief Describes the processing of calls for the communication class + * interface. + */ +typedef struct _CDCCallManagementDescriptor { + + /** Size of this descriptor in bytes. */ + uint8_t bFunctionLength; + /** Descriptor type . */ + uint8_t bDescriptorType; + /** Descriptor sub-type . */ + uint8_t bDescriptorSubtype; + /** Configuration capabilities + \sa usb_cdc_cb_man_desc CDC CallManagement Capabilities. */ + uint8_t bmCapabilities; + /** Interface number of the data class interface used for call management + (optional). */ + uint8_t bDataInterface; + +} __attribute__ ((packed)) CDCCallManagementDescriptor; /* GCC */ + +/** + * \typedef CDCAbstractControlManagementDescriptor + * \brief Describes the command supported by the communication interface class + * with the Abstract Control Model subclass code. + */ +typedef struct _CDCAbstractControlManagementDescriptor { + + /** Size of this descriptor in bytes. */ + uint8_t bFunctionLength; + /** Descriptor type . */ + uint8_t bDescriptorType; + /** Descriptor subtype . */ + uint8_t bDescriptorSubtype; + /** Configuration capabilities. + \sa usb_cdc_acm CDC ACM Capabilities. */ + uint8_t bmCapabilities; + +} __attribute__ ((packed)) CDCAbstractControlManagementDescriptor; /* GCC */ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + + +/**@}*/ +#endif /* #ifndef _CDCDESCRIPTORS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCHIDDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCHIDDDriver.h new file mode 100644 index 00000000..b0026111 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCHIDDDriver.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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definitions and methods for USB composite device implement. + * + * \section 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 +/** \addtogroup usbd_cdc_hid + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/** \addtogroup usbd_cdc_hid_desc USB CDC(Serial) + HID(Kbd) Descriptors define + * @{ + */ +/** Number of interfaces of the device */ +#define CDCHIDDDriverDescriptors_NUMINTERFACE 3 +/** Number of the CDC interface. */ +#define CDCHIDDDriverDescriptors_CDC_INTERFACE 0 +/** Number of the HID interface. */ +#define CDCHIDDDriverDescriptors_HID_INTERFACE 2 +/** @}*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef CdcHidDriverConfigurationDescriptors + * \brief Configuration descriptor list for a device implementing a + * composite driver. + */ +typedef struct _CdcHidDriverConfigurationDescriptors { + + /** 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; + HIDDescriptor1 hid; + USBEndpointDescriptor hidInterruptIn; + USBEndpointDescriptor hidInterruptOut; + +} __attribute__ ((packed)) CdcHidDriverConfigurationDescriptors; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/* -CDCHID */ +extern void CDCHIDDDriver_Initialize( + const USBDDriverDescriptors * pDescriptors); + +extern void CDCHIDDDriver_ConfigurationChangedHandler(uint8_t cfgnum); + +extern void CDCHIDDDriver_RequestHandler(const USBGenericRequest *request); + +extern void CDCHIDDDriver_RemoteWakeUp(void); + +/**@}*/ +#endif //#ifndef CDCHIDDDRIVER_H + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCMSDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCMSDDriver.h new file mode 100644 index 00000000..6f01f1ab --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCMSDDriver.h @@ -0,0 +1,155 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definitions and methods for USB CDCMSD device implement. + * + * \section 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 +/** \addtogroup usbd_composite_cdcmsd + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Consts + *---------------------------------------------------------------------------*/ + +/** \addtogroup usbd_cdc_msd_desc USB CDC(Serial) + MS Descriptors define + * @{ + */ +/** Number of interfaces of the device */ +#define CDCMSDDriverDescriptors_NUMINTERFACE 3 +/** Number of the CDC interface. */ +#define CDCMSDDriverDescriptors_CDC_INTERFACE 0 +/** Number of the HID interface. */ +#define CDCMSDDriverDescriptors_MSD_INTERFACE 2 +/** @}*/ + + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef CDCMSDDriverConfigurationDescriptors + * \brief Configuration descriptor list for a device implementing + * a CDCMSD driver. + */ +typedef struct _CDCMSDDriverConfigurationDescriptors { + + /** 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 functions + *---------------------------------------------------------------------------*/ + +/* -CDCMSD */ +extern void CDCMSDDriver_Initialize( + const USBDDriverDescriptors *pDescriptors, + MSDLun *pLuns, unsigned char numLuns); + +extern void CDCMSDDriver_ConfigurationChangedHandler(unsigned char cfgnum); + +extern void CDCMSDDriver_RequestHandler(const USBGenericRequest *request); + +/**@}*/ +#endif /* #ifndef CDCMSDDDRIVER_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCNotifications.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCNotifications.h new file mode 100644 index 00000000..c37631cb --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCNotifications.h @@ -0,0 +1,111 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Definitions and methods for USB CDC Notifications. + */ + +#ifndef _CDCNOTIFICATIONS_H_ +#define _CDCNOTIFICATIONS_H_ +/** \addtogroup usb_cdc + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup cdc_serial_states CDC SerialState bits + * @{ + * This page lists the bit map for CDC Serial States. + * + * - \ref CDCSerialState_RXDRIVER + * - \ref CDCSerialState_TXCARRIER + * - \ref CDCSerialState_BREAK + * - \ref CDCSerialState_RINGSIGNAL + * - \ref CDCSerialState_FRAMING + * - \ref CDCSerialState_PARITY + * - \ref CDCSerialState_OVERRUN + */ + +/** Indicates the receiver carrier signal is present */ +#define CDCSerialState_RXDRIVER (1 << 0) +/** Indicates the transmission carrier signal is present */ +#define CDCSerialState_TXCARRIER (1 << 1) +/** Indicates a break has been detected */ +#define CDCSerialState_BREAK (1 << 2) +/** Indicates a ring signal has been detected */ +#define CDCSerialState_RINGSIGNAL (1 << 3) +/** Indicates a framing error has occured */ +#define CDCSerialState_FRAMING (1 << 4) +/** Indicates a parity error has occured */ +#define CDCSerialState_PARITY (1 << 5) +/** Indicates a data overrun error has occured */ +#define CDCSerialState_OVERRUN (1 << 6) +/** @}*/ + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** USB CDC SerialState struct (bitmap) */ +typedef struct _CDCSerialState { + uint16_t bRxCarrier:1, /**< State of receive carrier detection (V2.4 signal + 109 and RS-232 signal DCD) */ + bTxCarrier:1, /**< State of transmission carrier */ + bBreak:1, /**< State of break detection */ + bRingSignal:1, /**< State of ring signal */ + bFraming:1, /**< Framing error */ + bParity:1, /**< Parity error */ + bOverRun:1, /**< Received data discarded due to overrun error */ + reserved:9; /**< Reserved */ +} __attribute__ ((packed)) CDCSerialState; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + +/**@}*/ +#endif /* #ifndef _CDCNOTIFICATIONS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/CDCRequests.h b/sam3s_example/atmel_softpack_libraries/usb/include/CDCRequests.h new file mode 100644 index 00000000..eb30b999 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/CDCRequests.h @@ -0,0 +1,182 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * Definitions and classes for USB CDC class requests + * (mostly for ACM). + * + * \section CDCLineCoding + * + * -# 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 _CDCREQUESTS_H_ +#define _CDCREQUESTS_H_ +/** \addtogroup usb_cdc + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_cdc_request USB CDC Request Codes + * @{ + * This section lists USB CDC Request Codes. + * - \ref CDCGenericRequest_SETLINECODING + * - \ref CDCGenericRequest_GETLINECODING + * - \ref CDCGenericRequest_SETCONTROLLINESTATE + */ + +/** SetLineCoding request code. */ +#define CDCGenericRequest_SETLINECODING 0x20 +/** GetLineCoding request code. */ +#define CDCGenericRequest_GETLINECODING 0x21 +/** SetControlLineState request code. */ +#define CDCGenericRequest_SETCONTROLLINESTATE 0x22 +/** @}*/ + +/** \addtogroup usb_cdc_ctrl_line_state USB CDC ControlLineState bitmap + * @{ + * This section lists CDC ControlLineState bitmap. + * - \ref CDCControlLineState_DTR, CDCControlLineState_DTE_PRESENT + * - \ref CDCControlLineState_RTS, CDCControlLineState_CARRIER_ON + */ +/** Indicates to DCE if DTE is present or not. */ +#define CDCControlLineState_DTE_PRESENT (1 << 0) +/** RS232 signal DTR: Data Terminal Ready. */ +#define CDCControlLineState_DTR (1 << 0) +/** Carrier control for half duplex modems. */ +#define CDCControlLineState_CARRIER_ON (1 << 1) +/** RS232 signal RTS: Request to send. */ +#define CDCControlLineState_RTS (1 << 1) +/** @}*/ + +/** \addtogroup usb_cdc_stop USB CDC LineCoding StopBits + * @{ + * This section lists Stop Bits for CDC Line Coding. + * - \ref CDCLineCoding_ONESTOPBIT + * - \ref CDCLineCoding_ONE5STOPBIT + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_cdc_parity USB CDC LineCoding ParityCheckings + * @{ + * This section lists Parity checkings for CDC Line Coding. + * - \ref CDCLineCoding_NOPARITY + * - \ref CDCLineCoding_ODDPARITY + * - \ref CDCLineCoding_EVENPARITY + * - \ref CDCLineCoding_MARKPARITY + * - \ref 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 */ + +/** + * \typedef CDCLineCoding + * \brief Format of the data returned when a GetLineCoding request is received. + */ +typedef struct _CDCLineCoding { + + /** Data terminal rate in bits per second. */ + uint32_t dwDTERate; + /** Number of stop bits. + \sa usb_cdc_stop CDC LineCoding StopBits. */ + uint8_t bCharFormat; + /** Type of parity checking used. + \sa usb_cdc_parity CDC LineCoding ParityCheckings. */ + uint8_t bParityType; + /** Number of data bits (5, 6, 7, 8 or 16). */ + uint8_t bDataBits; + +} __attribute__ ((packed)) CDCLineCoding; /* GCC */ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + +extern uint8_t CDCSetControlLineStateRequest_IsDtePresent( + const USBGenericRequest *request); + +extern uint8_t CDCSetControlLineStateRequest_ActivateCarrier( + const USBGenericRequest *request); + +extern void CDCLineCoding_Initialize(CDCLineCoding *lineCoding, + uint32_t bitrate, + uint8_t stopbits, + uint8_t parity, + uint8_t databits); + + +/**@}*/ +#endif /* #define _CDCREQUESTS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/DUALCDCDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/DUALCDCDDriver.h new file mode 100644 index 00000000..4478fbe9 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/DUALCDCDDriver.h @@ -0,0 +1,157 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definitions and methods for USB composite device implement. + * + */ + +#ifndef DUALCDCDDRIVER_H +#define DUALCDCDDRIVER_H +/** \addtogroup usbd_composite_cdccdc + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include +#include + +#include +#include + + +/*--------------------------------------------------------------------------- + * Defines + *---------------------------------------------------------------------------*/ + +/** \addtogroup usbd_composite_cdccdc_desc + * The driver uses these interface numbers in configuration descriptor. + * @{ + */ +/** Number of interfaces of the device */ +#define DUALCDCDDriverDescriptors_NUMINTERFACE 4 +/** Number of the CDC0 interface. */ +#define DUALCDCDDriverDescriptors_INTERFACENUM0 0 +/** Number of the CDC1 interface. */ +#define DUALCDCDDriverDescriptors_INTERFACENUM1 2 +/** @}*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef DualCdcDriverConfigurationDescriptors + * \brief Configuration descriptor list for a device implementing a + * dual CDC serial composite driver. + */ +typedef struct _DualCdcDriverConfigurationDescriptors { + + /** 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 functions + *---------------------------------------------------------------------------*/ + +/* -DUALCDC */ +extern void DUALCDCDDriver_Initialize( + const USBDDriverDescriptors* pDescriptors); + +extern void DUALCDCDDriver_ConfigurationChangeHandler(uint8_t cfgnum); + +extern void DUALCDCDDriver_RequestHandler(const USBGenericRequest *request); + +extern CDCDSerialPort* DUALCDCDDriver_GetSerialPort(uint32_t port); + +/**@}*/ +#endif /* #ifndef DUALCDCDDRIVER_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDAUDDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDAUDDDriver.h new file mode 100644 index 00000000..d355e417 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDAUDDDriver.h @@ -0,0 +1,191 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definitions and methods for USB composite device implement. + * + */ + +#ifndef HIDAUDDDRIVER_H +#define HIDAUDDDRIVER_H +/** \addtogroup usbd_hid_aud + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/** \addtogroup usbd_hid_aud_desc USB HID(Keyboard) + AUD(Speaker) Definitions + * @{ + */ +/** Number of interfaces of the device 1+2 */ +#define HIDAUDDDriverDescriptors_NUMINTERFACE 3 +/** Number of the CDC interface. */ +#define HIDAUDDDriverDescriptors_HID_INTERFACE 0 +/** Number of the Audio interface. */ +#define HIDAUDDDriverDescriptors_AUD_INTERFACE 1 +/** @}*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** Structure of audio header descriptor*/ +typedef struct _AUDHeaderDescriptor1{ + + /** Header descriptor.*/ + AUDHeaderDescriptor header; + /** Id of the first grouped interface.*/ + unsigned char bInterface0; + +} __attribute__ ((packed)) AUDHeaderDescriptor1; + +/** + * Feature unit descriptor with 3 channel controls (master, right, left). + */ +typedef struct _AUDFeatureUnitDescriptor3{ + + /** 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; + +/** + * List of descriptors for detailling the audio control interface of a + * device using a USB audio speaker driver. + */ +typedef struct _AUDDSpeakerDriverAudioControlDescriptors{ + + /** 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 _AUDFormatTypeOneDescriptor1{ + + /** Format type I descriptor.*/ + AUDFormatTypeOneDescriptor formatType; + /** Sampling frequency in Hz.*/ + unsigned char tSamFreq[3]; + +} __attribute__ ((packed)) AUDFormatTypeOneDescriptor1; // GCC + +/** + * \typedef CdcAudDriverConfigurationDescriptors + * \brief Configuration descriptor list for a device implementing a + * composite HID (Keyboard) + Audio (Speaker) driver. + */ +typedef struct _HidAuddDriverConfigurationDescriptors { + + /** Standard configuration descriptor. */ + USBConfigurationDescriptor configuration; + + /* --- HID */ + /** HID interface. */ + USBInterfaceDescriptor hidInterface; + /** HID descriptor */ + HIDDescriptor1 hid; + /** HID interrupt IN */ + USBEndpointDescriptor hidInterruptIn; + /** HID interrupt OUT */ + USBEndpointDescriptor hidInterruptOut; + + /* --- AUDIO (AC) */ + /** Audio IAD */ + USBInterfaceAssociationDescriptor audIAD; + /** Audio control interface.*/ + USBInterfaceDescriptor audInterface; + /** Descriptors for the audio control interface.*/ + AUDDSpeakerDriverAudioControlDescriptors audControl; + /* -- AUDIO out (AS) */ + /** 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; + +} __attribute__ ((packed)) HidAuddDriverConfigurationDescriptors; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +extern void HIDAUDDDriver_Initialize(const USBDDriverDescriptors * pDescriptors); +extern void HIDAUDDDriver_ConfigurationChangedHandler(uint8_t cfgnum); +extern void HIDAUDDDriver_InterfaceSettingChangedHandler( + uint8_t interface, uint8_t setting); +extern void HIDAUDDDriver_RequestHandler(const USBGenericRequest *request); + +/**@}*/ +#endif //#ifndef CDCHIDDDRIVER_H + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDDFunction.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDFunction.h new file mode 100644 index 00000000..8fa93243 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDFunction.h @@ -0,0 +1,210 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * + * Definitions used for general HID support. + * + * The HID Function supports following: + * - 1 interface with 1 pipe in and 1 pipe out; + * - An input report list; + * - An output report list; + * - handles requests: + * - handles: GET_IDLE/SET_IDLE, + * GET_REPORT/SET_REPORT, + * SET_PROTOCOL/GET_PROTOCOL; + * - stall : SET_DESCRIPTOR. + */ + +#ifndef _HIDDFUNCTION_H_ +#define _HIDDFUNCTION_H_ +/** \addtogroup usbd_hid + * @{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + +#include +#include + +#include +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usbd_hid_events HIDD Event codes + * @{ + */ +/** Report sent */ +#define HIDD_EC_REPORTSENT 1 +/** Report changed */ +#define HIDD_EC_REPORTCHANGED 2 +/** Report sent because of GET_REPORT Request */ +#define HIDD_EC_GETREPORT 3 +/** Report changed because of SET_REPORT Request */ +#define HIDD_EC_SETREPORT 4 +/** @}*/ + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +/** + * Callback function for HID report events. + */ +typedef void(*HIDDReportEventCallback)(uint32_t ec, void *pArg); + +/** + * Struct for a header of basic HID report descriptor. + */ +typedef struct _HIDDReportHeader { + /** Callback when report done */ + HIDDReportEventCallback fCallback; + /** Callback arguments */ + void* pArg; + + /** Report size (ID + DATA) */ + uint16_t wMaxSize; + /** Transfered size */ + uint16_t wTransferred; + /** Report idle rate */ + uint8_t bIdleRate; + /** Delay count for Idle */ + uint8_t bDelay; + /** Report ID */ + uint8_t bID; +} HIDDReportHeader; + +/** + * Struct for an basic HID report descriptor. + */ +typedef struct _HIDDReport { + /** Callback when report done */ + HIDDReportEventCallback fCallback; + /** Callback arguments */ + void* pArg; + + /** Report size (ID + DATA) */ + uint16_t wMaxSize; + /** Transfered size */ + uint16_t wTransferred; + /** Report idle rate */ + uint8_t bIdleRate; + /** Delay count for Idle */ + uint8_t bDelay; + /** Report ID */ + uint8_t bID; + /** Report data block start ... */ + uint8_t bData[1]; +} HIDDReport; + +/** + * Struct for an HID general function. + * Supports Input/Output reports. No feature report support. + */ +typedef struct _HIDDFunction { + /** USB Driver for the %device */ + USBDDriver *pUsbd; + /** HID descriptor */ + HIDDescriptor *pHidDescriptor; + /** HID Specific report descriptor */ + uint8_t *pReportDescriptor; + /** USB interface for HID function */ + uint8_t bInterface; + /** USB interrupt IN EP */ + uint8_t bPipeIN; + /** USB interrupt OUT EP */ + uint8_t bPipeOUT; + + /** HID Protocol */ + uint8_t bProtocol; + + /** HID Input reports list */ + HIDDReport **pInputList; + /** HID Output reports list */ + HIDDReport **pOutputList; + /** HID Input report list size */ + uint8_t bInputListSize; + /** Current input report */ + uint8_t bCurrInput; + /** HID Output reports list */ + uint8_t bOutputListSize; + /** Current output report */ + uint8_t bCurrOutput; +} HIDDFunction; + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + +extern void HIDDFunction_Initialize( + HIDDFunction * pHidd, + USBDDriver * pUsbd, uint8_t bInterfaceNb, + const uint8_t * pReportDescriptor, + HIDDReport * pInputList [ ], uint8_t bInputListSize, + HIDDReport * pOutputList [ ], uint8_t bOutputListSize); + +extern USBGenericDescriptor* HIDDFunction_ParseInterface( + HIDDFunction * pHidd, + USBGenericDescriptor * pDescriptors, + uint32_t dwLength); + +extern uint32_t HIDDFunction_RequestHandler( + HIDDFunction * pHidd, + const USBGenericRequest * request); + +extern uint32_t HIDDFunction_StartSendingInputs(HIDDFunction * pHidd); + +extern uint32_t HIDDFunction_StartPollingOutputs(HIDDFunction * pHidd); + +extern uint32_t HIDDFunction_Read( + const HIDDFunction * pHidd, + void * pData, uint32_t dwLength, + TransferCallback fCallback, void * pArg); + +extern uint32_t HIDDFunction_Write( + const HIDDFunction * pHidd, + void * pData, uint32_t dwLength, + TransferCallback fCallback, void * pArg); + +extern void HIDDFunction_InitializeReport( + HIDDReport * pReport, + uint16_t wSize, + uint8_t bID, + HIDDReportEventCallback fCallback, void* pArg); + +/**@}*/ +#endif /* #define _HIDDFUNCTION_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboard.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboard.h new file mode 100644 index 00000000..26ca8087 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboard.h @@ -0,0 +1,216 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * Definition of methods for using a HID keyboard function. + */ + +#ifndef HIDDKEYBOARD_H +#define HIDDKEYBOARD_H + +/** \addtogroup usbd_hid_key + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "board.h" + +#include "USBDescriptors.h" +#include "USBRequests.h" + +#include "HIDDescriptors.h" +#include "USBDDriver.h" + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_hid_kbd_desc HIDD Keyboard Driver Definitions + * @{ + */ + +/** Maximum number of simultaneous key presses. */ +#define HIDDKeyboardInputReport_MAXKEYPRESSES 3 + +/** \addtogroup usbd_hid_kbd_keys HID Keypad keys + * @{ + * This page lists definition for HID keypad keys. + * + * \section Keys + * - HIDDKeyboardDescriptors_FIRSTMODIFIERKEY + * - HIDDKeyboardDescriptors_LASTMODIFIERKEY + * - HIDDKeyboardDescriptors_FIRSTSTANDARDKEY + * - HIDDKeyboardDescriptors_LASTSTANDARDKEY + */ +/** Key code of the first accepted modifier key */ +#define HIDDKeyboardDescriptors_FIRSTMODIFIERKEY HIDKeypad_LEFTCONTROL +/** Key code of the last accepted modifier key */ +#define HIDDKeyboardDescriptors_LASTMODIFIERKEY HIDKeypad_RIGHTGUI +/** Key code of the first accepted standard key */ +#define HIDDKeyboardDescriptors_FIRSTSTANDARDKEY 0 +/** Key code of the last accepted standard key */ +#define HIDDKeyboardDescriptors_LASTSTANDARDKEY HIDKeypad_NUMLOCK +/** @}*/ + +/** \addtogroup usbd_hid_kbd_polling HID Keyboard Default Polling Rates + * @{ + */ +/** Default HID interrupt IN endpoint polling rate FS (16ms). */ +#define HIDDKeyboardDescriptors_INTERRUPTIN_POLLING_FS 16 +/** Default HID interrupt IN endpoint polling rate HS (16ms). */ +#define HIDDKeyboardDescriptors_INTERRUPTIN_POLLING_HS 8 +/** Default interrupt OUT endpoint polling rate FS (16ms). */ +#define HIDDKeyboardDescriptors_INTERRUPTOUT_POLLING_FS 16 +/** Default interrupt OUT endpoint polling rate HS (16ms). */ +#define HIDDKeyboardDescriptors_INTERRUPTOUT_POLLING_HS 8 +/** @}*/ + +/** Size of the report descriptor in bytes */ +#define HIDDKeyboard_REPORTDESCRIPTORSIZE 61 + +/** @}*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef HIDDKeyboardOutputReport + * \brief 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 _HIDDKeyboardOutputReport { + + uint8_t 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 */ + +/** + * \typedef HIDDKeyboardInputReport + * \brief 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 _HIDDKeyboardInputReport { + + /** State of modifier keys. */ + uint8_t bmModifierKeys:8; + /** Key codes of pressed keys. */ + uint8_t pressedKeys[HIDDKeyboardInputReport_MAXKEYPRESSES]; +} __attribute__ ((packed)) HIDDKeyboardInputReport; /* GCC */ + + +/** + * \typedef HIDDKeyboardDriverConfigurationDescriptors + * \brief List of descriptors that make up the configuration descriptors of a + * device using the HID keyboard driver. + */ +typedef struct _HIDDKeyboardDriverConfigurationDescriptors { + + /** Configuration descriptor. */ + USBConfigurationDescriptor configuration; + /** Interface descriptor. */ + USBInterfaceDescriptor interface; + /** HID descriptor. */ + HIDDescriptor1 hid; + /** Interrupt IN endpoint descriptor. */ + USBEndpointDescriptor interruptIn; + /** Interrupt OUT endpoint descriptor. */ + USBEndpointDescriptor interruptOut; + +} __attribute__ ((packed)) HIDDKeyboardDriverConfigurationDescriptors; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern void HIDDKeyboard_Initialize(USBDDriver * pUsbd,uint8_t bInterfaceNb); + +extern void HIDDKeyboard_ConfigureFunction( USBGenericDescriptor * pDescriptors, uint16_t wLength); + +extern uint32_t HIDDKeyboard_RequestHandler( const USBGenericRequest *request); + +extern uint32_t HIDDKeyboard_ChangeKeys( + uint8_t *pressedKeys, + uint8_t pressedKeysSize, + uint8_t *releasedKeys, + uint8_t releasedKeysSize); + +extern void HIDDKeyboard_RemoteWakeUp(void); + +extern void HIDDKeyboardCallbacks_LedsChanged( + uint8_t numLockStatus, + uint8_t capsLockStatus, + uint8_t scrollLockStatus); + + +extern void HIDDKeyboardInputReport_Initialize(HIDDKeyboardInputReport *report); + +extern void HIDDKeyboardInputReport_PressStandardKey( HIDDKeyboardInputReport *report, uint8_t key ) ; + +extern void HIDDKeyboardInputReport_ReleaseStandardKey( HIDDKeyboardInputReport *report, uint8_t key ) ; + +extern void HIDDKeyboardInputReport_PressModifierKey( HIDDKeyboardInputReport *report, uint8_t key); + +extern void HIDDKeyboardInputReport_ReleaseModifierKey( HIDDKeyboardInputReport *report, uint8_t key); + + +extern void HIDDKeyboardOutputReport_Initialize( HIDDKeyboardOutputReport *report); + +extern uint8_t HIDDKeyboardOutputReport_GetNumLockStatus( const HIDDKeyboardOutputReport *report); + +extern uint8_t HIDDKeyboardOutputReport_GetCapsLockStatus( const HIDDKeyboardOutputReport *report); + +extern uint8_t HIDDKeyboardOutputReport_GetScrollLockStatus( const HIDDKeyboardOutputReport *report); + +/**@}*/ + +#endif /*#ifndef HIDDKEYBOARD_H*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboardDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboardDriver.h new file mode 100644 index 00000000..e7fa5f49 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDKeyboardDriver.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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Definition of methods for using a HID keyboard device driver. + * + * \section 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 + +/** \addtogroup usbd_hid_key + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include + +#include + +#include + +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern void HIDDKeyboardDriver_Initialize( + const USBDDriverDescriptors *pDescriptors); + +extern void HIDDKeyboardDriver_ConfigurationChangedHandler( + uint8_t cfgnum); + +extern void HIDDKeyboardDriver_RequestHandler( + const USBGenericRequest *request); + +/** + * 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. + */ +static inline uint32_t HIDDKeyboardDriver_ChangeKeys( + uint8_t *pressedKeys, + uint8_t pressedKeysSize, + uint8_t *releasedKeys, + uint8_t releasedKeysSize){ + return HIDDKeyboard_ChangeKeys(pressedKeys, pressedKeysSize, + releasedKeys, releasedKeysSize); +} + +/** + * Starts a remote wake-up sequence if the host has explicitely enabled it + * by sending the appropriate SET_FEATURE request. + */ +static inline void HIDDKeyboardDriver_RemoteWakeUp(void) { + HIDDKeyboard_RemoteWakeUp(); +} + +/**@}*/ + +#endif /*#ifndef HIDDKEYBOARDDRIVER_H*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDDMouseDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDMouseDriver.h new file mode 100644 index 00000000..546f8350 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDMouseDriver.h @@ -0,0 +1,151 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * + * \section Purpose + * + * Definition of methods for using a HID mouse device driver. + * + * \section 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 + +/** \addtogroup usbd_hid_mouse + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include +#include + +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_hid_mouse_button_bitmaps HID Mouse Button bitmaps + * @{ + * \section 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) +/** @}*/ + +/** Size of the report descriptor in bytes. */ +#define HIDDMouseDriver_REPORTDESCRIPTORSIZE 50 + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef HIDDMouseDriverConfigurationDescriptors + * \brief List of descriptors that make up the configuration descriptors of a + * device using the HID Mouse driver. + */ +typedef struct _HIDDMouseDriverConfigurationDescriptors { + + /** Configuration descriptor. */ + USBConfigurationDescriptor configuration; + /** Interface descriptor. */ + USBInterfaceDescriptor interface; + /** HID descriptor. */ + HIDDescriptor1 hid; + /** Interrupt IN endpoint descriptor. */ + USBEndpointDescriptor interruptIn; + +} __attribute__ ((packed)) HIDDMouseDriverConfigurationDescriptors; + +/** + * \typedef HIDDMouseInputReport + * \brief HID input report data struct used by the Mouse driver to notify the + * host of pressed keys. + */ +typedef struct _HIDDMouseInputReport { + + uint8_t bmButtons; /**< Bitmap state of three mouse buttons. */ + int8_t bX; /**< Pointer displacement along the X axis. */ + int8_t bY; /**< Pointer displacement along the Y axis. */ +} __attribute__ ((packed)) HIDDMouseInputReport; /* GCC */ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern void HIDDMouseDriver_Initialize(const USBDDriverDescriptors *pDescriptors); + +extern void HIDDMouseDriver_ConfigurationChangedHandler(uint8_t cfgnum); + +extern void HIDDMouseDriver_RequestHandler(const USBGenericRequest *request); + +extern uint8_t HIDDMouseDriver_ChangePoints(uint8_t bmButtons, + int8_t deltaX, + int8_t deltaY); + +extern void HIDDMouseDriver_RemoteWakeUp(void); + +/**@}*/ + +#endif /*#ifndef HIDDKEYBOARDDRIVER_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDDTransferDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDTransferDriver.h new file mode 100644 index 00000000..76dcdff1 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDTransferDriver.h @@ -0,0 +1,141 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + *\file + * + *\section Purpose + * + *Definition of methods for using a HID transfer %device driver. + * + *\section 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 + +/** \addtogroup usbd_hid_tran + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include + +#include + +#include +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** Size of the input and output report, in bytes */ +#define HIDDTransferDriver_REPORTSIZE 32 + +/** Size of the report descriptor, in bytes */ +#define HIDDTransferDriver_REPORTDESCRIPTORSIZE 32 + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef HIDDTransferDriverConfigurationDescriptors + * \brief List of descriptors that make up the configuration descriptors of a + * device using the HID Transfer driver. + */ +typedef struct _HIDDTransferDriverConfigurationDescriptors { + + /** Configuration descriptor. */ + USBConfigurationDescriptor configuration; + /** Interface descriptor. */ + USBInterfaceDescriptor interface; + /** HID descriptor. */ + HIDDescriptor1 hid; + /** Interrupt IN endpoint descriptor. */ + USBEndpointDescriptor interruptIn; + /** Interrupt OUT endpoint descriptor. */ + USBEndpointDescriptor interruptOut; + +} __attribute__ ((packed)) HIDDTransferDriverConfigurationDescriptors; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern void HIDDTransferDriver_Initialize( + const USBDDriverDescriptors * pDescriptors); + +extern void HIDDTransferDriver_ConfigurationChangedHandler(uint8_t cfgnum); + +extern void HIDDTransferDriver_RequestHandler( + const USBGenericRequest *request); + +extern uint16_t HIDDTransferDriver_Read(void *pData, + uint32_t dLength); + +extern uint16_t HIDDTransferDriver_ReadReport(void *pData, + uint32_t dLength); + +extern uint8_t HIDDTransferDriver_Write(const void *pData, + uint32_t size, + TransferCallback callback, + void *pArg); + + +extern void HIDDTransferDriver_RemoteWakeUp(void); + +/**@}*/ + +#endif /*#ifndef HIDDKEYBOARDDRIVER_H*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDDescriptors.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDescriptors.h new file mode 100644 index 00000000..41104be6 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDDescriptors.h @@ -0,0 +1,229 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * + * \section Purpose + * + * Definitions used for declaring the descriptors of a HID device. + * + */ + +#ifndef _HIDDESCRIPTORS_H_ +#define _HIDDESCRIPTORS_H_ +/** \addtogroup usb_hid + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + +#include "HIDReports.h" +#include "HIDUsages.h" + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_hid_device_descriptor_codes HID Device Descriptor Codes + * @{ + * This page lists HID device class, subclass and protocol codes. + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_interface_descriptor_codes HID Interface Descriptor Codes + * @{ + * This page lists HID Interface class, subclass and protocol codes. + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_ver HID Release Numbers + * @{ + * - \ref HIDDescriptor_HID1_11 + */ + +/** Identifies version 1.11 of the HID specification. */ +#define HIDDescriptor_HID1_11 0x0111 +/** @}*/ + +/** \addtogroup usb_descriptors_types HID Descriptors Types + * @{ + * + * \section 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 +/** @}*/ + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef HIDDescriptor + * \brief Identifies the length of type of subordinate descriptors of a HID + * device. This particular type has no subordinate descriptor. + */ +typedef struct _HIDDescriptor { + + /** Size of descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (\ref HIDGenericDescriptor_HID). */ + uint8_t bDescriptorType; + /** HID class specification release number in BCD format. */ + uint16_t bcdHID; + /** Country code of the device if it is localized. */ + uint8_t bCountryCode; + /** Number of subordinate descriptors. */ + uint8_t bNumDescriptors; + +} __attribute__ ((packed)) HIDDescriptor; /* GCC */ + +/** + * \typedef HIDDescriptor + * \brief Identifies the length of type of subordinate descriptors of a HID + * device. This particular type only supports one subordinate descriptor. + */ +typedef struct _HIDDescriptor1 { + + /** Size of descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (\ref HIDGenericDescriptor_HID). */ + uint8_t bDescriptorType; + /** HID class specification release number in BCD format. */ + uint16_t bcdHID; + /** Country code of the device if it is localized. */ + uint8_t bCountryCode; + /** Number of subordinate descriptors. */ + uint8_t bNumDescriptors; + /** Type of the first subordinate descriptor. */ + uint8_t bDescriptorType0; + /** Size in bytes of the first subordinate descriptor. */ + /* uint8_t bDescriptorLength0[2]; */ + uint16_t wDescriptorLength0; + +} __attribute__ ((packed)) HIDDescriptor1; /* GCC */ + +/** + * HID Physical Descriptor set 0: specifies the number of additional + * descriptor sets. + */ +typedef struct _HIDPhysicalDescriptor0 { + /** Numeric expression specifying the number of Physical Descriptor sets + Physical Descriptor 0 itself not included */ + uint8_t bNumber; + /** Numeric expression identifying the length of each Physical descriptor */ + uint8_t bLength[2]; +} __attribute__ ((packed)) HIDPhysicalDescriptor0; /* GCC */ + +/** + * HID Physical information + */ +typedef union _HIDPhysicalInfo { + /** Bits specifying physical information: 7..5 Bias, 4..0 Preference */ + uint8_t bData; + struct { + uint8_t Preference:5, /**< 0=Most preferred */ + Bias:3; /**< indicates which hand the descriptor + set is characterizing */ + } sPhysicalInfo; +} HIDPhysicalInfo; + +/** + * HID Physical Descriptor + */ +typedef struct _HIDPhysicalDescriptor { + /** Designator: indicates which part of the body affects the item */ + uint8_t bDesignator; + /** Bits specifying flags: + 7..5 Qualifier; + 4..0 Effort */ + uint8_t bFlags; +} __attribute__ ((packed)) HIDPhysicalDescriptor; /* GCC */ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + +/**@}*/ +#endif /* #ifndef _HIDDESCRIPTORS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDMSDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDMSDDriver.h new file mode 100644 index 00000000..795f1df0 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDMSDDriver.h @@ -0,0 +1,140 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * \section Purpose + * + * Definitions and methods for USB HID + MSD device implement. + * + * \section 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 + +/** \addtogroup usbd_composite_hidmsd + *@{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Consts + *---------------------------------------------------------------------------*/ + +/** \addtogroup usbd_hid_msd_desc USB HID(Kbd) + MSD Descriptors define + * @{ + */ +/** Number of interfaces of the device */ +#define HIDMSDDriverDescriptors_NUMINTERFACE 2 +/** Number of the HID (Keyboard) interface. */ +#define HIDMSDDriverDescriptors_HID_INTERFACE 0 +/** Number of the MSD interface. */ +#define HIDMSDDriverDescriptors_MSD_INTERFACE 1 +/** @}*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef HidMsdDriverConfigurationDescriptors + * \brief Configuration descriptor list for a device implementing a + * HID MSD composite driver. + */ +typedef struct _HidMsdDriverConfigurationDescriptors { + + /** Standard configuration descriptor. */ + USBConfigurationDescriptor configuration; + + /* --- HID */ + USBInterfaceDescriptor hidInterface; + HIDDescriptor1 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 */ + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/* -HIDMSD Composite device */ +extern void HIDMSDDriver_Initialize( + const USBDDriverDescriptors *pDescriptors, + MSDLun *pLuns, uint8_t numLuns); + +extern void HIDMSDDriver_ConfigurationChangedHandler(uint8_t cfgnum); + +extern void HIDMSDDriver_RequestHandler(const USBGenericRequest *request); + +extern void HIDMSDDriver_RemoteWakeUp(void); + +/**@}*/ +#endif //#ifndef HIDMSDDDRIVER_H + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDReports.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDReports.h new file mode 100644 index 00000000..2b2b551b --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDReports.h @@ -0,0 +1,299 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * + * \section Purpose + * + * Definitions used when declaring an HID report descriptors. + * + * \section Usage + * + * Use the definitions provided here when declaring a report descriptor, + * which shall be an uint8_t array. +*/ + +#ifndef _HIDREPORTS_H_ +#define _HIDREPORTS_H_ +/** \addtogroup usb_hid + *@{ + * \addtogroup usb_hid_report USB HID Report + * @{ + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_hid_item HID Items Definitions + * @{ + */ +/** Item size 0 bytes */ +#define HIDItemSize_0B 0 +/** Item size 1 bytes */ +#define HIDItemSize_1B 1 +/** Item size 2 bytes */ +#define HIDItemSize_2B 2 +/** Item size 4 bytes */ +#define HIDItemSize_4B 3 + +/** Item type: Main */ +#define HIDItemType_MAIN 0 +/** Item type: Global */ +#define HIDItemType_GLOBAL 1 +/** Item type: Local */ +#define HIDItemType_LOCAL 2 + +/** Item prefix for long items */ +#define HIDItem_LONGITEM 0xFE +/** @}*/ + +/** \addtogroup usb_hid_main HID Main Item Tags + * @{ + * This section lists the Main Item Tags defined for HID device. + * ( HID Spec. 6.2.2.4 ) + * + * - \ref HIDReport_INPUT + * - \ref HIDReport_FEATURE + * - \ref HIDReport_COLLECTION + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_hid_data HID Items for Data Fields + * @{ + * This section 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 ) + * - \ref HIDReport_CONSTANT + * - \ref HIDReport_VARIABLE + * - \ref HIDReport_RELATIVE + * - \ref HIDReport_WRAP + * - \ref HIDReport_NONLINEAR + * - \ref HIDReport_NOPREFERRED + * - \ref HIDReport_NULLSTATE + * - \ref HIDReport_VOLATILE + * - \ref 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) +/** @}*/ + +/** \addtogroup usb_hid_collection HID Collection Items + * @{ + * This section lists definitions for HID Collection Items. + * ( HID Spec. 6.2.2.6 ) + * - \ref HIDReport_COLLECTION_PHYSICAL + * - \ref HIDReport_COLLECTION_APPLICATION + * - \ref HIDReport_COLLECTION_LOGICAL + * - \ref HIDReport_COLLECTION_REPORT + * - \ref HIDReport_COLLECTION_NAMEDARRAY + * - \ref HIDReport_COLLECTION_USAGESWITCH + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_hid_global HID Global Items + * @{ + * This section lists HID Global Items. + * ( HID Spec. 6.2.2.7 ) + * - \ref HIDReport_GLOBAL_USAGEPAGE + * - \ref HIDReport_GLOBAL_LOGICALMINIMUM + * - \ref HIDReport_GLOBAL_LOGICALMAXIMUM + * - \ref HIDReport_GLOBAL_PHYSICALMINIMUM + * - \ref HIDReport_GLOBAL_PHYSICALMAXIMUM + * - \ref HIDReport_GLOBAL_UNITEXPONENT + * - \ref HIDReport_GLOBAL_UNIT + * - \ref HIDReport_GLOBAL_REPORTSIZE + * - \ref HIDReport_GLOBAL_REPORTID + * - \ref HIDReport_GLOBAL_REPORTCOUNT + * - \ref HIDReport_GLOBAL_PUSH + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_hid_local HID Local Items + * @{ + * This section lists definitions for HID Local Items. + * ( HID Spec. 6.2.2.8 ) + * - \ref HIDReport_LOCAL_USAGE + * - \ref HIDReport_LOCAL_USAGEMINIMUM + * - \ref HIDReport_LOCAL_USAGEMAXIMUM + * - \ref HIDReport_LOCAL_DESIGNATORINDEX + * - \ref HIDReport_LOCAL_DESIGNATORMINIMUM + * - \ref HIDReport_LOCAL_DESIGNATORMAXIMUM + * - \ref HIDReport_LOCAL_STRINGINDEX + * - \ref HIDReport_LOCAL_STRINGMINIMUM + * - \ref HIDReport_LOCAL_STRINGMAXIMUM + * - \ref 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 +/** @}*/ + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** HID Short Item Header, followed by bSize bytes of data */ +typedef struct _HIDShortItem { + uint8_t bSize:2, /**< data size (0, 1, 2 or 4) */ + bType:2, /**< fundamental type */ + bTag:4; /**< item type */ +} HIDShortItem; + +/** HID Long Item Header, followed by bDataSize bytes of data */ +typedef struct _HIDLongItem { + uint8_t bPrefix; /**< Prefix, 0xFE */ + uint8_t bDataSize; /**< data size */ + uint16_t bLongItemTag; /**< item type */ +} HIDLongItem; + +/** HID Report without ID (with one byte data) */ +typedef struct _HIDReportNoID { + uint8_t bData[1]; /**< First report data byte */ +} HIDReportNoID; + +/** HID Report with ID (with one byte data) */ +typedef struct _HIDReport { + uint8_t bID; /**< Report ID */ + uint8_t bData[1]; /**< First report data byte */ +} HIDReport; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + +/** @}*/ +/**@}*/ +#endif /*#ifndef _HIDREPORTS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDRequests.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDRequests.h new file mode 100644 index 00000000..5e1c5877 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDRequests.h @@ -0,0 +1,154 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * + * \section Purpose + * + * Definitions used for declaring the requests of a HID device. + * + * -# 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. + * -# Retrieve the idle rate indicated by a GET_IDLE or SET_IDLE request + * with HIDIdleRequest_GetIdleRate. + */ + +#ifndef _HIDREQUESTS_H_ +#define _HIDREQUESTS_H_ +/** \addtogroup usb_hid + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_hid_request_codes HID Request Codes + * @{ + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_report_types HID Report Types + * @{ + * This page lists the types for USB HID Reports. + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_protocol_types HID Protocol Types + * @{ + */ +/** Boot Protocol */ +#define HIDProtocol_BOOT 0 +/** Report Protocol */ +#define HIDProtocol_REPORT 1 + +/** Infinite idle rate.*/ +#define HIDIdleRequest_INFINITE 0 + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + + + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*---------------------------------------------------------------------------- + * Functions + *----------------------------------------------------------------------------*/ + +extern uint8_t HIDReportRequest_GetReportType( + const USBGenericRequest *request); + +extern uint8_t HIDReportRequest_GetReportId( + const USBGenericRequest *request); + + +static inline uint16_t HIDProtocolRequest_GetProtocol( + const USBGenericRequest *request) +{ + return USBGenericRequest_GetValue(request); +} + +extern uint8_t HIDIdleRequest_GetReportId( + const USBGenericRequest * request); + +extern uint8_t HIDIdleRequest_GetIdleRate( + const USBGenericRequest *request); + +/**@}*/ +#endif /* #define _HIDREQUESTS_H_ */ diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/HIDUsages.h b/sam3s_example/atmel_softpack_libraries/usb/include/HIDUsages.h new file mode 100644 index 00000000..bc135429 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/HIDUsages.h @@ -0,0 +1,393 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/**\file + * + * \section Purpose + * + * Definitions used for declaring the usages of a HID device. + * + */ + +#ifndef _HIDUSAGES_H_ +#define _HIDUSAGES_H_ +/** \addtogroup usb_hid + *@{ + */ + +/*---------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include + + +/*---------------------------------------------------------------------------- + * Defines + *----------------------------------------------------------------------------*/ + +/** \addtogroup usb_hid_usage_pages HID Usage Pages' IDs + * @{ + * (HUT section 3) + */ + +/** ID for the HID Generic Desktop Controls. */ +#define HIDUsage_GENERICDESKTOP 1 +/** ID for the HID Game Controls. */ +#define HIDUsage_GAME 5 +/** ID for the HID Generic Device Controls. */ +#define HIDUsage_GENERICDEVICE 6 +/** ID for the HID Keyboard/Keypad */ +#define HIDUsage_KEYBOARD 7 +/** ID for the HID LEDs. */ +#define HIDUsage_LEDS 8 +/** ID for the HID buttons. */ +#define HIDUsage_BUTTON 9 +/** ID for Bar Code Scanner page. */ +#define HIDUsage_BARCODE 0x8C +/** ID for Camera Control Page. */ +#define HIDUsage_CAMERA 0x90 +/** ID for vendor-defined controls. */ +#define HIDUsage_VENDOR 0xFF +/** @}*/ + +/** \addtogroup usb_hid_genericdesktop_page_id HID GenericDesktop Page ID + * @{ + * + * \section ID + * - HIDGenericDesktop_PAGEID + */ + +/** ID for the HID generic desktop usage page. */ +#define HIDGenericDesktop_PAGEID 0x01 +/** @}*/ + +/** \addtogroup usb_hid_genericdesktop_usages HID GenericDesktop Usages + * @{ + * + * \section 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 +/** @}*/ + + +/** \addtogroup usb_hid_keypad_page_id HID Keypad Page ID + * @{ + * This page lists HID Keypad page ID. + * + * \section ID + * - HIDKeypad_PAGEID + */ + +/** Identifier for the HID keypad usage page */ +#define HIDKeypad_PAGEID 0x07 +/** @}*/ + +/** \addtogroup usb_hid_alphabetic_keys HID Alphabetic Keys + * @{ + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_numeric_keys HID Numeric Keys + * @{ + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_special_keys HID Special Keys + * @{ + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_modified_keys HID Modified Keys + * @{ + * + * \section 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 +/** @}*/ + +/** \addtogroup usb_hid_error_codes HID Error Codes + * @{ + * + * \section Codes + * - HIDKeypad_ERRORROLLOVER + * - HIDKeypad_POSTFAIL + * - HIDKeypad_ERRORUNDEFINED + */ + +/** Indicates that too many keys have been pressed at the same time. */ +#define HIDKeypad_ERRORROLLOVER 1 +/** postfail */ +#define HIDKeypad_POSTFAIL 2 +/** Indicates an undefined error. */ +#define HIDKeypad_ERRORUNDEFINED 3 +/** @}*/ + + +/** \addtogroup usb_hid_leds_page_id HID LEDs Page ID + * @{ + * This page lists the page ID of the HID LEDs usage page. + * + * \section ID + * - HIDLeds_PAGEID + */ + +/** ID of the HID LEDs usage page. */ +#define HIDLeds_PAGEID 0x08 +/** @}*/ + +/** \addtogroup usb_hid_leds_usage HID LEDs Usages + * @{ + * This page lists the Usages of the HID LEDs. + * + * \section 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 +/** @}*/ + + +/** \addtogroup usb_hid_buttons_page_id HID BUTTONs Page ID + * @{ + */ +/** Identifier for the HID button usage page*/ +#define HIDButton_PAGEID 0x09 +/** @}*/ + + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern uint8_t HIDKeypad_IsModifierKey(uint8_t key); + +/**@}*/ +#endif /* #define _HIDUSAGES_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/MSD.h b/sam3s_example/atmel_softpack_libraries/usb/include/MSD.h new file mode 100644 index 00000000..ba8ef388 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/MSD.h @@ -0,0 +1,245 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * Mass Storage class definitions. + * + * See + * - + * USB Mass Storage Class Spec. Overview + * - + * USB Mass Storage Class Bulk-Only Transport + * + * \section 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 + +/** \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Includes + *------------------------------------------------------------------------------*/ + +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/* + * MSD Requests + * This section lists MSD-specific requests ( Actually for Bulk-only protocol ). + * + * \section 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 + +/** \addtogroup usbd_msd_subclass MSD Subclass Codes + * @{ + * This page lists the Subclass Codes for bInterfaceSubClass field. + * (Table 2.1, USB Mass Storage Class Spec. Overview) + * + * \section 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 +/** @} */ + + +/** \addtogroup usbd_msd_protocol_codes MSD Protocol Codes + * @{ + * This page lists the Transport Protocol codes for MSD. + * (Table 3.1, USB Mass Storage Class Spec. Overview) + * + * \section 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 +/** @}*/ + +/** \addtogroup usbd_msd_cbw_def MSD CBW Definitions + * @{ + * This page lists the Command Block Wrapper (CBW) definitions. + * + * \section Constants + * - MSD_CBW_SIZE + * - MSD_CBW_SIGNATURE + * + * \section 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) +/** @}*/ + +/** \addtogroup usbd_msd_csw_def MSD CSW Definitions + * @{ + * This page lists the Command Status Wrapper (CSW) definitions. + * + * \section Constants + * - MSD_CSW_SIZE + * - MSD_CSW_SIGNATURE + * + * \section 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) */ + uint32_t dCBWSignature; + /** Must be the same as dCSWTag */ + uint32_t dCBWTag; + /** Number of bytes transfer */ + uint32_t dCBWDataTransferLength; + /** Indicates the directin of the transfer: + * - 0x80=IN=device-to-host; + * - 0x00=OUT=host-to-device + */ + uint8_t bmCBWFlags; + /** bits 0->3: bCBWLUN */ + uint8_t bCBWLUN :4, + bReserved1:4; /** reserved */ + /** bits 0->4: bCBWCBLength */ + uint8_t bCBWCBLength:5, + bReserved2 :3; /** reserved */ + /** Command block */ + uint8_t pCommand[16]; + +} MSCbw; + +/*------------------------------------------------------------------------------ + * Command Status Wrapper (CSW), + * See Table 5.2, USB Mass Storage Class Bulk-Only Transport. + *------------------------------------------------------------------------------*/ +typedef struct +{ + /** 'USBS' 0x53425355 (little endian) */ + uint32_t dCSWSignature; + /** Must be the same as dCBWTag */ + uint32_t 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. + */ + uint32_t dCSWDataResidue; + /** Indicates the success or failure of the command. */ + uint8_t bCSWStatus; + +} MSCsw; + +/**@}*/ +#endif /*#ifndef MSD_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/MSDDStateMachine.h b/sam3s_example/atmel_softpack_libraries/usb/include/MSDDStateMachine.h new file mode 100644 index 00000000..2df59075 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/MSDDStateMachine.h @@ -0,0 +1,256 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * Definitions, structs, functions required by a Mass Storage device driver + * state machine.. + * + * \section Usage + * + * - For a USB device: + * -# MSDD_StateMachine is invoked to run the MSD state machine. + * + *-----------------------------------------------------------------------------*/ + +#ifndef MSDDSTATEMACHINE_H +#define MSDDSTATEMACHINE_H + +/** \addtogroup usbd_msd + *@{ + */ + +/*----------------------------------------------------------------------------- + * Headers + *-----------------------------------------------------------------------------*/ + +#include "MSD.h" +#include "MSDLun.h" +#include +#include + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ + +/** \addtogroup usbd_msd_driver_possible_states MSD Driver Possible 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) +/** @}*/ + +/** \addtogroup usbd_msd_driver_result_codes MSD Driver Result Codes + * @{ + * This page lists result codes for MSD functions. + * + * \section 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 +/** @}*/ + +/** \addtogroup usbd_msd_driver_action_cases MSD Driver Action Cases + * @{ + * This page lists actions to perform during the post-processing phase of a + * command. + * + * \section 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) +/** @}*/ + +/*------------------------------------------------------------------------------ */ + +/** \addtogroup usbd_msd_driver_xfr_directions MSD Driver Xfr Directions + * @{ + * This page lists possible direction values for a data transfer + * - MSDD_DEVICE_TO_HOST + * - MSDD_HOST_TO_DEVICE + * - MSDD_NO_TRANSFER + */ +/** Data transfer from device to host (READ) */ +#define MSDD_DEVICE_TO_HOST 0 +/** Data transfer from host to device (WRITE) */ +#define MSDD_HOST_TO_DEVICE 1 +/** No data transfer */ +#define MSDD_NO_TRANSFER 2 +/** @}*/ + +/*----------------------------------------------------------------------------- + * Types + *-----------------------------------------------------------------------------*/ + +/** + * \typedef MSDTransfer + * \brief Structure for holding the result of a USB transfer + * \see MSDDriver_Callback + */ +typedef struct _MSDTransfer { + + uint32_t transferred; /** Number of bytes transferred */ + uint32_t remaining; /** Number of bytes not transferred */ + volatile uint16_t semaphore; /** Semaphore to indicate transfer completion */ + uint16_t status; /** Operation result code */ +} MSDTransfer; + +/** + * \typedef MSDCommandState + * \brief Status of an executing command + * \see MSDCbw + * \see MSDCsw + * \see MSDTransfer + *------------------------------------------------------------------------------*/ +typedef struct _MSDCommandState { + + MSDTransfer transfer; /**< Current transfer status (USB) */ + MSDTransfer disktransfer;/**< Current transfer status (Disk) */ + uint32_t length; /**< Remaining length of command */ + MSCbw cbw; /**< Received CBW (31 bytes) */ + uint8_t state; /**< Current command state */ + MSCsw csw; /**< CSW to send (13 bytes) */ + uint8_t postprocess; /**< Actions to perform when command is complete */ + uint8_t pipeIN; /**< Pipe ID for input */ + uint8_t pipeOUT; /**< Pipe ID for output */ +} MSDCommandState; + +/** + * \typedef MSDDriver + * \brief MSD driver state variables + * \see MSDCommandState + * \see MSDLun + */ +typedef struct _MSDDriver { + + /** USB Driver for the %device. */ + USBDDriver *pUsbd; + /** LUN list for the %device. */ + MSDLun *luns; + /** State of the currently executing command */ + MSDCommandState commandState; + /** Associated interface number */ + uint8_t interfaceNb; + /** Maximum LUN index */ + uint8_t maxLun; + /** Current state of the driver */ + uint8_t state; + /** Indicates if the driver is waiting for a reset recovery */ + uint8_t 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, + uint8_t status, + uint32_t transferred, + uint32_t remaining) +{ + TRACE_DEBUG( "Cbk " ) ; + transfer->semaphore++; + transfer->status = status; + transfer->transferred = transferred; + transfer->remaining = remaining; +} + +/*----------------------------------------------------------------------------- + * Exported functions + *-----------------------------------------------------------------------------*/ + +extern void MSDD_StateMachine(MSDDriver * pMsdDriver); + +/**@}*/ + +#endif /* #define MSDDSTATEMACHINE_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/MSDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/MSDDriver.h new file mode 100644 index 00000000..37ea63a9 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/MSDDriver.h @@ -0,0 +1,141 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * Mass storage %device driver implementation. + * + * \section Usage + * + * -# Enable and setup USB related pins (see pio & board.h). + * -# Configure the memory interfaces used for Mass Storage LUNs + * (see memories, MSDLun.h). + * -# Instance the USB device configure descriptor as + * MSDConfigurationDescriptors or MSDConfigurationDescriptorsOTG defined. + * Interface number should be 0. + * -# 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 + +/** \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * \typedef MSDConfigurationDescriptors + * \brief List of configuration descriptors used by a Mass Storage device driver. + */ +typedef struct _MSDConfigurationDescriptors { + + /** Standard configuration descriptor. */ + USBConfigurationDescriptor configuration; + /** Mass storage interface descriptor. */ + USBInterfaceDescriptor interface; + /** Bulk-out endpoint descriptor. */ + USBEndpointDescriptor bulkOut; + /** Bulk-in endpoint descriptor. */ + USBEndpointDescriptor bulkIn; + +} __attribute__ ((packed)) MSDConfigurationDescriptors; + +/** + * \typedef MSDConfigurationDescriptorsOTG + * \brief List of configuration descriptors used by a + * Mass Storage device driver, with OTG support. + */ +typedef struct _MSDConfigurationDescriptorsOTG { + + /** Standard configuration descriptor. */ + USBConfigurationDescriptor configuration; + /* OTG descriptor */ + USBOtgDescriptor otgDescriptor; + /** Mass storage interface descriptor. */ + USBInterfaceDescriptor interface; + /** Bulk-out endpoint descriptor. */ + USBEndpointDescriptor bulkOut; + /** Bulk-in endpoint descriptor. */ + USBEndpointDescriptor bulkIn; + +} __attribute__ ((packed)) MSDConfigurationDescriptorsOTG; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*------------------------------------------------------------------------------ + * Global functions + *------------------------------------------------------------------------------*/ + +extern void MSDDriver_Initialize( + const USBDDriverDescriptors *pDescriptors, + MSDLun *luns, uint8_t numLuns); + +extern void MSDDriver_RequestHandler( + const USBGenericRequest *request); + +extern void MSDDriver_ConfigurationChangeHandler( + uint8_t cfgnum); + +/** + * State machine for the MSD driver + * \param pMsdDriver Pointer to MSDDriver instance. + */ +static inline void MSDDriver_StateMachine(void) { + MSDFunction_StateMachine(); +} + +/**@}*/ + +#endif /* #ifndef MSDDRIVER_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/MSDFunction.h b/sam3s_example/atmel_softpack_libraries/usb/include/MSDFunction.h new file mode 100644 index 00000000..0cffc59b --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/MSDFunction.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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Mass storage function driver definitions. + */ + +#ifndef MSDFUNCTION_H +#define MSDFUNCTION_H + +/** \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + * Global functions + *------------------------------------------------------------------------------*/ + +extern void MSDFunction_Initialize( + USBDDriver * pUsbd, uint8_t bInterfaceNb, + MSDLun * pLuns, uint8_t numLuns); + +extern uint32_t MSDFunction_RequestHandler( + const USBGenericRequest *request); + +extern void MSDFunction_Configure( + USBGenericDescriptor * pDescriptors, uint16_t wLength); + +extern void MSDFunction_StateMachine(void); + +/**@}*/ + +#endif /* #ifndef MSDDRIVER_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/MSDIOFifo.h b/sam3s_example/atmel_softpack_libraries/usb/include/MSDIOFifo.h new file mode 100644 index 00000000..4ed70fc5 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/MSDIOFifo.h @@ -0,0 +1,145 @@ +/* ---------------------------------------------------------------------------- + * 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 + +/** \file + * \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * 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) */ +#if !defined(MSD_OP_BUFFER) +#define MSDIO_READ10_CHUNK_SIZE (4*512) +#define MSDIO_WRITE10_CHUNK_SIZE (4*512) +#endif + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** \brief 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/sam3s_example/atmel_softpack_libraries/usb/include/MSDLun.h b/sam3s_example/atmel_softpack_libraries/usb/include/MSDLun.h new file mode 100644 index 00000000..57114000 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/MSDLun.h @@ -0,0 +1,176 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * Logical Unit Number (LUN) used by the Mass Storage driver and the SCSI + * protocol. Represents a logical hard-drive. + * + * \section 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 + +/** \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include +#include "memories.h" + +#include "SBC.h" +#include "MSDIOFifo.h" +#include "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 + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** Mass storage device data flow monitor function type + * \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 + */ +typedef void(*MSDLunDataMonitorFunction)(uint8_t flowDirection, + uint32_t dataLength, + uint32_t fifoNullCount, + uint32_t fifoFullCount); + +/*------------------------------------------------------------------------------ + * Structures + *------------------------------------------------------------------------------*/ + +/** \brief 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)(uint8_t flowDirection, + uint32_t dataLength, + uint32_t fifoNullCount, + uint32_t fifoFullCount); + /** The start position of the media (blocks) allocated to the LUN. */ + uint32_t baseAddress; + /** The size of the media (blocks) allocated to the LUN. */ + uint32_t size; + /** Sector size of the media in number of media blocks */ + uint16_t blockSize; + /** The LUN can be readonly even the media is writable */ + uint8_t protected; + /** The LUN status (Ejected/Changed/) */ + uint8_t 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, + uint8_t *ioBuffer, + uint32_t ioBufferSize, + uint32_t baseAddress, + uint32_t size, + uint16_t blockSize, + uint8_t protected, + void (*dataMonitor)(uint8_t flowDirection, + uint32_t dataLength, + uint32_t fifoNullCount, + uint32_t fifoFullCount)); + +extern uint32_t LUN_Eject(MSDLun *lun); + +extern uint32_t LUN_Write(MSDLun *lun, + uint32_t blockAddress, + void *data, + uint32_t length, + TransferCallback callback, + void *argument); + +extern uint32_t LUN_Read(MSDLun *lun, + uint32_t blockAddress, + void *data, + uint32_t length, + TransferCallback callback, + void *argument); + +/**@}*/ + +#endif /*#ifndef MSDLUN_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/MSDescriptors.h b/sam3s_example/atmel_softpack_libraries/usb/include/MSDescriptors.h new file mode 100644 index 00000000..c5bcc290 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/MSDescriptors.h @@ -0,0 +1,109 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * + * \section ms_dev_desc Device Descriptors + * + * Declaration of constants for using Device Descriptors with a Mass Storage + * driver. + * + * - For a USB device: + * -# When declaring a USBDeviceDescriptor instance, use the Mass Storage + * codes defined in this file (see "MS device codes"). + * + * \section ms_if_desc Interface Descriptors + * + * Definition of several constants used when manipulating Mass Storage interface + * descriptors. + * + * - 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 _MSDESCRIPTORS_H_ +#define _MSDESCRIPTORS_H_ +/**\addtogroup usb_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_ms_device_codes MS device codes + * @{ + * This page lists the class, subclass & protocol codes used by a device with + * a Mass Storage driver. + * + * \section 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 +/** @}*/ + + +/** \addtogroup usb_ms_interface_code MS interface codes + * @{ + * This page lists the available class, subclass & protocol codes for a Mass + * Storage interface. + * + * \section 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 _MSDESCRIPTORS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/SBC.h b/sam3s_example/atmel_softpack_libraries/usb/include/SBC.h new file mode 100644 index 00000000..163c9a84 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/SBC.h @@ -0,0 +1,678 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * SCSI definitions. + * + * \section Usage + * + * -# After command block received, Access and decode the SCSI command block + * with SBCCommand structure. + */ + +#ifndef SBC_H +#define SBC_H + +/** \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_sbc_operation_codes 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 + * + * \section Codes + * - SBC_INQUIRY + * - SBC_READ_10 + * - SBC_READ_CAPACITY_10 + * - SBC_REQUEST_SENSE + * - SBC_TEST_UNIT_READY + * - SBC_WRITE_10 + * + * \section 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 +/** @}*/ + +/** \addtogroup usbd_sbc_periph_quali 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 + * + * \section 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 +/** @}*/ + +/** \addtogroup usbd_sbc_periph_types 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 + * + * \section 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 +/*------------------------------------------------------------------------------ */ + +/** \addtogroup usbd_sbc_secse_codes 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 + * + * \section 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 +/** @}*/ + +/** \addtogroup usbd_sbc_sense_keys SBC Sense Keys + * @{ + * This page lists sense key values returned in the REQUEST SENSE data + * \see spc4r06.pdf - Section 4.5.6 - Table 27 + * + * \section 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 +/** @}*/ + +/** \addtogroup usbd_sbc_sense_additionals SBC Sense Additionals + * @{ + * This page lists additional sense code values returned in REQUEST SENSE data + * \see spc4r06.pdf - Section 4.5.6 - Table 28 + * + * \section 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 +/*------------------------------------------------------------------------------ */ + +/** \addtogroup usbd_msd_endian_macros MSD Endian Macros + * @{ + * This page lists the macros for endianness conversion. + * + * \section 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 */ + +/** + * \typedef SBCInquiry + * \brief Structure for the INQUIRY command + * \see spc4r06.pdf - Section 6.4.1 - Table 81 + */ +typedef struct _SBCInquiry { + + 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 */ + +/** + * \typedef SBCInquiryData + * \brief Standard INQUIRY data format returned by the device + * \see spc4r06.pdf - Section 6.4.2 - Table 82 + */ +typedef struct _SBCInquiryData { + + 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 */ + +/** + * \typedef SBCRead10 + * \brief Data structure for the READ (10) command + * \see sbc3r07.pdf - Section 5.7 - Table 34 + */ +typedef struct _SBCRead10 { + + 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 */ + +/** + * \typedef SBCReadCapacity10 + * \brief Structure for the READ CAPACITY (10) command + * \see sbc3r07.pdf - Section 5.11.1 - Table 40 + */ +typedef struct _SBCReadCapacity10 { + + 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 SBCTestUnitReady + * Data structure for the TEST UNIT READY command + * \see spc4r06.pdf - Section 6.34 - Table 192 + */ +typedef struct _SBCTestUnitReady { + + unsigned char bOperationCode; /*!< 0x00 : SBC_TEST_UNIT_READY */ + unsigned char pReserved1[4]; /*!< Reserved bits */ + unsigned char bControl; /*!< 0x00 */ + +} __attribute__ ((packed)) SBCTestUnitReady; /* GCC */ + +/** + * \typedef SBCWrite10 + * \brief Structure for the WRITE (10) command + * \see sbc3r07.pdf - Section 5.26 - Table 70 + */ +typedef struct _SBCWrite10 { + + 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; + +/** + * \typedef SBCMediumRemoval + * \brief Structure for the PREVENT/ALLOW MEDIUM REMOVAL command + * \see sbc3r07.pdf - Section 5.5 - Table 30 + */ +typedef struct _SBCMediumRemoval { + + 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 */ + +/** + * \typedef SBCModeSense6 + * \brief Structure for the MODE SENSE (6) command + * \see spc4r06 - Section 6.9.1 - Table 98 + */ +typedef struct _SBCModeSense6 { + + 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 */ + +/** + * \typedef SBCModeParameterHeader6 + * \brief Header for the data returned after a MODE SENSE (6) command + * \see spc4r06.pdf - Section 7.4.3 - Table 268 + */ +typedef struct _SBCModeParameterHeader6 { + + 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 */ + +/** + * \typedef SBCInformationalExceptionsControl + * \brief Informational exceptions control mode page + * \see spc4r06.pdf - Section 7.4.11 - Table 285 + */ +typedef struct _SBCInformationalExceptionsControl { + + 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 */ + +/** + * \typedef SBCReadWriteErrorRecovery + * \brief Read/write error recovery mode page + * \see sbc3r07.pdf - Section 6.3.5 - Table 122 + */ +typedef struct _SBCReadWriteErrorRecovery { + + 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 */ + +/** + * \typedef SBCCommand + * \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 _SBCCommand { + + 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/sam3s_example/atmel_softpack_libraries/usb/include/SBCMethods.h b/sam3s_example/atmel_softpack_libraries/usb/include/SBCMethods.h new file mode 100644 index 00000000..3e78b4e3 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/SBCMethods.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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * SCSI commands implementation. + * + * section 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 + +/** \addtogroup usbd_msd + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "SBC.h" +#include "MSDLun.h" +#include "MSDDStateMachine.h" + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/** \addtogroup usbd_sbc_command_state SBC Command States + * @{ + * This page lists the possible states of a SBC command. + * + * \section 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/sam3s_example/atmel_softpack_libraries/usb/include/USBD.h b/sam3s_example/atmel_softpack_libraries/usb/include/USBD.h new file mode 100644 index 00000000..15a68595 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * Collection of methods for using the USB device controller on AT91 + * microcontrollers. + * + * \section Usage + * + * Please refer to the corresponding application note. + * - \ref usbd_framework AT91 USB device framework + * - \ref usbd_api USBD API + * + */ + +#ifndef USBD_H +#define USBD_H + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + + +#include "USBDescriptors.h" +#include "USBRequests.h" + +#include "USBLib_Types.h" + +#include + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ + +/* Define attribute */ +#if defined ( __CC_ARM ) /* Keil µVision 4 */ + #define WEAK __attribute__ ((weak)) +#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */ + #define WEAK __weak +#elif defined ( __GNUC__ ) /* GCC CS3 2009q3-68 */ + #define WEAK __attribute__ ((weak)) +#endif + +/* Define NO_INIT attribute */ +#if defined ( __CC_ARM ) + #define NO_INIT +#elif defined ( __ICCARM__ ) + #define NO_INIT __no_init +#elif defined ( __GNUC__ ) + #define NO_INIT +#endif + + +/** \addtogroup usbd_interface + *@{*/ + +/** + * \addtogroup usbd_rc USB device API return codes + * @{ + * This section lists the return codes for the USB device driver API + * - \ref USBD_STATUS_SUCCESS + * - \ref USBD_STATUS_LOCKED + * - \ref USBD_STATUS_ABORTED + * - \ref USBD_STATUS_RESET + */ + +/** Indicates the operation was successful. */ +#define USBD_STATUS_SUCCESS USBRC_SUCCESS +/** Endpoint/device is already busy. */ +#define USBD_STATUS_LOCKED USBRC_BUSY +/** Operation has been aborted (error or stall). */ +#define USBD_STATUS_ABORTED USBRC_ABORTED +/** Operation has been canceled (by user). */ +#define USBD_STATUS_CANCELED USBRC_CANCELED +/** Operation has been aborted because the device init/reset/un-configure. */ +#define USBD_STATUS_RESET USBRC_RESET +/** Part ot operation successfully done. */ +#define USBD_STATUS_PARTIAL_DONE USBRC_PARTIAL_DONE +/** Operation failed because parameter error */ +#define USBD_STATUS_INVALID_PARAMETER USBRC_PARAM_ERR +/** Operation failed because in unexpected state */ +#define USBD_STATUS_WRONG_STATE USBRC_STATE_ERR +/** Operation failed because SW not supported */ +#define USBD_STATUS_SW_NOT_SUPPORTED USBRC_SW_NOT_SUPPORTED +/** Operation failed because HW not supported */ +#define USBD_STATUS_HW_NOT_SUPPORTED USBRC_HW_NOT_SUPPORTED +/** @}*/ + +/** \addtogroup usbd_states USB device states + * @{ + * This section lists the device states of the USB device driver. + * - \ref USBD_STATE_SUSPENDED + * - \ref USBD_STATE_ATTACHED + * - \ref USBD_STATE_POWERED + * - \ref USBD_STATE_DEFAULT + * - \ref USBD_STATE_ADDRESS + * - \ref 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 +/** @}*/ + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +/** + * \brief 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 */ + uint8_t * pBuffer; + /** Size of the frame (up to 64K-1) */ + uint16_t size; + /** Bytes transferred */ + uint16_t transferred; + /** Bytes in FIFO */ + uint16_t buffered; + /** Bytes remaining */ + uint16_t remaining; +} USBDTransferBuffer; + +#ifdef __ICCARM__ /* IAR*/ +#define __attribute__(...) /* IAR*/ +#endif /* IAR*/ + +/** + * \brief 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 */ + uint32_t ctrlSettings:8, /** Control settings */ + reserved:8, /** Not used */ + bufferLength:16; /** Length of buffer */ + /** Loaded to DMA register, OK to modify */ + uint32_t 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, + uint8_t status, + uint32_t transferred, + uint32_t 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. + */ +typedef void (*MblTransferCallback)(void *pArg, + uint8_t status); + +/**@}*/ + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +//extern void USBD_IrqHandler(void); + +extern void USBD_Init(void); + +extern void USBD_ConfigureSpeed(uint8_t forceFS); + +extern void USBD_Connect(void); + +extern void USBD_Disconnect(void); + +extern uint8_t USBD_Write( + uint8_t bEndpoint, + const void *pData, + uint32_t size, + TransferCallback callback, + void *pArg); + +extern uint8_t USBD_Read( + uint8_t bEndpoint, + void *pData, + uint32_t dLength, + TransferCallback fCallback, + void *pArg); + +extern uint8_t USBD_Stall(uint8_t bEndpoint); + +extern void USBD_Halt(uint8_t bEndpoint); + +extern void USBD_Unhalt(uint8_t bEndpoint); + +extern void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor); + +extern uint8_t USBD_IsHalted(uint8_t bEndpoint); + +extern void USBD_RemoteWakeUp(void); + +extern void USBD_SetAddress(uint8_t address); + +extern void USBD_SetConfiguration(uint8_t cfgnum); + +extern uint8_t USBD_GetState(void); + +extern uint8_t USBD_IsHighSpeed(void); + +extern void USBD_Test(uint8_t bIndex); + +extern void USBD_SuspendHandler(void); +extern void USBD_ResumeHandler(void); +extern void USBD_ResetHandler(void); +extern void USBD_RequestHandler(uint8_t bEndpoint, + const USBGenericRequest * pRequest); + +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 USBD_H*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/USBDDriver.h b/sam3s_example/atmel_softpack_libraries/usb/include/USBDDriver.h new file mode 100644 index 00000000..79ccb2d4 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/USBDDriver.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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * USB Device Driver class definition. + * + * \section 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 + +/** \addtogroup usbd_interface + *@{ + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 by working group + * ISO/IEC JTC1/SC22/WG14. + */ +#include +#include +#include + +#include +#include +#include + +/*------------------------------------------------------------------------------ + * Types + *------------------------------------------------------------------------------*/ + +/** + * \typedef USBDDriverDescriptors + * \brief 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 _USBDDriverDescriptors { + + /** 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 uint8_t **pStrings; + /** Number of string descriptors in list */ + uint8_t numStrings; + +} USBDDriverDescriptors; + +/** + * \typedef USBDDriver + * \brief USB device driver structure, holding a list of descriptors identifying + * the device as well as the driver current state. + */ +typedef struct _USBDDriver { + + /** List of descriptors used by the device. */ + const USBDDriverDescriptors *pDescriptors; + /** Current setting for each interface. */ + uint8_t *pInterfaces; + /** Current configuration number (0 -> device is not configured). */ + uint8_t cfgnum; + /** Indicates if remote wake up has been enabled by the host. */ + uint8_t isRemoteWakeUpEnabled; + /** Features supported by OTG */ + uint8_t otg_features_supported; +} USBDDriver; + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +extern USBDDriver *USBD_GetDriver(void); +extern void USBDDriver_Initialize( + USBDDriver *pDriver, + const USBDDriverDescriptors *pDescriptors, + uint8_t *pInterfaces); +extern USBConfigurationDescriptor* USBDDriver_GetCfgDescriptors( + USBDDriver * pDriver, + uint8_t cfgNum); +extern void USBDDriver_RequestHandler( + USBDDriver *pDriver, + const USBGenericRequest *pRequest); +extern uint8_t USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver); +extern uint8_t USBDDriver_returnOTGFeatures(const USBDDriver *pDriver); +extern void USBDDriver_clearOTGFeatures(USBDDriver *pDriver); + +extern void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum); +extern void USBDDriverCallbacks_InterfaceSettingChanged(uint8_t interface, uint8_t setting); + +/**@}*/ + +#endif /*#ifndef USBDDRIVER_H*/ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/USBD_HAL.h b/sam3s_example/atmel_softpack_libraries/usb/include/USBD_HAL.h new file mode 100644 index 00000000..76f6c403 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/USBD_HAL.h @@ -0,0 +1,107 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 USBD_HAL_H +#define USBD_HAL_H + +/** + * \file + * + * This file defines functions for USB Device Hardware Access Level. + */ + +/** \addtogroup usbd_hal + *@{*/ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +/* Introduced in C99 by working group ISO/IEC JTC1/SC22/WG14. */ +#include +#include +#include + +#include "USBD.h" +#include +#include + +/*---------------------------------------------------------------------------- + * Consts + *----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Macros + *----------------------------------------------------------------------------*/ + +/** Get bitmap for an endpoint */ +#define bmEP(bEP) (1 << (bEP)) + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Exported functoins + *----------------------------------------------------------------------------*/ + +extern void USBD_HAL_Init(void); +extern void USBD_HAL_Connect(void); +extern void USBD_HAL_Disconnect(void); + +extern void USBD_HAL_RemoteWakeUp(void); +extern void USBD_HAL_SetConfiguration(uint8_t cfgnum); +extern void USBD_HAL_SetAddress(uint8_t address); +extern uint8_t USBD_HAL_IsHighSpeed(void); + +extern void USBD_HAL_Suspend(void); +extern void USBD_HAL_Activate(void); + +extern void USBD_HAL_ResetEPs(uint32_t bmEPs,uint8_t bStatus, uint8_t bKeepCfg); +extern void USBD_HAL_CancelIo(uint32_t bmEPs); +extern uint8_t USBD_HAL_ConfigureEP(const USBEndpointDescriptor * pDescriptor); + +extern uint8_t USBD_HAL_SetTransferCallback(uint8_t bEP, + TransferCallback fCallback, + void * pCbData); +extern uint8_t USBD_HAL_SetupMblTransfer(uint8_t bEndpoint, + USBDTransferBuffer * pMbList, + uint16_t mblSize, + uint16_t startOffset); +extern uint8_t USBD_HAL_Write(uint8_t bEndpoint, + const void * pData, + uint32_t dLength); +extern uint8_t USBD_HAL_Read(uint8_t bEndpoint, + void * pData, + uint32_t dLength); +extern uint8_t USBD_HAL_Stall(uint8_t bEP); +extern uint8_t USBD_HAL_Halt(uint8_t bEndpoint,uint8_t ctl); +/**@}*/ + +#endif // #define USBD_HAL_H diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/USBDescriptors.h b/sam3s_example/atmel_softpack_libraries/usb/include/USBDescriptors.h new file mode 100644 index 00000000..84b5ef69 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/USBDescriptors.h @@ -0,0 +1,552 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * Definitions and methods for USB descriptor structures described by the + * USB specification. + * + * \section Usage + * + */ + +#ifndef _USBDESCRIPTORS_H_ +#define _USBDESCRIPTORS_H_ +/** \addtogroup usb_general + * @{ + * \addtogroup usb_descriptor USB Descriptors + * @{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 by working group + * ISO/IEC JTC1/SC22/WG14. + */ +#include + +/*--------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/*--------- Generic Descriptors --------*/ + +/** \addtogroup usb_desc_type USB Descriptor types + * @{ + * This section lists the codes of the usb descriptor types + * - \ref USBGenericDescriptor_DEVICE + * - \ref USBGenericDescriptor_CONFIGURATION + * - \ref USBGenericDescriptor_STRING + * - \ref USBGenericDescriptor_INTERFACE + * - \ref USBGenericDescriptor_ENDPOINT + * - \ref USBGenericDescriptor_DEVICEQUALIFIER + * - \ref USBGenericDescriptor_OTHERSPEEDCONFIGURATION + * - \ref USBGenericDescriptor_INTERFACEPOWER + * - \ref USBGenericDescriptor_OTG + * - \ref USBGenericDescriptor_DEBUG + * - \ref 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 +/** @}*/ + + +/*--------- Device Descriptors --------*/ + +/** \addtogroup usb_release_number USB release numbers + * @{ + * This section lists the codes of USB release numbers. + * - \ref USBDeviceDescriptor_USB2_00 + */ + +/** The device supports USB 2.00. */ +#define USBDeviceDescriptor_USB2_00 0x0200 +/** @}*/ + + +/*--------- Configuration Descriptors --------*/ + +/** \addtogroup usb_attributes USB Device Attributes + * @{ + * This section lists the codes of the usb attributes. + * - \ref USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP + * - \ref USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP + * - \ref USBConfigurationDescriptor_BUSPOWERED_RWAKEUP + * - \ref USBConfigurationDescriptor_SELFPOWERED_RWAKEUP + * - \ref 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) +/** @}*/ + + +/*--------- Endpoint Descriptors --------*/ + +/** \addtogroup usb_ep_define USB Endpoint definitions + * @{ + * This section lists definitions and macro for endpoint descriptors. + * - \ref usb_ep_dir USB Endpoint directions + * - \ref USBEndpointDescriptor_OUT + * - \ref USBEndpointDescriptor_IN + * + * - \ref usb_ep_type USB Endpoint types + * - \ref USBEndpointDescriptor_CONTROL + * - \ref USBEndpointDescriptor_ISOCHRONOUS + * - \ref USBEndpointDescriptor_BULK + * - \ref USBEndpointDescriptor_INTERRUPT + * + * - \ref usb_ep_size USB Endpoint maximun sizes + * - \ref USBEndpointDescriptor_MAXCTRLSIZE_FS + * - \ref USBEndpointDescriptor_MAXCTRLSIZE_HS + * - \ref USBEndpointDescriptor_MAXBULKSIZE_FS + * - \ref USBEndpointDescriptor_MAXBULKSIZE_HS + * - \ref USBEndpointDescriptor_MAXINTERRUPTSIZE_FS + * - \ref USBEndpointDescriptor_MAXINTERRUPTSIZE_HS + * - \ref USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS + * - \ref USBEndpointDescriptor_MAXISOCHRONOUSSIZE_HS + * + * - \ref usb_ep_addr USB Endpoint address define + * - \ref USBEndpointDescriptor_ADDRESS + */ + +/** \addtogroup usb_ep_dir USB Endpoint directions + * @{ + * This section lists definitions of USB endpoint 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 +/** @}*/ + +/** \addtogroup usb_ep_type USB Endpoint types + * @{ + * This section lists definitions of USB endpoint types. + * - \ref USBEndpointDescriptor_CONTROL + * - \ref USBEndpointDescriptor_ISOCHRONOUS + * - \ref USBEndpointDescriptor_BULK + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_ep_size USB Endpoint maximun sizes + * @{ + * This section lists definitions of USB endpoint maximun sizes. + * - \ref USBEndpointDescriptor_MAXCTRLSIZE_FS + * - \ref USBEndpointDescriptor_MAXCTRLSIZE_HS + * - \ref USBEndpointDescriptor_MAXBULKSIZE_FS + * - \ref USBEndpointDescriptor_MAXBULKSIZE_HS + * - \ref USBEndpointDescriptor_MAXINTERRUPTSIZE_FS + * - \ref USBEndpointDescriptor_MAXINTERRUPTSIZE_HS + * - \ref USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_ep_addr USB Endpoint address define + * @{ + * This section lists macro for USB endpoint address definition. + * - \ref 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)) +/** @}*/ +/** @}*/ + + +/*--------- Generic Descriptors --------*/ + +/** \addtogroup usb_string_descriptor USB String Descriptor Definitions + * @{ + * This section lists the codes and macros for USB string descriptor definition. + * + * \par Language IDs + * - USBStringDescriptor_ENGLISH_US + * + * \par String Descriptor Length + * - USBStringDescriptor_LENGTH + * + * \par 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 +/** @}*/ + + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/* + * Function types + */ + +typedef uint32_t (*USBDescriptorParseFunction)(void *descriptor, void *parseArg); + + +/* + * Descriptor structs types + */ +#pragma pack(1) + +#if defined ( __CC_ARM ) /* Keil µVision 4 */ +#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */ +#define __attribute__(...) +#elif defined ( __GNUC__ ) /* GCC CS3 2009q3-68 */ + +#endif + + + +/** + \typedef USBGenericDescriptor + \brief Holds the few fields shared by all USB descriptors. + */ +typedef struct _USBGenericDescriptor { + + /** Length of the descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type. */ + uint8_t bDescriptorType; + +} __attribute__ ((packed)) USBGenericDescriptor; /* GCC */ + +/** + * \typedef USBDeviceDescriptor + * \brief USB standard device descriptor structure. + */ +typedef struct _USBDeviceDescriptor { + + /** Size of this descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (USBGenericDescriptor_DEVICE). */ + uint8_t bDescriptorType; + /** USB specification release number in BCD format. */ + uint16_t bcdUSB; + /** Device class code. */ + uint8_t bDeviceClass; + /** Device subclass code. */ + uint8_t bDeviceSubClass; + /** Device protocol code. */ + uint8_t bDeviceProtocol; + /** Maximum packet size of endpoint 0 (in bytes). */ + uint8_t bMaxPacketSize0; + /** Vendor ID. */ + uint16_t idVendor; + /** Product ID. */ + uint16_t idProduct; + /** Device release number in BCD format. */ + uint16_t bcdDevice; + /** Index of the manufacturer string descriptor. */ + uint8_t iManufacturer; + /** Index of the product string descriptor. */ + uint8_t iProduct; + /** Index of the serial number string descriptor. */ + uint8_t iSerialNumber; + /** Number of possible configurations for the device. */ + uint8_t bNumConfigurations; + +} __attribute__ ((packed)) USBDeviceDescriptor; /* GCC */ + +/** + * \typedef USBOtgDescriptor + * \brief USB On-The-Go descriptor struct. + */ +typedef struct _USBOtgDescriptor { + + /** Size of this descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (USBGenericDescriptor_OTG). */ + uint8_t bDescriptorType; + /** Attribute Fields D7?: Reserved D1: HNP support D0: SRP support */ + uint8_t bmAttributes; + +} __attribute__ ((packed)) USBOtgDescriptor; /* GCC */ + +/** + * \typedef USBDeviceQualifierDescriptor + * \brief 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 _USBDeviceQualifierDescriptor { + + /** Size of the descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (USBDESC_DEVICE_QUALIFIER or "USB device types"). */ + uint8_t bDescriptorType; + /** USB specification release number (in BCD format). */ + uint16_t bcdUSB; + /** Device class code. */ + uint8_t bDeviceClass; + /** Device subclass code. */ + uint8_t bDeviceSubClass; + /** Device protocol code. */ + uint8_t bDeviceProtocol; + /** Maximum packet size of endpoint 0. */ + uint8_t bMaxPacketSize0; + /** Number of possible configurations for the device. */ + uint8_t bNumConfigurations; + /** Reserved. */ + uint8_t bReserved; + +} __attribute__ ((packed)) USBDeviceQualifierDescriptor; /* GCC */ + +/** + * \typedef USBConfigurationDescriptor + * \brief USB standard configuration descriptor structure. + */ +typedef struct _USBConfigurationDescriptor { + + /** Size of the descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type + (USBDESC_CONFIGURATION of \ref usb_desc_type USB Descriptor types). */ + uint8_t bDescriptorType; + /** Length of all descriptors returned along with this configuration + descriptor. */ + uint16_t wTotalLength; + /** Number of interfaces in this configuration. */ + uint8_t bNumInterfaces; + /** Value for selecting this configuration. */ + uint8_t bConfigurationValue; + /** Index of the configuration string descriptor. */ + uint8_t iConfiguration; + /** Configuration characteristics. */ + uint8_t bmAttributes; + /** Maximum power consumption of the device when in this configuration. */ + uint8_t bMaxPower; + +} __attribute__ ((packed)) USBConfigurationDescriptor; /* GCC*/ + +/** + * \typedef USBInterfaceAssociationDescriptor + * \brief + */ +typedef struct _USBInterfaceAssociationDescriptor { + + 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*/ + +/** + * \typedef USBInterfaceDescriptor + * \brief USB standard interface descriptor structure. + */ +typedef struct _USBInterfaceDescriptor { + + /** Size of the descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (USBGenericDescriptor_INTERFACE). */ + uint8_t bDescriptorType; + /** Number of the interface in its configuration. */ + uint8_t bInterfaceNumber; + /** Value to select this alternate interface setting. */ + uint8_t bAlternateSetting; + /** Number of endpoints used by the inteface (excluding endpoint 0). */ + uint8_t bNumEndpoints; + /** Interface class code. */ + uint8_t bInterfaceClass; + /** Interface subclass code. */ + uint8_t bInterfaceSubClass; + /** Interface protocol code. */ + uint8_t bInterfaceProtocol; + /** Index of the interface string descriptor. */ + uint8_t iInterface; + +} __attribute__ ((packed)) USBInterfaceDescriptor; /* GCC */ + +/** + * \typedef USBEndpointDescriptor + * \brief USB standard endpoint descriptor structure. + */ +typedef struct _USBEndpointDescriptor { + + /** Size of the descriptor in bytes. */ + uint8_t bLength; + /** Descriptor type (\ref USBGenericDescriptor_ENDPOINT). */ + uint8_t bDescriptorType; + /** Address and direction of the endpoint. */ + uint8_t bEndpointAddress; + /** Endpoint type and additional characteristics + (for isochronous endpoints). */ + uint8_t bmAttributes; + /** Maximum packet size (in bytes) of the endpoint. */ + uint16_t wMaxPacketSize; + /** Polling rate of the endpoint. */ + uint8_t bInterval; + +} __attribute__ ((packed)) USBEndpointDescriptor; /* GCC*/ + + +#pragma pack() + +/*--------------------------------------------------------------------------- + * Exported Functions + *---------------------------------------------------------------------------*/ + +extern uint32_t USBGenericDescriptor_GetLength( + const USBGenericDescriptor *descriptor); + +extern uint8_t USBGenericDescriptor_GetType( + const USBGenericDescriptor *descriptor); + +extern USBGenericDescriptor *USBGenericDescriptor_GetNextDescriptor( + const USBGenericDescriptor *descriptor); + +extern USBGenericDescriptor *USBGenericDescriptor_Parse( + const USBGenericDescriptor * descriptor, + uint32_t totalLength, + USBDescriptorParseFunction parseFunction, + void * parseArg); + + +extern uint32_t USBConfigurationDescriptor_GetTotalLength( + const USBConfigurationDescriptor *configuration); + +extern uint8_t USBConfigurationDescriptor_GetNumInterfaces( + const USBConfigurationDescriptor *configuration); + +extern uint8_t USBConfigurationDescriptor_IsSelfPowered( + const USBConfigurationDescriptor *configuration); + +extern void USBConfigurationDescriptor_Parse( + const USBConfigurationDescriptor *configuration, + USBInterfaceDescriptor **interfaces, + USBEndpointDescriptor **endpoints, + USBGenericDescriptor **others); + +extern uint8_t USBEndpointDescriptor_GetNumber( + const USBEndpointDescriptor *endpoint); + +extern uint8_t USBEndpointDescriptor_GetDirection( + const USBEndpointDescriptor *endpoint); + +extern uint8_t USBEndpointDescriptor_GetType( + const USBEndpointDescriptor *endpoint); + +extern uint16_t USBEndpointDescriptor_GetMaxPacketSize( + const USBEndpointDescriptor *endpoint); + +extern uint8_t USBEndpointDescriptor_GetInterval( + const USBEndpointDescriptor *endpoint); + + +/** @}*/ +/**@}*/ +#endif /* #ifndef _USBDESCRIPTORS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Trace.h b/sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Trace.h new file mode 100644 index 00000000..ae35266e --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Trace.h @@ -0,0 +1,209 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \par Purpose + * + * Standard output methods for reporting debug information, warnings and + * errors, which can be easily be turned on/off. + * + * \par Usage + * -# Initialize the debug message port in application, for stdio printf(). + * -# Uses the TRACE_DEBUG(), TRACE_INFO(), TRACE_WARNING(), TRACE_ERROR() + * TRACE_FATAL() macros to output traces throughout the program. + * -# Each type of trace has a level : Debug 5, Info 4, Warning 3, Error 2 + * and Fatal 1. Disable a group of traces by changing the value of + * TRACE_LEVEL during compilation; traces with a level bigger than TRACE_LEVEL + * are not generated. To generate no trace, use the reserved value 0. + * -# Trace disabling can be static or dynamic. If dynamic disabling is selected + * the trace level can be modified in runtime. If static disabling is selected + * the disabled traces are not compiled. + * + * \par traceLevels Trace level description + * -# TRACE_DEBUG (5): Traces whose only purpose is for debugging the program, + * and which do not produce meaningful information otherwise. + * -# TRACE_INFO (4): Informational trace about the program execution. Should + * enable the user to see the execution flow. + * -# TRACE_WARNING (3): Indicates that a minor error has happened. In most case + * it can be discarded safely; it may even be expected. + * -# TRACE_ERROR (2): Indicates an error which may not stop the program execution, + * but which indicates there is a problem with the code. + * -# TRACE_FATAL (1): Indicates a major error which prevents the program from going + * any further. + */ + +#ifndef _USBLIB_TRACE_H +#define _USBLIB_TRACE_H + +/* + * Headers + */ + +#include + +/* + * Global Definitions + */ + +/** Softpack Version */ +#define USBLIB_VERSION "0.1" + +#define TRACE_LEVEL_DEBUG 5 +#define TRACE_LEVEL_INFO 4 +#define TRACE_LEVEL_WARNING 3 +#define TRACE_LEVEL_ERROR 2 +#define TRACE_LEVEL_FATAL 1 +#define TRACE_LEVEL_NO_TRACE 0 + +/* By default, all traces are output except the debug one. */ +#if !defined(TRACE_LEVEL) +#define TRACE_LEVEL TRACE_LEVEL_INFO +#endif + +/* By default, trace level is static (not dynamic) */ +#if !defined(DYN_TRACES) +#define DYN_TRACES 0 +#endif + +#if defined(NOTRACE) +#error "Error: NOTRACE has to be not defined !" +#endif + +#undef NOTRACE +#if (DYN_TRACES==0) + #if (TRACE_LEVEL == TRACE_LEVEL_NO_TRACE) + #define NOTRACE + #endif +#endif + + + +/* ------------------------------------------------------------------------------ + * Global Macros + * ------------------------------------------------------------------------------ + */ + +#ifndef DYNTRACE +#define DYNTRACE 0 +#endif + + +/** + * Outputs a formatted string using 'printf' if the log level is high + * enough. Can be disabled by defining TRACE_LEVEL=0 during compilation. + * \param ... Additional parameters depending on formatted string. + */ +#if defined(NOTRACE) + +/* Empty macro */ +#define TRACE_DEBUG(...) { } +#define TRACE_INFO(...) { } +#define TRACE_WARNING(...) { } +#define TRACE_ERROR(...) { } +#define TRACE_FATAL(...) { while(1); } + +#define TRACE_DEBUG_WP(...) { } +#define TRACE_INFO_WP(...) { } +#define TRACE_WARNING_WP(...) { } +#define TRACE_ERROR_WP(...) { } +#define TRACE_FATAL_WP(...) { while(1); } + +#elif (DYN_TRACES == 1) + +/* Trace output depends on dwTraceLevel value */ +#define TRACE_DEBUG(...) { if (dwTraceLevel >= TRACE_LEVEL_DEBUG) { printf("-D- " __VA_ARGS__); } } +#define TRACE_INFO(...) { if (dwTraceLevel >= TRACE_LEVEL_INFO) { printf("-I- " __VA_ARGS__); } } +#define TRACE_WARNING(...) { if (dwTraceLevel >= TRACE_LEVEL_WARNING) { printf("-W- " __VA_ARGS__); } } +#define TRACE_ERROR(...) { if (dwTraceLevel >= TRACE_LEVEL_ERROR) { printf("-E- " __VA_ARGS__); } } +#define TRACE_FATAL(...) { if (dwTraceLevel >= TRACE_LEVEL_FATAL) { printf("-F- " __VA_ARGS__); while(1); } } + +#define TRACE_DEBUG_WP(...) { if (dwTraceLevel >= TRACE_LEVEL_DEBUG) { printf(__VA_ARGS__); } } +#define TRACE_INFO_WP(...) { if (dwTraceLevel >= TRACE_LEVEL_INFO) { printf(__VA_ARGS__); } } +#define TRACE_WARNING_WP(...) { if (dwTraceLevel >= TRACE_LEVEL_WARNING) { printf(__VA_ARGS__); } } +#define TRACE_ERROR_WP(...) { if (dwTraceLevel >= TRACE_LEVEL_ERROR) { printf(__VA_ARGS__); } } +#define TRACE_FATAL_WP(...) { if (dwTraceLevel >= TRACE_LEVEL_FATAL) { printf(__VA_ARGS__); while(1); } } + +#else + +/* Trace compilation depends on TRACE_LEVEL value */ +#if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) +#define TRACE_DEBUG(...) { printf("-D- " __VA_ARGS__); } +#define TRACE_DEBUG_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_DEBUG(...) { } +#define TRACE_DEBUG_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_INFO) +#define TRACE_INFO(...) { printf("-I- " __VA_ARGS__); } +#define TRACE_INFO_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_INFO(...) { } +#define TRACE_INFO_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_WARNING) +#define TRACE_WARNING(...) { printf("-W- " __VA_ARGS__); } +#define TRACE_WARNING_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_WARNING(...) { } +#define TRACE_WARNING_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_ERROR) +#define TRACE_ERROR(...) { printf("-E- " __VA_ARGS__); } +#define TRACE_ERROR_WP(...) { printf(__VA_ARGS__); } +#else +#define TRACE_ERROR(...) { } +#define TRACE_ERROR_WP(...) { } +#endif + +#if (TRACE_LEVEL >= TRACE_LEVEL_FATAL) +#define TRACE_FATAL(...) { printf("-F- " __VA_ARGS__); while(1); } +#define TRACE_FATAL_WP(...) { printf(__VA_ARGS__); while(1); } +#else +#define TRACE_FATAL(...) { while(1); } +#define TRACE_FATAL_WP(...) { while(1); } +#endif + +#endif + + +/** + * Exported variables + */ +/** Depending on DYN_TRACES, dwTraceLevel is a modifable runtime variable or a define */ +#if !defined(NOTRACE) && (DYN_TRACES == 1) + extern uint32_t dwTraceLevel ; +#endif + +#endif /* #ifndef _USBLIB_TRACE_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Types.h b/sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Types.h new file mode 100644 index 00000000..8a58a65d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/USBLib_Types.h @@ -0,0 +1,65 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * Definitions for USB Lib compiling. + */ + +#ifndef USBLIB_TYPES_H +#define USBLIB_TYPES_H + +/*---------------------------------------------------------------------------- + * Defines + *----------------------------------------------------------------------------*/ + +/** USB status ReturnCode */ +typedef enum _USBRC { + USBRC_OK = 0, /**< Operation was successful */ + USBRC_SUCCESS = 0, /**< Operation was successful */ + /* Bool codes */ + USBRC_FALSE = 0, /**< As boolean TRUE */ + USBRC_TRUE = 1, /**< As boolean FALSE */ + /* Error codes */ + USBRC_BUSY, /**< EP/Device is already busy */ + USBRC_ABORTED, /**< Operation aborted due to error or stall */ + USBRC_CANCELED, /**< Operation canceled by user */ + USBRC_RESET, /**< Operation aborted due to init/reset/un-configure */ + USBRC_PARTIAL_DONE,/**< Part of operation successfully done */ + USBRC_FINISHED, /**< All operation successfully done and terminate */ + + USBRC_PARAM_ERR, /**< Failed due to parameter error */ + USBRC_STATE_ERR, /**< Failed due to state error */ + USBRC_ERROR, /**< General error */ + + USBRC_SW_NOT_SUPPORTED = 0xFD, /**< Failed due to SW not supported */ + USBRC_HW_NOT_SUPPORTED = 0xFE /**< Failed due to HW not supported */ +} USBRC; + +#endif /* #define USBLIB_TYPES_H */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/include/USBRequests.h b/sam3s_example/atmel_softpack_libraries/usb/include/USBRequests.h new file mode 100644 index 00000000..af646cf7 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/include/USBRequests.h @@ -0,0 +1,354 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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. + * ---------------------------------------------------------------------------- + */ + +/** \file + * \section Purpose + * + * Definitions and methods for USB request structures described by the + * USB specification. + * + * \section Usage + * + */ + +#ifndef _USBREQUESTS_H_ +#define _USBREQUESTS_H_ +/** \addtogroup usb_general + * @{ + * \addtogroup usb_request USB Requests + * @{ + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +/* These headers were introduced in C99 by working group + * ISO/IEC JTC1/SC22/WG14. + */ +#include + +/*--------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/*----------- Generic Request ------------*/ + +/** \addtogroup usb_request_define USB Generic Request definitions + * @{ + * This section lists the codes of USB generic request. + * + * - \ref usb_request_code USB Request codes + * - \ref USBGenericRequest_GETSTATUS + * - \ref USBGenericRequest_CLEARFEATURE + * - \ref USBGenericRequest_SETFEATURE + * - \ref USBGenericRequest_SETADDRESS + * - \ref USBGenericRequest_GETDESCRIPTOR + * - \ref USBGenericRequest_SETDESCRIPTOR + * - \ref USBGenericRequest_GETCONFIGURATION + * - \ref USBGenericRequest_SETCONFIGURATION + * - \ref USBGenericRequest_GETINTERFACE + * - \ref USBGenericRequest_SETINTERFACE + * - \ref USBGenericRequest_SYNCHFRAME + * + * - \ref usb_request_recipient USB Request Recipients + * - \ref USBGenericRequest_DEVICE + * - \ref USBGenericRequest_INTERFACE + * - \ref USBGenericRequest_ENDPOINT + * - \ref USBGenericRequest_OTHER + * + * - \ref usb_request_type USB Request Types + * - \ref USBGenericRequest_STANDARD + * - \ref USBGenericRequest_CLASS + * - \ref USBGenericRequest_VENDOR + * + * - \ref usb_request_dir USB Request Directions + * - \ref USBGenericRequest_IN + * - \ref USBGenericRequest_OUT + */ + +/** \addtogroup usb_request_code USB Request codes + * @{ + * This section lists the USB generic request codes. + * - \ref USBGenericRequest_GETSTATUS + * - \ref USBGenericRequest_CLEARFEATURE + * - \ref USBGenericRequest_SETFEATURE + * - \ref USBGenericRequest_SETADDRESS + * - \ref USBGenericRequest_GETDESCRIPTOR + * - \ref USBGenericRequest_SETDESCRIPTOR + * - \ref USBGenericRequest_GETCONFIGURATION + * - \ref USBGenericRequest_SETCONFIGURATION + * - \ref USBGenericRequest_GETINTERFACE + * - \ref USBGenericRequest_SETINTERFACE + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_request_recipient USB Request Recipients + * @{ + * This section lists codes of USB request recipients. + * - \ref USBGenericRequest_DEVICE + * - \ref USBGenericRequest_INTERFACE + * - \ref USBGenericRequest_ENDPOINT + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_request_type USB Request Types + * @{ + * This section lists codes of USB request types. + * - \ref USBGenericRequest_STANDARD + * - \ref USBGenericRequest_CLASS + * - \ref 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 +/** @}*/ + +/** \addtogroup usb_request_dir USB Request Directions + * @{ + * This section lists codes of USB request directions. + * - \ref USBGenericRequest_IN + * - \ref 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 +/** @}*/ +/** @}*/ + + +/*----------- Feature Request ------------*/ + +/** \addtogroup usb_feature_def USB Feature Request Definitions + * @{ + * This section lists codes of USB Feature Request + * + * - \ref usb_feature_sel USB Feature selectors + * - \ref USBFeatureRequest_ENDPOINTHALT + * - \ref USBFeatureRequest_DEVICEREMOTEWAKEUP + * - \ref USBFeatureRequest_TESTMODE + * + * - \ref usb_test_sel USB Test mode selectors + * - \ref USBFeatureRequest_TESTJ + * - \ref USBFeatureRequest_TESTK + * - \ref USBFeatureRequest_TESTSE0NAK + * - \ref USBFeatureRequest_TESTPACKET + * - \ref USBFeatureRequest_TESTFORCEENABLE + * - \ref USBFeatureRequest_TESTSENDZLP + */ + +/** \addtogroup usb_feature_sel USB Feature selectors + * @{ + * This section lists codes of USB feature selectors. + * - \ref USBFeatureRequest_ENDPOINTHALT + * - \ref USBFeatureRequest_DEVICEREMOTEWAKEUP + * - \ref 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 +/** OTG b_hnp_enable */ +#define USBFeatureRequest_OTG_B_HNP_ENABLE 3 +/** OTG a_hnp_support */ +#define USBFeatureRequest_OTG_A_HNP_SUPPORT 4 +/** OTG a_alt_hnp_support */ +#define USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT 5 +/** @}*/ + +/** \addtogroup usb_test_sel USB Test mode selectors + * @{ + * This section lists codes of USB high speed test mode selectors. + * - \ref USBFeatureRequest_TESTJ + * - \ref USBFeatureRequest_TESTK + * - \ref USBFeatureRequest_TESTSE0NAK + * - \ref USBFeatureRequest_TESTPACKET + * - \ref USBFeatureRequest_TESTFORCEENABLE + * - \ref 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 +/** @}*/ +/** @}*/ + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/* + * Function types + */ + +/* + * Descriptor structs types + */ +#ifdef __ICCARM__ /* IAR */ +#pragma pack(1) /* IAR */ +#define __attribute__(...) /* IAR */ +#endif /* IAR */ + +/** + * Generic USB SETUP request sent over Control endpoints. + */ +typedef struct { + + /** Type of request + * \sa usb_request_recipient "USB Request Recipients" + * \sa usb_request_type "USB Request Types" + * \sa usb_request_dir "USB Request Directions" */ + uint8_t bmRequestType:8; + /** Request code + * \sa usb_request_code "USB Request Codes" */ + uint8_t bRequest:8; + /** Request-specific value parameter. */ + uint16_t wValue:16; + /** Request-specific index parameter. */ + uint16_t wIndex:16; + /** Expected length (in bytes) of the data phase. */ + uint16_t wLength:16; + +} USBGenericRequest; + +#ifdef __ICCARM__ /* IAR */ +#pragma pack() /* IAR */ +#endif /* IAR */ + +/*--------------------------------------------------------------------------- + * Exported Functions + *---------------------------------------------------------------------------*/ + +extern uint8_t USBGenericRequest_GetType( + const USBGenericRequest *request); + +extern uint8_t USBGenericRequest_GetRequest( + const USBGenericRequest *request); + +extern uint16_t USBGenericRequest_GetValue( + const USBGenericRequest *request); + +extern uint16_t USBGenericRequest_GetIndex( + const USBGenericRequest *request); + +extern uint16_t USBGenericRequest_GetLength( + const USBGenericRequest *request); + +extern uint8_t USBGenericRequest_GetEndpointNumber( + const USBGenericRequest *request); + +extern uint8_t USBGenericRequest_GetRecipient( + const USBGenericRequest *request); + +extern uint8_t USBGenericRequest_GetDirection( + const USBGenericRequest *request); + + +extern uint8_t USBGetDescriptorRequest_GetDescriptorType( + const USBGenericRequest *request); + +extern uint8_t USBGetDescriptorRequest_GetDescriptorIndex( + const USBGenericRequest *request); + + +extern uint8_t USBSetAddressRequest_GetAddress( + const USBGenericRequest *request); + + +extern uint8_t USBSetConfigurationRequest_GetConfiguration( + const USBGenericRequest *request); + + +extern uint8_t USBInterfaceRequest_GetInterface( + const USBGenericRequest *request); + +extern uint8_t USBInterfaceRequest_GetAlternateSetting( + const USBGenericRequest *request); + + +extern uint8_t USBFeatureRequest_GetFeatureSelector( + const USBGenericRequest *request); + +extern uint8_t USBFeatureRequest_GetTestSelector( + const USBGenericRequest *request); + +/** @}*/ +/**@}*/ +#endif /* #ifndef _USBREQUESTS_H_ */ + diff --git a/sam3s_example/atmel_softpack_libraries/usb/lib/libusb_sam3s_gcc_dbg.a b/sam3s_example/atmel_softpack_libraries/usb/lib/libusb_sam3s_gcc_dbg.a new file mode 100644 index 0000000000000000000000000000000000000000..bbf50062bc9f2530e6af4d0496f54a3db7310a80 GIT binary patch literal 434082 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 literal 0 HcmV?d00001 diff --git a/sam3s_example/atmel_softpack_libraries/usb/usb.h b/sam3s_example/atmel_softpack_libraries/usb/usb.h new file mode 100644 index 00000000..b74cc109 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/usb/usb.h @@ -0,0 +1,99 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file usb.h + * + * Definition of SAM3S-EK usb library + * + */ + +#ifndef _usb_ +#define _usb_ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "board.h" + +#include "include/USBD.h" +#include "include/USBD_HAL.h" + +#include "include/USBDescriptors.h" + +#include "include/USBDDriver.h" + +#include "include/AUDDescriptors.h" +#include "include/AUDDFunction.h" +#include "include/AUDDSpeakerDriver.h" +#include "include/AUDDSpeakerPhone.h" +#include "include/AUDDSpeakerPhoneDriver.h" +#include "include/AUDDStream.h" +#include "include/AUDRequests.h" + +#include "include/CDCAUDDDriver.h" +#include "include/CDCDescriptors.h" +#include "include/CDCDSerial.h" +#include "include/CDCDSerialDriver.h" +#include "include/CDCDSerialPort.h" +#include "include/CDCHIDDDriver.h" +#include "include/CDCMSDDriver.h" +#include "include/CDCNotifications.h" +#include "include/CDCRequests.h" + +#include "include/DUALCDCDDriver.h" + +#include "include/HIDAUDDDriver.h" +#include "include/HIDDescriptors.h" +#include "include/HIDDFunction.h" +#include "include/HIDDKeyboard.h" +#include "include/HIDDKeyboardDriver.h" +#include "include/HIDDMouseDriver.h" +#include "include/HIDDTransferDriver.h" +#include "include/HIDMSDDriver.h" +#include "include/HIDReports.h" +#include "include/HIDRequests.h" +#include "include/HIDUsages.h" + +#include "include/MSD.h" +#include "include/MSDDriver.h" +#include "include/MSDDStateMachine.h" +#include "include/MSDescriptors.h" +#include "include/MSDFunction.h" +#include "include/MSDIOFifo.h" +#include "include/MSDLun.h" + +#include "include/SBC.h" +#include "include/SBCMethods.h" + +#include "include/USBLib_Trace.h" +#include "include/USBLib_Types.h" +#include "include/USBRequests.h" + +#endif /* #ifndef _usb_ */