From eb2e883fd35b5332a7425488105a7adb500ce3fe Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Fri, 18 Nov 2011 06:26:51 +0000 Subject: Added Class, ClassDevice, ClassHost and ClassCommon to the internal class driver source filenames to prevent ambiguities. --- LUFA/DoxygenPages/ChangeLog.txt | 1 + LUFA/DoxygenPages/MigrationInformation.txt | 4 + LUFA/Drivers/USB/Class/Audio.h | 80 --- LUFA/Drivers/USB/Class/AudioClass.h | 80 +++ LUFA/Drivers/USB/Class/CDC.h | 80 --- LUFA/Drivers/USB/Class/CDCClass.h | 80 +++ LUFA/Drivers/USB/Class/Common/Audio.h | 774 --------------------- LUFA/Drivers/USB/Class/Common/AudioClassCommon.h | 774 +++++++++++++++++++++ LUFA/Drivers/USB/Class/Common/CDC.h | 386 ---------- LUFA/Drivers/USB/Class/Common/CDCClassCommon.h | 386 ++++++++++ LUFA/Drivers/USB/Class/Common/HID.h | 656 ----------------- LUFA/Drivers/USB/Class/Common/HIDClassCommon.h | 656 +++++++++++++++++ LUFA/Drivers/USB/Class/Common/HIDParser.h | 2 +- LUFA/Drivers/USB/Class/Common/MIDI.h | 309 -------- LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h | 309 ++++++++ LUFA/Drivers/USB/Class/Common/MassStorage.h | 365 ---------- .../USB/Class/Common/MassStorageClassCommon.h | 365 ++++++++++ LUFA/Drivers/USB/Class/Common/Printer.h | 119 ---- LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h | 119 ++++ LUFA/Drivers/USB/Class/Common/RNDIS.h | 414 ----------- LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h | 414 +++++++++++ LUFA/Drivers/USB/Class/Common/StillImage.h | 161 ----- .../USB/Class/Common/StillImageClassCommon.h | 161 +++++ LUFA/Drivers/USB/Class/Device/Audio.c | 182 ----- LUFA/Drivers/USB/Class/Device/Audio.h | 375 ---------- LUFA/Drivers/USB/Class/Device/AudioClassDevice.c | 182 +++++ LUFA/Drivers/USB/Class/Device/AudioClassDevice.h | 375 ++++++++++ LUFA/Drivers/USB/Class/Device/CDC.c | 361 ---------- LUFA/Drivers/USB/Class/Device/CDC.h | 357 ---------- LUFA/Drivers/USB/Class/Device/CDCClassDevice.c | 361 ++++++++++ LUFA/Drivers/USB/Class/Device/CDCClassDevice.h | 357 ++++++++++ LUFA/Drivers/USB/Class/Device/HID.c | 197 ------ LUFA/Drivers/USB/Class/Device/HID.h | 211 ------ LUFA/Drivers/USB/Class/Device/HIDClassDevice.c | 197 ++++++ LUFA/Drivers/USB/Class/Device/HIDClassDevice.h | 211 ++++++ LUFA/Drivers/USB/Class/Device/MIDI.c | 149 ---- LUFA/Drivers/USB/Class/Device/MIDI.h | 180 ----- LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c | 149 ++++ LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h | 180 +++++ LUFA/Drivers/USB/Class/Device/MassStorage.c | 238 ------- LUFA/Drivers/USB/Class/Device/MassStorage.h | 166 ----- .../USB/Class/Device/MassStorageClassDevice.c | 238 +++++++ .../USB/Class/Device/MassStorageClassDevice.h | 166 +++++ LUFA/Drivers/USB/Class/Device/RNDIS.c | 530 -------------- LUFA/Drivers/USB/Class/Device/RNDIS.h | 211 ------ LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c | 530 ++++++++++++++ LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h | 211 ++++++ LUFA/Drivers/USB/Class/HID.h | 81 --- LUFA/Drivers/USB/Class/HIDClass.h | 81 +++ LUFA/Drivers/USB/Class/Host/Audio.c | 247 ------- LUFA/Drivers/USB/Class/Host/Audio.h | 420 ----------- LUFA/Drivers/USB/Class/Host/AudioClassHost.c | 247 +++++++ LUFA/Drivers/USB/Class/Host/AudioClassHost.h | 420 +++++++++++ LUFA/Drivers/USB/Class/Host/CDC.c | 513 -------------- LUFA/Drivers/USB/Class/Host/CDC.h | 358 ---------- LUFA/Drivers/USB/Class/Host/CDCClassHost.c | 513 ++++++++++++++ LUFA/Drivers/USB/Class/Host/CDCClassHost.h | 358 ++++++++++ LUFA/Drivers/USB/Class/Host/HID.c | 432 ------------ LUFA/Drivers/USB/Class/Host/HID.h | 320 --------- LUFA/Drivers/USB/Class/Host/HIDClassHost.c | 432 ++++++++++++ LUFA/Drivers/USB/Class/Host/HIDClassHost.h | 320 +++++++++ LUFA/Drivers/USB/Class/Host/MIDI.c | 236 ------- LUFA/Drivers/USB/Class/Host/MIDI.h | 196 ------ LUFA/Drivers/USB/Class/Host/MIDIClassHost.c | 236 +++++++ LUFA/Drivers/USB/Class/Host/MIDIClassHost.h | 196 ++++++ LUFA/Drivers/USB/Class/Host/MassStorage.c | 663 ------------------ LUFA/Drivers/USB/Class/Host/MassStorage.h | 341 --------- LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c | 663 ++++++++++++++++++ LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h | 341 +++++++++ LUFA/Drivers/USB/Class/Host/Printer.c | 426 ------------ LUFA/Drivers/USB/Class/Host/Printer.h | 291 -------- LUFA/Drivers/USB/Class/Host/PrinterClassHost.c | 426 ++++++++++++ LUFA/Drivers/USB/Class/Host/PrinterClassHost.h | 291 ++++++++ LUFA/Drivers/USB/Class/Host/RNDIS.c | 512 -------------- LUFA/Drivers/USB/Class/Host/RNDIS.h | 279 -------- LUFA/Drivers/USB/Class/Host/RNDISClassHost.c | 512 ++++++++++++++ LUFA/Drivers/USB/Class/Host/RNDISClassHost.h | 279 ++++++++ LUFA/Drivers/USB/Class/Host/StillImage.c | 472 ------------- LUFA/Drivers/USB/Class/Host/StillImage.h | 326 --------- LUFA/Drivers/USB/Class/Host/StillImageClassHost.c | 472 +++++++++++++ LUFA/Drivers/USB/Class/Host/StillImageClassHost.h | 326 +++++++++ LUFA/Drivers/USB/Class/MIDI.h | 83 --- LUFA/Drivers/USB/Class/MIDIClass.h | 83 +++ LUFA/Drivers/USB/Class/MassStorage.h | 80 --- LUFA/Drivers/USB/Class/MassStorageClass.h | 80 +++ LUFA/Drivers/USB/Class/Printer.h | 77 -- LUFA/Drivers/USB/Class/PrinterClass.h | 77 ++ LUFA/Drivers/USB/Class/RNDIS.h | 80 --- LUFA/Drivers/USB/Class/RNDISClass.h | 80 +++ LUFA/Drivers/USB/Class/StillImage.h | 75 -- LUFA/Drivers/USB/Class/StillImageClass.h | 75 ++ LUFA/Drivers/USB/USB.h | 16 +- LUFA/makefile | 28 +- 93 files changed, 13037 insertions(+), 13032 deletions(-) delete mode 100644 LUFA/Drivers/USB/Class/Audio.h create mode 100644 LUFA/Drivers/USB/Class/AudioClass.h delete mode 100644 LUFA/Drivers/USB/Class/CDC.h create mode 100644 LUFA/Drivers/USB/Class/CDCClass.h delete mode 100644 LUFA/Drivers/USB/Class/Common/Audio.h create mode 100644 LUFA/Drivers/USB/Class/Common/AudioClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Common/CDC.h create mode 100644 LUFA/Drivers/USB/Class/Common/CDCClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Common/HID.h create mode 100644 LUFA/Drivers/USB/Class/Common/HIDClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Common/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Common/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Common/Printer.h create mode 100644 LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Common/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Common/StillImage.h create mode 100644 LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h delete mode 100644 LUFA/Drivers/USB/Class/Device/Audio.c delete mode 100644 LUFA/Drivers/USB/Class/Device/Audio.h create mode 100644 LUFA/Drivers/USB/Class/Device/AudioClassDevice.c create mode 100644 LUFA/Drivers/USB/Class/Device/AudioClassDevice.h delete mode 100644 LUFA/Drivers/USB/Class/Device/CDC.c delete mode 100644 LUFA/Drivers/USB/Class/Device/CDC.h create mode 100644 LUFA/Drivers/USB/Class/Device/CDCClassDevice.c create mode 100644 LUFA/Drivers/USB/Class/Device/CDCClassDevice.h delete mode 100644 LUFA/Drivers/USB/Class/Device/HID.c delete mode 100644 LUFA/Drivers/USB/Class/Device/HID.h create mode 100644 LUFA/Drivers/USB/Class/Device/HIDClassDevice.c create mode 100644 LUFA/Drivers/USB/Class/Device/HIDClassDevice.h delete mode 100644 LUFA/Drivers/USB/Class/Device/MIDI.c delete mode 100644 LUFA/Drivers/USB/Class/Device/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c create mode 100644 LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h delete mode 100644 LUFA/Drivers/USB/Class/Device/MassStorage.c delete mode 100644 LUFA/Drivers/USB/Class/Device/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c create mode 100644 LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h delete mode 100644 LUFA/Drivers/USB/Class/Device/RNDIS.c delete mode 100644 LUFA/Drivers/USB/Class/Device/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c create mode 100644 LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h delete mode 100644 LUFA/Drivers/USB/Class/HID.h create mode 100644 LUFA/Drivers/USB/Class/HIDClass.h delete mode 100644 LUFA/Drivers/USB/Class/Host/Audio.c delete mode 100644 LUFA/Drivers/USB/Class/Host/Audio.h create mode 100644 LUFA/Drivers/USB/Class/Host/AudioClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/AudioClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/Host/CDC.c delete mode 100644 LUFA/Drivers/USB/Class/Host/CDC.h create mode 100644 LUFA/Drivers/USB/Class/Host/CDCClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/CDCClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/Host/HID.c delete mode 100644 LUFA/Drivers/USB/Class/Host/HID.h create mode 100644 LUFA/Drivers/USB/Class/Host/HIDClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/HIDClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/Host/MIDI.c delete mode 100644 LUFA/Drivers/USB/Class/Host/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/Host/MIDIClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/MIDIClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/Host/MassStorage.c delete mode 100644 LUFA/Drivers/USB/Class/Host/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/Host/Printer.c delete mode 100644 LUFA/Drivers/USB/Class/Host/Printer.h create mode 100644 LUFA/Drivers/USB/Class/Host/PrinterClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/PrinterClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/Host/RNDIS.c delete mode 100644 LUFA/Drivers/USB/Class/Host/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/Host/RNDISClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/RNDISClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/Host/StillImage.c delete mode 100644 LUFA/Drivers/USB/Class/Host/StillImage.h create mode 100644 LUFA/Drivers/USB/Class/Host/StillImageClassHost.c create mode 100644 LUFA/Drivers/USB/Class/Host/StillImageClassHost.h delete mode 100644 LUFA/Drivers/USB/Class/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/MIDIClass.h delete mode 100644 LUFA/Drivers/USB/Class/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/MassStorageClass.h delete mode 100644 LUFA/Drivers/USB/Class/Printer.h create mode 100644 LUFA/Drivers/USB/Class/PrinterClass.h delete mode 100644 LUFA/Drivers/USB/Class/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/RNDISClass.h delete mode 100644 LUFA/Drivers/USB/Class/StillImage.h create mode 100644 LUFA/Drivers/USB/Class/StillImageClass.h (limited to 'LUFA') diff --git a/LUFA/DoxygenPages/ChangeLog.txt b/LUFA/DoxygenPages/ChangeLog.txt index 340fa6ba1..00aa13f6a 100644 --- a/LUFA/DoxygenPages/ChangeLog.txt +++ b/LUFA/DoxygenPages/ChangeLog.txt @@ -19,6 +19,7 @@ * - Core: * - When automatic PLL management mode is enabled on the U4 series AVR8 chips, the PLL is now configured for 48MHz and not * a divided 96MHz, to lower power consumption and to keep the system within the datasheet specs for 3.3V operation (thanks to Scott Vitale) + * - Added Class, ClassDevice, ClassHost and ClassCommon to the internal class driver source filenames to prevent ambiguities * - Library Applications: * - None * diff --git a/LUFA/DoxygenPages/MigrationInformation.txt b/LUFA/DoxygenPages/MigrationInformation.txt index de7da5d1b..3fe03349a 100644 --- a/LUFA/DoxygenPages/MigrationInformation.txt +++ b/LUFA/DoxygenPages/MigrationInformation.txt @@ -14,6 +14,10 @@ * USB Core * - The HID_KEYBOARD_MODIFER_* macros in the HID class driver have been corrected to HID_KEYBOARD_MODIFIER_* (note the spelling of "modifier"). * Existing applications should switch over to the correctly spelled macro names. + * - The names of the USB Device and USB Host class driver files have changed; a new "ClassDevice" and "ClassHost" postfix has been added to the + * respective class driver files. Projects referencing the class driver source files by filename rather than the LUFA_SRC_USBCLASS makefile + * variable should append these postfixes to the source file names. Projects including the USB class driver dispatch headers directly should either + * switch to including the main USB driver header instead, or use the updated header filenames. * * \section Sec_Migration111009 Migrating from 110528 to 111009 * Non-USB Library Components diff --git a/LUFA/Drivers/USB/Class/Audio.h b/LUFA/Drivers/USB/Class/Audio.h deleted file mode 100644 index 5d02b4d4a..000000000 --- a/LUFA/Drivers/USB/Class/Audio.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/Audio.h" - #endif - - #if defined(USB_CAN_BE_HOST) - #include "Host/Audio.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/AudioClass.h b/LUFA/Drivers/USB/Class/AudioClass.h new file mode 100644 index 000000000..ff6eb9190 --- /dev/null +++ b/LUFA/Drivers/USB/Class/AudioClass.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/CDC.h b/LUFA/Drivers/USB/Class/CDC.h deleted file mode 100644 index 935291cd2..000000000 --- a/LUFA/Drivers/USB/Class/CDC.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/CDC.h" - #endif - - #if defined(USB_CAN_BE_HOST) - #include "Host/CDC.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/CDCClass.h b/LUFA/Drivers/USB/Class/CDCClass.h new file mode 100644 index 000000000..4e3a06d61 --- /dev/null +++ b/LUFA/Drivers/USB/Class/CDCClass.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/Audio.h b/LUFA/Drivers/USB/Class/Common/Audio.h deleted file mode 100644 index 32a66409b..000000000 --- a/LUFA/Drivers/USB/Class/Common/Audio.h +++ /dev/null @@ -1,774 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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. */ - 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. */ - 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. - * - * \note This descriptor must 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 24bit 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. - * - * \note This descriptor must 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h b/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h new file mode 100644 index 000000000..32a66409b --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h @@ -0,0 +1,774 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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. */ + 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. */ + 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. + * + * \note This descriptor must 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 24bit 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. + * + * \note This descriptor must 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/CDC.h b/LUFA/Drivers/USB/Class/Common/CDC.h deleted file mode 100644 index 45e0c5851..000000000 --- a/LUFA/Drivers/USB/Class/Common/CDC.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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 typedef 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. - */ - } 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. */ - } 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 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h b/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h new file mode 100644 index 000000000..45e0c5851 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h @@ -0,0 +1,386 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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 typedef 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. + */ + } 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. */ + } 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 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/HID.h b/LUFA/Drivers/USB/Class/Common/HID.h deleted file mode 100644 index 95b3484fd..000000000 --- a/LUFA/Drivers/USB/Class/Common/HID.h +++ /dev/null @@ -1,656 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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 KATANA mode is currently set. */ - #define HID_KEYBOARD_LED_KATANA (1 << 3) - //@} - - /** \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_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_POWER 0x66 - #define HID_KEYBOARD_SC_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_MANU 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 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_SISREQ 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_ANDPROPS 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 - //@} - - /** \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 - * { - * intB_t X; // Signed X axis value - * intB_t Y; // Signed Y axis value - * int8_t Z; // Signed Z axis value - * // Additional axis elements here - * uintA_t Buttons; // Pressed buttons bitmask - * } Joystick_Report; - * \endcode - * - * Where \c uintA_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] NumAxis Number of axis in the joystick (8-bit) - * \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(NumAxis, 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_MINIMUM(8, 0x30), \ - HID_RI_USAGE_MAXIMUM(8, (0x30 + (NumAxis - 1))), \ - 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, NumAxis), \ - HID_RI_REPORT_SIZE(8, ((((MinAxisVal >= -0xFF) && (MaxAxisVal <= 0xFF)) ? 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, (8 - (Buttons % 8))), \ - 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 (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, 0x65), \ - HID_RI_USAGE_PAGE(8, 0x07), \ - HID_RI_USAGE_MINIMUM(8, 0x00), \ - HID_RI_USAGE_MAXIMUM(8, 0x65), \ - 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 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, (8 - (Buttons % 8))), \ - 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 >= -0xFF) && (MaxAxisVal <= 0xFF)) ? 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 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. */ - 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. */ - 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h b/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h new file mode 100644 index 000000000..95b3484fd --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h @@ -0,0 +1,656 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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 KATANA mode is currently set. */ + #define HID_KEYBOARD_LED_KATANA (1 << 3) + //@} + + /** \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_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_POWER 0x66 + #define HID_KEYBOARD_SC_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_MANU 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 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_SISREQ 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_ANDPROPS 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 + //@} + + /** \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 + * { + * intB_t X; // Signed X axis value + * intB_t Y; // Signed Y axis value + * int8_t Z; // Signed Z axis value + * // Additional axis elements here + * uintA_t Buttons; // Pressed buttons bitmask + * } Joystick_Report; + * \endcode + * + * Where \c uintA_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] NumAxis Number of axis in the joystick (8-bit) + * \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(NumAxis, 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_MINIMUM(8, 0x30), \ + HID_RI_USAGE_MAXIMUM(8, (0x30 + (NumAxis - 1))), \ + 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, NumAxis), \ + HID_RI_REPORT_SIZE(8, ((((MinAxisVal >= -0xFF) && (MaxAxisVal <= 0xFF)) ? 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, (8 - (Buttons % 8))), \ + 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 (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, 0x65), \ + HID_RI_USAGE_PAGE(8, 0x07), \ + HID_RI_USAGE_MINIMUM(8, 0x00), \ + HID_RI_USAGE_MAXIMUM(8, 0x65), \ + 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 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, (8 - (Buttons % 8))), \ + 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 >= -0xFF) && (MaxAxisVal <= 0xFF)) ? 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 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. */ + 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. */ + 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/HIDParser.h b/LUFA/Drivers/USB/Class/Common/HIDParser.h index e49121332..3e3bb237e 100644 --- a/LUFA/Drivers/USB/Class/Common/HIDParser.h +++ b/LUFA/Drivers/USB/Class/Common/HIDParser.h @@ -70,7 +70,7 @@ #include "../../../../Common/Common.h" #include "HIDReportData.h" - #include "../Common/HID.h" + #include "HIDClassCommon.h" /* Enable C linkage for C++ Compilers: */ #if defined(__cplusplus) diff --git a/LUFA/Drivers/USB/Class/Common/MIDI.h b/LUFA/Drivers/USB/Class/Common/MIDI.h deleted file mode 100644 index a273589e4..000000000 --- a/LUFA/Drivers/USB/Class/Common/MIDI.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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 "Audio.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 */ - //@{ - /** MIDI command for a note on (activation) event. */ - #define MIDI_COMMAND_NOTE_ON 0x90 - - /** MIDI command for a note off (deactivation) event. */ - #define MIDI_COMMAND_NOTE_OFF 0x80 - //@} - - /** 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. - */ - #define MIDI_CHANNEL(channel) ((channel) - 1) - - /* 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. - */ - 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. */ - 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 - { - unsigned Command : 4; /**< Upper nibble of the MIDI command being sent or received in the event packet. */ - unsigned CableNumber : 4; /**< Virtual cable number of the event being sent or received in the given MIDI interface. */ - - 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h b/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h new file mode 100644 index 000000000..725549973 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h @@ -0,0 +1,309 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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 */ + //@{ + /** MIDI command for a note on (activation) event. */ + #define MIDI_COMMAND_NOTE_ON 0x90 + + /** MIDI command for a note off (deactivation) event. */ + #define MIDI_COMMAND_NOTE_OFF 0x80 + //@} + + /** 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. + */ + #define MIDI_CHANNEL(channel) ((channel) - 1) + + /* 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. + */ + 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. */ + 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 + { + unsigned Command : 4; /**< Upper nibble of the MIDI command being sent or received in the event packet. */ + unsigned CableNumber : 4; /**< Virtual cable number of the event being sent or received in the given MIDI interface. */ + + 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/MassStorage.h b/LUFA/Drivers/USB/Class/Common/MassStorage.h deleted file mode 100644 index 49246ba7d..000000000 --- a/LUFA/Drivers/USB/Class/Common/MassStorage.h +++ /dev/null @@ -1,365 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h b/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h new file mode 100644 index 000000000..49246ba7d --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h @@ -0,0 +1,365 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/Printer.h b/LUFA/Drivers/USB/Class/Common/Printer.h deleted file mode 100644 index 3d52be306..000000000 --- a/LUFA/Drivers/USB/Class/Common/Printer.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h b/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h new file mode 100644 index 000000000..3d52be306 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h @@ -0,0 +1,119 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/RNDIS.h b/LUFA/Drivers/USB/Class/Common/RNDIS.h deleted file mode 100644 index f931de826..000000000 --- a/LUFA/Drivers/USB/Class/Common/RNDIS.h +++ /dev/null @@ -1,414 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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 "CDC.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 a RNDIS control message which can be sent or received. */ - #define RNDIS_MESSAGE_BUFFER_SIZE 128 - - /** 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h b/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h new file mode 100644 index 000000000..30840f5a3 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h @@ -0,0 +1,414 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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 a RNDIS control message which can be sent or received. */ + #define RNDIS_MESSAGE_BUFFER_SIZE 128 + + /** 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/StillImage.h b/LUFA/Drivers/USB/Class/Common/StillImage.h deleted file mode 100644 index 4f418ad9e..000000000 --- a/LUFA/Drivers/USB/Class/Common/StillImage.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h b/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h new file mode 100644 index 000000000..4f418ad9e --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h @@ -0,0 +1,161 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Device/Audio.c b/LUFA/Drivers/USB/Class/Device/Audio.c deleted file mode 100644 index cdbe1a0d9..000000000 --- a/LUFA/Drivers/USB/Class/Device/Audio.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_DEVICE) - -#define __INCLUDE_FROM_AUDIO_DRIVER -#define __INCLUDE_FROM_AUDIO_DEVICE_C -#include "Audio.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) - { - if (USB_ControlRequest.wIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber) - return; - } - else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) - { - bool EndpointFilterMatch = false; - - EndpointFilterMatch |= (AudioInterfaceInfo->Config.DataINEndpointNumber && - ((uint8_t)USB_ControlRequest.wIndex == (ENDPOINT_DIR_IN | AudioInterfaceInfo->Config.DataINEndpointNumber))); - - EndpointFilterMatch |= (AudioInterfaceInfo->Config.DataOUTEndpointNumber && - ((uint8_t)USB_ControlRequest.wIndex == (ENDPOINT_DIR_OUT | AudioInterfaceInfo->Config.DataOUTEndpointNumber))); - - if (!(EndpointFilterMatch)) - 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 == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | 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); - } - } - - break; - case AUDIO_REQ_GetCurrent: - case AUDIO_REQ_GetMinimum: - case AUDIO_REQ_GetMaximum: - case AUDIO_REQ_GetResolution: - if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | 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(); - } - } - - break; - } -} - -bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) -{ - memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State)); - - for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Direction; - bool DoubleBanked; - - if (EndpointNum == AudioInterfaceInfo->Config.DataINEndpointNumber) - { - Size = AudioInterfaceInfo->Config.DataINEndpointSize; - Direction = ENDPOINT_DIR_IN; - Type = EP_TYPE_ISOCHRONOUS; - DoubleBanked = true; - } - else if (EndpointNum == AudioInterfaceInfo->Config.DataOUTEndpointNumber) - { - Size = AudioInterfaceInfo->Config.DataOUTEndpointSize; - Direction = ENDPOINT_DIR_OUT; - Type = EP_TYPE_ISOCHRONOUS; - DoubleBanked = true; - } - else - { - continue; - } - - if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, - DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) - { - return false; - } - } - - return true; -} - -void Audio_Device_Event_Stub(void) -{ - -} - -#endif diff --git a/LUFA/Drivers/USB/Class/Device/Audio.h b/LUFA/Drivers/USB/Class/Device/Audio.h deleted file mode 100644 index 60880c29e..000000000 --- a/LUFA/Drivers/USB/Class/Device/Audio.h +++ /dev/null @@ -1,375 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief Device mode driver for the library USB Audio 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/Audio.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 - { - const struct - { - uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this - * structure controls. - */ - - uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming Audio Streaming data, if available - * (zero if unused). - */ - uint16_t DataINEndpointSize; /**< Size in bytes of the incoming Audio Streaming data endpoint, if available - * (zero if unused). - */ - - uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing Audio Streaming data, if available - * (zero if unused). - */ - uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing Audio Streaming data endpoint, if available - * (zero if unused). - */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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 retreived 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 true if the property get/set was successful, 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); - - /** 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.DataOUTEndpointNumber); - return Endpoint_IsOUTReceived(); - } - - /** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects - * the streaming IN endpoint ready for writing. - * - * \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.DataINEndpointNumber); - 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.DataINEndpointSize) - 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.DataINEndpointSize) - 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.DataINEndpointSize) - 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c b/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c new file mode 100644 index 000000000..d8c5d29eb --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c @@ -0,0 +1,182 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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) + { + if (USB_ControlRequest.wIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber) + return; + } + else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT) + { + bool EndpointFilterMatch = false; + + EndpointFilterMatch |= (AudioInterfaceInfo->Config.DataINEndpointNumber && + ((uint8_t)USB_ControlRequest.wIndex == (ENDPOINT_DIR_IN | AudioInterfaceInfo->Config.DataINEndpointNumber))); + + EndpointFilterMatch |= (AudioInterfaceInfo->Config.DataOUTEndpointNumber && + ((uint8_t)USB_ControlRequest.wIndex == (ENDPOINT_DIR_OUT | AudioInterfaceInfo->Config.DataOUTEndpointNumber))); + + if (!(EndpointFilterMatch)) + 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 == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | 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); + } + } + + break; + case AUDIO_REQ_GetCurrent: + case AUDIO_REQ_GetMinimum: + case AUDIO_REQ_GetMaximum: + case AUDIO_REQ_GetResolution: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | 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(); + } + } + + break; + } +} + +bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) +{ + memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State)); + + for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Direction; + bool DoubleBanked; + + if (EndpointNum == AudioInterfaceInfo->Config.DataINEndpointNumber) + { + Size = AudioInterfaceInfo->Config.DataINEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_ISOCHRONOUS; + DoubleBanked = true; + } + else if (EndpointNum == AudioInterfaceInfo->Config.DataOUTEndpointNumber) + { + Size = AudioInterfaceInfo->Config.DataOUTEndpointSize; + Direction = ENDPOINT_DIR_OUT; + Type = EP_TYPE_ISOCHRONOUS; + DoubleBanked = true; + } + else + { + continue; + } + + if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, + DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) + { + return false; + } + } + + return true; +} + +void Audio_Device_Event_Stub(void) +{ + +} + +#endif diff --git a/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h b/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h new file mode 100644 index 000000000..175bc8bf4 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h @@ -0,0 +1,375 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB Audio 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this + * structure controls. + */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming Audio Streaming data, if available + * (zero if unused). + */ + uint16_t DataINEndpointSize; /**< Size in bytes of the incoming Audio Streaming data endpoint, if available + * (zero if unused). + */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing Audio Streaming data, if available + * (zero if unused). + */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing Audio Streaming data endpoint, if available + * (zero if unused). + */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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 retreived 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 true if the property get/set was successful, 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); + + /** 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.DataOUTEndpointNumber); + return Endpoint_IsOUTReceived(); + } + + /** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects + * the streaming IN endpoint ready for writing. + * + * \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.DataINEndpointNumber); + 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.DataINEndpointSize) + 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.DataINEndpointSize) + 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.DataINEndpointSize) + 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c deleted file mode 100644 index 29e5c25eb..000000000 --- a/LUFA/Drivers/USB/Class/Device/CDC.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_DEVICE) - -#define __INCLUDE_FROM_CDC_DRIVER -#define __INCLUDE_FROM_CDC_DEVICE_C -#include "CDC.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())); - - 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)); - - for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Direction; - bool DoubleBanked; - - if (EndpointNum == CDCInterfaceInfo->Config.DataINEndpointNumber) - { - Size = CDCInterfaceInfo->Config.DataINEndpointSize; - Direction = ENDPOINT_DIR_IN; - Type = EP_TYPE_BULK; - DoubleBanked = CDCInterfaceInfo->Config.DataINEndpointDoubleBank; - } - else if (EndpointNum == CDCInterfaceInfo->Config.DataOUTEndpointNumber) - { - Size = CDCInterfaceInfo->Config.DataOUTEndpointSize; - Direction = ENDPOINT_DIR_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank; - } - else if (EndpointNum == CDCInterfaceInfo->Config.NotificationEndpointNumber) - { - Size = CDCInterfaceInfo->Config.NotificationEndpointSize; - Direction = ENDPOINT_DIR_IN; - Type = EP_TYPE_INTERRUPT; - DoubleBanked = CDCInterfaceInfo->Config.NotificationEndpointDoubleBank; - } - else - { - continue; - } - - if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, - DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) - { - 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) - 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.DataINEndpointNumber); - return Endpoint_Write_Stream_LE(String, strlen(String), NULL); -} - -uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, - const char* const Buffer, - const uint16_t Length) -{ - if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) - return ENDPOINT_RWSTREAM_DeviceDisconnected; - - Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); - return Endpoint_Write_Stream_LE(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.DataINEndpointNumber); - - 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.DataINEndpointNumber); - - if (!(Endpoint_BytesInEndpoint())) - return ENDPOINT_READYWAIT_NoError; - - bool BankFull = !(Endpoint_IsReadWriteAllowed()); - - Endpoint_ClearIN(); - - if (BankFull) - { - if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) - return ErrorCode; - - Endpoint_ClearIN(); - } - - return ENDPOINT_READYWAIT_NoError; -} - -uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) -{ - if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) - return 0; - - Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber); - - if (Endpoint_IsOUTReceived()) - { - if (!(Endpoint_BytesInEndpoint())) - { - Endpoint_ClearOUT(); - return 0; - } - else - { - return Endpoint_BytesInEndpoint(); - } - } - else - { - return 0; - } -} - -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.DataOUTEndpointNumber); - - 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.NotificationEndpointNumber); - - 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 - diff --git a/LUFA/Drivers/USB/Class/Device/CDC.h b/LUFA/Drivers/USB/Class/Device/CDC.h deleted file mode 100644 index b1eeb41dc..000000000 --- a/LUFA/Drivers/USB/Class/Device/CDC.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief Device mode driver for the library USB CDC Class driver. - * - * Device mode driver for the library USB CDC Class driver. - * - * \note This file should not be included directly. It is automatically included as needed by the USB module driver - * dispatch header located in LUFA/Drivers/USB.h. - */ - -/** \ingroup Group_USBClassCDC - * \defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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, as each interface will be loaded into a separate driver instance. To - * combat this, you should use the "Interface Association Descriptor" addendum to - * the USB standard which is available on most OSes when creating Composite devices. - * - * Another major oversight is that there is no mechanism for the host to notify the - * device that there is a data sink on the host side ready to accept data. This - * means that the device may try to send data while the host isn't listening, causing - * lengthy blocking timeouts in the transmission routines. To combat this, it is - * recommended that the virtual serial line DTR (Data Terminal Ready) be used where - * possible to determine if a host application is ready for data. - * - * @{ - */ - -#ifndef _CDC_CLASS_DEVICE_H_ -#define _CDC_CLASS_DEVICE_H_ - - /* Includes: */ - #include "../../USB.h" - #include "../Common/CDC.h" - - #include - - /* 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 - { - const struct - { - uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */ - - uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint. */ - uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint. */ - bool DataINEndpointDoubleBank; /**< Indicates if the CDC interface's IN data endpoint should use double banking. */ - - uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint. */ - uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint. */ - bool DataOUTEndpointDoubleBank; /**< Indicates if the CDC interface's OUT data endpoint should use double banking. */ - - uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used. */ - uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used. */ - bool NotificationEndpointDoubleBank; /**< Indicates if the CDC interface's notification endpoint should use double banking. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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 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 State.ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as - * a mask of CDC_CONTROL_LINE_OUT_* masks. - * - * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. - */ - void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); - - /** CDC class driver event for a send break request sent to the device from the host. This is generally used to 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 char* 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 - * 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); - - /** 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 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 stdout if desired to direct the standard output from all 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); - - /* 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c b/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c new file mode 100644 index 000000000..e3b05e037 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c @@ -0,0 +1,361 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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())); + + 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)); + + for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Direction; + bool DoubleBanked; + + if (EndpointNum == CDCInterfaceInfo->Config.DataINEndpointNumber) + { + Size = CDCInterfaceInfo->Config.DataINEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_BULK; + DoubleBanked = CDCInterfaceInfo->Config.DataINEndpointDoubleBank; + } + else if (EndpointNum == CDCInterfaceInfo->Config.DataOUTEndpointNumber) + { + Size = CDCInterfaceInfo->Config.DataOUTEndpointSize; + Direction = ENDPOINT_DIR_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = CDCInterfaceInfo->Config.DataOUTEndpointDoubleBank; + } + else if (EndpointNum == CDCInterfaceInfo->Config.NotificationEndpointNumber) + { + Size = CDCInterfaceInfo->Config.NotificationEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_INTERRUPT; + DoubleBanked = CDCInterfaceInfo->Config.NotificationEndpointDoubleBank; + } + else + { + continue; + } + + if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, + DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) + { + 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) + 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.DataINEndpointNumber); + return Endpoint_Write_Stream_LE(String, strlen(String), NULL); +} + +uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, + const char* const Buffer, + const uint16_t Length) +{ + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) + return ENDPOINT_RWSTREAM_DeviceDisconnected; + + Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); + return Endpoint_Write_Stream_LE(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.DataINEndpointNumber); + + 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.DataINEndpointNumber); + + if (!(Endpoint_BytesInEndpoint())) + return ENDPOINT_READYWAIT_NoError; + + bool BankFull = !(Endpoint_IsReadWriteAllowed()); + + Endpoint_ClearIN(); + + if (BankFull) + { + if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) + return ErrorCode; + + Endpoint_ClearIN(); + } + + return ENDPOINT_READYWAIT_NoError; +} + +uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) +{ + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) + return 0; + + Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber); + + if (Endpoint_IsOUTReceived()) + { + if (!(Endpoint_BytesInEndpoint())) + { + Endpoint_ClearOUT(); + return 0; + } + else + { + return Endpoint_BytesInEndpoint(); + } + } + else + { + return 0; + } +} + +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.DataOUTEndpointNumber); + + 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.NotificationEndpointNumber); + + 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 + diff --git a/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h b/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h new file mode 100644 index 000000000..449b76afd --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h @@ -0,0 +1,357 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB CDC Class driver. + * + * Device mode driver for the library USB CDC Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the USB module driver + * dispatch header located in LUFA/Drivers/USB.h. + */ + +/** \ingroup Group_USBClassCDC + * \defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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, as each interface will be loaded into a separate driver instance. To + * combat this, you should use the "Interface Association Descriptor" addendum to + * the USB standard which is available on most OSes when creating Composite devices. + * + * Another major oversight is that there is no mechanism for the host to notify the + * device that there is a data sink on the host side ready to accept data. This + * means that the device may try to send data while the host isn't listening, causing + * lengthy blocking timeouts in the transmission routines. To combat this, it is + * recommended that the virtual serial line DTR (Data Terminal Ready) be used where + * possible to determine if a host application is ready for data. + * + * @{ + */ + +#ifndef _CDC_CLASS_DEVICE_H_ +#define _CDC_CLASS_DEVICE_H_ + + /* Includes: */ + #include "../../USB.h" + #include "../Common/CDCClassCommon.h" + + #include + + /* 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 + { + const struct + { + uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint. */ + uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint. */ + bool DataINEndpointDoubleBank; /**< Indicates if the CDC interface's IN data endpoint should use double banking. */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint. */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint. */ + bool DataOUTEndpointDoubleBank; /**< Indicates if the CDC interface's OUT data endpoint should use double banking. */ + + uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used. */ + uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used. */ + bool NotificationEndpointDoubleBank; /**< Indicates if the CDC interface's notification endpoint should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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 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 State.ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as + * a mask of CDC_CONTROL_LINE_OUT_* masks. + * + * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. + */ + void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /** CDC class driver event for a send break request sent to the device from the host. This is generally used to 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 char* 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 + * 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); + + /** 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 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 stdout if desired to direct the standard output from all 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); + + /* 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Device/HID.c b/LUFA/Drivers/USB/Class/Device/HID.c deleted file mode 100644 index ec02138ab..000000000 --- a/LUFA/Drivers/USB/Class/Device/HID.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_DEVICE) - -#define __INCLUDE_FROM_HID_DRIVER -#define __INCLUDE_FROM_HID_DEVICE_C -#include "HID.h" - -void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) -{ - if (!(Endpoint_IsSETUPReceived())) - return; - - if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber) - return; - - switch (USB_ControlRequest.bRequest) - { - case 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(); - 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; - - if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber, EP_TYPE_INTERRUPT, - ENDPOINT_DIR_IN, HIDInterfaceInfo->Config.ReportINEndpointSize, - HIDInterfaceInfo->Config.ReportINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) - { - return false; - } - - return true; -} - -void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) -{ - if (USB_DeviceState != DEVICE_STATE_Configured) - return; - - Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber); - - if (Endpoint_IsReadWriteAllowed()) - { - uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize]; - uint8_t ReportID = 0; - uint16_t ReportINSize = 0; - - memset(ReportINData, 0, sizeof(ReportINData)); - - bool ForceSend = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, 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.ReportINEndpointNumber); - - if (ReportID) - Endpoint_Write_8(ReportID); - - Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NULL); - - Endpoint_ClearIN(); - } - } -} - -#endif - diff --git a/LUFA/Drivers/USB/Class/Device/HID.h b/LUFA/Drivers/USB/Class/Device/HID.h deleted file mode 100644 index 52bff7ec9..000000000 --- a/LUFA/Drivers/USB/Class/Device/HID.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief Device mode driver for the library USB HID Class driver. - * - * Device mode driver for the library USB HID Class driver. - * - * \note This file should not be included directly. It is automatically included as needed by the USB module driver - * dispatch header located in LUFA/Drivers/USB.h. - */ - -/** \ingroup Group_USBClassHID - * \defgroup Group_USBClassHIDDevice HID Class Device Mode Driver - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/HID.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 - { - const struct - { - uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device. */ - - uint8_t ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint. */ - uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint. */ - bool ReportINEndpointDoubleBank; /**< Indicates if the HID interface's IN report endpoint should use double banking. */ - - void* PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be - * stored by the driver, for comparison purposes to detect report changes that - * must be sent immediately to the host. This should point to a buffer big enough - * to hold the largest HID input report sent from the HID interface. If this is set - * to \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. \ref 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 - * must be set or the interface will fail to enumerate and operate correctly. - */ - struct - { - bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode. */ - uint16_t IdleCount; /**< Report idle period, in milliseconds, set by the host. */ - uint16_t IdleMSRemaining; /**< Total number of milliseconds remaining before the idle period elapsed - this - * should be decremented by the user application if non-zero each millisecond. */ - } State; /**< State data for the USB class interface within the device. All elements in this section - * are reset to their defaults when the interface is enumerated. - */ - } USB_ClassInfo_HID_Device_t; - - /* Function Prototypes: */ - /** Configures the endpoints of a given HID interface, ready for use. This should be linked to the library - * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration - * containing the given HID interface is selected. - * - * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. - * - * \return Boolean \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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c b/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c new file mode 100644 index 000000000..9b5a7dd35 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c @@ -0,0 +1,197 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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(); + 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; + + if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber, EP_TYPE_INTERRUPT, + ENDPOINT_DIR_IN, HIDInterfaceInfo->Config.ReportINEndpointSize, + HIDInterfaceInfo->Config.ReportINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) + { + return false; + } + + return true; +} + +void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber); + + if (Endpoint_IsReadWriteAllowed()) + { + uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize]; + uint8_t ReportID = 0; + uint16_t ReportINSize = 0; + + memset(ReportINData, 0, sizeof(ReportINData)); + + bool ForceSend = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, 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.ReportINEndpointNumber); + + if (ReportID) + Endpoint_Write_8(ReportID); + + Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NULL); + + Endpoint_ClearIN(); + } + } +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h b/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h new file mode 100644 index 000000000..40aab3902 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h @@ -0,0 +1,211 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB HID Class driver. + * + * Device mode driver for the library USB HID Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the USB module driver + * dispatch header located in LUFA/Drivers/USB.h. + */ + +/** \ingroup Group_USBClassHID + * \defgroup Group_USBClassHIDDevice HID Class Device Mode Driver + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device. */ + + uint8_t ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint. */ + uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint. */ + bool ReportINEndpointDoubleBank; /**< Indicates if the HID interface's IN report endpoint should use double banking. */ + + void* PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be + * stored by the driver, for comparison purposes to detect report changes that + * must be sent immediately to the host. This should point to a buffer big enough + * to hold the largest HID input report sent from the HID interface. If this is set + * to \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. \ref 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 + * must be set or the interface will fail to enumerate and operate correctly. + */ + struct + { + bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode. */ + uint16_t IdleCount; /**< Report idle period, in milliseconds, set by the host. */ + uint16_t IdleMSRemaining; /**< Total number of milliseconds remaining before the idle period elapsed - this + * should be decremented by the user application if non-zero each millisecond. */ + } State; /**< State data for the USB class interface within the device. All elements in this section + * are reset to their defaults when the interface is enumerated. + */ + } USB_ClassInfo_HID_Device_t; + + /* Function Prototypes: */ + /** Configures the endpoints of a given HID interface, ready for use. This should be linked to the library + * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration + * containing the given HID interface is selected. + * + * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. + * + * \return Boolean \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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Device/MIDI.c b/LUFA/Drivers/USB/Class/Device/MIDI.c deleted file mode 100644 index 5e4bd9c2d..000000000 --- a/LUFA/Drivers/USB/Class/Device/MIDI.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_DEVICE) - -#define __INCLUDE_FROM_MIDI_DRIVER -#define __INCLUDE_FROM_MIDI_DEVICE_C -#include "MIDI.h" - -bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) -{ - memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State)); - - for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Direction; - bool DoubleBanked; - - if (EndpointNum == MIDIInterfaceInfo->Config.DataINEndpointNumber) - { - Size = MIDIInterfaceInfo->Config.DataINEndpointSize; - Direction = ENDPOINT_DIR_IN; - Type = EP_TYPE_BULK; - DoubleBanked = MIDIInterfaceInfo->Config.DataINEndpointDoubleBank; - } - else if (EndpointNum == MIDIInterfaceInfo->Config.DataOUTEndpointNumber) - { - Size = MIDIInterfaceInfo->Config.DataOUTEndpointSize; - Direction = ENDPOINT_DIR_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = MIDIInterfaceInfo->Config.DataOUTEndpointDoubleBank; - } - else - { - continue; - } - - if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, - DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) - { - 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) - 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.DataINEndpointNumber); - - 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.DataINEndpointNumber); - - if (Endpoint_BytesInEndpoint()) - { - Endpoint_ClearIN(); - - if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) - return ErrorCode; - } - - return ENDPOINT_READYWAIT_NoError; -} - -bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, - MIDI_EventPacket_t* const Event) -{ - if (USB_DeviceState != DEVICE_STATE_Configured) - return false; - - Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber); - - if (!(Endpoint_IsReadWriteAllowed())) - return false; - - Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); - - if (!(Endpoint_IsReadWriteAllowed())) - Endpoint_ClearOUT(); - - return true; -} - -#endif - diff --git a/LUFA/Drivers/USB/Class/Device/MIDI.h b/LUFA/Drivers/USB/Class/Device/MIDI.h deleted file mode 100644 index 45a756157..000000000 --- a/LUFA/Drivers/USB/Class/Device/MIDI.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief Device mode driver for the library USB MIDI Class driver. - * - * Device mode driver for the library USB MIDI Class driver. - * - * \note This file should not be included directly. It is automatically included as needed by the USB module driver - * dispatch header located in LUFA/Drivers/USB.h. - */ - -/** \ingroup Group_USBClassMIDI - * \defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/MIDI.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 - { - const struct - { - uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls. */ - - uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming MIDI IN data, if available (zero if unused). */ - uint16_t DataINEndpointSize; /**< Size in bytes of the incoming MIDI IN data endpoint, if available (zero if unused). */ - bool DataINEndpointDoubleBank; /**< Indicates if the MIDI interface's IN data endpoint should use double banking. */ - - uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing MIDI OUT data, if available (zero if unused). */ - uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing MIDI OUT data endpoint, if available (zero if unused). */ - bool DataOUTEndpointDoubleBank; /**< Indicates if the MIDI interface's OUT data endpoint should use double banking. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must be set or the interface will fail to enumerate and operate correctly. - */ - - struct - { - // 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 behaviour, to flush queued events. - * - * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. - * - * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. - */ - uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c b/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c new file mode 100644 index 000000000..13454592b --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c @@ -0,0 +1,149 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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)); + + for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Direction; + bool DoubleBanked; + + if (EndpointNum == MIDIInterfaceInfo->Config.DataINEndpointNumber) + { + Size = MIDIInterfaceInfo->Config.DataINEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_BULK; + DoubleBanked = MIDIInterfaceInfo->Config.DataINEndpointDoubleBank; + } + else if (EndpointNum == MIDIInterfaceInfo->Config.DataOUTEndpointNumber) + { + Size = MIDIInterfaceInfo->Config.DataOUTEndpointSize; + Direction = ENDPOINT_DIR_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = MIDIInterfaceInfo->Config.DataOUTEndpointDoubleBank; + } + else + { + continue; + } + + if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, + DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) + { + 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) + 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.DataINEndpointNumber); + + 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.DataINEndpointNumber); + + if (Endpoint_BytesInEndpoint()) + { + Endpoint_ClearIN(); + + if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) + return ErrorCode; + } + + return ENDPOINT_READYWAIT_NoError; +} + +bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, + MIDI_EventPacket_t* const Event) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return false; + + Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber); + + if (!(Endpoint_IsReadWriteAllowed())) + return false; + + Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); + + if (!(Endpoint_IsReadWriteAllowed())) + Endpoint_ClearOUT(); + + return true; +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h b/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h new file mode 100644 index 000000000..c73ce43bf --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h @@ -0,0 +1,180 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB MIDI Class driver. + * + * Device mode driver for the library USB MIDI Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the USB module driver + * dispatch header located in LUFA/Drivers/USB.h. + */ + +/** \ingroup Group_USBClassMIDI + * \defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls. */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming MIDI IN data, if available (zero if unused). */ + uint16_t DataINEndpointSize; /**< Size in bytes of the incoming MIDI IN data endpoint, if available (zero if unused). */ + bool DataINEndpointDoubleBank; /**< Indicates if the MIDI interface's IN data endpoint should use double banking. */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing MIDI OUT data, if available (zero if unused). */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing MIDI OUT data endpoint, if available (zero if unused). */ + bool DataOUTEndpointDoubleBank; /**< Indicates if the MIDI interface's OUT data endpoint should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must be set or the interface will fail to enumerate and operate correctly. + */ + + struct + { + // 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 behaviour, to flush queued events. + * + * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. + * + * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. + */ + uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Device/MassStorage.c b/LUFA/Drivers/USB/Class/Device/MassStorage.c deleted file mode 100644 index 7586c2812..000000000 --- a/LUFA/Drivers/USB/Class/Device/MassStorage.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_DEVICE) - -#define __INCLUDE_FROM_MS_DRIVER -#define __INCLUDE_FROM_MASSSTORAGE_DEVICE_C -#include "MassStorage.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)); - - for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Direction; - bool DoubleBanked; - - if (EndpointNum == MSInterfaceInfo->Config.DataINEndpointNumber) - { - Size = MSInterfaceInfo->Config.DataINEndpointSize; - Direction = ENDPOINT_DIR_IN; - Type = EP_TYPE_BULK; - DoubleBanked = MSInterfaceInfo->Config.DataINEndpointDoubleBank; - } - else if (EndpointNum == MSInterfaceInfo->Config.DataOUTEndpointNumber) - { - Size = MSInterfaceInfo->Config.DataOUTEndpointSize; - Direction = ENDPOINT_DIR_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = MSInterfaceInfo->Config.DataOUTEndpointDoubleBank; - } - else - { - continue; - } - - if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, - DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) - { - return false; - } - } - - return true; -} - -void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) -{ - if (USB_DeviceState != DEVICE_STATE_Configured) - return; - - Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); - - if (Endpoint_IsReadWriteAllowed()) - { - if (MS_Device_ReadInCommandBlock(MSInterfaceInfo)) - { - if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN) - Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); - - 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.DataOUTEndpointNumber); - Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); - - Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); - Endpoint_ClearStall(); - Endpoint_ResetDataToggle(); - Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); - Endpoint_ClearStall(); - Endpoint_ResetDataToggle(); - - MSInterfaceInfo->State.IsMassStoreReset = false; - } -} - -static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) -{ - uint16_t BytesProcessed; - - Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); - - 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.DataINEndpointNumber); - 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.DataOUTEndpointNumber); - - while (Endpoint_IsStalled()) - { - #if !defined(INTERRUPT_CONTROL_ENDPOINT) - USB_USBTask(); - #endif - - if (MSInterfaceInfo->State.IsMassStoreReset) - return; - } - - Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); - - while (Endpoint_IsStalled()) - { - #if !defined(INTERRUPT_CONTROL_ENDPOINT) - USB_USBTask(); - #endif - - if (MSInterfaceInfo->State.IsMassStoreReset) - return; - } - - 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 diff --git a/LUFA/Drivers/USB/Class/Device/MassStorage.h b/LUFA/Drivers/USB/Class/Device/MassStorage.h deleted file mode 100644 index 6f0539e54..000000000 --- a/LUFA/Drivers/USB/Class/Device/MassStorage.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief Device mode driver for the library USB Mass Storage Class driver. - * - * Device mode driver for the library USB Mass Storage Class driver. - * - * \note This file should not be included directly. It is automatically included as needed by the 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/MassStorage.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 - { - const struct - { - uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device. */ - - uint8_t DataINEndpointNumber; /**< Endpoint number of the Mass Storage interface's IN data endpoint. */ - uint16_t DataINEndpointSize; /**< Size in bytes of the Mass Storage interface's IN data endpoint. */ - bool DataINEndpointDoubleBank; /**< Indicates if the Mass Storage interface's IN data endpoint should use double banking. */ - - uint8_t DataOUTEndpointNumber; /**< Endpoint number of the Mass Storage interface's OUT data endpoint. */ - uint16_t DataOUTEndpointSize; /**< Size in bytes of the Mass Storage interface's OUT data endpoint. */ - bool DataOUTEndpointDoubleBank; /**< Indicates if the Mass Storage interface's OUT data endpoint should use double banking. */ - - uint8_t TotalLUNs; /**< Total number of logical drives in the Mass Storage interface. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c b/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c new file mode 100644 index 000000000..1e3fe3412 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c @@ -0,0 +1,238 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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)); + + for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Direction; + bool DoubleBanked; + + if (EndpointNum == MSInterfaceInfo->Config.DataINEndpointNumber) + { + Size = MSInterfaceInfo->Config.DataINEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_BULK; + DoubleBanked = MSInterfaceInfo->Config.DataINEndpointDoubleBank; + } + else if (EndpointNum == MSInterfaceInfo->Config.DataOUTEndpointNumber) + { + Size = MSInterfaceInfo->Config.DataOUTEndpointSize; + Direction = ENDPOINT_DIR_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = MSInterfaceInfo->Config.DataOUTEndpointDoubleBank; + } + else + { + continue; + } + + if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, + DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) + { + return false; + } + } + + return true; +} + +void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); + + if (Endpoint_IsReadWriteAllowed()) + { + if (MS_Device_ReadInCommandBlock(MSInterfaceInfo)) + { + if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN) + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); + + 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.DataOUTEndpointNumber); + Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); + + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); + Endpoint_ClearStall(); + Endpoint_ResetDataToggle(); + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); + Endpoint_ClearStall(); + Endpoint_ResetDataToggle(); + + MSInterfaceInfo->State.IsMassStoreReset = false; + } +} + +static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +{ + uint16_t BytesProcessed; + + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); + + 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.DataINEndpointNumber); + 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.DataOUTEndpointNumber); + + while (Endpoint_IsStalled()) + { + #if !defined(INTERRUPT_CONTROL_ENDPOINT) + USB_USBTask(); + #endif + + if (MSInterfaceInfo->State.IsMassStoreReset) + return; + } + + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); + + while (Endpoint_IsStalled()) + { + #if !defined(INTERRUPT_CONTROL_ENDPOINT) + USB_USBTask(); + #endif + + if (MSInterfaceInfo->State.IsMassStoreReset) + return; + } + + 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 diff --git a/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h b/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h new file mode 100644 index 000000000..ce0bcb787 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h @@ -0,0 +1,166 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB Mass Storage Class driver. + * + * Device mode driver for the library USB Mass Storage Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device. */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the Mass Storage interface's IN data endpoint. */ + uint16_t DataINEndpointSize; /**< Size in bytes of the Mass Storage interface's IN data endpoint. */ + bool DataINEndpointDoubleBank; /**< Indicates if the Mass Storage interface's IN data endpoint should use double banking. */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the Mass Storage interface's OUT data endpoint. */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the Mass Storage interface's OUT data endpoint. */ + bool DataOUTEndpointDoubleBank; /**< Indicates if the Mass Storage interface's OUT data endpoint should use double banking. */ + + uint8_t TotalLUNs; /**< Total number of logical drives in the Mass Storage interface. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.c b/LUFA/Drivers/USB/Class/Device/RNDIS.c deleted file mode 100644 index 9a89ae077..000000000 --- a/LUFA/Drivers/USB/Class/Device/RNDIS.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_DEVICE) - -#define __INCLUDE_FROM_RNDIS_DRIVER -#define __INCLUDE_FROM_RNDIS_DEVICE_C -#include "RNDIS.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->State.RNDISMessageBuffer, 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->State.RNDISMessageBuffer; - - if (!(MessageHeader->MessageLength)) - { - RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0; - MessageHeader->MessageLength = CPU_TO_LE32(1); - } - - Endpoint_ClearSETUP(); - Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, 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)); - - for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Direction; - bool DoubleBanked; - - if (EndpointNum == RNDISInterfaceInfo->Config.DataINEndpointNumber) - { - Size = RNDISInterfaceInfo->Config.DataINEndpointSize; - Direction = ENDPOINT_DIR_IN; - Type = EP_TYPE_BULK; - DoubleBanked = RNDISInterfaceInfo->Config.DataINEndpointDoubleBank; - } - else if (EndpointNum == RNDISInterfaceInfo->Config.DataOUTEndpointNumber) - { - Size = RNDISInterfaceInfo->Config.DataOUTEndpointSize; - Direction = ENDPOINT_DIR_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = RNDISInterfaceInfo->Config.DataOUTEndpointDoubleBank; - } - else if (EndpointNum == RNDISInterfaceInfo->Config.NotificationEndpointNumber) - { - Size = RNDISInterfaceInfo->Config.NotificationEndpointSize; - Direction = ENDPOINT_DIR_IN; - Type = EP_TYPE_INTERRUPT; - DoubleBanked = RNDISInterfaceInfo->Config.NotificationEndpointDoubleBank; - } - else - { - continue; - } - - if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, - DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) - { - return false; - } - } - - return true; -} - -void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) -{ - if (USB_DeviceState != DEVICE_STATE_Configured) - return; - - Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber); - - if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady) - { - USB_Request_Header_t Notification = (USB_Request_Header_t) - { - .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), - .bRequest = 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->State.RNDISMessageBuffer; - - 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->State.RNDISMessageBuffer; - RNDIS_Initialize_Complete_t* INITIALIZE_Response = - (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - - 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->State.RNDISMessageBuffer; - RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid); - - void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + - le32_to_cpu(QUERY_Message->InformationBufferOffset)]; - void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; - RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - 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->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; - - 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->State.RNDISMessageBuffer; - RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = - (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - - 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(RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX); - - return true; - default: - return false; - } -} - -static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, - const uint32_t OId, - 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 = le32_to_cpu((RNDISInterfaceInfo->State.CurrPacketFilter) ? - RNDIS_Data_Initialized : RNDIS_Data_Initialized); - - return true; - case OID_802_3_MULTICAST_LIST: - /* Do nothing - throw away the value from the host as it is unused */ - - return true; - default: - return false; - } -} - -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.DataOUTEndpointNumber); - 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.DataOUTEndpointNumber); - - *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.DataINEndpointNumber); - - 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 - diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.h b/LUFA/Drivers/USB/Class/Device/RNDIS.h deleted file mode 100644 index a3b45cbc5..000000000 --- a/LUFA/Drivers/USB/Class/Device/RNDIS.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief Device mode driver for the library USB RNDIS Class driver. - * - * Device mode driver for the library USB RNDIS Class driver. - * - * \note This file should not be included directly. It is automatically included as needed by the USB module driver - * dispatch header located in LUFA/Drivers/USB.h. - */ - -/** \ingroup Group_USBClassRNDIS - * \defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/RNDIS.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 - { - const struct - { - uint8_t ControlInterfaceNumber; /**< Interface number of the RNDIS control interface within the device. */ - - uint8_t DataINEndpointNumber; /**< Endpoint number of the RNDIS interface's IN data endpoint. */ - uint16_t DataINEndpointSize; /**< Size in bytes of the RNDIS interface's IN data endpoint. */ - bool DataINEndpointDoubleBank; /**< Indicates if the RNDIS interface's IN data endpoint should use double banking. */ - - uint8_t DataOUTEndpointNumber; /**< Endpoint number of the RNDIS interface's OUT data endpoint. */ - uint16_t DataOUTEndpointSize; /**< Size in bytes of the RNDIS interface's OUT data endpoint. */ - bool DataOUTEndpointDoubleBank; /**< Indicates if the RNDIS interface's OUT data endpoint should use double banking. */ - - uint8_t NotificationEndpointNumber; /**< Endpoint number of the RNDIS interface's IN notification endpoint, if used. */ - uint16_t NotificationEndpointSize; /**< Size in bytes of the RNDIS interface's IN notification endpoint, if used. */ - bool NotificationEndpointDoubleBank; /**< Indicates if the RNDIS interface's notification endpoint should use double banking. */ - - char* AdapterVendorDescription; /**< String description of the adapter vendor. */ - MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must be set or the interface will fail to enumerate and operate correctly. - */ - struct - { - uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE]; /**< Buffer to hold RNDIS messages to and from the host, - * managed by the class driver. - */ - bool ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host. */ - uint8_t CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the \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); - - /** 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); - - /** 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); - - /* Private Interface - For use in library only: */ - #if !defined(__DOXYGEN__) - /* 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c b/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c new file mode 100644 index 000000000..12115ee5e --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c @@ -0,0 +1,530 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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->State.RNDISMessageBuffer, 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->State.RNDISMessageBuffer; + + if (!(MessageHeader->MessageLength)) + { + RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0; + MessageHeader->MessageLength = CPU_TO_LE32(1); + } + + Endpoint_ClearSETUP(); + Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, 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)); + + for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Direction; + bool DoubleBanked; + + if (EndpointNum == RNDISInterfaceInfo->Config.DataINEndpointNumber) + { + Size = RNDISInterfaceInfo->Config.DataINEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_BULK; + DoubleBanked = RNDISInterfaceInfo->Config.DataINEndpointDoubleBank; + } + else if (EndpointNum == RNDISInterfaceInfo->Config.DataOUTEndpointNumber) + { + Size = RNDISInterfaceInfo->Config.DataOUTEndpointSize; + Direction = ENDPOINT_DIR_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = RNDISInterfaceInfo->Config.DataOUTEndpointDoubleBank; + } + else if (EndpointNum == RNDISInterfaceInfo->Config.NotificationEndpointNumber) + { + Size = RNDISInterfaceInfo->Config.NotificationEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_INTERRUPT; + DoubleBanked = RNDISInterfaceInfo->Config.NotificationEndpointDoubleBank; + } + else + { + continue; + } + + if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, + DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) + { + return false; + } + } + + return true; +} + +void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber); + + if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady) + { + USB_Request_Header_t Notification = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), + .bRequest = 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->State.RNDISMessageBuffer; + + 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->State.RNDISMessageBuffer; + RNDIS_Initialize_Complete_t* INITIALIZE_Response = + (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + 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->State.RNDISMessageBuffer; + RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid); + + void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + + le32_to_cpu(QUERY_Message->InformationBufferOffset)]; + void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; + RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + 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->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; + + 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->State.RNDISMessageBuffer; + RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = + (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + 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(RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX); + + return true; + default: + return false; + } +} + +static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, + const uint32_t OId, + 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 = le32_to_cpu((RNDISInterfaceInfo->State.CurrPacketFilter) ? + RNDIS_Data_Initialized : RNDIS_Data_Initialized); + + return true; + case OID_802_3_MULTICAST_LIST: + /* Do nothing - throw away the value from the host as it is unused */ + + return true; + default: + return false; + } +} + +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.DataOUTEndpointNumber); + 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.DataOUTEndpointNumber); + + *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.DataINEndpointNumber); + + 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 + diff --git a/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h b/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h new file mode 100644 index 000000000..9953fa1a3 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h @@ -0,0 +1,211 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB RNDIS Class driver. + * + * Device mode driver for the library USB RNDIS Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the USB module driver + * dispatch header located in LUFA/Drivers/USB.h. + */ + +/** \ingroup Group_USBClassRNDIS + * \defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t ControlInterfaceNumber; /**< Interface number of the RNDIS control interface within the device. */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the RNDIS interface's IN data endpoint. */ + uint16_t DataINEndpointSize; /**< Size in bytes of the RNDIS interface's IN data endpoint. */ + bool DataINEndpointDoubleBank; /**< Indicates if the RNDIS interface's IN data endpoint should use double banking. */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the RNDIS interface's OUT data endpoint. */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the RNDIS interface's OUT data endpoint. */ + bool DataOUTEndpointDoubleBank; /**< Indicates if the RNDIS interface's OUT data endpoint should use double banking. */ + + uint8_t NotificationEndpointNumber; /**< Endpoint number of the RNDIS interface's IN notification endpoint, if used. */ + uint16_t NotificationEndpointSize; /**< Size in bytes of the RNDIS interface's IN notification endpoint, if used. */ + bool NotificationEndpointDoubleBank; /**< Indicates if the RNDIS interface's notification endpoint should use double banking. */ + + char* AdapterVendorDescription; /**< String description of the adapter vendor. */ + MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must be set or the interface will fail to enumerate and operate correctly. + */ + struct + { + uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE]; /**< Buffer to hold RNDIS messages to and from the host, + * managed by the class driver. + */ + bool ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host. */ + uint8_t CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the \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); + + /** 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); + + /** 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); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/HID.h b/LUFA/Drivers/USB/Class/HID.h deleted file mode 100644 index f72d47b8e..000000000 --- a/LUFA/Drivers/USB/Class/HID.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/HIDParser.c (Makefile source module name: LUFA_SRC_USB) - * - * \section Sec_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/HID.h" - #endif - - #if defined(USB_CAN_BE_HOST) - #include "Host/HID.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/HIDClass.h b/LUFA/Drivers/USB/Class/HIDClass.h new file mode 100644 index 000000000..71a9b2ea4 --- /dev/null +++ b/LUFA/Drivers/USB/Class/HIDClass.h @@ -0,0 +1,81 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/HIDParser.c (Makefile source module name: LUFA_SRC_USB) + * + * \section Sec_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/Audio.c b/LUFA/Drivers/USB/Class/Host/Audio.c deleted file mode 100644 index d8665e4ea..000000000 --- a/LUFA/Drivers/USB/Class/Host/Audio.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_AUDIO_DRIVER -#define __INCLUDE_FROM_AUDIO_HOST_C -#include "Audio.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.DataINPipeNumber && !(DataINEndpoint)) || - (AudioInterfaceInfo->Config.DataOUTPipeNumber && !(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; - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - bool DoubleBanked; - - if (PipeNum == AudioInterfaceInfo->Config.DataINPipeNumber) - { - Size = le16_to_cpu(DataINEndpoint->EndpointSize); - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_ISOCHRONOUS; - DoubleBanked = true; - - AudioInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == AudioInterfaceInfo->Config.DataOUTPipeNumber) - { - Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_ISOCHRONOUS; - DoubleBanked = true; - - AudioInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - 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 - diff --git a/LUFA/Drivers/USB/Class/Host/Audio.h b/LUFA/Drivers/USB/Class/Host/Audio.h deleted file mode 100644 index 310d21c08..000000000 --- a/LUFA/Drivers/USB/Class/Host/Audio.h +++ /dev/null @@ -1,420 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/Audio.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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the Audio interface's IN data pipe. If this interface should not - * bind to an IN endpoint, this may be set to 0 to disable audio input streaming for - * this driver instance. - */ - uint8_t DataOUTPipeNumber; /**< Pipe number of the Audio interface's OUT data pipe. If this interface should not - * bind to an OUT endpoint, this may be set to 0 to disable audio output streaming for - * this driver instance. - */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the Audio interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the Audio interface's OUT data pipe. */ - } State; /**< State data for the USB class interface within the device. All elements in this section - * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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, 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.DataINPipeNumber); - 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.DataOUTPipeNumber); - 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/AudioClassHost.c b/LUFA/Drivers/USB/Class/Host/AudioClassHost.c new file mode 100644 index 000000000..af6f0ec53 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/AudioClassHost.c @@ -0,0 +1,247 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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.DataINPipeNumber && !(DataINEndpoint)) || + (AudioInterfaceInfo->Config.DataOUTPipeNumber && !(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; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + bool DoubleBanked; + + if (PipeNum == AudioInterfaceInfo->Config.DataINPipeNumber) + { + Size = le16_to_cpu(DataINEndpoint->EndpointSize); + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_ISOCHRONOUS; + DoubleBanked = true; + + AudioInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == AudioInterfaceInfo->Config.DataOUTPipeNumber) + { + Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_ISOCHRONOUS; + DoubleBanked = true; + + AudioInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + 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 + diff --git a/LUFA/Drivers/USB/Class/Host/AudioClassHost.h b/LUFA/Drivers/USB/Class/Host/AudioClassHost.h new file mode 100644 index 000000000..8be5210c2 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/AudioClassHost.h @@ -0,0 +1,420 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/Audio.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the Audio interface's IN data pipe. If this interface should not + * bind to an IN endpoint, this may be set to 0 to disable audio input streaming for + * this driver instance. + */ + uint8_t DataOUTPipeNumber; /**< Pipe number of the Audio interface's OUT data pipe. If this interface should not + * bind to an OUT endpoint, this may be set to 0 to disable audio output streaming for + * this driver instance. + */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the Audio interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the Audio interface's OUT data pipe. */ + } State; /**< State data for the USB class interface within the device. All elements in this section + * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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, 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.DataINPipeNumber); + 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.DataOUTPipeNumber); + 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/CDC.c b/LUFA/Drivers/USB/Class/Host/CDC.c deleted file mode 100644 index 2b9835996..000000000 --- a/LUFA/Drivers/USB/Class/Host/CDC.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_CDC_DRIVER -#define __INCLUDE_FROM_CDC_HOST_C -#include "CDC.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; - } - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - uint8_t InterruptPeriod; - bool DoubleBanked; - - if (PipeNum == CDCInterfaceInfo->Config.DataINPipeNumber) - { - Size = le16_to_cpu(DataINEndpoint->EndpointSize); - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_BULK; - DoubleBanked = CDCInterfaceInfo->Config.DataINPipeDoubleBank; - InterruptPeriod = 0; - - CDCInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == CDCInterfaceInfo->Config.DataOUTPipeNumber) - { - Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = CDCInterfaceInfo->Config.DataOUTPipeDoubleBank; - InterruptPeriod = 0; - - CDCInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - } - else if (PipeNum == CDCInterfaceInfo->Config.NotificationPipeNumber) - { - Size = le16_to_cpu(NotificationEndpoint->EndpointSize); - EndpointAddress = NotificationEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_INTERRUPT; - DoubleBanked = CDCInterfaceInfo->Config.NotificationPipeDoubleBank; - InterruptPeriod = NotificationEndpoint->PollingIntervalMS; - - CDCInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - return CDC_ENUMERROR_PipeConfigurationFailed; - } - - if (InterruptPeriod) - Pipe_SetInterruptPeriod(InterruptPeriod); - } - - 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.NotificationPipeNumber); - 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 uint8_t* 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.DataOUTPipeNumber); - - 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.DataOUTPipeNumber); - - 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.DataOUTPipeNumber); - 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.DataINPipeNumber); - 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.DataINPipeNumber); - 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.DataOUTPipeNumber); - 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 - diff --git a/LUFA/Drivers/USB/Class/Host/CDC.h b/LUFA/Drivers/USB/Class/Host/CDC.h deleted file mode 100644 index 7fd9e49f4..000000000 --- a/LUFA/Drivers/USB/Class/Host/CDC.h +++ /dev/null @@ -1,358 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/CDC.h" - - #include - - /* 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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the CDC interface's IN data pipe. */ - bool DataINPipeDoubleBank; /**< Indicates if the CDC interface's IN data pipe should use double banking. */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the CDC interface's OUT data pipe. */ - bool DataOUTPipeDoubleBank; /**< Indicates if the CDC interface's OUT data pipe should use double banking. */ - - uint8_t NotificationPipeNumber; /**< Pipe number of the CDC interface's IN notification endpoint, if used. */ - bool NotificationPipeDoubleBank; /**< Indicates if the CDC interface's notification pipe should use double banking. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the CDC interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the CDC interface's OUT data pipe. */ - uint16_t NotificationPipeSize; /**< Size in bytes of the CDC interface's IN notification pipe, if used. */ - - 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 - * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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 uint8_t* const Buffer, - const uint16_t Length); - - /** 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); - - /** 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 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 stdout if desired to direct the standard output from all \c 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); - - /** 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); - - /** 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 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/CDCClassHost.c b/LUFA/Drivers/USB/Class/Host/CDCClassHost.c new file mode 100644 index 000000000..184406643 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/CDCClassHost.c @@ -0,0 +1,513 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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; + } + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + uint8_t InterruptPeriod; + bool DoubleBanked; + + if (PipeNum == CDCInterfaceInfo->Config.DataINPipeNumber) + { + Size = le16_to_cpu(DataINEndpoint->EndpointSize); + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_BULK; + DoubleBanked = CDCInterfaceInfo->Config.DataINPipeDoubleBank; + InterruptPeriod = 0; + + CDCInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == CDCInterfaceInfo->Config.DataOUTPipeNumber) + { + Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = CDCInterfaceInfo->Config.DataOUTPipeDoubleBank; + InterruptPeriod = 0; + + CDCInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else if (PipeNum == CDCInterfaceInfo->Config.NotificationPipeNumber) + { + Size = le16_to_cpu(NotificationEndpoint->EndpointSize); + EndpointAddress = NotificationEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_INTERRUPT; + DoubleBanked = CDCInterfaceInfo->Config.NotificationPipeDoubleBank; + InterruptPeriod = NotificationEndpoint->PollingIntervalMS; + + CDCInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + return CDC_ENUMERROR_PipeConfigurationFailed; + } + + if (InterruptPeriod) + Pipe_SetInterruptPeriod(InterruptPeriod); + } + + 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.NotificationPipeNumber); + 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 uint8_t* 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.DataOUTPipeNumber); + + 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.DataOUTPipeNumber); + + 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.DataOUTPipeNumber); + 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.DataINPipeNumber); + 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.DataINPipeNumber); + 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.DataOUTPipeNumber); + 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 + diff --git a/LUFA/Drivers/USB/Class/Host/CDCClassHost.h b/LUFA/Drivers/USB/Class/Host/CDCClassHost.h new file mode 100644 index 000000000..4de504380 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/CDCClassHost.h @@ -0,0 +1,358 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/CDC.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + + /* 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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the CDC interface's IN data pipe. */ + bool DataINPipeDoubleBank; /**< Indicates if the CDC interface's IN data pipe should use double banking. */ + + uint8_t DataOUTPipeNumber; /**< Pipe number of the CDC interface's OUT data pipe. */ + bool DataOUTPipeDoubleBank; /**< Indicates if the CDC interface's OUT data pipe should use double banking. */ + + uint8_t NotificationPipeNumber; /**< Pipe number of the CDC interface's IN notification endpoint, if used. */ + bool NotificationPipeDoubleBank; /**< Indicates if the CDC interface's notification pipe should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the CDC interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the CDC interface's OUT data pipe. */ + uint16_t NotificationPipeSize; /**< Size in bytes of the CDC interface's IN notification pipe, if used. */ + + 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 + * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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 uint8_t* const Buffer, + const uint16_t Length); + + /** 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); + + /** 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 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 stdout if desired to direct the standard output from all \c 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); + + /** 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); + + /** 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 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/HID.c b/LUFA/Drivers/USB/Class/Host/HID.c deleted file mode 100644 index bfbe6cf69..000000000 --- a/LUFA/Drivers/USB/Class/Host/HID.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_HID_DRIVER -#define __INCLUDE_FROM_HID_HOST_C -#include "HID.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 || DataOUTEndpoint) - 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; - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - uint8_t InterruptPeriod; - bool DoubleBanked; - - if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber) - { - Size = le16_to_cpu(DataINEndpoint->EndpointSize); - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_INTERRUPT; - DoubleBanked = HIDInterfaceInfo->Config.DataINPipeDoubleBank; - InterruptPeriod = DataINEndpoint->PollingIntervalMS; - - HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber) - { - if (DataOUTEndpoint == NULL) - continue; - - Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_INTERRUPT; - DoubleBanked = HIDInterfaceInfo->Config.DataOUTPipeDoubleBank; - InterruptPeriod = DataOUTEndpoint->PollingIntervalMS; - - HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - HIDInterfaceInfo->State.DeviceUsesOUTPipe = true; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - return HID_ENUMERROR_PipeConfigurationFailed; - } - - if (InterruptPeriod) - Pipe_SetInterruptPeriod(InterruptPeriod); - } - - 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.DataINPipeNumber); - 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 false; - - if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out)) - { - uint8_t ErrorCode; - - Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber); - 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.DataINPipeNumber); - 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 - diff --git a/LUFA/Drivers/USB/Class/Host/HID.h b/LUFA/Drivers/USB/Class/Host/HID.h deleted file mode 100644 index 08410f2b1..000000000 --- a/LUFA/Drivers/USB/Class/Host/HID.h +++ /dev/null @@ -1,320 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/HID.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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the HID interface's IN data pipe. */ - bool DataINPipeDoubleBank; /**< Indicates if the HID interface's IN data pipe should use double banking. */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the HID interface's OUT data pipe. */ - bool DataOUTPipeDoubleBank; /**< Indicates if the HID interface's OUT data pipe should use double banking. */ - - 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 method is unavailable. - */ - #endif - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the HID interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the HID interface's OUT data pipe. */ - - 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 - * may 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. - * - * \note Once the device pipes are configured, the HID device's reporting protocol must 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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. - * - * \note 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 ocurred; 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. - * - * \note Whether this function is used or not, the \ref CALLBACK_HIDParser_FilterHIDReportItem() callback from the HID - * Report Parser this function references must be implemented in the user code. - * \n\n - * - * \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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/HIDClassHost.c b/LUFA/Drivers/USB/Class/Host/HIDClassHost.c new file mode 100644 index 000000000..88e3c4993 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/HIDClassHost.c @@ -0,0 +1,432 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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 || DataOUTEndpoint) + 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; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + uint8_t InterruptPeriod; + bool DoubleBanked; + + if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber) + { + Size = le16_to_cpu(DataINEndpoint->EndpointSize); + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_INTERRUPT; + DoubleBanked = HIDInterfaceInfo->Config.DataINPipeDoubleBank; + InterruptPeriod = DataINEndpoint->PollingIntervalMS; + + HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber) + { + if (DataOUTEndpoint == NULL) + continue; + + Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_INTERRUPT; + DoubleBanked = HIDInterfaceInfo->Config.DataOUTPipeDoubleBank; + InterruptPeriod = DataOUTEndpoint->PollingIntervalMS; + + HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + HIDInterfaceInfo->State.DeviceUsesOUTPipe = true; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + return HID_ENUMERROR_PipeConfigurationFailed; + } + + if (InterruptPeriod) + Pipe_SetInterruptPeriod(InterruptPeriod); + } + + 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.DataINPipeNumber); + 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 false; + + if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out)) + { + uint8_t ErrorCode; + + Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber); + 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.DataINPipeNumber); + 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 + diff --git a/LUFA/Drivers/USB/Class/Host/HIDClassHost.h b/LUFA/Drivers/USB/Class/Host/HIDClassHost.h new file mode 100644 index 000000000..5d8c8e922 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/HIDClassHost.h @@ -0,0 +1,320 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/HID.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the HID interface's IN data pipe. */ + bool DataINPipeDoubleBank; /**< Indicates if the HID interface's IN data pipe should use double banking. */ + + uint8_t DataOUTPipeNumber; /**< Pipe number of the HID interface's OUT data pipe. */ + bool DataOUTPipeDoubleBank; /**< Indicates if the HID interface's OUT data pipe should use double banking. */ + + 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 method is unavailable. + */ + #endif + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the HID interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the HID interface's OUT data pipe. */ + + 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 + * may 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. + * + * \note Once the device pipes are configured, the HID device's reporting protocol must 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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. + * + * \note 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 ocurred; 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. + * + * \note Whether this function is used or not, the \ref CALLBACK_HIDParser_FilterHIDReportItem() callback from the HID + * Report Parser this function references must be implemented in the user code. + * \n\n + * + * \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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/MIDI.c b/LUFA/Drivers/USB/Class/Host/MIDI.c deleted file mode 100644 index 9f7bbd4ea..000000000 --- a/LUFA/Drivers/USB/Class/Host/MIDI.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_MIDI_DRIVER -#define __INCLUDE_FROM_MIDI_HOST_C -#include "MIDI.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; - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - bool DoubleBanked; - - if (PipeNum == MIDIInterfaceInfo->Config.DataINPipeNumber) - { - Size = le16_to_cpu(DataINEndpoint->EndpointSize); - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_BULK; - DoubleBanked = MIDIInterfaceInfo->Config.DataINPipeDoubleBank; - - MIDIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == MIDIInterfaceInfo->Config.DataOUTPipeNumber) - { - Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank; - - MIDIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - 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.DataOUTPipeNumber); - - if (Pipe_BytesInPipe()) - { - Pipe_ClearOUT(); - - if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError) - return ErrorCode; - } - - 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.DataOUTPipeNumber); - - if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - if (!(Pipe_IsReadWriteAllowed())) - Pipe_ClearOUT(); - - 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; - - Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipeNumber); - - if (!(Pipe_IsReadWriteAllowed())) - return false; - - Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); - - if (!(Pipe_IsReadWriteAllowed())) - Pipe_ClearIN(); - - return true; -} - -#endif - diff --git a/LUFA/Drivers/USB/Class/Host/MIDI.h b/LUFA/Drivers/USB/Class/Host/MIDI.h deleted file mode 100644 index c4451b117..000000000 --- a/LUFA/Drivers/USB/Class/Host/MIDI.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/MIDI.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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the MIDI interface's streaming IN data pipe. */ - bool DataINPipeDoubleBank; /**< Indicates if the MIDI interface's IN data pipe should use double banking. */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the MIDI interface's streaming OUT data pipe. */ - bool DataOUTPipeDoubleBank; /**< Indicates if the MIDI interface's OUT data pipe should use double banking. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's OUT data pipe. */ - } State; /**< State data for the USB class interface within the device. All elements in this section - * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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 behaviour, 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c b/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c new file mode 100644 index 000000000..109b075d9 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c @@ -0,0 +1,236 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + bool DoubleBanked; + + if (PipeNum == MIDIInterfaceInfo->Config.DataINPipeNumber) + { + Size = le16_to_cpu(DataINEndpoint->EndpointSize); + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_BULK; + DoubleBanked = MIDIInterfaceInfo->Config.DataINPipeDoubleBank; + + MIDIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == MIDIInterfaceInfo->Config.DataOUTPipeNumber) + { + Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank; + + MIDIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + 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.DataOUTPipeNumber); + + if (Pipe_BytesInPipe()) + { + Pipe_ClearOUT(); + + if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError) + return ErrorCode; + } + + 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.DataOUTPipeNumber); + + if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if (!(Pipe_IsReadWriteAllowed())) + Pipe_ClearOUT(); + + 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; + + Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipeNumber); + + if (!(Pipe_IsReadWriteAllowed())) + return false; + + Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL); + + if (!(Pipe_IsReadWriteAllowed())) + Pipe_ClearIN(); + + return true; +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h b/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h new file mode 100644 index 000000000..3398830e1 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h @@ -0,0 +1,196 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the MIDI interface's streaming IN data pipe. */ + bool DataINPipeDoubleBank; /**< Indicates if the MIDI interface's IN data pipe should use double banking. */ + + uint8_t DataOUTPipeNumber; /**< Pipe number of the MIDI interface's streaming OUT data pipe. */ + bool DataOUTPipeDoubleBank; /**< Indicates if the MIDI interface's OUT data pipe should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's OUT data pipe. */ + } State; /**< State data for the USB class interface within the device. All elements in this section + * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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 behaviour, 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.c b/LUFA/Drivers/USB/Class/Host/MassStorage.c deleted file mode 100644 index 36503bf45..000000000 --- a/LUFA/Drivers/USB/Class/Host/MassStorage.c +++ /dev/null @@ -1,663 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_MS_DRIVER -#define __INCLUDE_FROM_MASSSTORAGE_HOST_C -#include "MassStorage.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; - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - bool DoubleBanked; - - if (PipeNum == MSInterfaceInfo->Config.DataINPipeNumber) - { - Size = le16_to_cpu(DataINEndpoint->EndpointSize); - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_BULK; - DoubleBanked = MSInterfaceInfo->Config.DataINPipeDoubleBank; - - MSInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == MSInterfaceInfo->Config.DataOUTPipeNumber) - { - Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = MSInterfaceInfo->Config.DataOUTPipeDoubleBank; - - MSInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - 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.DataOUTPipeNumber); - 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)) != PIPE_RWSTREAM_NoError)) - { - Pipe_Freeze(); - return ErrorCode; - } - - return ErrorCode; -} - -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.DataINPipeNumber); - 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.DataOUTPipeNumber); - Pipe_Unfreeze(); - - if (Pipe_IsStalled()) - { - USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); - return PIPE_RWSTREAM_PipeStalled; - } - - Pipe_Freeze(); - Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); - 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.DataINPipeNumber); - Pipe_Freeze(); - - Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); - 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.DataINPipeNumber); - Pipe_Unfreeze(); - - if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - Pipe_ClearIN(); - } - else - { - Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); - 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.DataINPipeNumber); - 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.DataINPipeNumber); - - if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful) - return ErrorCode; - - Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); - - 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 = HOST_SENDCONTROL_Successful; - - 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; - - uint8_t ErrorCode; - - 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) - } - }; - - MS_CommandStatusWrapper_t SCSICommandStatus; - - if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, InquiryData)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - return PIPE_RWSTREAM_NoError; -} - -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; - - uint8_t ErrorCode; - - 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) - } - }; - - MS_CommandStatusWrapper_t SCSICommandStatus; - - if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - return PIPE_RWSTREAM_NoError; -} - -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) - } - }; - - MS_CommandStatusWrapper_t SCSICommandStatus; - - 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); - - if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - 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; - - uint8_t ErrorCode; - - 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) - } - }; - - MS_CommandStatusWrapper_t SCSICommandStatus; - - if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, SenseData)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - return PIPE_RWSTREAM_NoError; -} - -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; - - uint8_t ErrorCode; - - 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) - } - }; - - MS_CommandStatusWrapper_t SCSICommandStatus; - - if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - return PIPE_RWSTREAM_NoError; -} - -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; - - uint8_t ErrorCode; - - 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) - } - }; - - MS_CommandStatusWrapper_t SCSICommandStatus; - - if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - return PIPE_RWSTREAM_NoError; -} - -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; - - uint8_t ErrorCode; - - 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) - } - }; - - MS_CommandStatusWrapper_t SCSICommandStatus; - - if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) - return ErrorCode; - - return PIPE_RWSTREAM_NoError; -} - -#endif - diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.h b/LUFA/Drivers/USB/Class/Host/MassStorage.h deleted file mode 100644 index f0dd475f2..000000000 --- a/LUFA/Drivers/USB/Class/Host/MassStorage.h +++ /dev/null @@ -1,341 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/MassStorage.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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the Mass Storage interface's IN data pipe. */ - bool DataINPipeDoubleBank; /**< Indicates if the Mass Storage interface's IN data pipe should use double banking. */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the Mass Storage interface's OUT data pipe. */ - bool DataOUTPipeDoubleBank; /**< Indicates if the Mass Storage interface's OUT data pipe should use double banking. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the Mass Storage interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the Mass Storage interface's OUT data pipe. */ - - 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 - * may 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] ConfigDescriptorData 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* ConfigDescriptorData) 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c b/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c new file mode 100644 index 000000000..96550cc3f --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c @@ -0,0 +1,663 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + bool DoubleBanked; + + if (PipeNum == MSInterfaceInfo->Config.DataINPipeNumber) + { + Size = le16_to_cpu(DataINEndpoint->EndpointSize); + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_BULK; + DoubleBanked = MSInterfaceInfo->Config.DataINPipeDoubleBank; + + MSInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == MSInterfaceInfo->Config.DataOUTPipeNumber) + { + Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = MSInterfaceInfo->Config.DataOUTPipeDoubleBank; + + MSInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + 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.DataOUTPipeNumber); + 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)) != PIPE_RWSTREAM_NoError)) + { + Pipe_Freeze(); + return ErrorCode; + } + + return ErrorCode; +} + +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.DataINPipeNumber); + 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.DataOUTPipeNumber); + Pipe_Unfreeze(); + + if (Pipe_IsStalled()) + { + USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); + return PIPE_RWSTREAM_PipeStalled; + } + + Pipe_Freeze(); + Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); + 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.DataINPipeNumber); + Pipe_Freeze(); + + Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); + 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.DataINPipeNumber); + Pipe_Unfreeze(); + + if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + Pipe_ClearIN(); + } + else + { + Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); + 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.DataINPipeNumber); + 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.DataINPipeNumber); + + if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful) + return ErrorCode; + + Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); + + 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 = HOST_SENDCONTROL_Successful; + + 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; + + uint8_t ErrorCode; + + 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) + } + }; + + MS_CommandStatusWrapper_t SCSICommandStatus; + + if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, InquiryData)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + return PIPE_RWSTREAM_NoError; +} + +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; + + uint8_t ErrorCode; + + 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) + } + }; + + MS_CommandStatusWrapper_t SCSICommandStatus; + + if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + return PIPE_RWSTREAM_NoError; +} + +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) + } + }; + + MS_CommandStatusWrapper_t SCSICommandStatus; + + 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); + + if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + 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; + + uint8_t ErrorCode; + + 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) + } + }; + + MS_CommandStatusWrapper_t SCSICommandStatus; + + if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, SenseData)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + return PIPE_RWSTREAM_NoError; +} + +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; + + uint8_t ErrorCode; + + 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) + } + }; + + MS_CommandStatusWrapper_t SCSICommandStatus; + + if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + return PIPE_RWSTREAM_NoError; +} + +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; + + uint8_t ErrorCode; + + 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) + } + }; + + MS_CommandStatusWrapper_t SCSICommandStatus; + + if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + return PIPE_RWSTREAM_NoError; +} + +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; + + uint8_t ErrorCode; + + 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) + } + }; + + MS_CommandStatusWrapper_t SCSICommandStatus; + + if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + return PIPE_RWSTREAM_NoError; +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h b/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h new file mode 100644 index 000000000..3b3b9fa5a --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h @@ -0,0 +1,341 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the Mass Storage interface's IN data pipe. */ + bool DataINPipeDoubleBank; /**< Indicates if the Mass Storage interface's IN data pipe should use double banking. */ + + uint8_t DataOUTPipeNumber; /**< Pipe number of the Mass Storage interface's OUT data pipe. */ + bool DataOUTPipeDoubleBank; /**< Indicates if the Mass Storage interface's OUT data pipe should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the Mass Storage interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the Mass Storage interface's OUT data pipe. */ + + 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 + * may 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] ConfigDescriptorData 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* ConfigDescriptorData) 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/Printer.c b/LUFA/Drivers/USB/Class/Host/Printer.c deleted file mode 100644 index 576dd36f1..000000000 --- a/LUFA/Drivers/USB/Class/Host/Printer.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_PRINTER_DRIVER -#define __INCLUDE_FROM_PRINTER_HOST_C -#include "Printer.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; - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - bool DoubleBanked; - - if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber) - { - Size = le16_to_cpu(DataINEndpoint->EndpointSize); - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_BULK; - DoubleBanked = PRNTInterfaceInfo->Config.DataINPipeDoubleBank; - - PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber) - { - Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank; - - PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - 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.DataOUTPipeNumber); - 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.DataOUTPipeNumber); - 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, - void* String) -{ - uint8_t ErrorCode; - - if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive)) - return PIPE_RWSTREAM_DeviceDisconnected; - - Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber); - 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, - 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.DataOUTPipeNumber); - 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.DataINPipeNumber); - 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.DataINPipeNumber); - 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 = HOST_SENDCONTROL_Successful; - 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 - diff --git a/LUFA/Drivers/USB/Class/Host/Printer.h b/LUFA/Drivers/USB/Class/Host/Printer.h deleted file mode 100644 index 9f5c8161a..000000000 --- a/LUFA/Drivers/USB/Class/Host/Printer.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/Printer.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/Printer.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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the Printer interface's IN data pipe. */ - bool DataINPipeDoubleBank; /**< Indicates if the Printer interface's IN data pipe should use double banking. */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the Printer interface's OUT data pipe. */ - bool DataOUTPipeDoubleBank; /**< Indicates if the Printer interface's OUT data pipe should use double banking. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the Printer interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the Printer interface's OUT data pipe. */ - } State; /**< State data for the USB class interface within the device. All elements in this section - * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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, - void* 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, - 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); - - /** 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); - - /** 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c b/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c new file mode 100644 index 000000000..8bb0acdd6 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c @@ -0,0 +1,426 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + bool DoubleBanked; + + if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber) + { + Size = le16_to_cpu(DataINEndpoint->EndpointSize); + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_BULK; + DoubleBanked = PRNTInterfaceInfo->Config.DataINPipeDoubleBank; + + PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber) + { + Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank; + + PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + 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.DataOUTPipeNumber); + 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.DataOUTPipeNumber); + 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, + void* String) +{ + uint8_t ErrorCode; + + if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive)) + return PIPE_RWSTREAM_DeviceDisconnected; + + Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber); + 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, + 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.DataOUTPipeNumber); + 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.DataINPipeNumber); + 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.DataINPipeNumber); + 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 = HOST_SENDCONTROL_Successful; + 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 + diff --git a/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h b/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h new file mode 100644 index 000000000..f0fe8ee98 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h @@ -0,0 +1,291 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/Printer.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the Printer interface's IN data pipe. */ + bool DataINPipeDoubleBank; /**< Indicates if the Printer interface's IN data pipe should use double banking. */ + + uint8_t DataOUTPipeNumber; /**< Pipe number of the Printer interface's OUT data pipe. */ + bool DataOUTPipeDoubleBank; /**< Indicates if the Printer interface's OUT data pipe should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the Printer interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the Printer interface's OUT data pipe. */ + } State; /**< State data for the USB class interface within the device. All elements in this section + * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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, + void* 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, + 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); + + /** 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); + + /** 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/RNDIS.c b/LUFA/Drivers/USB/Class/Host/RNDIS.c deleted file mode 100644 index b942c536c..000000000 --- a/LUFA/Drivers/USB/Class/Host/RNDIS.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_RNDIS_DRIVER -#define __INCLUDE_FROM_RNDIS_HOST_C -#include "RNDIS.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; - } - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - uint8_t InterruptPeriod; - bool DoubleBanked; - - if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber) - { - Size = le16_to_cpu(DataINEndpoint->EndpointSize); - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_BULK; - DoubleBanked = RNDISInterfaceInfo->Config.DataINPipeDoubleBank; - InterruptPeriod = 0; - - RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber) - { - Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank; - InterruptPeriod = 0; - - RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - } - else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber) - { - Size = le16_to_cpu(NotificationEndpoint->EndpointSize); - EndpointAddress = NotificationEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_INTERRUPT; - DoubleBanked = RNDISInterfaceInfo->Config.NotificationPipeDoubleBank; - InterruptPeriod = NotificationEndpoint->PollingIntervalMS; - - RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - return CDC_ENUMERROR_PipeConfigurationFailed; - } - - if (InterruptPeriod) - Pipe_SetInterruptPeriod(InterruptPeriod); - } - - 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, - SetMessageData.SetMessage.MessageLength)) != 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.DataINPipeNumber); - - 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.DataINPipeNumber); - 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(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.DataOUTPipeNumber); - 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 - diff --git a/LUFA/Drivers/USB/Class/Host/RNDIS.h b/LUFA/Drivers/USB/Class/Host/RNDIS.h deleted file mode 100644 index f90ed412d..000000000 --- a/LUFA/Drivers/USB/Class/Host/RNDIS.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/RNDIS.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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the RNDIS interface's IN data pipe. */ - bool DataINPipeDoubleBank; /**< Indicates if the RNDIS interface's IN data pipe should use double banking. */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the RNDIS interface's OUT data pipe. */ - bool DataOUTPipeDoubleBank; /**< Indicates if the RNDIS interface's OUT data pipe should use double banking. */ - - uint8_t NotificationPipeNumber; /**< Pipe number of the RNDIS interface's IN notification endpoint, if used. */ - bool NotificationPipeDoubleBank; /**< Indicates if the RNDIS interface's notification pipe should use double banking. */ - - 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 - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the RNDIS interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the RNDIS interface's OUT data pipe. */ - uint16_t NotificationPipeSize; /**< Size in bytes of the RNDIS interface's IN notification pipe, if used. */ - - 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 - * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c b/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c new file mode 100644 index 000000000..61f14020c --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c @@ -0,0 +1,512 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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; + } + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + uint8_t InterruptPeriod; + bool DoubleBanked; + + if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber) + { + Size = le16_to_cpu(DataINEndpoint->EndpointSize); + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_BULK; + DoubleBanked = RNDISInterfaceInfo->Config.DataINPipeDoubleBank; + InterruptPeriod = 0; + + RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber) + { + Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank; + InterruptPeriod = 0; + + RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber) + { + Size = le16_to_cpu(NotificationEndpoint->EndpointSize); + EndpointAddress = NotificationEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_INTERRUPT; + DoubleBanked = RNDISInterfaceInfo->Config.NotificationPipeDoubleBank; + InterruptPeriod = NotificationEndpoint->PollingIntervalMS; + + RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + return CDC_ENUMERROR_PipeConfigurationFailed; + } + + if (InterruptPeriod) + Pipe_SetInterruptPeriod(InterruptPeriod); + } + + 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, + SetMessageData.SetMessage.MessageLength)) != 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.DataINPipeNumber); + + 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.DataINPipeNumber); + 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(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.DataOUTPipeNumber); + 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 + diff --git a/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h b/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h new file mode 100644 index 000000000..7b0acfb5c --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h @@ -0,0 +1,279 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the RNDIS interface's IN data pipe. */ + bool DataINPipeDoubleBank; /**< Indicates if the RNDIS interface's IN data pipe should use double banking. */ + + uint8_t DataOUTPipeNumber; /**< Pipe number of the RNDIS interface's OUT data pipe. */ + bool DataOUTPipeDoubleBank; /**< Indicates if the RNDIS interface's OUT data pipe should use double banking. */ + + uint8_t NotificationPipeNumber; /**< Pipe number of the RNDIS interface's IN notification endpoint, if used. */ + bool NotificationPipeDoubleBank; /**< Indicates if the RNDIS interface's notification pipe should use double banking. */ + + 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 + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the RNDIS interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the RNDIS interface's OUT data pipe. */ + uint16_t NotificationPipeSize; /**< Size in bytes of the RNDIS interface's IN notification pipe, if used. */ + + 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 + * may 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] DeviceConfigDescriptor 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* DeviceConfigDescriptor) 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/StillImage.c b/LUFA/Drivers/USB/Class/Host/StillImage.c deleted file mode 100644 index 48aa86431..000000000 --- a/LUFA/Drivers/USB/Class/Host/StillImage.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -#define __INCLUDE_FROM_USB_DRIVER -#include "../../Core/USBMode.h" - -#if defined(USB_CAN_BE_HOST) - -#define __INCLUDE_FROM_SI_DRIVER -#define __INCLUDE_FROM_STILLIMAGE_HOST_C -#include "StillImage.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; - } - } - - for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) - { - uint16_t Size; - uint8_t Type; - uint8_t Token; - uint8_t EndpointAddress; - uint8_t InterruptPeriod; - bool DoubleBanked; - - if (PipeNum == SIInterfaceInfo->Config.DataINPipeNumber) - { - Size = DataINEndpoint->EndpointSize; - EndpointAddress = DataINEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_BULK; - DoubleBanked = SIInterfaceInfo->Config.DataINPipeDoubleBank; - InterruptPeriod = 0; - - SIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; - } - else if (PipeNum == SIInterfaceInfo->Config.DataOUTPipeNumber) - { - Size = DataOUTEndpoint->EndpointSize; - EndpointAddress = DataOUTEndpoint->EndpointAddress; - Token = PIPE_TOKEN_OUT; - Type = EP_TYPE_BULK; - DoubleBanked = SIInterfaceInfo->Config.DataOUTPipeDoubleBank; - InterruptPeriod = 0; - - SIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; - } - else if (PipeNum == SIInterfaceInfo->Config.EventsPipeNumber) - { - Size = EventsEndpoint->EndpointSize; - EndpointAddress = EventsEndpoint->EndpointAddress; - Token = PIPE_TOKEN_IN; - Type = EP_TYPE_INTERRUPT; - DoubleBanked = SIInterfaceInfo->Config.EventsPipeDoubleBank; - InterruptPeriod = EventsEndpoint->PollingIntervalMS; - - SIInterfaceInfo->State.EventsPipeSize = EventsEndpoint->EndpointSize; - } - else - { - continue; - } - - if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, - DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) - { - return SI_ENUMERROR_PipeConfigurationFailed; - } - - if (InterruptPeriod) - Pipe_SetInterruptPeriod(InterruptPeriod); - } - - 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.DataOUTPipeNumber); - 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.DataINPipeNumber); - 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.DataOUTPipeNumber); - Pipe_Unfreeze(); - - if (Pipe_IsStalled()) - { - USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); - return PIPE_RWSTREAM_PipeStalled; - } - - Pipe_Freeze(); - Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); - 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, - 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.DataOUTPipeNumber); - 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.DataINPipeNumber); - 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.EventsPipeNumber); - Pipe_Unfreeze(); - - if (Pipe_BytesInPipe()) - 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.EventsPipeNumber); - 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 - diff --git a/LUFA/Drivers/USB/Class/Host/StillImage.h b/LUFA/Drivers/USB/Class/Host/StillImage.h deleted file mode 100644 index 2c5c6b1b6..000000000 --- a/LUFA/Drivers/USB/Class/Host/StillImage.h +++ /dev/null @@ -1,326 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/StillImage.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/StillImage.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 - { - const struct - { - uint8_t DataINPipeNumber; /**< Pipe number of the Still Image interface's IN data pipe. */ - bool DataINPipeDoubleBank; /**< Indicates if the Still Image interface's IN data pipe should use double banking. */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the Still Image interface's OUT data pipe. */ - bool DataOUTPipeDoubleBank; /**< Indicates if the Still Image interface's OUT data pipe should use double banking. */ - - uint8_t EventsPipeNumber; /**< Pipe number of the Still Image interface's IN events endpoint, if used. */ - bool EventsPipeDoubleBank; /**< Indicates if the Still Image interface's events data pipe should use double banking. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must 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. */ - - uint16_t DataINPipeSize; /**< Size in bytes of the Still Image interface's IN data pipe. */ - uint16_t DataOUTPipeSize; /**< Size in bytes of the Still Image interface's OUT data pipe. */ - uint16_t EventsPipeSize; /**< Size in bytes of the Still Image interface's IN events pipe. */ - - 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 - * may 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, - 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 - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c b/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c new file mode 100644 index 000000000..31f581355 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c @@ -0,0 +1,472 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../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; + } + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + uint16_t Size; + uint8_t Type; + uint8_t Token; + uint8_t EndpointAddress; + uint8_t InterruptPeriod; + bool DoubleBanked; + + if (PipeNum == SIInterfaceInfo->Config.DataINPipeNumber) + { + Size = DataINEndpoint->EndpointSize; + EndpointAddress = DataINEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_BULK; + DoubleBanked = SIInterfaceInfo->Config.DataINPipeDoubleBank; + InterruptPeriod = 0; + + SIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == SIInterfaceInfo->Config.DataOUTPipeNumber) + { + Size = DataOUTEndpoint->EndpointSize; + EndpointAddress = DataOUTEndpoint->EndpointAddress; + Token = PIPE_TOKEN_OUT; + Type = EP_TYPE_BULK; + DoubleBanked = SIInterfaceInfo->Config.DataOUTPipeDoubleBank; + InterruptPeriod = 0; + + SIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else if (PipeNum == SIInterfaceInfo->Config.EventsPipeNumber) + { + Size = EventsEndpoint->EndpointSize; + EndpointAddress = EventsEndpoint->EndpointAddress; + Token = PIPE_TOKEN_IN; + Type = EP_TYPE_INTERRUPT; + DoubleBanked = SIInterfaceInfo->Config.EventsPipeDoubleBank; + InterruptPeriod = EventsEndpoint->PollingIntervalMS; + + SIInterfaceInfo->State.EventsPipeSize = EventsEndpoint->EndpointSize; + } + else + { + continue; + } + + if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, + DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) + { + return SI_ENUMERROR_PipeConfigurationFailed; + } + + if (InterruptPeriod) + Pipe_SetInterruptPeriod(InterruptPeriod); + } + + 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.DataOUTPipeNumber); + 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.DataINPipeNumber); + 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.DataOUTPipeNumber); + Pipe_Unfreeze(); + + if (Pipe_IsStalled()) + { + USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress()); + return PIPE_RWSTREAM_PipeStalled; + } + + Pipe_Freeze(); + Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); + 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, + 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.DataOUTPipeNumber); + 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.DataINPipeNumber); + 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.EventsPipeNumber); + Pipe_Unfreeze(); + + if (Pipe_BytesInPipe()) + 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.EventsPipeNumber); + 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 + diff --git a/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h b/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h new file mode 100644 index 000000000..44894fe6b --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h @@ -0,0 +1,326 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/StillImage.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + { + const struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the Still Image interface's IN data pipe. */ + bool DataINPipeDoubleBank; /**< Indicates if the Still Image interface's IN data pipe should use double banking. */ + + uint8_t DataOUTPipeNumber; /**< Pipe number of the Still Image interface's OUT data pipe. */ + bool DataOUTPipeDoubleBank; /**< Indicates if the Still Image interface's OUT data pipe should use double banking. */ + + uint8_t EventsPipeNumber; /**< Pipe number of the Still Image interface's IN events endpoint, if used. */ + bool EventsPipeDoubleBank; /**< Indicates if the Still Image interface's events data pipe should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must 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. */ + + uint16_t DataINPipeSize; /**< Size in bytes of the Still Image interface's IN data pipe. */ + uint16_t DataOUTPipeSize; /**< Size in bytes of the Still Image interface's OUT data pipe. */ + uint16_t EventsPipeSize; /**< Size in bytes of the Still Image interface's IN events pipe. */ + + 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 + * may 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, + 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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/MIDI.h b/LUFA/Drivers/USB/Class/MIDI.h deleted file mode 100644 index 3f7970b6d..000000000 --- a/LUFA/Drivers/USB/Class/MIDI.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/MIDI.h" - #endif - - #if defined(USB_CAN_BE_HOST) - #include "Host/MIDI.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/MIDIClass.h b/LUFA/Drivers/USB/Class/MIDIClass.h new file mode 100644 index 000000000..fae117b39 --- /dev/null +++ b/LUFA/Drivers/USB/Class/MIDIClass.h @@ -0,0 +1,83 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/MIDI.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/MassStorage.h b/LUFA/Drivers/USB/Class/MassStorage.h deleted file mode 100644 index 49af9dd24..000000000 --- a/LUFA/Drivers/USB/Class/MassStorage.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/MassStorage.h" - #endif - - #if defined(USB_CAN_BE_HOST) - #include "Host/MassStorage.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/MassStorageClass.h b/LUFA/Drivers/USB/Class/MassStorageClass.h new file mode 100644 index 000000000..003c63be2 --- /dev/null +++ b/LUFA/Drivers/USB/Class/MassStorageClass.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/MassStorage.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Printer.h b/LUFA/Drivers/USB/Class/Printer.h deleted file mode 100644 index 067ce756c..000000000 --- a/LUFA/Drivers/USB/Class/Printer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/Printer.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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_HOST) - #include "Host/Printer.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/PrinterClass.h b/LUFA/Drivers/USB/Class/PrinterClass.h new file mode 100644 index 000000000..52edd5208 --- /dev/null +++ b/LUFA/Drivers/USB/Class/PrinterClass.h @@ -0,0 +1,77 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/Printer.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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_HOST) + #include "Host/PrinterClassHost.h" + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/RNDIS.h b/LUFA/Drivers/USB/Class/RNDIS.h deleted file mode 100644 index 37a584088..000000000 --- a/LUFA/Drivers/USB/Class/RNDIS.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Device/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/RNDIS.h" - #endif - - #if defined(USB_CAN_BE_HOST) - #include "Host/RNDIS.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/RNDISClass.h b/LUFA/Drivers/USB/Class/RNDISClass.h new file mode 100644 index 000000000..a85ba1d06 --- /dev/null +++ b/LUFA/Drivers/USB/Class/RNDISClass.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Device/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/RNDIS.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/StillImage.h b/LUFA/Drivers/USB/Class/StillImage.h deleted file mode 100644 index a421b1555..000000000 --- a/LUFA/Drivers/USB/Class/StillImage.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2011. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * \brief 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 - * - * \section Sec_Dependencies Module Source Dependencies - * The following files must be built with any user project that uses this module: - * - LUFA/Drivers/USB/Class/Host/StillImage.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \section Sec_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/StillImage.h" - #endif - -#endif - -/** @} */ - diff --git a/LUFA/Drivers/USB/Class/StillImageClass.h b/LUFA/Drivers/USB/Class/StillImageClass.h new file mode 100644 index 000000000..74e93ed21 --- /dev/null +++ b/LUFA/Drivers/USB/Class/StillImageClass.h @@ -0,0 +1,75 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/Class/Host/StillImage.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \section Sec_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 + +/** @} */ + diff --git a/LUFA/Drivers/USB/USB.h b/LUFA/Drivers/USB/USB.h index fa4fcf1c3..a5a743bef 100644 --- a/LUFA/Drivers/USB/USB.h +++ b/LUFA/Drivers/USB/USB.h @@ -388,14 +388,14 @@ #include "Core/OTG.h" #endif - #include "Class/Audio.h" - #include "Class/CDC.h" - #include "Class/HID.h" - #include "Class/MassStorage.h" - #include "Class/MIDI.h" - #include "Class/Printer.h" - #include "Class/RNDIS.h" - #include "Class/StillImage.h" + #include "Class/AudioClass.h" + #include "Class/CDCClass.h" + #include "Class/HIDClass.h" + #include "Class/MassStorageClass.h" + #include "Class/MIDIClass.h" + #include "Class/PrinterClass.h" + #include "Class/RNDISClass.h" + #include "Class/StillImageClass.h" #endif diff --git a/LUFA/makefile b/LUFA/makefile index a05b95670..226cf5a75 100644 --- a/LUFA/makefile +++ b/LUFA/makefile @@ -37,20 +37,20 @@ LUFA_SRC_USB = $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Device_$(ARCH $(LUFA_ROOT_PATH)/Drivers/USB/Core/HostStandardReq.c \ $(LUFA_ROOT_PATH)/Drivers/USB/Core/USBTask.c \ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Common/HIDParser.c -LUFA_SRC_USBCLASS = $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/Audio.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDC.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/HID.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MassStorage.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MIDI.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/RNDIS.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/Audio.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/CDC.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/HID.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MassStorage.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MIDI.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/Printer.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/RNDIS.c \ - $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/StillImage.c +LUFA_SRC_USBCLASS = $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/AudioClassDevice.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/HIDClassDevice.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MassStorageClassDevice.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MIDIClassDevice.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/RNDISClassDevice.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/AudioClassHost.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/CDCClassHost.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/HIDClassHost.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MassStorageClassHost.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MIDIClassHost.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/PrinterClassHost.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/RNDISClassHost.c \ + $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/StillImageClassHost.c LUFA_SRC_TEMPERATURE = $(LUFA_ROOT_PATH)/Drivers/Board/Temperature.c LUFA_SRC_SERIAL = $(LUFA_ROOT_PATH)/Drivers/Peripheral/$(ARCH)/Serial_$(ARCH).c LUFA_SRC_TWI = $(LUFA_ROOT_PATH)/Drivers/Peripheral/$(ARCH)/TWI_$(ARCH).c -- cgit v1.2.3