Renamed main folder to firmware
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
@@ -0,0 +1,234 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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_speaker
|
||||
*@{
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <AUDDSpeakerDriver.h>
|
||||
|
||||
#include <AUDDSpeakerPhone.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
#include <AUDRequests.h>
|
||||
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* 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[0];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
#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 */
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -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 <AUDDSpeakerPhoneDriver.h>
|
||||
|
||||
#include <AUDRequests.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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[0];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
#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 */
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <AUDDSpeakerPhone.h>
|
||||
|
||||
#include <USBDescriptors.h>
|
||||
#include <USBRequests.h>
|
||||
#include <AUDDescriptors.h>
|
||||
#include <AUDRequests.h>
|
||||
|
||||
#include <USBD_HAL.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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<<bCh)) > 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
1531
firmware/atmel_softpack_libraries/usb/device/ccid/cciddriver.c
Normal file
388
firmware/atmel_softpack_libraries/usb/device/ccid/cciddriver.h
Normal file
@@ -0,0 +1,388 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \unit
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// Definition of methods for using a CCID device driver.
|
||||
///
|
||||
/// !Usage
|
||||
///
|
||||
/// -# CCIDDriver_Initialize
|
||||
/// -# CCID_Read
|
||||
/// -# CCID_Write
|
||||
/// -# CCID_SmartCardRequest
|
||||
/// -# CCID_Insertion
|
||||
/// -# CCID_Removal
|
||||
/// -# RDRtoPCHardwareError
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef CCID_DRIVER_H
|
||||
#define CCID_DRIVER_H
|
||||
|
||||
// FIXME: This is dirty! Typedef copied from USBD.h
|
||||
typedef void (*TransferCallback)(void *pArg,
|
||||
uint8_t status,
|
||||
uint32_t transferred,
|
||||
uint32_t remaining);
|
||||
|
||||
|
||||
|
||||
/// For reference, the absolute maximum block size
|
||||
/// for a TPDU T=0 block is 260 bytes (5 bytes command; 255 bytes data), or
|
||||
/// for a TPDU T=1 block is 259 bytes, or
|
||||
/// for a short APDU T=1 block is 261 bytes, or
|
||||
/// for an extended APDU T=1 block is 65544 bytes.
|
||||
#define ABDATA_SIZE 260
|
||||
|
||||
/// define protocol T=0
|
||||
#define PROTOCOL_TO 0
|
||||
/// define protocol T=1
|
||||
#define PROTOCOL_T1 1
|
||||
|
||||
/// define for dwFeatures see Table 5.1-1 Smart Card Device Class Descriptors
|
||||
/// No special characteristics
|
||||
#define CCID_FEATURES_NADA 0x00000000
|
||||
/// Automatic parameter configuration based on ATR data
|
||||
#define CCID_FEATURES_AUTO_PCONF 0x00000002
|
||||
/// Automatic activation of ICC on inserting
|
||||
#define CCID_FEATURES_AUTO_ACTIV 0x00000004
|
||||
/// Automatic ICC voltage selection
|
||||
#define CCID_FEATURES_AUTO_VOLT 0x00000008
|
||||
/// Automatic ICC clock frequency change according to active parameters provided
|
||||
/// by the Host or self determined
|
||||
#define CCID_FEATURES_AUTO_CLOCK 0x00000010
|
||||
/// Automatic baud rate change according to active parameters provided by the
|
||||
/// Host or self determined
|
||||
#define CCID_FEATURES_AUTO_BAUD 0x00000020
|
||||
/// Automatic parameters negotiation made by the CCID (use of warm or cold
|
||||
/// resets or PPS according to a manufacturer proprietary algorithm to select
|
||||
/// the communication parameters with the ICC)
|
||||
#define CCID_FEATURES_AUTO_PNEGO 0x00000040
|
||||
/// Automatic PPS made by the CCID according to the active parameters
|
||||
#define CCID_FEATURES_AUTO_PPS 0x00000080
|
||||
/// CCID can set ICC in clock stop mode
|
||||
#define CCID_FEATURES_ICCSTOP 0x00000100
|
||||
/// NAD value other than 00 accepted (T=1 protocol in use)
|
||||
#define CCID_FEATURES_NAD 0x00000200
|
||||
/// Automatic IFSD exchange as first exchange (T=1 protocol in use)
|
||||
#define CCID_FEATURES_AUTO_IFSD 0x00000400
|
||||
/// TPDU level exchanges with CCID
|
||||
#define CCID_FEATURES_EXC_TPDU 0x00010000
|
||||
/// Short APDU level exchange with CCID
|
||||
#define CCID_FEATURES_EXC_SAPDU 0x00020000
|
||||
/// Short and Extended APDU level exchange with CCID
|
||||
#define CCID_FEATURES_EXC_APDU 0x00040000
|
||||
/// USB Wake up signaling supported on card insertion and removal
|
||||
#define CCID_FEATURES_WAKEUP 0x00100000
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Bulk CCID Message header structure
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bMessageType;
|
||||
/// Message-specific data length
|
||||
unsigned long wLength;
|
||||
/// Identifies the slot number for this command
|
||||
unsigned char bSlot;
|
||||
/// Sequence number for command.
|
||||
unsigned char bSeq;
|
||||
/// Slot status register
|
||||
unsigned char bStatus;
|
||||
/// Slot error
|
||||
unsigned char bError;
|
||||
/// specific register
|
||||
unsigned char bSpecific;
|
||||
/// Data block sent to the CCID.
|
||||
unsigned char abData[ABDATA_SIZE];
|
||||
unsigned char bSizeToSend;
|
||||
} __attribute__ ((packed)) S_ccid_bulk_in_header;
|
||||
|
||||
/// 6.1 Bulk Transfers
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bMessageType;
|
||||
/// Message-specific data length
|
||||
unsigned long wLength;
|
||||
/// Identifies the slot number for this command
|
||||
unsigned char bSlot;
|
||||
/// Sequence number for command.
|
||||
unsigned char bSeq;
|
||||
/// specific register
|
||||
unsigned char bSpecific_0;
|
||||
unsigned char bSpecific_1;
|
||||
unsigned char bSpecific_2;
|
||||
/// Application Protocol Data Unit
|
||||
unsigned char APDU[ABDATA_SIZE];
|
||||
} __attribute__ ((packed)) S_ccid_bulk_out_header;
|
||||
|
||||
|
||||
/// 6.1.11.2 PIN Verification Data Structure
|
||||
typedef struct
|
||||
{
|
||||
/// Number of seconds.
|
||||
unsigned char bTimerOut;
|
||||
/// Several parameters for the PIN format options
|
||||
unsigned char bmFormatString;
|
||||
/// Define the length of the PIN to present in the APDU command
|
||||
unsigned char bmPINBlockString;
|
||||
/// Allows the length PIN insertion in the APDU command
|
||||
unsigned char bmPINLengthFormat;
|
||||
/// Minimum PIN size in digit and Maximum PIN size in digit
|
||||
unsigned char wPINMaxExtraDigit;
|
||||
/// The value is a bit wise OR operation.
|
||||
unsigned char bEntryValidationCondition;
|
||||
/// Number of messages to display for the PIN modify command
|
||||
unsigned char bNumberMessage;
|
||||
/// Language used to display the messages.
|
||||
unsigned char wLangId;
|
||||
/// Message index in the Reader message table
|
||||
unsigned char bMsgIndex;
|
||||
/// T=1 I-block prologue field to use
|
||||
unsigned char bTeoPrologue[3];
|
||||
/// APDU to send to the ICC
|
||||
unsigned char abPINApdu[255];
|
||||
}__attribute__ ((packed)) S_ccid_PIN_Verification;
|
||||
|
||||
|
||||
/// 6.1.11.7 PIN Modification Data Structure
|
||||
typedef struct
|
||||
{
|
||||
/// Number of seconds. If 00h then CCID default value is used.
|
||||
unsigned char bTimeOut;
|
||||
/// Several parameters for the PIN format options (defined in § 6.1.11.4)
|
||||
unsigned char bmFormatString4;
|
||||
/// Define the length of the PIN to present in the APDU command
|
||||
unsigned char bmPINBlockString;
|
||||
/// Allows the length PIN insertion in the APDU command (defined in § 6.1.11.6)
|
||||
unsigned char bmPinLengthFormat;
|
||||
/// Insertion position offset in byte for the current PIN
|
||||
unsigned char bInsertionOffsetOld;
|
||||
/// Insertion position offset in byte for the new PIN
|
||||
unsigned char bInsertionOffsetNew;
|
||||
/// XXYYh
|
||||
/// XX: Minimum PIN size in digit
|
||||
/// YY: Maximum PIN size in digit
|
||||
unsigned char wPINMaxExtraDigit;
|
||||
/// 00h,01h,02h,03h
|
||||
/// Indicates if a confirmation is requested before acceptance of a new PIN (meaning that the user has to enter this new PIN twice before it is accepted)
|
||||
/// Indicates if the current PIN must be entered and set in the same APDU field of not.
|
||||
unsigned char bConfirmPIN;
|
||||
/// The value is a bit wise OR operation.
|
||||
/// 01h Max size reached
|
||||
/// 02h Validation key pressed
|
||||
/// 04h Timeout occurred
|
||||
unsigned char bEntryValidationCondition;
|
||||
/// 00h,01h,02h,03h,or FFh
|
||||
/// Number of messages to display for the PIN modify command.
|
||||
unsigned char bNumberMessage;
|
||||
/// Language used to display the messages. The 16 bit
|
||||
unsigned char wLangId;
|
||||
/// Message index in the Reader message table (should be 00h or 01h).
|
||||
unsigned char bMsgIndex1;
|
||||
/// Message index in the Reader message table (should be 01h or 02h).
|
||||
unsigned char bMsgIndex2;
|
||||
/// Message index in the Reader message table (should be 02h).
|
||||
unsigned char bMsgIndex3;
|
||||
/// T=1 I-block prologue field to use. Significant only if protocol in use is T=1.
|
||||
unsigned char bTeoPrologue[3];
|
||||
/// Byte array APDU to send to the ICC
|
||||
unsigned char abPINApdu[255];
|
||||
}__attribute__ ((packed)) S_ccid_PIN_Modification;
|
||||
|
||||
/// Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h)
|
||||
typedef struct
|
||||
{
|
||||
/// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
|
||||
/// clock rate conversion factor
|
||||
/// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
|
||||
/// baud rate conversion factor
|
||||
unsigned char bmFindexDindex;
|
||||
/// For T=0 ,B0 – 0b, B7-2 – 000000b
|
||||
/// B1 – Convention used (b1=0 for direct, b1=1 for inverse)
|
||||
unsigned char bmTCCKST0; // 0 to 2
|
||||
/// Extra Guardtime between two characters. Add 0 to 254 etu to the normal
|
||||
/// guardtime of 12etu. FFh is the same as 00h.
|
||||
unsigned char bGuardTimeT0; // 0 to FF
|
||||
/// WI for T=0 used to define WWT
|
||||
unsigned char bWaitingIntegerT0; // 0 to FF
|
||||
/// ICC Clock Stop Support
|
||||
/// 00 = Stopping the Clock is not allowed
|
||||
/// 01 = Stop with Clock signal Low
|
||||
/// 02 = Stop with Clock signal High
|
||||
/// 03 = Stop with Clock either High or Low
|
||||
unsigned char bClockStop; // 0 to 3
|
||||
} __attribute__ ((packed)) S_ccid_protocol_t0;
|
||||
|
||||
|
||||
/// Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h)
|
||||
typedef struct
|
||||
{
|
||||
/// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
|
||||
/// clock rate conversion factor
|
||||
/// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
|
||||
/// baud rate conversion factor
|
||||
unsigned char bmFindexDindex;
|
||||
/// For T=1, B7-2 – 000100b
|
||||
/// B0 – Checksum type (b0=0 for LRC, b0=1 for CRC
|
||||
/// B1 – Convention used (b1=0 for direct, b1=1 for inverse)
|
||||
unsigned char bmTCCKST1; // 10h, 11h, 12h, 13h
|
||||
/// Extra Guardtime (0 to 254 etu between two characters).
|
||||
/// If value is FFh, then guardtime is reduced by 1.
|
||||
unsigned char bGuardTimeT1; // 0 to FF
|
||||
/// B7-4 = BWI
|
||||
/// B3-0 = CWI
|
||||
unsigned char bmWaitingIntegersT1; // 0 to 9
|
||||
/// ICC Clock Stop Support
|
||||
/// 00 = Stopping the Clock is not allowed
|
||||
/// 01 = Stop with Clock signal Low
|
||||
/// 02 = Stop with Clock signal High
|
||||
/// 03 = Stop with Clock either High or Low
|
||||
unsigned char bClockStop; // 0 to 3
|
||||
/// Size of negotiated IFSC
|
||||
unsigned char bIFSC; // 0 to FE
|
||||
/// Nad value used by CCID
|
||||
unsigned char bNadValue; // 0 to FF
|
||||
} __attribute__ ((packed)) S_ccid_protocol_t1;
|
||||
|
||||
|
||||
/// Identifies the length of type of subordinate descriptors of a CCID device
|
||||
/// Table 5.1-1 Smart Card Device Class descriptors
|
||||
typedef struct
|
||||
{
|
||||
/// Size of this descriptor, in bytes.
|
||||
unsigned char bLength;
|
||||
/// Functional Descriptor type
|
||||
unsigned char bDescriptorType;
|
||||
/// Integrated Circuit(s) Cards Interface Devices (CCID) Specification
|
||||
/// Release Number
|
||||
unsigned short bcdCCID;
|
||||
/// Index of the highest available slot. An USB-ICC is regarded as a single
|
||||
/// slot CCID.
|
||||
unsigned char bMaxSlotIndex;
|
||||
/// This value indicates what voltages the CCID can supply to its slots.
|
||||
/// It is a bitwise OR operation performed on the following values:
|
||||
/// - 01h 5.0V
|
||||
/// - 02h 3.0V
|
||||
/// - 04h 1.8V
|
||||
/// Other bits are RFU.
|
||||
unsigned char bVoltageSupport;
|
||||
/// RRRR –Upper Word- is RFU = 0000h
|
||||
/// PPPP –Lower Word- Encodes the supported protocol types. A ‘1’ in a given
|
||||
/// bit position indicates support for the associated ISO protocol.
|
||||
/// 0001h = Protocol T=0
|
||||
/// 0002h = Protocol T=1
|
||||
/// All other bits are reserved and must be set to zero. The field is
|
||||
/// intended to correspond to the PCSC specification definitions.
|
||||
unsigned long dwProtocols;
|
||||
/// Default ICC clock frequency in KHz. This is an integer value.
|
||||
unsigned long dwDefaultClock;
|
||||
/// Maximum supported ICC clock frequency in KHz. This is an integer value.
|
||||
unsigned long dwMaximumClock;
|
||||
/// The number of clock frequencies that are supported by the CCID. If the
|
||||
/// value is 00h, the supported clock frequencies are assumed to be the
|
||||
/// default clock frequency defined by dwDefaultClock and the maximum clock
|
||||
/// frequency defined by dwMaximumClock.
|
||||
unsigned char bNumClockSupported;
|
||||
/// Default ICC I/O data rate in bps. This is an integer value
|
||||
unsigned long dwDataRate;
|
||||
/// Maximum supported ICC I/O data rate in bps
|
||||
unsigned long dwMaxDataRate;
|
||||
/// The number of data rates that are supported by the CCID.
|
||||
unsigned char bNumDataRatesSupported;
|
||||
/// Indicates the maximum IFSD supported by CCID for protocol T=1.
|
||||
unsigned long dwMaxIFSD;
|
||||
/// - RRRR-Upper Word- is RFU = 0000h
|
||||
/// - PPPP-Lower Word- encodes the supported protocol types. A ‘1’ in a given
|
||||
/// bit position indicates support for the associated protocol.
|
||||
/// 0001h indicates support for the 2-wire protocol 1
|
||||
/// 0002h indicates support for the 3-wire protocol 1
|
||||
/// 0004h indicates support for the I2C protocol 1
|
||||
/// All other values are outside of this specification, and must be handled
|
||||
/// by vendor-supplied drivers.
|
||||
unsigned long dwSynchProtocols;
|
||||
/// The value is a bitwise OR operation performed on the following values:
|
||||
/// - 00000000h No special characteristics
|
||||
/// - 00000001h Card accept mechanism 2
|
||||
/// - 00000002h Card ejection mechanism 2
|
||||
/// - 00000004h Card capture mechanism 2
|
||||
/// - 00000008h Card lock/unlock mechanism
|
||||
unsigned long dwMechanical;
|
||||
/// This value indicates what intelligent features the CCID has.
|
||||
unsigned long dwFeatures;
|
||||
/// For extended APDU level the value shall be between 261 + 10 (header) and
|
||||
/// 65544 +10, otherwise the minimum value is the wMaxPacketSize of the
|
||||
/// Bulk-OUT endpoint.
|
||||
unsigned long dwMaxCCIDMessageLength;
|
||||
/// Significant only for CCID that offers an APDU level for exchanges.
|
||||
unsigned char bClassGetResponse;
|
||||
/// Significant only for CCID that offers an extended APDU level for exchanges.
|
||||
unsigned char bClassEnvelope;
|
||||
/// Number of lines and characters for the LCD display used to send messages for PIN entry.
|
||||
unsigned short wLcdLayout;
|
||||
/// This value indicates what PIN support features the CCID has.
|
||||
unsigned char bPINSupport;
|
||||
/// Maximum number of slots which can be simultaneously busy.
|
||||
unsigned char bMaxCCIDBusySlots;
|
||||
|
||||
} __attribute__ ((packed)) CCIDDescriptor;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exported functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern unsigned char RDRtoPCHardwareError( unsigned char bSlot,
|
||||
unsigned char bSeq,
|
||||
unsigned char bHardwareErrorCode );
|
||||
|
||||
/*
|
||||
#if !defined(NOAUTOCALLBACK)
|
||||
extern void USBDCallbacks_RequestReceived(const USBGenericRequest *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
|
||||
|
||||
@@ -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.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Title: cciddriverdescriptors.h
|
||||
//
|
||||
// About: Purpose
|
||||
// Definitions of the descriptors required by the ccid device driver.
|
||||
// DWG_Smart-Card_CCID_Rev110.pdf
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef CCID_DRIVER_DESCRIPTORS_H
|
||||
#define CCID_DRIVER_DESCRIPTORS_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Definitions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Constants: Endpoints
|
||||
// CCID_EPT_DATA_OUT endpoint data out bulk 1
|
||||
// CCID_EPT_DATA_IN endpoint data in bulk 2
|
||||
// CCID_EPT_NOTIFICATION endpoint data interupt 3
|
||||
//------------------------------------------------------------------------------
|
||||
#define CCID_EPT_DATA_OUT 1
|
||||
#define CCID_EPT_DATA_IN 2
|
||||
#define CCID_EPT_NOTIFICATION 3
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// USB-ICC protocol
|
||||
//------------------------------------------------------------------------------
|
||||
// CCID specification version 1.10
|
||||
#define CCID1_10 0x0110
|
||||
|
||||
#define SMART_CARD_DEVICE_CLASS 0x0B
|
||||
// Smart Card Device Class Descriptor Type
|
||||
#define CCID_DECRIPTOR_TYPE 0x21
|
||||
|
||||
// Table 5.3-1 Summary of CCID Class Specific Request
|
||||
#define CCIDGenericRequest_ABORT 0x01
|
||||
#define CCIDGenericRequest_GET_CLOCK_FREQUENCIES 0x02
|
||||
#define CCIDGenericRequest_GET_DATA_RATES 0x03
|
||||
|
||||
// 6.1 Command Pipe, Bulk-OUT Messages
|
||||
#define PC_TO_RDR_ICCPOWERON 0x62
|
||||
#define PC_TO_RDR_ICCPOWEROFF 0x63
|
||||
#define PC_TO_RDR_GETSLOTSTATUS 0x65
|
||||
#define PC_TO_RDR_XFRBLOCK 0x6F
|
||||
#define PC_TO_RDR_GETPARAMETERS 0x6C
|
||||
#define PC_TO_RDR_RESETPARAMETERS 0x6D
|
||||
#define PC_TO_RDR_SETPARAMETERS 0x61
|
||||
#define PC_TO_RDR_ESCAPE 0x6B
|
||||
#define PC_TO_RDR_ICCCLOCK 0x6E
|
||||
#define PC_TO_RDR_T0APDU 0x6A
|
||||
#define PC_TO_RDR_SECURE 0x69
|
||||
#define PC_TO_RDR_MECHANICAL 0x71
|
||||
#define PC_TO_RDR_ABORT 0x72
|
||||
#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73
|
||||
|
||||
// 6.2 Response Pipe, Bulk-IN Messages
|
||||
#define RDR_TO_PC_DATABLOCK 0x80
|
||||
#define RDR_TO_PC_SLOTSTATUS 0x81
|
||||
#define RDR_TO_PC_PARAMETERS 0x82
|
||||
#define RDR_TO_PC_ESCAPE 0x83
|
||||
#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84
|
||||
|
||||
// 6.3 Interrupt-IN Messages
|
||||
#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50
|
||||
#define RDR_TO_PC_HARDWAREERROR 0x51
|
||||
|
||||
// Table 6.2-2 Slot error register when bmCommandStatus = 1
|
||||
#define CMD_ABORTED 0xFF
|
||||
#define ICC_MUTE 0xFE
|
||||
#define XFR_PARITY_ERROR 0xFD
|
||||
#define XFR_OVERRUN 0xFC
|
||||
#define HW_ERROR 0xFB
|
||||
#define BAD_ATR_TS 0xF8
|
||||
#define BAD_ATR_TCK 0xF7
|
||||
#define ICC_PROTOCOL_NOT_SUPPORTED 0xF6
|
||||
#define ICC_CLASS_NOT_SUPPORTED 0xF5
|
||||
#define PROCEDURE_BYTE_CONFLICT 0xF4
|
||||
#define DEACTIVATED_PROTOCOL 0xF3
|
||||
#define BUSY_WITH_AUTO_SEQUENCE 0xF2
|
||||
#define PIN_TIMEOUT 0xF0
|
||||
#define PIN_CANCELLED 0xEF
|
||||
#define CMD_SLOT_BUSY 0xE0
|
||||
// User defined 0xC0 to 0x81
|
||||
// Reserved for futur use 0x80
|
||||
// not supported incorrect message parameter 0x7F to 0x01
|
||||
// Command not supported 0x00
|
||||
|
||||
// CCID rev 1.1, p.27
|
||||
#define VOLTS_AUTO 0x00
|
||||
#define VOLTS_5_0 0x01
|
||||
#define VOLTS_3_0 0x02
|
||||
#define VOLTS_1_8 0x03
|
||||
|
||||
// 6.3.1 RDR_to_PC_NotifySlotChange
|
||||
#define ICC_NOT_PRESENT 0x00
|
||||
#define ICC_PRESENT 0x01
|
||||
#define ICC_CHANGE 0x02
|
||||
#define ICC_INSERTED_EVENT 0x01
|
||||
//FIXME: #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
|
||||
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
#include <USBDDriver.h>
|
||||
#include <USBD_HAL.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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 */
|
||||
}
|
||||
/**@}*/
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
#include <USBDDriver.h>
|
||||
#include <USBD_HAL.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
#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 */
|
||||
}
|
||||
|
||||
@@ -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 <CDCDSerialPort.h>
|
||||
#include <CDCDescriptors.h>
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
@@ -0,0 +1,45 @@
|
||||
; $Id: 6119.inf,v 1.1.2.1 2006/12/05 08:33:25 danielru Exp $
|
||||
|
||||
[Version] ; Version section
|
||||
Signature="$Chicago$" ; All Windows versions
|
||||
Class=Ports ; This is a serial port driver
|
||||
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} ; Associated GUID
|
||||
Provider=%ATMEL% ; Driver is provided by ATMEL
|
||||
DriverVer=09/12/2006,1.1.1.5 ; Driver version 1.1.1.5 published on 23 February 2007
|
||||
|
||||
[DestinationDirs] ; DestinationDirs section
|
||||
DefaultDestDir=12 ; Default install directory is \drivers or \IOSubSys
|
||||
|
||||
[Manufacturer] ; Manufacturer section
|
||||
%ATMEL%=AtmelMfg ; Only one manufacturer (ATMEL), models section is named
|
||||
; AtmelMfg
|
||||
|
||||
[AtmelMfg] ; Models section corresponding to ATMEL
|
||||
%USBtoSerialConverter%=USBtoSer.Install,USB\VID_03EB&PID_6119 ; Identifies a device with ATMEL Vendor ID (03EBh) and
|
||||
; Product ID equal to 6119h. Corresponding Install section
|
||||
; is named USBtoSer.Install
|
||||
|
||||
[USBtoSer.Install] ; Install section
|
||||
include=mdmcpq.inf
|
||||
CopyFiles=FakeModemCopyFileSection
|
||||
AddReg=USBtoSer.AddReg ; Registry keys to add are listed in USBtoSer.AddReg
|
||||
|
||||
[USBtoSer.AddReg] ; AddReg section
|
||||
HKR,,DevLoader,,*ntkern ;
|
||||
HKR,,NTMPDriver,,usbser.sys
|
||||
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
|
||||
|
||||
[USBtoSer.Install.Services] ; Services section
|
||||
AddService=usbser,0x00000002,USBtoSer.AddService ; Assign usbser as the PnP driver for the device
|
||||
|
||||
[USBtoSer.AddService] ; Service install section
|
||||
DisplayName=%USBSer% ; Name of the serial driver
|
||||
ServiceType=1 ; Service kernel driver
|
||||
StartType=3 ; Driver is started by the PnP manager
|
||||
ErrorControl=1 ; Warn about errors
|
||||
ServiceBinary=%12%\usbser.sys ; Driver filename
|
||||
|
||||
[Strings] ; Strings section
|
||||
ATMEL="ATMEL Corp." ; String value for the ATMEL symbol
|
||||
USBtoSerialConverter="AT91 USB to Serial Converter" ; String value for the USBtoSerialConverter symbol
|
||||
USBSer="USB Serial Driver" ; String value for the USBSer symbol
|
||||
@@ -0,0 +1,235 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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_aud_fun
|
||||
*@{
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
#include <AUDDFunction.h>
|
||||
#include <AUDDSpeakerPhone.h>
|
||||
|
||||
#include <AUDRequests.h>
|
||||
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* 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 <USBD_STATUS_SUCCESS> 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
|
||||
#include <CDCAUDDDriver.h>
|
||||
#include <CDCDSerial.h>
|
||||
#include <AUDDFunction.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
|
||||
#include <CDCHIDDDriver.h>
|
||||
#include <CDCDSerial.h>
|
||||
#include <HIDDKeyboard.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
|
||||
#include <CDCMSDDriver.h>
|
||||
|
||||
#include <CDCDSerial.h>
|
||||
#include <MSDFunction.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
|
||||
/* USB */
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
/* - DUALCDC */
|
||||
#include <DUALCDCDDriver.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
|
||||
#include <HIDAUDDDriver.h>
|
||||
#include <HIDDKeyboard.h>
|
||||
#include <AUDDFunction.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
|
||||
#include <HIDMSDDriver.h>
|
||||
|
||||
#include <HIDDKeyboard.h>
|
||||
#include <MSDFunction.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* 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");
|
||||
}
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 38 KiB |
@@ -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
|
||||
378
firmware/atmel_softpack_libraries/usb/device/core/USBD.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \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 <USBLib_Trace.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* 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?) */
|
||||
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 */
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
TRACE_DEBUG("%s\n\r", "USBD_RequestHandler");
|
||||
if (bEndpoint != 0) {
|
||||
TRACE_WARNING("EP%d request not supported, default EP only",
|
||||
bEndpoint);
|
||||
}
|
||||
else {
|
||||
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 */
|
||||
USBDCallbacks_Initialized();
|
||||
TRACE_DEBUG("%s\n\r", "..");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current state of the USB device.
|
||||
* \return Device current state.
|
||||
*/
|
||||
uint8_t USBD_GetState(void)
|
||||
{
|
||||
return deviceState;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
702
firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c
Normal file
@@ -0,0 +1,702 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \addtogroup usbd_interface
|
||||
*@{
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <board.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
#include "USBDDriver.h"
|
||||
#include "USBD.h"
|
||||
#include "USBD_HAL.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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 */
|
||||
TRACE_DEBUG("%s\n\r", "SetConfiguration");
|
||||
|
||||
if (USBD_IsHighSpeed()) {
|
||||
|
||||
pConfiguration = pDriver->pDescriptors->pHsConfiguration;
|
||||
}
|
||||
else {
|
||||
|
||||
pConfiguration = pDriver->pDescriptors->pFsConfiguration[cfgnum-1];
|
||||
}
|
||||
|
||||
/* 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[0];
|
||||
}
|
||||
|
||||
/* 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("%s", "HS ");
|
||||
pDevice = pDriver->pDescriptors->pHsDevice;
|
||||
pConfiguration = pDriver->pDescriptors->pHsConfiguration;
|
||||
pQualifier = pDriver->pDescriptors->pHsQualifier;
|
||||
pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
|
||||
}
|
||||
else {
|
||||
|
||||
TRACE_DEBUG("%s", "FS ");
|
||||
pDevice = pDriver->pDescriptors->pFsDevice;
|
||||
pConfiguration = pDriver->pDescriptors->pFsConfiguration[indexRDesc];
|
||||
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[0];
|
||||
|
||||
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<<USBFeatureRequest_OTG_B_HNP_ENABLE;
|
||||
USBD_Write(0, 0, 0, 0, 0);
|
||||
break;
|
||||
case USBFeatureRequest_OTG_A_HNP_SUPPORT:
|
||||
TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
|
||||
pDriver->otg_features_supported |=
|
||||
1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
|
||||
USBD_Write(0, 0, 0, 0, 0);
|
||||
break;
|
||||
case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
|
||||
TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
|
||||
pDriver->otg_features_supported |=
|
||||
1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
|
||||
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_SETINTERFACE:
|
||||
TRACE_INFO_WP("sInterface ");
|
||||
|
||||
infnum = USBInterfaceRequest_GetInterface(pRequest);
|
||||
setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
|
||||
SetInterface(pDriver, infnum, setting);
|
||||
break;
|
||||
|
||||
case USBGenericRequest_GETINTERFACE:
|
||||
TRACE_INFO_WP("gInterface ");
|
||||
|
||||
infnum = USBInterfaceRequest_GetInterface(pRequest);
|
||||
GetInterface(pDriver, infnum);
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE_WARNING(
|
||||
"USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
|
||||
USBGenericRequest_GetRequest(pRequest));
|
||||
USBD_Stall(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test if RemoteWakeUP feature is enabled
|
||||
* \param pDriver Pointer to an USBDDriver instance.
|
||||
* \return 1 if remote wake up has been enabled by the host; otherwise, returns
|
||||
* 0
|
||||
*/
|
||||
uint8_t USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver)
|
||||
{
|
||||
return pDriver->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;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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);
|
||||
}
|
||||
/**@}*/
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -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 <HIDDKeyboard.h>
|
||||
#include <HIDDFunction.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
#include <USBRequests.h>
|
||||
#include <HIDDescriptors.h>
|
||||
#include <HIDRequests.h>
|
||||
#include <HIDReports.h>
|
||||
#include <HIDUsages.h>
|
||||
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <HIDDKeyboardDriver.h>
|
||||
#include <HIDDFunction.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
#include <USBRequests.h>
|
||||
#include <HIDDescriptors.h>
|
||||
#include <HIDRequests.h>
|
||||
#include <HIDReports.h>
|
||||
#include <HIDUsages.h>
|
||||
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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[0];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <HIDDKeyboard.h>
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <HIDDKeyboard.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Initializes a keyboard output report.
|
||||
* \param report Pointer to a HIDDKeyboardOutputReport instance.
|
||||
*/
|
||||
void HIDDKeyboardOutputReport_Initialize(HIDDKeyboardOutputReport *report)
|
||||
{
|
||||
report->numLockStatus = 0;
|
||||
report->capsLockStatus = 0;
|
||||
report->scrollLockStatus = 0;
|
||||
report->padding = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the current status of the num. lock LED according to the
|
||||
* given report.
|
||||
* \param report Pointer to a HIDDKeyboardOutputReport instance.
|
||||
* \return 1 if the num. lock LED is light on; otherwise 0.
|
||||
*/
|
||||
unsigned char HIDDKeyboardOutputReport_GetNumLockStatus(
|
||||
const HIDDKeyboardOutputReport *report)
|
||||
{
|
||||
return report->numLockStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the current status of the caps lock LED according to the
|
||||
* given report.
|
||||
* \param report Pointer to a HIDDKeyboardOutputReport instance.
|
||||
* \return 1 if the caps lock LED is light on; otherwise 0.
|
||||
*/
|
||||
unsigned char HIDDKeyboardOutputReport_GetCapsLockStatus(
|
||||
const HIDDKeyboardOutputReport *report)
|
||||
{
|
||||
return report->capsLockStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the current status of the scroll lock LED according to the
|
||||
* given report.
|
||||
* \param report Pointer to a HIDDKeyboardOutputReport instance.
|
||||
* \return 1 if the scroll lock LED is light on; otherwise 0.
|
||||
*/
|
||||
unsigned char HIDDKeyboardOutputReport_GetScrollLockStatus(
|
||||
const HIDDKeyboardOutputReport *report)
|
||||
{
|
||||
return report->scrollLockStatus;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <HIDDFunction.h>
|
||||
#include <HIDDMouseDriver.h>
|
||||
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal Defines
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/** Tag bit (Always 1) */
|
||||
#define HIDDMouse_TAG (1 << 3)
|
||||
/** Xsign bit */
|
||||
#define HIDDMouse_Xsign (1 << 4)
|
||||
/** Ysign bit */
|
||||
#define HIDDMouse_Ysign (1 << 5)
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal types
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <HIDDFunction.h>
|
||||
#include <USBDescriptors.h>
|
||||
#include <HIDDescriptors.h>
|
||||
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
#include "HIDDTransferDriver.h"
|
||||
#include <USBLib_Trace.h>
|
||||
|
||||
#include <USBRequests.h>
|
||||
#include <HIDDescriptors.h>
|
||||
#include <HIDDFunction.h>
|
||||
|
||||
#include <USBD_HAL.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* 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[0];
|
||||
}
|
||||
|
||||
/* 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[0];
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <MSDDriver.h>
|
||||
#include <MSDFunction.h>
|
||||
#include <USBLib_Trace.h>
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
@@ -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
|
||||
* \addtogroup usbd_msd
|
||||
*@{
|
||||
* Implements Massstorage Function for USB device.
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Includes
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <MSDescriptors.h>
|
||||
|
||||
#include <MSDDriver.h>
|
||||
#include <USBLib_Trace.h>
|
||||
#include <USBD.h>
|
||||
#include <USBD_HAL.h>
|
||||
#include <USBDDriver.h>
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* 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);
|
||||
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
@@ -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 <USBLib_Trace.h>
|
||||
#include <USBD.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Constants
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/** Default LUN block size in bytes */
|
||||
#define DEFAULT_LUN_BLOCK_SIZE 512
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Internal variables
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/** Inquiry data to return to the host for the Lun. */
|
||||
static SBCInquiryData inquiryData = {
|
||||
|
||||
SBC_DIRECT_ACCESS_BLOCK_DEVICE, /* Direct-access block device */
|
||||
SBC_PERIPHERAL_DEVICE_CONNECTED,/* Peripheral device is connected */
|
||||
0x00, /* Reserved bits */
|
||||
0x01, /* Media is removable */
|
||||
SBC_SPC_VERSION_4, /* SPC-4 supported */
|
||||
0x2, /* Response data format, must be 0x2 */
|
||||
0, /* Hierarchical addressing not supported */
|
||||
0, /* ACA not supported */
|
||||
0x0, /* Obsolete bits */
|
||||
sizeof(SBCInquiryData) - 5, /* Additional length */
|
||||
0, /* No embedded SCC */
|
||||
0, /* No access control coordinator */
|
||||
SBC_TPGS_NONE, /* No target port support group */
|
||||
0, /* Third-party copy not supported */
|
||||
0x0, /* Reserved bits */
|
||||
0, /* Protection information not supported */
|
||||
0x0, /* Obsolete bit */
|
||||
0, /* No embedded enclosure service component */
|
||||
0x0, /* ??? */
|
||||
0, /* Device is not multi-port */
|
||||
0x0, /* Obsolete bits */
|
||||
0x0, /* Unused feature */
|
||||
0x0, /* Unused features */
|
||||
0, /* Task management model not supported */
|
||||
0x0, /* ??? */
|
||||
{'A','T','M','E','L',' ',' ',' '},
|
||||
{'M','a','s','s',' ',
|
||||
'S','t','o','r','a','g','e',' ',
|
||||
'M','S','D'},
|
||||
{'0','.','0','1'},
|
||||
{'M','a','s','s',' ',
|
||||
'S','t','o','r','a','g','e',' ',
|
||||
'E','x','a','m','p','l','e'},
|
||||
0x00, /* Unused features */
|
||||
0x00, /* Reserved bits */
|
||||
{SBC_VERSION_DESCRIPTOR_SBC_3}, /* SBC-3 compliant device */
|
||||
{0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0} /* Reserved */
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Initializes a LUN instance. Must be invoked at least once even no
|
||||
* Media is linked.
|
||||
* \param lun Pointer to the MSDLun instance to initialize
|
||||
* \param media Media on which the LUN is constructed, set to 0 to
|
||||
* disconnect the Media or initialize an ejected LUN.
|
||||
* \param ioBuffer Pointer to a buffer used for read/write operation and
|
||||
* which must be blockSize bytes long.
|
||||
* \param ioBufferSize Size of the allocated IO buffer.
|
||||
* \param baseAddress Base address of the LUN in number of media blocks
|
||||
* \param size Total size of the LUN in number of media blocks
|
||||
* \param blockSize One block of the LUN in number of media blocks
|
||||
* \param protected The LUN area is forced to readonly even the media
|
||||
* is writable
|
||||
* \param dataMonitor Pointer to a Monitor Function to analyze the flow of
|
||||
* this LUN.
|
||||
*/
|
||||
void LUN_Init(MSDLun *lun,
|
||||
Media *media,
|
||||
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;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
After Width: | Height: | Size: 3.5 KiB |