Add svn:eol-style property to source files, so that the line endings are correctly converted to the target system's native end of line style.
This commit is contained in:
parent
e331b531c6
commit
071e02c6b6
839 changed files with 274562 additions and 274562 deletions
|
@ -1,89 +1,89 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_AUDIO_DRIVER
|
||||
#include "Audio.h"
|
||||
|
||||
void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_SetInterface:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
AudioInterfaceInfo->State.InterfaceEnabled = ((USB_ControlRequest.wValue & 0xFF) != 0);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* AudioInterfaceInfo)
|
||||
{
|
||||
memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State));
|
||||
|
||||
if (AudioInterfaceInfo->Config.DataINEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_ISOCHRONOUS,
|
||||
ENDPOINT_DIR_IN, AudioInterfaceInfo->Config.DataINEndpointSize,
|
||||
ENDPOINT_BANK_DOUBLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (AudioInterfaceInfo->Config.DataOUTEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_ISOCHRONOUS,
|
||||
ENDPOINT_DIR_OUT, AudioInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
ENDPOINT_BANK_DOUBLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_AUDIO_DRIVER
|
||||
#include "Audio.h"
|
||||
|
||||
void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_SetInterface:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
AudioInterfaceInfo->State.InterfaceEnabled = ((USB_ControlRequest.wValue & 0xFF) != 0);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* AudioInterfaceInfo)
|
||||
{
|
||||
memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State));
|
||||
|
||||
if (AudioInterfaceInfo->Config.DataINEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_ISOCHRONOUS,
|
||||
ENDPOINT_DIR_IN, AudioInterfaceInfo->Config.DataINEndpointSize,
|
||||
ENDPOINT_BANK_DOUBLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (AudioInterfaceInfo->Config.DataOUTEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(AudioInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_ISOCHRONOUS,
|
||||
ENDPOINT_DIR_OUT, AudioInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
ENDPOINT_BANK_DOUBLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,319 +1,319 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB Audio Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB Audio Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/Audio.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassAudio
|
||||
* @defgroup Group_USBClassAudioDevice Audio Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/Audio.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the Audio USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_CLASS_DEVICE_H_
|
||||
#define _AUDIO_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/Audio.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_AUDIO_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/Audio.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief Audio Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each Audio interface
|
||||
* within the user application, and passed to each of the Audio class driver functions as the
|
||||
* AudioInterfaceInfo parameter. This stores each Audio interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this
|
||||
* structure controls
|
||||
*/
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming Audio Streaming data, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the incoming Audio Streaming data endpoint, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing Audio Streaming data, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing Audio Streaming data endpoint, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool InterfaceEnabled; /**< Set and cleared by the class driver to indicate if the host has enabled the streaming endpoints
|
||||
* of the Audio Streaming interface.
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_Audio_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given Audio interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the
|
||||
* given Audio interface is selected.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given Audio class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*/
|
||||
void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Audio class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*/
|
||||
static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo);
|
||||
static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
(void)AudioInterfaceInfo;
|
||||
}
|
||||
|
||||
/** Determines if the given audio interface is ready for a sample to be read from it, and selects the streaming
|
||||
* OUT endpoint ready for reading.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the given Audio interface has a sample to be read, false otherwise
|
||||
*/
|
||||
static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled))
|
||||
return false;
|
||||
|
||||
Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
return Endpoint_IsOUTReceived();
|
||||
}
|
||||
|
||||
/** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects
|
||||
* the streaming IN endpoint ready for writing.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the given Audio interface is ready to accept the next sample, false otherwise
|
||||
*/
|
||||
static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled))
|
||||
return false;
|
||||
|
||||
Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataINEndpointNumber);
|
||||
return Endpoint_IsINReady();
|
||||
}
|
||||
|
||||
/** Reads the next 8-bit audio sample from the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsSampleReceived() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Signed 8-bit audio sample from the audio interface
|
||||
*/
|
||||
static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_ALWAYS_INLINE;
|
||||
static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
int8_t Sample;
|
||||
|
||||
(void)AudioInterfaceInfo;
|
||||
|
||||
Sample = Endpoint_Read_Byte();
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return Sample;
|
||||
}
|
||||
|
||||
/** Reads the next 16-bit audio sample from the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsSampleReceived() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Signed 16-bit audio sample from the audio interface
|
||||
*/
|
||||
static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_ALWAYS_INLINE;
|
||||
static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
int16_t Sample;
|
||||
|
||||
(void)AudioInterfaceInfo;
|
||||
|
||||
Sample = (int16_t)Endpoint_Read_Word_LE();
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return Sample;
|
||||
}
|
||||
|
||||
/** Reads the next 24-bit audio sample from the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsSampleReceived() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Signed 24-bit audio sample from the audio interface
|
||||
*/
|
||||
static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_ALWAYS_INLINE;
|
||||
static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
int32_t Sample;
|
||||
|
||||
(void)AudioInterfaceInfo;
|
||||
|
||||
Sample = (((uint32_t)Endpoint_Read_Byte() << 16) | Endpoint_Read_Word_LE());
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return Sample;
|
||||
}
|
||||
|
||||
/** Writes the next 8-bit audio sample to the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsReadyForNextSample() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
* \param[in] Sample Signed 8-bit audio sample
|
||||
*/
|
||||
static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int8_t Sample) ATTR_ALWAYS_INLINE;
|
||||
static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int8_t Sample)
|
||||
{
|
||||
Endpoint_Write_Byte(Sample);
|
||||
|
||||
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize)
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
/** Writes the next 16-bit audio sample to the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsReadyForNextSample() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
* \param[in] Sample Signed 16-bit audio sample
|
||||
*/
|
||||
static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int16_t Sample) ATTR_ALWAYS_INLINE;
|
||||
static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int16_t Sample)
|
||||
{
|
||||
Endpoint_Write_Word_LE(Sample);
|
||||
|
||||
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize)
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
/** Writes the next 24-bit audio sample to the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsReadyForNextSample() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
* \param[in] Sample Signed 24-bit audio sample
|
||||
*/
|
||||
static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int32_t Sample) ATTR_ALWAYS_INLINE;
|
||||
static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int32_t Sample)
|
||||
{
|
||||
Endpoint_Write_Byte(Sample >> 16);
|
||||
Endpoint_Write_Word_LE(Sample);
|
||||
|
||||
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize)
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB Audio Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB Audio Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/Audio.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassAudio
|
||||
* @defgroup Group_USBClassAudioDevice Audio Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/Audio.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the Audio USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_CLASS_DEVICE_H_
|
||||
#define _AUDIO_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/Audio.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_AUDIO_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/Audio.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief Audio Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each Audio interface
|
||||
* within the user application, and passed to each of the Audio class driver functions as the
|
||||
* AudioInterfaceInfo parameter. This stores each Audio interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this
|
||||
* structure controls
|
||||
*/
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming Audio Streaming data, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the incoming Audio Streaming data endpoint, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing Audio Streaming data, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing Audio Streaming data endpoint, if available
|
||||
* (zero if unused)
|
||||
*/
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool InterfaceEnabled; /**< Set and cleared by the class driver to indicate if the host has enabled the streaming endpoints
|
||||
* of the Audio Streaming interface.
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_Audio_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given Audio interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the
|
||||
* given Audio interface is selected.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given Audio class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*/
|
||||
void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Audio class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*/
|
||||
static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo);
|
||||
static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
(void)AudioInterfaceInfo;
|
||||
}
|
||||
|
||||
/** Determines if the given audio interface is ready for a sample to be read from it, and selects the streaming
|
||||
* OUT endpoint ready for reading.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the given Audio interface has a sample to be read, false otherwise
|
||||
*/
|
||||
static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled))
|
||||
return false;
|
||||
|
||||
Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
return Endpoint_IsOUTReceived();
|
||||
}
|
||||
|
||||
/** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects
|
||||
* the streaming IN endpoint ready for writing.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the given Audio interface is ready to accept the next sample, false otherwise
|
||||
*/
|
||||
static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled))
|
||||
return false;
|
||||
|
||||
Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataINEndpointNumber);
|
||||
return Endpoint_IsINReady();
|
||||
}
|
||||
|
||||
/** Reads the next 8-bit audio sample from the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsSampleReceived() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Signed 8-bit audio sample from the audio interface
|
||||
*/
|
||||
static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_ALWAYS_INLINE;
|
||||
static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
int8_t Sample;
|
||||
|
||||
(void)AudioInterfaceInfo;
|
||||
|
||||
Sample = Endpoint_Read_Byte();
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return Sample;
|
||||
}
|
||||
|
||||
/** Reads the next 16-bit audio sample from the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsSampleReceived() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Signed 16-bit audio sample from the audio interface
|
||||
*/
|
||||
static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_ALWAYS_INLINE;
|
||||
static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
int16_t Sample;
|
||||
|
||||
(void)AudioInterfaceInfo;
|
||||
|
||||
Sample = (int16_t)Endpoint_Read_Word_LE();
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return Sample;
|
||||
}
|
||||
|
||||
/** Reads the next 24-bit audio sample from the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsSampleReceived() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
*
|
||||
* \return Signed 24-bit audio sample from the audio interface
|
||||
*/
|
||||
static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_ALWAYS_INLINE;
|
||||
static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
|
||||
{
|
||||
int32_t Sample;
|
||||
|
||||
(void)AudioInterfaceInfo;
|
||||
|
||||
Sample = (((uint32_t)Endpoint_Read_Byte() << 16) | Endpoint_Read_Word_LE());
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return Sample;
|
||||
}
|
||||
|
||||
/** Writes the next 8-bit audio sample to the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsReadyForNextSample() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
* \param[in] Sample Signed 8-bit audio sample
|
||||
*/
|
||||
static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int8_t Sample) ATTR_ALWAYS_INLINE;
|
||||
static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int8_t Sample)
|
||||
{
|
||||
Endpoint_Write_Byte(Sample);
|
||||
|
||||
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize)
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
/** Writes the next 16-bit audio sample to the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsReadyForNextSample() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
* \param[in] Sample Signed 16-bit audio sample
|
||||
*/
|
||||
static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int16_t Sample) ATTR_ALWAYS_INLINE;
|
||||
static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int16_t Sample)
|
||||
{
|
||||
Endpoint_Write_Word_LE(Sample);
|
||||
|
||||
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize)
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
/** Writes the next 24-bit audio sample to the current audio interface.
|
||||
*
|
||||
* \note This should be preceded immediately by a call to the USB_Audio_IsReadyForNextSample() function to ensure that
|
||||
* the correct endpoint is selected and ready for data.
|
||||
*
|
||||
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state
|
||||
* \param[in] Sample Signed 24-bit audio sample
|
||||
*/
|
||||
static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int32_t Sample) ATTR_ALWAYS_INLINE;
|
||||
static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
|
||||
const int32_t Sample)
|
||||
{
|
||||
Endpoint_Write_Byte(Sample >> 16);
|
||||
Endpoint_Write_Word_LE(Sample);
|
||||
|
||||
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize)
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,299 +1,299 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_CDC_CLASS_DEVICE_C
|
||||
#define __INCLUDE_FROM_CDC_DRIVER
|
||||
#include "CDC.h"
|
||||
|
||||
void CDC_Device_Event_Stub(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_GetLineEncoding:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
Endpoint_Write_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding));
|
||||
Endpoint_ClearOUT();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetLineEncoding:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
Endpoint_Read_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding));
|
||||
EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetControlLineState:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
|
||||
EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SendBreak:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, CDCInterfaceInfo->Config.DataINEndpointSize,
|
||||
CDCInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, CDCInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, CDCInterfaceInfo->Config.NotificationEndpointSize,
|
||||
CDCInterfaceInfo->Config.NotificationEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsOUTReceived() && !(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
CDC_Device_Flush(CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
|
||||
return Endpoint_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
{
|
||||
Endpoint_ClearIN();
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Endpoint_Write_Byte(Data);
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
|
||||
bool BankFull = !(Endpoint_IsReadWriteAllowed());
|
||||
|
||||
Endpoint_ClearIN();
|
||||
|
||||
if (BankFull)
|
||||
{
|
||||
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return 0;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsOUTReceived())
|
||||
{
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
{
|
||||
Endpoint_ClearOUT();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Endpoint_BytesInEndpoint();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return 0;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
uint8_t DataByte = Endpoint_Read_Byte();
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return DataByte;
|
||||
}
|
||||
|
||||
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber);
|
||||
|
||||
USB_Request_Header_t Notification = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = NOTIF_SerialState,
|
||||
.wValue = 0,
|
||||
.wIndex = 0,
|
||||
.wLength = sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
|
||||
};
|
||||
|
||||
Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
|
||||
sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
|
||||
NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
static int CDC_Device_putchar(char c, FILE* Stream)
|
||||
{
|
||||
return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
|
||||
}
|
||||
|
||||
static int CDC_Device_getchar(FILE* Stream)
|
||||
{
|
||||
if (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))))
|
||||
return _FDEV_EOF;
|
||||
|
||||
return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
static int CDC_Device_getchar_Blocking(FILE* Stream)
|
||||
{
|
||||
while (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))))
|
||||
{
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return _FDEV_EOF;
|
||||
|
||||
CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
|
||||
USB_USBTask();
|
||||
}
|
||||
|
||||
return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_CDC_CLASS_DEVICE_C
|
||||
#define __INCLUDE_FROM_CDC_DRIVER
|
||||
#include "CDC.h"
|
||||
|
||||
void CDC_Device_Event_Stub(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_GetLineEncoding:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
Endpoint_Write_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding));
|
||||
Endpoint_ClearOUT();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetLineEncoding:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
Endpoint_Read_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding));
|
||||
EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetControlLineState:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
|
||||
EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SendBreak:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, CDCInterfaceInfo->Config.DataINEndpointSize,
|
||||
CDCInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, CDCInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, CDCInterfaceInfo->Config.NotificationEndpointSize,
|
||||
CDCInterfaceInfo->Config.NotificationEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsOUTReceived() && !(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
CDC_Device_Flush(CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
|
||||
return Endpoint_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
{
|
||||
Endpoint_ClearIN();
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Endpoint_Write_Byte(Data);
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
|
||||
bool BankFull = !(Endpoint_IsReadWriteAllowed());
|
||||
|
||||
Endpoint_ClearIN();
|
||||
|
||||
if (BankFull)
|
||||
{
|
||||
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return 0;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsOUTReceived())
|
||||
{
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
{
|
||||
Endpoint_ClearOUT();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Endpoint_BytesInEndpoint();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return 0;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
uint8_t DataByte = Endpoint_Read_Byte();
|
||||
|
||||
if (!(Endpoint_BytesInEndpoint()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return DataByte;
|
||||
}
|
||||
|
||||
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpointNumber);
|
||||
|
||||
USB_Request_Header_t Notification = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = NOTIF_SerialState,
|
||||
.wValue = 0,
|
||||
.wIndex = 0,
|
||||
.wLength = sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
|
||||
};
|
||||
|
||||
Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
|
||||
sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
|
||||
NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
static int CDC_Device_putchar(char c, FILE* Stream)
|
||||
{
|
||||
return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
|
||||
}
|
||||
|
||||
static int CDC_Device_getchar(FILE* Stream)
|
||||
{
|
||||
if (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))))
|
||||
return _FDEV_EOF;
|
||||
|
||||
return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
static int CDC_Device_getchar_Blocking(FILE* Stream)
|
||||
{
|
||||
while (!(CDC_Device_BytesReceived((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))))
|
||||
{
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return _FDEV_EOF;
|
||||
|
||||
CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
|
||||
USB_USBTask();
|
||||
}
|
||||
|
||||
return CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,331 +1,331 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/CDC.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassCDC
|
||||
* @defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/CDC.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the CDC USB Class driver.
|
||||
*
|
||||
* \note There are several major drawbacks to the CDC-ACM standard USB class, however
|
||||
* it is very standardized and thus usually available as a built-in driver on
|
||||
* most platforms, and so is a better choice than a proprietary serial class.
|
||||
*
|
||||
* One major issue with CDC-ACM is that it requires two Interface descriptors,
|
||||
* which will upset most hosts when part of a multi-function "Composite" USB
|
||||
* device, as each interface will be loaded into a separate driver instance. To
|
||||
* conbat this, you should use the "Interface Association Descriptor" addendum to
|
||||
* the USB standard which is available on most OSes when creating Composite devices.
|
||||
*
|
||||
* Another major oversight is that there is no mechanism for the host to notify the
|
||||
* device that there is a data sink on the host side ready to accept data. This
|
||||
* means that the device may try to send data while the host isn't listening, causing
|
||||
* lengthy blocking timeouts in the transmission routines. To combat this, it is
|
||||
* recommended that the virtual serial line DTR (Data Terminal Ready) be used where
|
||||
* possible to determine if a host application is ready for data.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CDC_CLASS_DEVICE_H_
|
||||
#define _CDC_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/CDC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_CDC_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/CDC.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief CDC Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each CDC interface
|
||||
* within the user application, and passed to each of the CDC class driver functions as the
|
||||
* CDCInterfaceInfo parameter. This stores each CDC interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the CDC interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the CDC interface's OUT data endpoint should use double banking */
|
||||
|
||||
uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */
|
||||
uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */
|
||||
bool NotificationEndpointDoubleBank; /** Indicates if the CDC interface's notification endpoint should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_*
|
||||
* masks. This value is updated each time \ref CDC_Device_USBTask() is called.
|
||||
*/
|
||||
uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of CDC_CONTROL_LINE_IN_*
|
||||
* masks - to notify the host of changes to these values, call the
|
||||
* \ref CDC_Device_SendControlLineStateChange() function.
|
||||
*/
|
||||
} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
|
||||
uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
|
||||
* CDCDevice_CDC_LineCodingFormats_t enum
|
||||
*/
|
||||
uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
|
||||
* CDCDevice_LineCodingParity_t enum
|
||||
*/
|
||||
uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
|
||||
} LineEncoding; /** Line encoding used in the virtual serial port, for the device's information. This is generally
|
||||
* only used if the virtual serial port data is to be reconstructed on a physical UART.
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_CDC_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given CDC interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing
|
||||
* the given CDC interface is selected.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given CDC class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given CDC class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** CDC class driver event for a line encoding change on a CDC interface. This event fires each time the host requests a
|
||||
* line encoding change (containing the serial parity, baud and other configuration information) and may be hooked in the
|
||||
* user program by declaring a handler function with the same name and parameters listed here. The new line encoding
|
||||
* settings are available in the LineEncoding structure inside the CDC interface structure passed as a parameter.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** CDC class driver event for a control line state change on a CDC interface. This event fires each time the host requests a
|
||||
* control line state change (containing the virtual serial control line states, such as DTR) and may be hooked in the
|
||||
* user program by declaring a handler function with the same name and parameters listed here. The new control line states
|
||||
* are available in the ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as
|
||||
* a mask of CDC_CONTROL_LINE_OUT_* masks.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** CDC class driver event for a send break request sent to the device from the host. This is generally used to seperate
|
||||
* data or to indicate a special condition to the receiving device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in] Duration Duration of the break that has been sent by the host, in milliseconds
|
||||
*/
|
||||
void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a given string to the attached USB host, if connected. If a host is not connected when the function is called, the
|
||||
* string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the
|
||||
* \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single endpoint packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in] Data Pointer to the string to send to the host
|
||||
* \param[in] Length Size in bytes of the string to send to the host
|
||||
*
|
||||
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the
|
||||
* byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the
|
||||
* \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single endpoint packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in] Data Byte of data to send to the host
|
||||
*
|
||||
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Determines the number of bytes received by the CDC interface from the host, waiting to be read.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return Total number of buffered bytes received from the host
|
||||
*/
|
||||
uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Reads a byte of data from the host. If no data is waiting to be read of if a USB host is not connected, the function
|
||||
* returns 0. The \ref CDC_Device_BytesReceived() function should be queried before data is received to ensure that no data
|
||||
* underflow occurs.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return Next received byte from the host, or 0 if no data received
|
||||
*/
|
||||
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a Serial Control Line State Change notification to the host. This should be called when the virtual serial
|
||||
* control lines (DCD, DSR, etc.) have changed states, or to give BREAK notifications to the host. Line states persist
|
||||
* until they are cleared via a second notification. This should be called each time the CDC class driver's
|
||||
* ControlLineStates.DeviceToHost value is updated to push the new states to the USB host.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Creates a standard characer stream for the given CDC Device instance so that it can be used with all the regular
|
||||
* functions in the avr-libc <stdio.h> library that accept a FILE stream as a destination (e.g. fprintf). The created
|
||||
* stream is bidirectional and can be used for both input and output functions.
|
||||
*
|
||||
* Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
|
||||
* fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
|
||||
* be used when the read data is processed byte-per-bye (via getc()) or when the user application will implement its own
|
||||
* line buffering.
|
||||
*
|
||||
* \note The created stream can be given as stdout if desired to direct the standard output from all <stdio.h> functions
|
||||
* to the given CDC interface.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/** Identical to CDC_Device_CreateStream(), except that reads are blocking until the calling stream function terminates
|
||||
* the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_CDC_CLASS_DEVICE_C)
|
||||
static int CDC_Device_putchar(char c, FILE* Stream);
|
||||
static int CDC_Device_getchar(FILE* Stream);
|
||||
static int CDC_Device_getchar_Blocking(FILE* Stream);
|
||||
|
||||
void CDC_Device_Event_Stub(void);
|
||||
void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
|
||||
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
|
||||
void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, uint8_t Duration)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/CDC.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassCDC
|
||||
* @defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/CDC.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the CDC USB Class driver.
|
||||
*
|
||||
* \note There are several major drawbacks to the CDC-ACM standard USB class, however
|
||||
* it is very standardized and thus usually available as a built-in driver on
|
||||
* most platforms, and so is a better choice than a proprietary serial class.
|
||||
*
|
||||
* One major issue with CDC-ACM is that it requires two Interface descriptors,
|
||||
* which will upset most hosts when part of a multi-function "Composite" USB
|
||||
* device, as each interface will be loaded into a separate driver instance. To
|
||||
* conbat this, you should use the "Interface Association Descriptor" addendum to
|
||||
* the USB standard which is available on most OSes when creating Composite devices.
|
||||
*
|
||||
* Another major oversight is that there is no mechanism for the host to notify the
|
||||
* device that there is a data sink on the host side ready to accept data. This
|
||||
* means that the device may try to send data while the host isn't listening, causing
|
||||
* lengthy blocking timeouts in the transmission routines. To combat this, it is
|
||||
* recommended that the virtual serial line DTR (Data Terminal Ready) be used where
|
||||
* possible to determine if a host application is ready for data.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CDC_CLASS_DEVICE_H_
|
||||
#define _CDC_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/CDC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_CDC_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/CDC.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief CDC Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each CDC interface
|
||||
* within the user application, and passed to each of the CDC class driver functions as the
|
||||
* CDCInterfaceInfo parameter. This stores each CDC interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the CDC interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the CDC interface's OUT data endpoint should use double banking */
|
||||
|
||||
uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */
|
||||
uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */
|
||||
bool NotificationEndpointDoubleBank; /** Indicates if the CDC interface's notification endpoint should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_*
|
||||
* masks. This value is updated each time \ref CDC_Device_USBTask() is called.
|
||||
*/
|
||||
uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of CDC_CONTROL_LINE_IN_*
|
||||
* masks - to notify the host of changes to these values, call the
|
||||
* \ref CDC_Device_SendControlLineStateChange() function.
|
||||
*/
|
||||
} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
|
||||
uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
|
||||
* CDCDevice_CDC_LineCodingFormats_t enum
|
||||
*/
|
||||
uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
|
||||
* CDCDevice_LineCodingParity_t enum
|
||||
*/
|
||||
uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
|
||||
} LineEncoding; /** Line encoding used in the virtual serial port, for the device's information. This is generally
|
||||
* only used if the virtual serial port data is to be reconstructed on a physical UART.
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_CDC_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given CDC interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing
|
||||
* the given CDC interface is selected.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given CDC class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given CDC class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** CDC class driver event for a line encoding change on a CDC interface. This event fires each time the host requests a
|
||||
* line encoding change (containing the serial parity, baud and other configuration information) and may be hooked in the
|
||||
* user program by declaring a handler function with the same name and parameters listed here. The new line encoding
|
||||
* settings are available in the LineEncoding structure inside the CDC interface structure passed as a parameter.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** CDC class driver event for a control line state change on a CDC interface. This event fires each time the host requests a
|
||||
* control line state change (containing the virtual serial control line states, such as DTR) and may be hooked in the
|
||||
* user program by declaring a handler function with the same name and parameters listed here. The new control line states
|
||||
* are available in the ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as
|
||||
* a mask of CDC_CONTROL_LINE_OUT_* masks.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** CDC class driver event for a send break request sent to the device from the host. This is generally used to seperate
|
||||
* data or to indicate a special condition to the receiving device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in] Duration Duration of the break that has been sent by the host, in milliseconds
|
||||
*/
|
||||
void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a given string to the attached USB host, if connected. If a host is not connected when the function is called, the
|
||||
* string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the
|
||||
* \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single endpoint packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in] Data Pointer to the string to send to the host
|
||||
* \param[in] Length Size in bytes of the string to send to the host
|
||||
*
|
||||
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the
|
||||
* byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the
|
||||
* \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single endpoint packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in] Data Byte of data to send to the host
|
||||
*
|
||||
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Determines the number of bytes received by the CDC interface from the host, waiting to be read.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return Total number of buffered bytes received from the host
|
||||
*/
|
||||
uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Reads a byte of data from the host. If no data is waiting to be read of if a USB host is not connected, the function
|
||||
* returns 0. The \ref CDC_Device_BytesReceived() function should be queried before data is received to ensure that no data
|
||||
* underflow occurs.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return Next received byte from the host, or 0 if no data received
|
||||
*/
|
||||
uint8_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*
|
||||
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a Serial Control Line State Change notification to the host. This should be called when the virtual serial
|
||||
* control lines (DCD, DSR, etc.) have changed states, or to give BREAK notifications to the host. Line states persist
|
||||
* until they are cleared via a second notification. This should be called each time the CDC class driver's
|
||||
* ControlLineStates.DeviceToHost value is updated to push the new states to the USB host.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
*/
|
||||
void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Creates a standard characer stream for the given CDC Device instance so that it can be used with all the regular
|
||||
* functions in the avr-libc <stdio.h> library that accept a FILE stream as a destination (e.g. fprintf). The created
|
||||
* stream is bidirectional and can be used for both input and output functions.
|
||||
*
|
||||
* Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
|
||||
* fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
|
||||
* be used when the read data is processed byte-per-bye (via getc()) or when the user application will implement its own
|
||||
* line buffering.
|
||||
*
|
||||
* \note The created stream can be given as stdout if desired to direct the standard output from all <stdio.h> functions
|
||||
* to the given CDC interface.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/** Identical to CDC_Device_CreateStream(), except that reads are blocking until the calling stream function terminates
|
||||
* the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_CDC_CLASS_DEVICE_C)
|
||||
static int CDC_Device_putchar(char c, FILE* Stream);
|
||||
static int CDC_Device_getchar(FILE* Stream);
|
||||
static int CDC_Device_getchar_Blocking(FILE* Stream);
|
||||
|
||||
void CDC_Device_Event_Stub(void);
|
||||
void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
|
||||
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
|
||||
void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, uint8_t Duration)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,194 +1,194 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_HID_DRIVER
|
||||
#include "HID.h"
|
||||
|
||||
void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_GetReport:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
uint16_t ReportINSize = 0;
|
||||
uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
|
||||
uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1;
|
||||
uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
|
||||
|
||||
memset(ReportINData, 0, sizeof(ReportINData));
|
||||
|
||||
CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, ReportType,
|
||||
HIDInterfaceInfo->Config.PrevReportINBuffer, &ReportINSize);
|
||||
|
||||
if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
|
||||
memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, HIDInterfaceInfo->Config.PrevReportINBufferSize);
|
||||
|
||||
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
|
||||
Endpoint_Write_Control_Stream_LE(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize);
|
||||
Endpoint_ClearOUT();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetReport:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
uint16_t ReportOUTSize = USB_ControlRequest.wLength;
|
||||
uint8_t ReportOUTData[ReportOUTSize];
|
||||
uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
|
||||
|
||||
Endpoint_Read_Control_Stream_LE(ReportOUTData, ReportOUTSize);
|
||||
CALLBACK_HID_Device_ProcessHIDReport(HIDInterfaceInfo, ReportID, ReportOUTData, ReportOUTSize);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetProtocol:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Write_Byte(HIDInterfaceInfo->State.UsingReportProtocol);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetProtocol:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
HIDInterfaceInfo->State.UsingReportProtocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetIdle:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetIdle:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Write_Byte(HIDInterfaceInfo->State.IdleCount >> 2);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
|
||||
{
|
||||
memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
|
||||
HIDInterfaceInfo->State.UsingReportProtocol = true;
|
||||
HIDInterfaceInfo->State.IdleCount = 500;
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, HIDInterfaceInfo->Config.ReportINEndpointSize,
|
||||
HIDInterfaceInfo->Config.ReportINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);
|
||||
|
||||
if (Endpoint_IsReadWriteAllowed())
|
||||
{
|
||||
uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
|
||||
uint8_t ReportID = 0;
|
||||
uint16_t ReportINSize = 0;
|
||||
|
||||
memset(ReportINData, 0, sizeof(ReportINData));
|
||||
|
||||
bool ForceSend = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, REPORT_ITEM_TYPE_In,
|
||||
ReportINData, &ReportINSize);
|
||||
bool StatesChanged = false;
|
||||
bool IdlePeriodElapsed = (HIDInterfaceInfo->State.IdleCount && !(HIDInterfaceInfo->State.IdleMSRemaining));
|
||||
|
||||
if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
|
||||
{
|
||||
StatesChanged = (memcmp(ReportINData, HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize) != 0);
|
||||
memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, HIDInterfaceInfo->Config.PrevReportINBufferSize);
|
||||
}
|
||||
|
||||
if (ReportINSize && (ForceSend || StatesChanged || IdlePeriodElapsed))
|
||||
{
|
||||
HIDInterfaceInfo->State.IdleMSRemaining = HIDInterfaceInfo->State.IdleCount;
|
||||
|
||||
Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);
|
||||
|
||||
if (ReportID)
|
||||
Endpoint_Write_Byte(ReportID);
|
||||
|
||||
Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NO_STREAM_CALLBACK);
|
||||
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_HID_DRIVER
|
||||
#include "HID.h"
|
||||
|
||||
void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_GetReport:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
uint16_t ReportINSize = 0;
|
||||
uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
|
||||
uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1;
|
||||
uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
|
||||
|
||||
memset(ReportINData, 0, sizeof(ReportINData));
|
||||
|
||||
CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, ReportType,
|
||||
HIDInterfaceInfo->Config.PrevReportINBuffer, &ReportINSize);
|
||||
|
||||
if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
|
||||
memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, HIDInterfaceInfo->Config.PrevReportINBufferSize);
|
||||
|
||||
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
|
||||
Endpoint_Write_Control_Stream_LE(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize);
|
||||
Endpoint_ClearOUT();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetReport:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
uint16_t ReportOUTSize = USB_ControlRequest.wLength;
|
||||
uint8_t ReportOUTData[ReportOUTSize];
|
||||
uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
|
||||
|
||||
Endpoint_Read_Control_Stream_LE(ReportOUTData, ReportOUTSize);
|
||||
CALLBACK_HID_Device_ProcessHIDReport(HIDInterfaceInfo, ReportID, ReportOUTData, ReportOUTSize);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetProtocol:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Write_Byte(HIDInterfaceInfo->State.UsingReportProtocol);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetProtocol:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
HIDInterfaceInfo->State.UsingReportProtocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetIdle:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetIdle:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Write_Byte(HIDInterfaceInfo->State.IdleCount >> 2);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
|
||||
{
|
||||
memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
|
||||
HIDInterfaceInfo->State.UsingReportProtocol = true;
|
||||
HIDInterfaceInfo->State.IdleCount = 500;
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, HIDInterfaceInfo->Config.ReportINEndpointSize,
|
||||
HIDInterfaceInfo->Config.ReportINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);
|
||||
|
||||
if (Endpoint_IsReadWriteAllowed())
|
||||
{
|
||||
uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
|
||||
uint8_t ReportID = 0;
|
||||
uint16_t ReportINSize = 0;
|
||||
|
||||
memset(ReportINData, 0, sizeof(ReportINData));
|
||||
|
||||
bool ForceSend = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, REPORT_ITEM_TYPE_In,
|
||||
ReportINData, &ReportINSize);
|
||||
bool StatesChanged = false;
|
||||
bool IdlePeriodElapsed = (HIDInterfaceInfo->State.IdleCount && !(HIDInterfaceInfo->State.IdleMSRemaining));
|
||||
|
||||
if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
|
||||
{
|
||||
StatesChanged = (memcmp(ReportINData, HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize) != 0);
|
||||
memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, HIDInterfaceInfo->Config.PrevReportINBufferSize);
|
||||
}
|
||||
|
||||
if (ReportINSize && (ForceSend || StatesChanged || IdlePeriodElapsed))
|
||||
{
|
||||
HIDInterfaceInfo->State.IdleMSRemaining = HIDInterfaceInfo->State.IdleCount;
|
||||
|
||||
Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber);
|
||||
|
||||
if (ReportID)
|
||||
Endpoint_Write_Byte(ReportID);
|
||||
|
||||
Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NO_STREAM_CALLBACK);
|
||||
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,206 +1,206 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/HID.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassHID
|
||||
* @defgroup Group_USBClassHIDDevice HID Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/HID.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the HID USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HID_CLASS_DEVICE_H_
|
||||
#define _HID_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/HID.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_HID_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/HID.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief HID Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each HID interface
|
||||
* within the user application, and passed to each of the HID class driver functions as the
|
||||
* HIDInterfaceInfo parameter. This stores each HID interface's configuration and state information.
|
||||
*
|
||||
* \note Due to technical limitations, the HID device class driver does not utilize a separate OUT
|
||||
* endpoint for host->device communications. Instead, the host->device data (if any) is sent to
|
||||
* the device via the control endpoint.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device */
|
||||
|
||||
uint8_t ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint */
|
||||
uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint */
|
||||
bool ReportINEndpointDoubleBank; /** Indicates if the HID interface's IN report endpoint should use double banking */
|
||||
|
||||
void* PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be
|
||||
* stored by the driver, for comparison purposes to detect report changes that
|
||||
* must be sent immediately to the host. This should point to a buffer big enough
|
||||
* to hold the largest HID input report sent from the HID interface. If this is set
|
||||
* to NULL, it is up to the user to force transfers when needed in the
|
||||
* \ref CALLBACK_HID_Device_CreateHIDReport() callback function.
|
||||
*
|
||||
* \note Due to the single buffer, the internal driver can only correctly compare
|
||||
* subsequent reports with identical report IDs. In multiple report devices,
|
||||
* this buffer should be set to NULL and the decision to send reports made
|
||||
* by the user application instead.
|
||||
*/
|
||||
uint8_t PrevReportINBufferSize; /**< Size in bytes of the given input report buffer. This is used to create a
|
||||
* second buffer of the same size within the driver so that subsequent reports
|
||||
* can be compared. If the user app is to determine when reports are to be sent
|
||||
* exclusively (i.e. \ref PrevReportINBuffer is NULL) this value must still be
|
||||
* set to the size of the largest report the device can issue to the host.
|
||||
*/
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode */
|
||||
uint16_t IdleCount; /**< Report idle period, in milliseconds, set by the host */
|
||||
uint16_t IdleMSRemaining; /**< Total number of milliseconds remaining before the idle period elapsed - this
|
||||
* should be decremented by the user application if non-zero each millisecond */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_HID_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given HID interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given HID interface is selected.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given HID class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*/
|
||||
void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given HID class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*/
|
||||
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** HID class driver callback for the user creation of a HID IN report. This callback may fire in response to either
|
||||
* HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback the
|
||||
* user is responsible for the creation of the next HID input report to be sent to the host.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
* \param[in,out] ReportID If preset to a non-zero value, this is the report ID being requested by the host. If zero, this should
|
||||
* be set to the report ID of the generated HID input report (if any). If multiple reports are not sent via the
|
||||
* given HID interface, this parameter should be ignored.
|
||||
* \param[in] ReportType Type of HID report to generate, either \ref REPORT_ITEM_TYPE_In or \ref REPORT_ITEM_TYPE_Feature
|
||||
* \param[out] ReportData Pointer to a buffer where the generated HID report should be stored
|
||||
* \param[out] ReportSize Number of bytes in the generated input report, or zero if no report is to be sent
|
||||
*
|
||||
* \return Boolean true to force the sending of the report even if it is identical to the previous report and still within
|
||||
* the idle period (useful for devices which report relative movement), false otherwise
|
||||
*/
|
||||
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, uint8_t* const ReportID,
|
||||
const uint8_t ReportType, void* ReportData, uint16_t* ReportSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(4) ATTR_NON_NULL_PTR_ARG(5);
|
||||
|
||||
/** HID class driver callback for the user processing of a received HID OUT report. This callback may fire in response to
|
||||
* either HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback
|
||||
* the user is responsible for the processing of the received HID output report from the host.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
* \param[in] ReportID Report ID of the received output report. If multiple reports are not received via the given HID
|
||||
* interface, this parameter should be ignored.
|
||||
* \param[in] ReportData Pointer to a buffer where the received HID report is stored.
|
||||
* \param[in] ReportSize Size in bytes of the received report from the host.
|
||||
*/
|
||||
void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, const uint8_t ReportID,
|
||||
const void* ReportData, const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** Indicates that a millisecond of idle time has elapsed on the given HID interface, and the interface's idle count should be
|
||||
* decremented. This should be called once per millisecond so that hardware key-repeats function correctly. It is recommended
|
||||
* that this be called by the \ref EVENT_USB_Device_StartOfFrame() event, once SOF events have been enabled via
|
||||
* \ref USB_Device_EnableSOFEvents();.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*/
|
||||
static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo);
|
||||
static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo)
|
||||
{
|
||||
if (HIDInterfaceInfo->State.IdleMSRemaining)
|
||||
HIDInterfaceInfo->State.IdleMSRemaining--;
|
||||
}
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/HID.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassHID
|
||||
* @defgroup Group_USBClassHIDDevice HID Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/HID.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the HID USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HID_CLASS_DEVICE_H_
|
||||
#define _HID_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/HID.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_HID_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/HID.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief HID Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each HID interface
|
||||
* within the user application, and passed to each of the HID class driver functions as the
|
||||
* HIDInterfaceInfo parameter. This stores each HID interface's configuration and state information.
|
||||
*
|
||||
* \note Due to technical limitations, the HID device class driver does not utilize a separate OUT
|
||||
* endpoint for host->device communications. Instead, the host->device data (if any) is sent to
|
||||
* the device via the control endpoint.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device */
|
||||
|
||||
uint8_t ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint */
|
||||
uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint */
|
||||
bool ReportINEndpointDoubleBank; /** Indicates if the HID interface's IN report endpoint should use double banking */
|
||||
|
||||
void* PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be
|
||||
* stored by the driver, for comparison purposes to detect report changes that
|
||||
* must be sent immediately to the host. This should point to a buffer big enough
|
||||
* to hold the largest HID input report sent from the HID interface. If this is set
|
||||
* to NULL, it is up to the user to force transfers when needed in the
|
||||
* \ref CALLBACK_HID_Device_CreateHIDReport() callback function.
|
||||
*
|
||||
* \note Due to the single buffer, the internal driver can only correctly compare
|
||||
* subsequent reports with identical report IDs. In multiple report devices,
|
||||
* this buffer should be set to NULL and the decision to send reports made
|
||||
* by the user application instead.
|
||||
*/
|
||||
uint8_t PrevReportINBufferSize; /**< Size in bytes of the given input report buffer. This is used to create a
|
||||
* second buffer of the same size within the driver so that subsequent reports
|
||||
* can be compared. If the user app is to determine when reports are to be sent
|
||||
* exclusively (i.e. \ref PrevReportINBuffer is NULL) this value must still be
|
||||
* set to the size of the largest report the device can issue to the host.
|
||||
*/
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode */
|
||||
uint16_t IdleCount; /**< Report idle period, in milliseconds, set by the host */
|
||||
uint16_t IdleMSRemaining; /**< Total number of milliseconds remaining before the idle period elapsed - this
|
||||
* should be decremented by the user application if non-zero each millisecond */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_HID_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given HID interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given HID interface is selected.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given HID class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*/
|
||||
void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given HID class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*/
|
||||
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** HID class driver callback for the user creation of a HID IN report. This callback may fire in response to either
|
||||
* HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback the
|
||||
* user is responsible for the creation of the next HID input report to be sent to the host.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
* \param[in,out] ReportID If preset to a non-zero value, this is the report ID being requested by the host. If zero, this should
|
||||
* be set to the report ID of the generated HID input report (if any). If multiple reports are not sent via the
|
||||
* given HID interface, this parameter should be ignored.
|
||||
* \param[in] ReportType Type of HID report to generate, either \ref REPORT_ITEM_TYPE_In or \ref REPORT_ITEM_TYPE_Feature
|
||||
* \param[out] ReportData Pointer to a buffer where the generated HID report should be stored
|
||||
* \param[out] ReportSize Number of bytes in the generated input report, or zero if no report is to be sent
|
||||
*
|
||||
* \return Boolean true to force the sending of the report even if it is identical to the previous report and still within
|
||||
* the idle period (useful for devices which report relative movement), false otherwise
|
||||
*/
|
||||
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, uint8_t* const ReportID,
|
||||
const uint8_t ReportType, void* ReportData, uint16_t* ReportSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(4) ATTR_NON_NULL_PTR_ARG(5);
|
||||
|
||||
/** HID class driver callback for the user processing of a received HID OUT report. This callback may fire in response to
|
||||
* either HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback
|
||||
* the user is responsible for the processing of the received HID output report from the host.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
* \param[in] ReportID Report ID of the received output report. If multiple reports are not received via the given HID
|
||||
* interface, this parameter should be ignored.
|
||||
* \param[in] ReportData Pointer to a buffer where the received HID report is stored.
|
||||
* \param[in] ReportSize Size in bytes of the received report from the host.
|
||||
*/
|
||||
void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, const uint8_t ReportID,
|
||||
const void* ReportData, const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** Indicates that a millisecond of idle time has elapsed on the given HID interface, and the interface's idle count should be
|
||||
* decremented. This should be called once per millisecond so that hardware key-repeats function correctly. It is recommended
|
||||
* that this be called by the \ref EVENT_USB_Device_StartOfFrame() event, once SOF events have been enabled via
|
||||
* \ref USB_Device_EnableSOFEvents();.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state
|
||||
*/
|
||||
static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo);
|
||||
static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* HIDInterfaceInfo)
|
||||
{
|
||||
if (HIDInterfaceInfo->State.IdleMSRemaining)
|
||||
HIDInterfaceInfo->State.IdleMSRemaining--;
|
||||
}
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,124 +1,124 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_MIDI_DRIVER
|
||||
#include "MIDI.h"
|
||||
|
||||
bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
|
||||
|
||||
if (MIDIInterfaceInfo->Config.DataINEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, MIDIInterfaceInfo->Config.DataINEndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (MIDIInterfaceInfo->Config.DataOUTEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, MIDIInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (Endpoint_IsReadWriteAllowed());
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((ErrorCode = Endpoint_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK)) != ENDPOINT_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
return ENDPOINT_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (Endpoint_BytesInEndpoint())
|
||||
{
|
||||
Endpoint_ClearIN();
|
||||
|
||||
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return false;
|
||||
|
||||
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
return false;
|
||||
|
||||
Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_MIDI_DRIVER
|
||||
#include "MIDI.h"
|
||||
|
||||
bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
|
||||
|
||||
if (MIDIInterfaceInfo->Config.DataINEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, MIDIInterfaceInfo->Config.DataINEndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (MIDIInterfaceInfo->Config.DataOUTEndpointNumber)
|
||||
{
|
||||
if (!(Endpoint_ConfigureEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, MIDIInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (Endpoint_IsReadWriteAllowed());
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((ErrorCode = Endpoint_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK)) != ENDPOINT_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
return ENDPOINT_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return ENDPOINT_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (Endpoint_BytesInEndpoint())
|
||||
{
|
||||
Endpoint_ClearIN();
|
||||
|
||||
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ENDPOINT_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return false;
|
||||
|
||||
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
return false;
|
||||
|
||||
Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,184 +1,184 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MIDI.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMIDI
|
||||
* @defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/MIDI.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the MIDI USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _MIDI_CLASS_DEVICE_H_
|
||||
#define _MIDI_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MIDI.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MIDI_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MIDI.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Define: */
|
||||
/** \brief MIDI Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each MIDI interface
|
||||
* within the user application, and passed to each of the MIDI class driver functions as the
|
||||
* MIDIInterfaceInfo parameter. This stores each MIDI interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming MIDI data, if available (zero if unused) */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the incoming MIDI data endpoint, if available (zero if unused) */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the MIDI interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing MIDI data, if available (zero if unused) */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing MIDI data endpoint, if available (zero if unused) */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the MIDI interface's IN data endpoint should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
// No state information for this class yet
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MIDI_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given MIDI interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given MIDI interface is selected.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a MIDI event packet to the host. If no host is connected, the event packet is discarded. Events are queued into the
|
||||
* endpoint bank until either the endpoint bank is full, or \ref MIDI_Device_Flush() is called. This allows for multiple
|
||||
* MIDI events to be packed into a single endpoint packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[in] Event Pointer to a populated USB_MIDI_EventPacket_t structure containing the MIDI event to send
|
||||
*
|
||||
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
|
||||
/** Flushes the MIDI send buffer, sending any queued MIDI events to the host. This should be called to override the
|
||||
* \ref MIDI_Device_SendEventPacket() function's packing behaviour, to flush queued events.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*
|
||||
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo);
|
||||
|
||||
/** Receives a MIDI event packet from the host. Events are unpacked from the endpoint, thus if the endpoint bank contains
|
||||
* multiple MIDI events from the host in the one packet, multiple calls to this function will return each individual event.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[out] Event Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed
|
||||
*
|
||||
* \return Boolean true if a MIDI event packet was received, false otherwise
|
||||
*/
|
||||
bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given MIDI class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*/
|
||||
static inline void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo);
|
||||
static inline void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
(void)MIDIInterfaceInfo;
|
||||
}
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given MIDI class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*/
|
||||
static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
(void)MIDIInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MIDI.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMIDI
|
||||
* @defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/MIDI.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the MIDI USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _MIDI_CLASS_DEVICE_H_
|
||||
#define _MIDI_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MIDI.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MIDI_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MIDI.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Define: */
|
||||
/** \brief MIDI Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each MIDI interface
|
||||
* within the user application, and passed to each of the MIDI class driver functions as the
|
||||
* MIDIInterfaceInfo parameter. This stores each MIDI interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming MIDI data, if available (zero if unused) */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the incoming MIDI data endpoint, if available (zero if unused) */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the MIDI interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing MIDI data, if available (zero if unused) */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing MIDI data endpoint, if available (zero if unused) */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the MIDI interface's IN data endpoint should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
// No state information for this class yet
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MIDI_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given MIDI interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given MIDI interface is selected.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a MIDI event packet to the host. If no host is connected, the event packet is discarded. Events are queued into the
|
||||
* endpoint bank until either the endpoint bank is full, or \ref MIDI_Device_Flush() is called. This allows for multiple
|
||||
* MIDI events to be packed into a single endpoint packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[in] Event Pointer to a populated USB_MIDI_EventPacket_t structure containing the MIDI event to send
|
||||
*
|
||||
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
|
||||
/** Flushes the MIDI send buffer, sending any queued MIDI events to the host. This should be called to override the
|
||||
* \ref MIDI_Device_SendEventPacket() function's packing behaviour, to flush queued events.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*
|
||||
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo);
|
||||
|
||||
/** Receives a MIDI event packet from the host. Events are unpacked from the endpoint, thus if the endpoint bank contains
|
||||
* multiple MIDI events from the host in the one packet, multiple calls to this function will return each individual event.
|
||||
*
|
||||
* \note This function must only be called when the Device state machine is in the DEVICE_STATE_Configured state or
|
||||
* the call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[out] Event Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed
|
||||
*
|
||||
* \return Boolean true if a MIDI event packet was received, false otherwise
|
||||
*/
|
||||
bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given MIDI class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*/
|
||||
static inline void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo);
|
||||
static inline void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
(void)MIDIInterfaceInfo;
|
||||
}
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given MIDI class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*/
|
||||
static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
(void)MIDIInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,230 +1,230 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_MS_CLASS_DEVICE_C
|
||||
#define __INCLUDE_FROM_MS_DRIVER
|
||||
#include "MassStorage.h"
|
||||
|
||||
static volatile bool* CallbackIsResetSource;
|
||||
|
||||
void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_MassStorageReset:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
MSInterfaceInfo->State.IsMassStoreReset = true;
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetMaxLUN:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Write_Byte(MSInterfaceInfo->Config.TotalLUNs - 1);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, MSInterfaceInfo->Config.DataINEndpointSize,
|
||||
MSInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, MSInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
MSInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsReadWriteAllowed())
|
||||
{
|
||||
if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
|
||||
{
|
||||
if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
MSInterfaceInfo->State.CommandStatus.Status = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo) ?
|
||||
SCSI_Command_Pass : SCSI_Command_Fail;
|
||||
MSInterfaceInfo->State.CommandStatus.Signature = MS_CSW_SIGNATURE;
|
||||
MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag;
|
||||
MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;
|
||||
|
||||
if ((MSInterfaceInfo->State.CommandStatus.Status == SCSI_Command_Fail) &&
|
||||
(MSInterfaceInfo->State.CommandStatus.DataTransferResidue))
|
||||
{
|
||||
Endpoint_StallTransaction();
|
||||
}
|
||||
|
||||
MS_Device_ReturnCommandStatus(MSInterfaceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (MSInterfaceInfo->State.IsMassStoreReset)
|
||||
{
|
||||
Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
Endpoint_ClearStall();
|
||||
Endpoint_ResetDataToggle();
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
Endpoint_ClearStall();
|
||||
Endpoint_ResetDataToggle();
|
||||
|
||||
MSInterfaceInfo->State.IsMassStoreReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
|
||||
if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock,
|
||||
(sizeof(MS_CommandBlockWrapper_t) - 16),
|
||||
StreamCallback_MS_Device_AbortOnMassStoreReset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((MSInterfaceInfo->State.CommandBlock.Signature != MS_CBW_SIGNATURE) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.LUN >= MSInterfaceInfo->Config.TotalLUNs) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.Flags & 0x1F) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.SCSICommandLength > 16))
|
||||
{
|
||||
Endpoint_StallTransaction();
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
Endpoint_StallTransaction();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
|
||||
if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData,
|
||||
MSInterfaceInfo->State.CommandBlock.SCSICommandLength,
|
||||
StreamCallback_MS_Device_AbortOnMassStoreReset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
while (Endpoint_IsStalled())
|
||||
{
|
||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_USBTask();
|
||||
#endif
|
||||
|
||||
if (MSInterfaceInfo->State.IsMassStoreReset)
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
while (Endpoint_IsStalled())
|
||||
{
|
||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_USBTask();
|
||||
#endif
|
||||
|
||||
if (MSInterfaceInfo->State.IsMassStoreReset)
|
||||
return;
|
||||
}
|
||||
|
||||
CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
|
||||
if (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus, sizeof(MS_CommandStatusWrapper_t),
|
||||
StreamCallback_MS_Device_AbortOnMassStoreReset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
static uint8_t StreamCallback_MS_Device_AbortOnMassStoreReset(void)
|
||||
{
|
||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_USBTask();
|
||||
#endif
|
||||
|
||||
if (*CallbackIsResetSource)
|
||||
return STREAMCALLBACK_Abort;
|
||||
else
|
||||
return STREAMCALLBACK_Continue;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_MS_CLASS_DEVICE_C
|
||||
#define __INCLUDE_FROM_MS_DRIVER
|
||||
#include "MassStorage.h"
|
||||
|
||||
static volatile bool* CallbackIsResetSource;
|
||||
|
||||
void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_MassStorageReset:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
MSInterfaceInfo->State.IsMassStoreReset = true;
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetMaxLUN:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Write_Byte(MSInterfaceInfo->Config.TotalLUNs - 1);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
Endpoint_ClearStatusStage();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, MSInterfaceInfo->Config.DataINEndpointSize,
|
||||
MSInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, MSInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
MSInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsReadWriteAllowed())
|
||||
{
|
||||
if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
|
||||
{
|
||||
if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
MSInterfaceInfo->State.CommandStatus.Status = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo) ?
|
||||
SCSI_Command_Pass : SCSI_Command_Fail;
|
||||
MSInterfaceInfo->State.CommandStatus.Signature = MS_CSW_SIGNATURE;
|
||||
MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag;
|
||||
MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;
|
||||
|
||||
if ((MSInterfaceInfo->State.CommandStatus.Status == SCSI_Command_Fail) &&
|
||||
(MSInterfaceInfo->State.CommandStatus.DataTransferResidue))
|
||||
{
|
||||
Endpoint_StallTransaction();
|
||||
}
|
||||
|
||||
MS_Device_ReturnCommandStatus(MSInterfaceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (MSInterfaceInfo->State.IsMassStoreReset)
|
||||
{
|
||||
Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
Endpoint_ClearStall();
|
||||
Endpoint_ResetDataToggle();
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
Endpoint_ClearStall();
|
||||
Endpoint_ResetDataToggle();
|
||||
|
||||
MSInterfaceInfo->State.IsMassStoreReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
|
||||
if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock,
|
||||
(sizeof(MS_CommandBlockWrapper_t) - 16),
|
||||
StreamCallback_MS_Device_AbortOnMassStoreReset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((MSInterfaceInfo->State.CommandBlock.Signature != MS_CBW_SIGNATURE) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.LUN >= MSInterfaceInfo->Config.TotalLUNs) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.Flags & 0x1F) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0) ||
|
||||
(MSInterfaceInfo->State.CommandBlock.SCSICommandLength > 16))
|
||||
{
|
||||
Endpoint_StallTransaction();
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
Endpoint_StallTransaction();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
|
||||
if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData,
|
||||
MSInterfaceInfo->State.CommandBlock.SCSICommandLength,
|
||||
StreamCallback_MS_Device_AbortOnMassStoreReset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
while (Endpoint_IsStalled())
|
||||
{
|
||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_USBTask();
|
||||
#endif
|
||||
|
||||
if (MSInterfaceInfo->State.IsMassStoreReset)
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
while (Endpoint_IsStalled())
|
||||
{
|
||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_USBTask();
|
||||
#endif
|
||||
|
||||
if (MSInterfaceInfo->State.IsMassStoreReset)
|
||||
return;
|
||||
}
|
||||
|
||||
CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
|
||||
if (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus, sizeof(MS_CommandStatusWrapper_t),
|
||||
StreamCallback_MS_Device_AbortOnMassStoreReset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
static uint8_t StreamCallback_MS_Device_AbortOnMassStoreReset(void)
|
||||
{
|
||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_USBTask();
|
||||
#endif
|
||||
|
||||
if (*CallbackIsResetSource)
|
||||
return STREAMCALLBACK_Abort;
|
||||
else
|
||||
return STREAMCALLBACK_Continue;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,168 +1,168 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MassStorage.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMS
|
||||
* @defgroup Group_USBClassMSDevice Mass Storage Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/MassStorage.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the Mass Storage USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _MS_CLASS_DEVICE_H_
|
||||
#define _MS_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MassStorage.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MassStorage.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief Mass Storage Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each Mass Storage interface
|
||||
* within the user application, and passed to each of the Mass Storage class driver functions as the
|
||||
* MSInterfaceInfo parameter. This stores each Mass Storage interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the Mass Storage interface's IN data endpoint */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the Mass Storage interface's IN data endpoint */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the Mass Storage interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the Mass Storage interface's OUT data endpoint */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the Mass Storage interface's OUT data endpoint */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the Mass Storage interface's OUT data endpoint should use double banking */
|
||||
|
||||
uint8_t TotalLUNs; /**< Total number of logical drives in the Mass Storage interface */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
MS_CommandBlockWrapper_t CommandBlock; /**< Mass Storage class command block structure, stores the received SCSI
|
||||
* command from the host which is to be processed
|
||||
*/
|
||||
MS_CommandStatusWrapper_t CommandStatus; /**< Mass Storage class command status structure, set elements to indicate
|
||||
* the issued command's success or failure to the host
|
||||
*/
|
||||
volatile bool IsMassStoreReset; /**< Flag indicating that the host has requested that the Mass Storage interface be reset
|
||||
* and that all current Mass Storage operations should immediately abort
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MS_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given Mass Storage interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given Mass Storage interface is selected.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given Mass Storage class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||
*/
|
||||
void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given Mass Storage class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage configuration and state
|
||||
*/
|
||||
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Mass Storage class driver callback for the user processing of a received SCSI command. This callback will fire each time the
|
||||
* host sends a SCSI command which requires processing by the user application. Inside this callback the user is responsible
|
||||
* for the processing of the received SCSI command from the host. The SCSI command is available in the CommandBlock structure
|
||||
* inside the Mass Storage class state structure passed as a parameter to the callback function.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the SCSI command was successfully processed, false otherwise
|
||||
*/
|
||||
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_MS_CLASS_DEVICE_C)
|
||||
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t StreamCallback_MS_Device_AbortOnMassStoreReset(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MassStorage.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMS
|
||||
* @defgroup Group_USBClassMSDevice Mass Storage Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/MassStorage.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the Mass Storage USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _MS_CLASS_DEVICE_H_
|
||||
#define _MS_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MassStorage.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MassStorage.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief Mass Storage Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each Mass Storage interface
|
||||
* within the user application, and passed to each of the Mass Storage class driver functions as the
|
||||
* MSInterfaceInfo parameter. This stores each Mass Storage interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the Mass Storage interface's IN data endpoint */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the Mass Storage interface's IN data endpoint */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the Mass Storage interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the Mass Storage interface's OUT data endpoint */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the Mass Storage interface's OUT data endpoint */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the Mass Storage interface's OUT data endpoint should use double banking */
|
||||
|
||||
uint8_t TotalLUNs; /**< Total number of logical drives in the Mass Storage interface */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
MS_CommandBlockWrapper_t CommandBlock; /**< Mass Storage class command block structure, stores the received SCSI
|
||||
* command from the host which is to be processed
|
||||
*/
|
||||
MS_CommandStatusWrapper_t CommandStatus; /**< Mass Storage class command status structure, set elements to indicate
|
||||
* the issued command's success or failure to the host
|
||||
*/
|
||||
volatile bool IsMassStoreReset; /**< Flag indicating that the host has requested that the Mass Storage interface be reset
|
||||
* and that all current Mass Storage operations should immediately abort
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MS_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given Mass Storage interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given Mass Storage interface is selected.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given Mass Storage class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||
*/
|
||||
void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given Mass Storage class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage configuration and state
|
||||
*/
|
||||
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Mass Storage class driver callback for the user processing of a received SCSI command. This callback will fire each time the
|
||||
* host sends a SCSI command which requires processing by the user application. Inside this callback the user is responsible
|
||||
* for the processing of the received SCSI command from the host. The SCSI command is available in the CommandBlock structure
|
||||
* inside the Mass Storage class state structure passed as a parameter to the callback function.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the SCSI command was successfully processed, false otherwise
|
||||
*/
|
||||
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_MS_CLASS_DEVICE_C)
|
||||
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t StreamCallback_MS_Device_AbortOnMassStoreReset(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,472 +1,472 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_RNDIS_CLASS_DEVICE_C
|
||||
#define __INCLUDE_FROM_RNDIS_DRIVER
|
||||
#include "RNDIS.h"
|
||||
|
||||
static const uint32_t PROGMEM AdapterSupportedOIDList[] =
|
||||
{
|
||||
OID_GEN_SUPPORTED_LIST,
|
||||
OID_GEN_PHYSICAL_MEDIUM,
|
||||
OID_GEN_HARDWARE_STATUS,
|
||||
OID_GEN_MEDIA_SUPPORTED,
|
||||
OID_GEN_MEDIA_IN_USE,
|
||||
OID_GEN_MAXIMUM_FRAME_SIZE,
|
||||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||||
OID_GEN_LINK_SPEED,
|
||||
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
||||
OID_GEN_RECEIVE_BLOCK_SIZE,
|
||||
OID_GEN_VENDOR_ID,
|
||||
OID_GEN_VENDOR_DESCRIPTION,
|
||||
OID_GEN_CURRENT_PACKET_FILTER,
|
||||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||||
OID_GEN_MEDIA_CONNECT_STATUS,
|
||||
OID_GEN_XMIT_OK,
|
||||
OID_GEN_RCV_OK,
|
||||
OID_GEN_XMIT_ERROR,
|
||||
OID_GEN_RCV_ERROR,
|
||||
OID_GEN_RCV_NO_BUFFER,
|
||||
OID_802_3_PERMANENT_ADDRESS,
|
||||
OID_802_3_CURRENT_ADDRESS,
|
||||
OID_802_3_MULTICAST_LIST,
|
||||
OID_802_3_MAXIMUM_LIST_SIZE,
|
||||
OID_802_3_RCV_ERROR_ALIGNMENT,
|
||||
OID_802_3_XMIT_ONE_COLLISION,
|
||||
OID_802_3_XMIT_MORE_COLLISIONS,
|
||||
};
|
||||
|
||||
void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_SendEncapsulatedCommand:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, USB_ControlRequest.wLength);
|
||||
RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetEncapsulatedResponse:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
if (!(MessageHeader->MessageLength))
|
||||
{
|
||||
RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0;
|
||||
MessageHeader->MessageLength = 1;
|
||||
}
|
||||
|
||||
Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, MessageHeader->MessageLength);
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
MessageHeader->MessageLength = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.DataINEndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, RNDISInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.NotificationEndpointSize,
|
||||
RNDISInterfaceInfo->Config.NotificationEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber);
|
||||
|
||||
if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
|
||||
{
|
||||
USB_Request_Header_t Notification = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = NOTIF_ResponseAvailable,
|
||||
.wValue = 0,
|
||||
.wIndex = 0,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK);
|
||||
|
||||
Endpoint_ClearIN();
|
||||
|
||||
RNDISInterfaceInfo->State.ResponseReady = false;
|
||||
}
|
||||
|
||||
if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
|
||||
{
|
||||
RNDIS_Packet_Message_t RNDISPacketHeader;
|
||||
|
||||
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer))
|
||||
{
|
||||
Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
|
||||
{
|
||||
Endpoint_StallTransaction();
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
|
||||
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength;
|
||||
|
||||
RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true;
|
||||
}
|
||||
|
||||
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer)
|
||||
{
|
||||
memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
|
||||
|
||||
RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength);
|
||||
RNDISPacketHeader.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
|
||||
RNDISPacketHeader.DataLength = RNDISInterfaceInfo->State.FrameOUT.FrameLength;
|
||||
|
||||
Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
/* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
|
||||
this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
|
||||
|
||||
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
switch (MessageHeader->MessageType)
|
||||
{
|
||||
case REMOTE_NDIS_INITIALIZE_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Initialize_Message_t* INITIALIZE_Message =
|
||||
(RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_Initialize_Complete_t* INITIALIZE_Response =
|
||||
(RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
|
||||
INITIALIZE_Response->MessageLength = sizeof(RNDIS_Initialize_Complete_t);
|
||||
INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
|
||||
INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
|
||||
INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
|
||||
INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR;
|
||||
INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;
|
||||
INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;
|
||||
INITIALIZE_Response->MaxPacketsPerTransfer = 1;
|
||||
INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);
|
||||
INITIALIZE_Response->PacketAlignmentFactor = 0;
|
||||
INITIALIZE_Response->AFListOffset = 0;
|
||||
INITIALIZE_Response->AFListSize = 0;
|
||||
|
||||
RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_HALT_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = false;
|
||||
MessageHeader->MessageLength = 0;
|
||||
|
||||
RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_QUERY_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
uint32_t Query_Oid = QUERY_Message->Oid;
|
||||
|
||||
void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
|
||||
QUERY_Message->InformationBufferOffset];
|
||||
void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)];
|
||||
uint16_t ResponseSize;
|
||||
|
||||
QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||
QUERY_Response->MessageLength = sizeof(RNDIS_Query_Complete_t);
|
||||
|
||||
if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
|
||||
ResponseData, &ResponseSize))
|
||||
{
|
||||
QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
QUERY_Response->MessageLength += ResponseSize;
|
||||
|
||||
QUERY_Response->InformationBufferLength = ResponseSize;
|
||||
QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
|
||||
|
||||
QUERY_Response->InformationBufferLength = 0;
|
||||
QUERY_Response->InformationBufferOffset = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_SET_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
uint32_t SET_Oid = SET_Message->Oid;
|
||||
|
||||
SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
|
||||
SET_Response->MessageLength = sizeof(RNDIS_Set_Complete_t);
|
||||
SET_Response->RequestId = SET_Message->RequestId;
|
||||
|
||||
void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
|
||||
SET_Message->InformationBufferOffset];
|
||||
|
||||
SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,
|
||||
SET_Message->InformationBufferLength) ?
|
||||
REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
case REMOTE_NDIS_RESET_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
||||
RESET_Response->MessageLength = sizeof(RNDIS_Reset_Complete_t);
|
||||
RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
RESET_Response->AddressingReset = 0;
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_KEEPALIVE_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
|
||||
(RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
|
||||
(RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
|
||||
KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KeepAlive_Complete_t);
|
||||
KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
|
||||
KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
|
||||
const uint32_t OId, void* const QueryData, const uint16_t QuerySize,
|
||||
void* ResponseData, uint16_t* const ResponseSize)
|
||||
{
|
||||
(void)QueryData;
|
||||
(void)QuerySize;
|
||||
|
||||
switch (OId)
|
||||
{
|
||||
case OID_GEN_SUPPORTED_LIST:
|
||||
*ResponseSize = sizeof(AdapterSupportedOIDList);
|
||||
|
||||
memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
|
||||
|
||||
return true;
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate that the device is a true ethernet link */
|
||||
*((uint32_t*)ResponseData) = 0;
|
||||
|
||||
return true;
|
||||
case OID_GEN_HARDWARE_STATUS:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = NDIS_HardwareStatus_Ready;
|
||||
|
||||
return true;
|
||||
case OID_GEN_MEDIA_SUPPORTED:
|
||||
case OID_GEN_MEDIA_IN_USE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
|
||||
|
||||
return true;
|
||||
case OID_GEN_VENDOR_ID:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
|
||||
*((uint32_t*)ResponseData) = 0x00FFFFFF;
|
||||
|
||||
return true;
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||||
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
|
||||
|
||||
return true;
|
||||
case OID_GEN_VENDOR_DESCRIPTION:
|
||||
*ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
|
||||
|
||||
memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
|
||||
|
||||
return true;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
|
||||
|
||||
return true;
|
||||
case OID_GEN_LINK_SPEED:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate 10Mb/s link speed */
|
||||
*((uint32_t*)ResponseData) = 100000;
|
||||
|
||||
return true;
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
*ResponseSize = sizeof(MAC_Address_t);
|
||||
|
||||
memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
|
||||
|
||||
return true;
|
||||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate only one multicast address supported */
|
||||
*((uint32_t*)ResponseData) = 1;
|
||||
|
||||
return true;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = RNDISInterfaceInfo->State.CurrPacketFilter;
|
||||
|
||||
return true;
|
||||
case OID_GEN_XMIT_OK:
|
||||
case OID_GEN_RCV_OK:
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
case OID_GEN_RCV_ERROR:
|
||||
case OID_GEN_RCV_NO_BUFFER:
|
||||
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
||||
case OID_802_3_XMIT_ONE_COLLISION:
|
||||
case OID_802_3_XMIT_MORE_COLLISIONS:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Unused statistic OIDs - always return 0 for each */
|
||||
*((uint32_t*)ResponseData) = 0;
|
||||
|
||||
return true;
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
|
||||
*((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, const uint32_t OId,
|
||||
void* SetData, const uint16_t SetSize)
|
||||
{
|
||||
(void)SetSize;
|
||||
|
||||
switch (OId)
|
||||
{
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
RNDISInterfaceInfo->State.CurrPacketFilter = *((uint32_t*)SetData);
|
||||
RNDISInterfaceInfo->State.CurrRNDISState = ((RNDISInterfaceInfo->State.CurrPacketFilter) ?
|
||||
RNDIS_Data_Initialized : RNDIS_Data_Initialized);
|
||||
|
||||
return true;
|
||||
case OID_802_3_MULTICAST_LIST:
|
||||
/* Do nothing - throw away the value from the host as it is unused */
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_DEVICE)
|
||||
|
||||
#define __INCLUDE_FROM_RNDIS_CLASS_DEVICE_C
|
||||
#define __INCLUDE_FROM_RNDIS_DRIVER
|
||||
#include "RNDIS.h"
|
||||
|
||||
static const uint32_t PROGMEM AdapterSupportedOIDList[] =
|
||||
{
|
||||
OID_GEN_SUPPORTED_LIST,
|
||||
OID_GEN_PHYSICAL_MEDIUM,
|
||||
OID_GEN_HARDWARE_STATUS,
|
||||
OID_GEN_MEDIA_SUPPORTED,
|
||||
OID_GEN_MEDIA_IN_USE,
|
||||
OID_GEN_MAXIMUM_FRAME_SIZE,
|
||||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||||
OID_GEN_LINK_SPEED,
|
||||
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
||||
OID_GEN_RECEIVE_BLOCK_SIZE,
|
||||
OID_GEN_VENDOR_ID,
|
||||
OID_GEN_VENDOR_DESCRIPTION,
|
||||
OID_GEN_CURRENT_PACKET_FILTER,
|
||||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||||
OID_GEN_MEDIA_CONNECT_STATUS,
|
||||
OID_GEN_XMIT_OK,
|
||||
OID_GEN_RCV_OK,
|
||||
OID_GEN_XMIT_ERROR,
|
||||
OID_GEN_RCV_ERROR,
|
||||
OID_GEN_RCV_NO_BUFFER,
|
||||
OID_802_3_PERMANENT_ADDRESS,
|
||||
OID_802_3_CURRENT_ADDRESS,
|
||||
OID_802_3_MULTICAST_LIST,
|
||||
OID_802_3_MAXIMUM_LIST_SIZE,
|
||||
OID_802_3_RCV_ERROR_ALIGNMENT,
|
||||
OID_802_3_XMIT_ONE_COLLISION,
|
||||
OID_802_3_XMIT_MORE_COLLISIONS,
|
||||
};
|
||||
|
||||
void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
if (!(Endpoint_IsSETUPReceived()))
|
||||
return;
|
||||
|
||||
if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)
|
||||
return;
|
||||
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case REQ_SendEncapsulatedCommand:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, USB_ControlRequest.wLength);
|
||||
RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetEncapsulatedResponse:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
if (!(MessageHeader->MessageLength))
|
||||
{
|
||||
RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0;
|
||||
MessageHeader->MessageLength = 1;
|
||||
}
|
||||
|
||||
Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, MessageHeader->MessageLength);
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
MessageHeader->MessageLength = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.DataINEndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, RNDISInterfaceInfo->Config.DataOUTEndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.NotificationEndpointSize,
|
||||
RNDISInterfaceInfo->Config.NotificationEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber);
|
||||
|
||||
if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
|
||||
{
|
||||
USB_Request_Header_t Notification = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = NOTIF_ResponseAvailable,
|
||||
.wValue = 0,
|
||||
.wIndex = 0,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK);
|
||||
|
||||
Endpoint_ClearIN();
|
||||
|
||||
RNDISInterfaceInfo->State.ResponseReady = false;
|
||||
}
|
||||
|
||||
if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
|
||||
{
|
||||
RNDIS_Packet_Message_t RNDISPacketHeader;
|
||||
|
||||
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
|
||||
|
||||
if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer))
|
||||
{
|
||||
Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
|
||||
{
|
||||
Endpoint_StallTransaction();
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
|
||||
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength;
|
||||
|
||||
RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true;
|
||||
}
|
||||
|
||||
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
|
||||
|
||||
if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer)
|
||||
{
|
||||
memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
|
||||
|
||||
RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength);
|
||||
RNDISPacketHeader.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
|
||||
RNDISPacketHeader.DataLength = RNDISInterfaceInfo->State.FrameOUT.FrameLength;
|
||||
|
||||
Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
/* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
|
||||
this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
|
||||
|
||||
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
switch (MessageHeader->MessageType)
|
||||
{
|
||||
case REMOTE_NDIS_INITIALIZE_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Initialize_Message_t* INITIALIZE_Message =
|
||||
(RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_Initialize_Complete_t* INITIALIZE_Response =
|
||||
(RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
|
||||
INITIALIZE_Response->MessageLength = sizeof(RNDIS_Initialize_Complete_t);
|
||||
INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
|
||||
INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
|
||||
INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
|
||||
INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR;
|
||||
INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;
|
||||
INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;
|
||||
INITIALIZE_Response->MaxPacketsPerTransfer = 1;
|
||||
INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);
|
||||
INITIALIZE_Response->PacketAlignmentFactor = 0;
|
||||
INITIALIZE_Response->AFListOffset = 0;
|
||||
INITIALIZE_Response->AFListSize = 0;
|
||||
|
||||
RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_HALT_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = false;
|
||||
MessageHeader->MessageLength = 0;
|
||||
|
||||
RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_QUERY_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
uint32_t Query_Oid = QUERY_Message->Oid;
|
||||
|
||||
void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
|
||||
QUERY_Message->InformationBufferOffset];
|
||||
void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)];
|
||||
uint16_t ResponseSize;
|
||||
|
||||
QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||
QUERY_Response->MessageLength = sizeof(RNDIS_Query_Complete_t);
|
||||
|
||||
if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
|
||||
ResponseData, &ResponseSize))
|
||||
{
|
||||
QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
QUERY_Response->MessageLength += ResponseSize;
|
||||
|
||||
QUERY_Response->InformationBufferLength = ResponseSize;
|
||||
QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
|
||||
|
||||
QUERY_Response->InformationBufferLength = 0;
|
||||
QUERY_Response->InformationBufferOffset = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_SET_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
uint32_t SET_Oid = SET_Message->Oid;
|
||||
|
||||
SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
|
||||
SET_Response->MessageLength = sizeof(RNDIS_Set_Complete_t);
|
||||
SET_Response->RequestId = SET_Message->RequestId;
|
||||
|
||||
void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
|
||||
SET_Message->InformationBufferOffset];
|
||||
|
||||
SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,
|
||||
SET_Message->InformationBufferLength) ?
|
||||
REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
case REMOTE_NDIS_RESET_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
||||
RESET_Response->MessageLength = sizeof(RNDIS_Reset_Complete_t);
|
||||
RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
RESET_Response->AddressingReset = 0;
|
||||
|
||||
break;
|
||||
case REMOTE_NDIS_KEEPALIVE_MSG:
|
||||
RNDISInterfaceInfo->State.ResponseReady = true;
|
||||
|
||||
RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
|
||||
(RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
|
||||
(RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
|
||||
|
||||
KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
|
||||
KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KeepAlive_Complete_t);
|
||||
KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
|
||||
KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
|
||||
const uint32_t OId, void* const QueryData, const uint16_t QuerySize,
|
||||
void* ResponseData, uint16_t* const ResponseSize)
|
||||
{
|
||||
(void)QueryData;
|
||||
(void)QuerySize;
|
||||
|
||||
switch (OId)
|
||||
{
|
||||
case OID_GEN_SUPPORTED_LIST:
|
||||
*ResponseSize = sizeof(AdapterSupportedOIDList);
|
||||
|
||||
memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
|
||||
|
||||
return true;
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate that the device is a true ethernet link */
|
||||
*((uint32_t*)ResponseData) = 0;
|
||||
|
||||
return true;
|
||||
case OID_GEN_HARDWARE_STATUS:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = NDIS_HardwareStatus_Ready;
|
||||
|
||||
return true;
|
||||
case OID_GEN_MEDIA_SUPPORTED:
|
||||
case OID_GEN_MEDIA_IN_USE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
|
||||
|
||||
return true;
|
||||
case OID_GEN_VENDOR_ID:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
|
||||
*((uint32_t*)ResponseData) = 0x00FFFFFF;
|
||||
|
||||
return true;
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||||
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
|
||||
|
||||
return true;
|
||||
case OID_GEN_VENDOR_DESCRIPTION:
|
||||
*ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
|
||||
|
||||
memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
|
||||
|
||||
return true;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
|
||||
|
||||
return true;
|
||||
case OID_GEN_LINK_SPEED:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate 10Mb/s link speed */
|
||||
*((uint32_t*)ResponseData) = 100000;
|
||||
|
||||
return true;
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
*ResponseSize = sizeof(MAC_Address_t);
|
||||
|
||||
memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
|
||||
|
||||
return true;
|
||||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate only one multicast address supported */
|
||||
*((uint32_t*)ResponseData) = 1;
|
||||
|
||||
return true;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
*((uint32_t*)ResponseData) = RNDISInterfaceInfo->State.CurrPacketFilter;
|
||||
|
||||
return true;
|
||||
case OID_GEN_XMIT_OK:
|
||||
case OID_GEN_RCV_OK:
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
case OID_GEN_RCV_ERROR:
|
||||
case OID_GEN_RCV_NO_BUFFER:
|
||||
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
||||
case OID_802_3_XMIT_ONE_COLLISION:
|
||||
case OID_802_3_XMIT_MORE_COLLISIONS:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Unused statistic OIDs - always return 0 for each */
|
||||
*((uint32_t*)ResponseData) = 0;
|
||||
|
||||
return true;
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
*ResponseSize = sizeof(uint32_t);
|
||||
|
||||
/* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
|
||||
*((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, const uint32_t OId,
|
||||
void* SetData, const uint16_t SetSize)
|
||||
{
|
||||
(void)SetSize;
|
||||
|
||||
switch (OId)
|
||||
{
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
RNDISInterfaceInfo->State.CurrPacketFilter = *((uint32_t*)SetData);
|
||||
RNDISInterfaceInfo->State.CurrRNDISState = ((RNDISInterfaceInfo->State.CurrPacketFilter) ?
|
||||
RNDIS_Data_Initialized : RNDIS_Data_Initialized);
|
||||
|
||||
return true;
|
||||
case OID_802_3_MULTICAST_LIST:
|
||||
/* Do nothing - throw away the value from the host as it is unused */
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,171 +1,171 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/RNDIS.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassRNDIS
|
||||
* @defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/RNDIS.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the RNDIS USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _RNDIS_CLASS_DEVICE_H_
|
||||
#define _RNDIS_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/RNDIS.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_RNDIS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/RNDIS.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief RNDIS Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each RNDIS interface
|
||||
* within the user application, and passed to each of the RNDIS class driver functions as the
|
||||
* RNDISInterfaceInfo parameter. This stores each RNDIS interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the RNDIS interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the RNDIS interface's OUT data endpoint should use double banking */
|
||||
|
||||
uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */
|
||||
uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */
|
||||
bool NotificationEndpointDoubleBank; /** Indicates if the RNDIS interface's notification endpoint should use double banking */
|
||||
|
||||
char* AdapterVendorDescription; /**< String description of the adapter vendor */
|
||||
MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE]; /**< Buffer to hold RNDIS messages to and from the host,
|
||||
* managed by the class driver
|
||||
*/
|
||||
bool ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host */
|
||||
uint8_t CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the RNDIS_States_t enum */
|
||||
uint32_t CurrPacketFilter; /**< Current packet filter mode, used internally by the class driver */
|
||||
Ethernet_Frame_Info_t FrameIN; /**< Structure holding the last received Ethernet frame from the host, for user
|
||||
* processing
|
||||
*/
|
||||
Ethernet_Frame_Info_t FrameOUT; /**< Structure holding the next Ethernet frame to send to the host, populated by the
|
||||
* user application
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_RNDIS_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given RNDIS interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given HID interface is selected.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given RNDIS class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state
|
||||
*/
|
||||
void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given HID class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state
|
||||
*/
|
||||
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_RNDIS_CLASS_DEVICE_C)
|
||||
static void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
ATTR_NON_NULL_PTR_ARG(1);
|
||||
static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
|
||||
const uint32_t OId, void* const QueryData, const uint16_t QuerySize,
|
||||
void* ResponseData, uint16_t* const ResponseSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(5) ATTR_NON_NULL_PTR_ARG(6);
|
||||
static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, const uint32_t OId,
|
||||
void* SetData, const uint16_t SetSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Device mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* Device mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/RNDIS.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassRNDIS
|
||||
* @defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Device/RNDIS.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Device Mode USB Class driver framework interface, for the RNDIS USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _RNDIS_CLASS_DEVICE_H_
|
||||
#define _RNDIS_CLASS_DEVICE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/RNDIS.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_RNDIS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/RNDIS.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief RNDIS Class Device Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made for each RNDIS interface
|
||||
* within the user application, and passed to each of the RNDIS class driver functions as the
|
||||
* RNDISInterfaceInfo parameter. This stores each RNDIS interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */
|
||||
|
||||
uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint */
|
||||
uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint */
|
||||
bool DataINEndpointDoubleBank; /** Indicates if the RNDIS interface's IN data endpoint should use double banking */
|
||||
|
||||
uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint */
|
||||
uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint */
|
||||
bool DataOUTEndpointDoubleBank; /** Indicates if the RNDIS interface's OUT data endpoint should use double banking */
|
||||
|
||||
uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used */
|
||||
uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */
|
||||
bool NotificationEndpointDoubleBank; /** Indicates if the RNDIS interface's notification endpoint should use double banking */
|
||||
|
||||
char* AdapterVendorDescription; /**< String description of the adapter vendor */
|
||||
MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE]; /**< Buffer to hold RNDIS messages to and from the host,
|
||||
* managed by the class driver
|
||||
*/
|
||||
bool ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host */
|
||||
uint8_t CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the RNDIS_States_t enum */
|
||||
uint32_t CurrPacketFilter; /**< Current packet filter mode, used internally by the class driver */
|
||||
Ethernet_Frame_Info_t FrameIN; /**< Structure holding the last received Ethernet frame from the host, for user
|
||||
* processing
|
||||
*/
|
||||
Ethernet_Frame_Info_t FrameOUT; /**< Structure holding the next Ethernet frame to send to the host, populated by the
|
||||
* user application
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* are reset to their defaults when the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_RNDIS_Device_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the endpoints of a given RNDIS interface, ready for use. This should be linked to the library
|
||||
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
|
||||
* containing the given HID interface is selected.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state
|
||||
*
|
||||
* \return Boolean true if the endpoints were successfully configured, false otherwise
|
||||
*/
|
||||
bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Processes incoming control requests from the host, that are directed to the given RNDIS class interface. This should be
|
||||
* linked to the library \ref EVENT_USB_Device_UnhandledControlRequest() event.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state
|
||||
*/
|
||||
void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** General management task for a given HID class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state
|
||||
*/
|
||||
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_RNDIS_CLASS_DEVICE_C)
|
||||
static void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
|
||||
ATTR_NON_NULL_PTR_ARG(1);
|
||||
static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
|
||||
const uint32_t OId, void* const QueryData, const uint16_t QuerySize,
|
||||
void* ResponseData, uint16_t* const ResponseSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(5) ATTR_NON_NULL_PTR_ARG(6);
|
||||
static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, const uint32_t OId,
|
||||
void* SetData, const uint16_t SetSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue