1
0
Fork 0

Squashed 'tmk_core/' changes from caca2c0..dc0e46e

dc0e46e Rename LUFA to LUFA-git
3bfa7fa Remove LUFA-120730
215b764 Merge commit 'afa0f22a9299686fd88f58ce09c5b521ac917e8f' as 'protocol/lufa/LUFA'
afa0f22 Squashed 'protocol/lufa/LUFA/' content from commit def7fca
c0c42fa Remove submodule of LUFA
30f897d Merge commit '87ced33feb74e79c3281dda36eb6d6d153399b41' as 'protocol/usb_hid/USB_Host_Shield_2.0'
87ced33 Squashed 'protocol/usb_hid/USB_Host_Shield_2.0/' content from commit aab4a69
14f6d49 Remove submodule of USB_Host_Shield_2.0

git-subtree-dir: tmk_core
git-subtree-split: dc0e46eaa4367d4e218f8816e3c117895820f07c
This commit is contained in:
tmk 2015-05-13 11:13:10 +09:00
parent 4d116a04e9
commit f6d56675f9
1575 changed files with 421901 additions and 63190 deletions

View file

@ -0,0 +1,77 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB Android Open Accessory Class driver.
*
* Master include file for the library USB Android Open Accessory Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassAOA Android Open Accessory Class Driver
* \brief USB class driver for the Google Android Open Accessory class standard.
*
* \section Sec_USBClassAOA_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassAOA_ModDescription Module Description
* Android Open Accessory Class Driver module. This module contains an internal implementation of the USB Android Open Accessory
* Class, for Host USB mode. User applications can use this class driver instead of implementing the Android Open Accessory Class
* manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Host using the USB Android Open Accessory Class.
*
* @{
*/
#ifndef _AOA_CLASS_H_
#define _AOA_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_AOA_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#include "Host/AndroidAccessoryClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,81 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB Audio 1.0 Class driver.
*
* Master include file for the library USB Audio 1.0 Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassAudio Audio 1.0 Class Driver
* \brief USB class driver for the USB-IF Audio 1.0 class standard.
*
* \section Sec_USBClassAudio_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/AudioClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/AudioClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassAudio_ModDescription Module Description
* Audio 1.0 Class Driver module. This module contains an internal implementation of the USB Audio 1.0 Class, for both
* Device and Host USB modes. User applications can use this class driver instead of implementing the Audio 1.0 class
* manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Hosts or Devices using the USB Audio 1.0 Class.
*
* @{
*/
#ifndef _AUDIO_CLASS_H_
#define _AUDIO_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_AUDIO_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "Device/AudioClassDevice.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "Host/AudioClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,81 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB CDC-ACM Class driver.
*
* Master include file for the library USB CDC Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassCDC CDC-ACM (Virtual Serial) Class Driver
* \brief USB class driver for the USB-IF CDC-ACM (Virtual Serial) class standard.
*
* \section Sec_USBClassCDC_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/CDCClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/CDCClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassCDC_ModDescription Module Description
* CDC Class Driver module. This module contains an internal implementation of the USB CDC-ACM class Virtual Serial
* Ports, for both Device and Host USB modes. User applications can use this class driver instead of implementing the
* CDC class manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Hosts or Devices using the USB CDC Class.
*
* @{
*/
#ifndef _CDC_CLASS_H_
#define _CDC_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_CDC_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "Device/CDCClassDevice.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "Host/CDCClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,129 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB Android Open Accessory Class driver.
*
* Common definitions and declarations for the library USB Android Open Accessory Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassAOA
* \defgroup Group_USBClassAOACommon Common Class Definitions
*
* \section Sec_USBClassAOACommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* Android Open Accessory Class.
*
* @{
*/
#ifndef _AOA_CLASS_COMMON_H_
#define _AOA_CLASS_COMMON_H_
/* Includes: */
#include "../../Core/StdDescriptors.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_AOA_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
#endif
/* Macros: */
/** Product ID value in a Device Descriptor to indicate an Android device in Open Accessory mode. */
#define ANDROID_ACCESSORY_PRODUCT_ID 0x2D00
/** Product ID value in a Device Descriptor to indicate an Android device in Open Accessory and Android Debug mode. */
#define ANDROID_ACCESSORY_ADB_PRODUCT_ID 0x2D01
/* Enums: */
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the
* Android Open Accessory class.
*/
enum AOA_Descriptor_ClassSubclassProtocol_t
{
AOA_CSCP_AOADataClass = 0xFF, /**< Descriptor Class value indicating that the device or interface
* belongs to the AOA data class.
*/
AOA_CSCP_AOADataSubclass = 0xFF, /**< Descriptor Subclass value indicating that the device or interface
* belongs to AOA data subclass.
*/
AOA_CSCP_AOADataProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
* belongs to the AOA data class protocol.
*/
};
/** Enum for the Android Open Accessory class specific control requests that can be issued by the USB bus host. */
enum AOA_ClassRequests_t
{
AOA_REQ_GetAccessoryProtocol = 0x33, /**< Android Open Accessory control request to retrieve the device's supported Accessory Protocol version. */
AOA_REQ_SendString = 0x34, /**< Android Open Accessory control request to set an accessory property string in the device. */
AOA_REQ_StartAccessoryMode = 0x35, /**< Android Open Accessory control request to switch the device into Accessory mode. */
};
/** Enum for the possible Android Open Accessory property string indexes. */
enum AOA_Strings_t
{
AOA_STRING_Manufacturer = 0, /**< Index of the Manufacturer property string. */
AOA_STRING_Model = 1, /**< Index of the Model Name property string. */
AOA_STRING_Description = 2, /**< Index of the Description property string. */
AOA_STRING_Version = 3, /**< Index of the Version Number property string. */
AOA_STRING_URI = 4, /**< Index of the URI Information property string. */
AOA_STRING_Serial = 5, /**< Index of the Serial Number property string. */
#if !defined(__DOXYGEN__)
AOA_STRING_TOTAL_STRINGS
#endif
};
/** Enum for the possible Android Open Accessory protocol versions. */
enum AOA_Protocols_t
{
AOA_PROTOCOL_AccessoryV1 = 0x0001, /**< Android Open Accessory version 1. */
AOA_PROTOCOL_AccessoryV2 = 0x0002, /**< Android Open Accessory version 2. */
};
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,780 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB Audio 1.0 Class driver.
*
* Common definitions and declarations for the library USB Audio 1.0 Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassAudio
* \defgroup Group_USBClassAudioCommon Common Class Definitions
*
* \section Sec_USBClassAudioCommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* Audio 1.0 Class.
*
* @{
*/
#ifndef _AUDIO_CLASS_COMMON_H_
#define _AUDIO_CLASS_COMMON_H_
/* Includes: */
#include "../../Core/StdDescriptors.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/USB.h instead.
#endif
/* Macros: */
/** \name Audio Channel Masks */
//@{
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_LEFT_FRONT (1 << 0)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_RIGHT_FRONT (1 << 1)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_CENTER_FRONT (1 << 2)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_LOW_FREQ_ENHANCE (1 << 3)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_LEFT_SURROUND (1 << 4)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_RIGHT_SURROUND (1 << 5)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_LEFT_OF_CENTER (1 << 6)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_RIGHT_OF_CENTER (1 << 7)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_SURROUND (1 << 8)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_SIDE_LEFT (1 << 9)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_SIDE_RIGHT (1 << 10)
/** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_CHANNEL_TOP (1 << 11)
//@}
/** \name Audio Feature Masks */
//@{
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_MUTE (1 << 0)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_VOLUME (1 << 1)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_BASS (1 << 2)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_MID (1 << 3)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_TREBLE (1 << 4)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_GRAPHIC_EQUALIZER (1 << 5)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_AUTOMATIC_GAIN (1 << 6)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_DELAY (1 << 7)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_BASS_BOOST (1 << 8)
/** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
#define AUDIO_FEATURE_BASS_LOUDNESS (1 << 9)
//@}
/** \name Audio Terminal Types */
//@{
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_UNDEFINED 0x0100
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_STREAMING 0x0101
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_VENDOR 0x01FF
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_UNDEFINED 0x0200
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_MIC 0x0201
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_DESKTOP_MIC 0x0202
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_PERSONAL_MIC 0x0203
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_OMNIDIR_MIC 0x0204
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_MIC_ARRAY 0x0205
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_PROCESSING_MIC 0x0206
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_IN_OUT_UNDEFINED 0x0300
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_OUT_SPEAKER 0x0301
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_OUT_HEADPHONES 0x0302
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_OUT_HEAD_MOUNTED 0x0303
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_OUT_DESKTOP 0x0304
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_OUT_ROOM 0x0305
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_OUT_COMMUNICATION 0x0306
/** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
#define AUDIO_TERMINAL_OUT_LOWFREQ 0x0307
//@}
/** Convenience macro to fill a 24-bit \ref USB_Audio_SampleFreq_t structure with the given sample rate as a 24-bit number.
*
* \param[in] freq Required audio sampling frequency in HZ
*/
#define AUDIO_SAMPLE_FREQ(freq) {.Byte1 = ((uint32_t)freq & 0xFF), .Byte2 = (((uint32_t)freq >> 8) & 0xFF), .Byte3 = (((uint32_t)freq >> 16) & 0xFF)}
/** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
* accepts only filled endpoint packets of audio samples.
*/
#define AUDIO_EP_FULL_PACKETS_ONLY (1 << 7)
/** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
* will accept partially filled endpoint packets of audio samples.
*/
#define AUDIO_EP_ACCEPTS_SMALL_PACKETS (0 << 7)
/** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
* allows for sampling frequency adjustments to be made via control requests directed at the endpoint.
*/
#define AUDIO_EP_SAMPLE_FREQ_CONTROL (1 << 0)
/** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
* allows for pitch adjustments to be made via control requests directed at the endpoint.
*/
#define AUDIO_EP_PITCH_CONTROL (1 << 1)
/* Enums: */
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the Audio
* device class.
*/
enum Audio_Descriptor_ClassSubclassProtocol_t
{
AUDIO_CSCP_AudioClass = 0x01, /**< Descriptor Class value indicating that the device or
* interface belongs to the USB Audio 1.0 class.
*/
AUDIO_CSCP_ControlSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or
* interface belongs to the Audio Control subclass.
*/
AUDIO_CSCP_ControlProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or
* interface belongs to the Audio Control protocol.
*/
AUDIO_CSCP_AudioStreamingSubclass = 0x02, /**< Descriptor Subclass value indicating that the device or
* interface belongs to the MIDI Streaming subclass.
*/
AUDIO_CSCP_MIDIStreamingSubclass = 0x03, /**< Descriptor Subclass value indicating that the device or
* interface belongs to the Audio streaming subclass.
*/
AUDIO_CSCP_StreamingProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or
* interface belongs to the Streaming Audio protocol.
*/
};
/** Audio class specific interface description subtypes, for the Audio Control interface. */
enum Audio_CSInterface_AC_SubTypes_t
{
AUDIO_DSUBTYPE_CSInterface_Header = 0x01, /**< Audio class specific control interface header. */
AUDIO_DSUBTYPE_CSInterface_InputTerminal = 0x02, /**< Audio class specific control interface Input Terminal. */
AUDIO_DSUBTYPE_CSInterface_OutputTerminal = 0x03, /**< Audio class specific control interface Output Terminal. */
AUDIO_DSUBTYPE_CSInterface_Mixer = 0x04, /**< Audio class specific control interface Mixer Unit. */
AUDIO_DSUBTYPE_CSInterface_Selector = 0x05, /**< Audio class specific control interface Selector Unit. */
AUDIO_DSUBTYPE_CSInterface_Feature = 0x06, /**< Audio class specific control interface Feature Unit. */
AUDIO_DSUBTYPE_CSInterface_Processing = 0x07, /**< Audio class specific control interface Processing Unit. */
AUDIO_DSUBTYPE_CSInterface_Extension = 0x08, /**< Audio class specific control interface Extension Unit. */
};
/** Audio class specific interface description subtypes, for the Audio Streaming interface. */
enum Audio_CSInterface_AS_SubTypes_t
{
AUDIO_DSUBTYPE_CSInterface_General = 0x01, /**< Audio class specific streaming interface general descriptor. */
AUDIO_DSUBTYPE_CSInterface_FormatType = 0x02, /**< Audio class specific streaming interface format type descriptor. */
AUDIO_DSUBTYPE_CSInterface_FormatSpecific = 0x03, /**< Audio class specific streaming interface format information descriptor. */
};
/** Audio class specific endpoint description subtypes, for the Audio Streaming interface. */
enum Audio_CSEndpoint_SubTypes_t
{
AUDIO_DSUBTYPE_CSEndpoint_General = 0x01, /**< Audio class specific endpoint general descriptor. */
};
/** Enum for the Audio class specific control requests that can be issued by the USB bus host. */
enum Audio_ClassRequests_t
{
AUDIO_REQ_SetCurrent = 0x01, /**< Audio class-specific request to set the current value of a parameter within the device. */
AUDIO_REQ_SetMinimum = 0x02, /**< Audio class-specific request to set the minimum value of a parameter within the device. */
AUDIO_REQ_SetMaximum = 0x03, /**< Audio class-specific request to set the maximum value of a parameter within the device. */
AUDIO_REQ_SetResolution = 0x04, /**< Audio class-specific request to set the resolution value of a parameter within the device. */
AUDIO_REQ_SetMemory = 0x05, /**< Audio class-specific request to set the memory value of a parameter within the device. */
AUDIO_REQ_GetCurrent = 0x81, /**< Audio class-specific request to get the current value of a parameter within the device. */
AUDIO_REQ_GetMinimum = 0x82, /**< Audio class-specific request to get the minimum value of a parameter within the device. */
AUDIO_REQ_GetMaximum = 0x83, /**< Audio class-specific request to get the maximum value of a parameter within the device. */
AUDIO_REQ_GetResolution = 0x84, /**< Audio class-specific request to get the resolution value of a parameter within the device. */
AUDIO_REQ_GetMemory = 0x85, /**< Audio class-specific request to get the memory value of a parameter within the device. */
AUDIO_REQ_GetStatus = 0xFF, /**< Audio class-specific request to get the device status. */
};
/** Enum for Audio class specific Endpoint control modifiers which can be set and retrieved by a USB host, if the corresponding
* endpoint control is indicated to be supported in the Endpoint's Audio-class specific endpoint descriptor.
*/
enum Audio_EndpointControls_t
{
AUDIO_EPCONTROL_SamplingFreq = 0x01, /**< Sampling frequency adjustment of the endpoint. */
AUDIO_EPCONTROL_Pitch = 0x02, /**< Pitch adjustment of the endpoint. */
};
/* Type Defines: */
/** \brief Audio class-specific Input Terminal Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific input terminal descriptor. This indicates to the host that the device
* contains an input audio source, either from a physical terminal on the device, or a logical terminal (for example,
* a USB endpoint). See the USB Audio specification for more details.
*
* \see \ref USB_Audio_StdDescriptor_InputTerminal_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_InputTerminal.
*/
uint8_t TerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
uint16_t TerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
uint8_t AssociatedOutputTerminal; /**< ID of associated output terminal, for physically grouped terminals
* such as the speaker and microphone of a phone handset.
*/
uint8_t TotalChannels; /**< Total number of separate audio channels within this interface (right, left, etc.) */
uint16_t ChannelConfig; /**< \c CHANNEL_* masks indicating what channel layout is supported by this terminal. */
uint8_t ChannelStrIndex; /**< Index of a string descriptor describing this channel within the device. */
uint8_t TerminalStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_Audio_Descriptor_InputTerminal_t;
/** \brief Audio class-specific Input Terminal Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific input terminal descriptor. This indicates to the host that the device
* contains an input audio source, either from a physical terminal on the device, or a logical terminal (for example,
* a USB endpoint). See the USB Audio specification for more details.
*
* \see \ref USB_Audio_Descriptor_InputTerminal_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_InputTerminal.
*/
uint8_t bTerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
uint16_t wTerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
uint8_t bAssocTerminal; /**< ID of associated output terminal, for physically grouped terminals
* such as the speaker and microphone of a phone handset.
*/
uint8_t bNrChannels; /**< Total number of separate audio channels within this interface (right, left, etc.) */
uint16_t wChannelConfig; /**< \c CHANNEL_* masks indicating what channel layout is supported by this terminal. */
uint8_t iChannelNames; /**< Index of a string descriptor describing this channel within the device. */
uint8_t iTerminal; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_Audio_StdDescriptor_InputTerminal_t;
/** \brief Audio class-specific Output Terminal Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific output terminal descriptor. This indicates to the host that the device
* contains an output audio sink, either to a physical terminal on the device, or a logical terminal (for example,
* a USB endpoint). See the USB Audio specification for more details.
*
* \see \ref USB_Audio_StdDescriptor_OutputTerminal_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_OutputTerminal.
*/
uint8_t TerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
uint16_t TerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
uint8_t AssociatedInputTerminal; /**< ID of associated input terminal, for physically grouped terminals
* such as the speaker and microphone of a phone handset.
*/
uint8_t SourceID; /**< ID value of the unit this terminal's audio is sourced from. */
uint8_t TerminalStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_Audio_Descriptor_OutputTerminal_t;
/** \brief Audio class-specific Output Terminal Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific output terminal descriptor. This indicates to the host that the device
* contains an output audio sink, either to a physical terminal on the device, or a logical terminal (for example,
* a USB endpoint). See the USB Audio specification for more details.
*
* \see \ref USB_Audio_Descriptor_OutputTerminal_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_OutputTerminal.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSInterface_AC_SubTypes_t enum.
*/
uint8_t bTerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
uint16_t wTerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
uint8_t bAssocTerminal; /**< ID of associated input terminal, for physically grouped terminals
* such as the speaker and microphone of a phone handset.
*/
uint8_t bSourceID; /**< ID value of the unit this terminal's audio is sourced from. */
uint8_t iTerminal; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_Audio_StdDescriptor_OutputTerminal_t;
/** \brief Audio class-specific Interface Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific interface descriptor. This follows a regular interface descriptor to
* supply extra information about the audio device's layout to the host. See the USB Audio specification for more
* details.
*
* \see \ref USB_Audio_StdDescriptor_Interface_AC_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
*/
uint16_t ACSpecification; /**< Binary Coded Decimal value, indicating the supported Audio Class specification version.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint16_t TotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
uint8_t InCollection; /**< Total number of Audio Streaming interfaces linked to this Audio Control interface (must be 1). */
uint8_t InterfaceNumber; /**< Interface number of the associated Audio Streaming interface. */
} ATTR_PACKED USB_Audio_Descriptor_Interface_AC_t;
/** \brief Audio class-specific Interface Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific interface descriptor. This follows a regular interface descriptor to
* supply extra information about the audio device's layout to the host. See the USB Audio specification for more
* details.
*
* \see \ref USB_Audio_Descriptor_Interface_AC_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype;/**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
*/
uint16_t bcdADC; /**< Binary coded decimal value, indicating the supported Audio Class specification version.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint16_t wTotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
uint8_t bInCollection; /**< Total number of Audio Streaming interfaces linked to this Audio Control interface (must be 1). */
uint8_t bInterfaceNumbers; /**< Interface number of the associated Audio Streaming interface. */
} ATTR_PACKED USB_Audio_StdDescriptor_Interface_AC_t;
/** \brief Audio class-specific Feature Unit Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific Feature Unit descriptor. This indicates to the host what features
* are present in the device's audio stream for basic control, such as per-channel volume. See the USB Audio
* specification for more details.
*
* \see \ref USB_Audio_StdDescriptor_FeatureUnit_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_Feature.
*/
uint8_t UnitID; /**< ID value of this feature unit - must be a unique value within the device. */
uint8_t SourceID; /**< Source ID value of the audio source input into this feature unit. */
uint8_t ControlSize; /**< Size of each element in the \c ChannelControls array. */
uint8_t ChannelControls[3]; /**< Feature masks for the control channel, and each separate audio channel. */
uint8_t FeatureUnitStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_Audio_Descriptor_FeatureUnit_t;
/** \brief Audio class-specific Feature Unit Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific Feature Unit descriptor. This indicates to the host what features
* are present in the device's audio stream for basic control, such as per-channel volume. See the USB Audio
* specification for more details.
*
* \see \ref USB_Audio_Descriptor_FeatureUnit_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_Feature.
*/
uint8_t bUnitID; /**< ID value of this feature unit - must be a unique value within the device. */
uint8_t bSourceID; /**< Source ID value of the audio source input into this feature unit. */
uint8_t bControlSize; /**< Size of each element in the \c ChannelControls array. */
uint8_t bmaControls[3]; /**< Feature masks for the control channel, and each separate audio channel. */
uint8_t iFeature; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_Audio_StdDescriptor_FeatureUnit_t;
/** \brief Audio class-specific Streaming Audio Interface Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific streaming interface descriptor. This indicates to the host
* how audio streams within the device are formatted. See the USB Audio specification for more details.
*
* \see \ref USB_Audio_StdDescriptor_Interface_AS_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
*/
uint8_t TerminalLink; /**< ID value of the output terminal this descriptor is describing. */
uint8_t FrameDelay; /**< Delay in frames resulting from the complete sample processing from input to output. */
uint16_t AudioFormat; /**< Format of the audio stream, see Audio Device Formats specification. */
} ATTR_PACKED USB_Audio_Descriptor_Interface_AS_t;
/** \brief Audio class-specific Streaming Audio Interface Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific streaming interface descriptor. This indicates to the host
* how audio streams within the device are formatted. See the USB Audio specification for more details.
*
* \see \ref USB_Audio_Descriptor_Interface_AS_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
*/
uint8_t bTerminalLink; /**< ID value of the output terminal this descriptor is describing. */
uint8_t bDelay; /**< Delay in frames resulting from the complete sample processing from input to output. */
uint16_t wFormatTag; /**< Format of the audio stream, see Audio Device Formats specification. */
} ATTR_PACKED USB_Audio_StdDescriptor_Interface_AS_t;
/** \brief Audio class-specific Format Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific audio format descriptor. This is used to give the host full details
* about the number of channels, the sample resolution, acceptable sample frequencies and encoding method used
* in the device's audio streams. See the USB Audio specification for more details.
*
* \attention This descriptor <b>must</b> be followed by one or more \ref USB_Audio_SampleFreq_t elements containing
* the continuous or discrete sample frequencies.
*
* \see \ref USB_Audio_StdDescriptor_Format_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_FormatType.
*/
uint8_t FormatType; /**< Format of the audio stream, see Audio Device Formats specification. */
uint8_t Channels; /**< Total number of discrete channels in the stream. */
uint8_t SubFrameSize; /**< Size in bytes of each channel's sample data in the stream. */
uint8_t BitResolution; /**< Bits of resolution of each channel's samples in the stream. */
uint8_t TotalDiscreteSampleRates; /**< Total number of discrete sample frequencies supported by the device. When
* zero, this must be followed by the lower and upper continuous sampling
* frequencies supported by the device; otherwise, this must be followed
* by the given number of discrete sampling frequencies supported.
*/
} ATTR_PACKED USB_Audio_Descriptor_Format_t;
/** \brief 24-Bit Audio Frequency Structure.
*
* Type define for a 24-bit audio sample frequency structure. As GCC does not contain a built in 24-bit datatype,
* this this structure is used to build up the value instead. Fill this structure with the \ref AUDIO_SAMPLE_FREQ() macro.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t Byte1; /**< Lowest 8 bits of the 24-bit value. */
uint8_t Byte2; /**< Middle 8 bits of the 24-bit value. */
uint8_t Byte3; /**< Upper 8 bits of the 24-bit value. */
} ATTR_PACKED USB_Audio_SampleFreq_t;
/** \brief Audio class-specific Format Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific audio format descriptor. This is used to give the host full details
* about the number of channels, the sample resolution, acceptable sample frequencies and encoding method used
* in the device's audio streams. See the USB Audio specification for more details.
*
* \attention This descriptor <b>must</b> be followed by one or more 24-bit integer elements containing the continuous
* or discrete sample frequencies.
*
* \see \ref USB_Audio_Descriptor_Format_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Sub type value used to distinguish between audio class-specific descriptors,
* must be \ref AUDIO_DSUBTYPE_CSInterface_FormatType.
*/
uint8_t bDescriptorSubtype;/**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
*/
uint8_t bFormatType; /**< Format of the audio stream, see Audio Device Formats specification. */
uint8_t bNrChannels; /**< Total number of discrete channels in the stream. */
uint8_t bSubFrameSize; /**< Size in bytes of each channel's sample data in the stream. */
uint8_t bBitResolution; /**< Bits of resolution of each channel's samples in the stream. */
uint8_t bSampleFrequencyType; /**< Total number of sample frequencies supported by the device. When
* zero, this must be followed by the lower and upper continuous sampling
* frequencies supported by the device; otherwise, this must be followed
* by the given number of discrete sampling frequencies supported.
*/
} ATTR_PACKED USB_Audio_StdDescriptor_Format_t;
/** \brief Audio class-specific Streaming Endpoint Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific endpoint descriptor. This contains a regular endpoint
* descriptor with a few Audio-class-specific extensions. See the USB Audio specification for more details.
*
* \see \ref USB_Audio_StdDescriptor_StreamEndpoint_Std_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Endpoint_t Endpoint; /**< Standard endpoint descriptor describing the audio endpoint. */
uint8_t Refresh; /**< Always set to zero for Audio class devices. */
uint8_t SyncEndpointNumber; /**< Endpoint address to send synchronization information to, if needed (zero otherwise). */
} ATTR_PACKED USB_Audio_Descriptor_StreamEndpoint_Std_t;
/** \brief Audio class-specific Streaming Endpoint Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific endpoint descriptor. This contains a regular endpoint
* descriptor with a few Audio-class-specific extensions. See the USB Audio specification for more details.
*
* \see \ref USB_Audio_Descriptor_StreamEndpoint_Std_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a
* value given by the specific class.
*/
uint8_t bEndpointAddress; /**< Logical address of the endpoint within the device for the current
* configuration, including direction mask.
*/
uint8_t bmAttributes; /**< Endpoint attributes, comprised of a mask of the endpoint type (\c EP_TYPE_*)
* and attributes (\c ENDPOINT_ATTR_*) masks.
*/
uint16_t wMaxPacketSize; /**< Size of the endpoint bank, in bytes. This indicates the maximum packet size
* that the endpoint can receive at a time.
*/
uint8_t bInterval; /**< Polling interval in milliseconds for the endpoint if it is an INTERRUPT or
* ISOCHRONOUS type.
*/
uint8_t bRefresh; /**< Always set to zero for Audio class devices. */
uint8_t bSynchAddress; /**< Endpoint address to send synchronization information to, if needed (zero otherwise). */
} ATTR_PACKED USB_Audio_StdDescriptor_StreamEndpoint_Std_t;
/** \brief Audio class-specific Extended Endpoint Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific extended endpoint descriptor. This contains extra information
* on the usage of endpoints used to stream audio in and out of the USB Audio device, and follows an Audio
* class-specific extended endpoint descriptor. See the USB Audio specification for more details.
*
* \see \ref USB_Audio_StdDescriptor_StreamEndpoint_Spc_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSEndpoint_SubTypes_t enum.
*/
uint8_t Attributes; /**< Audio class-specific endpoint attributes, such as \ref AUDIO_EP_FULL_PACKETS_ONLY. */
uint8_t LockDelayUnits; /**< Units used for the LockDelay field, see Audio class specification. */
uint16_t LockDelay; /**< Time required to internally lock endpoint's internal clock recovery circuitry. */
} ATTR_PACKED USB_Audio_Descriptor_StreamEndpoint_Spc_t;
/** \brief Audio class-specific Extended Endpoint Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific extended endpoint descriptor. This contains extra information
* on the usage of endpoints used to stream audio in and out of the USB Audio device, and follows an Audio
* class-specific extended endpoint descriptor. See the USB Audio specification for more details.
*
* \see \ref USB_Audio_Descriptor_StreamEndpoint_Spc_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
* a value from the \ref Audio_CSEndpoint_SubTypes_t enum.
*/
uint8_t bmAttributes; /**< Audio class-specific endpoint attributes, such as \ref AUDIO_EP_FULL_PACKETS_ONLY. */
uint8_t bLockDelayUnits; /**< Units used for the LockDelay field, see Audio class specification. */
uint16_t wLockDelay; /**< Time required to internally lock endpoint's internal clock recovery circuitry. */
} ATTR_PACKED USB_Audio_StdDescriptor_StreamEndpoint_Spc_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,391 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB CDC Class driver.
*
* Common definitions and declarations for the library USB CDC Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassCDC
* \defgroup Group_USBClassCDCCommon Common Class Definitions
*
* \section Sec_USBClassCDCCommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* CDC Class.
*
* @{
*/
#ifndef _CDC_CLASS_COMMON_H_
#define _CDC_CLASS_COMMON_H_
/* Includes: */
#include "../../Core/StdDescriptors.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/USB.h instead.
#endif
/* Macros: */
/** \name Virtual Control Line Masks */
//@{
/** Mask for the DTR handshake line for use with the \ref CDC_REQ_SetControlLineState class-specific request
* from the host, to indicate that the DTR line state should be high.
*/
#define CDC_CONTROL_LINE_OUT_DTR (1 << 0)
/** Mask for the RTS handshake line for use with the \ref CDC_REQ_SetControlLineState class-specific request
* from the host, to indicate that the RTS line state should be high.
*/
#define CDC_CONTROL_LINE_OUT_RTS (1 << 1)
/** Mask for the DCD handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
* from the device to the host, to indicate that the DCD line state is currently high.
*/
#define CDC_CONTROL_LINE_IN_DCD (1 << 0)
/** Mask for the DSR handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
* from the device to the host, to indicate that the DSR line state is currently high.
*/
#define CDC_CONTROL_LINE_IN_DSR (1 << 1)
/** Mask for the BREAK handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
* from the device to the host, to indicate that the BREAK line state is currently high.
*/
#define CDC_CONTROL_LINE_IN_BREAK (1 << 2)
/** Mask for the RING handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
* from the device to the host, to indicate that the RING line state is currently high.
*/
#define CDC_CONTROL_LINE_IN_RING (1 << 3)
/** Mask for use with the \ref CDC_NOTIF_SerialState class-specific notification from the device to the host,
* to indicate that a framing error has occurred on the virtual serial port.
*/
#define CDC_CONTROL_LINE_IN_FRAMEERROR (1 << 4)
/** Mask for use with the \ref CDC_NOTIF_SerialState class-specific notification from the device to the host,
* to indicate that a parity error has occurred on the virtual serial port.
*/
#define CDC_CONTROL_LINE_IN_PARITYERROR (1 << 5)
/** Mask for use with the \ref CDC_NOTIF_SerialState class-specific notification from the device to the host,
* to indicate that a data overrun error has occurred on the virtual serial port.
*/
#define CDC_CONTROL_LINE_IN_OVERRUNERROR (1 << 6)
//@}
/** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a
* uniform structure but variable sized data payloads, thus cannot be represented accurately by
* a single \c typedef \c struct. A macro is used instead so that functional descriptors can be created
* easily by specifying the size of the payload. This allows \c sizeof() to work correctly.
*
* \param[in] DataSize Size in bytes of the CDC functional descriptor's data payload.
*/
#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
struct \
{ \
USB_Descriptor_Header_t Header; \
uint8_t SubType; \
uint8_t Data[DataSize]; \
}
/* Enums: */
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the CDC
* device class.
*/
enum CDC_Descriptor_ClassSubclassProtocol_t
{
CDC_CSCP_CDCClass = 0x02, /**< Descriptor Class value indicating that the device or interface
* belongs to the CDC class.
*/
CDC_CSCP_NoSpecificSubclass = 0x00, /**< Descriptor Subclass value indicating that the device or interface
* belongs to no specific subclass of the CDC class.
*/
CDC_CSCP_ACMSubclass = 0x02, /**< Descriptor Subclass value indicating that the device or interface
* belongs to the Abstract Control Model CDC subclass.
*/
CDC_CSCP_ATCommandProtocol = 0x01, /**< Descriptor Protocol value indicating that the device or interface
* belongs to the AT Command protocol of the CDC class.
*/
CDC_CSCP_NoSpecificProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
* belongs to no specific protocol of the CDC class.
*/
CDC_CSCP_VendorSpecificProtocol = 0xFF, /**< Descriptor Protocol value indicating that the device or interface
* belongs to a vendor-specific protocol of the CDC class.
*/
CDC_CSCP_CDCDataClass = 0x0A, /**< Descriptor Class value indicating that the device or interface
* belongs to the CDC Data class.
*/
CDC_CSCP_NoDataSubclass = 0x00, /**< Descriptor Subclass value indicating that the device or interface
* belongs to no specific subclass of the CDC data class.
*/
CDC_CSCP_NoDataProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
* belongs to no specific protocol of the CDC data class.
*/
};
/** Enum for the CDC class specific control requests that can be issued by the USB bus host. */
enum CDC_ClassRequests_t
{
CDC_REQ_SendEncapsulatedCommand = 0x00, /**< CDC class-specific request to send an encapsulated command to the device. */
CDC_REQ_GetEncapsulatedResponse = 0x01, /**< CDC class-specific request to retrieve an encapsulated command response from the device. */
CDC_REQ_SetLineEncoding = 0x20, /**< CDC class-specific request to set the current virtual serial port configuration settings. */
CDC_REQ_GetLineEncoding = 0x21, /**< CDC class-specific request to get the current virtual serial port configuration settings. */
CDC_REQ_SetControlLineState = 0x22, /**< CDC class-specific request to set the current virtual serial port handshake line states. */
CDC_REQ_SendBreak = 0x23, /**< CDC class-specific request to send a break to the receiver via the carrier channel. */
};
/** Enum for the CDC class specific notification requests that can be issued by a CDC device to a host. */
enum CDC_ClassNotifications_t
{
CDC_NOTIF_SerialState = 0x20, /**< Notification type constant for a change in the virtual serial port
* handshake line states, for use with a \ref USB_Request_Header_t
* notification structure when sent to the host via the CDC notification
* endpoint.
*/
};
/** Enum for the CDC class specific interface descriptor subtypes. */
enum CDC_DescriptorSubtypes_t
{
CDC_DSUBTYPE_CSInterface_Header = 0x00, /**< CDC class-specific Header functional descriptor. */
CDC_DSUBTYPE_CSInterface_CallManagement = 0x01, /**< CDC class-specific Call Management functional descriptor. */
CDC_DSUBTYPE_CSInterface_ACM = 0x02, /**< CDC class-specific Abstract Control Model functional descriptor. */
CDC_DSUBTYPE_CSInterface_DirectLine = 0x03, /**< CDC class-specific Direct Line functional descriptor. */
CDC_DSUBTYPE_CSInterface_TelephoneRinger = 0x04, /**< CDC class-specific Telephone Ringer functional descriptor. */
CDC_DSUBTYPE_CSInterface_TelephoneCall = 0x05, /**< CDC class-specific Telephone Call functional descriptor. */
CDC_DSUBTYPE_CSInterface_Union = 0x06, /**< CDC class-specific Union functional descriptor. */
CDC_DSUBTYPE_CSInterface_CountrySelection = 0x07, /**< CDC class-specific Country Selection functional descriptor. */
CDC_DSUBTYPE_CSInterface_TelephoneOpModes = 0x08, /**< CDC class-specific Telephone Operation Modes functional descriptor. */
CDC_DSUBTYPE_CSInterface_USBTerminal = 0x09, /**< CDC class-specific USB Terminal functional descriptor. */
CDC_DSUBTYPE_CSInterface_NetworkChannel = 0x0A, /**< CDC class-specific Network Channel functional descriptor. */
CDC_DSUBTYPE_CSInterface_ProtocolUnit = 0x0B, /**< CDC class-specific Protocol Unit functional descriptor. */
CDC_DSUBTYPE_CSInterface_ExtensionUnit = 0x0C, /**< CDC class-specific Extension Unit functional descriptor. */
CDC_DSUBTYPE_CSInterface_MultiChannel = 0x0D, /**< CDC class-specific Multi-Channel Management functional descriptor. */
CDC_DSUBTYPE_CSInterface_CAPI = 0x0E, /**< CDC class-specific Common ISDN API functional descriptor. */
CDC_DSUBTYPE_CSInterface_Ethernet = 0x0F, /**< CDC class-specific Ethernet functional descriptor. */
CDC_DSUBTYPE_CSInterface_ATM = 0x10, /**< CDC class-specific Asynchronous Transfer Mode functional descriptor. */
};
/** Enum for the possible line encoding formats of a virtual serial port. */
enum CDC_LineEncodingFormats_t
{
CDC_LINEENCODING_OneStopBit = 0, /**< Each frame contains one stop bit. */
CDC_LINEENCODING_OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits. */
CDC_LINEENCODING_TwoStopBits = 2, /**< Each frame contains two stop bits. */
};
/** Enum for the possible line encoding parity settings of a virtual serial port. */
enum CDC_LineEncodingParity_t
{
CDC_PARITY_None = 0, /**< No parity bit mode on each frame. */
CDC_PARITY_Odd = 1, /**< Odd parity bit mode on each frame. */
CDC_PARITY_Even = 2, /**< Even parity bit mode on each frame. */
CDC_PARITY_Mark = 3, /**< Mark parity bit mode on each frame. */
CDC_PARITY_Space = 4, /**< Space parity bit mode on each frame. */
};
/* Type Defines: */
/** \brief CDC class-specific Functional Header Descriptor (LUFA naming conventions).
*
* Type define for a CDC class-specific functional header descriptor. This indicates to the host that the device
* contains one or more CDC functional data descriptors, which give the CDC interface's capabilities and configuration.
* See the CDC class specification for more details.
*
* \see \ref USB_CDC_StdDescriptor_FunctionalHeader_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between CDC class-specific descriptors,
* must be \ref CDC_DSUBTYPE_CSInterface_Header.
*/
uint16_t CDCSpecification; /**< Version number of the CDC specification implemented by the device,
* encoded in BCD format.
*
* \see \ref VERSION_BCD() utility macro.
*/
} ATTR_PACKED USB_CDC_Descriptor_FunctionalHeader_t;
/** \brief CDC class-specific Functional Header Descriptor (USB-IF naming conventions).
*
* Type define for a CDC class-specific functional header descriptor. This indicates to the host that the device
* contains one or more CDC functional data descriptors, which give the CDC interface's capabilities and configuration.
* See the CDC class specification for more details.
*
* \see \ref USB_CDC_Descriptor_FunctionalHeader_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bFunctionLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubType; /**< Sub type value used to distinguish between CDC class-specific descriptors,
* must be \ref CDC_DSUBTYPE_CSInterface_Header.
*/
uint16_t bcdCDC; /**< Version number of the CDC specification implemented by the device, encoded in BCD format.
*
* \see \ref VERSION_BCD() utility macro.
*/
} ATTR_PACKED USB_CDC_StdDescriptor_FunctionalHeader_t;
/** \brief CDC class-specific Functional ACM Descriptor (LUFA naming conventions).
*
* Type define for a CDC class-specific functional ACM descriptor. This indicates to the host that the CDC interface
* supports the CDC ACM subclass of the CDC specification. See the CDC class specification for more details.
*
* \see \ref USB_CDC_StdDescriptor_FunctionalACM_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between CDC class-specific descriptors,
* must be \ref CDC_DSUBTYPE_CSInterface_ACM.
*/
uint8_t Capabilities; /**< Capabilities of the ACM interface, given as a bit mask. For most devices,
* this should be set to a fixed value of \c 0x06 - for other capabilities, refer
* to the CDC ACM specification.
*/
} ATTR_PACKED USB_CDC_Descriptor_FunctionalACM_t;
/** \brief CDC class-specific Functional ACM Descriptor (USB-IF naming conventions).
*
* Type define for a CDC class-specific functional ACM descriptor. This indicates to the host that the CDC interface
* supports the CDC ACM subclass of the CDC specification. See the CDC class specification for more details.
*
* \see \ref USB_CDC_Descriptor_FunctionalACM_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bFunctionLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubType; /**< Sub type value used to distinguish between CDC class-specific descriptors,
* must be \ref CDC_DSUBTYPE_CSInterface_ACM.
*/
uint8_t bmCapabilities; /**< Capabilities of the ACM interface, given as a bit mask. For most devices,
* this should be set to a fixed value of 0x06 - for other capabilities, refer
* to the CDC ACM specification.
*/
} ATTR_PACKED USB_CDC_StdDescriptor_FunctionalACM_t;
/** \brief CDC class-specific Functional Union Descriptor (LUFA naming conventions).
*
* Type define for a CDC class-specific functional Union descriptor. This indicates to the host that specific
* CDC control and data interfaces are related. See the CDC class specification for more details.
*
* \see \ref USB_CDC_StdDescriptor_FunctionalUnion_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between CDC class-specific descriptors,
* must be \ref CDC_DSUBTYPE_CSInterface_Union.
*/
uint8_t MasterInterfaceNumber; /**< Interface number of the CDC Control interface. */
uint8_t SlaveInterfaceNumber; /**< Interface number of the CDC Data interface. */
} ATTR_PACKED USB_CDC_Descriptor_FunctionalUnion_t;
/** \brief CDC class-specific Functional Union Descriptor (USB-IF naming conventions).
*
* Type define for a CDC class-specific functional Union descriptor. This indicates to the host that specific
* CDC control and data interfaces are related. See the CDC class specification for more details.
*
* \see \ref USB_CDC_Descriptor_FunctionalUnion_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bFunctionLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubType; /**< Sub type value used to distinguish between CDC class-specific descriptors,
* must be \ref CDC_DSUBTYPE_CSInterface_Union.
*/
uint8_t bMasterInterface; /**< Interface number of the CDC Control interface. */
uint8_t bSlaveInterface0; /**< Interface number of the CDC Data interface. */
} ATTR_PACKED USB_CDC_StdDescriptor_FunctionalUnion_t;
/** \brief CDC Virtual Serial Port Line Encoding Settings Structure.
*
* Type define for a CDC Line Encoding structure, used to hold the various encoding parameters for a virtual
* serial port.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef 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
* \ref CDC_LineEncodingFormats_t enum.
*/
uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
* \ref CDC_LineEncodingParity_t enum.
*/
uint8_t DataBits; /**< Bits of data per character of the virtual serial port. */
} ATTR_PACKED CDC_LineEncoding_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,682 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB HID Class driver.
*
* Common definitions and declarations for the library USB HID Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassHID
* \defgroup Group_USBClassHIDCommon Common Class Definitions
*
* \section Sec_USBClassHIDCommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* HID Class.
*
* @{
*/
#ifndef _HID_CLASS_COMMON_H_
#define _HID_CLASS_COMMON_H_
/* Includes: */
#include "../../Core/StdDescriptors.h"
#include "HIDParser.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/USB.h instead.
#endif
/* Macros: */
/** \name Keyboard Standard Report Modifier Masks */
//@{
/** Constant for a keyboard report modifier byte, indicating that the keyboard's left control key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_LEFTCTRL (1 << 0)
/** Constant for a keyboard report modifier byte, indicating that the keyboard's left shift key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_LEFTSHIFT (1 << 1)
/** Constant for a keyboard report modifier byte, indicating that the keyboard's left alt key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_LEFTALT (1 << 2)
/** Constant for a keyboard report modifier byte, indicating that the keyboard's left GUI key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_LEFTGUI (1 << 3)
/** Constant for a keyboard report modifier byte, indicating that the keyboard's right control key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_RIGHTCTRL (1 << 4)
/** Constant for a keyboard report modifier byte, indicating that the keyboard's right shift key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_RIGHTSHIFT (1 << 5)
/** Constant for a keyboard report modifier byte, indicating that the keyboard's right alt key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_RIGHTALT (1 << 6)
/** Constant for a keyboard report modifier byte, indicating that the keyboard's right GUI key is currently pressed. */
#define HID_KEYBOARD_MODIFIER_RIGHTGUI (1 << 7)
//@}
/** \name Keyboard Standard Report LED Masks */
//@{
/** Constant for a keyboard output report LED byte, indicating that the host's NUM LOCK mode is currently set. */
#define HID_KEYBOARD_LED_NUMLOCK (1 << 0)
/** Constant for a keyboard output report LED byte, indicating that the host's CAPS LOCK mode is currently set. */
#define HID_KEYBOARD_LED_CAPSLOCK (1 << 1)
/** Constant for a keyboard output report LED byte, indicating that the host's SCROLL LOCK mode is currently set. */
#define HID_KEYBOARD_LED_SCROLLLOCK (1 << 2)
/** Constant for a keyboard output report LED byte, indicating that the host's COMPOSE mode is currently set. */
#define HID_KEYBOARD_LED_COMPOSE (1 << 3)
/** Constant for a keyboard output report LED byte, indicating that the host's KANA mode is currently set. */
#define HID_KEYBOARD_LED_KANA (1 << 4)
//@}
/** \name Keyboard Standard Report Key Scan-codes */
//@{
#define HID_KEYBOARD_SC_ERROR_ROLLOVER 0x01
#define HID_KEYBOARD_SC_POST_FAIL 0x02
#define HID_KEYBOARD_SC_ERROR_UNDEFINED 0x03
#define HID_KEYBOARD_SC_A 0x04
#define HID_KEYBOARD_SC_B 0x05
#define HID_KEYBOARD_SC_C 0x06
#define HID_KEYBOARD_SC_D 0x07
#define HID_KEYBOARD_SC_E 0x08
#define HID_KEYBOARD_SC_F 0x09
#define HID_KEYBOARD_SC_G 0x0A
#define HID_KEYBOARD_SC_H 0x0B
#define HID_KEYBOARD_SC_I 0x0C
#define HID_KEYBOARD_SC_J 0x0D
#define HID_KEYBOARD_SC_K 0x0E
#define HID_KEYBOARD_SC_L 0x0F
#define HID_KEYBOARD_SC_M 0x10
#define HID_KEYBOARD_SC_N 0x11
#define HID_KEYBOARD_SC_O 0x12
#define HID_KEYBOARD_SC_P 0x13
#define HID_KEYBOARD_SC_Q 0x14
#define HID_KEYBOARD_SC_R 0x15
#define HID_KEYBOARD_SC_S 0x16
#define HID_KEYBOARD_SC_T 0x17
#define HID_KEYBOARD_SC_U 0x18
#define HID_KEYBOARD_SC_V 0x19
#define HID_KEYBOARD_SC_W 0x1A
#define HID_KEYBOARD_SC_X 0x1B
#define HID_KEYBOARD_SC_Y 0x1C
#define HID_KEYBOARD_SC_Z 0x1D
#define HID_KEYBOARD_SC_1_AND_EXCLAMATION 0x1E
#define HID_KEYBOARD_SC_2_AND_AT 0x1F
#define HID_KEYBOARD_SC_3_AND_HASHMARK 0x20
#define HID_KEYBOARD_SC_4_AND_DOLLAR 0x21
#define HID_KEYBOARD_SC_5_AND_PERCENTAGE 0x22
#define HID_KEYBOARD_SC_6_AND_CARET 0x23
#define HID_KEYBOARD_SC_7_AND_AMPERSAND 0x24
#define HID_KEYBOARD_SC_8_AND_ASTERISK 0x25
#define HID_KEYBOARD_SC_9_AND_OPENING_PARENTHESIS 0x26
#define HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS 0x27
#define HID_KEYBOARD_SC_ENTER 0x28
#define HID_KEYBOARD_SC_ESCAPE 0x29
#define HID_KEYBOARD_SC_BACKSPACE 0x2A
#define HID_KEYBOARD_SC_TAB 0x2B
#define HID_KEYBOARD_SC_SPACE 0x2C
#define HID_KEYBOARD_SC_MINUS_AND_UNDERSCORE 0x2D
#define HID_KEYBOARD_SC_EQUAL_AND_PLUS 0x2E
#define HID_KEYBOARD_SC_OPENING_BRACKET_AND_OPENING_BRACE 0x2F
#define HID_KEYBOARD_SC_CLOSING_BRACKET_AND_CLOSING_BRACE 0x30
#define HID_KEYBOARD_SC_BACKSLASH_AND_PIPE 0x31
#define HID_KEYBOARD_SC_NON_US_HASHMARK_AND_TILDE 0x32
#define HID_KEYBOARD_SC_SEMICOLON_AND_COLON 0x33
#define HID_KEYBOARD_SC_APOSTROPHE_AND_QUOTE 0x34
#define HID_KEYBOARD_SC_GRAVE_ACCENT_AND_TILDE 0x35
#define HID_KEYBOARD_SC_COMMA_AND_LESS_THAN_SIGN 0x36
#define HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN 0x37
#define HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK 0x38
#define HID_KEYBOARD_SC_CAPS_LOCK 0x39
#define HID_KEYBOARD_SC_F1 0x3A
#define HID_KEYBOARD_SC_F2 0x3B
#define HID_KEYBOARD_SC_F3 0x3C
#define HID_KEYBOARD_SC_F4 0x3D
#define HID_KEYBOARD_SC_F5 0x3E
#define HID_KEYBOARD_SC_F6 0x3F
#define HID_KEYBOARD_SC_F7 0x40
#define HID_KEYBOARD_SC_F8 0x41
#define HID_KEYBOARD_SC_F9 0x42
#define HID_KEYBOARD_SC_F10 0x43
#define HID_KEYBOARD_SC_F11 0x44
#define HID_KEYBOARD_SC_F12 0x45
#define HID_KEYBOARD_SC_PRINT_SCREEN 0x46
#define HID_KEYBOARD_SC_SCROLL_LOCK 0x47
#define HID_KEYBOARD_SC_PAUSE 0x48
#define HID_KEYBOARD_SC_INSERT 0x49
#define HID_KEYBOARD_SC_HOME 0x4A
#define HID_KEYBOARD_SC_PAGE_UP 0x4B
#define HID_KEYBOARD_SC_DELETE 0x4C
#define HID_KEYBOARD_SC_END 0x4D
#define HID_KEYBOARD_SC_PAGE_DOWN 0x4E
#define HID_KEYBOARD_SC_RIGHT_ARROW 0x4F
#define HID_KEYBOARD_SC_LEFT_ARROW 0x50
#define HID_KEYBOARD_SC_DOWN_ARROW 0x51
#define HID_KEYBOARD_SC_UP_ARROW 0x52
#define HID_KEYBOARD_SC_NUM_LOCK 0x53
#define HID_KEYBOARD_SC_KEYPAD_SLASH 0x54
#define HID_KEYBOARD_SC_KEYPAD_ASTERISK 0x55
#define HID_KEYBOARD_SC_KEYPAD_MINUS 0x56
#define HID_KEYBOARD_SC_KEYPAD_PLUS 0x57
#define HID_KEYBOARD_SC_KEYPAD_ENTER 0x58
#define HID_KEYBOARD_SC_KEYPAD_1_AND_END 0x59
#define HID_KEYBOARD_SC_KEYPAD_2_AND_DOWN_ARROW 0x5A
#define HID_KEYBOARD_SC_KEYPAD_3_AND_PAGE_DOWN 0x5B
#define HID_KEYBOARD_SC_KEYPAD_4_AND_LEFT_ARROW 0x5C
#define HID_KEYBOARD_SC_KEYPAD_5 0x5D
#define HID_KEYBOARD_SC_KEYPAD_6_AND_RIGHT_ARROW 0x5E
#define HID_KEYBOARD_SC_KEYPAD_7_AND_HOME 0x5F
#define HID_KEYBOARD_SC_KEYPAD_8_AND_UP_ARROW 0x60
#define HID_KEYBOARD_SC_KEYPAD_9_AND_PAGE_UP 0x61
#define HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT 0x62
#define HID_KEYBOARD_SC_KEYPAD_DOT_AND_DELETE 0x63
#define HID_KEYBOARD_SC_NON_US_BACKSLASH_AND_PIPE 0x64
#define HID_KEYBOARD_SC_APPLICATION 0x65
#define HID_KEYBOARD_SC_POWER 0x66
#define HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN 0x67
#define HID_KEYBOARD_SC_F13 0x68
#define HID_KEYBOARD_SC_F14 0x69
#define HID_KEYBOARD_SC_F15 0x6A
#define HID_KEYBOARD_SC_F16 0x6B
#define HID_KEYBOARD_SC_F17 0x6C
#define HID_KEYBOARD_SC_F18 0x6D
#define HID_KEYBOARD_SC_F19 0x6E
#define HID_KEYBOARD_SC_F20 0x6F
#define HID_KEYBOARD_SC_F21 0x70
#define HID_KEYBOARD_SC_F22 0x71
#define HID_KEYBOARD_SC_F23 0x72
#define HID_KEYBOARD_SC_F24 0x73
#define HID_KEYBOARD_SC_EXECUTE 0x74
#define HID_KEYBOARD_SC_HELP 0x75
#define HID_KEYBOARD_SC_MENU 0x76
#define HID_KEYBOARD_SC_SELECT 0x77
#define HID_KEYBOARD_SC_STOP 0x78
#define HID_KEYBOARD_SC_AGAIN 0x79
#define HID_KEYBOARD_SC_UNDO 0x7A
#define HID_KEYBOARD_SC_CUT 0x7B
#define HID_KEYBOARD_SC_COPY 0x7C
#define HID_KEYBOARD_SC_PASTE 0x7D
#define HID_KEYBOARD_SC_FIND 0x7E
#define HID_KEYBOARD_SC_MUTE 0x7F
#define HID_KEYBOARD_SC_VOLUME_UP 0x80
#define HID_KEYBOARD_SC_VOLUME_DOWN 0x81
#define HID_KEYBOARD_SC_LOCKING_CAPS_LOCK 0x82
#define HID_KEYBOARD_SC_LOCKING_NUM_LOCK 0x83
#define HID_KEYBOARD_SC_LOCKING_SCROLL_LOCK 0x84
#define HID_KEYBOARD_SC_KEYPAD_COMMA 0x85
#define HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN_AS400 0x86
#define HID_KEYBOARD_SC_INTERNATIONAL1 0x87
#define HID_KEYBOARD_SC_INTERNATIONAL2 0x88
#define HID_KEYBOARD_SC_INTERNATIONAL3 0x89
#define HID_KEYBOARD_SC_INTERNATIONAL4 0x8A
#define HID_KEYBOARD_SC_INTERNATIONAL5 0x8B
#define HID_KEYBOARD_SC_INTERNATIONAL6 0x8C
#define HID_KEYBOARD_SC_INTERNATIONAL7 0x8D
#define HID_KEYBOARD_SC_INTERNATIONAL8 0x8E
#define HID_KEYBOARD_SC_INTERNATIONAL9 0x8F
#define HID_KEYBOARD_SC_LANG1 0x90
#define HID_KEYBOARD_SC_LANG2 0x91
#define HID_KEYBOARD_SC_LANG3 0x92
#define HID_KEYBOARD_SC_LANG4 0x93
#define HID_KEYBOARD_SC_LANG5 0x94
#define HID_KEYBOARD_SC_LANG6 0x95
#define HID_KEYBOARD_SC_LANG7 0x96
#define HID_KEYBOARD_SC_LANG8 0x97
#define HID_KEYBOARD_SC_LANG9 0x98
#define HID_KEYBOARD_SC_ALTERNATE_ERASE 0x99
#define HID_KEYBOARD_SC_SYSREQ 0x9A
#define HID_KEYBOARD_SC_CANCEL 0x9B
#define HID_KEYBOARD_SC_CLEAR 0x9C
#define HID_KEYBOARD_SC_PRIOR 0x9D
#define HID_KEYBOARD_SC_RETURN 0x9E
#define HID_KEYBOARD_SC_SEPARATOR 0x9F
#define HID_KEYBOARD_SC_OUT 0xA0
#define HID_KEYBOARD_SC_OPER 0xA1
#define HID_KEYBOARD_SC_CLEAR_AND_AGAIN 0xA2
#define HID_KEYBOARD_SC_CRSEL_AND_PROPS 0xA3
#define HID_KEYBOARD_SC_EXSEL 0xA4
#define HID_KEYBOARD_SC_KEYPAD_00 0xB0
#define HID_KEYBOARD_SC_KEYPAD_000 0xB1
#define HID_KEYBOARD_SC_THOUSANDS_SEPARATOR 0xB2
#define HID_KEYBOARD_SC_DECIMAL_SEPARATOR 0xB3
#define HID_KEYBOARD_SC_CURRENCY_UNIT 0xB4
#define HID_KEYBOARD_SC_CURRENCY_SUB_UNIT 0xB5
#define HID_KEYBOARD_SC_KEYPAD_OPENING_PARENTHESIS 0xB6
#define HID_KEYBOARD_SC_KEYPAD_CLOSING_PARENTHESIS 0xB7
#define HID_KEYBOARD_SC_KEYPAD_OPENING_BRACE 0xB8
#define HID_KEYBOARD_SC_KEYPAD_CLOSING_BRACE 0xB9
#define HID_KEYBOARD_SC_KEYPAD_TAB 0xBA
#define HID_KEYBOARD_SC_KEYPAD_BACKSPACE 0xBB
#define HID_KEYBOARD_SC_KEYPAD_A 0xBC
#define HID_KEYBOARD_SC_KEYPAD_B 0xBD
#define HID_KEYBOARD_SC_KEYPAD_C 0xBE
#define HID_KEYBOARD_SC_KEYPAD_D 0xBF
#define HID_KEYBOARD_SC_KEYPAD_E 0xC0
#define HID_KEYBOARD_SC_KEYPAD_F 0xC1
#define HID_KEYBOARD_SC_KEYPAD_XOR 0xC2
#define HID_KEYBOARD_SC_KEYPAD_CARET 0xC3
#define HID_KEYBOARD_SC_KEYPAD_PERCENTAGE 0xC4
#define HID_KEYBOARD_SC_KEYPAD_LESS_THAN_SIGN 0xC5
#define HID_KEYBOARD_SC_KEYPAD_GREATER_THAN_SIGN 0xC6
#define HID_KEYBOARD_SC_KEYPAD_AMP 0xC7
#define HID_KEYBOARD_SC_KEYPAD_AMP_AMP 0xC8
#define HID_KEYBOARD_SC_KEYPAD_PIPE 0xC9
#define HID_KEYBOARD_SC_KEYPAD_PIPE_PIPE 0xCA
#define HID_KEYBOARD_SC_KEYPAD_COLON 0xCB
#define HID_KEYBOARD_SC_KEYPAD_HASHMARK 0xCC
#define HID_KEYBOARD_SC_KEYPAD_SPACE 0xCD
#define HID_KEYBOARD_SC_KEYPAD_AT 0xCE
#define HID_KEYBOARD_SC_KEYPAD_EXCLAMATION_SIGN 0xCF
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_STORE 0xD0
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_RECALL 0xD1
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_CLEAR 0xD2
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_ADD 0xD3
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_SUBTRACT 0xD4
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_MULTIPLY 0xD5
#define HID_KEYBOARD_SC_KEYPAD_MEMORY_DIVIDE 0xD6
#define HID_KEYBOARD_SC_KEYPAD_PLUS_AND_MINUS 0xD7
#define HID_KEYBOARD_SC_KEYPAD_CLEAR 0xD8
#define HID_KEYBOARD_SC_KEYPAD_CLEAR_ENTRY 0xD9
#define HID_KEYBOARD_SC_KEYPAD_BINARY 0xDA
#define HID_KEYBOARD_SC_KEYPAD_OCTAL 0xDB
#define HID_KEYBOARD_SC_KEYPAD_DECIMAL 0xDC
#define HID_KEYBOARD_SC_KEYPAD_HEXADECIMAL 0xDD
#define HID_KEYBOARD_SC_LEFT_CONTROL 0xE0
#define HID_KEYBOARD_SC_LEFT_SHIFT 0xE1
#define HID_KEYBOARD_SC_LEFT_ALT 0xE2
#define HID_KEYBOARD_SC_LEFT_GUI 0xE3
#define HID_KEYBOARD_SC_RIGHT_CONTROL 0xE4
#define HID_KEYBOARD_SC_RIGHT_SHIFT 0xE5
#define HID_KEYBOARD_SC_RIGHT_ALT 0xE6
#define HID_KEYBOARD_SC_RIGHT_GUI 0xE7
#define HID_KEYBOARD_SC_MEDIA_PLAY 0xE8
#define HID_KEYBOARD_SC_MEDIA_STOP 0xE9
#define HID_KEYBOARD_SC_MEDIA_PREVIOUS_TRACK 0xEA
#define HID_KEYBOARD_SC_MEDIA_NEXT_TRACK 0xEB
#define HID_KEYBOARD_SC_MEDIA_EJECT 0xEC
#define HID_KEYBOARD_SC_MEDIA_VOLUME_UP 0xED
#define HID_KEYBOARD_SC_MEDIA_VOLUME_DOWN 0xEE
#define HID_KEYBOARD_SC_MEDIA_MUTE 0xEF
#define HID_KEYBOARD_SC_MEDIA_WWW 0xF0
#define HID_KEYBOARD_SC_MEDIA_BACKWARD 0xF1
#define HID_KEYBOARD_SC_MEDIA_FORWARD 0xF2
#define HID_KEYBOARD_SC_MEDIA_CANCEL 0xF3
#define HID_KEYBOARD_SC_MEDIA_SEARCH 0xF4
#define HID_KEYBOARD_SC_MEDIA_SLEEP 0xF8
#define HID_KEYBOARD_SC_MEDIA_LOCK 0xF9
#define HID_KEYBOARD_SC_MEDIA_RELOAD 0xFA
#define HID_KEYBOARD_SC_MEDIA_CALCULATOR 0xFB
//@}
/** \name Common HID Device Report Descriptors */
//@{
/** \hideinitializer
* A list of HID report item array elements that describe a typical HID USB Joystick. The resulting report
* descriptor is structured according to the following layout:
*
* \code
* struct
* {
* intA_t X; // Signed X axis value
* intA_t Y; // Signed Y axis value
* intA_t Z; // Signed Z axis value
* uintB_t Buttons; // Pressed buttons bitmask
* } Joystick_Report;
* \endcode
*
* Where \c uintA_t is a type large enough to hold the ranges of the signed \c MinAxisVal and \c MaxAxisVal values,
* and \c intB_t is a type large enough to hold one bit per button.
*
* \param[in] MinAxisVal Minimum logical axis value (16-bit).
* \param[in] MaxAxisVal Maximum logical axis value (16-bit).
* \param[in] MinPhysicalVal Minimum physical axis value, for movement resolution calculations (16-bit).
* \param[in] MaxPhysicalVal Maximum physical axis value, for movement resolution calculations (16-bit).
* \param[in] Buttons Total number of buttons in the device (8-bit).
*/
#define HID_DESCRIPTOR_JOYSTICK(MinAxisVal, MaxAxisVal, MinPhysicalVal, MaxPhysicalVal, Buttons) \
HID_RI_USAGE_PAGE(8, 0x01), \
HID_RI_USAGE(8, 0x04), \
HID_RI_COLLECTION(8, 0x01), \
HID_RI_USAGE(8, 0x01), \
HID_RI_COLLECTION(8, 0x00), \
HID_RI_USAGE(8, 0x30), \
HID_RI_USAGE(8, 0x31), \
HID_RI_USAGE(8, 0x32), \
HID_RI_LOGICAL_MINIMUM(16, MinAxisVal), \
HID_RI_LOGICAL_MAXIMUM(16, MaxAxisVal), \
HID_RI_PHYSICAL_MINIMUM(16, MinPhysicalVal), \
HID_RI_PHYSICAL_MAXIMUM(16, MaxPhysicalVal), \
HID_RI_REPORT_COUNT(8, 3), \
HID_RI_REPORT_SIZE(8, (((MinAxisVal >= -128) && (MaxAxisVal <= 127)) ? 8 : 16)), \
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RI_END_COLLECTION(0), \
HID_RI_USAGE_PAGE(8, 0x09), \
HID_RI_USAGE_MINIMUM(8, 0x01), \
HID_RI_USAGE_MAXIMUM(8, Buttons), \
HID_RI_LOGICAL_MINIMUM(8, 0x00), \
HID_RI_LOGICAL_MAXIMUM(8, 0x01), \
HID_RI_REPORT_SIZE(8, 0x01), \
HID_RI_REPORT_COUNT(8, Buttons), \
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RI_REPORT_SIZE(8, (Buttons % 8) ? (8 - (Buttons % 8)) : 0), \
HID_RI_REPORT_COUNT(8, 0x01), \
HID_RI_INPUT(8, HID_IOF_CONSTANT), \
HID_RI_END_COLLECTION(0)
/** \hideinitializer
* A list of HID report item array elements that describe a typical HID USB keyboard. The resulting report descriptor
* is compatible with \ref USB_KeyboardReport_Data_t when \c MaxKeys is equal to 6. For other values, the report will
* be structured according to the following layout:
*
* \code
* struct
* {
* uint8_t Modifier; // Keyboard modifier byte indicating pressed modifier keys (\c HID_KEYBOARD_MODIFER_* masks)
* uint8_t Reserved; // Reserved for OEM use, always set to 0.
* uint8_t KeyCode[MaxKeys]; // Length determined by the number of keys that can be reported
* } Keyboard_Report;
* \endcode
*
* \param[in] MaxKeys Number of simultaneous keys that can be reported at the one time (8-bit).
*/
#define HID_DESCRIPTOR_KEYBOARD(MaxKeys) \
HID_RI_USAGE_PAGE(8, 0x01), \
HID_RI_USAGE(8, 0x06), \
HID_RI_COLLECTION(8, 0x01), \
HID_RI_USAGE_PAGE(8, 0x07), \
HID_RI_USAGE_MINIMUM(8, 0xE0), \
HID_RI_USAGE_MAXIMUM(8, 0xE7), \
HID_RI_LOGICAL_MINIMUM(8, 0x00), \
HID_RI_LOGICAL_MAXIMUM(8, 0x01), \
HID_RI_REPORT_SIZE(8, 0x01), \
HID_RI_REPORT_COUNT(8, 0x08), \
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RI_REPORT_COUNT(8, 0x01), \
HID_RI_REPORT_SIZE(8, 0x08), \
HID_RI_INPUT(8, HID_IOF_CONSTANT), \
HID_RI_USAGE_PAGE(8, 0x08), \
HID_RI_USAGE_MINIMUM(8, 0x01), \
HID_RI_USAGE_MAXIMUM(8, 0x05), \
HID_RI_REPORT_COUNT(8, 0x05), \
HID_RI_REPORT_SIZE(8, 0x01), \
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), \
HID_RI_REPORT_COUNT(8, 0x01), \
HID_RI_REPORT_SIZE(8, 0x03), \
HID_RI_OUTPUT(8, HID_IOF_CONSTANT), \
HID_RI_LOGICAL_MINIMUM(8, 0x00), \
HID_RI_LOGICAL_MAXIMUM(8, 0xFF), \
HID_RI_USAGE_PAGE(8, 0x07), \
HID_RI_USAGE_MINIMUM(8, 0x00), \
HID_RI_USAGE_MAXIMUM(8, 0xFF), \
HID_RI_REPORT_COUNT(8, MaxKeys), \
HID_RI_REPORT_SIZE(8, 0x08), \
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), \
HID_RI_END_COLLECTION(0)
/** \hideinitializer
* A list of HID report item array elements that describe a typical HID USB mouse. The resulting report descriptor
* is compatible with \ref USB_MouseReport_Data_t if the \c MinAxisVal and \c MaxAxisVal values fit within a \c int8_t range
* and the number of Buttons is less than 8. For other values, the report is structured according to the following layout:
*
* \code
* struct
* {
* uintA_t Buttons; // Pressed buttons bitmask
* intB_t X; // X axis value
* intB_t Y; // Y axis value
* } Mouse_Report;
* \endcode
*
* Where \c intA_t is a type large enough to hold one bit per button, and \c intB_t is a type large enough to hold the
* ranges of the signed \c MinAxisVal and \c MaxAxisVal values.
*
* \param[in] MinAxisVal Minimum X/Y logical axis value (16-bit).
* \param[in] MaxAxisVal Maximum X/Y logical axis value (16-bit).
* \param[in] MinPhysicalVal Minimum X/Y physical axis value, for movement resolution calculations (16-bit).
* \param[in] MaxPhysicalVal Maximum X/Y physical axis value, for movement resolution calculations (16-bit).
* \param[in] Buttons Total number of buttons in the device (8-bit).
* \param[in] AbsoluteCoords Boolean \c true to use absolute X/Y coordinates (e.g. touchscreen).
*/
#define HID_DESCRIPTOR_MOUSE(MinAxisVal, MaxAxisVal, MinPhysicalVal, MaxPhysicalVal, Buttons, AbsoluteCoords) \
HID_RI_USAGE_PAGE(8, 0x01), \
HID_RI_USAGE(8, 0x02), \
HID_RI_COLLECTION(8, 0x01), \
HID_RI_USAGE(8, 0x01), \
HID_RI_COLLECTION(8, 0x00), \
HID_RI_USAGE_PAGE(8, 0x09), \
HID_RI_USAGE_MINIMUM(8, 0x01), \
HID_RI_USAGE_MAXIMUM(8, Buttons), \
HID_RI_LOGICAL_MINIMUM(8, 0x00), \
HID_RI_LOGICAL_MAXIMUM(8, 0x01), \
HID_RI_REPORT_COUNT(8, Buttons), \
HID_RI_REPORT_SIZE(8, 0x01), \
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RI_REPORT_COUNT(8, 0x01), \
HID_RI_REPORT_SIZE(8, (Buttons % 8) ? (8 - (Buttons % 8)) : 0), \
HID_RI_INPUT(8, HID_IOF_CONSTANT), \
HID_RI_USAGE_PAGE(8, 0x01), \
HID_RI_USAGE(8, 0x30), \
HID_RI_USAGE(8, 0x31), \
HID_RI_LOGICAL_MINIMUM(16, MinAxisVal), \
HID_RI_LOGICAL_MAXIMUM(16, MaxAxisVal), \
HID_RI_PHYSICAL_MINIMUM(16, MinPhysicalVal), \
HID_RI_PHYSICAL_MAXIMUM(16, MaxPhysicalVal), \
HID_RI_REPORT_COUNT(8, 0x02), \
HID_RI_REPORT_SIZE(8, (((MinAxisVal >= -128) && (MaxAxisVal <= 127)) ? 8 : 16)), \
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | (AbsoluteCoords ? HID_IOF_ABSOLUTE : HID_IOF_RELATIVE)), \
HID_RI_END_COLLECTION(0), \
HID_RI_END_COLLECTION(0)
/** \hideinitializer
* A list of HID report item array elements that describe a typical Vendor Defined byte array HID report descriptor,
* used for transporting arbitrary data between the USB host and device via HID reports. The resulting report should be
* a \c uint8_t byte array of the specified length in both Device to Host (IN) and Host to Device (OUT) directions.
*
* \param[in] VendorPageNum Vendor Defined HID Usage Page index, ranging from 0x00 to 0xFF.
* \param[in] CollectionUsage Vendor Usage for the encompassing report IN and OUT collection, ranging from 0x00 to 0xFF.
* \param[in] DataINUsage Vendor Usage for the IN report data, ranging from 0x00 to 0xFF.
* \param[in] DataOUTUsage Vendor Usage for the OUT report data, ranging from 0x00 to 0xFF.
* \param[in] NumBytes Length of the data IN and OUT reports.
*/
#define HID_DESCRIPTOR_VENDOR(VendorPageNum, CollectionUsage, DataINUsage, DataOUTUsage, NumBytes) \
HID_RI_USAGE_PAGE(16, (0xFF00 | VendorPageNum)), \
HID_RI_USAGE(8, CollectionUsage), \
HID_RI_COLLECTION(8, 0x01), \
HID_RI_USAGE(8, DataINUsage), \
HID_RI_LOGICAL_MINIMUM(8, 0x00), \
HID_RI_LOGICAL_MAXIMUM(8, 0xFF), \
HID_RI_REPORT_SIZE(8, 0x08), \
HID_RI_REPORT_COUNT(8, NumBytes), \
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
HID_RI_USAGE(8, DataOUTUsage), \
HID_RI_LOGICAL_MINIMUM(8, 0x00), \
HID_RI_LOGICAL_MAXIMUM(8, 0xFF), \
HID_RI_REPORT_SIZE(8, 0x08), \
HID_RI_REPORT_COUNT(8, NumBytes), \
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), \
HID_RI_END_COLLECTION(0)
//@}
/* Type Defines: */
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the HID
* device class.
*/
enum HID_Descriptor_ClassSubclassProtocol_t
{
HID_CSCP_HIDClass = 0x03, /**< Descriptor Class value indicating that the device or interface
* belongs to the HID class.
*/
HID_CSCP_NonBootSubclass = 0x00, /**< Descriptor Subclass value indicating that the device or interface
* does not implement a HID boot protocol.
*/
HID_CSCP_BootSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or interface
* implements a HID boot protocol.
*/
HID_CSCP_NonBootProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
* does not belong to a HID boot protocol.
*/
HID_CSCP_KeyboardBootProtocol = 0x01, /**< Descriptor Protocol value indicating that the device or interface
* belongs to the Keyboard HID boot protocol.
*/
HID_CSCP_MouseBootProtocol = 0x02, /**< Descriptor Protocol value indicating that the device or interface
* belongs to the Mouse HID boot protocol.
*/
};
/** Enum for the HID class specific control requests that can be issued by the USB bus host. */
enum HID_ClassRequests_t
{
HID_REQ_GetReport = 0x01, /**< HID class-specific Request to get the current HID report from the device. */
HID_REQ_GetIdle = 0x02, /**< HID class-specific Request to get the current device idle count. */
HID_REQ_GetProtocol = 0x03, /**< HID class-specific Request to get the current HID report protocol mode. */
HID_REQ_SetReport = 0x09, /**< HID class-specific Request to set the current HID report to the device. */
HID_REQ_SetIdle = 0x0A, /**< HID class-specific Request to set the device's idle count. */
HID_REQ_SetProtocol = 0x0B, /**< HID class-specific Request to set the current HID report protocol mode. */
};
/** Enum for the HID class specific descriptor types. */
enum HID_DescriptorTypes_t
{
HID_DTYPE_HID = 0x21, /**< Descriptor header type value, to indicate a HID class HID descriptor. */
HID_DTYPE_Report = 0x22, /**< Descriptor header type value, to indicate a HID class HID report descriptor. */
};
/** Enum for the different types of HID reports. */
enum HID_ReportItemTypes_t
{
HID_REPORT_ITEM_In = 0, /**< Indicates that the item is an IN report type. */
HID_REPORT_ITEM_Out = 1, /**< Indicates that the item is an OUT report type. */
HID_REPORT_ITEM_Feature = 2, /**< Indicates that the item is a FEATURE report type. */
};
/** \brief HID class-specific HID Descriptor (LUFA naming conventions).
*
* Type define for the HID class-specific HID descriptor, to describe the HID device's specifications. Refer to the HID
* specification for details on the structure elements.
*
* \see \ref USB_HID_StdDescriptor_HID_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint16_t HIDSpec; /**< BCD encoded version that the HID descriptor and device complies to.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t CountryCode; /**< Country code of the localized device, or zero if universal. */
uint8_t TotalReportDescriptors; /**< Total number of HID report descriptors for the interface. */
uint8_t HIDReportType; /**< Type of HID report, set to \ref HID_DTYPE_Report. */
uint16_t HIDReportLength; /**< Length of the associated HID report descriptor, in bytes. */
} ATTR_PACKED USB_HID_Descriptor_HID_t;
/** \brief HID class-specific HID Descriptor (USB-IF naming conventions).
*
* Type define for the HID class-specific HID descriptor, to describe the HID device's specifications. Refer to the HID
* specification for details on the structure elements.
*
* \see \ref USB_HID_Descriptor_HID_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint16_t bcdHID; /**< BCD encoded version that the HID descriptor and device complies to.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint8_t bCountryCode; /**< Country code of the localized device, or zero if universal. */
uint8_t bNumDescriptors; /**< Total number of HID report descriptors for the interface. */
uint8_t bDescriptorType2; /**< Type of HID report, set to \ref HID_DTYPE_Report. */
uint16_t wDescriptorLength; /**< Length of the associated HID report descriptor, in bytes. */
} ATTR_PACKED USB_HID_StdDescriptor_HID_t;
/** \brief Standard HID Boot Protocol Mouse Report.
*
* Type define for a standard Boot Protocol Mouse report
*/
typedef struct
{
uint8_t Button; /**< Button mask for currently pressed buttons in the mouse. */
int8_t X; /**< Current delta X movement of the mouse. */
int8_t Y; /**< Current delta Y movement on the mouse. */
} ATTR_PACKED USB_MouseReport_Data_t;
/** \brief Standard HID Boot Protocol Keyboard Report.
*
* Type define for a standard Boot Protocol Keyboard report
*/
typedef struct
{
uint8_t Modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of
* \c HID_KEYBOARD_MODIFER_* masks).
*/
uint8_t Reserved; /**< Reserved for OEM use, always set to 0. */
uint8_t KeyCode[6]; /**< Key codes of the currently pressed keys. */
} ATTR_PACKED USB_KeyboardReport_Data_t;
/** Type define for the data type used to store HID report descriptor elements. */
typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,389 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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
#define __INCLUDE_FROM_HID_DRIVER
#include "HIDParser.h"
uint8_t USB_ProcessHIDReport(const uint8_t* ReportData,
uint16_t ReportSize,
HID_ReportInfo_t* const ParserData)
{
HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];
HID_StateTable_t* CurrStateTable = &StateTable[0];
HID_CollectionPath_t* CurrCollectionPath = NULL;
HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0];
uint16_t UsageList[HID_USAGE_STACK_DEPTH];
uint8_t UsageListSize = 0;
HID_MinMax_t UsageMinMax = {0, 0};
memset(ParserData, 0x00, sizeof(HID_ReportInfo_t));
memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t));
memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
ParserData->TotalDeviceReports = 1;
while (ReportSize)
{
uint8_t HIDReportItem = *ReportData;
uint32_t ReportItemData;
ReportData++;
ReportSize--;
switch (HIDReportItem & HID_RI_DATA_SIZE_MASK)
{
case HID_RI_DATA_BITS_32:
ReportItemData = (((uint32_t)ReportData[3] << 24) | ((uint32_t)ReportData[2] << 16) |
((uint16_t)ReportData[1] << 8) | ReportData[0]);
ReportSize -= 4;
ReportData += 4;
break;
case HID_RI_DATA_BITS_16:
ReportItemData = (((uint16_t)ReportData[1] << 8) | (ReportData[0]));
ReportSize -= 2;
ReportData += 2;
break;
case HID_RI_DATA_BITS_8:
ReportItemData = ReportData[0];
ReportSize -= 1;
ReportData += 1;
break;
default:
ReportItemData = 0;
break;
}
switch (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK))
{
case HID_RI_PUSH(0):
if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1])
return HID_PARSE_HIDStackOverflow;
memcpy((CurrStateTable + 1),
CurrStateTable,
sizeof(HID_ReportItem_t));
CurrStateTable++;
break;
case HID_RI_POP(0):
if (CurrStateTable == &StateTable[0])
return HID_PARSE_HIDStackUnderflow;
CurrStateTable--;
break;
case HID_RI_USAGE_PAGE(0):
if ((HIDReportItem & HID_RI_DATA_SIZE_MASK) == HID_RI_DATA_BITS_32)
CurrStateTable->Attributes.Usage.Page = (ReportItemData >> 16);
CurrStateTable->Attributes.Usage.Page = ReportItemData;
break;
case HID_RI_LOGICAL_MINIMUM(0):
CurrStateTable->Attributes.Logical.Minimum = ReportItemData;
break;
case HID_RI_LOGICAL_MAXIMUM(0):
CurrStateTable->Attributes.Logical.Maximum = ReportItemData;
break;
case HID_RI_PHYSICAL_MINIMUM(0):
CurrStateTable->Attributes.Physical.Minimum = ReportItemData;
break;
case HID_RI_PHYSICAL_MAXIMUM(0):
CurrStateTable->Attributes.Physical.Maximum = ReportItemData;
break;
case HID_RI_UNIT_EXPONENT(0):
CurrStateTable->Attributes.Unit.Exponent = ReportItemData;
break;
case HID_RI_UNIT(0):
CurrStateTable->Attributes.Unit.Type = ReportItemData;
break;
case HID_RI_REPORT_SIZE(0):
CurrStateTable->Attributes.BitSize = ReportItemData;
break;
case HID_RI_REPORT_COUNT(0):
CurrStateTable->ReportCount = ReportItemData;
break;
case HID_RI_REPORT_ID(0):
CurrStateTable->ReportID = ReportItemData;
if (ParserData->UsingReportIDs)
{
CurrReportIDInfo = NULL;
for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++)
{
if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID)
{
CurrReportIDInfo = &ParserData->ReportIDSizes[i];
break;
}
}
if (CurrReportIDInfo == NULL)
{
if (ParserData->TotalDeviceReports == HID_MAX_REPORT_IDS)
return HID_PARSE_InsufficientReportIDItems;
CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports++];
memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
}
}
ParserData->UsingReportIDs = true;
CurrReportIDInfo->ReportID = CurrStateTable->ReportID;
break;
case HID_RI_USAGE(0):
if (UsageListSize == HID_USAGE_STACK_DEPTH)
return HID_PARSE_UsageListOverflow;
UsageList[UsageListSize++] = ReportItemData;
break;
case HID_RI_USAGE_MINIMUM(0):
UsageMinMax.Minimum = ReportItemData;
break;
case HID_RI_USAGE_MAXIMUM(0):
UsageMinMax.Maximum = ReportItemData;
break;
case HID_RI_COLLECTION(0):
if (CurrCollectionPath == NULL)
{
CurrCollectionPath = &ParserData->CollectionPaths[0];
}
else
{
HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;
CurrCollectionPath = &ParserData->CollectionPaths[1];
while (CurrCollectionPath->Parent != NULL)
{
if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1])
return HID_PARSE_InsufficientCollectionPaths;
CurrCollectionPath++;
}
CurrCollectionPath->Parent = ParentCollectionPath;
}
CurrCollectionPath->Type = ReportItemData;
CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;
if (UsageListSize)
{
CurrCollectionPath->Usage.Usage = UsageList[0];
for (uint8_t i = 1; i < UsageListSize; i++)
UsageList[i - 1] = UsageList[i];
UsageListSize--;
}
else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
{
CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++;
}
break;
case HID_RI_END_COLLECTION(0):
if (CurrCollectionPath == NULL)
return HID_PARSE_UnexpectedEndCollection;
CurrCollectionPath = CurrCollectionPath->Parent;
break;
case HID_RI_INPUT(0):
case HID_RI_OUTPUT(0):
case HID_RI_FEATURE(0):
for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)
{
HID_ReportItem_t NewReportItem;
memcpy(&NewReportItem.Attributes,
&CurrStateTable->Attributes,
sizeof(HID_ReportItem_Attributes_t));
NewReportItem.ItemFlags = ReportItemData;
NewReportItem.CollectionPath = CurrCollectionPath;
NewReportItem.ReportID = CurrStateTable->ReportID;
if (UsageListSize)
{
NewReportItem.Attributes.Usage.Usage = UsageList[0];
for (uint8_t i = 1; i < UsageListSize; i++)
UsageList[i - 1] = UsageList[i];
UsageListSize--;
}
else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
{
NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++;
}
uint8_t ItemTypeTag = (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK));
if (ItemTypeTag == HID_RI_INPUT(0))
NewReportItem.ItemType = HID_REPORT_ITEM_In;
else if (ItemTypeTag == HID_RI_OUTPUT(0))
NewReportItem.ItemType = HID_REPORT_ITEM_Out;
else
NewReportItem.ItemType = HID_REPORT_ITEM_Feature;
NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType];
CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize;
ParserData->LargestReportSizeBits = MAX(ParserData->LargestReportSizeBits, CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType]);
if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)
return HID_PARSE_InsufficientReportItems;
memcpy(&ParserData->ReportItems[ParserData->TotalReportItems],
&NewReportItem, sizeof(HID_ReportItem_t));
if (!(ReportItemData & HID_IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem))
ParserData->TotalReportItems++;
}
break;
default:
break;
}
if ((HIDReportItem & HID_RI_TYPE_MASK) == HID_RI_TYPE_MAIN)
{
UsageMinMax.Minimum = 0;
UsageMinMax.Maximum = 0;
UsageListSize = 0;
}
}
if (!(ParserData->TotalReportItems))
return HID_PARSE_NoUnfilteredReportItems;
return HID_PARSE_Successful;
}
bool USB_GetHIDReportItemInfo(const uint8_t* ReportData,
HID_ReportItem_t* const ReportItem)
{
if (ReportItem == NULL)
return false;
uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
uint16_t CurrentBit = ReportItem->BitOffset;
uint32_t BitMask = (1 << 0);
if (ReportItem->ReportID)
{
if (ReportItem->ReportID != ReportData[0])
return false;
ReportData++;
}
ReportItem->PreviousValue = ReportItem->Value;
ReportItem->Value = 0;
while (DataBitsRem--)
{
if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))
ReportItem->Value |= BitMask;
CurrentBit++;
BitMask <<= 1;
}
return true;
}
void USB_SetHIDReportItemInfo(uint8_t* ReportData,
HID_ReportItem_t* const ReportItem)
{
if (ReportItem == NULL)
return;
uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
uint16_t CurrentBit = ReportItem->BitOffset;
uint32_t BitMask = (1 << 0);
if (ReportItem->ReportID)
{
ReportData[0] = ReportItem->ReportID;
ReportData++;
}
ReportItem->PreviousValue = ReportItem->Value;
while (DataBitsRem--)
{
if (ReportItem->Value & (1 << (CurrentBit % 8)))
ReportData[CurrentBit / 8] |= BitMask;
CurrentBit++;
BitMask <<= 1;
}
}
uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData,
const uint8_t ReportID,
const uint8_t ReportType)
{
for (uint8_t i = 0; i < HID_MAX_REPORT_IDS; i++)
{
uint16_t ReportSizeBits = ParserData->ReportIDSizes[i].ReportSizeBits[ReportType];
if (ParserData->ReportIDSizes[i].ReportID == ReportID)
return (ReportSizeBits / 8) + ((ReportSizeBits % 8) ? 1 : 0);
}
return 0;
}

View file

@ -0,0 +1,364 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 USB Human Interface Device (HID) Class report descriptor parser.
*
* This file allows for the easy parsing of complex HID report descriptors, which describes the data that
* a HID device transmits to the host. It also provides an easy API for extracting and processing the data
* elements inside a HID report sent from an attached HID device.
*/
/** \ingroup Group_USB
* \defgroup Group_HIDParser HID Report Parser
* \brief USB Human Interface Device (HID) Class report descriptor parser.
*
* \section Sec_HIDParser_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/HIDParser.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
*
* \section Sec_HIDParser_ModDescription Module Description
* Human Interface Device (HID) class report descriptor parser. This module implements a parser than is
* capable of processing a complete HID report descriptor, and outputting a flat structure containing the
* contents of the report in an a more friendly format. The parsed data may then be further processed and used
* within an application to process sent and received HID reports to and from an attached HID device.
*
* A HID report descriptor consists of a set of HID report items, which describe the function and layout
* of data exchanged between a HID device and a host, including both the physical encoding of each item
* (such as a button, key press or joystick axis) in the sent and received data packets - known as "reports" -
* as well as other information about each item such as the usages, data range, physical location and other
* characteristics. In this way a HID device can retain a high degree of flexibility in its capabilities, as it
* is not forced to comply with a given report layout or feature-set.
*
* This module also contains routines for the processing of data in an actual HID report, using the parsed report
* descriptor data as a guide for the encoding.
*
* @{
*/
#ifndef __HIDPARSER_H__
#define __HIDPARSER_H__
/* Includes: */
#include "../../../../Common/Common.h"
#include "HIDReportData.h"
#include "HIDClassCommon.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Macros: */
#if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__)
/** Constant indicating the maximum stack depth of the state table. A larger state table
* allows for more PUSH/POP report items to be nested, but consumes more memory. By default
* this is set to 2 levels (allowing non-nested PUSH items) but this can be overridden by
* defining \c HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the
* define to the compiler using the -D compiler switch.
*/
#define HID_STATETABLE_STACK_DEPTH 2
#endif
#if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__)
/** Constant indicating the maximum stack depth of the usage table. A larger usage table
* allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than
* one, but requires more stack space. By default this is set to 8 levels (allowing for a report
* item with a count of 8) but this can be overridden by defining \c HID_USAGE_STACK_DEPTH to another
* value in the user project makefile, passing the define to the compiler using the -D compiler
* switch.
*/
#define HID_USAGE_STACK_DEPTH 8
#endif
#if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__)
/** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be
* processed in the report item descriptor. A large value allows for more COLLECTION items to be
* processed, but consumes more memory. By default this is set to 10 collections, but this can be
* overridden by defining \c HID_MAX_COLLECTIONS to another value in the user project makefile, passing
* the define to the compiler using the -D compiler switch.
*/
#define HID_MAX_COLLECTIONS 10
#endif
#if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__)
/** Constant indicating the maximum number of report items (IN, OUT or FEATURE) that can be processed
* in the report item descriptor and stored in the user HID Report Info structure. A large value allows
* for more report items to be stored, but consumes more memory. By default this is set to 20 items,
* but this can be overridden by defining \c HID_MAX_REPORTITEMS to another value in the user project
* makefile, and passing the define to the compiler using the -D compiler switch.
*/
#define HID_MAX_REPORTITEMS 20
#endif
#if !defined(HID_MAX_REPORT_IDS) || defined(__DOXYGEN__)
/** Constant indicating the maximum number of unique report IDs that can be processed in the report item
* descriptor for the report size information array in the user HID Report Info structure. A large value
* allows for more report ID report sizes to be stored, but consumes more memory. By default this is set
* to 10 items, but this can be overridden by defining \c HID_MAX_REPORT_IDS to another value in the user project
* makefile, and passing the define to the compiler using the -D compiler switch. Note that IN, OUT and FEATURE
* items sharing the same report ID consume only one size item in the array.
*/
#define HID_MAX_REPORT_IDS 10
#endif
/** Returns the value a given HID report item (once its value has been fetched via \ref USB_GetHIDReportItemInfo())
* left-aligned to the given data type. This allows for signed data to be interpreted correctly, by shifting the data
* leftwards until the data's sign bit is in the correct position.
*
* \param[in] ReportItem HID Report Item whose retrieved value is to be aligned.
* \param[in] Type Data type to align the HID report item's value to.
*
* \return Left-aligned data of the given report item's pre-retrieved value for the given datatype.
*/
#define HID_ALIGN_DATA(ReportItem, Type) ((Type)(ReportItem->Value << ((8 * sizeof(Type)) - ReportItem->Attributes.BitSize)))
/* Public Interface - May be used in end-application: */
/* Enums: */
/** Enum for the possible error codes in the return value of the \ref USB_ProcessHIDReport() function. */
enum HID_Parse_ErrorCodes_t
{
HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */
HID_PARSE_HIDStackOverflow = 1, /**< More than \ref HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */
HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */
HID_PARSE_InsufficientReportItems = 3, /**< More than \ref HID_MAX_REPORTITEMS report items in the report. */
HID_PARSE_UnexpectedEndCollection = 4, /**< An END COLLECTION item found without matching COLLECTION item. */
HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */
HID_PARSE_UsageListOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */
HID_PARSE_InsufficientReportIDItems = 7, /**< More than \ref HID_MAX_REPORT_IDS report IDs in the device. */
HID_PARSE_NoUnfilteredReportItems = 8, /**< All report items from the device were filtered by the filtering callback routine. */
};
/* Type Defines: */
/** \brief HID Parser Report Item Min/Max Structure.
*
* Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max).
*/
typedef struct
{
uint32_t Minimum; /**< Minimum value for the attribute. */
uint32_t Maximum; /**< Maximum value for the attribute. */
} HID_MinMax_t;
/** \brief HID Parser Report Item Unit Structure.
*
* Type define for the Unit attributes of a report item.
*/
typedef struct
{
uint32_t Type; /**< Unit type (refer to HID specifications for details). */
uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */
} HID_Unit_t;
/** \brief HID Parser Report Item Usage Structure.
*
* Type define for the Usage attributes of a report item.
*/
typedef struct
{
uint16_t Page; /**< Usage page of the report item. */
uint16_t Usage; /**< Usage of the report item. */
} HID_Usage_t;
/** \brief HID Parser Report Item Collection Path Structure.
*
* Type define for a COLLECTION object. Contains the collection attributes and a reference to the
* parent collection if any.
*/
typedef struct HID_CollectionPath
{
uint8_t Type; /**< Collection type (e.g. "Generic Desktop"). */
HID_Usage_t Usage; /**< Collection usage. */
struct HID_CollectionPath* Parent; /**< Reference to parent collection, or \c NULL if root collection. */
} HID_CollectionPath_t;
/** \brief HID Parser Report Item Attributes Structure.
*
* Type define for all the data attributes of a report item, except flags.
*/
typedef struct
{
uint8_t BitSize; /**< Size in bits of the report item's data. */
HID_Usage_t Usage; /**< Usage of the report item. */
HID_Unit_t Unit; /**< Unit type and exponent of the report item. */
HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */
HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */
} HID_ReportItem_Attributes_t;
/** \brief HID Parser Report Item Details Structure.
*
* Type define for a report item (IN, OUT or FEATURE) layout attributes and other details.
*/
typedef struct
{
uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */
uint8_t ItemType; /**< Report item type, a value in \ref HID_ReportItemTypes_t. */
uint16_t ItemFlags; /**< Item data flags, a mask of \c HID_IOF_* constants. */
uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */
HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */
HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */
uint32_t Value; /**< Current value of the report item - use \ref HID_ALIGN_DATA() when processing
* a retrieved value so that it is aligned to a specific type.
*/
uint32_t PreviousValue; /**< Previous value of the report item. */
} HID_ReportItem_t;
/** \brief HID Parser Report Size Structure.
*
* Type define for a report item size information structure, to retain the size of a device's reports by ID.
*/
typedef struct
{
uint8_t ReportID; /**< Report ID of the report within the HID interface. */
uint16_t ReportSizeBits[3]; /**< Total number of bits in each report type for the given Report ID,
* indexed by the \ref HID_ReportItemTypes_t enum.
*/
} HID_ReportSizeInfo_t;
/** \brief HID Parser State Structure.
*
* Type define for a complete processed HID report, including all report item data and collections.
*/
typedef struct
{
uint8_t TotalReportItems; /**< Total number of report items stored in the \c ReportItems array. */
HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including all IN, OUT
* and FEATURE items.
*/
HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced
* by the report items.
*/
uint8_t TotalDeviceReports; /**< Number of reports within the HID interface */
HID_ReportSizeInfo_t ReportIDSizes[HID_MAX_REPORT_IDS]; /**< Report sizes for each report in the interface */
uint16_t LargestReportSizeBits; /**< Largest report that the attached device will generate, in bits */
bool UsingReportIDs; /**< Indicates if the device has at least one REPORT ID
* element in its HID report descriptor.
*/
} HID_ReportInfo_t;
/* Function Prototypes: */
/** Function to process a given HID report returned from an attached device, and store it into a given
* \ref HID_ReportInfo_t structure.
*
* \param[in] ReportData Buffer containing the device's HID report table.
* \param[in] ReportSize Size in bytes of the HID report table.
* \param[out] ParserData Pointer to a \ref HID_ReportInfo_t instance for the parser output.
*
* \return A value in the \ref HID_Parse_ErrorCodes_t enum.
*/
uint8_t USB_ProcessHIDReport(const uint8_t* ReportData,
uint16_t ReportSize,
HID_ReportInfo_t* const ParserData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Extracts the given report item's value out of the given HID report and places it into the Value
* member of the report item's \ref HID_ReportItem_t structure.
*
* When called on a report with an item that exists in that report, this copies the report item's \c Value
* to its \c PreviousValue element for easy checking to see if an item's value has changed before processing
* a report. If the given item does not exist in the report, the function does not modify the report item's
* data.
*
* \param[in] ReportData Buffer containing an IN or FEATURE report from an attached device.
* \param[in,out] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array.
*
* \returns Boolean \c true if the item to retrieve was located in the given report, \c false otherwise.
*/
bool USB_GetHIDReportItemInfo(const uint8_t* ReportData,
HID_ReportItem_t* const ReportItem) ATTR_NON_NULL_PTR_ARG(1);
/** Retrieves the given report item's value out of the \c Value member of the report item's
* \ref HID_ReportItem_t structure and places it into the correct position in the HID report
* buffer. The report buffer is assumed to have the appropriate bits cleared before calling
* this function (i.e., the buffer should be explicitly cleared before report values are added).
*
* When called, this copies the report item's \c Value element to its \c PreviousValue element for easy
* checking to see if an item's value has changed before sending a report.
*
* If the device has multiple HID reports, the first byte in the report is set to the report ID of the given item.
*
* \param[out] ReportData Buffer holding the current OUT or FEATURE report data.
* \param[in] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array.
*/
void USB_SetHIDReportItemInfo(uint8_t* ReportData,
HID_ReportItem_t* const ReportItem) ATTR_NON_NULL_PTR_ARG(1);
/** Retrieves the size of a given HID report in bytes from its Report ID.
*
* \param[in] ParserData Pointer to a \ref HID_ReportInfo_t instance containing the parser output.
* \param[in] ReportID Report ID of the report whose size is to be determined.
* \param[in] ReportType Type of the report whose size is to be determined, a value from the
* \ref HID_ReportItemTypes_t enum.
*
* \return Size of the report in bytes, or \c 0 if the report does not exist.
*/
uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData,
const uint8_t ReportID,
const uint8_t ReportType) ATTR_CONST ATTR_NON_NULL_PTR_ARG(1);
/** Callback routine for the HID Report Parser. This callback <b>must</b> be implemented by the user code when
* the parser is used, to determine what report IN, OUT and FEATURE item's information is stored into the user
* \ref HID_ReportInfo_t structure. This can be used to filter only those items the application will be using, so that
* no RAM is wasted storing the attributes for report items which will never be referenced by the application.
*
* Report item pointers passed to this callback function may be cached by the user application for later use
* when processing report items. This provides faster report processing in the user application than would
* a search of the entire parsed report item table for each received or sent report.
*
* \param[in] CurrentItem Pointer to the current report item for user checking.
*
* \return Boolean \c true if the item should be stored into the \ref HID_ReportInfo_t structure, \c false if
* it should be ignored.
*/
bool CALLBACK_HIDParser_FilterHIDReportItem(HID_ReportItem_t* const CurrentItem);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Type Defines: */
typedef struct
{
HID_ReportItem_Attributes_t Attributes;
uint8_t ReportCount;
uint8_t ReportID;
} HID_StateTable_t;
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,126 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Constants for HID report item attributes.
*
* HID report item constants for report item attributes. Refer to the HID specification for
* details on each flag's meaning when applied to an IN, OUT or FEATURE item.
*/
/** \ingroup Group_HIDParser
* \defgroup Group_HIDReportItemConst HID Report Descriptor Item Constants
*
* General HID constant definitions for HID Report Descriptor elements.
*
* @{
*/
#ifndef __HIDREPORTDATA_H__
#define __HIDREPORTDATA_H__
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define HID_RI_DATA_SIZE_MASK 0x03
#define HID_RI_TYPE_MASK 0x0C
#define HID_RI_TAG_MASK 0xF0
#define HID_RI_TYPE_MAIN 0x00
#define HID_RI_TYPE_GLOBAL 0x04
#define HID_RI_TYPE_LOCAL 0x08
#define HID_RI_DATA_BITS_0 0x00
#define HID_RI_DATA_BITS_8 0x01
#define HID_RI_DATA_BITS_16 0x02
#define HID_RI_DATA_BITS_32 0x03
#define HID_RI_DATA_BITS(DataBits) CONCAT_EXPANDED(HID_RI_DATA_BITS_, DataBits)
#define _HID_RI_ENCODE_0(Data)
#define _HID_RI_ENCODE_8(Data) , (Data & 0xFF)
#define _HID_RI_ENCODE_16(Data) _HID_RI_ENCODE_8(Data) _HID_RI_ENCODE_8(Data >> 8)
#define _HID_RI_ENCODE_32(Data) _HID_RI_ENCODE_16(Data) _HID_RI_ENCODE_16(Data >> 16)
#define _HID_RI_ENCODE(DataBits, ...) CONCAT_EXPANDED(_HID_RI_ENCODE_, DataBits(__VA_ARGS__))
#define _HID_RI_ENTRY(Type, Tag, DataBits, ...) (Type | Tag | HID_RI_DATA_BITS(DataBits)) _HID_RI_ENCODE(DataBits, (__VA_ARGS__))
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name HID Input, Output and Feature Report Descriptor Item Flags */
//@{
#define HID_IOF_CONSTANT (1 << 0)
#define HID_IOF_DATA (0 << 0)
#define HID_IOF_VARIABLE (1 << 1)
#define HID_IOF_ARRAY (0 << 1)
#define HID_IOF_RELATIVE (1 << 2)
#define HID_IOF_ABSOLUTE (0 << 2)
#define HID_IOF_WRAP (1 << 3)
#define HID_IOF_NO_WRAP (0 << 3)
#define HID_IOF_NON_LINEAR (1 << 4)
#define HID_IOF_LINEAR (0 << 4)
#define HID_IOF_NO_PREFERRED_STATE (1 << 5)
#define HID_IOF_PREFERRED_STATE (0 << 5)
#define HID_IOF_NULLSTATE (1 << 6)
#define HID_IOF_NO_NULL_POSITION (0 << 6)
#define HID_IOF_VOLATILE (1 << 7)
#define HID_IOF_NON_VOLATILE (0 << 7)
#define HID_IOF_BUFFERED_BYTES (1 << 8)
#define HID_IOF_BITFIELD (0 << 8)
//@}
/** \name HID Report Descriptor Item Macros */
//@{
#define HID_RI_INPUT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0x80, DataBits, __VA_ARGS__)
#define HID_RI_OUTPUT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0x90, DataBits, __VA_ARGS__)
#define HID_RI_COLLECTION(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0xA0, DataBits, __VA_ARGS__)
#define HID_RI_FEATURE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0xB0, DataBits, __VA_ARGS__)
#define HID_RI_END_COLLECTION(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0xC0, DataBits, __VA_ARGS__)
#define HID_RI_USAGE_PAGE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x00, DataBits, __VA_ARGS__)
#define HID_RI_LOGICAL_MINIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x10, DataBits, __VA_ARGS__)
#define HID_RI_LOGICAL_MAXIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x20, DataBits, __VA_ARGS__)
#define HID_RI_PHYSICAL_MINIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x30, DataBits, __VA_ARGS__)
#define HID_RI_PHYSICAL_MAXIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x40, DataBits, __VA_ARGS__)
#define HID_RI_UNIT_EXPONENT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x50, DataBits, __VA_ARGS__)
#define HID_RI_UNIT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x60, DataBits, __VA_ARGS__)
#define HID_RI_REPORT_SIZE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x70, DataBits, __VA_ARGS__)
#define HID_RI_REPORT_ID(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x80, DataBits, __VA_ARGS__)
#define HID_RI_REPORT_COUNT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x90, DataBits, __VA_ARGS__)
#define HID_RI_PUSH(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0xA0, DataBits, __VA_ARGS__)
#define HID_RI_POP(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0xB0, DataBits, __VA_ARGS__)
#define HID_RI_USAGE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_LOCAL , 0x00, DataBits, __VA_ARGS__)
#define HID_RI_USAGE_MINIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_LOCAL , 0x10, DataBits, __VA_ARGS__)
#define HID_RI_USAGE_MAXIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_LOCAL , 0x20, DataBits, __VA_ARGS__)
//@}
/** @} */
#endif

View file

@ -0,0 +1,363 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB MIDI Class driver.
*
* Common definitions and declarations for the library USB MIDI Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassMIDI
* \defgroup Group_USBClassMIDICommon Common Class Definitions
*
* \section Sec_USBClassMIDICommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* MIDI Class.
*
* @{
*/
#ifndef _MIDI_CLASS_COMMON_H_
#define _MIDI_CLASS_COMMON_H_
/* Macros: */
#define __INCLUDE_FROM_AUDIO_DRIVER
/* Includes: */
#include "../../Core/StdDescriptors.h"
#include "AudioClassCommon.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/USB.h instead.
#endif
/* Macros: */
/** \name MIDI Command Values
* See http://www.midi.org/techspecs/midimessages.php for more information.
*/
//@{
/** MIDI command for System Exclusive (SysEx) single event that has one byte of data total. */
#define MIDI_COMMAND_SYSEX_1BYTE MIDI_COMMAND_SYSEX_END_1BYTE
/** MIDI command for System Exclusive (SysEx) single event that has two bytes of data total. */
#define MIDI_COMMAND_SYSEX_2BYTE 0x20
/** MIDI command for System Exclusive (SysEx) single event that has three bytes of data total. */
#define MIDI_COMMAND_SYSEX_3BYTE 0x30
/** MIDI command for System Exclusive (SysEx) stream event that has at least four bytes of data total. */
#define MIDI_COMMAND_SYSEX_START_3BYTE 0x40
/** MIDI command for System Exclusive (SysEx) stream event terminator with one remaining data byte. */
#define MIDI_COMMAND_SYSEX_END_1BYTE 0x50
/** MIDI command for System Exclusive (SysEx) stream event terminator with two remaining data bytes. */
#define MIDI_COMMAND_SYSEX_END_2BYTE 0x60
/** MIDI command for System Exclusive (SysEx) stream event terminator with three remaining data bytes. */
#define MIDI_COMMAND_SYSEX_END_3BYTE 0x70
/** MIDI command for a note off (deactivation) event. */
#define MIDI_COMMAND_NOTE_OFF 0x80
/** MIDI command for a note on (activation) event. */
#define MIDI_COMMAND_NOTE_ON 0x90
/** MIDI command for a note pressure change event. */
#define MIDI_COMMAND_NOTE_PRESSURE 0xA0
/** MIDI command for a control change event. */
#define MIDI_COMMAND_CONTROL_CHANGE 0xB0
/** MIDI command for a control change event. */
#define MIDI_COMMAND_PROGRAM_CHANGE 0xC0
/** MIDI command for a channel pressure change event. */
#define MIDI_COMMAND_CHANNEL_PRESSURE 0xD0
/** MIDI command for a pitch change event. */
#define MIDI_COMMAND_PITCH_WHEEL_CHANGE 0xE0
//@}
/** Standard key press velocity value used for all note events. */
#define MIDI_STANDARD_VELOCITY 64
/** Convenience macro. MIDI channels are numbered from 1-10 (natural numbers) however the logical channel
* addresses are zero-indexed. This converts a natural MIDI channel number into the logical channel address.
*
* \param[in] channel MIDI channel number to address.
*
* \return Constructed MIDI channel ID.
*/
#define MIDI_CHANNEL(channel) ((channel) - 1)
/** Constructs a MIDI event ID from a given MIDI command and a virtual MIDI cable index. This can then be
* used to create and decode \ref MIDI_EventPacket_t MIDI event packets.
*
* \param[in] virtualcable Index of the virtual MIDI cable the event relates to
* \param[in] command MIDI command to send through the virtual MIDI cable
*
* \return Constructed MIDI event ID.
*/
#define MIDI_EVENT(virtualcable, command) (((virtualcable) << 4) | ((command) >> 4))
/* Enums: */
/** Enum for the possible MIDI jack types in a MIDI device jack descriptor. */
enum MIDI_JackTypes_t
{
MIDI_JACKTYPE_Embedded = 0x01, /**< MIDI class descriptor jack type value for an embedded (logical) MIDI input or output jack. */
MIDI_JACKTYPE_External = 0x02, /**< MIDI class descriptor jack type value for an external (physical) MIDI input or output jack. */
};
/* Type Defines: */
/** \brief MIDI class-specific Streaming Interface Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific MIDI streaming interface descriptor. This indicates to the host
* how MIDI the specification compliance of the device and the total length of the Audio class-specific descriptors.
* See the USB Audio specification for more details.
*
* \see \ref USB_MIDI_StdDescriptor_AudioInterface_AS_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint16_t AudioSpecification; /**< Binary coded decimal value, indicating the supported Audio Class
* specification version.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint16_t TotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
} ATTR_PACKED USB_MIDI_Descriptor_AudioInterface_AS_t;
/** \brief MIDI class-specific Streaming Interface Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific MIDI streaming interface descriptor. This indicates to the host
* how MIDI the specification compliance of the device and the total length of the Audio class-specific descriptors.
* See the USB Audio specification for more details.
*
* \see \ref USB_MIDI_Descriptor_AudioInterface_AS_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint16_t bcdMSC; /**< Binary coded decimal value, indicating the supported MIDI Class specification version.
*
* \see \ref VERSION_BCD() utility macro.
*/
uint16_t wTotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
} ATTR_PACKED USB_MIDI_StdDescriptor_AudioInterface_AS_t;
/** \brief MIDI class-specific Input Jack Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific MIDI IN jack. This gives information to the host on a MIDI input, either
* a physical input jack, or a logical jack (receiving input data internally, or from the host via an endpoint).
*
* \see \ref USB_MIDI_StdDescriptor_InputJack_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint8_t JackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
uint8_t JackID; /**< ID value of this jack - must be a unique value within the device. */
uint8_t JackStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_MIDI_Descriptor_InputJack_t;
/** \brief MIDI class-specific Input Jack Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific MIDI IN jack. This gives information to the host on a MIDI input, either
* a physical input jack, or a logical jack (receiving input data internally, or from the host via an endpoint).
*
* \see \ref USB_MIDI_Descriptor_InputJack_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint8_t bJackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
uint8_t bJackID; /**< ID value of this jack - must be a unique value within the device. */
uint8_t iJack; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_MIDI_StdDescriptor_InputJack_t;
/** \brief MIDI class-specific Output Jack Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific MIDI OUT jack. This gives information to the host on a MIDI output, either
* a physical output jack, or a logical jack (sending output data internally, or to the host via an endpoint).
*
* \see \ref USB_MIDI_StdDescriptor_OutputJack_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint8_t JackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
uint8_t JackID; /**< ID value of this jack - must be a unique value within the device. */
uint8_t NumberOfPins; /**< Number of output channels within the jack, either physical or logical. */
uint8_t SourceJackID[1]; /**< ID of each output pin's source data jack. */
uint8_t SourcePinID[1]; /**< Pin number in the input jack of each output pin's source data. */
uint8_t JackStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_MIDI_Descriptor_OutputJack_t;
/** \brief MIDI class-specific Output Jack Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific MIDI OUT jack. This gives information to the host on a MIDI output, either
* a physical output jack, or a logical jack (sending output data internally, or to the host via an endpoint).
*
* \see \ref USB_MIDI_Descriptor_OutputJack_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint8_t bJackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
uint8_t bJackID; /**< ID value of this jack - must be a unique value within the device. */
uint8_t bNrInputPins; /**< Number of output channels within the jack, either physical or logical. */
uint8_t baSourceID[1]; /**< ID of each output pin's source data jack. */
uint8_t baSourcePin[1]; /**< Pin number in the input jack of each output pin's source data. */
uint8_t iJack; /**< Index of a string descriptor describing this descriptor within the device. */
} ATTR_PACKED USB_MIDI_StdDescriptor_OutputJack_t;
/** \brief Audio class-specific Jack Endpoint Descriptor (LUFA naming conventions).
*
* Type define for an Audio class-specific extended MIDI jack endpoint descriptor. This contains extra information
* on the usage of MIDI endpoints used to stream MIDI events in and out of the USB Audio device, and follows an Audio
* class-specific extended MIDI endpoint descriptor. See the USB Audio specification for more details.
*
* \see \ref USB_MIDI_StdDescriptor_Jack_Endpoint_t for the version of this type with standard element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint8_t TotalEmbeddedJacks; /**< Total number of jacks inside this endpoint. */
uint8_t AssociatedJackID[1]; /**< IDs of each jack inside the endpoint. */
} ATTR_PACKED USB_MIDI_Descriptor_Jack_Endpoint_t;
/** \brief Audio class-specific Jack Endpoint Descriptor (USB-IF naming conventions).
*
* Type define for an Audio class-specific extended MIDI jack endpoint descriptor. This contains extra information
* on the usage of MIDI endpoints used to stream MIDI events in and out of the USB Audio device, and follows an Audio
* class-specific extended MIDI endpoint descriptor. See the USB Audio specification for more details.
*
* \see \ref USB_MIDI_Descriptor_Jack_Endpoint_t for the version of this type with non-standard LUFA specific
* element names.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t bLength; /**< Size of the descriptor, in bytes. */
uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
* given by the specific class.
*/
uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
uint8_t bNumEmbMIDIJack; /**< Total number of jacks inside this endpoint. */
uint8_t bAssocJackID[1]; /**< IDs of each jack inside the endpoint. */
} ATTR_PACKED USB_MIDI_StdDescriptor_Jack_Endpoint_t;
/** \brief MIDI Class Driver Event Packet.
*
* Type define for a USB MIDI event packet, used to encapsulate sent and received MIDI messages from a USB MIDI interface.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint8_t Event; /**< MIDI event type, constructed with the \ref MIDI_EVENT() macro. */
uint8_t Data1; /**< First byte of data in the MIDI event. */
uint8_t Data2; /**< Second byte of data in the MIDI event. */
uint8_t Data3; /**< Third byte of data in the MIDI event. */
} ATTR_PACKED MIDI_EventPacket_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,368 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB Mass Storage Class driver.
*
* Common definitions and declarations for the library USB Mass Storage Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassMS
* \defgroup Group_USBClassMSCommon Common Class Definitions
*
* \section Sec_USBClassMSCommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* Mass Storage Class.
*
* @{
*/
#ifndef _MS_CLASS_COMMON_H_
#define _MS_CLASS_COMMON_H_
/* Includes: */
#include "../../Core/StdDescriptors.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/USB.h instead.
#endif
/* Macros: */
/** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */
#define MS_CBW_SIGNATURE 0x43425355UL
/** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */
#define MS_CSW_SIGNATURE 0x53425355UL
/** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */
#define MS_COMMAND_DIR_DATA_OUT (0 << 7)
/** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */
#define MS_COMMAND_DIR_DATA_IN (1 << 7)
/** \name SCSI Commands*/
//@{
/** SCSI Command Code for an INQUIRY command. */
#define SCSI_CMD_INQUIRY 0x12
/** SCSI Command Code for a REQUEST SENSE command. */
#define SCSI_CMD_REQUEST_SENSE 0x03
/** SCSI Command Code for a TEST UNIT READY command. */
#define SCSI_CMD_TEST_UNIT_READY 0x00
/** SCSI Command Code for a READ CAPACITY (10) command. */
#define SCSI_CMD_READ_CAPACITY_10 0x25
/** SCSI Command Code for a START STOP UNIT command. */
#define SCSI_CMD_START_STOP_UNIT 0x1B
/** SCSI Command Code for a SEND DIAGNOSTIC command. */
#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
/** SCSI Command Code for a PREVENT ALLOW MEDIUM REMOVAL command. */
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
/** SCSI Command Code for a WRITE (10) command. */
#define SCSI_CMD_WRITE_10 0x2A
/** SCSI Command Code for a READ (10) command. */
#define SCSI_CMD_READ_10 0x28
/** SCSI Command Code for a WRITE (6) command. */
#define SCSI_CMD_WRITE_6 0x0A
/** SCSI Command Code for a READ (6) command. */
#define SCSI_CMD_READ_6 0x08
/** SCSI Command Code for a VERIFY (10) command. */
#define SCSI_CMD_VERIFY_10 0x2F
/** SCSI Command Code for a MODE SENSE (6) command. */
#define SCSI_CMD_MODE_SENSE_6 0x1A
/** SCSI Command Code for a MODE SENSE (10) command. */
#define SCSI_CMD_MODE_SENSE_10 0x5A
//@}
/** \name SCSI Sense Key Values */
//@{
/** SCSI Sense Code to indicate no error has occurred. */
#define SCSI_SENSE_KEY_GOOD 0x00
/** SCSI Sense Code to indicate that the device has recovered from an error. */
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
/** SCSI Sense Code to indicate that the device is not ready for a new command. */
#define SCSI_SENSE_KEY_NOT_READY 0x02
/** SCSI Sense Code to indicate an error whilst accessing the medium. */
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
/** SCSI Sense Code to indicate a hardware error has occurred. */
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
/** SCSI Sense Code to indicate that an illegal request has been issued. */
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
/** SCSI Sense Code to indicate that the unit requires attention from the host to indicate
* a reset event, medium removal or other condition.
*/
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
/** SCSI Sense Code to indicate that a write attempt on a protected block has been made. */
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
/** SCSI Sense Code to indicate an error while trying to write to a write-once medium. */
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
/** SCSI Sense Code to indicate a vendor specific error has occurred. */
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
/** SCSI Sense Code to indicate that an EXTENDED COPY command has aborted due to an error. */
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
/** SCSI Sense Code to indicate that the device has aborted the issued command. */
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
/** SCSI Sense Code to indicate an attempt to write past the end of a partition has been made. */
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
/** SCSI Sense Code to indicate that the source data did not match the data read from the medium. */
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
//@}
/** \name SCSI Additional Sense Codes */
//@{
/** SCSI Additional Sense Code to indicate no additional sense information is available. */
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
/** SCSI Additional Sense Code to indicate that the logical unit (LUN) addressed is not ready. */
#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
/** SCSI Additional Sense Code to indicate an invalid field was encountered while processing the issued command. */
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
/** SCSI Additional Sense Code to indicate that a medium that was previously indicated as not ready has now
* become ready for use.
*/
#define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28
/** SCSI Additional Sense Code to indicate that an attempt to write to a protected area was made. */
#define SCSI_ASENSE_WRITE_PROTECTED 0x27
/** SCSI Additional Sense Code to indicate an error whilst formatting the device medium. */
#define SCSI_ASENSE_FORMAT_ERROR 0x31
/** SCSI Additional Sense Code to indicate an invalid command was issued. */
#define SCSI_ASENSE_INVALID_COMMAND 0x20
/** SCSI Additional Sense Code to indicate a write to a block out outside of the medium's range was issued. */
#define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
/** SCSI Additional Sense Code to indicate that no removable medium is inserted into the device. */
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
//@}
/** \name SCSI Additional Sense Key Code Qualifiers */
//@{
/** SCSI Additional Sense Qualifier Code to indicate no additional sense qualifier information is available. */
#define SCSI_ASENSEQ_NO_QUALIFIER 0x00
/** SCSI Additional Sense Qualifier Code to indicate that a medium format command failed to complete. */
#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
/** SCSI Additional Sense Qualifier Code to indicate that an initializing command must be issued before the issued
* command can be executed.
*/
#define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
/** SCSI Additional Sense Qualifier Code to indicate that an operation is currently in progress. */
#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
//@}
/* Enums: */
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the Mass
* Storage device class.
*/
enum MS_Descriptor_ClassSubclassProtocol_t
{
MS_CSCP_MassStorageClass = 0x08, /**< Descriptor Class value indicating that the device or interface
* belongs to the Mass Storage class.
*/
MS_CSCP_SCSITransparentSubclass = 0x06, /**< Descriptor Subclass value indicating that the device or interface
* belongs to the SCSI Transparent Command Set subclass of the Mass
* storage class.
*/
MS_CSCP_BulkOnlyTransportProtocol = 0x50, /**< Descriptor Protocol value indicating that the device or interface
* belongs to the Bulk Only Transport protocol of the Mass Storage class.
*/
};
/** Enum for the Mass Storage class specific control requests that can be issued by the USB bus host. */
enum MS_ClassRequests_t
{
MS_REQ_GetMaxLUN = 0xFE, /**< Mass Storage class-specific request to retrieve the total number of Logical
* Units (drives) in the SCSI device.
*/
MS_REQ_MassStorageReset = 0xFF, /**< Mass Storage class-specific request to reset the Mass Storage interface,
* ready for the next command.
*/
};
/** Enum for the possible command status wrapper return status codes. */
enum MS_CommandStatusCodes_t
{
MS_SCSI_COMMAND_Pass = 0, /**< Command completed with no error */
MS_SCSI_COMMAND_Fail = 1, /**< Command failed to complete - host may check the exact error via a
* SCSI REQUEST SENSE command.
*/
MS_SCSI_COMMAND_PhaseError = 2, /**< Command failed due to being invalid in the current phase. */
};
/* Type Defines: */
/** \brief Mass Storage Class Command Block Wrapper.
*
* Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t Signature; /**< Command block signature, must be \ref MS_CBW_SIGNATURE to indicate a valid Command Block. */
uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper. */
uint32_t DataTransferLength; /**< Length of the optional data portion of the issued command, in bytes. */
uint8_t Flags; /**< Command block flags, indicating command data direction. */
uint8_t LUN; /**< Logical Unit number this command is issued to. */
uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array. */
uint8_t SCSICommandData[16]; /**< Issued SCSI command in the Command Block. */
} ATTR_PACKED MS_CommandBlockWrapper_t;
/** \brief Mass Storage Class Command Status Wrapper.
*
* Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t Signature; /**< Status block signature, must be \ref MS_CSW_SIGNATURE to indicate a valid Command Status. */
uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper. */
uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command. */
uint8_t Status; /**< Status code of the issued command - a value from the \ref MS_CommandStatusCodes_t enum. */
} ATTR_PACKED MS_CommandStatusWrapper_t;
/** \brief Mass Storage Class SCSI Sense Structure
*
* Type define for a SCSI Sense structure. Structures of this type are filled out by the
* device via the \ref MS_Host_RequestSense() function, indicating the current sense data of the
* device (giving explicit error codes for the last issued command). For details of the
* structure contents, refer to the SCSI specifications.
*/
typedef struct
{
uint8_t ResponseCode;
uint8_t SegmentNumber;
unsigned SenseKey : 4;
unsigned Reserved : 1;
unsigned ILI : 1;
unsigned EOM : 1;
unsigned FileMark : 1;
uint8_t Information[4];
uint8_t AdditionalLength;
uint8_t CmdSpecificInformation[4];
uint8_t AdditionalSenseCode;
uint8_t AdditionalSenseQualifier;
uint8_t FieldReplaceableUnitCode;
uint8_t SenseKeySpecific[3];
} ATTR_PACKED SCSI_Request_Sense_Response_t;
/** \brief Mass Storage Class SCSI Inquiry Structure.
*
* Type define for a SCSI Inquiry structure. Structures of this type are filled out by the
* device via the \ref MS_Host_GetInquiryData() function, retrieving the attached device's
* information.
*
* For details of the structure contents, refer to the SCSI specifications.
*/
typedef struct
{
unsigned DeviceType : 5;
unsigned PeripheralQualifier : 3;
unsigned Reserved : 7;
unsigned Removable : 1;
uint8_t Version;
unsigned ResponseDataFormat : 4;
unsigned Reserved2 : 1;
unsigned NormACA : 1;
unsigned TrmTsk : 1;
unsigned AERC : 1;
uint8_t AdditionalLength;
uint8_t Reserved3[2];
unsigned SoftReset : 1;
unsigned CmdQue : 1;
unsigned Reserved4 : 1;
unsigned Linked : 1;
unsigned Sync : 1;
unsigned WideBus16Bit : 1;
unsigned WideBus32Bit : 1;
unsigned RelAddr : 1;
uint8_t VendorID[8];
uint8_t ProductID[16];
uint8_t RevisionID[4];
} ATTR_PACKED SCSI_Inquiry_Response_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,119 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB Printer Class driver.
*
* Common definitions and declarations for the library USB Printer Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassPrinter
* \defgroup Group_USBClassPrinterCommon Common Class Definitions
*
* \section Sec_USBClassPrinterCommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* Printer Class.
*
* @{
*/
#ifndef _PRINTER_CLASS_COMMON_H_
#define _PRINTER_CLASS_COMMON_H_
/* Includes: */
#include "../../Core/StdDescriptors.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
#endif
/* Macros: */
/** \name Virtual Printer Status Line Masks */
//@{
/** Port status mask for a printer device, indicating that an error has *not* occurred. */
#define PRNT_PORTSTATUS_NOTERROR (1 << 3)
/** Port status mask for a printer device, indicating that the device is currently selected. */
#define PRNT_PORTSTATUS_SELECT (1 << 4)
/** Port status mask for a printer device, indicating that the device is currently out of paper. */
#define PRNT_PORTSTATUS_PAPEREMPTY (1 << 5)
//@}
/* Enums: */
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the Printer
* device class.
*/
enum PRNT_Descriptor_ClassSubclassProtocol_t
{
PRNT_CSCP_PrinterClass = 0x07, /**< Descriptor Class value indicating that the device or interface
* belongs to the Printer class.
*/
PRNT_CSCP_PrinterSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or interface
* belongs to the Printer subclass.
*/
PRNT_CSCP_BidirectionalProtocol = 0x02, /**< Descriptor Protocol value indicating that the device or interface
* belongs to the Bidirectional protocol of the Printer class.
*/
};
/** Enum for the Printer class specific control requests that can be issued by the USB bus host. */
enum PRNT_ClassRequests_t
{
PRNT_REQ_GetDeviceID = 0x00, /**< Printer class-specific request to retrieve the Unicode ID
* string of the device, containing the device's name, manufacturer
* and supported printer languages.
*/
PRNT_REQ_GetPortStatus = 0x01, /**< Printer class-specific request to get the current status of the
* virtual printer port, for device selection and ready states.
*/
PRNT_REQ_SoftReset = 0x02, /**< Printer class-specific request to reset the device, ready for new
* printer commands.
*/
};
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,411 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB RNDIS Class driver.
*
* Common definitions and declarations for the library USB RNDIS Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassRNDIS
* \defgroup Group_USBClassRNDISCommon Common Class Definitions
*
* \section Sec_USBClassRNDISCommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* RNDIS Class.
*
* @{
*/
#ifndef _RNDIS_CLASS_COMMON_H_
#define _RNDIS_CLASS_COMMON_H_
/* Macros: */
#define __INCLUDE_FROM_CDC_DRIVER
/* Includes: */
#include "../../Core/StdDescriptors.h"
#include "CDCClassCommon.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/USB.h instead.
#endif
/* Macros: */
/** Additional error code for RNDIS functions when a device returns a logical command failure. */
#define RNDIS_ERROR_LOGICAL_CMD_FAILED 0x80
/** Implemented RNDIS Version Major. */
#define REMOTE_NDIS_VERSION_MAJOR 0x01
/** Implemented RNDIS Version Minor. */
#define REMOTE_NDIS_VERSION_MINOR 0x00
/** \name RNDIS Message Values */
//@{
#define REMOTE_NDIS_PACKET_MSG 0x00000001UL
#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL
#define REMOTE_NDIS_HALT_MSG 0x00000003UL
#define REMOTE_NDIS_QUERY_MSG 0x00000004UL
#define REMOTE_NDIS_SET_MSG 0x00000005UL
#define REMOTE_NDIS_RESET_MSG 0x00000006UL
#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL
#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL
//@}
/** \name RNDIS Response Values */
//@{
#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL
#define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL
#define REMOTE_NDIS_SET_CMPLT 0x80000005UL
#define REMOTE_NDIS_RESET_CMPLT 0x80000006UL
#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL
//@}
/** \name RNDIS Status Values */
//@{
#define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL
#define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL
#define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL
#define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL
#define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL
#define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL
//@}
/** \name RNDIS Media States */
//@{
#define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL
#define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL
//@}
/** \name RNDIS Media Types */
//@{
#define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL
//@}
/** \name RNDIS Connection Types */
//@{
#define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL
#define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL
//@}
/** \name RNDIS Packet Types */
//@{
#define REMOTE_NDIS_PACKET_DIRECTED 0x00000001UL
#define REMOTE_NDIS_PACKET_MULTICAST 0x00000002UL
#define REMOTE_NDIS_PACKET_ALL_MULTICAST 0x00000004UL
#define REMOTE_NDIS_PACKET_BROADCAST 0x00000008UL
#define REMOTE_NDIS_PACKET_SOURCE_ROUTING 0x00000010UL
#define REMOTE_NDIS_PACKET_PROMISCUOUS 0x00000020UL
#define REMOTE_NDIS_PACKET_SMT 0x00000040UL
#define REMOTE_NDIS_PACKET_ALL_LOCAL 0x00000080UL
#define REMOTE_NDIS_PACKET_GROUP 0x00001000UL
#define REMOTE_NDIS_PACKET_ALL_FUNCTIONAL 0x00002000UL
#define REMOTE_NDIS_PACKET_FUNCTIONAL 0x00004000UL
#define REMOTE_NDIS_PACKET_MAC_FRAME 0x00008000UL
//@}
/** \name RNDIS OID Values */
//@{
#define OID_GEN_SUPPORTED_LIST 0x00010101UL
#define OID_GEN_HARDWARE_STATUS 0x00010102UL
#define OID_GEN_MEDIA_SUPPORTED 0x00010103UL
#define OID_GEN_MEDIA_IN_USE 0x00010104UL
#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL
#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
#define OID_GEN_LINK_SPEED 0x00010107UL
#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL
#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL
#define OID_GEN_VENDOR_ID 0x0001010CUL
#define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL
#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL
#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL
#define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL
#define OID_GEN_XMIT_OK 0x00020101UL
#define OID_GEN_RCV_OK 0x00020102UL
#define OID_GEN_XMIT_ERROR 0x00020103UL
#define OID_GEN_RCV_ERROR 0x00020104UL
#define OID_GEN_RCV_NO_BUFFER 0x00020105UL
#define OID_802_3_PERMANENT_ADDRESS 0x01010101UL
#define OID_802_3_CURRENT_ADDRESS 0x01010102UL
#define OID_802_3_MULTICAST_LIST 0x01010103UL
#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL
#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL
#define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL
#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL
//@}
/** Maximum size in bytes of an Ethernet frame according to the Ethernet standard. */
#define ETHERNET_FRAME_SIZE_MAX 1500
/* Enums: */
/** Enum for the RNDIS class specific control requests that can be issued by the USB bus host. */
enum RNDIS_ClassRequests_t
{
RNDIS_REQ_SendEncapsulatedCommand = 0x00, /**< RNDIS request to issue a host-to-device NDIS command. */
RNDIS_REQ_GetEncapsulatedResponse = 0x01, /**< RNDIS request to issue a device-to-host NDIS response. */
};
/** Enum for the possible NDIS adapter states. */
enum RNDIS_States_t
{
RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized. */
RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers. */
RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers. */
};
/** Enum for the RNDIS class specific notification requests that can be issued by a RNDIS device to a host. */
enum RNDIS_ClassNotifications_t
{
RNDIS_NOTIF_ResponseAvailable = 0x01, /**< Notification request value for a RNDIS Response Available notification. */
};
/** Enum for the NDIS hardware states. */
enum NDIS_Hardware_Status_t
{
NDIS_HardwareStatus_Ready, /**< Hardware Ready to accept commands from the host. */
NDIS_HardwareStatus_Initializing, /**< Hardware busy initializing. */
NDIS_HardwareStatus_Reset, /**< Hardware reset. */
NDIS_HardwareStatus_Closing, /**< Hardware currently closing. */
NDIS_HardwareStatus_NotReady /**< Hardware not ready to accept commands from the host. */
};
/* Type Defines: */
/** \brief MAC Address Structure.
*
* Type define for a physical MAC address of a device on a network.
*/
typedef struct
{
uint8_t Octets[6]; /**< Individual bytes of a MAC address */
} ATTR_PACKED MAC_Address_t;
/** \brief RNDIS Common Message Header Structure.
*
* Type define for a RNDIS message header, sent before RNDIS messages.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType; /**< RNDIS message type, a \c REMOTE_NDIS_*_MSG constant */
uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */
} ATTR_PACKED RNDIS_Message_Header_t;
/** \brief RNDIS Message Structure.
*
* Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t DataOffset;
uint32_t DataLength;
uint32_t OOBDataOffset;
uint32_t OOBDataLength;
uint32_t NumOOBDataElements;
uint32_t PerPacketInfoOffset;
uint32_t PerPacketInfoLength;
uint32_t VcHandle;
uint32_t Reserved;
} ATTR_PACKED RNDIS_Packet_Message_t;
/** \brief RNDIS Initialization Message Structure.
*
* Type define for a RNDIS Initialize command message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
uint32_t MajorVersion;
uint32_t MinorVersion;
uint32_t MaxTransferSize;
} ATTR_PACKED RNDIS_Initialize_Message_t;
/** \brief RNDIS Initialize Complete Message Structure.
*
* Type define for a RNDIS Initialize Complete response message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
uint32_t Status;
uint32_t MajorVersion;
uint32_t MinorVersion;
uint32_t DeviceFlags;
uint32_t Medium;
uint32_t MaxPacketsPerTransfer;
uint32_t MaxTransferSize;
uint32_t PacketAlignmentFactor;
uint32_t AFListOffset;
uint32_t AFListSize;
} ATTR_PACKED RNDIS_Initialize_Complete_t;
/** \brief RNDIS Keep Alive Message Structure.
*
* Type define for a RNDIS Keep Alive command message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
} ATTR_PACKED RNDIS_KeepAlive_Message_t;
/** \brief RNDIS Keep Alive Complete Message Structure.
*
* Type define for a RNDIS Keep Alive Complete response message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
uint32_t Status;
} ATTR_PACKED RNDIS_KeepAlive_Complete_t;
/** \brief RNDIS Reset Complete Message Structure.
*
* Type define for a RNDIS Reset Complete response message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t Status;
uint32_t AddressingReset;
} ATTR_PACKED RNDIS_Reset_Complete_t;
/** \brief RNDIS OID Property Set Message Structure.
*
* Type define for a RNDIS OID Property Set command message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
uint32_t Oid;
uint32_t InformationBufferLength;
uint32_t InformationBufferOffset;
uint32_t DeviceVcHandle;
} ATTR_PACKED RNDIS_Set_Message_t;
/** \brief RNDIS OID Property Set Complete Message Structure.
*
* Type define for a RNDIS OID Property Set Complete response message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
uint32_t Status;
} ATTR_PACKED RNDIS_Set_Complete_t;
/** \brief RNDIS OID Property Query Message Structure.
*
* Type define for a RNDIS OID Property Query command message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
uint32_t Oid;
uint32_t InformationBufferLength;
uint32_t InformationBufferOffset;
uint32_t DeviceVcHandle;
} ATTR_PACKED RNDIS_Query_Message_t;
/** \brief RNDIS OID Property Query Complete Message Structure.
*
* Type define for a RNDIS OID Property Query Complete response message.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t MessageType;
uint32_t MessageLength;
uint32_t RequestId;
uint32_t Status;
uint32_t InformationBufferLength;
uint32_t InformationBufferOffset;
} ATTR_PACKED RNDIS_Query_Complete_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,161 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Common definitions and declarations for the library USB Still Image Class driver.
*
* Common definitions and declarations for the library USB Still Image Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassSI
* \defgroup Group_USBClassSICommon Common Class Definitions
*
* \section Sec_USBClassSICommon_ModDescription Module Description
* Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
* Still Image Class.
*
* @{
*/
#ifndef _SI_CLASS_COMMON_H_
#define _SI_CLASS_COMMON_H_
/* Includes: */
#include "../../Core/StdDescriptors.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_SI_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
#endif
/* Macros: */
/** Length in bytes of a given Unicode string's character length.
*
* \param[in] Chars Total number of Unicode characters in the string.
*
* \return Number of bytes of the given unicode string.
*/
#define UNICODE_STRING_LENGTH(Chars) ((Chars) << 1)
/** Used in the DataLength field of a PIMA container, to give the total container size in bytes for
* a command container.
*
* \param[in] Params Number of parameters which are to be sent in the \c Param field of the container.
*/
#define PIMA_COMMAND_SIZE(Params) ((sizeof(PIMA_Container_t) - 12) + ((Params) * sizeof(uint32_t)))
/** Used in the DataLength field of a PIMA container, to give the total container size in bytes for
* a data container.
*
* \param[in] DataLen Length in bytes of the data in the container.
*/
#define PIMA_DATA_SIZE(DataLen) ((sizeof(PIMA_Container_t) - 12) + (DataLen))
/* Enums: */
/** Enum for the possible PIMA contains types. */
enum PIMA_Container_Types_t
{
PIMA_CONTAINER_Undefined = 0, /**< Undefined container type. */
PIMA_CONTAINER_CommandBlock = 1, /**< Command Block container type. */
PIMA_CONTAINER_DataBlock = 2, /**< Data Block container type. */
PIMA_CONTAINER_ResponseBlock = 3, /**< Response container type. */
PIMA_CONTAINER_EventBlock = 4, /**< Event Block container type. */
};
/* Enums: */
/** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the
* Still Image device class.
*/
enum SI_Descriptor_ClassSubclassProtocol_t
{
SI_CSCP_StillImageClass = 0x06, /**< Descriptor Class value indicating that the device or interface
* belongs to the Still Image class.
*/
SI_CSCP_StillImageSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or interface
* belongs to the Still Image subclass.
*/
SI_CSCP_BulkOnlyProtocol = 0x01, /**< Descriptor Protocol value indicating that the device or interface
* belongs to the Bulk Only Transport protocol of the Still Image class.
*/
};
/** Enums for the possible status codes of a returned Response Block from an attached PIMA compliant Still Image device. */
enum PIMA_ResponseCodes_t
{
PIMA_RESPONSE_OK = 1, /**< Response code indicating no error in the issued command. */
PIMA_RESPONSE_GeneralError = 2, /**< Response code indicating a general error while processing the
* issued command.
*/
PIMA_RESPONSE_SessionNotOpen = 3, /**< Response code indicating that the sent command requires an open
* session before being issued.
*/
PIMA_RESPONSE_InvalidTransaction = 4, /**< Response code indicating an invalid transaction occurred. */
PIMA_RESPONSE_OperationNotSupported = 5, /**< Response code indicating that the issued command is not supported
* by the attached device.
*/
PIMA_RESPONSE_ParameterNotSupported = 6, /**< Response code indicating that one or more of the issued command's
* parameters are not supported by the device.
*/
};
/* Type Defines: */
/** \brief PIMA Still Image Device Command/Response Container.
*
* Type define for a PIMA container, use to send commands and receive responses to and from an
* attached Still Image device.
*
* \note Regardless of CPU architecture, these values should be stored as little endian.
*/
typedef struct
{
uint32_t DataLength; /**< Length of the container and data, in bytes. */
uint16_t Type; /**< Container type, a value from the \ref PIMA_Container_Types_t enum. */
uint16_t Code; /**< Command, event or response code of the container. */
uint32_t TransactionID; /**< Unique container ID to link blocks together. */
uint32_t Params[3]; /**< Block parameters to be issued along with the block code (command blocks only). */
} ATTR_PACKED PIMA_Container_t;
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,197 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_AUDIO_DRIVER
#define __INCLUDE_FROM_AUDIO_DEVICE_C
#include "AudioClassDevice.h"
void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
{
if (!(Endpoint_IsSETUPReceived()))
return;
if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE)
{
uint8_t InterfaceIndex = (USB_ControlRequest.wIndex & 0xFF);
if ((InterfaceIndex != AudioInterfaceInfo->Config.ControlInterfaceNumber) &&
(InterfaceIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber))
{
return;
}
}
else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT)
{
uint8_t EndpointAddress = (USB_ControlRequest.wIndex & 0xFF);
if ((EndpointAddress != AudioInterfaceInfo->Config.DataINEndpoint.Address) &&
(EndpointAddress != AudioInterfaceInfo->Config.DataOUTEndpoint.Address))
{
return;
}
}
switch (USB_ControlRequest.bRequest)
{
case REQ_SetInterface:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
AudioInterfaceInfo->State.InterfaceEnabled = ((USB_ControlRequest.wValue & 0xFF) != 0);
EVENT_Audio_Device_StreamStartStop(AudioInterfaceInfo);
}
break;
case AUDIO_REQ_GetStatus:
if ((USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) ||
(USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT)))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
}
break;
case AUDIO_REQ_SetCurrent:
case AUDIO_REQ_SetMinimum:
case AUDIO_REQ_SetMaximum:
case AUDIO_REQ_SetResolution:
if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT)
{
uint8_t EndpointProperty = USB_ControlRequest.bRequest;
uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex;
uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8);
if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress,
EndpointControl, NULL, NULL))
{
uint16_t ValueLength = USB_ControlRequest.wLength;
uint8_t Value[ValueLength];
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(Value, ValueLength);
Endpoint_ClearIN();
CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress,
EndpointControl, &ValueLength, Value);
}
}
else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE)
{
uint8_t Property = USB_ControlRequest.bRequest;
uint8_t Entity = (USB_ControlRequest.wIndex >> 8);
uint16_t Parameter = USB_ControlRequest.wValue;
if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity,
Parameter, NULL, NULL))
{
uint16_t ValueLength = USB_ControlRequest.wLength;
uint8_t Value[ValueLength];
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(Value, ValueLength);
Endpoint_ClearIN();
CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity,
Parameter, &ValueLength, Value);
}
}
break;
case AUDIO_REQ_GetCurrent:
case AUDIO_REQ_GetMinimum:
case AUDIO_REQ_GetMaximum:
case AUDIO_REQ_GetResolution:
if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT)
{
uint8_t EndpointProperty = USB_ControlRequest.bRequest;
uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex;
uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8);
uint16_t ValueLength = USB_ControlRequest.wLength;
uint8_t Value[ValueLength];
if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress,
EndpointControl, &ValueLength, Value))
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(Value, ValueLength);
Endpoint_ClearOUT();
}
}
else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE)
{
uint8_t Property = USB_ControlRequest.bRequest;
uint8_t Entity = (USB_ControlRequest.wIndex >> 8);
uint16_t Parameter = USB_ControlRequest.wValue;
uint16_t ValueLength = USB_ControlRequest.wLength;
uint8_t Value[ValueLength];
if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity,
Parameter, &ValueLength, Value))
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(Value, ValueLength);
Endpoint_ClearOUT();
}
}
break;
}
}
bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
{
memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State));
AudioInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_ISOCHRONOUS;
AudioInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_ISOCHRONOUS;
if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataINEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataOUTEndpoint, 1)))
return false;
return true;
}
void Audio_Device_Event_Stub(void)
{
}
#endif

View file

@ -0,0 +1,396 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 1.0 Class driver.
*
* Device mode driver for the library USB Audio 1.0 Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassAudio
* \defgroup Group_USBClassAudioDevice Audio 1.0 Class Device Mode Driver
*
* \section Sec_USBClassAudioDevice_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/AudioClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassAudioDevice_ModDescription Module Description
* Device Mode USB Class driver framework interface, for the Audio 1.0 USB Class driver.
*
* @{
*/
#ifndef _AUDIO_CLASS_DEVICE_H_
#define _AUDIO_CLASS_DEVICE_H_
/* Includes: */
#include "../../USB.h"
#include "../Common/AudioClassCommon.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/USB.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
* \c AudioInterfaceInfo parameter. This stores each Audio interface's configuration and state information.
*/
typedef struct
{
struct
{
uint8_t ControlInterfaceNumber; /**< Index of the Audio Control interface within the device this
* structure controls.
*/
uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this
* structure controls.
*/
USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
} 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 \c true if the endpoints were successfully configured, \c 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_ControlRequest() 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);
/** Audio class driver callback for the setting and retrieval of streaming endpoint properties. This callback must be implemented
* in the user application to handle property manipulations on streaming audio endpoints.
*
* When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for
* the given endpoint index, and should return as fast as possible. When non-NULL, this value may be altered for GET operations
* to indicate the size of the retrieved data.
*
* \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value
* of the \c DataLength parameter.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
* \param[in] EndpointProperty Property of the endpoint to get or set, a value from \ref Audio_ClassRequests_t.
* \param[in] EndpointAddress Address of the streaming endpoint whose property is being referenced.
* \param[in] EndpointControl Parameter of the endpoint to get or set, a value from \ref Audio_EndpointControls_t.
* \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
* length of the retrieved data. When NULL, the function should return whether the given property
* and parameter is valid for the requested endpoint without reading or modifying the Data buffer.
* \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
* the retrieved data is to be stored for GET operations.
*
* \return Boolean \c true if the property GET/SET was successful, \c false otherwise
*/
bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const uint8_t EndpointProperty,
const uint8_t EndpointAddress,
const uint8_t EndpointControl,
uint16_t* const DataLength,
uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1);
/** Audio class driver callback for the setting and retrieval of streaming interface properties. This callback must be implemented
* in the user application to handle property manipulations on streaming audio interfaces.
*
* When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for
* the given entity and should return as fast as possible. When non-NULL, this value may be altered for GET operations
* to indicate the size of the retrieved data.
*
* \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value
* of the \c DataLength parameter.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
* \param[in] Property Property of the interface to get or set, a value from \ref Audio_ClassRequests_t.
* \param[in] EntityAddress Address of the audio entity whose property is being referenced.
* \param[in] Parameter Parameter of the entity to get or set, specific to each type of entity (see USB Audio specification).
* \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
* length of the retrieved data. When NULL, the function should return whether the given property
* and parameter is valid for the requested endpoint without reading or modifying the Data buffer.
* \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
* the retrieved data is to be stored for GET operations.
*
* \return Boolean \c true if the property GET/SET was successful, \c false otherwise
*/
bool CALLBACK_Audio_Device_GetSetInterfaceProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const uint8_t Property,
const uint8_t EntityAddress,
const uint16_t Parameter,
uint16_t* const DataLength,
uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1);
/** Audio class driver event for an Audio Stream start/stop change. This event fires each time the device receives a stream enable or
* disable control request from the host, to start and stop the audio stream. The current state of the stream can be determined by the
* State.InterfaceEnabled value inside the Audio interface structure passed as a parameter.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
*/
void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo);
/* 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)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
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.
*
* \pre This function must only be called when the Device state machine is in the \ref 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 \c true if the given Audio interface has a sample to be read, \c false otherwise.
*/
static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
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.DataOUTEndpoint.Address);
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.
*
* \pre This function must only be called when the Device state machine is in the \ref 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 \c true if the given Audio interface is ready to accept the next sample, \c false otherwise.
*/
static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
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.DataINEndpoint.Address);
return Endpoint_IsINReady();
}
/** Reads the next 8-bit audio sample from the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Device_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_NON_NULL_PTR_ARG(1) 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_8();
if (!(Endpoint_BytesInEndpoint()))
Endpoint_ClearOUT();
return Sample;
}
/** Reads the next 16-bit audio sample from the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Device_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_NON_NULL_PTR_ARG(1) 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_16_LE();
if (!(Endpoint_BytesInEndpoint()))
Endpoint_ClearOUT();
return Sample;
}
/** Reads the next 24-bit audio sample from the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Device_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_NON_NULL_PTR_ARG(1) 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_8() << 16) | Endpoint_Read_16_LE());
if (!(Endpoint_BytesInEndpoint()))
Endpoint_ClearOUT();
return Sample;
}
/** Writes the next 8-bit audio sample to the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Device_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_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const int8_t Sample)
{
Endpoint_Write_8(Sample);
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size)
Endpoint_ClearIN();
}
/** Writes the next 16-bit audio sample to the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Device_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_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const int16_t Sample)
{
Endpoint_Write_16_LE(Sample);
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size)
Endpoint_ClearIN();
}
/** Writes the next 24-bit audio sample to the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Device_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_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
const int32_t Sample)
{
Endpoint_Write_16_LE(Sample);
Endpoint_Write_8(Sample >> 16);
if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size)
Endpoint_ClearIN();
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_AUDIO_DEVICE_C)
void Audio_Device_Event_Stub(void) ATTR_CONST;
void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(Audio_Device_Event_Stub);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,341 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_CDC_DRIVER
#define __INCLUDE_FROM_CDC_DEVICE_C
#include "CDCClassDevice.h"
void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
if (!(Endpoint_IsSETUPReceived()))
return;
if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
return;
switch (USB_ControlRequest.bRequest)
{
case CDC_REQ_GetLineEncoding:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
Endpoint_Write_32_LE(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.CharFormat);
Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.ParityType);
Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.DataBits);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
break;
case CDC_REQ_SetLineEncoding:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsOUTReceived()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE();
CDCInterfaceInfo->State.LineEncoding.CharFormat = Endpoint_Read_8();
CDCInterfaceInfo->State.LineEncoding.ParityType = Endpoint_Read_8();
CDCInterfaceInfo->State.LineEncoding.DataBits = Endpoint_Read_8();
Endpoint_ClearOUT();
Endpoint_ClearStatusStage();
EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
}
break;
case CDC_REQ_SetControlLineState:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
}
break;
case CDC_REQ_SendBreak:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
}
break;
}
}
bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
CDCInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
CDCInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
CDCInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;
if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataINEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataOUTEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.NotificationEndpoint, 1)))
return false;
return true;
}
void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
return;
#if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
if (Endpoint_IsINReady())
CDC_Device_Flush(CDCInterfaceInfo);
#endif
}
uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
const char* const String)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
}
uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
const void* const Buffer,
const uint16_t Length)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
}
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.DataINEndpoint.Address);
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
uint8_t ErrorCode;
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
return ErrorCode;
}
Endpoint_Write_8(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.DataINEndpoint.Address);
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.DataOUTEndpoint.Address);
if (Endpoint_IsOUTReceived())
{
if (!(Endpoint_BytesInEndpoint()))
{
Endpoint_ClearOUT();
return 0;
}
else
{
return Endpoint_BytesInEndpoint();
}
}
else
{
return 0;
}
}
int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
return -1;
int16_t ReceivedByte = -1;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);
if (Endpoint_IsOUTReceived())
{
if (Endpoint_BytesInEndpoint())
ReceivedByte = Endpoint_Read_8();
if (!(Endpoint_BytesInEndpoint()))
Endpoint_ClearOUT();
}
return ReceivedByte;
}
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.NotificationEndpoint.Address);
USB_Request_Header_t Notification = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = CDC_NOTIF_SerialState,
.wValue = CPU_TO_LE16(0),
.wIndex = CPU_TO_LE16(0),
.wLength = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)),
};
Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
NULL);
Endpoint_ClearIN();
}
#if defined(FDEV_SETUP_STREAM)
void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
FILE* const 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* const CDCInterfaceInfo,
FILE* const 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)
{
int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
if (ReceivedByte < 0)
return _FDEV_EOF;
return ReceivedByte;
}
static int CDC_Device_getchar_Blocking(FILE* Stream)
{
int16_t ReceivedByte;
while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return _FDEV_EOF;
CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
USB_USBTask();
}
return ReceivedByte;
}
#endif
void CDC_Device_Event_Stub(void)
{
}
#endif

View file

@ -0,0 +1,352 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassCDC
* \defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver
*
* \section Sec_USBClassCDCDevice_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/CDCClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassCDCDevice_ModDescription 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. This is because each interface will be loaded into a separate driver
* instance, causing the two interfaces be become unlinked. To prevent this, you
* should use the "Interface Association Descriptor" addendum to the USB 2.0 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. It is thus highly recommended
* that the virtual serial line DTR (Data Terminal Ready) signal 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/CDCClassCommon.h"
#include <stdio.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/USB.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
{
struct
{
uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */
USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */
} 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
{
uint16_t HostToDevice; /**< Control line states from the host to device, as a set of \c CDC_CONTROL_LINE_OUT_*
* masks. This value is updated each time \ref CDC_Device_USBTask() is called.
*/
uint16_t DeviceToHost; /**< Control line states from the device to host, as a set of \c 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. */
CDC_LineEncoding_t 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 \c true if the endpoints were successfully configured, \c 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_ControlRequest() 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 \c 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 \c ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as
* a mask of \c 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 separate
* 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,
const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a given data buffer 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.
*
* \pre This function must only be called when the Device state machine is in the \ref 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] Buffer Pointer to a buffer containing the data to send to the device.
* \param[in] Length Length of the data to send to the host.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
const void* const Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Sends a given null terminated 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.
*
* \pre This function must only be called when the Device state machine is in the \ref 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] String Pointer to the null terminated 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,
const char* const String) 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.
*
* \pre This function must only be called when the Device state machine is in the \ref 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. This indicates the number
* of bytes in the OUT endpoint bank only, and thus the number of calls to \ref CDC_Device_ReceiveByte() which are guaranteed to
* succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint
* bank will not be released back to the USB controller until all bytes are read.
*
* \pre This function must only be called when the Device state machine is in the \ref 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 a negative value. The \ref CDC_Device_BytesReceived() function may be queried in advance to determine how many
* bytes are currently buffered in the CDC interface's data receive endpoint bank, and thus how many repeated calls to this
* function which are guaranteed to succeed.
*
* \pre This function must only be called when the Device state machine is in the \ref 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 a negative value if no data received.
*/
int16_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.
*
* \pre This function must only be called when the Device state machine is in the \ref 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
* \c ControlLineStates.DeviceToHost value is updated to push the new states to the USB host.
*
* \pre This function must only be called when the Device state machine is in the \ref 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);
#if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__)
/** Creates a standard character stream for the given CDC Device instance so that it can be used with all the regular
* functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c 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 \c getc()) or when the user application will implement its own
* line buffering.
*
* \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
* to the given CDC interface.
* \n\n
*
* \note This function is not available on all microcontroller architectures.
*
* \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* const CDCInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Identical to \ref 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.
*
* \note This function is not available on all microcontroller architectures.
*
* \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* const CDCInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_CDC_DEVICE_C)
#if defined(FDEV_SETUP_STREAM)
static int CDC_Device_putchar(char c,
FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
static int CDC_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
static int CDC_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
#endif
void CDC_Device_Event_Stub(void) ATTR_CONST;
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,
const 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
/** @} */

View file

@ -0,0 +1,211 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_HID_DRIVER
#define __INCLUDE_FROM_HID_DEVICE_C
#include "HIDClassDevice.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 HID_REQ_GetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
uint16_t ReportSize = 0;
uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1;
uint8_t ReportData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
memset(ReportData, 0, sizeof(ReportData));
CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, ReportType, ReportData, &ReportSize);
if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
{
memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportData,
HIDInterfaceInfo->Config.PrevReportINBufferSize);
}
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
Endpoint_ClearSETUP();
if (ReportID)
Endpoint_Write_8(ReportID);
Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
Endpoint_ClearOUT();
}
break;
case HID_REQ_SetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
uint16_t ReportSize = USB_ControlRequest.wLength;
uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1;
uint8_t ReportData[ReportSize];
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(ReportData, ReportSize);
Endpoint_ClearIN();
CALLBACK_HID_Device_ProcessHIDReport(HIDInterfaceInfo, ReportID, ReportType,
&ReportData[ReportID ? 1 : 0], ReportSize - (ReportID ? 1 : 0));
}
break;
case HID_REQ_GetProtocol:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
Endpoint_Write_8(HIDInterfaceInfo->State.UsingReportProtocol);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
break;
case HID_REQ_SetProtocol:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
HIDInterfaceInfo->State.UsingReportProtocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
}
break;
case HID_REQ_SetIdle:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);
}
break;
case HID_REQ_GetIdle:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
Endpoint_Write_8(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;
HIDInterfaceInfo->Config.ReportINEndpoint.Type = EP_TYPE_INTERRUPT;
if (!(Endpoint_ConfigureEndpointTable(&HIDInterfaceInfo->Config.ReportINEndpoint, 1)))
return false;
return true;
}
void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
if (HIDInterfaceInfo->State.PrevFrameNum == USB_Device_GetFrameNumber())
{
#if defined(USB_DEVICE_OPT_LOWSPEED)
if (!(USB_Options & USB_DEVICE_OPT_LOWSPEED))
return;
#else
return;
#endif
}
Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpoint.Address);
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, HID_REPORT_ITEM_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.ReportINEndpoint.Address);
if (ReportID)
Endpoint_Write_8(ReportID);
Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NULL);
Endpoint_ClearIN();
}
HIDInterfaceInfo->State.PrevFrameNum = USB_Device_GetFrameNumber();
}
}
#endif

View file

@ -0,0 +1,210 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassHID
* \defgroup Group_USBClassHIDDevice HID Class Device Mode Driver
*
* \section Sec_USBClassHIDDevice_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/HIDClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassHIDDevice_ModDescription 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/HIDClassCommon.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/USB.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
* \c 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
{
struct
{
uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device. */
USB_Endpoint_Table_t ReportINEndpoint; /**< Data IN HID report endpoint configuration table. */
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 \c 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 \c 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. \c PrevReportINBuffer is \c 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 PrevFrameNum; /**< Frame number of the previous HID report packet opportunity. */
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 \c true if the endpoints were successfully configured, \c false otherwise.
*/
bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const 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_ControlRequest() 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* const 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* const 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 HID_REPORT_ITEM_In or \ref HID_REPORT_ITEM_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 \c 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), \c 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* const 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] ReportType Type of received HID report, either \ref HID_REPORT_ITEM_Out or \ref HID_REPORT_ITEM_Feature.
* \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 uint8_t ReportType,
const void* ReportData,
const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4);
/* 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* const HIDInterfaceInfo) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
{
if (HIDInterfaceInfo->State.IdleMSRemaining)
HIDInterfaceInfo->State.IdleMSRemaining--;
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,131 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_MIDI_DRIVER
#define __INCLUDE_FROM_MIDI_DEVICE_C
#include "MIDIClassDevice.h"
bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
{
memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
MIDIInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
MIDIInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataINEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataOUTEndpoint, 1)))
return false;
return true;
}
void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
#if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address);
if (Endpoint_IsINReady())
MIDI_Device_Flush(MIDIInterfaceInfo);
#endif
}
uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
const MIDI_EventPacket_t* const Event)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return ENDPOINT_RWSTREAM_DeviceDisconnected;
uint8_t ErrorCode;
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address);
if ((ErrorCode = Endpoint_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != 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.DataINEndpoint.Address);
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.DataOUTEndpoint.Address);
if (!(Endpoint_IsOUTReceived()))
return false;
if (!(Endpoint_IsReadWriteAllowed()))
return false;
Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL);
if (!(Endpoint_IsReadWriteAllowed()))
Endpoint_ClearOUT();
return true;
}
#endif

View file

@ -0,0 +1,175 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassMIDI
* \defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver
*
* \section Sec_USBClassMIDIDevice_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassMIDIDevice_ModDescription 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/MIDIClassCommon.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/USB.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
* \c MIDIInterfaceInfo parameter. This stores each MIDI interface's configuration and state information.
*/
typedef struct
{
struct
{
uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls. */
USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
} 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 RESERVED; // No state information for this class
} 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 \c true if the endpoints were successfully configured, \c false otherwise.
*/
bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** 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.
*/
void MIDI_Device_USBTask(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.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_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 \ref 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,
const 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 behavior, 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) ATTR_NON_NULL_PTR_ARG(1);
/** 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.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_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 \c true if a MIDI event packet was received, \c 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: */
/** 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_ControlRequest() 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
/** @} */

View file

@ -0,0 +1,215 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_MS_DRIVER
#define __INCLUDE_FROM_MASSSTORAGE_DEVICE_C
#include "MassStorageClassDevice.h"
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 MS_REQ_MassStorageReset:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
MSInterfaceInfo->State.IsMassStoreReset = true;
}
break;
case MS_REQ_GetMaxLUN:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
Endpoint_Write_8(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));
MSInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
MSInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataINEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataOUTEndpoint, 1)))
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.DataOUTEndpoint.Address);
if (Endpoint_IsOUTReceived())
{
if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
{
if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo);
MSInterfaceInfo->State.CommandStatus.Status = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail;
MSInterfaceInfo->State.CommandStatus.Signature = CPU_TO_LE32(MS_CSW_SIGNATURE);
MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag;
MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;
if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue)))
Endpoint_StallTransaction();
MS_Device_ReturnCommandStatus(MSInterfaceInfo);
}
}
if (MSInterfaceInfo->State.IsMassStoreReset)
{
Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
MSInterfaceInfo->State.IsMassStoreReset = false;
}
}
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
uint16_t BytesProcessed;
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
BytesProcessed = 0;
while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock,
(sizeof(MS_CommandBlockWrapper_t) - 16), &BytesProcessed) ==
ENDPOINT_RWSTREAM_IncompleteTransfer)
{
if (MSInterfaceInfo->State.IsMassStoreReset)
return false;
}
if ((MSInterfaceInfo->State.CommandBlock.Signature != CPU_TO_LE32(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.DataINEndpoint.Address);
Endpoint_StallTransaction();
return false;
}
BytesProcessed = 0;
while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData,
MSInterfaceInfo->State.CommandBlock.SCSICommandLength, &BytesProcessed) ==
ENDPOINT_RWSTREAM_IncompleteTransfer)
{
if (MSInterfaceInfo->State.IsMassStoreReset)
return false;
}
Endpoint_ClearOUT();
return true;
}
static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
while (Endpoint_IsStalled())
{
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();
#endif
if (MSInterfaceInfo->State.IsMassStoreReset)
return;
}
Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
while (Endpoint_IsStalled())
{
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();
#endif
if (MSInterfaceInfo->State.IsMassStoreReset)
return;
}
uint16_t BytesProcessed = 0;
while (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus,
sizeof(MS_CommandStatusWrapper_t), &BytesProcessed) ==
ENDPOINT_RWSTREAM_IncompleteTransfer)
{
if (MSInterfaceInfo->State.IsMassStoreReset)
return;
}
Endpoint_ClearIN();
}
#endif

View file

@ -0,0 +1,161 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassMS
* \defgroup Group_USBClassMSDevice Mass Storage Class Device Mode Driver
*
* \section Sec_USBClassMSDevice_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassMSDevice_ModDescription 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/MassStorageClassCommon.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/USB.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
* \c MSInterfaceInfo parameter. This stores each Mass Storage interface's configuration and state information.
*/
typedef struct
{
struct
{
uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device. */
USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
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 \c true if the endpoints were successfully configured, \c 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_ControlRequest() 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 \c true if the SCSI command was successfully processed, \c 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_MASSSTORAGE_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);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,314 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_PRINTER_DRIVER
#define __INCLUDE_FROM_PRINTER_DEVICE_C
#include "PrinterClassDevice.h"
void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
{
if (!(Endpoint_IsSETUPReceived()))
return;
if (USB_ControlRequest.wIndex != PRNTInterfaceInfo->Config.InterfaceNumber)
return;
switch (USB_ControlRequest.bRequest)
{
case PRNT_REQ_GetDeviceID:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
uint16_t IEEEStringLen = strlen(PRNTInterfaceInfo->Config.IEEE1284String);
Endpoint_Write_16_BE(IEEEStringLen);
Endpoint_Write_Control_Stream_LE(PRNTInterfaceInfo->Config.IEEE1284String, IEEEStringLen);
Endpoint_ClearStatusStage();
}
break;
case PRNT_REQ_GetPortStatus:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
Endpoint_Write_8(PRNTInterfaceInfo->State.PortStatus);
Endpoint_ClearStatusStage();
}
break;
case PRNT_REQ_SoftReset:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
PRNTInterfaceInfo->State.IsPrinterReset = true;
EVENT_PRNT_Device_SoftReset(PRNTInterfaceInfo);
}
break;
}
}
bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
{
memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
PRNTInterfaceInfo->State.PortStatus = PRNT_PORTSTATUS_NOTERROR | PRNT_PORTSTATUS_SELECT;
PRNTInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
PRNTInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataINEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataOUTEndpoint, 1)))
return false;
return true;
}
void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
#if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
if (Endpoint_IsINReady())
PRNT_Device_Flush(PRNTInterfaceInfo);
#endif
if (PRNTInterfaceInfo->State.IsPrinterReset)
{
Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
PRNTInterfaceInfo->State.IsPrinterReset = false;
}
}
uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
const char* const String)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
}
uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
const void* const Buffer,
const uint16_t Length)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
}
uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
const uint8_t Data)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
if (!(Endpoint_IsReadWriteAllowed()))
{
Endpoint_ClearIN();
uint8_t ErrorCode;
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
return ErrorCode;
}
Endpoint_Write_8(Data);
return ENDPOINT_READYWAIT_NoError;
}
uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return ENDPOINT_RWSTREAM_DeviceDisconnected;
uint8_t ErrorCode;
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
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 PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return 0;
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
if (Endpoint_IsOUTReceived())
{
if (!(Endpoint_BytesInEndpoint()))
{
Endpoint_ClearOUT();
return 0;
}
else
{
return Endpoint_BytesInEndpoint();
}
}
else
{
return 0;
}
}
int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return -1;
int16_t ReceivedByte = -1;
Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
if (Endpoint_IsOUTReceived())
{
if (Endpoint_BytesInEndpoint())
ReceivedByte = Endpoint_Read_8();
if (!(Endpoint_BytesInEndpoint()))
Endpoint_ClearOUT();
}
return ReceivedByte;
}
#if defined(FDEV_SETUP_STREAM)
void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
FILE* const Stream)
{
*Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar, _FDEV_SETUP_RW);
fdev_set_udata(Stream, PRNTInterfaceInfo);
}
void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
FILE* const Stream)
{
*Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar_Blocking, _FDEV_SETUP_RW);
fdev_set_udata(Stream, PRNTInterfaceInfo);
}
static int PRNT_Device_putchar(char c,
FILE* Stream)
{
return PRNT_Device_SendByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
}
static int PRNT_Device_getchar(FILE* Stream)
{
int16_t ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream));
if (ReceivedByte < 0)
return _FDEV_EOF;
return ReceivedByte;
}
static int PRNT_Device_getchar_Blocking(FILE* Stream)
{
int16_t ReceivedByte;
while ((ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream))) < 0)
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return _FDEV_EOF;
PRNT_Device_USBTask((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream));
USB_USBTask();
}
return ReceivedByte;
}
#endif
void PRNT_Device_Event_Stub(void)
{
}
#endif

View file

@ -0,0 +1,293 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Printer Class driver.
*
* Device mode driver for the library USB Printer Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassPrinter
* \defgroup Group_USBClassPrinterDevice Printer Class Device Mode Driver
*
* \section Sec_USBClassPrinterDevice_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassPrinterDevice_ModDescription Module Description
* Device Mode USB Class driver framework interface, for the Printer USB Class driver.
*
* @{
*/
#ifndef _PRINTER_CLASS_DEVICE_H_
#define _PRINTER_CLASS_DEVICE_H_
/* Includes: */
#include "../../USB.h"
#include "../Common/PrinterClassCommon.h"
#include <stdio.h>
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Type Defines: */
/** \brief Printer Class Device Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made for each Printer interface
* within the user application, and passed to each of the Printer class driver functions as the
* PRNTInterfaceInfo parameter. This stores each Printer interface's configuration and state information.
*/
typedef struct
{
struct
{
uint8_t InterfaceNumber; /**< Interface number of the Printer interface within the device. */
USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
char* IEEE1284String; /**< IEEE 1284 identification string, sent to the host during enumeration
* to identify the printer model, manufacturer and other characteristics.
*/
} 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 PortStatus; /**< Current status of the Printer virtual port, a collection of \c PRNT_PORTSTATUS_*
* bitmask values.
*/
volatile bool IsPrinterReset; /**< Flag indicating that the host has requested that the Printer 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_PRNT_Device_t;
/* Function Prototypes: */
/** Configures the endpoints of a given Printer 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 Printer interface is selected.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
*
* \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
*/
bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Processes incoming control requests from the host, that are directed to the given Printer class interface. This should be
* linked to the library \ref EVENT_USB_Device_ControlRequest() event.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
*/
void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** General management task for a given Printer 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] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
*/
void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Printer class driver event for a soft reset request on a Printer interface. This event fires each time the host
* requests a reset of the printer interface's internal state, and may be hooked in the user program by declaring a
* handler function with the same name and parameters listed here.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
*/
void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a given data buffer 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 PRNT_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.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
* the call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
* \param[in] Buffer Pointer to a buffer containing the data to send to the device.
* \param[in] Length Length of the data to send to the host.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
const void* const Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Sends a given null terminated 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 PRNT_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.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
* the call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
* \param[in] String Pointer to the null terminated string to send to the host.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
const char* const String) 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 PRNT_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.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
* the call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer 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 PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
/** Determines the number of bytes received by the Printer interface from the host, waiting to be read. This indicates the number
* of bytes in the OUT endpoint bank only, and thus the number of calls to \ref PRNT_Device_ReceiveByte() which are guaranteed to
* succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint
* bank will not be released back to the USB controller until all bytes are read.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
* the call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
*
* \return Total number of buffered bytes received from the host.
*/
uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) 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 a negative value. The \ref PRNT_Device_BytesReceived() function may be queried in advance to determine how many
* bytes are currently buffered in the Printer interface's data receive endpoint bank, and thus how many repeated calls to this
* function which are guaranteed to succeed.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
* the call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
*
* \return Next received byte from the host, or a negative value if no data received.
*/
int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
* the call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
*
* \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
#if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__)
/** Creates a standard character stream for the given Printer Device instance so that it can be used with all the regular
* functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c 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 \c getc()) or when the user application will implement its own
* line buffering.
*
* \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
* to the given Printer interface.
* \n\n
*
* \note This function is not available on all microcontroller architectures.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
*/
void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Identical to \ref PRNT_Device_CreateStream(), except that reads are blocking until the calling stream function terminates
* the transfer. While blocking, the USB and Printer service tasks are called repeatedly to maintain USB communications.
*
* \note This function is not available on all microcontroller architectures.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
*/
void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_PRINTER_DEVICE_C)
#if defined(FDEV_SETUP_STREAM)
static int PRNT_Device_putchar(char c,
FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
static int PRNT_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
static int PRNT_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
#endif
void PRNT_Device_Event_Stub(void) ATTR_CONST;
void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(PRNT_Device_Event_Stub);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,508 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#define __INCLUDE_FROM_RNDIS_DRIVER
#define __INCLUDE_FROM_RNDIS_DEVICE_C
#include "RNDISClassDevice.h"
static const uint32_t PROGMEM AdapterSupportedOIDList[] =
{
CPU_TO_LE32(OID_GEN_SUPPORTED_LIST),
CPU_TO_LE32(OID_GEN_PHYSICAL_MEDIUM),
CPU_TO_LE32(OID_GEN_HARDWARE_STATUS),
CPU_TO_LE32(OID_GEN_MEDIA_SUPPORTED),
CPU_TO_LE32(OID_GEN_MEDIA_IN_USE),
CPU_TO_LE32(OID_GEN_MAXIMUM_FRAME_SIZE),
CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE),
CPU_TO_LE32(OID_GEN_LINK_SPEED),
CPU_TO_LE32(OID_GEN_TRANSMIT_BLOCK_SIZE),
CPU_TO_LE32(OID_GEN_RECEIVE_BLOCK_SIZE),
CPU_TO_LE32(OID_GEN_VENDOR_ID),
CPU_TO_LE32(OID_GEN_VENDOR_DESCRIPTION),
CPU_TO_LE32(OID_GEN_CURRENT_PACKET_FILTER),
CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE),
CPU_TO_LE32(OID_GEN_MEDIA_CONNECT_STATUS),
CPU_TO_LE32(OID_GEN_XMIT_OK),
CPU_TO_LE32(OID_GEN_RCV_OK),
CPU_TO_LE32(OID_GEN_XMIT_ERROR),
CPU_TO_LE32(OID_GEN_RCV_ERROR),
CPU_TO_LE32(OID_GEN_RCV_NO_BUFFER),
CPU_TO_LE32(OID_802_3_PERMANENT_ADDRESS),
CPU_TO_LE32(OID_802_3_CURRENT_ADDRESS),
CPU_TO_LE32(OID_802_3_MULTICAST_LIST),
CPU_TO_LE32(OID_802_3_MAXIMUM_LIST_SIZE),
CPU_TO_LE32(OID_802_3_RCV_ERROR_ALIGNMENT),
CPU_TO_LE32(OID_802_3_XMIT_ONE_COLLISION),
CPU_TO_LE32(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 RNDIS_REQ_SendEncapsulatedCommand:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, USB_ControlRequest.wLength);
Endpoint_ClearIN();
RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
}
break;
case RNDIS_REQ_GetEncapsulatedResponse:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
if (!(MessageHeader->MessageLength))
{
RNDISInterfaceInfo->Config.MessageBuffer[0] = 0;
MessageHeader->MessageLength = CPU_TO_LE32(1);
}
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, le32_to_cpu(MessageHeader->MessageLength));
Endpoint_ClearOUT();
MessageHeader->MessageLength = CPU_TO_LE32(0);
}
break;
}
}
bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
{
memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
RNDISInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
RNDISInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;
if (RNDISInterfaceInfo->Config.MessageBuffer == NULL)
return false;
if (RNDISInterfaceInfo->Config.MessageBufferLength < RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH)
return false;
if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataOUTEndpoint, 1)))
return false;
if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.NotificationEndpoint, 1)))
return false;
return true;
}
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpoint.Address);
if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
{
USB_Request_Header_t Notification = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = RNDIS_NOTIF_ResponseAvailable,
.wValue = CPU_TO_LE16(0),
.wIndex = CPU_TO_LE16(0),
.wLength = CPU_TO_LE16(0),
};
Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
Endpoint_ClearIN();
RNDISInterfaceInfo->State.ResponseReady = 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->Config.MessageBuffer;
switch (le32_to_cpu(MessageHeader->MessageType))
{
case REMOTE_NDIS_INITIALIZE_MSG:
RNDISInterfaceInfo->State.ResponseReady = true;
RNDIS_Initialize_Message_t* INITIALIZE_Message =
(RNDIS_Initialize_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
RNDIS_Initialize_Complete_t* INITIALIZE_Response =
(RNDIS_Initialize_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
INITIALIZE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT);
INITIALIZE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t));
INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
INITIALIZE_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
INITIALIZE_Response->MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);
INITIALIZE_Response->MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);
INITIALIZE_Response->DeviceFlags = CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS);
INITIALIZE_Response->Medium = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);
INITIALIZE_Response->MaxPacketsPerTransfer = CPU_TO_LE32(1);
INITIALIZE_Response->MaxTransferSize = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);
INITIALIZE_Response->PacketAlignmentFactor = CPU_TO_LE32(0);
INITIALIZE_Response->AFListOffset = CPU_TO_LE32(0);
INITIALIZE_Response->AFListSize = CPU_TO_LE32(0);
RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
break;
case REMOTE_NDIS_HALT_MSG:
RNDISInterfaceInfo->State.ResponseReady = false;
MessageHeader->MessageLength = CPU_TO_LE32(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->Config.MessageBuffer;
RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid);
void* QueryData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
le32_to_cpu(QUERY_Message->InformationBufferOffset)];
void* ResponseData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Query_Complete_t)];
uint16_t ResponseSize;
QUERY_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT);
if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength),
ResponseData, &ResponseSize))
{
QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
QUERY_Response->MessageLength = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize);
QUERY_Response->InformationBufferLength = CPU_TO_LE32(ResponseSize);
QUERY_Response->InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
}
else
{
QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED);
QUERY_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t));
QUERY_Response->InformationBufferLength = CPU_TO_LE32(0);
QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0);
}
break;
case REMOTE_NDIS_SET_MSG:
RNDISInterfaceInfo->State.ResponseReady = true;
RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
uint32_t SET_Oid = le32_to_cpu(SET_Message->Oid);
SET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT);
SET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t));
SET_Response->RequestId = SET_Message->RequestId;
void* SetData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
le32_to_cpu(SET_Message->InformationBufferOffset)];
SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,
le32_to_cpu(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->Config.MessageBuffer;
RESET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT);
RESET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t));
RESET_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
RESET_Response->AddressingReset = CPU_TO_LE32(0);
break;
case REMOTE_NDIS_KEEPALIVE_MSG:
RNDISInterfaceInfo->State.ResponseReady = true;
RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
(RNDIS_KeepAlive_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
(RNDIS_KeepAlive_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
KEEPALIVE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT);
KEEPALIVE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t));
KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
KEEPALIVE_Response->Status = CPU_TO_LE32(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) = CPU_TO_LE32(0);
return true;
case OID_GEN_HARDWARE_STATUS:
*ResponseSize = sizeof(uint32_t);
*((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready);
return true;
case OID_GEN_MEDIA_SUPPORTED:
case OID_GEN_MEDIA_IN_USE:
*ResponseSize = sizeof(uint32_t);
*((uint32_t*)ResponseData) = CPU_TO_LE32(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) = CPU_TO_LE32(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) = CPU_TO_LE32(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) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED);
return true;
case OID_GEN_LINK_SPEED:
*ResponseSize = sizeof(uint32_t);
/* Indicate 10Mb/s link speed */
*((uint32_t*)ResponseData) = CPU_TO_LE32(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) = CPU_TO_LE32(1);
return true;
case OID_GEN_CURRENT_PACKET_FILTER:
*ResponseSize = sizeof(uint32_t);
*((uint32_t*)ResponseData) = cpu_to_le32(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) = CPU_TO_LE32(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) = CPU_TO_LE32(RNDISInterfaceInfo->Config.MessageBufferLength + 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,
const void* SetData,
const uint16_t SetSize)
{
(void)SetSize;
switch (OId)
{
case OID_GEN_CURRENT_PACKET_FILTER:
RNDISInterfaceInfo->State.CurrPacketFilter = le32_to_cpu(*((uint32_t*)SetData));
RNDISInterfaceInfo->State.CurrRNDISState = (RNDISInterfaceInfo->State.CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_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;
}
}
bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) ||
(RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
{
return false;
}
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
return Endpoint_IsOUTReceived();
}
uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
void* Buffer,
uint16_t* const PacketLength)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) ||
(RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
{
return ENDPOINT_RWSTREAM_DeviceDisconnected;
}
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
*PacketLength = 0;
if (!(Endpoint_IsOUTReceived()))
return ENDPOINT_RWSTREAM_NoError;
RNDIS_Packet_Message_t RNDISPacketHeader;
Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX)
{
Endpoint_StallTransaction();
return RNDIS_ERROR_LOGICAL_CMD_FAILED;
}
*PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength);
Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL);
Endpoint_ClearOUT();
return ENDPOINT_RWSTREAM_NoError;
}
uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t PacketLength)
{
uint8_t ErrorCode;
if ((USB_DeviceState != DEVICE_STATE_Configured) ||
(RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
{
return ENDPOINT_RWSTREAM_DeviceDisconnected;
}
Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address);
if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
return ErrorCode;
RNDIS_Packet_Message_t RNDISPacketHeader;
memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
RNDISPacketHeader.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
RNDISPacketHeader.MessageLength = cpu_to_le32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
RNDISPacketHeader.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
RNDISPacketHeader.DataLength = cpu_to_le32(PacketLength);
Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);
Endpoint_ClearIN();
return ENDPOINT_RWSTREAM_NoError;
}
#endif

View file

@ -0,0 +1,207 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassRNDIS
* \defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver
*
* \section Sec_USBClassRNDISDevice_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassRNDISDevice_ModDescription 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/RNDISClassCommon.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/USB.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
* \c RNDISInterfaceInfo parameter. This stores each RNDIS interface's configuration and state information.
*/
typedef struct
{
struct
{
uint8_t ControlInterfaceNumber; /**< Interface number of the RNDIS control interface within the device. */
USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */
char* AdapterVendorDescription; /**< String description of the adapter vendor. */
MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */
uint8_t* MessageBuffer; /**< Buffer where RNDIS messages can be stored by the internal driver. This
* should be at least 132 bytes in length for minimal functionality. */
uint16_t MessageBufferLength; /**< Length in bytes of the \ref MessageBuffer RNDIS buffer. */
} 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 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 \ref RNDIS_States_t enum. */
uint32_t CurrPacketFilter; /**< Current packet filter mode, used internally by the class driver. */
} 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 RNDIS interface is selected.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state.
*
* \return Boolean \c true if the endpoints were successfully configured, \c 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_ControlRequest() 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 RNDIS 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);
/** Determines if a packet is currently waiting for the device to read in and process.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
* call will fail.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state.
*
* \return Boolean \c true if a packet is waiting to be read in by the host, \c false otherwise.
*/
bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
* only the packet contents for processing by the device in the nominated buffer.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
* call will fail.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state.
* \param[out] Buffer Pointer to a buffer where the packer data is to be written to.
* \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
void* Buffer,
uint16_t* const PacketLength) ATTR_NON_NULL_PTR_ARG(1);
/** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
*
* \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
* call will fail.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state.
* \param[in] Buffer Pointer to a buffer where the packer data is to be read from.
* \param[in] PacketLength Length in bytes of the packet to send.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t PacketLength) ATTR_NON_NULL_PTR_ARG(1);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_Query_Complete_t)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_RNDIS_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,
const 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
/** @} */

View file

@ -0,0 +1,82 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB HID Class driver.
*
* Master include file for the library USB HID Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassHID HID Class Driver
* \brief USB class driver for the USB-IF Human Interface Device (HID) class standard.
*
* \section Sec_USBClassHID_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/HIDClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/HIDClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/HIDParser.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
*
* \section Sec_USBClassHID_ModDescription Module Description
* HID Class Driver module. This module contains an internal implementation of the USB HID Class, for both Device
* and Host USB modes. User applications can use this class driver instead of implementing the HID class manually
* via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Hosts or Devices using the USB HID Class.
*
* @{
*/
#ifndef _HID_CLASS_H_
#define _HID_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_HID_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "Device/HIDClassDevice.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "Host/HIDClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,422 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_AOA_DRIVER
#define __INCLUDE_FROM_ANDROIDACCESSORY_HOST_C
#include "AndroidAccessoryClassHost.h"
bool AOA_Host_ValidateAccessoryDevice(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const USB_Descriptor_Device_t* const DeviceDescriptor,
bool* const NeedModeSwitch)
{
(void)AOAInterfaceInfo;
if (DeviceDescriptor->Header.Type != DTYPE_Device)
return false;
*NeedModeSwitch = ((DeviceDescriptor->ProductID != ANDROID_ACCESSORY_PRODUCT_ID) &&
(DeviceDescriptor->ProductID != ANDROID_ACCESSORY_ADB_PRODUCT_ID));
return true;
}
uint8_t AOA_Host_ConfigurePipes(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Interface_t* AOAInterface = NULL;
memset(&AOAInterfaceInfo->State, 0x00, sizeof(AOAInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return AOA_ENUMERROR_InvalidConfigDescriptor;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_AOA_Host_NextAndroidAccessoryInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return AOA_ENUMERROR_NoCompatibleInterfaceFound;
}
AOAInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_AOA_Host_NextInterfaceBulkEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
return AOA_ENUMERROR_NoCompatibleInterfaceFound;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
AOAInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
AOAInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
AOAInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
AOAInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
AOAInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
AOAInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataINPipe, 1)))
return AOA_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataOUTPipe, 1)))
return AOA_ENUMERROR_PipeConfigurationFailed;
AOAInterfaceInfo->State.IsActive = true;
AOAInterfaceInfo->State.InterfaceNumber = AOAInterface->InterfaceNumber;
return AOA_ENUMERROR_NoError;
}
static uint8_t DCOMP_AOA_Host_NextAndroidAccessoryInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == AOA_CSCP_AOADataClass) &&
(Interface->SubClass == AOA_CSCP_AOADataSubclass) &&
(Interface->Protocol == AOA_CSCP_AOADataProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_AOA_Host_NextInterfaceBulkEndpoint(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
if ((EndpointType == EP_TYPE_BULK) && (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
return DESCRIPTOR_SEARCH_Found;
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
void AOA_Host_USBTask(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
return;
#if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
AOA_Host_Flush(AOAInterfaceInfo);
#endif
}
uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
{
uint8_t ErrorCode;
uint16_t AccessoryProtocol;
if ((ErrorCode = AOA_Host_GetAccessoryProtocol(&AccessoryProtocol)) != HOST_WAITERROR_Successful)
return ErrorCode;
if ((AccessoryProtocol != CPU_TO_LE16(AOA_PROTOCOL_AccessoryV1)) && (AccessoryProtocol != CPU_TO_LE16(AOA_PROTOCOL_AccessoryV2)))
return AOA_ERROR_LOGICAL_CMD_FAILED;
for (uint8_t PropertyIndex = 0; PropertyIndex < AOA_STRING_TOTAL_STRINGS; PropertyIndex++)
{
if ((ErrorCode = AOA_Host_SendPropertyString(AOAInterfaceInfo, PropertyIndex)) != HOST_WAITERROR_Successful)
return ErrorCode;
}
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE),
.bRequest = AOA_REQ_StartAccessoryMode,
.wValue = 0,
.wIndex = 0,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(NULL);
}
static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE),
.bRequest = AOA_REQ_GetAccessoryProtocol,
.wValue = 0,
.wIndex = 0,
.wLength = sizeof(uint16_t),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(Protocol);
}
static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const uint8_t StringIndex)
{
const char* String = AOAInterfaceInfo->Config.PropertyStrings[StringIndex];
if (String == NULL)
String = "";
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE),
.bRequest = AOA_REQ_SendString,
.wValue = 0,
.wIndex = StringIndex,
.wLength = (strlen(String) + 1),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest((char*)String);
}
uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const void* const Buffer,
const uint16_t Length)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL);
Pipe_Freeze();
return ErrorCode;
}
uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const char* const String)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL);
Pipe_Freeze();
return ErrorCode;
}
uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const uint8_t Data)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_ClearOUT();
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
return ErrorCode;
}
Pipe_Write_8(Data);
Pipe_Freeze();
return PIPE_READYWAIT_NoError;
}
uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
return 0;
Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
if (!(Pipe_BytesInPipe()))
{
Pipe_ClearIN();
Pipe_Freeze();
return 0;
}
else
{
Pipe_Freeze();
return Pipe_BytesInPipe();
}
}
else
{
Pipe_Freeze();
return 0;
}
}
int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
return -1;
int16_t ReceivedByte = -1;
Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
if (Pipe_BytesInPipe())
ReceivedByte = Pipe_Read_8();
if (!(Pipe_BytesInPipe()))
Pipe_ClearIN();
}
Pipe_Freeze();
return ReceivedByte;
}
uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (!(Pipe_BytesInPipe()))
return PIPE_READYWAIT_NoError;
bool BankFull = !(Pipe_IsReadWriteAllowed());
Pipe_ClearOUT();
if (BankFull)
{
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
return ErrorCode;
Pipe_ClearOUT();
}
Pipe_Freeze();
return PIPE_READYWAIT_NoError;
}
#if defined(FDEV_SETUP_STREAM)
void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
FILE* const Stream)
{
*Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar, _FDEV_SETUP_RW);
fdev_set_udata(Stream, AOAInterfaceInfo);
}
void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
FILE* const Stream)
{
*Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar_Blocking, _FDEV_SETUP_RW);
fdev_set_udata(Stream, AOAInterfaceInfo);
}
static int AOA_Host_putchar(char c,
FILE* Stream)
{
return AOA_Host_SendByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
}
static int AOA_Host_getchar(FILE* Stream)
{
int16_t ReceivedByte = AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream));
if (ReceivedByte < 0)
return _FDEV_EOF;
return ReceivedByte;
}
static int AOA_Host_getchar_Blocking(FILE* Stream)
{
int16_t ReceivedByte;
while ((ReceivedByte = AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream))) < 0)
{
if (USB_HostState == HOST_STATE_Unattached)
return _FDEV_EOF;
AOA_Host_USBTask((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream));
USB_USBTask();
}
return ReceivedByte;
}
#endif
#endif

View file

@ -0,0 +1,314 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB Android Open Accessory Class driver.
*
* Host mode driver for the library USB Android Open Accessory Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassAOA
* \defgroup Group_USBClassAndroidAccessoryHost Android Open Accessory Class Host Mode Driver
*
* \section Sec_USBClassAndroidAccessoryHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassAndroidAccessoryHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the Android Open Accessory USB Class driver.
*
* @{
*/
#ifndef __AOA_CLASS_HOST_H__
#define __AOA_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/AndroidAccessoryClassCommon.h"
#include <stdio.h>
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_AOA_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Error code for some Android Open Accessory Host functions, indicating a logical (and not hardware) error. */
#define AOA_ERROR_LOGICAL_CMD_FAILED 0x80
/* Type Defines: */
/** \brief Android Open Accessory Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the Android Open Accessory class driver functions as the \c AOAInterfaceInfo
* parameter. This stores each Android Open Accessory interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
char* PropertyStrings[AOA_STRING_TOTAL_STRINGS]; /**< Android Accessory property strings, sent to identify the accessory when the
* Android device is switched into Open Accessory mode. */
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref AOA_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the AOA interface within the attached device. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_AOA_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref AOA_Host_ConfigurePipes() function. */
enum AOA_Host_EnumerationFailure_ErrorCodes_t
{
AOA_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
AOA_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
AOA_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Android Open Accessory interface was not found in the device's Configuration Descriptor. */
AOA_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** General management task for a given Android Open Accessory host 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] AOAInterfaceInfo Pointer to a structure containing an Android Open Accessory Class host configuration and state.
*/
void AOA_Host_USBTask(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Validates a device descriptor, to check if the device is a valid Android device, and if it is currently in Android Open Accessory mode.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing an AOA Class host configuration and state.
* \param[in] DeviceDescriptor Pointer a buffer containing the attached device's Device Descriptor.
* \param[out] NeedModeSwitch Pointer to a boolean where the mode switch requirement of the attached device is to be stored.
*
* \return Boolean \c true if the attached device is a valid Android device, \c false otherwise.
*/
bool AOA_Host_ValidateAccessoryDevice(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const USB_Descriptor_Device_t* const DeviceDescriptor,
bool* const NeedModeSwitch) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
/** Host interface configuration routine, to configure a given Android Open Accessory host interface instance using the Configuration
* Descriptor read from an attached USB device. This function automatically updates the given Android Open Accessory Host instance's
* state values and configures the pipes required to communicate with the interface if it is found within the device. This should be
* called once after the stack has enumerated the attached device, while the host state machine is in the Addressed state.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing an AOA Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref AOA_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t AOA_Host_ConfigurePipes(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Starts Accessory Mode in the attached Android device. This function will validate the device's Android Open Accessory protocol
* version, send the configured property strings, and request a switch to Android Open Accessory mode.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing an AOA Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum, or \ref AOA_ERROR_LOGICAL_CMD_FAILED if a logical error occurred..
*/
uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a given data buffer to the attached USB device, if connected. If a device is not connected when the function is
* called, the data will be discarded. Bytes will be queued for transmission to the device until either the pipe bank
* becomes full, or the \ref AOA_Host_Flush() function is called to flush the pending data to the device. This allows for
* multiple bytes to be packed into a single pipe packet, increasing data throughput.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
* \param[in] Buffer Pointer to a buffer containing the data to send to the device.
* \param[in] Length Length of the data to send to the device.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const void* const Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a given null-terminated string to the attached USB device, if connected. If a device is not connected when the
* function is called, the string is discarded. Bytes will be queued for transmission to the device until either the pipe
* bank becomes full, or the \ref AOA_Host_Flush() function is called to flush the pending data to the device. This allows
* for multiple bytes to be packed into a single pipe packet, increasing data throughput.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
* \param[in] String Pointer to the null terminated string to send to the device.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
* byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
* \ref AOA_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
* packed into a single pipe packet, increasing data throughput.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
* \param[in] Data Byte of data to send to the device.
*
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
/** Determines the number of bytes received by the AOA interface from the device, waiting to be read. This indicates the number
* of bytes in the IN pipe bank only, and thus the number of calls to \ref AOA_Host_ReceiveByte() which are guaranteed to succeed
* immediately. If multiple bytes are to be received, they should be buffered by the user application, as the pipe bank will not be
* released back to the USB controller until all bytes are read.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
*
* \return Total number of buffered bytes received from the device.
*/
uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
* returns a negative value. The \ref AOA_Host_BytesReceived() function may be queried in advance to determine how many bytes
* are currently buffered in the AOA interface's data receive pipe.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
*
* \return Next received byte from the device, or a negative value if no data received.
*/
int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
*
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Creates a standard character stream for the given AOA Device instance so that it can be used with all the regular
* functions in the standard \c <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c 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 \c getc()) or when the user application will implement its own
* line buffering.
*
* \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
* to the given AOA interface.
* \n\n
*
* \note This function is not available on all microcontroller architectures.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class configuration and state.
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
*/
void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Identical to \ref AOA_Host_CreateStream(), except that reads are blocking until the calling stream function terminates
* the transfer. While blocking, the USB and AOA service tasks are called repeatedly to maintain USB communications.
*
* \note This function is not available on all microcontroller architectures.
*
* \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class configuration and state.
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
*/
void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_ANDROIDACCESSORY_HOST_C)
#if defined(FDEV_SETUP_STREAM)
static int AOA_Host_putchar(char c,
FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
static int AOA_Host_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
static int AOA_Host_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
#endif
static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol) ATTR_NON_NULL_PTR_ARG(1);
static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
const uint8_t StringIndex) ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_AOA_Host_NextAndroidAccessoryInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_AOA_Host_NextInterfaceBulkEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,223 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_AUDIO_DRIVER
#define __INCLUDE_FROM_AUDIO_HOST_C
#include "AudioClassHost.h"
uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Interface_t* AudioControlInterface = NULL;
USB_Descriptor_Interface_t* AudioStreamingInterface = NULL;
memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return AUDIO_ENUMERROR_InvalidConfigDescriptor;
while ((AudioInterfaceInfo->Config.DataINPipe.Address && !(DataINEndpoint)) ||
(AudioInterfaceInfo->Config.DataOUTPipe.Address && !(DataOUTEndpoint)))
{
if (!(AudioControlInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (!(AudioControlInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_Audio_Host_NextAudioControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return AUDIO_ENUMERROR_NoCompatibleInterfaceFound;
}
AudioControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return AUDIO_ENUMERROR_NoCompatibleInterfaceFound;
}
}
AudioStreamingInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
AudioInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
AudioInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
AudioInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_ISOCHRONOUS;
AudioInterfaceInfo->Config.DataINPipe.Banks = 2;
AudioInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
AudioInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
AudioInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_ISOCHRONOUS;
AudioInterfaceInfo->Config.DataOUTPipe.Banks = 2;
if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataINPipe, 1)))
return AUDIO_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataOUTPipe, 1)))
return AUDIO_ENUMERROR_PipeConfigurationFailed;
AudioInterfaceInfo->State.ControlInterfaceNumber = AudioControlInterface->InterfaceNumber;
AudioInterfaceInfo->State.StreamingInterfaceNumber = AudioStreamingInterface->InterfaceNumber;
AudioInterfaceInfo->State.EnabledStreamingAltIndex = AudioStreamingInterface->AlternateSetting;
AudioInterfaceInfo->State.IsActive = true;
return AUDIO_ENUMERROR_NoError;
}
static uint8_t DCOMP_Audio_Host_NextAudioControlInterface(void* CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
(Interface->SubClass == AUDIO_CSCP_ControlSubclass) &&
(Interface->Protocol == AUDIO_CSCP_ControlProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_Audio_Host_NextAudioStreamInterface(void* CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
(Interface->SubClass == AUDIO_CSCP_AudioStreamingSubclass) &&
(Interface->Protocol == AUDIO_CSCP_StreamingProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint(void* CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
if ((Endpoint->Attributes & EP_TYPE_MASK) == EP_TYPE_ISOCHRONOUS)
return DESCRIPTOR_SEARCH_Found;
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
uint8_t Audio_Host_StartStopStreaming(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const bool EnableStreaming)
{
if (!(AudioInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
return USB_Host_SetInterfaceAltSetting(AudioInterfaceInfo->State.StreamingInterfaceNumber,
EnableStreaming ? AudioInterfaceInfo->State.EnabledStreamingAltIndex : 0);
}
uint8_t Audio_Host_GetSetEndpointProperty(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const uint8_t DataPipeIndex,
const uint8_t EndpointProperty,
const uint8_t EndpointControl,
const uint16_t DataLength,
void* const Data)
{
if (!(AudioInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t RequestType;
uint8_t EndpointAddress;
if (EndpointProperty & 0x80)
RequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT);
else
RequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT);
Pipe_SelectPipe(DataPipeIndex);
EndpointAddress = Pipe_GetBoundEndpointAddress();
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = RequestType,
.bRequest = EndpointProperty,
.wValue = ((uint16_t)EndpointControl << 8),
.wIndex = EndpointAddress,
.wLength = DataLength,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(Data);
}
#endif

View file

@ -0,0 +1,411 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB Audio 1.0 Class driver.
*
* Host mode driver for the library USB Audio 1.0 Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassAudio
* \defgroup Group_USBClassAudioHost Audio 1.0 Class Host Mode Driver
*
* \section Sec_USBClassAudioHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/AudioClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassAudioHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the Audio 1.0 USB Class driver.
*
* @{
*/
#ifndef __AUDIO_CLASS_HOST_H__
#define __AUDIO_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/AudioClassCommon.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/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Type Defines: */
/** \brief Audio Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the Audio class driver functions as the \c AudioInterfaceInfo parameter. This
* stores each Audio interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref Audio_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t ControlInterfaceNumber; /**< Interface index of the Audio Control interface within the attached device. */
uint8_t StreamingInterfaceNumber; /**< Interface index of the Audio Streaming interface within the attached device. */
uint8_t EnabledStreamingAltIndex; /**< Alternative setting index of the Audio Streaming interface when the stream is enabled. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_Audio_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref Audio_Host_ConfigurePipes() function. */
enum AUDIO_Host_EnumerationFailure_ErrorCodes_t
{
AUDIO_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
AUDIO_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
AUDIO_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible AUDIO interface was not found in the device's Configuration Descriptor. */
AUDIO_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** Host interface configuration routine, to configure a given Audio host interface instance using the Configuration
* Descriptor read from an attached USB device. This function automatically updates the given Audio Host instance's
* state values and configures the pipes required to communicate with the interface if it is found within the
* device. This should be called once after the stack has enumerated the attached device, while the host state
* machine is in the Addressed state.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref AUDIO_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Starts or stops the audio streaming for the given configured Audio Host interface, allowing for audio samples to be
* send and/or received.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class host configuration and state.
* \param[in] EnableStreaming Boolean true to enable streaming of the specified interface, \c false to disable
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t Audio_Host_StartStopStreaming(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const bool EnableStreaming) ATTR_NON_NULL_PTR_ARG(1);
/** Gets or sets the specified property of a streaming audio class endpoint that is bound to a pipe in the given
* class instance.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class host configuration and state.
* \param[in] DataPipeIndex Index of the data pipe whose bound endpoint is to be altered.
* \param[in] EndpointProperty Property of the endpoint to get or set, a value from \ref Audio_ClassRequests_t.
* \param[in] EndpointControl Parameter of the endpoint to get or set, a value from \ref Audio_EndpointControls_t.
* \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
* length of the retrieved data.
* \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
* the retrieved data is to be stored for GET operations.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t Audio_Host_GetSetEndpointProperty(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const uint8_t DataPipeIndex,
const uint8_t EndpointProperty,
const uint8_t EndpointControl,
const uint16_t DataLength,
void* const Data) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
/* Inline Functions: */
/** General management task for a given Audio host 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 host configuration and state.
*/
static inline void Audio_Host_USBTask(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void Audio_Host_USBTask(USB_ClassInfo_Audio_Host_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
* IN pipe ready for reading.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_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 \c true if the given Audio interface has a sample to be read, \c false otherwise.
*/
static inline bool Audio_Host_IsSampleReceived(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline bool Audio_Host_IsSampleReceived(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AudioInterfaceInfo->State.IsActive))
return false;
bool SampleReceived = false;
Pipe_SelectPipe(AudioInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
SampleReceived = Pipe_IsINReceived();
Pipe_Freeze();
return SampleReceived;
}
/** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects
* the streaming OUT pipe ready for writing.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_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 \c true if the given Audio interface is ready to accept the next sample, \c false otherwise.
*/
static inline bool Audio_Host_IsReadyForNextSample(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline bool Audio_Host_IsReadyForNextSample(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(AudioInterfaceInfo->State.IsActive))
return false;
Pipe_SelectPipe(AudioInterfaceInfo->Config.DataOUTPipe.Address);
return Pipe_IsOUTReady();
}
/** Reads the next 8-bit audio sample from the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Host_IsSampleReceived() function to ensure
* that the correct pipe 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_Host_ReadSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline int8_t Audio_Host_ReadSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
{
int8_t Sample;
(void)AudioInterfaceInfo;
Sample = Pipe_Read_8();
if (!(Pipe_BytesInPipe()))
{
Pipe_Unfreeze();
Pipe_ClearIN();
Pipe_Freeze();
}
return Sample;
}
/** Reads the next 16-bit audio sample from the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Host_IsSampleReceived() function to ensure
* that the correct pipe 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_Host_ReadSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline int16_t Audio_Host_ReadSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
{
int16_t Sample;
(void)AudioInterfaceInfo;
Sample = (int16_t)Pipe_Read_16_LE();
if (!(Pipe_BytesInPipe()))
{
Pipe_Unfreeze();
Pipe_ClearIN();
Pipe_Freeze();
}
return Sample;
}
/** Reads the next 24-bit audio sample from the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Host_IsSampleReceived() function to ensure
* that the correct pipe 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_Host_ReadSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline int32_t Audio_Host_ReadSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
{
int32_t Sample;
(void)AudioInterfaceInfo;
Sample = (((uint32_t)Pipe_Read_8() << 16) | Pipe_Read_16_LE());
if (!(Pipe_BytesInPipe()))
{
Pipe_Unfreeze();
Pipe_ClearIN();
Pipe_Freeze();
}
return Sample;
}
/** Writes the next 8-bit audio sample to the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Host_IsReadyForNextSample() function to
* ensure that the correct pipe 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_Host_WriteSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const int8_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void Audio_Host_WriteSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const int8_t Sample)
{
(void)AudioInterfaceInfo;
Pipe_Write_8(Sample);
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_Unfreeze();
Pipe_ClearOUT();
Pipe_WaitUntilReady();
Pipe_Freeze();
}
}
/** Writes the next 16-bit audio sample to the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Host_IsReadyForNextSample() function to
* ensure that the correct pipe 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_Host_WriteSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const int16_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void Audio_Host_WriteSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const int16_t Sample)
{
(void)AudioInterfaceInfo;
Pipe_Write_16_LE(Sample);
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_Unfreeze();
Pipe_ClearOUT();
Pipe_WaitUntilReady();
Pipe_Freeze();
}
}
/** Writes the next 24-bit audio sample to the current audio interface.
*
* \pre This should be preceded immediately by a call to the \ref Audio_Host_IsReadyForNextSample() function to
* ensure that the correct pipe 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_Host_WriteSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const int32_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void Audio_Host_WriteSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
const int32_t Sample)
{
(void)AudioInterfaceInfo;
Pipe_Write_16_LE(Sample);
Pipe_Write_8(Sample >> 16);
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_Unfreeze();
Pipe_ClearOUT();
Pipe_WaitUntilReady();
Pipe_Freeze();
}
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_AUDIO_HOST_C)
static uint8_t DCOMP_Audio_Host_NextAudioControlInterface(void* CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_Audio_Host_NextAudioStreamInterface(void* CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint(void* CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,477 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_CDC_DRIVER
#define __INCLUDE_FROM_CDC_HOST_C
#include "CDCClassHost.h"
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
USB_Descriptor_Interface_t* CDCControlInterface = NULL;
memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return CDC_ENUMERROR_InvalidConfigDescriptor;
while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
{
if (!(CDCControlInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (NotificationEndpoint)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return CDC_ENUMERROR_NoCompatibleInterfaceFound;
}
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
}
else
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return CDC_ENUMERROR_NoCompatibleInterfaceFound;
}
CDCControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
NotificationEndpoint = NULL;
}
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
{
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
NotificationEndpoint = EndpointData;
else
DataINEndpoint = EndpointData;
}
else
{
DataOUTEndpoint = EndpointData;
}
}
CDCInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
CDCInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
CDCInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
CDCInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
CDCInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
CDCInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
CDCInterfaceInfo->Config.NotificationPipe.Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
CDCInterfaceInfo->Config.NotificationPipe.EndpointAddress = NotificationEndpoint->EndpointAddress;
CDCInterfaceInfo->Config.NotificationPipe.Type = EP_TYPE_INTERRUPT;
if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataINPipe, 1)))
return CDC_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataOUTPipe, 1)))
return CDC_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.NotificationPipe, 1)))
return CDC_ENUMERROR_PipeConfigurationFailed;
CDCInterfaceInfo->State.ControlInterfaceNumber = CDCControlInterface->InterfaceNumber;
CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR);
CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR);
CDCInterfaceInfo->State.IsActive = true;
return CDC_ENUMERROR_NoError;
}
static uint8_t DCOMP_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == CDC_CSCP_CDCClass) &&
(Interface->SubClass == CDC_CSCP_ACMSubclass) &&
(Interface->Protocol == CDC_CSCP_ATCommandProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
(Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
(Interface->Protocol == CDC_CSCP_NoDataProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
{
return DESCRIPTOR_SEARCH_Found;
}
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return;
Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
USB_Request_Header_t Notification;
Pipe_Read_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
if ((Notification.bRequest == CDC_NOTIF_SerialState) &&
(Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)))
{
Pipe_Read_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
NULL);
Pipe_ClearIN();
EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
}
else
{
Pipe_ClearIN();
}
}
Pipe_Freeze();
#if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
CDC_Host_Flush(CDCInterfaceInfo);
#endif
}
uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = CDC_REQ_SetLineEncoding,
.wValue = 0,
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
.wLength = sizeof(CDCInterfaceInfo->State.LineEncoding),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(&CDCInterfaceInfo->State.LineEncoding);
}
uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = CDC_REQ_SetControlLineState,
.wValue = CDCInterfaceInfo->State.ControlLineStates.HostToDevice,
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(NULL);
}
uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const uint8_t Duration)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = CDC_REQ_SendBreak,
.wValue = Duration,
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(NULL);
}
uint8_t CDC_Host_SendData(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const void* const Buffer,
const uint16_t Length)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL);
Pipe_Freeze();
return ErrorCode;
}
uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const char* const String)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL);
Pipe_Freeze();
return ErrorCode;
}
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const uint8_t Data)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_ClearOUT();
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
return ErrorCode;
}
Pipe_Write_8(Data);
Pipe_Freeze();
return PIPE_READYWAIT_NoError;
}
uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return 0;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
if (!(Pipe_BytesInPipe()))
{
Pipe_ClearIN();
Pipe_Freeze();
return 0;
}
else
{
Pipe_Freeze();
return Pipe_BytesInPipe();
}
}
else
{
Pipe_Freeze();
return 0;
}
}
int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return -1;
int16_t ReceivedByte = -1;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
if (Pipe_BytesInPipe())
ReceivedByte = Pipe_Read_8();
if (!(Pipe_BytesInPipe()))
Pipe_ClearIN();
}
Pipe_Freeze();
return ReceivedByte;
}
uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (!(Pipe_BytesInPipe()))
return PIPE_READYWAIT_NoError;
bool BankFull = !(Pipe_IsReadWriteAllowed());
Pipe_ClearOUT();
if (BankFull)
{
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
return ErrorCode;
Pipe_ClearOUT();
}
Pipe_Freeze();
return PIPE_READYWAIT_NoError;
}
#if defined(FDEV_SETUP_STREAM)
void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
FILE* const Stream)
{
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar, _FDEV_SETUP_RW);
fdev_set_udata(Stream, CDCInterfaceInfo);
}
void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
FILE* const Stream)
{
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar_Blocking, _FDEV_SETUP_RW);
fdev_set_udata(Stream, CDCInterfaceInfo);
}
static int CDC_Host_putchar(char c,
FILE* Stream)
{
return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
}
static int CDC_Host_getchar(FILE* Stream)
{
int16_t ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
if (ReceivedByte < 0)
return _FDEV_EOF;
return ReceivedByte;
}
static int CDC_Host_getchar_Blocking(FILE* Stream)
{
int16_t ReceivedByte;
while ((ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))) < 0)
{
if (USB_HostState == HOST_STATE_Unattached)
return _FDEV_EOF;
CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
USB_USBTask();
}
return ReceivedByte;
}
#endif
void CDC_Host_Event_Stub(void)
{
}
#endif

View file

@ -0,0 +1,351 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB CDC Class driver.
*
* Host 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassCDC
* \defgroup Group_USBClassCDCHost CDC Class Host Mode Driver
*
* \section Sec_USBClassCDCHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/CDCClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassCDCHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the CDC USB Class driver.
*
* @{
*/
#ifndef __CDC_CLASS_HOST_H__
#define __CDC_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/CDCClassCommon.h"
#include <stdio.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/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Type Defines: */
/** \brief CDC Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the CDC class driver functions as the \c CDCInterfaceInfo parameter. This
* stores each CDC interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
USB_Pipe_Table_t NotificationPipe; /**< Notification IN Pipe configuration table. */
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref CDC_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t ControlInterfaceNumber; /**< Interface index of the CDC-ACM control interface within the attached device. */
struct
{
uint16_t HostToDevice; /**< Control line states from the host to device, as a set of \c CDC_CONTROL_LINE_OUT_*
* masks - to notify the device of changes to these values, call the
* \ref CDC_Host_SendControlLineStateChange() function.
*/
uint16_t DeviceToHost; /**< Control line states from the device to host, as a set of \c CDC_CONTROL_LINE_IN_*
* masks. This value is updated each time \ref CDC_Host_USBTask() is called.
*/
} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
CDC_LineEncoding_t 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. When set by the host application, the
* \ref CDC_Host_SetLineEncoding() function must be called to push the changes
* to the device.
*/
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_CDC_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref CDC_Host_ConfigurePipes() function. */
enum CDC_Host_EnumerationFailure_ErrorCodes_t
{
CDC_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
CDC_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
CDC_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible CDC interface was not found in the device's Configuration Descriptor. */
CDC_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** General management task for a given CDC host 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 an CDC Class host configuration and state.
*/
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Host interface configuration routine, to configure a given CDC host interface instance using the Configuration
* Descriptor read from an attached USB device. This function automatically updates the given CDC Host instance's
* state values and configures the pipes required to communicate with the interface if it is found within the device.
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
* the Addressed state.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref CDC_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Sets the line encoding for the attached device's virtual serial port. This should be called when the \c LineEncoding
* values of the interface have been changed to push the new settings to the USB device.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a Serial Control Line State Change notification to the device. This should be called when the virtual serial
* control lines (DTR, RTS, etc.) have changed states. Line states persist until they are cleared via a second
* notification. This should be called each time the CDC class driver's \c ControlLineStates.HostToDevice value is updated
* to push the new states to the USB device.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a Send Break request to the device. This is generally used to separate data or to indicate a special condition
* to the receiving device.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
* \param[in] Duration Duration of the break, in milliseconds.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a given data buffer to the attached USB device, if connected. If a device is not connected when the function is
* called, the data will be discarded. Bytes will be queued for transmission to the device until either the pipe bank
* becomes full, or the \ref CDC_Host_Flush() function is called to flush the pending data to the device. This allows for
* multiple bytes to be packed into a single pipe packet, increasing data throughput.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
* \param[in] Buffer Pointer to a buffer containing the data to send to the device.
* \param[in] Length Length of the data to send to the device.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t CDC_Host_SendData(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const void* const Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a given null-terminated string to the attached USB device, if connected. If a device is not connected when the
* function is called, the string is discarded. Bytes will be queued for transmission to the device until either the pipe
* bank becomes full, or the \ref CDC_Host_Flush() function is called to flush the pending data to the device. This allows
* for multiple bytes to be packed into a single pipe packet, increasing data throughput.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
* \param[in] String Pointer to the null terminated string to send to the device.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
* byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
* \ref CDC_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
* packed into a single pipe packet, increasing data throughput.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
* \param[in] Data Byte of data to send to the device.
*
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_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 device, waiting to be read. This indicates the number
* of bytes in the IN pipe bank only, and thus the number of calls to \ref CDC_Host_ReceiveByte() which are guaranteed to succeed
* immediately. If multiple bytes are to be received, they should be buffered by the user application, as the pipe bank will not be
* released back to the USB controller until all bytes are read.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
*
* \return Total number of buffered bytes received from the device.
*/
uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
* returns a negative value. The \ref CDC_Host_BytesReceived() function may be queried in advance to determine how many bytes
* are currently buffered in the CDC interface's data receive pipe.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
*
* \return Next received byte from the device, or a negative value if no data received.
*/
int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
*
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
#if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__)
/** Creates a standard character stream for the given CDC Device instance so that it can be used with all the regular
* functions in the standard \c <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c 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 \c getc()) or when the user application will implement its own
* line buffering.
*
* \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
* to the given CDC interface.
* \n\n
*
* \note This function is not available on all microcontroller architectures.
*
* \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_Host_CreateStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Identical to \ref CDC_Host_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.
*
* \note This function is not available on all microcontroller architectures.
*
* \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_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
#endif
/** CDC class driver event for a control line state change on a CDC host interface. This event fires each time the device notifies
* the host of a control line state change (containing the virtual serial control line states, such as DCD) 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 \c ControlLineStates.DeviceToHost value inside the CDC host interface structure passed as a parameter, set as
* a mask of \c CDC_CONTROL_LINE_IN_* masks.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
*/
void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_CDC_HOST_C)
#if defined(FDEV_SETUP_STREAM)
static int CDC_Host_putchar(char c,
FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
static int CDC_Host_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
static int CDC_Host_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
#endif
void CDC_Host_Event_Stub(void) ATTR_CONST;
void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Host_Event_Stub);
static uint8_t DCOMP_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,399 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_HID_DRIVER
#define __INCLUDE_FROM_HID_HOST_C
#include "HIDClassHost.h"
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Interface_t* HIDInterface = NULL;
USB_HID_Descriptor_HID_t* HIDDescriptor = NULL;
memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return HID_ENUMERROR_InvalidConfigDescriptor;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
if (!(HIDInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (DataINEndpoint)
break;
do
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return HID_ENUMERROR_NoCompatibleInterfaceFound;
}
HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
} while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
(HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDDescriptor) != DESCRIPTOR_SEARCH_COMP_Found)
{
return HID_ENUMERROR_NoCompatibleInterfaceFound;
}
HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t);
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
HIDInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
HIDInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
HIDInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_INTERRUPT;
if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataINPipe, 1)))
return HID_ENUMERROR_PipeConfigurationFailed;
if (DataOUTEndpoint)
{
HIDInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
HIDInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
HIDInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_INTERRUPT;
if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataOUTPipe, 1)))
return HID_ENUMERROR_PipeConfigurationFailed;
}
HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber;
HIDInterfaceInfo->State.HIDReportSize = LE16_TO_CPU(HIDDescriptor->HIDReportLength);
HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol);
HIDInterfaceInfo->State.LargestReportSize = 8;
HIDInterfaceInfo->State.IsActive = true;
return HID_ENUMERROR_NoError;
}
static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if (Interface->Class == HID_CSCP_HIDClass)
return DESCRIPTOR_SEARCH_Found;
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == HID_DTYPE_HID)
return DESCRIPTOR_SEARCH_Found;
else if (Header->Type == DTYPE_Interface)
return DESCRIPTOR_SEARCH_Fail;
else
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
return DESCRIPTOR_SEARCH_Found;
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
const uint8_t ReportID,
void* Buffer)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = HID_REQ_SetReport,
.wValue = ((HID_REPORT_ITEM_In + 1) << 8) | ReportID,
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
.wLength = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(Buffer);
}
#endif
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
void* Buffer)
{
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
uint16_t ReportSize;
uint8_t* BufferPos = Buffer;
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
if (!(HIDInterfaceInfo->State.UsingBootProtocol))
{
uint8_t ReportID = 0;
if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
{
ReportID = Pipe_Read_8();
*(BufferPos++) = ReportID;
}
ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
}
else
#endif
{
ReportSize = Pipe_BytesInPipe();
}
if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
Pipe_ClearIN();
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
const uint8_t ReportID,
#endif
const uint8_t ReportType,
void* Buffer,
const uint16_t ReportSize)
{
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_NoError;
if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
{
uint8_t ErrorCode;
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (ReportID)
Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NULL);
if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
Pipe_ClearOUT();
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
else
#endif
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = HID_REQ_SetReport,
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
.wValue = ((ReportType + 1) << 8) | ReportID,
#else
.wValue = ((ReportType + 1) << 8),
#endif
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
.wLength = ReportSize,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(Buffer);
}
}
bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
return false;
bool ReportReceived;
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
ReportReceived = Pipe_IsINReceived();
Pipe_Freeze();
return ReportReceived;
}
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
{
uint8_t ErrorCode;
if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
return HID_ERROR_LOGICAL;
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = HID_REQ_SetProtocol,
.wValue = 0,
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
HIDInterfaceInfo->State.LargestReportSize = 8;
HIDInterfaceInfo->State.UsingBootProtocol = true;
return HOST_SENDCONTROL_Successful;
}
uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
const uint16_t MS)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = HID_REQ_SetIdle,
.wValue = ((MS << 6) & 0xFF00),
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(NULL);
}
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
{
uint8_t ErrorCode;
uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
.bRequest = REQ_GetDescriptor,
.wValue = (HID_DTYPE_Report << 8),
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
.wLength = HIDInterfaceInfo->State.HIDReportSize,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
if (HIDInterfaceInfo->State.UsingBootProtocol)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = HID_REQ_SetProtocol,
.wValue = 1,
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
.wLength = 0,
};
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
HIDInterfaceInfo->State.UsingBootProtocol = false;
}
if (HIDInterfaceInfo->Config.HIDParserData == NULL)
return HID_ERROR_LOGICAL;
if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
{
return HID_ERROR_LOGICAL | ErrorCode;
}
uint16_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
return 0;
}
#endif
#endif

View file

@ -0,0 +1,313 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB HID Class driver.
*
* Host 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassHID
* \defgroup Group_USBClassHIDHost HID Class Host Mode Driver
*
* \section Sec_USBClassHIDHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/HIDClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassHIDHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the HID USB Class driver.
*
* @{
*/
#ifndef __HID_CLASS_HOST_H__
#define __HID_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/HIDClassCommon.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/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Error code for some HID Host functions, indicating a logical (and not hardware) error. */
#define HID_ERROR_LOGICAL 0x80
/* Type Defines: */
/** \brief HID Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the HID class driver functions as the \c HIDInterfaceInfo parameter. This
* stores each HID interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
uint8_t HIDInterfaceProtocol; /**< HID interface protocol value to match against if a specific
* boot subclass protocol is required, a protocol value from the
* \ref HID_Descriptor_ClassSubclassProtocol_t enum.
*/
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
HID_ReportInfo_t* HIDParserData; /**< HID parser data to store the parsed HID report data, when boot protocol
* is not used.
*
* \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined,
* this field is unavailable.
*/
#endif
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref HID_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the HID interface within the attached device. */
bool SupportsBootProtocol; /**< Indicates if the current interface instance supports the HID Boot
* Protocol when enabled via \ref HID_Host_SetBootProtocol().
*/
bool DeviceUsesOUTPipe; /**< Indicates if the current interface instance uses a separate OUT data pipe for
* OUT reports, or if OUT reports are sent via the control pipe instead.
*/
bool UsingBootProtocol; /**< Indicates that the interface is currently initialized in Boot Protocol mode */
uint16_t HIDReportSize; /**< Size in bytes of the HID report descriptor in the device. */
uint8_t LargestReportSize; /**< Largest report the device will send, in bytes. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_HID_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref HID_Host_ConfigurePipes() function. */
enum HID_Host_EnumerationFailure_ErrorCodes_t
{
HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
HID_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
HID_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor. */
HID_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** Host interface configuration routine, to configure a given HID host interface instance using the Configuration
* Descriptor read from an attached USB device. This function automatically updates the given HID Host instance's
* state values and configures the pipes required to communicate with the interface if it is found within the
* device. This should be called once after the stack has enumerated the attached device, while the host state
* machine is in the Addressed state.
*
* \attention Once the device pipes are configured, the HID device's reporting protocol <b>must</b> be set via a call
* to either the \ref HID_Host_SetBootProtocol() or \ref HID_Host_SetReportProtocol() function.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref HID_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Receives a HID IN report from the attached HID device, when a report has been received on the HID IN Data pipe.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \attention The destination buffer should be large enough to accommodate the largest report that the attached device
* can generate.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
* \param[in] Buffer Buffer to store the received report into.
*
* \return An error code from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
void* Buffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
/** Receives a HID IN report from the attached device, by the report ID.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
* \param[in] ReportID Report ID of the received report if ControlRequest is false, set by the to the Report ID to fetch.
* \param[in] Buffer Buffer to store the received report into.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
const uint8_t ReportID,
void* Buffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
#endif
/** Sends an OUT or FEATURE report to the currently attached HID device, using the device's OUT pipe if available,
* or the device's Control pipe if not.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, the ReportID parameter is removed
* from the parameter list of this function.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
* \param[in] ReportID Report ID of the report to send to the device, or 0 if the device does not use report IDs.
* \param[in] ReportType Type of report to issue to the device, either \ref HID_REPORT_ITEM_Out or \ref HID_REPORT_ITEM_Feature.
* \param[in] Buffer Buffer containing the report to send to the attached device.
* \param[in] ReportSize Report size in bytes to send to the attached device.
*
* \return An error code from the \ref USB_Host_SendControlErrorCodes_t enum if the DeviceUsesOUTPipe flag is set in
* the interface's state structure, a value from the \ref Pipe_Stream_RW_ErrorCodes_t enum otherwise.
*/
uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
const uint8_t ReportID,
#endif
const uint8_t ReportType,
void* Buffer,
const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1)
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
ATTR_NON_NULL_PTR_ARG(4);
#else
ATTR_NON_NULL_PTR_ARG(3);
#endif
/** Determines if a HID IN report has been received from the attached device on the data IN pipe.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
*
* \return Boolean \c true if a report has been received, \c false otherwise.
*/
bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Switches the attached HID device's reporting protocol over to the Boot Report protocol mode, on supported devices.
*
* \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method must still be called
* to explicitly place the attached device into boot protocol mode before use.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
*
* \return \ref HID_ERROR_LOGICAL if the device does not support Boot Protocol mode, a value from the
* \ref USB_Host_SendControlErrorCodes_t enum otherwise.
*/
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sets the idle period for the attached HID device to the specified interval. The HID idle period determines the rate
* at which the device should send a report, when no state changes have occurred; i.e. on HID keyboards, this sets the
* hardware key repeat interval.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
* \param[in] MS Idle period as a multiple of four milliseconds, zero to disable hardware repeats
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
const uint16_t MS) ATTR_NON_NULL_PTR_ARG(1);
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
/** Switches the attached HID device's reporting protocol over to the standard Report protocol mode. This also retrieves
* and parses the device's HID report descriptor, so that the size of each report can be determined in advance.
*
* \attention Whether this function is used or not, the \ref CALLBACK_HIDParser_FilterHIDReportItem() callback from the HID
* Report Parser this function references <b>must</b> be implemented in the user code.
*
* \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum if an error occurs while retrieving the HID
* Report descriptor or the setting of the Report protocol, \ref HID_ERROR_LOGICAL if the HID interface does
* not have a valid \ref HID_ReportInfo_t structure set in its configuration, a mask of \ref HID_ERROR_LOGICAL
* and a value from the \ref HID_Parse_ErrorCodes_t otherwise.
*/
uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
#endif
/* Inline Functions: */
/** General management task for a given Human Interface Class host 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 host configuration and state.
*/
static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
{
(void)HIDInterfaceInfo;
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_HID_HOST_C)
static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,231 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_MIDI_DRIVER
#define __INCLUDE_FROM_MIDI_HOST_C
#include "MIDIClassHost.h"
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Interface_t* MIDIInterface = NULL;
memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return MIDI_ENUMERROR_InvalidConfigDescriptor;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
if (!(MIDIInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return MIDI_ENUMERROR_NoCompatibleInterfaceFound;
}
MIDIInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
MIDIInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
MIDIInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
MIDIInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
MIDIInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
MIDIInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
MIDIInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
if (!(Pipe_ConfigurePipeTable(&MIDIInterfaceInfo->Config.DataINPipe, 1)))
return MIDI_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&MIDIInterfaceInfo->Config.DataOUTPipe, 1)))
return MIDI_ENUMERROR_PipeConfigurationFailed;
MIDIInterfaceInfo->State.InterfaceNumber = MIDIInterface->InterfaceNumber;
MIDIInterfaceInfo->State.IsActive = true;
return MIDI_ENUMERROR_NoError;
}
static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
(Interface->SubClass == AUDIO_CSCP_MIDIStreamingSubclass) &&
(Interface->Protocol == AUDIO_CSCP_StreamingProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
if ((EndpointType == EP_TYPE_BULK) && !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
return DESCRIPTOR_SEARCH_Found;
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
return;
#if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
MIDI_Host_Flush(MIDIInterfaceInfo);
#endif
}
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (Pipe_BytesInPipe())
{
Pipe_ClearOUT();
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
{
Pipe_Freeze();
return ErrorCode;
}
}
Pipe_Freeze();
return PIPE_READYWAIT_NoError;
}
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
MIDI_EventPacket_t* const Event)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != PIPE_RWSTREAM_NoError)
{
Pipe_Freeze();
return ErrorCode;
}
if (!(Pipe_IsReadWriteAllowed()))
Pipe_ClearOUT();
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
MIDI_EventPacket_t* const Event)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
bool DataReady = false;
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
if (Pipe_BytesInPipe())
{
Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL);
DataReady = true;
}
if (!(Pipe_BytesInPipe()))
Pipe_ClearIN();
}
Pipe_Freeze();
return DataReady;
}
#endif

View file

@ -0,0 +1,190 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB MIDI Class driver.
*
* Host 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassMIDI
* \defgroup Group_USBClassMIDIHost MIDI Class Host Mode Driver
*
* \section Sec_USBClassMIDIHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/MIDIClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassMIDIHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the MIDI USB Class driver.
*
* @{
*/
#ifndef __MIDI_CLASS_HOST_H__
#define __MIDI_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/MIDIClassCommon.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/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Type Defines: */
/** \brief MIDI Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the MIDI class driver functions as the \c MIDIInterfaceInfo parameter. This
* stores each MIDI interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the MIDI interface within the attached device. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_MIDI_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref MIDI_Host_ConfigurePipes() function. */
enum MIDI_Host_EnumerationFailure_ErrorCodes_t
{
MIDI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
MIDI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
MIDI_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible MIDI interface was not found in the device's Configuration Descriptor. */
MIDI_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** Host interface configuration routine, to configure a given MIDI host interface instance using the Configuration
* Descriptor read from an attached USB device. This function automatically updates the given MIDI Host instance's
* state values and configures the pipes required to communicate with the interface if it is found within the device.
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
* the Addressed state.
*
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref MIDI_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** General management task for a given MIDI host 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 an MIDI Class host configuration and state.
*/
void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a MIDI event packet to the device. If no device is connected, the event packet is discarded.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_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 Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_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 device. This should be called to override the
* \ref MIDI_Host_SendEventPacket() function's packing behavior, to flush queued events. Events are queued into the
* pipe bank until either the pipe bank is full, or \ref MIDI_Host_Flush() is called. This allows for multiple MIDI
* events to be packed into a single pipe packet, increasing data throughput.
*
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
*
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Receives a MIDI event packet from the device.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_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 \c true if a MIDI event packet was received, \c false otherwise.
*/
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_MIDI_HOST_C)
static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,579 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_MS_DRIVER
#define __INCLUDE_FROM_MASSSTORAGE_HOST_C
#include "MassStorageClassHost.h"
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Interface_t* MassStorageInterface = NULL;
memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return MS_ENUMERROR_InvalidConfigDescriptor;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
if (!(MassStorageInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MS_Host_NextMSInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MS_Host_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return MS_ENUMERROR_NoCompatibleInterfaceFound;
}
MassStorageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
MSInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
MSInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
MSInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
MSInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
MSInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
MSInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
if (!(Pipe_ConfigurePipeTable(&MSInterfaceInfo->Config.DataINPipe, 1)))
return MS_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&MSInterfaceInfo->Config.DataOUTPipe, 1)))
return MS_ENUMERROR_PipeConfigurationFailed;
MSInterfaceInfo->State.InterfaceNumber = MassStorageInterface->InterfaceNumber;
MSInterfaceInfo->State.IsActive = true;
return MS_ENUMERROR_NoError;
}
static uint8_t DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == MS_CSCP_MassStorageClass) &&
(Interface->SubClass == MS_CSCP_SCSITransparentSubclass) &&
(Interface->Protocol == MS_CSCP_BulkOnlyTransportProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
if ((EndpointType == EP_TYPE_BULK) && (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
{
return DESCRIPTOR_SEARCH_Found;
}
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandBlockWrapper_t* const SCSICommandBlock,
const void* const BufferPtr)
{
uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
if (++MSInterfaceInfo->State.TransactionTag == 0xFFFFFFFF)
MSInterfaceInfo->State.TransactionTag = 1;
SCSICommandBlock->Signature = CPU_TO_LE32(MS_CBW_SIGNATURE);
SCSICommandBlock->Tag = cpu_to_le32(MSInterfaceInfo->State.TransactionTag);
Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t),
NULL)) != PIPE_RWSTREAM_NoError)
{
return ErrorCode;
}
Pipe_ClearOUT();
Pipe_WaitUntilReady();
Pipe_Freeze();
if (BufferPtr != NULL)
{
ErrorCode = MS_Host_SendReceiveData(MSInterfaceInfo, SCSICommandBlock, (void*)BufferPtr);
if ((ErrorCode != PIPE_RWSTREAM_NoError) && (ErrorCode != PIPE_RWSTREAM_PipeStalled))
{
Pipe_Freeze();
return ErrorCode;
}
}
MS_CommandStatusWrapper_t SCSIStatusBlock;
return MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSIStatusBlock);
}
static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
{
uint16_t TimeoutMSRem = MS_COMMAND_DATA_TIMEOUT_MS;
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
while (!(Pipe_IsINReceived()))
{
uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
if (CurrentFrameNumber != PreviousFrameNumber)
{
PreviousFrameNumber = CurrentFrameNumber;
if (!(TimeoutMSRem--))
return PIPE_RWSTREAM_Timeout;
}
Pipe_Freeze();
Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsStalled())
{
USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
return PIPE_RWSTREAM_PipeStalled;
}
Pipe_Freeze();
Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsStalled())
{
USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
return PIPE_RWSTREAM_PipeStalled;
}
if (USB_HostState == HOST_STATE_Unattached)
return PIPE_RWSTREAM_DeviceDisconnected;
};
Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
Pipe_Freeze();
Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandBlockWrapper_t* const SCSICommandBlock,
void* BufferPtr)
{
uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
uint16_t BytesRem = le32_to_cpu(SCSICommandBlock->DataTransferLength);
if (SCSICommandBlock->Flags & MS_COMMAND_DIR_DATA_IN)
{
if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError)
{
Pipe_Freeze();
return ErrorCode;
}
Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
Pipe_ClearIN();
}
else
{
Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
Pipe_ClearOUT();
while (!(Pipe_IsOUTReady()))
{
if (USB_HostState == HOST_STATE_Unattached)
return PIPE_RWSTREAM_DeviceDisconnected;
}
}
Pipe_Freeze();
return ErrorCode;
}
static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandStatusWrapper_t* const SCSICommandStatus)
{
uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(MS_CommandStatusWrapper_t),
NULL)) != PIPE_RWSTREAM_NoError)
{
return ErrorCode;
}
Pipe_ClearIN();
Pipe_Freeze();
if (SCSICommandStatus->Status != MS_SCSI_COMMAND_Pass)
ErrorCode = MS_ERROR_LOGICAL_CMD_FAILED;
return ErrorCode;
}
uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
{
uint8_t ErrorCode;
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = MS_REQ_MassStorageReset,
.wValue = 0,
.wIndex = MSInterfaceInfo->State.InterfaceNumber,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful)
return ErrorCode;
Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful)
return ErrorCode;
return HOST_SENDCONTROL_Successful;
}
uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
uint8_t* const MaxLUNIndex)
{
uint8_t ErrorCode;
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = MS_REQ_GetMaxLUN,
.wValue = 0,
.wIndex = MSInterfaceInfo->State.InterfaceNumber,
.wLength = 1,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((ErrorCode = USB_Host_SendControlRequest(MaxLUNIndex)) == HOST_SENDCONTROL_SetupStalled)
{
*MaxLUNIndex = 0;
ErrorCode = HOST_SENDCONTROL_Successful;
}
return ErrorCode;
}
uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
SCSI_Inquiry_Response_t* const InquiryData)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
.DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Inquiry_Response_t)),
.Flags = MS_COMMAND_DIR_DATA_IN,
.LUN = LUNIndex,
.SCSICommandLength = 6,
.SCSICommandData =
{
SCSI_CMD_INQUIRY,
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
sizeof(SCSI_Inquiry_Response_t), // Allocation Length
0x00 // Unused (control)
}
};
return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, InquiryData);
}
uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
.DataTransferLength = CPU_TO_LE32(0),
.Flags = MS_COMMAND_DIR_DATA_IN,
.LUN = LUNIndex,
.SCSICommandLength = 6,
.SCSICommandData =
{
SCSI_CMD_TEST_UNIT_READY,
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
0x00 // Unused (control)
}
};
return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL);
}
uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
SCSI_Capacity_t* const DeviceCapacity)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
.DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Capacity_t)),
.Flags = MS_COMMAND_DIR_DATA_IN,
.LUN = LUNIndex,
.SCSICommandLength = 10,
.SCSICommandData =
{
SCSI_CMD_READ_CAPACITY_10,
0x00, // Reserved
0x00, // MSB of Logical block address
0x00,
0x00,
0x00, // LSB of Logical block address
0x00, // Reserved
0x00, // Reserved
0x00, // Partial Medium Indicator
0x00 // Unused (control)
}
};
if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, DeviceCapacity)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
DeviceCapacity->Blocks = BE32_TO_CPU(DeviceCapacity->Blocks);
DeviceCapacity->BlockSize = BE32_TO_CPU(DeviceCapacity->BlockSize);
return PIPE_RWSTREAM_NoError;
}
uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
SCSI_Request_Sense_Response_t* const SenseData)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
.DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Request_Sense_Response_t)),
.Flags = MS_COMMAND_DIR_DATA_IN,
.LUN = LUNIndex,
.SCSICommandLength = 6,
.SCSICommandData =
{
SCSI_CMD_REQUEST_SENSE,
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
sizeof(SCSI_Request_Sense_Response_t), // Allocation Length
0x00 // Unused (control)
}
};
return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, SenseData);
}
uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
const bool PreventRemoval)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
.DataTransferLength = CPU_TO_LE32(0),
.Flags = MS_COMMAND_DIR_DATA_OUT,
.LUN = LUNIndex,
.SCSICommandLength = 6,
.SCSICommandData =
{
SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,
0x00, // Reserved
0x00, // Reserved
PreventRemoval, // Prevent flag
0x00, // Reserved
0x00 // Unused (control)
}
};
return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL);
}
uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
const uint32_t BlockAddress,
const uint8_t Blocks,
const uint16_t BlockSize,
void* BlockBuffer)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
.DataTransferLength = cpu_to_le32((uint32_t)Blocks * BlockSize),
.Flags = MS_COMMAND_DIR_DATA_IN,
.LUN = LUNIndex,
.SCSICommandLength = 10,
.SCSICommandData =
{
SCSI_CMD_READ_10,
0x00, // Unused (control bits, all off)
(BlockAddress >> 24), // MSB of Block Address
(BlockAddress >> 16),
(BlockAddress >> 8),
(BlockAddress & 0xFF), // LSB of Block Address
0x00, // Reserved
0x00, // MSB of Total Blocks to Read
Blocks, // LSB of Total Blocks to Read
0x00 // Unused (control)
}
};
return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer);
}
uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
const uint32_t BlockAddress,
const uint8_t Blocks,
const uint16_t BlockSize,
const void* BlockBuffer)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
return HOST_SENDCONTROL_DeviceDisconnected;
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
.DataTransferLength = cpu_to_le32((uint32_t)Blocks * BlockSize),
.Flags = MS_COMMAND_DIR_DATA_OUT,
.LUN = LUNIndex,
.SCSICommandLength = 10,
.SCSICommandData =
{
SCSI_CMD_WRITE_10,
0x00, // Unused (control bits, all off)
(BlockAddress >> 24), // MSB of Block Address
(BlockAddress >> 16),
(BlockAddress >> 8),
(BlockAddress & 0xFF), // LSB of Block Address
0x00, // Reserved
0x00, // MSB of Total Blocks to Write
Blocks, // LSB of Total Blocks to Write
0x00 // Unused (control)
}
};
return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer);
}
#endif

View file

@ -0,0 +1,335 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB Mass Storage Class driver.
*
* Host 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassMS
* \defgroup Group_USBClassMassStorageHost Mass Storage Class Host Mode Driver
*
* \section Sec_USBClassMassStorageHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassMassStorageHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the Mass Storage USB Class driver.
*
* @{
*/
#ifndef __MS_CLASS_HOST_H__
#define __MS_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/MassStorageClassCommon.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/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Error code for some Mass Storage Host functions, indicating a logical (and not hardware) error. */
#define MS_ERROR_LOGICAL_CMD_FAILED 0x80
/* Type Defines: */
/** \brief Mass Storage Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the Mass Storage class driver functions as the \c MSInterfaceInfo parameter. This
* stores each Mass Storage interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref MS_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the Mass Storage interface within the attached device. */
uint32_t TransactionTag; /**< Current transaction tag for data synchronizing of packets. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_MS_Host_t;
/** \brief SCSI Device LUN Capacity Structure.
*
* SCSI capacity structure, to hold the total capacity of the device in both the number
* of blocks in the current LUN, and the size of each block. This structure is filled by
* the device when the \ref MS_Host_ReadDeviceCapacity() function is called.
*/
typedef struct
{
uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device. */
uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN. */
} SCSI_Capacity_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref MS_Host_ConfigurePipes() function. */
enum MS_Host_EnumerationFailure_ErrorCodes_t
{
MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
MS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor. */
MS_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** Host interface configuration routine, to configure a given Mass Storage host interface instance using the
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Mass
* Storage Host instance's state values and configures the pipes required to communicate with the interface if it
* is found within the device. This should be called once after the stack has enumerated the attached device, while
* the host state machine is in the Addressed state.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref MS_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Sends a MASS STORAGE RESET control request to the attached device, resetting the Mass Storage Interface
* and readying it for the next Mass Storage command. This should be called after a failed SCSI request to
* ensure the attached Mass Storage device is ready to receive the next command.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a GET MAX LUN control request to the attached device, retrieving the index of the highest LUN (Logical
* UNit, a logical drive) in the device. This value can then be used in the other functions of the Mass Storage
* Host mode Class driver to address a specific LUN within the device.
*
* \note Some devices do not support this request, and will STALL it when issued. To get around this,
* on unsupported devices the max LUN index will be reported as zero and no error will be returned
* if the device STALLs the request.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[out] MaxLUNIndex Pointer to a location where the highest LUN index value should be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
uint8_t* const MaxLUNIndex) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Retrieves the Mass Storage device's inquiry data for the specified LUN, indicating the device characteristics and
* properties.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[in] LUNIndex LUN index within the device the command is being issued to.
* \param[out] InquiryData Location where the read inquiry data should be stored.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED.
*/
uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
SCSI_Inquiry_Response_t* const InquiryData) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(3);
/** Sends a TEST UNIT READY command to the device, to determine if it is ready to accept other SCSI commands.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[in] LUNIndex LUN index within the device the command is being issued to.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
*/
uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex) ATTR_NON_NULL_PTR_ARG(1);
/** Retrieves the total capacity of the attached USB Mass Storage device, in blocks, and block size.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[in] LUNIndex LUN index within the device the command is being issued to.
* \param[out] DeviceCapacity Pointer to the location where the capacity information should be stored.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
*/
uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
SCSI_Capacity_t* const DeviceCapacity) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(3);
/** Retrieves the device sense data, indicating the current device state and error codes for the previously
* issued command.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[in] LUNIndex LUN index within the device the command is being issued to.
* \param[out] SenseData Pointer to the location where the sense information should be stored.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
*/
uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
SCSI_Request_Sense_Response_t* const SenseData) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(3);
/** Issues a PREVENT MEDIUM REMOVAL command, to logically (or, depending on the type of device, physically) lock
* the device from removal so that blocks of data on the medium can be read or altered.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[in] LUNIndex LUN index within the device the command is being issued to.
* \param[in] PreventRemoval Boolean \c true if the device should be locked from removal, \c false otherwise.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
*/
uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
const bool PreventRemoval) ATTR_NON_NULL_PTR_ARG(1);
/** Reads blocks of data from the attached Mass Storage device's medium.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[in] LUNIndex LUN index within the device the command is being issued to.
* \param[in] BlockAddress Starting block address within the device to read from.
* \param[in] Blocks Total number of blocks to read.
* \param[in] BlockSize Size in bytes of each block within the device.
* \param[out] BlockBuffer Pointer to where the read data from the device should be stored.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
*/
uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
const uint32_t BlockAddress,
const uint8_t Blocks,
const uint16_t BlockSize,
void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
/** Writes blocks of data to the attached Mass Storage device's medium.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
* \param[in] LUNIndex LUN index within the device the command is being issued to.
* \param[in] BlockAddress Starting block address within the device to write to.
* \param[in] Blocks Total number of blocks to read.
* \param[in] BlockSize Size in bytes of each block within the device.
* \param[in] BlockBuffer Pointer to where the data to write should be sourced from.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
*/
uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t LUNIndex,
const uint32_t BlockAddress,
const uint8_t Blocks,
const uint16_t BlockSize,
const void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
/* Inline Functions: */
/** General management task for a given Mass Storage host 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 an Mass Storage Class host configuration and state.
*/
static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
{
(void)MSInterfaceInfo;
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define MS_COMMAND_DATA_TIMEOUT_MS 10000
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_MASSSTORAGE_HOST_C)
static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandBlockWrapper_t* const SCSICommandBlock,
const void* const BufferPtr) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandBlockWrapper_t* const SCSICommandBlock,
void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandStatusWrapper_t* const SCSICommandStatus)
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
static uint8_t DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,400 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_PRINTER_DRIVER
#define __INCLUDE_FROM_PRINTER_HOST_C
#include "PrinterClassHost.h"
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Interface_t* PrinterInterface = NULL;
memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return PRNT_ENUMERROR_InvalidConfigDescriptor;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
if (!(PrinterInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_PRNT_Host_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return PRNT_ENUMERROR_NoCompatibleInterfaceFound;
}
PrinterInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
PRNTInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
PRNTInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
PRNTInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
PRNTInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
PRNTInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
PRNTInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataINPipe, 1)))
return PRNT_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataOUTPipe, 1)))
return PRNT_ENUMERROR_PipeConfigurationFailed;
PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
PRNTInterfaceInfo->State.IsActive = true;
return PRNT_ENUMERROR_NoError;
}
static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == PRNT_CSCP_PrinterClass) &&
(Interface->SubClass == PRNT_CSCP_PrinterSubclass) &&
(Interface->Protocol == PRNT_CSCP_BidirectionalProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
if (EndpointType == EP_TYPE_BULK)
return DESCRIPTOR_SEARCH_Found;
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
return;
#if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
PRNT_Host_Flush(PRNTInterfaceInfo);
#endif
}
uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
{
if (PRNTInterfaceInfo->State.AlternateSetting)
{
uint8_t ErrorCode;
if ((ErrorCode = USB_Host_SetInterfaceAltSetting(PRNTInterfaceInfo->State.InterfaceNumber,
PRNTInterfaceInfo->State.AlternateSetting)) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
}
return HOST_SENDCONTROL_Successful;
}
uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
uint8_t* const PortStatus)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = PRNT_REQ_GetPortStatus,
.wValue = 0,
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
.wLength = sizeof(uint8_t),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(PortStatus);
}
uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = PRNT_REQ_SoftReset,
.wValue = 0,
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
.wLength = 0,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(NULL);
}
uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (!(Pipe_BytesInPipe()))
return PIPE_READYWAIT_NoError;
bool BankFull = !(Pipe_IsReadWriteAllowed());
Pipe_ClearOUT();
if (BankFull)
{
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
return ErrorCode;
Pipe_ClearOUT();
}
Pipe_Freeze();
return PIPE_READYWAIT_NoError;
}
uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
const uint8_t Data)
{
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (!(Pipe_IsReadWriteAllowed()))
{
Pipe_ClearOUT();
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
return ErrorCode;
}
Pipe_Write_8(Data);
Pipe_Freeze();
return PIPE_READYWAIT_NoError;
}
uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
const char* const String)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
Pipe_ClearOUT();
ErrorCode = Pipe_WaitUntilReady();
Pipe_Freeze();
return ErrorCode;
}
uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
const void* Buffer,
const uint16_t Length)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
Pipe_ClearOUT();
ErrorCode = Pipe_WaitUntilReady();
Pipe_Freeze();
return ErrorCode;
}
uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
return 0;
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
if (!(Pipe_BytesInPipe()))
{
Pipe_ClearIN();
Pipe_Freeze();
return 0;
}
else
{
Pipe_Freeze();
return Pipe_BytesInPipe();
}
}
else
{
Pipe_Freeze();
return 0;
}
}
int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
int16_t ReceivedByte = -1;
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
{
if (Pipe_BytesInPipe())
ReceivedByte = Pipe_Read_8();
if (!(Pipe_BytesInPipe()))
Pipe_ClearIN();
}
Pipe_Freeze();
return ReceivedByte;
}
uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
char* const DeviceIDString,
const uint16_t BufferSize)
{
uint8_t ErrorCode;
uint16_t DeviceIDStringLength = 0;
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = PRNT_REQ_GetDeviceID,
.wValue = 0,
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
.wLength = sizeof(DeviceIDStringLength),
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
if (!(DeviceIDStringLength))
{
DeviceIDString[0] = 0x00;
return HOST_SENDCONTROL_Successful;
}
DeviceIDStringLength = be16_to_cpu(DeviceIDStringLength);
if (DeviceIDStringLength > BufferSize)
DeviceIDStringLength = BufferSize;
USB_ControlRequest.wLength = DeviceIDStringLength;
if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
return ErrorCode;
memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
DeviceIDString[DeviceIDStringLength - 2] = 0x00;
return HOST_SENDCONTROL_Successful;
}
#endif

View file

@ -0,0 +1,285 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB Printer Class driver.
*
* Host mode driver for the library USB Printer Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassPrinter
* \defgroup Group_USBClassPrinterHost Printer Class Host Mode Driver
*
* \section Sec_USBClassPrinterHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/PrinterClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassPrinterHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the Printer USB Class driver.
*
* @{
*/
#ifndef __PRINTER_CLASS_HOST_H__
#define __PRINTER_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/PrinterClassCommon.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Type Defines: */
/** \brief Printer Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the Printer class driver functions as the \c PRNTInterfaceInfo parameter. This
* stores each Printer interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref PRNT_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the Printer interface within the attached device. */
uint8_t AlternateSetting; /**< Alternate setting within the Printer Interface in the attached device. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_PRNT_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref PRNT_Host_ConfigurePipes() function. */
enum PRNT_Host_EnumerationFailure_ErrorCodes_t
{
PRNT_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
PRNT_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
PRNT_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Printer interface was not found in the device's Configuration Descriptor. */
PRNT_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** Host interface configuration routine, to configure a given Printer host interface instance using the
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Printer
* instance's state values and configures the pipes required to communicate with the interface if it is found within
* the device. This should be called once after the stack has enumerated the attached device, while the host state
* machine is in the Addressed state.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref PRNT_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** General management task for a given Printer host 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] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
*/
void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Configures the printer to enable Bidirectional mode, if it is not already in this mode. This should be called
* once the connected device's configuration has been set, to ensure the printer is ready to accept commands.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Retrieves the status of the virtual Printer port's inbound status lines. The result can then be masked against the
* \c PRNT_PORTSTATUS_* macros to determine the printer port's status.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
* \param[out] PortStatus Location where the retrieved port status should be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
uint8_t* const PortStatus)
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Soft-resets the attached printer, readying it for new commands.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
*/
uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
*
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends the given null terminated string to the attached printer's input endpoint.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
* \param[in] String Pointer to a null terminated string to send.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Sends the given raw data stream to the attached printer's input endpoint. This should contain commands that the
* printer is able to understand - for example, PCL data. Not all printers accept all printer languages; see
* \ref PRNT_Host_GetDeviceID() for details on determining acceptable languages for an attached printer.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
* \param[in] Buffer Pointer to a buffer containing the raw command stream to send to the printer.
* \param[in] Length Size in bytes of the command stream to be sent.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
const void* Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
* byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
* \ref PRNT_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
* packed into a single pipe packet, increasing data throughput.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
* \param[in] Data Byte of data to send to the device.
*
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
*/
uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
/** Determines the number of bytes received by the printer interface from the device, waiting to be read. This indicates the number
* of bytes in the IN pipe bank only, and thus the number of calls to \ref PRNT_Host_ReceiveByte() which are guaranteed to succeed
* immediately. If multiple bytes are to be received, they should be buffered by the user application, as the pipe bank will not be
* released back to the USB controller until all bytes are read.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
*
* \return Total number of buffered bytes received from the device.
*/
uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
* returns a negative value. The \ref PRNT_Host_BytesReceived() function may be queried in advance to determine how many bytes
* are currently buffered in the Printer interface's data receive pipe.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
*
* \return Next received byte from the device, or a negative value if no data received.
*/
int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Retrieves the attached printer device's ID string, formatted according to IEEE 1284. This string is sent as a
* Unicode string from the device and is automatically converted to an ASCII encoded C string by this function, thus
* the maximum reportable string length is two less than the size given (to accommodate the Unicode string length
* bytes which are removed).
*
* This string, when supported, contains the model, manufacturer and acceptable printer languages for the attached device.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
* \param[out] DeviceIDString Pointer to a buffer where the Device ID string should be stored, in ASCII format.
* \param[in] BufferSize Size in bytes of the buffer allocated for the Device ID string.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
char* const DeviceIDString,
const uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_PRINTER_HOST_C)
static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,476 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_RNDIS_DRIVER
#define __INCLUDE_FROM_RNDIS_HOST_C
#include "RNDISClassHost.h"
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
USB_Descriptor_Interface_t* RNDISControlInterface = NULL;
memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return RNDIS_ENUMERROR_InvalidConfigDescriptor;
RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
{
if (!(RNDISControlInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (NotificationEndpoint)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
}
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
}
else
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
}
RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
NotificationEndpoint = NULL;
}
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
{
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
NotificationEndpoint = EndpointData;
else
DataINEndpoint = EndpointData;
}
else
{
DataOUTEndpoint = EndpointData;
}
}
RNDISInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
RNDISInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
RNDISInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
RNDISInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
RNDISInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
RNDISInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
RNDISInterfaceInfo->Config.NotificationPipe.Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
RNDISInterfaceInfo->Config.NotificationPipe.EndpointAddress = NotificationEndpoint->EndpointAddress;
RNDISInterfaceInfo->Config.NotificationPipe.Type = EP_TYPE_INTERRUPT;
if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataINPipe, 1)))
return RNDIS_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataOUTPipe, 1)))
return RNDIS_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.NotificationPipe, 1)))
return RNDIS_ENUMERROR_PipeConfigurationFailed;
RNDISInterfaceInfo->State.ControlInterfaceNumber = RNDISControlInterface->InterfaceNumber;
RNDISInterfaceInfo->State.IsActive = true;
return RNDIS_ENUMERROR_NoError;
}
static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == CDC_CSCP_CDCClass) &&
(Interface->SubClass == CDC_CSCP_ACMSubclass) &&
(Interface->Protocol == CDC_CSCP_VendorSpecificProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor,
USB_Descriptor_Interface_t);
if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
(Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
(Interface->Protocol == CDC_CSCP_NoDataProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
{
return DESCRIPTOR_SEARCH_Found;
}
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t Length)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = RNDIS_REQ_SendEncapsulatedCommand,
.wValue = 0,
.wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
.wLength = Length,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(Buffer);
}
static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t Length)
{
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
.bRequest = RNDIS_REQ_GetEncapsulatedResponse,
.wValue = 0,
.wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
.wLength = Length,
};
Pipe_SelectPipe(PIPE_CONTROLPIPE);
return USB_Host_SendControlRequest(Buffer);
}
uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
{
uint8_t ErrorCode;
RNDIS_KeepAlive_Message_t KeepAliveMessage;
RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
KeepAliveMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_MSG);
KeepAliveMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Message_t));
KeepAliveMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
return HOST_SENDCONTROL_Successful;
}
uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
{
uint8_t ErrorCode;
RNDIS_Initialize_Message_t InitMessage;
RNDIS_Initialize_Complete_t InitMessageResponse;
InitMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_MSG);
InitMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Message_t));
InitMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
InitMessage.MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);
InitMessage.MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);
InitMessage.MaxTransferSize = cpu_to_le32(RNDISInterfaceInfo->Config.HostMaxPacketSize);
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
if (InitMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
return RNDIS_ERROR_LOGICAL_CMD_FAILED;
RNDISInterfaceInfo->State.DeviceMaxPacketSize = le32_to_cpu(InitMessageResponse.MaxTransferSize);
return HOST_SENDCONTROL_Successful;
}
uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
const uint32_t Oid,
void* Buffer,
const uint16_t Length)
{
uint8_t ErrorCode;
struct
{
RNDIS_Set_Message_t SetMessage;
uint8_t ContiguousBuffer[Length];
} SetMessageData;
RNDIS_Set_Complete_t SetMessageResponse;
SetMessageData.SetMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_MSG);
SetMessageData.SetMessage.MessageLength = cpu_to_le32(sizeof(RNDIS_Set_Message_t) + Length);
SetMessageData.SetMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
SetMessageData.SetMessage.Oid = cpu_to_le32(Oid);
SetMessageData.SetMessage.InformationBufferLength = cpu_to_le32(Length);
SetMessageData.SetMessage.InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
SetMessageData.SetMessage.DeviceVcHandle = CPU_TO_LE32(0);
memcpy(&SetMessageData.ContiguousBuffer, Buffer, Length);
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
(sizeof(RNDIS_Set_Message_t) + Length))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
if (SetMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
return RNDIS_ERROR_LOGICAL_CMD_FAILED;
return HOST_SENDCONTROL_Successful;
}
uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
const uint32_t Oid,
void* Buffer,
const uint16_t MaxLength)
{
uint8_t ErrorCode;
RNDIS_Query_Message_t QueryMessage;
struct
{
RNDIS_Query_Complete_t QueryMessageResponse;
uint8_t ContiguousBuffer[MaxLength];
} QueryMessageResponseData;
QueryMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_MSG);
QueryMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Message_t));
QueryMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
QueryMessage.Oid = cpu_to_le32(Oid);
QueryMessage.InformationBufferLength = CPU_TO_LE32(0);
QueryMessage.InformationBufferOffset = CPU_TO_LE32(0);
QueryMessage.DeviceVcHandle = CPU_TO_LE32(0);
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
{
return ErrorCode;
}
if (QueryMessageResponseData.QueryMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
return RNDIS_ERROR_LOGICAL_CMD_FAILED;
memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
return HOST_SENDCONTROL_Successful;
}
bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
{
bool PacketWaiting;
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
return false;
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
PacketWaiting = Pipe_IsINReceived();
Pipe_Freeze();
return PacketWaiting;
}
uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
uint16_t* const PacketLength)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (!(Pipe_IsReadWriteAllowed()))
{
if (Pipe_IsINReceived())
Pipe_ClearIN();
*PacketLength = 0;
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
RNDIS_Packet_Message_t DeviceMessage;
if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
NULL)) != PIPE_RWSTREAM_NoError)
{
return ErrorCode;
}
*PacketLength = (uint16_t)le32_to_cpu(DeviceMessage.DataLength);
Pipe_Discard_Stream(le32_to_cpu(DeviceMessage.DataOffset) -
(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
NULL);
Pipe_Read_Stream_LE(Buffer, *PacketLength, NULL);
if (!(Pipe_BytesInPipe()))
Pipe_ClearIN();
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t PacketLength)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
return PIPE_READYWAIT_DeviceDisconnected;
RNDIS_Packet_Message_t DeviceMessage;
memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
DeviceMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
DeviceMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
DeviceMessage.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
DeviceMessage.DataLength = cpu_to_le32(PacketLength);
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
NULL)) != PIPE_RWSTREAM_NoError)
{
return ErrorCode;
}
Pipe_Write_Stream_LE(Buffer, PacketLength, NULL);
Pipe_ClearOUT();
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
#endif

View file

@ -0,0 +1,270 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB RNDIS Class driver.
*
* Host 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 USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassRNDIS
* \defgroup Group_USBClassRNDISHost RNDIS Class Host Mode Driver
*
* \section Sec_USBClassRNDISHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/RNDISClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassRNDISHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the Microsoft RNDIS Ethernet
* USB Class driver.
*
* @{
*/
#ifndef __RNDIS_CLASS_HOST_H__
#define __RNDIS_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/RNDISClassCommon.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/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Type Defines: */
/** \brief RNDIS Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the RNDIS class driver functions as the \c RNDISInterfaceInfo parameter. This
* stores each RNDIS interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
USB_Pipe_Table_t NotificationPipe; /**< Notification IN Pipe configuration table. */
uint32_t HostMaxPacketSize; /**< Maximum size of a packet which can be buffered by 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref RNDIS_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t ControlInterfaceNumber; /**< Interface index of the RNDIS control interface within the attached device. */
uint32_t DeviceMaxPacketSize; /**< Maximum size of a packet which can be buffered by the attached RNDIS device. */
uint32_t RequestID; /**< Request ID counter to give a unique ID for each command/response pair. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_RNDIS_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref RNDIS_Host_ConfigurePipes() function. */
enum RNDIS_Host_EnumerationFailure_ErrorCodes_t
{
RNDIS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
RNDIS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
RNDIS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible RNDIS interface was not found in the device's Configuration Descriptor. */
RNDIS_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** Host interface configuration routine, to configure a given RNDIS host interface instance using the Configuration
* Descriptor read from an attached USB device. This function automatically updates the given RNDIS Host instance's
* state values and configures the pipes required to communicate with the interface if it is found within the device.
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
* the Addressed state.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref RNDIS_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods
* of long inactivity.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the device returned a
* logical command failure.
*/
uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Initializes the attached RNDIS device's RNDIS interface. This should be called after the device's pipes have been
* configured via the call to \ref RNDIS_Host_ConfigurePipes().
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the
* device returned a logical command failure.
*/
uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sets a given RNDIS property of an attached RNDIS device.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
* \param[in] Oid OID number of the parameter to set.
* \param[in] Buffer Pointer to where the property data is to be sourced from.
* \param[in] Length Length in bytes of the property data to sent to the device.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the
* device returned a logical command failure.
*/
uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
const uint32_t Oid,
void* Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Gets a given RNDIS property of an attached RNDIS device.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
* \param[in] Oid OID number of the parameter to get.
* \param[in] Buffer Pointer to where the property data is to be written to.
* \param[in] MaxLength Length in bytes of the destination buffer size.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the
* device returned a logical command failure.
*/
uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
const uint32_t Oid,
void* Buffer,
const uint16_t MaxLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Determines if a packet is currently waiting for the host to read in and process.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
*
* \return Boolean \c true if a packet is waiting to be read in by the host, \c false otherwise.
*/
bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
* only the packet contents for processing by the host in the nominated buffer.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
* \param[out] Buffer Pointer to a buffer where the packer data is to be written to.
* \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
uint16_t* const PacketLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2)
ATTR_NON_NULL_PTR_ARG(3);
/** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
* \param[in] Buffer Pointer to a buffer where the packer data is to be read from.
* \param[in] PacketLength Length in bytes of the packet to send.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t PacketLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/* Inline Functions: */
/** General management task for a given RNDIS host 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 an RNDIS Class host configuration and state.
*/
static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
{
(void)RNDISInterfaceInfo;
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_RNDIS_HOST_C)
static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(2);
static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
void* Buffer,
const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(2);
static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,436 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 "../../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#define __INCLUDE_FROM_SI_DRIVER
#define __INCLUDE_FROM_STILLIMAGE_HOST_C
#include "StillImageClassHost.h"
uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData)
{
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Endpoint_t* EventsEndpoint = NULL;
USB_Descriptor_Interface_t* StillImageInterface = NULL;
memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return SI_ENUMERROR_InvalidConfigDescriptor;
while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(EventsEndpoint))
{
if (!(StillImageInterface) ||
USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return SI_ENUMERROR_NoCompatibleInterfaceFound;
}
StillImageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
EventsEndpoint = NULL;
continue;
}
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
{
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
EventsEndpoint = EndpointData;
else
DataINEndpoint = EndpointData;
}
else
{
DataOUTEndpoint = EndpointData;
}
}
SIInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
SIInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
SIInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
SIInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
SIInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
SIInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
SIInterfaceInfo->Config.EventsPipe.Size = le16_to_cpu(EventsEndpoint->EndpointSize);
SIInterfaceInfo->Config.EventsPipe.EndpointAddress = EventsEndpoint->EndpointAddress;
SIInterfaceInfo->Config.EventsPipe.Type = EP_TYPE_INTERRUPT;
if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataINPipe, 1)))
return SI_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataOUTPipe, 1)))
return SI_ENUMERROR_PipeConfigurationFailed;
if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.EventsPipe, 1)))
return SI_ENUMERROR_PipeConfigurationFailed;
SIInterfaceInfo->State.InterfaceNumber = StillImageInterface->InterfaceNumber;
SIInterfaceInfo->State.IsActive = true;
return SI_ENUMERROR_NoError;
}
uint8_t DCOMP_SI_Host_NextSIInterface(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Interface)
{
USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
if ((Interface->Class == SI_CSCP_StillImageClass) &&
(Interface->SubClass == SI_CSCP_StillImageSubclass) &&
(Interface->Protocol == SI_CSCP_BulkOnlyProtocol))
{
return DESCRIPTOR_SEARCH_Found;
}
}
return DESCRIPTOR_SEARCH_NotFound;
}
uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
{
USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
if (Header->Type == DTYPE_Endpoint)
{
USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
(!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
{
return DESCRIPTOR_SEARCH_Found;
}
}
else if (Header->Type == DTYPE_Interface)
{
return DESCRIPTOR_SEARCH_Fail;
}
return DESCRIPTOR_SEARCH_NotFound;
}
uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
PIMA_Container_t* const PIMAHeader)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
if (SIInterfaceInfo->State.IsSessionOpen)
PIMAHeader->TransactionID = cpu_to_le32(SIInterfaceInfo->State.TransactionID++);
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
if (ParamBytes)
{
if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NULL)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
}
Pipe_ClearOUT();
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
PIMA_Container_t* const PIMAHeader)
{
uint16_t TimeoutMSRem = SI_COMMAND_DATA_TIMEOUT_MS;
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
while (!(Pipe_IsINReceived()))
{
uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
if (CurrentFrameNumber != PreviousFrameNumber)
{
PreviousFrameNumber = CurrentFrameNumber;
if (!(TimeoutMSRem--))
return PIPE_RWSTREAM_Timeout;
}
Pipe_Freeze();
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsStalled())
{
USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
return PIPE_RWSTREAM_PipeStalled;
}
Pipe_Freeze();
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsStalled())
{
USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
return PIPE_RWSTREAM_PipeStalled;
}
if (USB_HostState == HOST_STATE_Unattached)
return PIPE_RWSTREAM_DeviceDisconnected;
}
Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NULL);
if (PIMAHeader->Type == CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock))
{
uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
if (ParamBytes)
Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NULL);
Pipe_ClearIN();
}
Pipe_Freeze();
return PIPE_RWSTREAM_NoError;
}
uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
const void* Buffer,
const uint16_t Bytes)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);
Pipe_Unfreeze();
ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NULL);
Pipe_ClearOUT();
Pipe_Freeze();
return ErrorCode;
}
uint8_t SI_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
void* Buffer,
const uint16_t Bytes)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);
Pipe_Unfreeze();
ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NULL);
Pipe_Freeze();
return ErrorCode;
}
bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
bool IsEventReceived = false;
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return false;
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipe.Address);
Pipe_Unfreeze();
if (Pipe_IsINReceived())
IsEventReceived = true;
Pipe_Freeze();
return IsEventReceived;
}
uint8_t SI_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
PIMA_Container_t* const PIMAHeader)
{
uint8_t ErrorCode;
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipe.Address);
Pipe_Unfreeze();
ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(PIMA_Container_t), NULL);
Pipe_ClearIN();
Pipe_Freeze();
return ErrorCode;
}
uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
uint8_t ErrorCode;
SIInterfaceInfo->State.TransactionID = 0;
SIInterfaceInfo->State.IsSessionOpen = false;
PIMA_Container_t PIMABlock = (PIMA_Container_t)
{
.DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
.Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
.Code = CPU_TO_LE16(0x1002),
.Params = {CPU_TO_LE32(1)},
};
if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
return SI_ERROR_LOGICAL_CMD_FAILED;
SIInterfaceInfo->State.IsSessionOpen = true;
return PIPE_RWSTREAM_NoError;
}
uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
uint8_t ErrorCode;
PIMA_Container_t PIMABlock = (PIMA_Container_t)
{
.DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
.Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
.Code = CPU_TO_LE16(0x1003),
.Params = {CPU_TO_LE32(1)},
};
if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
SIInterfaceInfo->State.IsSessionOpen = false;
if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
return SI_ERROR_LOGICAL_CMD_FAILED;
return PIPE_RWSTREAM_NoError;
}
uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
const uint16_t Operation,
const uint8_t TotalParams,
uint32_t* const Params)
{
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
uint8_t ErrorCode;
PIMA_Container_t PIMABlock = (PIMA_Container_t)
{
.DataLength = cpu_to_le32(PIMA_COMMAND_SIZE(TotalParams)),
.Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
.Code = cpu_to_le16(Operation),
};
memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);
if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
return PIPE_RWSTREAM_NoError;
}
uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
uint8_t ErrorCode;
PIMA_Container_t PIMABlock;
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected;
if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
return SI_ERROR_LOGICAL_CMD_FAILED;
return PIPE_RWSTREAM_NoError;
}
#endif

View file

@ -0,0 +1,317 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Host mode driver for the library USB Still Image Class driver.
*
* Host mode driver for the library USB Still Image Class driver.
*
* \note This file should not be included directly. It is automatically included as needed by the USB module driver
* dispatch header located in LUFA/Drivers/USB.h.
*/
/** \ingroup Group_USBClassSI
* \defgroup Group_USBClassStillImageHost Still Image Class Host Mode Driver
*
* \section Sec_USBClassStillImageHost_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/StillImageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassStillImageHost_ModDescription Module Description
* Host Mode USB Class driver framework interface, for the Still Image USB Class driver.
*
* @{
*/
#ifndef __SI_CLASS_HOST_H__
#define __SI_CLASS_HOST_H__
/* Includes: */
#include "../../USB.h"
#include "../Common/StillImageClassCommon.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_SI_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Error code for some Still Image Host functions, indicating a logical (and not hardware) error. */
#define SI_ERROR_LOGICAL_CMD_FAILED 0x80
/* Type Defines: */
/** \brief Still Image Class Host Mode Configuration and State Structure.
*
* Class state structure. An instance of this structure should be made within the user application,
* and passed to each of the Still Image class driver functions as the \c SIInterfaceInfo parameter. This
* stores each Still Image interface's configuration and state information.
*/
typedef struct
{
struct
{
USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
USB_Pipe_Table_t EventsPipe; /**< Event notification IN Pipe configuration table. */
} 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 IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref SI_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the Still Image interface within the attached device. */
bool IsSessionOpen; /**< Indicates if a PIMA session is currently open with the attached device. */
uint32_t TransactionID; /**< Transaction ID for the next transaction to send to the device. */
} State; /**< State data for the USB class interface within the device. All elements in this section
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
* the interface is enumerated.
*/
} USB_ClassInfo_SI_Host_t;
/* Enums: */
/** Enum for the possible error codes returned by the \ref SI_Host_ConfigurePipes() function. */
enum SI_Host_EnumerationFailure_ErrorCodes_t
{
SI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
SI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
SI_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Still Image interface was not found in the device's
* Configuration Descriptor.
*/
SI_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
};
/* Function Prototypes: */
/** Host interface configuration routine, to configure a given Still Image host interface instance using the
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Still
* Image Host instance's state values and configures the pipes required to communicate with the interface if it is
* found within the device. This should be called once after the stack has enumerated the attached device, while
* the host state machine is in the Addressed state.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
*
* \return A value from the \ref SI_Host_EnumerationFailure_ErrorCodes_t enum.
*/
uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Opens a new PIMA session with the attached device. This should be used before any session-orientated PIMA commands
* are issued to the device. Only one session can be open at the one time.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
* returned a logical command failure.
*/
uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Closes an already opened PIMA session with the attached device. This should be used after all session-orientated
* PIMA commands have been issued to the device.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
* returned a logical command failure.
*/
uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a raw PIMA block header to the device, filling out the transaction ID automatically. This can be used to send
* arbitrary PIMA blocks to the device with or without parameters.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[in] PIMAHeader Pointer to a PIMA container structure that is to be sent.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(2);
/** Receives a raw PIMA block header from the device. This can be used to receive arbitrary PIMA blocks from the device with
* or without parameters.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[out] PIMAHeader Pointer to a PIMA container structure where the received block is to be stored.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(2);
/** Sends a given PIMA command to the attached device, filling out the PIMA command header's Transaction ID automatically.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[in] Operation PIMA operation code to issue to the device.
* \param[in] TotalParams Total number of 32-bit parameters to send to the device in the issued command block.
* \param[in] Params Pointer to an array of 32-bit values containing the parameters to send in the command block.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
* returned a logical command failure.
*/
uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
const uint16_t Operation,
const uint8_t TotalParams,
uint32_t* const Params) ATTR_NON_NULL_PTR_ARG(1);
/** Receives and checks a response block from the attached Still Image device, once a command has been issued and all data
* associated with the command has been transferred.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
* returned a logical command failure.
*/
uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Indicates if the device has issued a PIMA event block to the host via the asynchronous events pipe.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
*
* \return Boolean \c true if an event is waiting to be read, \c false otherwise.
*/
bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
/** Receives an asynchronous event block from the device via the asynchronous events pipe.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[out] PIMAHeader Pointer to a PIMA container structure where the event should be stored.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
* returned a logical command failure.
*/
uint8_t SI_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
ATTR_NON_NULL_PTR_ARG(2);
/** Sends arbitrary data to the attached device, for use in the data phase of PIMA commands which require data
* transfer beyond the regular PIMA command block parameters.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[in] Buffer Pointer to a buffer where the data to send has been stored.
* \param[in] Bytes Length in bytes of the data in the buffer to send to the attached device.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
const void* Buffer,
const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** Receives arbitrary data from the attached device, for use in the data phase of PIMA commands which require data
* transfer beyond the regular PIMA command block parameters.
*
* \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
* call will fail.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[out] Buffer Pointer to a buffer where the received data is to be stored.
* \param[in] Bytes Length in bytes of the data to read.
*
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
*/
uint8_t SI_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
void* Buffer,
const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/* Inline Functions: */
/** General management task for a given Still Image host 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] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
*/
static inline void SI_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
static inline void SI_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
(void)SIInterfaceInfo;
}
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define SI_COMMAND_DATA_TIMEOUT_MS 10000
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_STILLIMAGE_HOST_C)
static uint8_t DCOMP_SI_Host_NextSIInterface(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
#endif
#endif
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,84 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB MIDI Class driver.
*
* Master include file for the library USB MIDI Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassMIDI MIDI Class Driver
* \brief USB class driver for the USB-IF MIDI class standard.
*
* \section Sec_USBClassMIDI_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/MIDIClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassMIDI_ModDescription Module Description
* MIDI Class Driver module. This module contains an internal implementation of the USB MIDI Class, for both Device
* and Host USB modes. User applications can use this class driver instead of implementing the MIDI class manually
* via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Hosts or Devices using the USB MIDI Class.
*
* \note The USB MIDI class is actually a special case of the regular Audio class, thus this module depends on
* structure definitions from the \ref Group_USBClassAudioDevice class driver module.
*
* @{
*/
#ifndef _MIDI_CLASS_H_
#define _MIDI_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_MIDI_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "Device/MIDIClassDevice.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "Host/MIDIClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,81 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB Mass Storage Class driver.
*
* Master include file for the library USB Mass Storage Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassMS Mass Storage Class Driver
* \brief USB class driver for the USB-IF Bulk-Only Transport Mass Storage class standard.
*
* \section Sec_USBClassMS_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassMS_ModDescription Module Description
* Mass Storage Class Driver module. This module contains an internal implementation of the USB Mass Storage Class, for both
* Device and Host USB modes. User applications can use this class driver instead of implementing the Mass Storage class
* manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Hosts or Devices using the USB Mass Storage Class.
*
* @{
*/
#ifndef _MS_CLASS_H_
#define _MS_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_MS_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "Device/MassStorageClassDevice.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "Host/MassStorageClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,83 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB Printer Class driver.
*
* Master include file for the library USB Printer Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassPrinter Printer Class Driver
* \brief USB class driver for the USB-IF Printer class standard.
*
* \section Sec_USBClassPrinter_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/PrinterClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/PrinterClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassPrinter_ModDescription Module Description
* Printer Class Driver module. This module contains an internal implementation of the USB Printer Class, for the base
* USB Printer transport layer for USB Host mode only. Note that printers are free to implement whatever printer language
* they choose on top of this (e.g. Postscript), and so this driver exposes low level data transport functions only rather
* than high level raster or text functions. User applications can use this class driver instead of implementing the Printer
* class manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Devices using the USB Printer Class.
*
* @{
*/
#ifndef _PRINTER_CLASS_H_
#define _PRINTER_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_PRINTER_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "Device/PrinterClassDevice.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "Host/PrinterClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,81 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB RNDIS Class driver.
*
* Master include file for the library USB RNDIS Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassRNDIS RNDIS (Networking) Class Driver
* \brief USB class driver for the Microsoft Remote Network Driver Interface Specification (RNDIS) class standard.
*
* \section Sec_USBClassRNDIS_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
* - LUFA/Drivers/USB/Class/Host/RNDISClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassRNDIS_ModDescription Module Description
* RNDIS Class Driver module. This module contains an internal implementation of the Microsoft USB RNDIS Networking
* Class, for both Device and Host USB modes. User applications can use this class driver instead of implementing the
* RNDIS class manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Hosts using the USB RNDIS Class.
*
* @{
*/
#ifndef _RNDIS_CLASS_H_
#define _RNDIS_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_RNDIS_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_DEVICE)
#include "Device/RNDISClassDevice.h"
#endif
#if defined(USB_CAN_BE_HOST)
#include "Host/RNDISClassHost.h"
#endif
#endif
/** @} */

View file

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master include file for the library USB Still Image Class driver.
*
* Master include file for the library USB Still Image Class driver, for both host and device modes, where available.
*
* This file should be included in all user projects making use of this optional class driver, instead of
* including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
*/
/** \ingroup Group_USBClassDrivers
* \defgroup Group_USBClassSI Still Image Class Driver
* \brief USB class driver for the USB-IF Still Image (PIMA-compliant) class standard.
*
* \section Sec_USBClassSI_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Host/StillImageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
*
* \section Sec_USBClassSI_ModDescription Module Description
* Still Image Class Driver module. This module contains an internal implementation of the USB Still Image Class,
* for USB Host mode only. User applications can use this class driver instead of implementing the Still Image class
* manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Devices using the USB Still Image Class.
*
* @{
*/
#ifndef _SI_CLASS_H_
#define _SI_CLASS_H_
/* Macros: */
#define __INCLUDE_FROM_USB_DRIVER
#define __INCLUDE_FROM_SI_DRIVER
/* Includes: */
#include "../Core/USBMode.h"
#if defined(USB_CAN_BE_HOST)
#include "Host/StillImageClassHost.h"
#endif
#endif
/** @} */