From 237ea87c4fcb4865863fc15e07e179323caa7881 Mon Sep 17 00:00:00 2001 From: HÃ¥vard Espeland Date: Sat, 5 Feb 2011 19:26:39 +0100 Subject: Fork of LUFA CDC Bootloader Initial commit --- LUFA/Drivers/Board/ADAFRUITU4/LEDs.h | 129 +++ LUFA/Drivers/Board/ATAVRUSBRF01/Buttons.h | 98 +++ LUFA/Drivers/Board/ATAVRUSBRF01/LEDs.h | 141 +++ LUFA/Drivers/Board/BENITO/Buttons.h | 98 +++ LUFA/Drivers/Board/BENITO/LEDs.h | 130 +++ LUFA/Drivers/Board/BLACKCAT/LEDs.h | 131 +++ LUFA/Drivers/Board/BUI/LEDs.h | 132 +++ LUFA/Drivers/Board/BUMBLEB/Buttons.h | 103 +++ LUFA/Drivers/Board/BUMBLEB/Joystick.h | 120 +++ LUFA/Drivers/Board/BUMBLEB/LEDs.h | 143 ++++ LUFA/Drivers/Board/Buttons.h | 135 +++ LUFA/Drivers/Board/CULV3/Buttons.h | 98 +++ LUFA/Drivers/Board/CULV3/LEDs.h | 129 +++ LUFA/Drivers/Board/Dataflash.h | 212 +++++ LUFA/Drivers/Board/EVK527/AT45DB321C.h | 105 +++ LUFA/Drivers/Board/EVK527/Buttons.h | 104 +++ LUFA/Drivers/Board/EVK527/Dataflash.h | 184 ++++ LUFA/Drivers/Board/EVK527/Joystick.h | 119 +++ LUFA/Drivers/Board/EVK527/LEDs.h | 135 +++ LUFA/Drivers/Board/JMDBU2/Buttons.h | 98 +++ LUFA/Drivers/Board/JMDBU2/LEDs.h | 129 +++ LUFA/Drivers/Board/Joystick.h | 114 +++ LUFA/Drivers/Board/LEDs.h | 212 +++++ LUFA/Drivers/Board/MAXIMUS/LEDs.h | 131 +++ LUFA/Drivers/Board/MICROSIN162/Buttons.h | 98 +++ LUFA/Drivers/Board/MICROSIN162/LEDs.h | 129 +++ LUFA/Drivers/Board/MINIMUS/Buttons.h | 97 +++ LUFA/Drivers/Board/MINIMUS/LEDs.h | 131 +++ LUFA/Drivers/Board/OLIMEX162/Buttons.h | 98 +++ LUFA/Drivers/Board/OLIMEX162/LEDs.h | 129 +++ LUFA/Drivers/Board/RZUSBSTICK/LEDs.h | 163 ++++ LUFA/Drivers/Board/STK525/AT45DB321C.h | 105 +++ LUFA/Drivers/Board/STK525/Buttons.h | 104 +++ LUFA/Drivers/Board/STK525/Dataflash.h | 184 ++++ LUFA/Drivers/Board/STK525/Joystick.h | 119 +++ LUFA/Drivers/Board/STK525/LEDs.h | 138 +++ LUFA/Drivers/Board/STK526/AT45DB642D.h | 115 +++ LUFA/Drivers/Board/STK526/Buttons.h | 104 +++ LUFA/Drivers/Board/STK526/Dataflash.h | 184 ++++ LUFA/Drivers/Board/STK526/Joystick.h | 116 +++ LUFA/Drivers/Board/STK526/LEDs.h | 138 +++ LUFA/Drivers/Board/TEENSY/LEDs.h | 129 +++ LUFA/Drivers/Board/Temperature.c | 61 ++ LUFA/Drivers/Board/Temperature.h | 125 +++ LUFA/Drivers/Board/UDIP/Buttons.h | 98 +++ LUFA/Drivers/Board/UDIP/LEDs.h | 154 ++++ LUFA/Drivers/Board/UNO/LEDs.h | 130 +++ LUFA/Drivers/Board/USBFOO/Buttons.h | 98 +++ LUFA/Drivers/Board/USBFOO/LEDS.h | 129 +++ LUFA/Drivers/Board/USBKEY/AT45DB642D.h | 115 +++ LUFA/Drivers/Board/USBKEY/Buttons.h | 98 +++ LUFA/Drivers/Board/USBKEY/Dataflash.h | 192 +++++ LUFA/Drivers/Board/USBKEY/Joystick.h | 119 +++ LUFA/Drivers/Board/USBKEY/LEDs.h | 137 +++ LUFA/Drivers/Board/USBTINYMKII/Buttons.h | 98 +++ LUFA/Drivers/Board/USBTINYMKII/LEDs.h | 133 +++ LUFA/Drivers/Board/XPLAIN/AT45DB642D.h | 115 +++ LUFA/Drivers/Board/XPLAIN/Dataflash.h | 190 +++++ LUFA/Drivers/Board/XPLAIN/LEDs.h | 129 +++ LUFA/Drivers/Misc/TerminalCodes.h | 224 +++++ LUFA/Drivers/Peripheral/ADC.h | 72 ++ LUFA/Drivers/Peripheral/AVRU4U6U7/ADC.h | 411 +++++++++ LUFA/Drivers/Peripheral/AVRU4U6U7/TWI.h | 155 ++++ LUFA/Drivers/Peripheral/SPI.h | 208 +++++ LUFA/Drivers/Peripheral/Serial.c | 54 ++ LUFA/Drivers/Peripheral/Serial.h | 167 ++++ LUFA/Drivers/Peripheral/SerialStream.c | 54 ++ LUFA/Drivers/Peripheral/SerialStream.h | 116 +++ LUFA/Drivers/Peripheral/TWI.c | 75 ++ LUFA/Drivers/Peripheral/TWI.h | 72 ++ LUFA/Drivers/USB/Class/Audio.h | 75 ++ LUFA/Drivers/USB/Class/CDC.h | 80 ++ LUFA/Drivers/USB/Class/Common/Audio.h | 701 +++++++++++++++ LUFA/Drivers/USB/Class/Common/CDC.h | 372 ++++++++ LUFA/Drivers/USB/Class/Common/HID.h | 451 ++++++++++ LUFA/Drivers/USB/Class/Common/MIDI.h | 293 +++++++ LUFA/Drivers/USB/Class/Common/MassStorage.h | 362 ++++++++ LUFA/Drivers/USB/Class/Common/Printer.h | 121 +++ LUFA/Drivers/USB/Class/Common/RNDIS.h | 399 +++++++++ LUFA/Drivers/USB/Class/Common/StillImage.h | 161 ++++ LUFA/Drivers/USB/Class/Device/Audio.c | 98 +++ LUFA/Drivers/USB/Class/Device/Audio.h | 336 ++++++++ LUFA/Drivers/USB/Class/Device/CDC.c | 332 ++++++++ LUFA/Drivers/USB/Class/Device/CDC.h | 342 ++++++++ LUFA/Drivers/USB/Class/Device/HID.c | 190 +++++ LUFA/Drivers/USB/Class/Device/HID.h | 222 +++++ LUFA/Drivers/USB/Class/Device/MIDI.c | 148 ++++ LUFA/Drivers/USB/Class/Device/MIDI.h | 189 +++++ LUFA/Drivers/USB/Class/Device/MassStorage.c | 247 ++++++ LUFA/Drivers/USB/Class/Device/MassStorage.h | 177 ++++ LUFA/Drivers/USB/Class/Device/RNDIS.c | 496 +++++++++++ LUFA/Drivers/USB/Class/Device/RNDIS.h | 186 ++++ LUFA/Drivers/USB/Class/HID.h | 81 ++ LUFA/Drivers/USB/Class/Host/CDC.c | 465 ++++++++++ LUFA/Drivers/USB/Class/Host/CDC.h | 334 ++++++++ LUFA/Drivers/USB/Class/Host/HID.c | 387 +++++++++ LUFA/Drivers/USB/Class/Host/HID.h | 316 +++++++ LUFA/Drivers/USB/Class/Host/HIDParser.c | 361 ++++++++ LUFA/Drivers/USB/Class/Host/HIDParser.h | 356 ++++++++ LUFA/Drivers/USB/Class/Host/HIDReportData.h | 142 ++++ LUFA/Drivers/USB/Class/Host/MIDI.c | 215 +++++ LUFA/Drivers/USB/Class/Host/MIDI.h | 201 +++++ LUFA/Drivers/USB/Class/Host/MassStorage.c | 629 ++++++++++++++ LUFA/Drivers/USB/Class/Host/MassStorage.h | 344 ++++++++ LUFA/Drivers/USB/Class/Host/Printer.c | 392 +++++++++ LUFA/Drivers/USB/Class/Host/Printer.h | 282 ++++++ LUFA/Drivers/USB/Class/Host/RNDIS.c | 480 +++++++++++ LUFA/Drivers/USB/Class/Host/RNDIS.h | 290 +++++++ LUFA/Drivers/USB/Class/Host/StillImage.c | 443 ++++++++++ LUFA/Drivers/USB/Class/Host/StillImage.h | 331 ++++++++ LUFA/Drivers/USB/Class/MIDI.h | 83 ++ LUFA/Drivers/USB/Class/MassStorage.h | 80 ++ LUFA/Drivers/USB/Class/Printer.h | 77 ++ LUFA/Drivers/USB/Class/RNDIS.h | 80 ++ LUFA/Drivers/USB/Class/StillImage.h | 75 ++ LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c | 142 ++++ LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h | 287 +++++++ LUFA/Drivers/USB/HighLevel/DeviceStandardReq.c | 382 +++++++++ LUFA/Drivers/USB/HighLevel/DeviceStandardReq.h | 165 ++++ LUFA/Drivers/USB/HighLevel/EndpointStream.c | 233 +++++ LUFA/Drivers/USB/HighLevel/EndpointStream.h | 524 ++++++++++++ LUFA/Drivers/USB/HighLevel/Events.c | 39 + LUFA/Drivers/USB/HighLevel/Events.h | 375 ++++++++ LUFA/Drivers/USB/HighLevel/HostStandardReq.c | 180 ++++ LUFA/Drivers/USB/HighLevel/HostStandardReq.h | 118 +++ LUFA/Drivers/USB/HighLevel/PipeStream.c | 196 +++++ LUFA/Drivers/USB/HighLevel/PipeStream.h | 298 +++++++ LUFA/Drivers/USB/HighLevel/StdDescriptors.h | 692 +++++++++++++++ LUFA/Drivers/USB/HighLevel/StdRequestType.h | 247 ++++++ LUFA/Drivers/USB/HighLevel/StreamCallbacks.h | 87 ++ .../Template/Template_Endpoint_Control_R.c | 48 ++ .../Template/Template_Endpoint_Control_W.c | 56 ++ .../USB/HighLevel/Template/Template_Endpoint_RW.c | 79 ++ .../USB/HighLevel/Template/Template_Pipe_RW.c | 83 ++ LUFA/Drivers/USB/HighLevel/USBMode.h | 138 +++ LUFA/Drivers/USB/HighLevel/USBTask.c | 89 ++ LUFA/Drivers/USB/HighLevel/USBTask.h | 206 +++++ LUFA/Drivers/USB/LowLevel/Device.c | 53 ++ LUFA/Drivers/USB/LowLevel/Device.h | 247 ++++++ LUFA/Drivers/USB/LowLevel/Endpoint.c | 141 +++ LUFA/Drivers/USB/LowLevel/Endpoint.h | 892 +++++++++++++++++++ LUFA/Drivers/USB/LowLevel/Host.c | 355 ++++++++ LUFA/Drivers/USB/LowLevel/Host.h | 527 ++++++++++++ LUFA/Drivers/USB/LowLevel/OTG.h | 155 ++++ LUFA/Drivers/USB/LowLevel/Pipe.c | 140 +++ LUFA/Drivers/USB/LowLevel/Pipe.h | 941 +++++++++++++++++++++ LUFA/Drivers/USB/LowLevel/USBController.c | 232 +++++ LUFA/Drivers/USB/LowLevel/USBController.h | 471 +++++++++++ LUFA/Drivers/USB/LowLevel/USBInterrupt.c | 269 ++++++ LUFA/Drivers/USB/LowLevel/USBInterrupt.h | 106 +++ LUFA/Drivers/USB/USB.h | 408 +++++++++ 151 files changed, 31163 insertions(+) create mode 100644 LUFA/Drivers/Board/ADAFRUITU4/LEDs.h create mode 100644 LUFA/Drivers/Board/ATAVRUSBRF01/Buttons.h create mode 100644 LUFA/Drivers/Board/ATAVRUSBRF01/LEDs.h create mode 100644 LUFA/Drivers/Board/BENITO/Buttons.h create mode 100644 LUFA/Drivers/Board/BENITO/LEDs.h create mode 100644 LUFA/Drivers/Board/BLACKCAT/LEDs.h create mode 100644 LUFA/Drivers/Board/BUI/LEDs.h create mode 100644 LUFA/Drivers/Board/BUMBLEB/Buttons.h create mode 100644 LUFA/Drivers/Board/BUMBLEB/Joystick.h create mode 100644 LUFA/Drivers/Board/BUMBLEB/LEDs.h create mode 100644 LUFA/Drivers/Board/Buttons.h create mode 100644 LUFA/Drivers/Board/CULV3/Buttons.h create mode 100644 LUFA/Drivers/Board/CULV3/LEDs.h create mode 100644 LUFA/Drivers/Board/Dataflash.h create mode 100644 LUFA/Drivers/Board/EVK527/AT45DB321C.h create mode 100644 LUFA/Drivers/Board/EVK527/Buttons.h create mode 100644 LUFA/Drivers/Board/EVK527/Dataflash.h create mode 100644 LUFA/Drivers/Board/EVK527/Joystick.h create mode 100644 LUFA/Drivers/Board/EVK527/LEDs.h create mode 100644 LUFA/Drivers/Board/JMDBU2/Buttons.h create mode 100644 LUFA/Drivers/Board/JMDBU2/LEDs.h create mode 100644 LUFA/Drivers/Board/Joystick.h create mode 100644 LUFA/Drivers/Board/LEDs.h create mode 100644 LUFA/Drivers/Board/MAXIMUS/LEDs.h create mode 100644 LUFA/Drivers/Board/MICROSIN162/Buttons.h create mode 100644 LUFA/Drivers/Board/MICROSIN162/LEDs.h create mode 100644 LUFA/Drivers/Board/MINIMUS/Buttons.h create mode 100644 LUFA/Drivers/Board/MINIMUS/LEDs.h create mode 100644 LUFA/Drivers/Board/OLIMEX162/Buttons.h create mode 100644 LUFA/Drivers/Board/OLIMEX162/LEDs.h create mode 100644 LUFA/Drivers/Board/RZUSBSTICK/LEDs.h create mode 100644 LUFA/Drivers/Board/STK525/AT45DB321C.h create mode 100644 LUFA/Drivers/Board/STK525/Buttons.h create mode 100644 LUFA/Drivers/Board/STK525/Dataflash.h create mode 100644 LUFA/Drivers/Board/STK525/Joystick.h create mode 100644 LUFA/Drivers/Board/STK525/LEDs.h create mode 100644 LUFA/Drivers/Board/STK526/AT45DB642D.h create mode 100644 LUFA/Drivers/Board/STK526/Buttons.h create mode 100644 LUFA/Drivers/Board/STK526/Dataflash.h create mode 100644 LUFA/Drivers/Board/STK526/Joystick.h create mode 100644 LUFA/Drivers/Board/STK526/LEDs.h create mode 100644 LUFA/Drivers/Board/TEENSY/LEDs.h create mode 100644 LUFA/Drivers/Board/Temperature.c create mode 100644 LUFA/Drivers/Board/Temperature.h create mode 100644 LUFA/Drivers/Board/UDIP/Buttons.h create mode 100644 LUFA/Drivers/Board/UDIP/LEDs.h create mode 100644 LUFA/Drivers/Board/UNO/LEDs.h create mode 100644 LUFA/Drivers/Board/USBFOO/Buttons.h create mode 100644 LUFA/Drivers/Board/USBFOO/LEDS.h create mode 100644 LUFA/Drivers/Board/USBKEY/AT45DB642D.h create mode 100644 LUFA/Drivers/Board/USBKEY/Buttons.h create mode 100644 LUFA/Drivers/Board/USBKEY/Dataflash.h create mode 100644 LUFA/Drivers/Board/USBKEY/Joystick.h create mode 100644 LUFA/Drivers/Board/USBKEY/LEDs.h create mode 100644 LUFA/Drivers/Board/USBTINYMKII/Buttons.h create mode 100644 LUFA/Drivers/Board/USBTINYMKII/LEDs.h create mode 100644 LUFA/Drivers/Board/XPLAIN/AT45DB642D.h create mode 100644 LUFA/Drivers/Board/XPLAIN/Dataflash.h create mode 100644 LUFA/Drivers/Board/XPLAIN/LEDs.h create mode 100644 LUFA/Drivers/Misc/TerminalCodes.h create mode 100644 LUFA/Drivers/Peripheral/ADC.h create mode 100644 LUFA/Drivers/Peripheral/AVRU4U6U7/ADC.h create mode 100644 LUFA/Drivers/Peripheral/AVRU4U6U7/TWI.h create mode 100644 LUFA/Drivers/Peripheral/SPI.h create mode 100644 LUFA/Drivers/Peripheral/Serial.c create mode 100644 LUFA/Drivers/Peripheral/Serial.h create mode 100644 LUFA/Drivers/Peripheral/SerialStream.c create mode 100644 LUFA/Drivers/Peripheral/SerialStream.h create mode 100644 LUFA/Drivers/Peripheral/TWI.c create mode 100644 LUFA/Drivers/Peripheral/TWI.h create mode 100644 LUFA/Drivers/USB/Class/Audio.h create mode 100644 LUFA/Drivers/USB/Class/CDC.h create mode 100644 LUFA/Drivers/USB/Class/Common/Audio.h create mode 100644 LUFA/Drivers/USB/Class/Common/CDC.h create mode 100644 LUFA/Drivers/USB/Class/Common/HID.h create mode 100644 LUFA/Drivers/USB/Class/Common/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/Common/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/Common/Printer.h create mode 100644 LUFA/Drivers/USB/Class/Common/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/Common/StillImage.h create mode 100644 LUFA/Drivers/USB/Class/Device/Audio.c create mode 100644 LUFA/Drivers/USB/Class/Device/Audio.h create mode 100644 LUFA/Drivers/USB/Class/Device/CDC.c create mode 100644 LUFA/Drivers/USB/Class/Device/CDC.h create mode 100644 LUFA/Drivers/USB/Class/Device/HID.c create mode 100644 LUFA/Drivers/USB/Class/Device/HID.h create mode 100644 LUFA/Drivers/USB/Class/Device/MIDI.c create mode 100644 LUFA/Drivers/USB/Class/Device/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/Device/MassStorage.c create mode 100644 LUFA/Drivers/USB/Class/Device/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/Device/RNDIS.c create mode 100644 LUFA/Drivers/USB/Class/Device/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/HID.h create mode 100644 LUFA/Drivers/USB/Class/Host/CDC.c create mode 100644 LUFA/Drivers/USB/Class/Host/CDC.h create mode 100644 LUFA/Drivers/USB/Class/Host/HID.c create mode 100644 LUFA/Drivers/USB/Class/Host/HID.h create mode 100644 LUFA/Drivers/USB/Class/Host/HIDParser.c create mode 100644 LUFA/Drivers/USB/Class/Host/HIDParser.h create mode 100644 LUFA/Drivers/USB/Class/Host/HIDReportData.h create mode 100644 LUFA/Drivers/USB/Class/Host/MIDI.c create mode 100644 LUFA/Drivers/USB/Class/Host/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/Host/MassStorage.c create mode 100644 LUFA/Drivers/USB/Class/Host/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/Host/Printer.c create mode 100644 LUFA/Drivers/USB/Class/Host/Printer.h create mode 100644 LUFA/Drivers/USB/Class/Host/RNDIS.c create mode 100644 LUFA/Drivers/USB/Class/Host/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/Host/StillImage.c create mode 100644 LUFA/Drivers/USB/Class/Host/StillImage.h create mode 100644 LUFA/Drivers/USB/Class/MIDI.h create mode 100644 LUFA/Drivers/USB/Class/MassStorage.h create mode 100644 LUFA/Drivers/USB/Class/Printer.h create mode 100644 LUFA/Drivers/USB/Class/RNDIS.h create mode 100644 LUFA/Drivers/USB/Class/StillImage.h create mode 100644 LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c create mode 100644 LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h create mode 100644 LUFA/Drivers/USB/HighLevel/DeviceStandardReq.c create mode 100644 LUFA/Drivers/USB/HighLevel/DeviceStandardReq.h create mode 100644 LUFA/Drivers/USB/HighLevel/EndpointStream.c create mode 100644 LUFA/Drivers/USB/HighLevel/EndpointStream.h create mode 100644 LUFA/Drivers/USB/HighLevel/Events.c create mode 100644 LUFA/Drivers/USB/HighLevel/Events.h create mode 100644 LUFA/Drivers/USB/HighLevel/HostStandardReq.c create mode 100644 LUFA/Drivers/USB/HighLevel/HostStandardReq.h create mode 100644 LUFA/Drivers/USB/HighLevel/PipeStream.c create mode 100644 LUFA/Drivers/USB/HighLevel/PipeStream.h create mode 100644 LUFA/Drivers/USB/HighLevel/StdDescriptors.h create mode 100644 LUFA/Drivers/USB/HighLevel/StdRequestType.h create mode 100644 LUFA/Drivers/USB/HighLevel/StreamCallbacks.h create mode 100644 LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_R.c create mode 100644 LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_W.c create mode 100644 LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_RW.c create mode 100644 LUFA/Drivers/USB/HighLevel/Template/Template_Pipe_RW.c create mode 100644 LUFA/Drivers/USB/HighLevel/USBMode.h create mode 100644 LUFA/Drivers/USB/HighLevel/USBTask.c create mode 100644 LUFA/Drivers/USB/HighLevel/USBTask.h create mode 100644 LUFA/Drivers/USB/LowLevel/Device.c create mode 100644 LUFA/Drivers/USB/LowLevel/Device.h create mode 100644 LUFA/Drivers/USB/LowLevel/Endpoint.c create mode 100644 LUFA/Drivers/USB/LowLevel/Endpoint.h create mode 100644 LUFA/Drivers/USB/LowLevel/Host.c create mode 100644 LUFA/Drivers/USB/LowLevel/Host.h create mode 100644 LUFA/Drivers/USB/LowLevel/OTG.h create mode 100644 LUFA/Drivers/USB/LowLevel/Pipe.c create mode 100644 LUFA/Drivers/USB/LowLevel/Pipe.h create mode 100644 LUFA/Drivers/USB/LowLevel/USBController.c create mode 100644 LUFA/Drivers/USB/LowLevel/USBController.h create mode 100644 LUFA/Drivers/USB/LowLevel/USBInterrupt.c create mode 100644 LUFA/Drivers/USB/LowLevel/USBInterrupt.h create mode 100644 LUFA/Drivers/USB/USB.h (limited to 'LUFA/Drivers') diff --git a/LUFA/Drivers/Board/ADAFRUITU4/LEDs.h b/LUFA/Drivers/Board/ADAFRUITU4/LEDs.h new file mode 100644 index 0000000..39b6256 --- /dev/null +++ b/LUFA/Drivers/Board/ADAFRUITU4/LEDs.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Adafruit U4 Breakout board. + * + * Board specific LED driver header for the Adafruit U4 Breakout board (http://ladyada.net/products/atmega32u4breakout). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_ADAFRUITU4 ADAFRUITU4 + * + * Board specific LED driver header for the Adafruit U4 Breakout board (http://ladyada.net/products/atmega32u4breakout). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_ADAFRUITU4_H__ +#define __LEDS_ADAFRUITU4_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for the none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRE |= LEDS_ALL_LEDS; + PORTE &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTE |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTE &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTE = ((PORTE & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTE = ((PORTE & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTE = (PORTE ^ (LEDMask & LEDS_ALL_LEDS)); + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTE & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/ATAVRUSBRF01/Buttons.h b/LUFA/Drivers/Board/ATAVRUSBRF01/Buttons.h new file mode 100644 index 0000000..80063bd --- /dev/null +++ b/LUFA/Drivers/Board/ATAVRUSBRF01/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Atmel ATAVRUSBRF01. + * + * Board specific Buttons driver header for the Atmel ATAVRUSBRF01. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_ATAVRUSBRF01 ATAVRUSBRF01 + * + * Board specific Buttons driver header for the Atmel ATAVRUSBRF01. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_ATAVRUSBRF01_H__ +#define __BUTTONS_ATAVRUSBRF01_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/ATAVRUSBRF01/LEDs.h b/LUFA/Drivers/Board/ATAVRUSBRF01/LEDs.h new file mode 100644 index 0000000..f52df99 --- /dev/null +++ b/LUFA/Drivers/Board/ATAVRUSBRF01/LEDs.h @@ -0,0 +1,141 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Atmel ATAVRUSBRF01. + * + * Board specific LED driver header for the Atmel ATAVRUSBRF01. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_ATAVRUSBRF01 ATAVRUSBRF01 + * + * Board specific LED driver header for the Atmel ATAVRUSBRF01. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_ATAVRUSBRF01_H__ +#define __LEDS_ATAVRUSBRF01_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define LEDS_PORTD_LEDS (LEDS_LED1 | LEDS_LED2) + #define LEDS_PORTE_LEDS (LEDS_LED3 | LEDS_LED4) + + #define LEDS_PORTE_MASK_SHIFT 4 + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 0) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 1) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= (LEDMask & LEDS_ALL_LEDS); + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~(LEDMask & LEDS_ALL_LEDS); + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = (PORTD & ~LEDS_ALL_LEDS) | (LEDMask & LEDS_ALL_LEDS); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/BENITO/Buttons.h b/LUFA/Drivers/Board/BENITO/Buttons.h new file mode 100644 index 0000000..d47e017 --- /dev/null +++ b/LUFA/Drivers/Board/BENITO/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Tempusdictum Benito. + * + * Board specific Buttons driver header for the Tempusdictum Benito (http://dorkbotpdx.org/wiki/benito). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_BENITO BENITO + * + * Board specific Buttons driver header for the Tempusdictum Benito (http://dorkbotpdx.org/wiki/benito). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_BENITO_H__ +#define __BUTTONS_BENITO_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/BENITO/LEDs.h b/LUFA/Drivers/Board/BENITO/LEDs.h new file mode 100644 index 0000000..72c0d24 --- /dev/null +++ b/LUFA/Drivers/Board/BENITO/LEDs.h @@ -0,0 +1,130 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Tempusdictum Benito. + * + * Board specific LED driver header for the Tempusdictum Benito (http://dorkbotpdx.org/wiki/benito). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_BENITO BENITO + * + * Board specific LED driver header for the Tempusdictum Benito (http://dorkbotpdx.org/wiki/benito). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_BENITO_H__ +#define __LEDS_BENITO_H__ + + /* Includes: */ + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 7) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRC |= LEDS_ALL_LEDS; + PORTC |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTC &= ~LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTC |= LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTC = ((PORTC | LEDS_ALL_LEDS) & ~LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTC = ((PORTC | LEDMask) & ~ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTC ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTC & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/BLACKCAT/LEDs.h b/LUFA/Drivers/Board/BLACKCAT/LEDs.h new file mode 100644 index 0000000..8ca1b95 --- /dev/null +++ b/LUFA/Drivers/Board/BLACKCAT/LEDs.h @@ -0,0 +1,131 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the BLACKCAT USB JTAG. + * + * Board specific LED driver header for the TCNISO Blackcat USB JTAG (http://www.embeddedcomputers.net/products/BlackcatUSB/. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_BLACKCAT BLACKCAT + * + * Board specific LED driver header for the TCNISO Blackcat USB JTAG (http://www.embeddedcomputers.net/products/BlackcatUSB/. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_BLACKCAT_H__ +#define __LEDS_BLACKCAT_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 3) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ diff --git a/LUFA/Drivers/Board/BUI/LEDs.h b/LUFA/Drivers/Board/BUI/LEDs.h new file mode 100644 index 0000000..b1e3a99 --- /dev/null +++ b/LUFA/Drivers/Board/BUI/LEDs.h @@ -0,0 +1,132 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Busware BUI. + * + * Board specific LED driver header for the Busware BUI (http://www.busware.de/tiki-index.php?page=BUI). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_BUI BUI + * + * Board specific LED driver header for the Busware BUI (http://www.busware.de/tiki-index.php?page=BUI). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_BUI_H__ +#define __LEDS_BUI_H__ + + /* Includes: */ + #include + +/* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 2) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 3) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 (1 << 4) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRC |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTC |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTC &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTC = (PORTC & ~LEDS_ALL_LEDS) | LEDMask; + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTC = (PORTC & ~LEDMask) | ActiveMask; + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTC ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTC & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/BUMBLEB/Buttons.h b/LUFA/Drivers/Board/BUMBLEB/Buttons.h new file mode 100644 index 0000000..b4c1f80 --- /dev/null +++ b/LUFA/Drivers/Board/BUMBLEB/Buttons.h @@ -0,0 +1,103 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Fletchtronics BUMBLEB. + * + * Board specific Buttons driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). + * + * The BUMBLEB third-party board does not include any on-board peripherals, but does have an officially recommended + * external peripheral layout for buttons, LEDs and a Joystick. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_BUMBLEB BUMBLEB + * + * Board specific buttons driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). The BUMBLEB + * third-party board does not include any on-board peripherals, but does have an officially recommended external peripheral + * layout for buttons, LEDs and a Joystick. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_BUMBLEB_H__ +#define __BUTTONS_BUMBLEB_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/BUMBLEB/Joystick.h b/LUFA/Drivers/Board/BUMBLEB/Joystick.h new file mode 100644 index 0000000..7197726 --- /dev/null +++ b/LUFA/Drivers/Board/BUMBLEB/Joystick.h @@ -0,0 +1,120 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific joystick driver header for the Fletchtronics BUMLEB. + * + * Board specific joystick driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). + * + * The BUMBLEB third-party board does not include any on-board peripherals, but does have an officially recommended + * external peripheral layout for buttons, LEDs and a Joystick. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + */ + +/** \ingroup Group_Joystick + * @defgroup Group_Joystick_BUMBLEB BUMBLEB + * + * Board specific joystick driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). The BUMBLEB + * third-party board does not include any on-board peripherals, but does have an officially recommended external peripheral + * layout for buttons, LEDs and a Joystick. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + * + * @{ + */ + +#ifndef __JOYSTICK_BUMBLEB_H__ +#define __JOYSTICK_BUMBLEB_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_JOYSTICK_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define JOY_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for the joystick being pushed in the left direction. */ + #define JOY_LEFT (1 << 2) + + /** Mask for the joystick being pushed in the upward direction. */ + #define JOY_UP (1 << 3) + + /** Mask for the joystick being pushed in the right direction. */ + #define JOY_RIGHT (1 << 0) + + /** Mask for the joystick being pushed in the downward direction. */ + #define JOY_DOWN (1 << 1) + + /** Mask for the joystick being pushed inward. */ + #define JOY_PRESS (1 << 4) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Joystick_Init(void) + { + DDRD &= ~JOY_MASK; + PORTD |= JOY_MASK; + } + + static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Joystick_GetStatus(void) + { + return (uint8_t)(~PIND & JOY_MASK); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/BUMBLEB/LEDs.h b/LUFA/Drivers/Board/BUMBLEB/LEDs.h new file mode 100644 index 0000000..839f188 --- /dev/null +++ b/LUFA/Drivers/Board/BUMBLEB/LEDs.h @@ -0,0 +1,143 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Fletchtronics BUMBLEB. + * + * Board specific LED driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). + * + * The BUMBLEB third-party board does not include any on-board peripherals, but does have an officially recommended + * external peripheral layout for buttons, LEDs and a Joystick. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_BUMBLEB BUMBLEB + * + * Board specific LED driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). The BUMBLEB + * third-party board does not include any on-board peripherals, but does have an officially recommended external + * peripheral layout for buttons, LEDs and a Joystick. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_BUMBLEB_H__ +#define __LEDS_BUMBLEB_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 5) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 (1 << 6) + + /** LED mask for the fourth LED on the board. */ + #define LEDS_LED4 (1 << 7) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRB |= LEDS_ALL_LEDS; + PORTB &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LedMask) + { + PORTB |= LedMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LedMask) + { + PORTB &= ~LedMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LedMask) + { + PORTB = ((PORTB & ~LEDS_ALL_LEDS) | LedMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LedMask, + const uint8_t ActiveMask) + { + PORTB = ((PORTB & ~LedMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTB ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTB & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/Buttons.h b/LUFA/Drivers/Board/Buttons.h new file mode 100644 index 0000000..57fcc63 --- /dev/null +++ b/LUFA/Drivers/Board/Buttons.h @@ -0,0 +1,135 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the board digital button driver. + * + * This file is the master dispatch header file for the board-specific Buttons driver, for boards containing + * physical pushbuttons connected to the AVR's GPIO pins. + * + * User code should include this file, which will in turn include the correct Button driver header file for the + * currently selected board. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/Buttons.h file in the user project + * directory. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + */ + +/** \ingroup Group_BoardDrivers + * @defgroup Group_Buttons Buttons Driver - LUFA/Drivers/Board/Buttons.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Module Description + * Hardware buttons driver. This provides an easy to use driver for the hardware buttons present on many boards. + * It provides a way to easily configure and check the status of all the buttons on the board so that appropriate + * actions can be taken. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/Dataflash.h file in the user project + * directory. Otherwise, it will include the appropriate built in board driver header file. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + * + * @{ + */ + +#ifndef __BUTTONS_H__ +#define __BUTTONS_H__ + + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __INCLUDE_FROM_BUTTONS_H + #define INCLUDE_FROM_BUTTONS_H + #endif + + /* Includes: */ + #include "../../Common/Common.h" + + #if (BOARD == BOARD_NONE) + #error The Board Buttons driver cannot be used if the makefile BOARD option is not set. + #elif (BOARD == BOARD_USBKEY) + #include "USBKEY/Buttons.h" + #elif (BOARD == BOARD_STK525) + #include "STK525/Buttons.h" + #elif (BOARD == BOARD_STK526) + #include "STK526/Buttons.h" + #elif (BOARD == BOARD_ATAVRUSBRF01) + #include "ATAVRUSBRF01/Buttons.h" + #elif (BOARD == BOARD_BUMBLEB) + #include "BUMBLEB/Buttons.h" + #elif (BOARD == BOARD_EVK527) + #include "EVK527/Buttons.h" + #elif (BOARD == BOARD_USBTINYMKII) + #include "USBTINYMKII/Buttons.h" + #elif (BOARD == BOARD_BENITO) + #include "BENITO/Buttons.h" + #elif (BOARD == BOARD_JMDBU2) + #include "JMDBU2/Buttons.h" + #elif (BOARD == BOARD_OLIMEX162) + #include "OLIMEX162/Buttons.h" + #elif (BOARD == BOARD_USBFOO) + #include "USBFOO/Buttons.h" + #elif (BOARD == BOARD_UDIP) + #include "UDIP/Buttons.h" + #elif (BOARD == BOARD_CULV3) + #include "CULV3/Buttons.h" + #elif (BOARD == BOARD_MINIMUS) + #include "MINIMUS/Buttons.h" + #elif (BOARD == BOARD_MICROSIN162) + #include "MICROSIN162/Buttons.h" + #elif (BOARD == BOARD_USER) + #include "Board/Buttons.h" + #else + #error The selected board does not contain any GPIO buttons. + #endif + + /* Pseudo-Functions for Doxygen: */ + #if defined(__DOXYGEN__) + /** Initialises the BUTTONS driver, so that the current button position can be read. This sets the appropriate + * I/O pins to an inputs with pull-ups enabled. + * + * This must be called before any Button driver functions are used. + */ + static inline void Buttons_Init(void); + + /** Returns a mask indicating which board buttons are currently pressed. + * + * \return Mask indicating which board buttons are currently pressed. + */ + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/CULV3/Buttons.h b/LUFA/Drivers/Board/CULV3/Buttons.h new file mode 100644 index 0000000..088559a --- /dev/null +++ b/LUFA/Drivers/Board/CULV3/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Busware CULV3. + * + * Board specific LED driver header for the Busware CUL V3 (http://busware.de/tiki-index.php?page=CUL). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_CULV3 CULV3 + * + * Board specific LED driver header for the Busware CUL V3 (http://busware.de/tiki-index.php?page=CUL). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __BUTTONS_CULV3_H__ +#define __BUTTONS_CULV3_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 2) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRE &= ~BUTTONS_BUTTON1; + PORTE |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/CULV3/LEDs.h b/LUFA/Drivers/Board/CULV3/LEDs.h new file mode 100644 index 0000000..52fd337 --- /dev/null +++ b/LUFA/Drivers/Board/CULV3/LEDs.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Busware CUL V3. + * + * Board specific LED driver header for the Busware CUL V3 (http://busware.de/tiki-index.php?page=CUL). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_CULV3 CULV3 + * + * Board specific LED driver header for the Busware CUL V3 (http://busware.de/tiki-index.php?page=CUL). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_CULV3_H__ +#define __LEDS_CULV3_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for the none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRE |= LEDS_ALL_LEDS; + PORTE &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTE |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTE &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTE = ((PORTE & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTE = ((PORTE & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTE = (PORTE ^ (LEDMask & LEDS_ALL_LEDS)); + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTE & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/Dataflash.h b/LUFA/Drivers/Board/Dataflash.h new file mode 100644 index 0000000..9c6bb8b --- /dev/null +++ b/LUFA/Drivers/Board/Dataflash.h @@ -0,0 +1,212 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the board dataflash IC driver. + * + * This file is the master dispatch header file for the board-specific dataflash driver, for boards containing + * dataflash ICs for external non-volatile storage. + * + * User code should include this file, which will in turn include the correct dataflash driver header file for + * the currently selected board. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/Dataflash.h file in the user project + * directory. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + */ + +/** \ingroup Group_BoardDrivers + * @defgroup Group_Dataflash Dataflash Driver - LUFA/Drivers/Board/Dataflash.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Module Description + * Dataflash driver. This module provides an easy to use interface for the Dataflash ICs located on many boards, + * for the storage of large amounts of data into the Dataflash's non-volatile memory. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/Dataflash.h file in the user project + * directory. Otherwise, it will include the appropriate built in board driver header file. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + * + * @{ + */ + +#ifndef __DATAFLASH_H__ +#define __DATAFLASH_H__ + + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __INCLUDE_FROM_DATAFLASH_H + #define INCLUDE_FROM_DATAFLASH_H + #endif + + /* Includes: */ + #include "../Peripheral/SPI.h" + #include "../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __GET_DATAFLASH_MASK2(x, y) x ## y + #define __GET_DATAFLASH_MASK(x) __GET_DATAFLASH_MASK2(DATAFLASH_CHIP,x) + #endif + + /** Retrieves the Dataflash chip select mask for the given Dataflash chip index. + * + * \param[in] index Index of the dataflash chip mask to retrieve + * + * \return Mask for the given Dataflash chip's /CS pin + */ + #define DATAFLASH_CHIP_MASK(index) __GET_DATAFLASH_MASK(index) + + /* Inline Functions: */ + /** Initialises the dataflash driver so that commands and data may be sent to an attached dataflash IC. + * The AVR's SPI driver MUST be initialized before any of the dataflash commands are used. + */ + static inline void Dataflash_Init(void); + + /** Determines the currently selected dataflash chip. + * + * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected + * or a DATAFLASH_CHIPn mask (where n is the chip number). + */ + static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + + /** Selects the given dataflash chip. + * + * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is + * the chip number). + */ + static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE; + + /** Deselects the current dataflash chip, so that no dataflash is selected. */ + static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE; + + /** Selects a dataflash IC from the given page number, which should range from 0 to + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one + * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside + * the total number of pages contained in the boards dataflash ICs, all dataflash ICs + * are deselected. + * + * \param[in] PageAddress Address of the page to manipulate, ranging from + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). + */ + static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress); + + /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive + * a new command. + */ + static inline void Dataflash_ToggleSelectedChipCS(void); + + /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main + * memory page program or main memory to buffer transfer. + */ + static inline void Dataflash_WaitWhileBusy(void); + + /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with + * dataflash commands which require a complete 24-byte address. + * + * \param[in] PageAddress Page address within the selected dataflash IC + * \param[in] BufferByte Address within the dataflash's buffer + */ + static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, + const uint16_t BufferByte); + + /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash. + * + * \param[in] Byte of data to send to the dataflash + * + * \return Last response byte from the dataflash + */ + static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; + static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) + { + return SPI_TransferByte(Byte); + } + + /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash. + * + * \param[in] Byte of data to send to the dataflash + */ + static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; + static inline void Dataflash_SendByte(const uint8_t Byte) + { + SPI_SendByte(Byte); + } + + /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash. + * + * \return Last response byte from the dataflash + */ + static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Dataflash_ReceiveByte(void) + { + return SPI_ReceiveByte(); + } + + /* Includes: */ + #if (BOARD == BOARD_NONE) + #error The Board Buttons driver cannot be used if the makefile BOARD option is not set. + #elif (BOARD == BOARD_USBKEY) + #include "USBKEY/Dataflash.h" + #elif (BOARD == BOARD_STK525) + #include "STK525/Dataflash.h" + #elif (BOARD == BOARD_STK526) + #include "STK526/Dataflash.h" + #elif (BOARD == BOARD_XPLAIN) + #include "XPLAIN/Dataflash.h" + #elif (BOARD == BOARD_XPLAIN_REV1) + #include "XPLAIN/Dataflash.h" + #elif (BOARD == BOARD_EVK527) + #include "EVK527/Dataflash.h" + #elif (BOARD == BOARD_USER) + #include "Board/Dataflash.h" + #else + #error The selected board does not contain a dataflash IC. + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/EVK527/AT45DB321C.h b/LUFA/Drivers/Board/EVK527/AT45DB321C.h new file mode 100644 index 0000000..9bcf510 --- /dev/null +++ b/LUFA/Drivers/Board/EVK527/AT45DB321C.h @@ -0,0 +1,105 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash commands header for the AT45DB321C as mounted on the Atmel EVK527. + * + * Board specific Dataflash commands header for the AT45DB321C as mounted on the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash_EVK527 + * @defgroup Group_Dataflash_EVK527_AT45DB321C AT45DB321C + * + * Board specific Dataflash commands header for the AT45DB321C as mounted on the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_CMDS_H__ +#define __DATAFLASH_CMDS_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name Dataflash Status Values */ + //@{ + #define DF_STATUS_READY (1 << 7) + #define DF_STATUS_COMPMISMATCH (1 << 6) + #define DF_STATUS_SECTORPROTECTION_ON (1 << 1) + //@} + + #define DF_MANUFACTURER_ATMEL 0x1F + + /** \name Dataflash Commands */ + //@{ + #define DF_CMD_GETSTATUS 0xD7 + + #define DF_CMD_MAINMEMTOBUFF1 0x53 + #define DF_CMD_MAINMEMTOBUFF2 0x55 + #define DF_CMD_MAINMEMTOBUFF1COMP 0x60 + #define DF_CMD_MAINMEMTOBUFF2COMP 0x61 + #define DF_CMD_AUTOREWRITEBUFF1 0x58 + #define DF_CMD_AUTOREWRITEBUFF2 0x59 + + #define DF_CMD_MAINMEMPAGEREAD 0xD2 + #define DF_CMD_CONTARRAYREAD_LF 0xE8 + #define DF_CMD_BUFF1READ_LF 0xD4 + #define DF_CMD_BUFF2READ_LF 0xD6 + + #define DF_CMD_BUFF1WRITE 0x84 + #define DF_CMD_BUFF2WRITE 0x87 + #define DF_CMD_BUFF1TOMAINMEMWITHERASE 0x83 + #define DF_CMD_BUFF2TOMAINMEMWITHERASE 0x86 + #define DF_CMD_BUFF1TOMAINMEM 0x88 + #define DF_CMD_BUFF2TOMAINMEM 0x89 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF1 0x82 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF2 0x85 + + #define DF_CMD_PAGEERASE 0x81 + #define DF_CMD_BLOCKERASE 0x50 + + #define DF_CMD_SECTORPROTECTIONOFF ((char[]){0x3D, 0x2A, 0x7F, 0xCF}) + #define DF_CMD_SECTORPROTECTIONOFF_BYTE1 0x3D + #define DF_CMD_SECTORPROTECTIONOFF_BYTE2 0x2A + #define DF_CMD_SECTORPROTECTIONOFF_BYTE3 0x7F + #define DF_CMD_SECTORPROTECTIONOFF_BYTE4 0xCF + + #define DF_CMD_READMANUFACTURERDEVICEINFO 0x9F + //@} + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/EVK527/Buttons.h b/LUFA/Drivers/Board/EVK527/Buttons.h new file mode 100644 index 0000000..4f6b536 --- /dev/null +++ b/LUFA/Drivers/Board/EVK527/Buttons.h @@ -0,0 +1,104 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Atmel EVK527. + * + * Board specific Buttons driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_EVK527 EVK527 + * + * Board specific Buttons driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_EVK527_H__ +#define __BUTTONS_EVK527_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 2) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRE &= ~BUTTONS_BUTTON1; + PORTE |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/EVK527/Dataflash.h b/LUFA/Drivers/Board/EVK527/Dataflash.h new file mode 100644 index 0000000..9f6c6d8 --- /dev/null +++ b/LUFA/Drivers/Board/EVK527/Dataflash.h @@ -0,0 +1,184 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash driver header for the Atmel EVK527. + * + * Board specific Dataflash driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash + * @defgroup Group_Dataflash_EVK527 EVK527 + * + * Board specific Dataflash driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_EVK527_H__ +#define __DATAFLASH_EVK527_H__ + + /* Includes: */ + #include "AT45DB321C.h" + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_DATAFLASH_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define DATAFLASH_CHIPCS_MASK (1 << 6) + #define DATAFLASH_CHIPCS_DDR DDRE + #define DATAFLASH_CHIPCS_PORT PORTE + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Constant indicating the total number of dataflash ICs mounted on the selected board. */ + #define DATAFLASH_TOTALCHIPS 1 + + /** Mask for no dataflash chip selected. */ + #define DATAFLASH_NO_CHIP DATAFLASH_CHIPCS_MASK + + /** Mask for the first dataflash chip selected. */ + #define DATAFLASH_CHIP1 0 + + /** Internal main memory page size for the board's dataflash IC. */ + #define DATAFLASH_PAGE_SIZE 512 + + /** Total number of pages inside the board's dataflash IC. */ + #define DATAFLASH_PAGES 8192 + + /* Inline Functions: */ + /** Initialises the dataflash driver so that commands and data may be sent to an attached dataflash IC. + * The AVR's SPI driver MUST be initialized before any of the dataflash commands are used. + */ + static inline void Dataflash_Init(void) + { + DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK; + DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK; + } + + /** Determines the currently selected dataflash chip. + * + * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected + * or a DATAFLASH_CHIPn mask (where n is the chip number). + */ + static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Dataflash_GetSelectedChip(void) + { + return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK); + } + + /** Selects the given dataflash chip. + * + * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is + * the chip number). + */ + static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE; + static inline void Dataflash_SelectChip(const uint8_t ChipMask) + { + DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask); + } + + /** Deselects the current dataflash chip, so that no dataflash is selected. */ + static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE; + static inline void Dataflash_DeselectChip(void) + { + Dataflash_SelectChip(DATAFLASH_NO_CHIP); + } + + /** Selects a dataflash IC from the given page number, which should range from 0 to + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one + * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside + * the total number of pages contained in the boards dataflash ICs, all dataflash ICs + * are deselected. + * + * \param[in] PageAddress Address of the page to manipulate, ranging from + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). + */ + static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress) + { + Dataflash_DeselectChip(); + + if (PageAddress >= DATAFLASH_PAGES) + return; + + Dataflash_SelectChip(DATAFLASH_CHIP1); + } + + /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive + * a new command. + */ + static inline void Dataflash_ToggleSelectedChipCS(void) + { + uint8_t SelectedChipMask = Dataflash_GetSelectedChip(); + + Dataflash_DeselectChip(); + Dataflash_SelectChip(SelectedChipMask); + } + + /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main + * memory page program or main memory to buffer transfer. + */ + static inline void Dataflash_WaitWhileBusy(void) + { + Dataflash_ToggleSelectedChipCS(); + Dataflash_SendByte(DF_CMD_GETSTATUS); + while (!(Dataflash_ReceiveByte() & DF_STATUS_READY)); + Dataflash_ToggleSelectedChipCS(); + } + + /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with + * dataflash commands which require a complete 24-byte address. + * + * \param[in] PageAddress Page address within the selected dataflash IC + * \param[in] BufferByte Address within the dataflash's buffer + */ + static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, + const uint16_t BufferByte) + { + Dataflash_SendByte(PageAddress >> 5); + Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8)); + Dataflash_SendByte(BufferByte); + } + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/EVK527/Joystick.h b/LUFA/Drivers/Board/EVK527/Joystick.h new file mode 100644 index 0000000..06c14fe --- /dev/null +++ b/LUFA/Drivers/Board/EVK527/Joystick.h @@ -0,0 +1,119 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific joystick driver header for the Atmel EVK527. + * + * Board specific joystick driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + */ + +/** \ingroup Group_Joystick + * @defgroup Group_Joystick_EVK527 EVK527 + * + * Board specific joystick driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + * + * @{ + */ + +#ifndef __JOYSTICK_EVK527_H__ +#define __JOYSTICK_EVK527_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_JOYSTICK_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define JOY_FMASK ((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)) + #define JOY_CMASK (1 << 6)) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for the joystick being pushed in the left direction. */ + #define JOY_LEFT (1 << 4) + + /** Mask for the joystick being pushed in the right direction. */ + #define JOY_RIGHT (1 << 7) + + /** Mask for the joystick being pushed in the upward direction. */ + #define JOY_UP (1 << 5) + + /** Mask for the joystick being pushed in the downward direction. */ + #define JOY_DOWN ((1 << 6) >> 3) + + /** Mask for the joystick being pushed inward. */ + #define JOY_PRESS (1 << 6) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Joystick_Init(void) + { + DDRF &= ~(JOY_FMASK); + DDRC &= ~(JOY_CMASK); + + PORTF |= JOY_FMASK; + PORTC |= JOY_CMASK; + } + + static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Joystick_GetStatus(void) + { + return (((uint8_t)~PINF & JOY_FMASK) | (((uint8_t)~PINC & JOY_CMASK) >> 3)); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/EVK527/LEDs.h b/LUFA/Drivers/Board/EVK527/LEDs.h new file mode 100644 index 0000000..0ac7a53 --- /dev/null +++ b/LUFA/Drivers/Board/EVK527/LEDs.h @@ -0,0 +1,135 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Atmel EVK527. + * + * Board specific LED driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_EVK527 EVK527 + * + * Board specific LED driver header for the Atmel EVK527. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_EVK527_H__ +#define __LEDS_EVK527_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 5) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 6) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 (1 << 7) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/JMDBU2/Buttons.h b/LUFA/Drivers/Board/JMDBU2/Buttons.h new file mode 100644 index 0000000..eacece7 --- /dev/null +++ b/LUFA/Drivers/Board/JMDBU2/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Mattairtech JM-DB-U2. + * + * Board specific Buttons driver header for the Mattairtech JM-DB-U2 (http://u2.mattair.net/index.html). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_JMDBU2 JMDBU2 + * + * Board specific Buttons driver header for the Mattairtech JM-DB-U2 (http://u2.mattair.net/index.html). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_JMDBU2_H__ +#define __BUTTONS_JMDBU2_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/JMDBU2/LEDs.h b/LUFA/Drivers/Board/JMDBU2/LEDs.h new file mode 100644 index 0000000..46ac849 --- /dev/null +++ b/LUFA/Drivers/Board/JMDBU2/LEDs.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Mattairtech JM-DB-U2. + * + * Board specific LED driver header for the Mattairtech JM-DB-U2 (http://u2.mattair.net/index.html). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_JMDBU2 JMDBU2 + * + * Board specific LED driver header for the Mattairtech JM-DB-U2 (http://u2.mattair.net/index.html). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_JMDBU2_H__ +#define __LEDS_JMDBU2_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/Joystick.h b/LUFA/Drivers/Board/Joystick.h new file mode 100644 index 0000000..e43110a --- /dev/null +++ b/LUFA/Drivers/Board/Joystick.h @@ -0,0 +1,114 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the board digital joystick driver. + * + * This file is the master dispatch header file for the board-specific Joystick driver, for boards containing a + * 5-way joystick. + * + * User code should include this file, which will in turn include the correct joystick driver header file for the + * currently selected board. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/Joystick.h file in the user project + * directory. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + */ + +/** \ingroup Group_BoardDrivers + * @defgroup Group_Joystick Joystick Driver - LUFA/Drivers/Board/Joystick.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Module Description + * Hardware Joystick driver. This module provides an easy to use interface to control the hardware digital Joystick + * located on many boards. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/Dataflash.h file in the user project + * directory. Otherwise, it will include the appropriate built in board driver header file. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + * + * @{ + */ + +#ifndef __JOYSTICK_H__ +#define __JOYSTICK_H__ + + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __INCLUDE_FROM_JOYSTICK_H + #define INCLUDE_FROM_JOYSTICK_H + #endif + + /* Includes: */ + #include "../../Common/Common.h" + + #if (BOARD == BOARD_NONE) + #error The Board Joystick driver cannot be used if the makefile BOARD option is not set. + #elif (BOARD == BOARD_USBKEY) + #include "USBKEY/Joystick.h" + #elif (BOARD == BOARD_STK525) + #include "STK525/Joystick.h" + #elif (BOARD == BOARD_STK526) + #include "STK526/Joystick.h" + #elif (BOARD == BOARD_BUMBLEB) + #include "BUMBLEB/Joystick.h" + #elif (BOARD == BOARD_EVK527) + #include "EVK527/Joystick.h" + #elif (BOARD == BOARD_USER) + #include "Board/Joystick.h" + #else + #error The selected board does not contain a joystick. + #endif + + /* Pseudo-Functions for Doxygen: */ + #if defined(__DOXYGEN__) + /** Initialises the joystick driver so that the joystick position can be read. This sets the appropriate + * I/O pins to inputs with their pull-ups enabled. + */ + static inline void Joystick_Init(void); + + /** Returns the current status of the joystick, as a mask indicating the direction the joystick is + * currently facing in (multiple bits can be set). + * + * \return Mask indicating the joystick direction - see corresponding board specific Joystick.h file + * for direction masks. + */ + static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/LEDs.h b/LUFA/Drivers/Board/LEDs.h new file mode 100644 index 0000000..72ed729 --- /dev/null +++ b/LUFA/Drivers/Board/LEDs.h @@ -0,0 +1,212 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the board LEDs driver. + * + * This file is the master dispatch header file for the board-specific LED driver, for boards containing user + * controllable LEDs. + * + * User code should include this file, which will in turn include the correct LED driver header file for the + * currently selected board. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/LEDs.h file in the user project + * directory. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + */ + +/** \ingroup Group_BoardDrivers + * @defgroup Group_LEDs LEDs Driver - LUFA/Drivers/Board/LEDs.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Module Description + * Hardware LEDs driver. This provides an easy to use driver for the hardware LEDs present on many boards. It + * provides an interface to configure, test and change the status of all the board LEDs. + * + * If the BOARD value is set to BOARD_USER, this will include the /Board/Dataflash.h file in the user project + * directory. Otherwise, it will include the appropriate built in board driver header file. If the BOARD value + * is set to BOARD_NONE, this driver is silently disabled. + * + * For possible BOARD makefile values, see \ref Group_BoardTypes. + * + * \note To make code as compatible as possible, it is assumed that all boards carry a minimum of four LEDs. If + * a board contains less than four LEDs, the remaining LED masks are defined to 0 so as to have no effect. + * If other behaviour is desired, either alias the remaining LED masks to existing LED masks via the -D + * switch in the project makefile, or alias them to nothing in the makefile to cause compilation errors when + * a non-existing LED is referenced in application code. Note that this means that it is possible to make + * compatible code for a board with no LEDs by making a board LED driver (see \ref Page_WritingBoardDrivers) + * which contains only stub functions and defines no LEDs. + * + * @{ + */ + +#ifndef __LEDS_H__ +#define __LEDS_H__ + + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __INCLUDE_FROM_LEDS_H + #define INCLUDE_FROM_LEDS_H + #endif + + /* Includes: */ + #include "../../Common/Common.h" + + #if (BOARD == BOARD_NONE) + static inline void LEDs_Init(void) {}; + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) {}; + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) {}; + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) {}; + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask) {}; + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) {}; + static inline uint8_t LEDs_GetLEDs(void) { return 0; } + #elif (BOARD == BOARD_USBKEY) + #include "USBKEY/LEDs.h" + #elif (BOARD == BOARD_STK525) + #include "STK525/LEDs.h" + #elif (BOARD == BOARD_STK526) + #include "STK526/LEDs.h" + #elif (BOARD == BOARD_RZUSBSTICK) + #include "RZUSBSTICK/LEDs.h" + #elif (BOARD == BOARD_ATAVRUSBRF01) + #include "ATAVRUSBRF01/LEDs.h" + #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1)) + #include "XPLAIN/LEDs.h" + #elif (BOARD == BOARD_BUMBLEB) + #include "BUMBLEB/LEDs.h" + #elif (BOARD == BOARD_EVK527) + #include "EVK527/LEDs.h" + #elif (BOARD == BOARD_TEENSY) + #include "TEENSY/LEDs.h" + #elif (BOARD == BOARD_USBTINYMKII) + #include "USBTINYMKII/LEDs.h" + #elif (BOARD == BOARD_BENITO) + #include "BENITO/LEDs.h" + #elif (BOARD == BOARD_JMDBU2) + #include "JMDBU2/LEDs.h" + #elif (BOARD == BOARD_OLIMEX162) + #include "OLIMEX162/LEDs.h" + #elif (BOARD == BOARD_USBFOO) + #include "USBFOO/LEDs.h" + #elif (BOARD == BOARD_UDIP) + #include "UDIP/LEDs.h" + #elif (BOARD == BOARD_BUI) + #include "BUI/LEDs.h" + #elif (BOARD == BOARD_UNO) + #include "UNO/LEDs.h" + #elif (BOARD == BOARD_CULV3) + #include "CULV3/LEDs.h" + #elif (BOARD == BOARD_BLACKCAT) + #include "BLACKCAT/LEDs.h" + #elif (BOARD == BOARD_MAXIMUS) + #include "MAXIMUS/LEDs.h" + #elif (BOARD == BOARD_MINIMUS) + #include "MINIMUS/LEDs.h" + #elif (BOARD == BOARD_ADAFRUITU4) + #include "ADAFRUITU4/LEDs.h" + #elif (BOARD == BOARD_MICROSIN162) + #include "MICROSIN162/LEDs.h" + #elif (BOARD == BOARD_USER) + #include "Board/LEDs.h" + #endif + + #if !defined(LEDS_LED1) + #define LEDS_LED1 0 + #endif + + #if !defined(LEDS_LED2) + #define LEDS_LED2 0 + #endif + + #if !defined(LEDS_LED3) + #define LEDS_LED3 0 + #endif + + #if !defined(LEDS_LED4) + #define LEDS_LED4 0 + #endif + + /* Pseudo-Functions for Doxygen: */ + #if defined(__DOXYGEN__) + /** Initialises the board LED driver so that the LEDs can be controlled. This sets the appropriate port + * I/O pins as outputs, and sets the LEDs to default to off. + */ + static inline void LEDs_Init(void); + + /** Turns on the LEDs specified in the given LED mask. + * + * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file). + */ + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask); + + /** Turns off the LEDs specified in the given LED mask. + * + * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file). + */ + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask); + + /** Turns off all LEDs not specified in the given LED mask, and turns on all the LEDs in the given LED + * mask. + * + * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file). + */ + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask); + + /** Turns off all LEDs in the LED mask that are not set in the active mask, and turns on all the LEDs + * specified in both the LED and active masks. + * + * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file). + * \param[in] ActiveMask Mask of whether the LEDs in the LED mask should be turned on or off. + */ + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask); + + /** Toggles all LEDs in the LED mask, leaving all others in their current states. + * + * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file). + */ + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask); + + /** Returns the status of all the board LEDs; set LED masks in the return value indicate that the + * corresponding LED is on. + * + * \return Mask of the board LEDs which are currently turned on. + */ + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/MAXIMUS/LEDs.h b/LUFA/Drivers/Board/MAXIMUS/LEDs.h new file mode 100644 index 0000000..d540d32 --- /dev/null +++ b/LUFA/Drivers/Board/MAXIMUS/LEDs.h @@ -0,0 +1,131 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Maximus. + * + * Board specific LED driver header for the Maximus (http://www.avrusb.com/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_MAXIMUS MAXIMUS + * + * Board specific LED driver header for the Maximus (http://www.avrusb.com/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_MAXIMUS_H__ +#define __LEDS_MAXIMUS_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 7) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2) + + /** LED mask for the none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRB |= LEDS_ALL_LEDS; + PORTB &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTB |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTB &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTB = ((PORTB & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTB = ((PORTB & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTB = (PORTB ^ (LEDMask & LEDS_ALL_LEDS)); + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTB & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ diff --git a/LUFA/Drivers/Board/MICROSIN162/Buttons.h b/LUFA/Drivers/Board/MICROSIN162/Buttons.h new file mode 100644 index 0000000..78f9c1e --- /dev/null +++ b/LUFA/Drivers/Board/MICROSIN162/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Microsin AVR-USB162 board. + * + * Board specific Buttons driver header for the Microsin AVR-USB162 board (http://microsin.ru/content/view/685/44/). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_MICROSIN162 MICROSIN162 + * + * Board specific Buttons driver header for the Microsin AVR-USB162 board (http://microsin.ru/content/view/685/44/). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_MICROSIN162_H__ +#define __BUTTONS_MICROSIN162_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/MICROSIN162/LEDs.h b/LUFA/Drivers/Board/MICROSIN162/LEDs.h new file mode 100644 index 0000000..1ac0eea --- /dev/null +++ b/LUFA/Drivers/Board/MICROSIN162/LEDs.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Microsin AVR-USB162 board. + * + * Board specific LED driver header for the Microsin AVR-USB162 board (http://microsin.ru/content/view/685/44/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_MICROSIN162 MICROSIN162 + * + * Board specific LED driver header for the Microsin AVR-USB162 board (http://microsin.ru/content/view/685/44/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_MICROSIN162_H__ +#define __LEDS_MICROSIN162_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD | LEDMask) & ~ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (~PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/MINIMUS/Buttons.h b/LUFA/Drivers/Board/MINIMUS/Buttons.h new file mode 100644 index 0000000..c38c9c3 --- /dev/null +++ b/LUFA/Drivers/Board/MINIMUS/Buttons.h @@ -0,0 +1,97 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the MINIMUS. + * + * Board specific Buttons driver header for the MINIMUS. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_MINIMUS MINIMUS + * + * Board specific Buttons driver header for the MINIMUS. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_MINIMUS_H__ +#define __BUTTONS_MINIMUS_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 8) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ diff --git a/LUFA/Drivers/Board/MINIMUS/LEDs.h b/LUFA/Drivers/Board/MINIMUS/LEDs.h new file mode 100644 index 0000000..96db6ee --- /dev/null +++ b/LUFA/Drivers/Board/MINIMUS/LEDs.h @@ -0,0 +1,131 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the MINIMUS. + * + * Board specific LED driver header for the Minimus USB (http://www.minimususb.com/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_MINIMUS MINIMUS + * + * Board specific LED driver header for the Minimus USB (http://www.minimususb.com/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_MINIMUS_H__ +#define __LEDS_MINIMUS_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 5) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2) + + /** LED mask for the none of the board LEDs. */ + #define LEDS_NO_LEDS 1 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD = (PORTD ^ (LEDMask & LEDS_ALL_LEDS)); + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ diff --git a/LUFA/Drivers/Board/OLIMEX162/Buttons.h b/LUFA/Drivers/Board/OLIMEX162/Buttons.h new file mode 100644 index 0000000..9632f7a --- /dev/null +++ b/LUFA/Drivers/Board/OLIMEX162/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Olimex AVR-USB-162 Development Board. + * + * Board specific Buttons driver header for the Olimex AVR-USB-162 Development Board (http://www.olimex.com/dev/avr-usb-162.html). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_OLIMEX162 OLIMEX162 + * + * Board specific Buttons driver header for the Olimex AVR-USB-162 Development Board (http://www.olimex.com/dev/avr-usb-162.html). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_OLIMEX162_H__ +#define __BUTTONS_OLIMEX162_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/OLIMEX162/LEDs.h b/LUFA/Drivers/Board/OLIMEX162/LEDs.h new file mode 100644 index 0000000..d90f079 --- /dev/null +++ b/LUFA/Drivers/Board/OLIMEX162/LEDs.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Olimex AVR-USB-162. + * + * Board specific LED driver header for the Olimex AVR-USB-162 (http://www.olimex.com/dev/avr-usb-162.html). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_OLIMEX162 OLIMEX162 + * + * Board specific LED driver header for the Olimex AVR-USB-162 (http://www.olimex.com/dev/avr-usb-162.html). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_OLIMEX162_H__ +#define __LEDS_OLIMEX162_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD | LEDMask) & ~ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (~PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/RZUSBSTICK/LEDs.h b/LUFA/Drivers/Board/RZUSBSTICK/LEDs.h new file mode 100644 index 0000000..d8949bd --- /dev/null +++ b/LUFA/Drivers/Board/RZUSBSTICK/LEDs.h @@ -0,0 +1,163 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Atmel RZUSBSTICK. + * + * Board specific LED driver header for the Atmel RZUSBSTICK. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_RZUSBSTICK RZUSBSTICK + * + * Board specific LED driver header for the Atmel RZUSBSTICK. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_RZUSBSTICK_H__ +#define __LEDS_RZUSBSTICK_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define LEDS_PORTD_LEDS (LEDS_LED1 | LEDS_LED2) + #define LEDS_PORTE_LEDS (LEDS_LED3 | LEDS_LED4) + + #define LEDS_PORTE_MASK_SHIFT 4 + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 7) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 5) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 ((1 << 6) >> LEDS_PORTE_MASK_SHIFT) + + /** LED mask for the fourth LED on the board. */ + #define LEDS_LED4 ((1 << 7) >> LEDS_PORTE_MASK_SHIFT) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_PORTD_LEDS; + PORTD &= ~LEDS_LED1; + PORTD |= LEDS_LED2; + + DDRE |= (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT); + PORTE |= (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT); + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= (LEDMask & LEDS_LED1); + PORTD &= ~(LEDMask & LEDS_LED2); + PORTE &= ~((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT); + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~(LEDMask & LEDS_LED1); + PORTD |= (LEDMask & LEDS_LED2); + PORTE |= ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT); + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = (((PORTD & ~LEDS_LED1) | (LEDMask & LEDS_LED1)) | + ((PORTD | LEDS_LED2) & ~(LEDMask & LEDS_LED2))); + PORTE = ((PORTE | (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT)) & + ~((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT)); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = (((PORTD & ~(LEDMask & LEDS_LED1)) | (ActiveMask & LEDS_LED1)) | + ((PORTD | (LEDMask & LEDS_LED2)) & ~(ActiveMask & LEDS_LED2))); + PORTE = ((PORTE | ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT)) & + ~((ActiveMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT)); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD = (PORTD ^ (LEDMask & LEDS_PORTD_LEDS)); + PORTE = (PORTE ^ ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT)); + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (((PORTD & LEDS_LED1) | (~PORTD & LEDS_LED2)) | + ((~PORTE & (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT)) >> LEDS_PORTE_MASK_SHIFT)); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK525/AT45DB321C.h b/LUFA/Drivers/Board/STK525/AT45DB321C.h new file mode 100644 index 0000000..8599d0f --- /dev/null +++ b/LUFA/Drivers/Board/STK525/AT45DB321C.h @@ -0,0 +1,105 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash commands header for the AT45DB321C as mounted on the Atmel STK525. + * + * Board specific Dataflash commands header for the AT45DB321C as mounted on the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash_STK525 + * @defgroup Group_Dataflash_STK525_AT45DB321C AT45DB321C + * + * Board specific Dataflash commands header for the AT45DB321C as mounted on the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_CMDS_H__ +#define __DATAFLASH_CMDS_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name Dataflash Status Values */ + //@{ + #define DF_STATUS_READY (1 << 7) + #define DF_STATUS_COMPMISMATCH (1 << 6) + #define DF_STATUS_SECTORPROTECTION_ON (1 << 1) + //@} + + #define DF_MANUFACTURER_ATMEL 0x1F + + /** \name Dataflash Commands */ + //@{ + #define DF_CMD_GETSTATUS 0xD7 + + #define DF_CMD_MAINMEMTOBUFF1 0x53 + #define DF_CMD_MAINMEMTOBUFF2 0x55 + #define DF_CMD_MAINMEMTOBUFF1COMP 0x60 + #define DF_CMD_MAINMEMTOBUFF2COMP 0x61 + #define DF_CMD_AUTOREWRITEBUFF1 0x58 + #define DF_CMD_AUTOREWRITEBUFF2 0x59 + + #define DF_CMD_MAINMEMPAGEREAD 0xD2 + #define DF_CMD_CONTARRAYREAD_LF 0xE8 + #define DF_CMD_BUFF1READ_LF 0xD4 + #define DF_CMD_BUFF2READ_LF 0xD6 + + #define DF_CMD_BUFF1WRITE 0x84 + #define DF_CMD_BUFF2WRITE 0x87 + #define DF_CMD_BUFF1TOMAINMEMWITHERASE 0x83 + #define DF_CMD_BUFF2TOMAINMEMWITHERASE 0x86 + #define DF_CMD_BUFF1TOMAINMEM 0x88 + #define DF_CMD_BUFF2TOMAINMEM 0x89 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF1 0x82 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF2 0x85 + + #define DF_CMD_PAGEERASE 0x81 + #define DF_CMD_BLOCKERASE 0x50 + + #define DF_CMD_SECTORPROTECTIONOFF ((char[]){0x3D, 0x2A, 0x7F, 0xCF}) + #define DF_CMD_SECTORPROTECTIONOFF_BYTE1 0x3D + #define DF_CMD_SECTORPROTECTIONOFF_BYTE2 0x2A + #define DF_CMD_SECTORPROTECTIONOFF_BYTE3 0x7F + #define DF_CMD_SECTORPROTECTIONOFF_BYTE4 0xCF + + #define DF_CMD_READMANUFACTURERDEVICEINFO 0x9F + //@} + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK525/Buttons.h b/LUFA/Drivers/Board/STK525/Buttons.h new file mode 100644 index 0000000..73ef3aa --- /dev/null +++ b/LUFA/Drivers/Board/STK525/Buttons.h @@ -0,0 +1,104 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Atmel STK525. + * + * Board specific Buttons driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_STK525 STK525 + * + * Board specific Buttons driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_STK525_H__ +#define __BUTTONS_STK525_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 2) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRE &= ~BUTTONS_BUTTON1; + PORTE |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK525/Dataflash.h b/LUFA/Drivers/Board/STK525/Dataflash.h new file mode 100644 index 0000000..10054d1 --- /dev/null +++ b/LUFA/Drivers/Board/STK525/Dataflash.h @@ -0,0 +1,184 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash driver header for the Atmel STK525. + * + * Board specific Dataflash driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash + * @defgroup Group_Dataflash_STK525 STK525 + * + * Board specific Dataflash driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_STK525_H__ +#define __DATAFLASH_STK525_H__ + + /* Includes: */ + #include "AT45DB321C.h" + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_DATAFLASH_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define DATAFLASH_CHIPCS_MASK (1 << 4) + #define DATAFLASH_CHIPCS_DDR DDRB + #define DATAFLASH_CHIPCS_PORT PORTB + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Constant indicating the total number of dataflash ICs mounted on the selected board. */ + #define DATAFLASH_TOTALCHIPS 1 + + /** Mask for no dataflash chip selected. */ + #define DATAFLASH_NO_CHIP DATAFLASH_CHIPCS_MASK + + /** Mask for the first dataflash chip selected. */ + #define DATAFLASH_CHIP1 0 + + /** Internal main memory page size for the board's dataflash IC. */ + #define DATAFLASH_PAGE_SIZE 512 + + /** Total number of pages inside the board's dataflash IC. */ + #define DATAFLASH_PAGES 8192 + + /* Inline Functions: */ + /** Initialises the dataflash driver so that commands and data may be sent to an attached dataflash IC. + * The AVR's SPI driver MUST be initialized before any of the dataflash commands are used. + */ + static inline void Dataflash_Init(void) + { + DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK; + DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK; + } + + /** Determines the currently selected dataflash chip. + * + * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected + * or a DATAFLASH_CHIPn mask (where n is the chip number). + */ + static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Dataflash_GetSelectedChip(void) + { + return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK); + } + + /** Selects the given dataflash chip. + * + * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is + * the chip number). + */ + static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE; + static inline void Dataflash_SelectChip(const uint8_t ChipMask) + { + DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask); + } + + /** Deselects the current dataflash chip, so that no dataflash is selected. */ + static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE; + static inline void Dataflash_DeselectChip(void) + { + Dataflash_SelectChip(DATAFLASH_NO_CHIP); + } + + /** Selects a dataflash IC from the given page number, which should range from 0 to + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one + * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside + * the total number of pages contained in the boards dataflash ICs, all dataflash ICs + * are deselected. + * + * \param[in] PageAddress Address of the page to manipulate, ranging from + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). + */ + static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress) + { + Dataflash_DeselectChip(); + + if (PageAddress >= DATAFLASH_PAGES) + return; + + Dataflash_SelectChip(DATAFLASH_CHIP1); + } + + /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive + * a new command. + */ + static inline void Dataflash_ToggleSelectedChipCS(void) + { + uint8_t SelectedChipMask = Dataflash_GetSelectedChip(); + + Dataflash_DeselectChip(); + Dataflash_SelectChip(SelectedChipMask); + } + + /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main + * memory page program or main memory to buffer transfer. + */ + static inline void Dataflash_WaitWhileBusy(void) + { + Dataflash_ToggleSelectedChipCS(); + Dataflash_SendByte(DF_CMD_GETSTATUS); + while (!(Dataflash_ReceiveByte() & DF_STATUS_READY)); + Dataflash_ToggleSelectedChipCS(); + } + + /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with + * dataflash commands which require a complete 24-byte address. + * + * \param[in] PageAddress Page address within the selected dataflash IC + * \param[in] BufferByte Address within the dataflash's buffer + */ + static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, + const uint16_t BufferByte) + { + Dataflash_SendByte(PageAddress >> 6); + Dataflash_SendByte((PageAddress << 2) | (BufferByte >> 8)); + Dataflash_SendByte(BufferByte); + } + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK525/Joystick.h b/LUFA/Drivers/Board/STK525/Joystick.h new file mode 100644 index 0000000..0535558 --- /dev/null +++ b/LUFA/Drivers/Board/STK525/Joystick.h @@ -0,0 +1,119 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific joystick driver header for the Atmel STK525. + * + * Board specific joystick driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + */ + +/** \ingroup Group_Joystick + * @defgroup Group_Joystick_STK525 STK525 + * + * Board specific joystick driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + * + * @{ + */ + +#ifndef __JOYSTICK_STK525_H__ +#define __JOYSTICK_STK525_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_JOYSTICK_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define JOY_BMASK ((1 << 5) | (1 << 6) | (1 << 7)) + #define JOY_EMASK ((1 << 4) | (1 << 5)) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for the joystick being pushed in the left direction. */ + #define JOY_LEFT (1 << 6) + + /** Mask for the joystick being pushed in the right direction. */ + #define JOY_RIGHT ((1 << 4) >> 1) + + /** Mask for the joystick being pushed in the upward direction. */ + #define JOY_UP (1 << 7) + + /** Mask for the joystick being pushed in the downward direction. */ + #define JOY_DOWN ((1 << 5) >> 1) + + /** Mask for the joystick being pushed inward. */ + #define JOY_PRESS (1 << 5) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Joystick_Init(void) + { + DDRB &= ~(JOY_BMASK); + DDRE &= ~(JOY_EMASK); + + PORTB |= JOY_BMASK; + PORTE |= JOY_EMASK; + } + + static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Joystick_GetStatus(void) + { + return (((uint8_t)~PINB & JOY_BMASK) | (((uint8_t)~PINE & JOY_EMASK) >> 1)); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK525/LEDs.h b/LUFA/Drivers/Board/STK525/LEDs.h new file mode 100644 index 0000000..edfc2bf --- /dev/null +++ b/LUFA/Drivers/Board/STK525/LEDs.h @@ -0,0 +1,138 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Atmel STK525. + * + * Board specific LED driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_STK525 STK525 + * + * Board specific LED driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_STK525_H__ +#define __LEDS_STK525_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 5) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 (1 << 7) + + /** LED mask for the fourth LED on the board. */ + #define LEDS_LED4 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK526/AT45DB642D.h b/LUFA/Drivers/Board/STK526/AT45DB642D.h new file mode 100644 index 0000000..c273083 --- /dev/null +++ b/LUFA/Drivers/Board/STK526/AT45DB642D.h @@ -0,0 +1,115 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel STK526. + * + * Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash_STK526 + * @defgroup Group_Dataflash_STK526_AT45DB642D AT45DB642D + * + * Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_CMDS_H__ +#define __DATAFLASH_CMDS_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name Dataflash Status Values */ + //@{ + #define DF_STATUS_READY (1 << 7) + #define DF_STATUS_COMPMISMATCH (1 << 6) + #define DF_STATUS_SECTORPROTECTION_ON (1 << 1) + #define DF_STATUS_BINARYPAGESIZE_ON (1 << 0) + //@} + + #define DF_MANUFACTURER_ATMEL 0x1F + + /** \name Dataflash Commands */ + //@{ + #define DF_CMD_GETSTATUS 0xD7 + #define DF_CMD_POWERDOWN 0xB9 + #define DF_CMD_WAKEUP 0xAB + + #define DF_CMD_MAINMEMTOBUFF1 0x53 + #define DF_CMD_MAINMEMTOBUFF2 0x55 + #define DF_CMD_MAINMEMTOBUFF1COMP 0x60 + #define DF_CMD_MAINMEMTOBUFF2COMP 0x61 + #define DF_CMD_AUTOREWRITEBUFF1 0x58 + #define DF_CMD_AUTOREWRITEBUFF2 0x59 + + #define DF_CMD_MAINMEMPAGEREAD 0xD2 + #define DF_CMD_CONTARRAYREAD_LF 0x03 + #define DF_CMD_BUFF1READ_LF 0xD1 + #define DF_CMD_BUFF2READ_LF 0xD3 + + #define DF_CMD_BUFF1WRITE 0x84 + #define DF_CMD_BUFF2WRITE 0x87 + #define DF_CMD_BUFF1TOMAINMEMWITHERASE 0x83 + #define DF_CMD_BUFF2TOMAINMEMWITHERASE 0x86 + #define DF_CMD_BUFF1TOMAINMEM 0x88 + #define DF_CMD_BUFF2TOMAINMEM 0x89 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF1 0x82 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF2 0x85 + + #define DF_CMD_PAGEERASE 0x81 + #define DF_CMD_BLOCKERASE 0x50 + #define DF_CMD_SECTORERASE 0x7C + + #define DF_CMD_CHIPERASE ((char[]){0xC7, 0x94, 0x80, 0x9A}) + #define DF_CMD_CHIPERASE_BYTE1 0xC7 + #define DF_CMD_CHIPERASE_BYTE2 0x94 + #define DF_CMD_CHIPERASE_BYTE3 0x80 + #define DF_CMD_CHIPERASE_BYTE4 0x9A + + #define DF_CMD_SECTORPROTECTIONOFF ((char[]){0x3D, 0x2A, 0x7F, 0x9A}) + #define DF_CMD_SECTORPROTECTIONOFF_BYTE1 0x3D + #define DF_CMD_SECTORPROTECTIONOFF_BYTE2 0x2A + #define DF_CMD_SECTORPROTECTIONOFF_BYTE3 0x7F + #define DF_CMD_SECTORPROTECTIONOFF_BYTE4 0x9A + + #define DF_CMD_READMANUFACTURERDEVICEINFO 0x9F + //@} + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK526/Buttons.h b/LUFA/Drivers/Board/STK526/Buttons.h new file mode 100644 index 0000000..cc07054 --- /dev/null +++ b/LUFA/Drivers/Board/STK526/Buttons.h @@ -0,0 +1,104 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Atmel STK526. + * + * Board specific Buttons driver header for the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_STK526 STK526 + * + * Board specific Buttons driver header for the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_STK526_H__ +#define __BUTTONS_STK526_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK526/Dataflash.h b/LUFA/Drivers/Board/STK526/Dataflash.h new file mode 100644 index 0000000..087bfd2 --- /dev/null +++ b/LUFA/Drivers/Board/STK526/Dataflash.h @@ -0,0 +1,184 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash driver header for the Atmel STK525. + * + * Board specific Dataflash driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash + * @defgroup Group_Dataflash_STK526 STK526 + * + * Board specific Dataflash driver header for the Atmel STK525. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_STK526_H__ +#define __DATAFLASH_STK526_H__ + + /* Includes: */ + #include "AT45DB642D.h" + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_DATAFLASH_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define DATAFLASH_CHIPCS_MASK (1 << 2) + #define DATAFLASH_CHIPCS_DDR DDRC + #define DATAFLASH_CHIPCS_PORT PORTC + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Constant indicating the total number of dataflash ICs mounted on the selected board. */ + #define DATAFLASH_TOTALCHIPS 1 + + /** Mask for no dataflash chip selected. */ + #define DATAFLASH_NO_CHIP DATAFLASH_CHIPCS_MASK + + /** Mask for the first dataflash chip selected. */ + #define DATAFLASH_CHIP1 0 + + /** Internal main memory page size for the board's dataflash IC. */ + #define DATAFLASH_PAGE_SIZE 1024 + + /** Total number of pages inside the board's dataflash IC. */ + #define DATAFLASH_PAGES 8192 + + /* Inline Functions: */ + /** Initialises the dataflash driver so that commands and data may be sent to an attached dataflash IC. + * The AVR's SPI driver MUST be initialized before any of the dataflash commands are used. + */ + static inline void Dataflash_Init(void) + { + DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK; + DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK; + } + + /** Determines the currently selected dataflash chip. + * + * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected + * or a DATAFLASH_CHIPn mask (where n is the chip number). + */ + static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Dataflash_GetSelectedChip(void) + { + return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK); + } + + /** Selects the given dataflash chip. + * + * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is + * the chip number). + */ + static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE; + static inline void Dataflash_SelectChip(const uint8_t ChipMask) + { + DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask); + } + + /** Deselects the current dataflash chip, so that no dataflash is selected. */ + static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE; + static inline void Dataflash_DeselectChip(void) + { + Dataflash_SelectChip(DATAFLASH_NO_CHIP); + } + + /** Selects a dataflash IC from the given page number, which should range from 0 to + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one + * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside + * the total number of pages contained in the boards dataflash ICs, all dataflash ICs + * are deselected. + * + * \param[in] PageAddress Address of the page to manipulate, ranging from + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). + */ + static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress) + { + Dataflash_DeselectChip(); + + if (PageAddress >= DATAFLASH_PAGES) + return; + + Dataflash_SelectChip(DATAFLASH_CHIP1); + } + + /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive + * a new command. + */ + static inline void Dataflash_ToggleSelectedChipCS(void) + { + uint8_t SelectedChipMask = Dataflash_GetSelectedChip(); + + Dataflash_DeselectChip(); + Dataflash_SelectChip(SelectedChipMask); + } + + /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main + * memory page program or main memory to buffer transfer. + */ + static inline void Dataflash_WaitWhileBusy(void) + { + Dataflash_ToggleSelectedChipCS(); + Dataflash_SendByte(DF_CMD_GETSTATUS); + while (!(Dataflash_ReceiveByte() & DF_STATUS_READY)); + Dataflash_ToggleSelectedChipCS(); + } + + /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with + * dataflash commands which require a complete 24-byte address. + * + * \param[in] PageAddress Page address within the selected dataflash IC + * \param[in] BufferByte Address within the dataflash's buffer + */ + static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, + const uint16_t BufferByte) + { + Dataflash_SendByte(PageAddress >> 5); + Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8)); + Dataflash_SendByte(BufferByte); + } + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK526/Joystick.h b/LUFA/Drivers/Board/STK526/Joystick.h new file mode 100644 index 0000000..7309963 --- /dev/null +++ b/LUFA/Drivers/Board/STK526/Joystick.h @@ -0,0 +1,116 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific joystick driver header for the Atmel STK526. + * + * Board specific joystick driver header for the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + */ + +/** \ingroup Group_Joystick + * @defgroup Group_Joystick_STK526 STK526 + * + * Board specific joystick driver header for the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + * + * @{ + */ + +#ifndef __JOYSTICK_STK526_H__ +#define __JOYSTICK_STK526_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_JOYSTICK_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define JOY_BMASK ((1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for the joystick being pushed in the left direction. */ + #define JOY_LEFT (1 << 4) + + /** Mask for the joystick being pushed in the right direction. */ + #define JOY_RIGHT (1 << 6) + + /** Mask for the joystick being pushed in the upward direction. */ + #define JOY_UP (1 << 5) + + /** Mask for the joystick being pushed in the downward direction. */ + #define JOY_DOWN (1 << 7) + + /** Mask for the joystick being pushed inward. */ + #define JOY_PRESS (1 << 0) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Joystick_Init(void) + { + DDRB &= ~JOY_BMASK; + + PORTB |= JOY_BMASK; + } + + static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Joystick_GetStatus(void) + { + return ((uint8_t)~PINB & JOY_BMASK); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/STK526/LEDs.h b/LUFA/Drivers/Board/STK526/LEDs.h new file mode 100644 index 0000000..b407d44 --- /dev/null +++ b/LUFA/Drivers/Board/STK526/LEDs.h @@ -0,0 +1,138 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Atmel STK526. + * + * Board specific LED driver header for the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_STK526 STK526 + * + * Board specific LED driver header for the Atmel STK526. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_STK526_H__ +#define __LEDS_STK526_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 1) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 0) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 (1 << 5) + + /** LED mask for the fourth LED on the board. */ + #define LEDS_LED4 (1 << 4) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/TEENSY/LEDs.h b/LUFA/Drivers/Board/TEENSY/LEDs.h new file mode 100644 index 0000000..29ed008 --- /dev/null +++ b/LUFA/Drivers/Board/TEENSY/LEDs.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the PJRC Teensy boards. + * + * Board specific LED driver header for the PJRC Teensy boards (http://www.pjrc.com/teensy/index.html). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_TEENSY TEENSY + * + * Board specific LED driver header for the PJRC Teensy boards (http://www.pjrc.com/teensy/index.html). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_TEENSY_H__ +#define __LEDS_TEENSY_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD | LEDMask) & ~ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (~PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/Temperature.c b/LUFA/Drivers/Board/Temperature.c new file mode 100644 index 0000000..719dfe1 --- /dev/null +++ b/LUFA/Drivers/Board/Temperature.c @@ -0,0 +1,61 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include "Temperature.h" + +static const uint16_t PROGMEM Temperature_Lookup[] = { + 0x3B4, 0x3B0, 0x3AB, 0x3A6, 0x3A0, 0x39A, 0x394, 0x38E, 0x388, 0x381, 0x37A, 0x373, + 0x36B, 0x363, 0x35B, 0x353, 0x34A, 0x341, 0x338, 0x32F, 0x325, 0x31B, 0x311, 0x307, + 0x2FC, 0x2F1, 0x2E6, 0x2DB, 0x2D0, 0x2C4, 0x2B8, 0x2AC, 0x2A0, 0x294, 0x288, 0x27C, + 0x26F, 0x263, 0x256, 0x24A, 0x23D, 0x231, 0x225, 0x218, 0x20C, 0x200, 0x1F3, 0x1E7, + 0x1DB, 0x1CF, 0x1C4, 0x1B8, 0x1AC, 0x1A1, 0x196, 0x18B, 0x180, 0x176, 0x16B, 0x161, + 0x157, 0x14D, 0x144, 0x13A, 0x131, 0x128, 0x11F, 0x117, 0x10F, 0x106, 0x0FE, 0x0F7, + 0x0EF, 0x0E8, 0x0E1, 0x0DA, 0x0D3, 0x0CD, 0x0C7, 0x0C0, 0x0BA, 0x0B5, 0x0AF, 0x0AA, + 0x0A4, 0x09F, 0x09A, 0x096, 0x091, 0x08C, 0x088, 0x084, 0x080, 0x07C, 0x078, 0x074, + 0x071, 0x06D, 0x06A, 0x067, 0x064, 0x061, 0x05E, 0x05B, 0x058, 0x055, 0x053, 0x050, + 0x04E, 0x04C, 0x049, 0x047, 0x045, 0x043, 0x041, 0x03F, 0x03D, 0x03C, 0x03A, 0x038 + }; + +int8_t Temperature_GetTemperature(void) +{ + uint16_t Temp_ADC = ADC_GetChannelReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | TEMP_ADC_CHANNEL_MASK); + + if (Temp_ADC > pgm_read_word(&Temperature_Lookup[0])) + return TEMP_MIN_TEMP; + + for (uint16_t Index = 0; Index < TEMP_TABLE_SIZE; Index++) + { + if (Temp_ADC > pgm_read_word(&Temperature_Lookup[Index])) + return (Index + TEMP_TABLE_OFFSET); + } + + return TEMP_MAX_TEMP; +} + diff --git a/LUFA/Drivers/Board/Temperature.h b/LUFA/Drivers/Board/Temperature.h new file mode 100644 index 0000000..e34a141 --- /dev/null +++ b/LUFA/Drivers/Board/Temperature.h @@ -0,0 +1,125 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the board temperature sensor driver. + * + * Master include file for the board temperature sensor driver, for the USB boards which contain a temperature sensor. + */ + +/** \ingroup Group_BoardDrivers + * @defgroup Group_Temperature Temperature Sensor Driver - LUFA/Drivers/Board/Temperature.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/Board/Temperature.c (Makefile source module name: LUFA_SRC_TEMPERATURE) + * + * \section Module Description + * Temperature sensor driver. This provides an easy to use interface for the hardware temperature sensor located + * on many boards. It provides an interface to configure the sensor and appropriate ADC channel, plus read out the + * current temperature in degrees C. It is designed for and will only work with the temperature sensor located on the + * official Atmel USB AVR boards, as each sensor has different characteristics. + * + * @{ + */ + +#ifndef __TEMPERATURE_H__ +#define __TEMPERATURE_H__ + + /* Includes: */ + #include + + #include "../../Common/Common.h" + #include "../Peripheral/ADC.h" + + #if (BOARD == BOARD_NONE) + #error The Board Temperature Sensor driver cannot be used if the makefile BOARD option is not set. + #elif ((BOARD != BOARD_USBKEY) && (BOARD != BOARD_STK525) && \ + (BOARD != BOARD_STK526) && (BOARD != BOARD_USER) && \ + (BOARD != BOARD_EVK527)) + #error The selected board does not contain a temperature sensor. + #endif + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** ADC channel number for the temperature sensor. */ + #define TEMP_ADC_CHANNEL 0 + + /** ADC channel MUX mask for the temperature sensor. */ + #define TEMP_ADC_CHANNEL_MASK ADC_CHANNEL0 + + /** Minimum returnable temperature from the \ref Temperature_GetTemperature() function. */ + #define TEMP_MIN_TEMP TEMP_TABLE_OFFSET + + /** Maximum returnable temperature from the \ref Temperature_GetTemperature() function. */ + #define TEMP_MAX_TEMP ((TEMP_TABLE_SIZE - 1) + TEMP_TABLE_OFFSET) + + /* Inline Functions: */ + /** Initialises the temperature sensor driver, including setting up the appropriate ADC channel. + * This must be called before any other temperature sensor routines. + * + * \pre The ADC itself (not the ADC channel) must be configured separately before calling the + * temperature sensor functions. + */ + static inline void Temperature_Init(void) ATTR_ALWAYS_INLINE; + static inline void Temperature_Init(void) + { + ADC_SetupChannel(TEMP_ADC_CHANNEL); + } + + /* Function Prototypes: */ + /** Performs a complete ADC on the temperature sensor channel, and converts the result into a + * valid temperature between \ref TEMP_MIN_TEMP and \ref TEMP_MAX_TEMP in degrees Celsius. + * + * \return Signed temperature value in degrees Celsius. + */ + int8_t Temperature_GetTemperature(void) ATTR_WARN_UNUSED_RESULT; + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define TEMP_TABLE_SIZE (sizeof(Temperature_Lookup) / sizeof(Temperature_Lookup[0])) + #define TEMP_TABLE_OFFSET -21 + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/UDIP/Buttons.h b/LUFA/Drivers/Board/UDIP/Buttons.h new file mode 100644 index 0000000..42646f8 --- /dev/null +++ b/LUFA/Drivers/Board/UDIP/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the UDIP. + * + * Board specific Buttons driver header for the Linnix UDIP (http://linnix.com/udip/). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_UDIP UDIP + * + * Board specific Buttons driver header for the Linnix UDIP (http://linnix.com/udip/). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_UDIP_H__ +#define __BUTTONS_UDIP_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/UDIP/LEDs.h b/LUFA/Drivers/Board/UDIP/LEDs.h new file mode 100644 index 0000000..e0060b5 --- /dev/null +++ b/LUFA/Drivers/Board/UDIP/LEDs.h @@ -0,0 +1,154 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Linnix UDIP. + * + * Board specific LED driver header for the Linnix UDIP (http://linnix.com/udip/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_UDIP UDIP + * + * Board specific LED driver header for the Linnix UDIP (http://linnix.com/udip/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_UDIP_H__ +#define __LEDS_UDIP_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define LEDS_PORTB_LEDS (LEDS_LED1 | LEDS_LED2) + #define LEDS_PORTD_LEDS (LEDS_LED3 | LEDS_LED4) + + #define LEDS_PORTD_MASK_SHIFT 1 + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 5) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 ((1 << 5) >> LEDS_PORTD_MASK_SHIFT) + + /** LED mask for the fourth LED on the board. */ + #define LEDS_LED4 ((1 << 4) >> LEDS_PORTD_MASK_SHIFT) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRB |= LEDS_PORTB_LEDS; + DDRD |= (LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT); + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTB |= (LEDMask & LEDS_PORTB_LEDS); + PORTD |= ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT); + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTB &= ~(LEDMask & LEDS_PORTB_LEDS); + PORTD &= ~((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT); + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTB = (PORTB & ~LEDS_PORTB_LEDS) | (LEDMask & LEDS_PORTB_LEDS); + PORTD = (PORTD & ~(LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT)) | + ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTB = (PORTB & ~(LEDMask & LEDS_PORTB_LEDS)) | (ActiveMask & LEDS_PORTB_LEDS); + PORTD = (PORTD & ~((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT)) | + ((ActiveMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTB ^= (LEDMask & LEDS_PORTB_LEDS); + PORTD ^= ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT); + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return ((PORTB & LEDS_PORTB_LEDS) | ((PORTD & LEDS_PORTD_LEDS) >> LEDS_PORTD_MASK_SHIFT)); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/UNO/LEDs.h b/LUFA/Drivers/Board/UNO/LEDs.h new file mode 100644 index 0000000..dc16cd1 --- /dev/null +++ b/LUFA/Drivers/Board/UNO/LEDs.h @@ -0,0 +1,130 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Arduino Uno. + * + * Board specific LED driver header for the Arduino Uno (http://arduino.cc/en/Main/ArduinoBoardUno). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_UNO UNO + * + * Board specific LED driver header for the Arduino Uno (http://arduino.cc/en/Main/ArduinoBoardUno). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_BENITO_H__ +#define __LEDS_BENITO_H__ + + /* Includes: */ + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 5) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD | LEDMask) & ~ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBFOO/Buttons.h b/LUFA/Drivers/Board/USBFOO/Buttons.h new file mode 100644 index 0000000..bb3f7e6 --- /dev/null +++ b/LUFA/Drivers/Board/USBFOO/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Kernel Concepts USBFOO. + * + * Board specific Buttons driver header for the Kernel Concepts USBFOO (http://shop.kernelconcepts.de/product_info.php?products_id=102). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_USBFOO USBFOO + * + * Board specific Buttons driver header for the Kernel Concepts USBFOO (http://shop.kernelconcepts.de/product_info.php?products_id=102). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_USBFOO_H__ +#define __BUTTONS_USBFOO_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBFOO/LEDS.h b/LUFA/Drivers/Board/USBFOO/LEDS.h new file mode 100644 index 0000000..e9dd196 --- /dev/null +++ b/LUFA/Drivers/Board/USBFOO/LEDS.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Kernel Concepts USBFOO. + * + * Board specific LED driver header for the Kernel Concepts USBFOO (http://shop.kernelconcepts.de/product_info.php?products_id=102). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_USBFOO USBFOO + * + * Board specific LED driver header for the Kernel Concepts USBFOO (http://shop.kernelconcepts.de/product_info.php?products_id=102). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_USBFOO_H__ +#define __LEDS_USBFOO_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD | LEDMask) & ~ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (~PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBKEY/AT45DB642D.h b/LUFA/Drivers/Board/USBKEY/AT45DB642D.h new file mode 100644 index 0000000..9f2a429 --- /dev/null +++ b/LUFA/Drivers/Board/USBKEY/AT45DB642D.h @@ -0,0 +1,115 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel USBKEY. + * + * Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash_USBKEY + * @defgroup Group_Dataflash_USBKEY_AT45DB642D AT45DB642D + * + * Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_CMDS_H__ +#define __DATAFLASH_CMDS_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name Dataflash Status Values */ + //@{ + #define DF_STATUS_READY (1 << 7) + #define DF_STATUS_COMPMISMATCH (1 << 6) + #define DF_STATUS_SECTORPROTECTION_ON (1 << 1) + #define DF_STATUS_BINARYPAGESIZE_ON (1 << 0) + //@} + + #define DF_MANUFACTURER_ATMEL 0x1F + + /** \name Dataflash Commands */ + //@{ + #define DF_CMD_GETSTATUS 0xD7 + #define DF_CMD_POWERDOWN 0xB9 + #define DF_CMD_WAKEUP 0xAB + + #define DF_CMD_MAINMEMTOBUFF1 0x53 + #define DF_CMD_MAINMEMTOBUFF2 0x55 + #define DF_CMD_MAINMEMTOBUFF1COMP 0x60 + #define DF_CMD_MAINMEMTOBUFF2COMP 0x61 + #define DF_CMD_AUTOREWRITEBUFF1 0x58 + #define DF_CMD_AUTOREWRITEBUFF2 0x59 + + #define DF_CMD_MAINMEMPAGEREAD 0xD2 + #define DF_CMD_CONTARRAYREAD_LF 0x03 + #define DF_CMD_BUFF1READ_LF 0xD1 + #define DF_CMD_BUFF2READ_LF 0xD3 + + #define DF_CMD_BUFF1WRITE 0x84 + #define DF_CMD_BUFF2WRITE 0x87 + #define DF_CMD_BUFF1TOMAINMEMWITHERASE 0x83 + #define DF_CMD_BUFF2TOMAINMEMWITHERASE 0x86 + #define DF_CMD_BUFF1TOMAINMEM 0x88 + #define DF_CMD_BUFF2TOMAINMEM 0x89 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF1 0x82 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF2 0x85 + + #define DF_CMD_PAGEERASE 0x81 + #define DF_CMD_BLOCKERASE 0x50 + #define DF_CMD_SECTORERASE 0x7C + + #define DF_CMD_CHIPERASE ((char[]){0xC7, 0x94, 0x80, 0x9A}) + #define DF_CMD_CHIPERASE_BYTE1 0xC7 + #define DF_CMD_CHIPERASE_BYTE2 0x94 + #define DF_CMD_CHIPERASE_BYTE3 0x80 + #define DF_CMD_CHIPERASE_BYTE4 0x9A + + #define DF_CMD_SECTORPROTECTIONOFF ((char[]){0x3D, 0x2A, 0x7F, 0x9A}) + #define DF_CMD_SECTORPROTECTIONOFF_BYTE1 0x3D + #define DF_CMD_SECTORPROTECTIONOFF_BYTE2 0x2A + #define DF_CMD_SECTORPROTECTIONOFF_BYTE3 0x7F + #define DF_CMD_SECTORPROTECTIONOFF_BYTE4 0x9A + + #define DF_CMD_READMANUFACTURERDEVICEINFO 0x9F + //@} + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBKEY/Buttons.h b/LUFA/Drivers/Board/USBKEY/Buttons.h new file mode 100644 index 0000000..d59e0a5 --- /dev/null +++ b/LUFA/Drivers/Board/USBKEY/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for the Atmel USBKEY. + * + * Board specific Buttons driver header for the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_USBKEY USBKEY + * + * Board specific Buttons driver header for the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_USBKEY_H__ +#define __BUTTONS_USBKEY_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 2) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRE &= ~BUTTONS_BUTTON1; + PORTE |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBKEY/Dataflash.h b/LUFA/Drivers/Board/USBKEY/Dataflash.h new file mode 100644 index 0000000..843928e --- /dev/null +++ b/LUFA/Drivers/Board/USBKEY/Dataflash.h @@ -0,0 +1,192 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash driver header for the Atmel USBKEY. + * + * Board specific Dataflash driver header for the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash + * @defgroup Group_Dataflash_USBKEY USBKEY + * + * Board specific Dataflash driver header for the Atmel USBKEY board. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_USBKEY_H__ +#define __DATAFLASH_USBKEY_H__ + + /* Includes: */ + #include "AT45DB642D.h" + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_DATAFLASH_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define DATAFLASH_CHIPCS_MASK ((1 << 1) | (1 << 0)) + #define DATAFLASH_CHIPCS_DDR DDRE + #define DATAFLASH_CHIPCS_PORT PORTE + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Constant indicating the total number of dataflash ICs mounted on the selected board. */ + #define DATAFLASH_TOTALCHIPS 2 + + /** Mask for no dataflash chip selected. */ + #define DATAFLASH_NO_CHIP DATAFLASH_CHIPCS_MASK + + /** Mask for the first dataflash chip selected. */ + #define DATAFLASH_CHIP1 (1 << 1) + + /** Mask for the second dataflash chip selected. */ + #define DATAFLASH_CHIP2 (1 << 0) + + /** Internal main memory page size for the board's dataflash ICs. */ + #define DATAFLASH_PAGE_SIZE 1024 + + /** Total number of pages inside each of the board's dataflash ICs. */ + #define DATAFLASH_PAGES 8192 + + /* Inline Functions: */ + /** Initialises the dataflash driver so that commands and data may be sent to an attached dataflash IC. + * The AVR's SPI driver MUST be initialized before any of the dataflash commands are used. + */ + static inline void Dataflash_Init(void) + { + DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK; + DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK; + } + + /** Determines the currently selected dataflash chip. + * + * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected + * or a DATAFLASH_CHIPn mask (where n is the chip number). + */ + static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Dataflash_GetSelectedChip(void) + { + return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK); + } + + /** Selects the given dataflash chip. + * + * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is + * the chip number). + */ + static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE; + static inline void Dataflash_SelectChip(const uint8_t ChipMask) + { + DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask); + } + + /** Deselects the current dataflash chip, so that no dataflash is selected. */ + static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE; + static inline void Dataflash_DeselectChip(void) + { + Dataflash_SelectChip(DATAFLASH_NO_CHIP); + } + + /** Selects a dataflash IC from the given page number, which should range from 0 to + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one + * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside + * the total number of pages contained in the boards dataflash ICs, all dataflash ICs + * are deselected. + * + * \param[in] PageAddress Address of the page to manipulate, ranging from + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). + */ + static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress) + { + Dataflash_DeselectChip(); + + if (PageAddress >= (DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS)) + return; + + if (PageAddress & 0x01) + Dataflash_SelectChip(DATAFLASH_CHIP2); + else + Dataflash_SelectChip(DATAFLASH_CHIP1); + } + + /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive + * a new command. + */ + static inline void Dataflash_ToggleSelectedChipCS(void) + { + uint8_t SelectedChipMask = Dataflash_GetSelectedChip(); + + Dataflash_DeselectChip(); + Dataflash_SelectChip(SelectedChipMask); + } + + /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main + * memory page program or main memory to buffer transfer. + */ + static inline void Dataflash_WaitWhileBusy(void) + { + Dataflash_ToggleSelectedChipCS(); + Dataflash_SendByte(DF_CMD_GETSTATUS); + while (!(Dataflash_ReceiveByte() & DF_STATUS_READY)); + Dataflash_ToggleSelectedChipCS(); + } + + /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with + * dataflash commands which require a complete 24-byte address. + * + * \param[in] PageAddress Page address within the selected dataflash IC + * \param[in] BufferByte Address within the dataflash's buffer + */ + static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, + const uint16_t BufferByte) + { + PageAddress >>= 1; + + Dataflash_SendByte(PageAddress >> 5); + Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8)); + Dataflash_SendByte(BufferByte); + } + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBKEY/Joystick.h b/LUFA/Drivers/Board/USBKEY/Joystick.h new file mode 100644 index 0000000..65d2b53 --- /dev/null +++ b/LUFA/Drivers/Board/USBKEY/Joystick.h @@ -0,0 +1,119 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific joystick driver header for the Atmel USBKEY. + * + * Board specific joystick driver header for the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + */ + +/** \ingroup Group_Joystick + * @defgroup Group_Joystick_USBKEY USBKEY + * + * Board specific joystick driver header for the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the joystick driver + * dispatch header located in LUFA/Drivers/Board/Joystick.h. + * + * @{ + */ + +#ifndef __JOYSTICK_USBKEY_H__ +#define __JOYSTICK_USBKEY_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_JOYSTICK_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define JOY_BMASK ((1 << 5) | (1 << 6) | (1 << 7)) + #define JOY_EMASK ((1 << 4) | (1 << 5)) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for the joystick being pushed in the left direction. */ + #define JOY_LEFT (1 << 6) + + /** Mask for the joystick being pushed in the right direction. */ + #define JOY_RIGHT ((1 << 4) >> 1) + + /** Mask for the joystick being pushed in the upward direction. */ + #define JOY_UP (1 << 7) + + /** Mask for the joystick being pushed in the downward direction. */ + #define JOY_DOWN ((1 << 5) >> 1) + + /** Mask for the joystick being pushed inward. */ + #define JOY_PRESS (1 << 5) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Joystick_Init(void) + { + DDRB &= ~(JOY_BMASK); + DDRE &= ~(JOY_EMASK); + + PORTB |= JOY_BMASK; + PORTE |= JOY_EMASK; + } + + static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Joystick_GetStatus(void) + { + return (((uint8_t)~PINB & JOY_BMASK) | (((uint8_t)~PINE & JOY_EMASK) >> 1)); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBKEY/LEDs.h b/LUFA/Drivers/Board/USBKEY/LEDs.h new file mode 100644 index 0000000..9362b78 --- /dev/null +++ b/LUFA/Drivers/Board/USBKEY/LEDs.h @@ -0,0 +1,137 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Atmel USBKEY. + * + * Board specific LED driver header for the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_USBKEY USBKEY + * + * Board specific LED driver header for the Atmel USBKEY. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_USBKEY_H__ +#define __LEDS_USBKEY_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 4) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 5) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 (1 << 7) + + /** LED mask for the fourth LED on the board. */ + #define LEDS_LED4 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRD |= LEDS_ALL_LEDS; + PORTD &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTD |= LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTD &= ~LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTD = ((PORTD & ~LEDMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTD & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ diff --git a/LUFA/Drivers/Board/USBTINYMKII/Buttons.h b/LUFA/Drivers/Board/USBTINYMKII/Buttons.h new file mode 100644 index 0000000..059016e --- /dev/null +++ b/LUFA/Drivers/Board/USBTINYMKII/Buttons.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Buttons driver header for Tom's USBTINY MKII. + * + * Board specific Buttons driver header for Tom's USBTINY MKII (http://tom-itx.dyndns.org:81/~webpage/). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + */ + +/** \ingroup Group_Buttons + * @defgroup Group_Buttons_USBTINYMKII USBTINYMKII + * + * Board specific Buttons driver header for Tom's USBTINY MKII (http://tom-itx.dyndns.org:81/~webpage/). + * + * \note This file should not be included directly. It is automatically included as needed by the Buttons driver + * dispatch header located in LUFA/Drivers/Board/Buttons.h. + * + * @{ + */ + +#ifndef __BUTTONS_USBTINYMKII_H__ +#define __BUTTONS_USBTINYMKII_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_BUTTONS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Button mask for the first button on the board. */ + #define BUTTONS_BUTTON1 (1 << 7) + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void Buttons_Init(void) + { + DDRD &= ~BUTTONS_BUTTON1; + PORTD |= BUTTONS_BUTTON1; + } + + static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Buttons_GetStatus(void) + { + return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/USBTINYMKII/LEDs.h b/LUFA/Drivers/Board/USBTINYMKII/LEDs.h new file mode 100644 index 0000000..cd33a2a --- /dev/null +++ b/LUFA/Drivers/Board/USBTINYMKII/LEDs.h @@ -0,0 +1,133 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for Tom's USBTINY MKII. + * + * Board specific LED driver header for Tom's USBTINY MKII (http://tom-itx.dyndns.org:81/~webpage/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_USBTINYMKII USBTINYMKII + * + * Board specific LED driver header for Tom's USBTINY MKII (http://tom-itx.dyndns.org:81/~webpage/). + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_USBTINYMKII_H__ +#define __LEDS_USBTINYMKII_H__ + + /* Includes: */ + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for the second LED on the board. */ + #define LEDS_LED2 (1 << 7) + + /** LED mask for the third LED on the board. */ + #define LEDS_LED3 (1 << 5) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3) + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRB |= LEDS_ALL_LEDS; + PORTB &= ~LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LedMask) + { + PORTB |= LedMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LedMask) + { + PORTB &= ~LedMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LedMask) + { + PORTB = ((PORTB & ~LEDS_ALL_LEDS) | LedMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LedMask, + const uint8_t ActiveMask) + { + PORTB = ((PORTB & ~LedMask) | ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTB ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (PORTB & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/XPLAIN/AT45DB642D.h b/LUFA/Drivers/Board/XPLAIN/AT45DB642D.h new file mode 100644 index 0000000..b02d338 --- /dev/null +++ b/LUFA/Drivers/Board/XPLAIN/AT45DB642D.h @@ -0,0 +1,115 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel XPLAIN. + * + * Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel XPLAIN. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash_XPLAIN + * @defgroup Group_Dataflash_XPLAIN_AT45DB642D AT45DB642D + * + * Board specific Dataflash commands header for the AT45DB642D as mounted on the Atmel XPLAIN. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_CMDS_H__ +#define __DATAFLASH_CMDS_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name Dataflash Status Values */ + //@{ + #define DF_STATUS_READY (1 << 7) + #define DF_STATUS_COMPMISMATCH (1 << 6) + #define DF_STATUS_SECTORPROTECTION_ON (1 << 1) + #define DF_STATUS_BINARYPAGESIZE_ON (1 << 0) + //@} + + #define DF_MANUFACTURER_ATMEL 0x1F + + /** \name Dataflash Commands */ + //@{ + #define DF_CMD_GETSTATUS 0xD7 + #define DF_CMD_POWERDOWN 0xB9 + #define DF_CMD_WAKEUP 0xAB + + #define DF_CMD_MAINMEMTOBUFF1 0x53 + #define DF_CMD_MAINMEMTOBUFF2 0x55 + #define DF_CMD_MAINMEMTOBUFF1COMP 0x60 + #define DF_CMD_MAINMEMTOBUFF2COMP 0x61 + #define DF_CMD_AUTOREWRITEBUFF1 0x58 + #define DF_CMD_AUTOREWRITEBUFF2 0x59 + + #define DF_CMD_MAINMEMPAGEREAD 0xD2 + #define DF_CMD_CONTARRAYREAD_LF 0x03 + #define DF_CMD_BUFF1READ_LF 0xD1 + #define DF_CMD_BUFF2READ_LF 0xD3 + + #define DF_CMD_BUFF1WRITE 0x84 + #define DF_CMD_BUFF2WRITE 0x87 + #define DF_CMD_BUFF1TOMAINMEMWITHERASE 0x83 + #define DF_CMD_BUFF2TOMAINMEMWITHERASE 0x86 + #define DF_CMD_BUFF1TOMAINMEM 0x88 + #define DF_CMD_BUFF2TOMAINMEM 0x89 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF1 0x82 + #define DF_CMD_MAINMEMPAGETHROUGHBUFF2 0x85 + + #define DF_CMD_PAGEERASE 0x81 + #define DF_CMD_BLOCKERASE 0x50 + #define DF_CMD_SECTORERASE 0x7C + + #define DF_CMD_CHIPERASE ((char[]){0xC7, 0x94, 0x80, 0x9A}) + #define DF_CMD_CHIPERASE_BYTE1 0xC7 + #define DF_CMD_CHIPERASE_BYTE2 0x94 + #define DF_CMD_CHIPERASE_BYTE3 0x80 + #define DF_CMD_CHIPERASE_BYTE4 0x9A + + #define DF_CMD_SECTORPROTECTIONOFF ((char[]){0x3D, 0x2A, 0x7F, 0x9A}) + #define DF_CMD_SECTORPROTECTIONOFF_BYTE1 0x3D + #define DF_CMD_SECTORPROTECTIONOFF_BYTE2 0x2A + #define DF_CMD_SECTORPROTECTIONOFF_BYTE3 0x7F + #define DF_CMD_SECTORPROTECTIONOFF_BYTE4 0x9A + + #define DF_CMD_READMANUFACTURERDEVICEINFO 0x9F + //@} + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/XPLAIN/Dataflash.h b/LUFA/Drivers/Board/XPLAIN/Dataflash.h new file mode 100644 index 0000000..0779b05 --- /dev/null +++ b/LUFA/Drivers/Board/XPLAIN/Dataflash.h @@ -0,0 +1,190 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific Dataflash driver header for the Atmel XPLAIN. + * + * Board specific Dataflash driver header for the Atmel XPLAIN. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + */ + +/** \ingroup Group_Dataflash + * @defgroup Group_Dataflash_XPLAIN XPLAIN + * + * Board specific Dataflash driver header for the Atmel XPLAIN. + * + * \note This file should not be included directly. It is automatically included as needed by the dataflash driver + * dispatch header located in LUFA/Drivers/Board/Dataflash.h. + * + * @{ + */ + +#ifndef __DATAFLASH_XPLAIN_H__ +#define __DATAFLASH_XPLAIN_H__ + + /* Includes: */ + #include "AT45DB642D.h" + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_DATAFLASH_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define DATAFLASH_CHIPCS_MASK (1 << 5) + #define DATAFLASH_CHIPCS_DDR DDRB + #define DATAFLASH_CHIPCS_PORT PORTB + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Constant indicating the total number of dataflash ICs mounted on the selected board. */ + #define DATAFLASH_TOTALCHIPS 1 + + /** Mask for no dataflash chip selected. */ + #define DATAFLASH_NO_CHIP DATAFLASH_CHIPCS_MASK + + /** Mask for the first dataflash chip selected. */ + #define DATAFLASH_CHIP1 0 + + #if (BOARD == BOARD_XPLAIN_REV1) + #define DATAFLASH_PAGE_SIZE 256 + + #define DATAFLASH_PAGES 2048 + #else + /** Internal main memory page size for the board's dataflash ICs. */ + #define DATAFLASH_PAGE_SIZE 1024 + + /** Total number of pages inside each of the board's dataflash ICs. */ + #define DATAFLASH_PAGES 8192 + #endif + + /* Inline Functions: */ + /** Initialises the dataflash driver so that commands and data may be sent to an attached dataflash IC. + * The AVR's SPI driver MUST be initialized before any of the dataflash commands are used. + */ + static inline void Dataflash_Init(void) + { + DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK; + DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK; + } + + /** Determines the currently selected dataflash chip. + * + * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected + * or a DATAFLASH_CHIPn mask (where n is the chip number). + */ + static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Dataflash_GetSelectedChip(void) + { + return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK); + } + + /** Selects the given dataflash chip. + * + * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is + * the chip number). + */ + static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE; + static inline void Dataflash_SelectChip(const uint8_t ChipMask) + { + DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask); + } + + /** Deselects the current dataflash chip, so that no dataflash is selected. */ + static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE; + static inline void Dataflash_DeselectChip(void) + { + Dataflash_SelectChip(DATAFLASH_NO_CHIP); + } + + /** Selects a dataflash IC from the given page number, which should range from 0 to + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one + * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside + * the total number of pages contained in the boards dataflash ICs, all dataflash ICs + * are deselected. + * + * \param[in] PageAddress Address of the page to manipulate, ranging from + * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). + */ + static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress) + { + Dataflash_DeselectChip(); + + if (PageAddress >= DATAFLASH_PAGES) + return; + + Dataflash_SelectChip(DATAFLASH_CHIP1); + } + + /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive + * a new command. + */ + static inline void Dataflash_ToggleSelectedChipCS(void) + { + uint8_t SelectedChipMask = Dataflash_GetSelectedChip(); + + Dataflash_DeselectChip(); + Dataflash_SelectChip(SelectedChipMask); + } + + /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main + * memory page program or main memory to buffer transfer. + */ + static inline void Dataflash_WaitWhileBusy(void) + { + Dataflash_ToggleSelectedChipCS(); + Dataflash_SendByte(DF_CMD_GETSTATUS); + while (!(Dataflash_ReceiveByte() & DF_STATUS_READY)); + Dataflash_ToggleSelectedChipCS(); + } + + /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with + * dataflash commands which require a complete 24-byte address. + * + * \param[in] PageAddress Page address within the selected dataflash IC + * \param[in] BufferByte Address within the dataflash's buffer + */ + static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, + const uint16_t BufferByte) + { + Dataflash_SendByte(PageAddress >> 5); + Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8)); + Dataflash_SendByte(BufferByte); + } + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Board/XPLAIN/LEDs.h b/LUFA/Drivers/Board/XPLAIN/LEDs.h new file mode 100644 index 0000000..a6b2fd2 --- /dev/null +++ b/LUFA/Drivers/Board/XPLAIN/LEDs.h @@ -0,0 +1,129 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Board specific LED driver header for the Atmel XPLAIN. + * + * Board specific LED driver header for the Atmel XPLAIN. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + */ + +/** \ingroup Group_LEDs + * @defgroup Group_LEDs_XPLAIN XPLAIN + * + * Board specific LED driver header for the Atmel XPLAIN. + * + * \note This file should not be included directly. It is automatically included as needed by the LEDs driver + * dispatch header located in LUFA/Drivers/Board/LEDs.h. + * + * @{ + */ + +#ifndef __LEDS_XPLAIN_H__ +#define __LEDS_XPLAIN_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_LEDS_H) + #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** LED mask for the first LED on the board. */ + #define LEDS_LED1 (1 << 6) + + /** LED mask for all the LEDs on the board. */ + #define LEDS_ALL_LEDS LEDS_LED1 + + /** LED mask for none of the board LEDs. */ + #define LEDS_NO_LEDS 0 + + /* Inline Functions: */ + #if !defined(__DOXYGEN__) + static inline void LEDs_Init(void) + { + DDRB |= LEDS_ALL_LEDS; + PORTB |= LEDS_ALL_LEDS; + } + + static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask) + { + PORTB &= ~LEDMask; + } + + static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask) + { + PORTB |= LEDMask; + } + + static inline void LEDs_SetAllLEDs(const uint8_t LEDMask) + { + PORTB = ((PORTB | LEDS_ALL_LEDS) & ~LEDMask); + } + + static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, + const uint8_t ActiveMask) + { + PORTB = ((PORTB | LEDMask) & ~ActiveMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTB ^= LEDMask; + } + + static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t LEDs_GetLEDs(void) + { + return (~PORTB & LEDS_ALL_LEDS); + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Misc/TerminalCodes.h b/LUFA/Drivers/Misc/TerminalCodes.h new file mode 100644 index 0000000..b1bb8b8 --- /dev/null +++ b/LUFA/Drivers/Misc/TerminalCodes.h @@ -0,0 +1,224 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief ANSI terminal special escape code macros. + * + * ANSI terminal compatible escape sequences. These escape sequences are designed to be concatenated with existing + * strings to modify their display on a compatible terminal application. + */ + +/** \ingroup Group_MiscDrivers + * @defgroup Group_Terminal ANSI Terminal Escape Codes - LUFA/Drivers/Misc/TerminalCodes.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Module Description + * Escape code macros for ANSI compliant text terminals. + * + * \note If desired, the macro DISABLE_TERMINAL_CODES can be defined in the project makefile and passed to the GCC + * compiler via the -D switch to disable the terminal codes without modifying the source, for use with non + * compatible terminals (any terminal codes then equate to empty strings). + * + * Example Usage: + * \code + * printf("Some String, " ESC_BOLD_ON " Some bold string"); + * \endcode + * + * @{ + */ + +#ifndef __TERMINALCODES_H__ +#define __TERMINALCODES_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + #if !defined(DISABLE_TERMINAL_CODES) + /** Creates an ANSI escape sequence with the specified payload. + * + * \param[in] EscapeSeq Payload to encode as an ANSI escape sequence, a ESC_* mask. + */ + #define ANSI_ESCAPE_SEQUENCE(EscapeSeq) "\33[" EscapeSeq + #else + #define ANSI_ESCAPE_SEQUENCE(EscapeSeq) + #endif + + /** \name Text Display Modifier Escape Sequences */ + //@{ + /** Turns on bold so that any following text is printed to the terminal in bold. */ + #define ESC_BOLD_ON ANSI_ESCAPE_SEQUENCE("1m") + + /** Turns on italics so that any following text is printed to the terminal in italics. */ + #define ESC_ITALICS_ON ANSI_ESCAPE_SEQUENCE("3m") + + /** Turns on underline so that any following text is printed to the terminal underlined. */ + #define ESC_UNDERLINE_ON ANSI_ESCAPE_SEQUENCE("4m") + + /** Turns on inverse so that any following text is printed to the terminal in inverted colours. */ + #define ESC_INVERSE_ON ANSI_ESCAPE_SEQUENCE("7m") + + /** Turns on strikethrough so that any following text is printed to the terminal with a line through the + * center. + */ + #define ESC_STRIKETHROUGH_ON ANSI_ESCAPE_SEQUENCE("9m") + + /** Turns off bold so that any following text is printed to the terminal in non bold. */ + #define ESC_BOLD_OFF ANSI_ESCAPE_SEQUENCE("22m") + + /** Turns off italics so that any following text is printed to the terminal in non italics. */ + #define ESC_ITALICS_OFF ANSI_ESCAPE_SEQUENCE("23m") + + /** Turns off underline so that any following text is printed to the terminal non underlined. */ + #define ESC_UNDERLINE_OFF ANSI_ESCAPE_SEQUENCE("24m") + + /** Turns off inverse so that any following text is printed to the terminal in non inverted colours. */ + #define ESC_INVERSE_OFF ANSI_ESCAPE_SEQUENCE("27m") + + /** Turns off strikethrough so that any following text is printed to the terminal without a line through + * the center. + */ + #define ESC_STRIKETHROUGH_OFF ANSI_ESCAPE_SEQUENCE("29m") + //@} + + /** \name Text Colour Control Sequences */ + //@{ + /** Sets the foreground (text) colour to black. */ + #define ESC_FG_BLACK ANSI_ESCAPE_SEQUENCE("30m") + + /** Sets the foreground (text) colour to red. */ + #define ESC_FG_RED ANSI_ESCAPE_SEQUENCE("31m") + + /** Sets the foreground (text) colour to green. */ + #define ESC_FG_GREEN ANSI_ESCAPE_SEQUENCE("32m") + + /** Sets the foreground (text) colour to yellow. */ + #define ESC_FG_YELLOW ANSI_ESCAPE_SEQUENCE("33m") + + /** Sets the foreground (text) colour to blue. */ + #define ESC_FG_BLUE ANSI_ESCAPE_SEQUENCE("34m") + + /** Sets the foreground (text) colour to magenta. */ + #define ESC_FG_MAGENTA ANSI_ESCAPE_SEQUENCE("35m") + + /** Sets the foreground (text) colour to cyan. */ + #define ESC_FG_CYAN ANSI_ESCAPE_SEQUENCE("36m") + + /** Sets the foreground (text) colour to white. */ + #define ESC_FG_WHITE ANSI_ESCAPE_SEQUENCE("37m") + + /** Sets the foreground (text) colour to the terminal's default. */ + #define ESC_FG_DEFAULT ANSI_ESCAPE_SEQUENCE("39m") + + /** Sets the text background colour to black. */ + #define ESC_BG_BLACK ANSI_ESCAPE_SEQUENCE("40m") + + /** Sets the text background colour to red. */ + #define ESC_BG_RED ANSI_ESCAPE_SEQUENCE("41m") + + /** Sets the text background colour to green. */ + #define ESC_BG_GREEN ANSI_ESCAPE_SEQUENCE("42m") + + /** Sets the text background colour to yellow. */ + #define ESC_BG_YELLOW ANSI_ESCAPE_SEQUENCE("43m") + + /** Sets the text background colour to blue. */ + #define ESC_BG_BLUE ANSI_ESCAPE_SEQUENCE("44m") + + /** Sets the text background colour to magenta. */ + #define ESC_BG_MAGENTA ANSI_ESCAPE_SEQUENCE("45m") + + /** Sets the text background colour to cyan. */ + #define ESC_BG_CYAN ANSI_ESCAPE_SEQUENCE("46m") + + /** Sets the text background colour to white. */ + #define ESC_BG_WHITE ANSI_ESCAPE_SEQUENCE("47m") + + /** Sets the text background colour to the terminal's default. */ + #define ESC_BG_DEFAULT ANSI_ESCAPE_SEQUENCE("49m") + //@} + + /** \name Cursor Positioning Control Sequences */ + //@{ + /** Saves the current cursor position so that it may be restored with \ref ESC_CURSOR_POS_RESTORE. */ + #define ESC_CURSOR_POS_SAVE ANSI_ESCAPE_SEQUENCE("s") + + /** Restores the cursor position to the last position saved with \ref ESC_CURSOR_POS_SAVE. */ + #define ESC_CURSOR_POS_RESTORE ANSI_ESCAPE_SEQUENCE("u") + + /** Sets the cursor position to the given line and column. + * + * \param[in] Line Line number to position the cursor at + * \param[in] Column Column number to position the cursor at + */ + #define ESC_CURSOR_POS(Line, Column) ANSI_ESCAPE_SEQUENCE(#Line ";" #Column "H") + + /** Moves the cursor up the given number of lines. + * + * \param[in] Lines Number of lines to move the cursor position + */ + #define ESC_CURSOR_UP(Lines) ANSI_ESCAPE_SEQUENCE(#Lines "A") + + /** Moves the cursor down the given number of lines. + * + * \param[in] Lines Number of lines to move the cursor position + */ + #define ESC_CURSOR_DOWN(Lines) ANSI_ESCAPE_SEQUENCE(#Lines "B") + + /** Moves the cursor to the right the given number of columns. + * + * \param[in] Columns Number of columns to move the cursor position + */ + #define ESC_CURSOR_FORWARD(Columns) ANSI_ESCAPE_SEQUENCE(#Columns "C") + + /** Moves the cursor to the left the given number of columns. + * + * \param[in] Columns Number of columns to move the cursor position + */ + #define ESC_CURSOR_BACKWARD(Columns) ANSI_ESCAPE_SEQUENCE(#Columns "D") + //@} + + /** \name Miscellaneous Control Sequences */ + //@{ + /** Resets any escape sequence modifiers back to their defaults. */ + #define ESC_RESET ANSI_ESCAPE_SEQUENCE("0m") + + /** Erases the entire display, returning the cursor to the top left. */ + #define ESC_ERASE_DISPLAY ANSI_ESCAPE_SEQUENCE("2J") + + /** Erases the current line, returning the cursor to the far left. */ + #define ESC_ERASE_LINE ANSI_ESCAPE_SEQUENCE("K") + //@} + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Peripheral/ADC.h b/LUFA/Drivers/Peripheral/ADC.h new file mode 100644 index 0000000..d172584 --- /dev/null +++ b/LUFA/Drivers/Peripheral/ADC.h @@ -0,0 +1,72 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the ADC peripheral driver. + * + * This file is the master dispatch header file for the device-specific ADC driver, for AVRs containing an ADC. + * + * User code should include this file, which will in turn include the correct ADC driver header file for the + * currently selected AVR model. + */ + +/** \ingroup Group_PeripheralDrivers + * @defgroup Group_ADC ADC Driver - LUFA/Drivers/Peripheral/ADC.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Module Description + * Hardware ADC driver. This module provides an easy to use driver for the hardware + * ADC present on many AVR models, for the conversion of analogue signals into the + * digital domain. + */ + +#ifndef __ADC_H__ +#define __ADC_H__ + + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __INCLUDE_FROM_ADC_H + #endif + + /* Includes: */ + #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \ + defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \ + defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || \ + defined(__AVR_ATmega32U6__)) + #include "AVRU4U6U7/ADC.h" + #else + #error "ADC is not available for the currently selected AVR model." + #endif + +#endif + diff --git a/LUFA/Drivers/Peripheral/AVRU4U6U7/ADC.h b/LUFA/Drivers/Peripheral/AVRU4U6U7/ADC.h new file mode 100644 index 0000000..9a72cd2 --- /dev/null +++ b/LUFA/Drivers/Peripheral/AVRU4U6U7/ADC.h @@ -0,0 +1,411 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief ADC peripheral driver for the U7, U6 and U4 USB AVRs. + * + * On-chip Analogue-to-Digital converter (ADC) driver for supported U4, U6 and U7 model AVRs that contain an ADC + * peripheral internally. + * + * \note This file should not be included directly. It is automatically included as needed by the ADC driver + * dispatch header located in LUFA/Drivers/Peripheral/ADC.h. + */ + +/** \ingroup Group_ADC + * @defgroup Group_ADC_AVRU4U6U7 Series U4, U6 and U7 Model ADC Driver + * + * On-chip Analogue-to-Digital converter (ADC) driver for supported U4, U6 and U7 model AVRs that contain an ADC + * peripheral internally. + * + * \note This file should not be included directly. It is automatically included as needed by the ADC driver + * dispatch header located in LUFA/Drivers/Peripheral/ADC.h. + * + * @{ + */ + +#ifndef __ADC_AVRU4U6U7_H__ +#define __ADC_AVRU4U6U7_H__ + + /* Includes: */ + #include "../../../Common/Common.h" + + #include + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_ADC_H) + #error Do not include this file directly. Include LUFA/Drivers/Peripheral/ADC.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name ADC Reference Configuration Masks */ + //@{ + /** Reference mask, for using the voltage present at the AVR's AREF pin for the ADC reference. */ + #define ADC_REFERENCE_AREF 0 + + /** Reference mask, for using the voltage present at the AVR's AVCC pin for the ADC reference. */ + #define ADC_REFERENCE_AVCC (1 << REFS0) + + /** Reference mask, for using the internally generated 2.56V reference voltage as the ADC reference. */ + #define ADC_REFERENCE_INT2560MV ((1 << REFS1) | (1 << REFS0)) + //@} + + /** \name ADC Result Adjustment Configuration Masks */ + //@{ + /** Left-adjusts the 10-bit ADC result, so that the upper 8 bits of the value returned by the + * ADC_GetResult() macro contain the 8 most significant bits of the result. + */ + #define ADC_LEFT_ADJUSTED (1 << ADLAR) + + /** Right-adjusts the 10-bit ADC result, so that the lower 8 bits of the value returned by the + * ADC_GetResult() macro contain the 8 least significant bits of the result. + */ + #define ADC_RIGHT_ADJUSTED (0 << ADLAR) + //@} + + /** \name ADC Mode Configuration Masks */ + //@{ + /** Sets the ADC mode to free running, so that conversions take place continuously as fast as the ADC + * is capable of at the given input clock speed. + */ + #define ADC_FREE_RUNNING (1 << ADATE) + + /** Sets the ADC mode to single conversion, so that only a single conversion will take place before + * the ADC returns to idle. + */ + #define ADC_SINGLE_CONVERSION (0 << ADATE) + //@} + + /** \name ADC Prescaler Configuration Masks */ + //@{ + /** Sets the ADC input clock to prescale by a factor of 2 the AVR's system clock. */ + #define ADC_PRESCALE_2 (1 << ADPS0) + + /** Sets the ADC input clock to prescale by a factor of 4 the AVR's system clock. */ + #define ADC_PRESCALE_4 (1 << ADPS1) + + /** Sets the ADC input clock to prescale by a factor of 8 the AVR's system clock. */ + #define ADC_PRESCALE_8 ((1 << ADPS0) | (1 << ADPS1)) + + /** Sets the ADC input clock to prescale by a factor of 16 the AVR's system clock. */ + #define ADC_PRESCALE_16 (1 << ADPS2) + + /** Sets the ADC input clock to prescale by a factor of 32 the AVR's system clock. */ + #define ADC_PRESCALE_32 ((1 << ADPS2) | (1 << ADPS0)) + + /** Sets the ADC input clock to prescale by a factor of 64 the AVR's system clock. */ + #define ADC_PRESCALE_64 ((1 << ADPS2) | (1 << ADPS1)) + + /** Sets the ADC input clock to prescale by a factor of 128 the AVR's system clock. */ + #define ADC_PRESCALE_128 ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)) + //@} + + /** \name ADC MUX Masks */ + //@{ + /** MUX mask define for the ADC0 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */ + #define ADC_CHANNEL0 (0x00 << MUX0) + + /** MUX mask define for the ADC1 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */ + #define ADC_CHANNEL1 (0x01 << MUX0) + + #if !(defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__DOXYGEN__)) + /** MUX mask define for the ADC2 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL2 (0x02 << MUX0) + + /** MUX mask define for the ADC3 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL3 (0x03 << MUX0) + #endif + + /** MUX mask define for the ADC4 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */ + #define ADC_CHANNEL4 (0x04 << MUX0) + + /** MUX mask define for the ADC5 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */ + #define ADC_CHANNEL5 (0x05 << MUX0) + + /** MUX mask define for the ADC6 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */ + #define ADC_CHANNEL6 (0x06 << MUX0) + + /** MUX mask define for the ADC7 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */ + #define ADC_CHANNEL7 (0x07 << MUX0) + + /** MUX mask define for the internal 1.1V bandgap channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */ + #define ADC_1100MV_BANDGAP (0x1E << MUX0) + + #if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__DOXYGEN__)) + /** MUX mask define for the ADC8 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL8 ((1 << 8) | (0x00 << MUX0)) + + /** MUX mask define for the ADC9 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL9 ((1 << 8) | (0x01 << MUX0)) + + /** MUX mask define for the ADC10 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL10 ((1 << 8) | (0x02 << MUX0)) + + /** MUX mask define for the ADC11 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL11 ((1 << 8) | (0x03 << MUX0)) + + /** MUX mask define for the ADC12 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL12 ((1 << 8) | (0x04 << MUX0)) + + /** MUX mask define for the ADC13 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_CHANNEL13 ((1 << 8) | (0x05 << MUX0)) + + /** MUX mask define for the internal temperature sensor channel of the ADC. See \ref ADC_StartReading and + * \ref ADC_GetChannelReading. + * + * \note Not available on all AVR models. + */ + #define ADC_INT_TEMP_SENS ((1 << 8) | (0x07 << MUX0)) + #endif + //@} + + /* Inline Functions: */ + /** Configures the given ADC channel, ready for ADC conversions. This function sets the + * associated port pin as an input and disables the digital portion of the I/O to reduce + * power consumption. + * + * \note This must only be called for ADC channels with are connected to a physical port + * pin of the AVR, denoted by its special alternative function ADCx. + * \n\n + * + * \note The channel number must be specified as an integer, and NOT a ADC_CHANNELx mask. + * + * \param[in] ChannelIndex ADC channel number to set up for conversions. + */ + static inline void ADC_SetupChannel(const uint8_t ChannelIndex) + { + #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \ + defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \ + defined(__AVR_ATmega32U6__)) + DDRF &= ~(1 << ChannelIndex); + DIDR0 |= (1 << ChannelIndex); + #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) + if (ChannelIndex < 8) + { + DDRF &= ~(1 << ChannelIndex); + DIDR0 |= (1 << ChannelIndex); + } + else if (ChannelIndex == 8) + { + DDRD &= ~(1 << 4); + DIDR2 |= (1 << 0); + } + else if (ChannelIndex < 11) + { + DDRD &= ~(1 << (ChannelIndex - 3)); + DIDR2 |= (1 << (ChannelIndex - 8)); + } + else + { + DDRB &= ~(1 << (ChannelIndex - 7)); + DIDR2 |= (1 << (ChannelIndex - 8)); + } + #endif + } + + /** De-configures the given ADC channel, re-enabling digital I/O mode instead of analog. This + * function sets the associated port pin as an input and re-enabled the digital portion of + * the I/O. + * + * \note This must only be called for ADC channels with are connected to a physical port + * pin of the AVR, denoted by its special alternative function ADCx. + * \n\n + * + * \note The channel number must be specified as an integer, and NOT a ADC_CHANNELx mask. + * + * \param[in] ChannelIndex ADC channel number to set up for conversions. + */ + static inline void ADC_DisableChannel(const uint8_t ChannelIndex) + { + #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \ + defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \ + defined(__AVR_ATmega32U6__)) + DDRF &= ~(1 << ChannelIndex); + DIDR0 &= ~(1 << ChannelIndex); + #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) + if (ChannelIndex < 8) + { + DDRF &= ~(1 << ChannelIndex); + DIDR0 &= ~(1 << ChannelIndex); + } + else if (ChannelIndex == 8) + { + DDRD &= ~(1 << 4); + DIDR2 &= ~(1 << 0); + } + else if (ChannelIndex < 11) + { + DDRD &= ~(1 << (ChannelIndex - 3)); + DIDR2 &= ~(1 << (ChannelIndex - 8)); + } + else + { + DDRB &= ~(1 << (ChannelIndex - 7)); + DIDR2 &= ~(1 << (ChannelIndex - 8)); + } + #endif + } + + /** Starts the reading of the given channel, but does not wait until the conversion has completed. + * Once executed, the conversion status can be determined via the \ref ADC_IsReadingComplete() macro and + * the result read via the \ref ADC_GetResult() macro. + * + * If the ADC has been initialized in free running mode, calling this function once will begin the repeated + * conversions. If the ADC is in single conversion mode (or the channel to convert from is to be changed), + * this function must be called each time a conversion is to take place. + * + * \param[in] MUXMask ADC channel mask, reference mask and adjustment mask. + */ + static inline void ADC_StartReading(const uint16_t MUXMask) + { + ADMUX = MUXMask; + + #if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__DOXYGEN__)) + if (MUXMask & (1 << 8)) + ADCSRB |= (1 << MUX5); + else + ADCSRB &= ~(1 << MUX5); + #endif + + ADCSRA |= (1 << ADSC); + } + + /** Indicates if the current ADC conversion is completed, or still in progress. + * + * \return Boolean false if the reading is still taking place, or true if the conversion is + * complete and ready to be read out with \ref ADC_GetResult(). + */ + static inline bool ADC_IsReadingComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool ADC_IsReadingComplete(void) + { + return ((ADCSRA & (1 << ADIF)) ? true : false); + } + + /** Retrieves the conversion value of the last completed ADC conversion and clears the reading + * completion flag. + * + * \return The result of the last ADC conversion as an unsigned value. + */ + static inline uint16_t ADC_GetResult(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t ADC_GetResult(void) + { + ADCSRA |= (1 << ADIF); + return ADC; + } + + /** Performs a complete single reading from channel, including a polling spin-loop to wait for the + * conversion to complete, and the returning of the converted value. + * + * \note For free running mode, the automated conversions should be initialized with a single call + * to \ref ADC_StartReading() to select the channel and begin the automated conversions, and + * the results read directly from the \ref ADC_GetResult() instead to reduce overhead. + * + * \param[in] MUXMask Mask comprising of an ADC channel mask, reference mask and adjustment mask. + */ + static inline uint16_t ADC_GetChannelReading(const uint16_t MUXMask) ATTR_WARN_UNUSED_RESULT; + static inline uint16_t ADC_GetChannelReading(const uint16_t MUXMask) + { + ADC_StartReading(MUXMask); + + while (!(ADC_IsReadingComplete())); + + return ADC_GetResult(); + } + + /** Initialises the ADC, ready for conversions. This must be called before any other ADC operations. + * The "mode" parameter should be a mask comprised of a conversion mode (free running or single) and + * prescaler masks. + * + * \param[in] Mode Mask of ADC prescale and mode settings. + */ + static inline void ADC_Init(uint8_t Mode) ATTR_ALWAYS_INLINE; + static inline void ADC_Init(uint8_t Mode) + { + ADCSRA = ((1 << ADEN) | Mode); + } + + /** Turns off the ADC. If this is called, any further ADC operations will require a call to + * \ref ADC_Init() before the ADC can be used again. + */ + static inline void ADC_ShutDown(void) ATTR_ALWAYS_INLINE; + static inline void ADC_ShutDown(void) + { + ADCSRA = 0; + } + + /** Indicates if the ADC is currently enabled. + * + * \return Boolean true if the ADC subsystem is currently enabled, false otherwise. + */ + static inline bool ADC_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool ADC_GetStatus(void) + { + return ((ADCSRA & (1 << ADEN)) ? true : false); + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Peripheral/AVRU4U6U7/TWI.h b/LUFA/Drivers/Peripheral/AVRU4U6U7/TWI.h new file mode 100644 index 0000000..a797990 --- /dev/null +++ b/LUFA/Drivers/Peripheral/AVRU4U6U7/TWI.h @@ -0,0 +1,155 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief TWI peripheral driver for the U7, U6 and U4 USB AVRs. + * + * Master mode TWI driver for the AT90USB1287, AT90USB1286, AT90USB647, AT90USB646, ATMEGA16U4 and ATMEGA32U4 AVRs. + * + * \note This file should not be included directly. It is automatically included as needed by the TWI driver + * dispatch header located in LUFA/Drivers/Peripheral/TWI.h. + */ + +/** \ingroup Group_TWI + * @defgroup Group_TWI_AVRU4U6U7 Series U4, U6 and U7 Model TWI Driver + * + * Master mode TWI driver for the AT90USB1287, AT90USB1286, AT90USB647, AT90USB646, ATMEGA16U4 and ATMEGA32U4 AVRs. + * + * \note This file should not be included directly. It is automatically included as needed by the TWI driver + * dispatch header located in LUFA/Drivers/Peripheral/TWI.h. + * + * @{ + */ + +#ifndef __TWI_AVRU4U6U7_H__ +#define __TWI_AVRU4U6U7_H__ + + /* Includes: */ + #include "../../../Common/Common.h" + + #include + #include + #include + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_TWI_H) + #error Do not include this file directly. Include LUFA/Drivers/Peripheral/TWI.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Inline Functions: */ + /** Initialises the TWI hardware into master mode, ready for data transmission and reception. This must be + * before any other TWI operations. + */ + static inline void TWI_Init(void) ATTR_ALWAYS_INLINE; + static inline void TWI_Init(void) + { + TWCR |= (1 << TWEN); + } + + /** Turns off the TWI driver hardware. If this is called, any further TWI operations will require a call to + * \ref TWI_Init() before the TWI can be used again. + */ + static inline void TWI_ShutDown(void) ATTR_ALWAYS_INLINE; + static inline void TWI_ShutDown(void) + { + TWCR &= ~(1 << TWEN); + } + + /** Sends a TWI STOP onto the TWI bus, terminating communication with the currently addressed device. */ + static inline void TWI_StopTransmission(void) ATTR_ALWAYS_INLINE; + static inline void TWI_StopTransmission(void) + { + TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN)); + } + + /** Sends a byte to the currently addressed device on the TWI bus. + * + * \param[in] Byte Byte to send to the currently addressed device + * + * \return Boolean true if the recipient ACKed the byte, false otherwise + */ + static inline bool TWI_SendByte(const uint8_t Byte) + { + TWDR = Byte; + TWCR = ((1 << TWINT) | (1 << TWEN)); + while (!(TWCR & (1 << TWINT))); + + return ((TWSR & TW_STATUS_MASK) == TW_MT_DATA_ACK); + } + + /** Receives a byte from the currently addressed device on the TWI bus. + * + * \param[in] Byte Location where the read byte is to be stored + * \param[in] LastByte Indicates if the byte should be ACKed if false, NAKed if true + * + * \return Boolean true if the byte reception successfully completed, false otherwise + */ + static inline bool TWI_ReceiveByte(uint8_t* const Byte, + const bool LastByte) + { + uint8_t TWCRMask = ((1 << TWINT) | (1 << TWEN)); + + if (!(LastByte)) + TWCRMask |= (1 << TWEA); + + TWCR = TWCRMask; + while (!(TWCR & (1 << TWINT))); + *Byte = TWDR; + + return ((TWSR & TW_STATUS_MASK) == TW_MR_DATA_ACK); + } + + /* Function Prototypes: */ + /** Begins a master mode TWI bus communication with the given slave device address. + * + * \param[in] SlaveAddress Address of the slave TWI device to communicate with + * \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds + * + * \return Boolean true if the device is ready for data, false otherwise + */ + bool TWI_StartTransmission(const uint8_t SlaveAddress, + const uint8_t TimeoutMS); + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Peripheral/SPI.h b/LUFA/Drivers/Peripheral/SPI.h new file mode 100644 index 0000000..957325e --- /dev/null +++ b/LUFA/Drivers/Peripheral/SPI.h @@ -0,0 +1,208 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the SPI peripheral driver. + * + * Hardware SPI subsystem driver for the supported USB AVRs models. + */ + +/** \ingroup Group_PeripheralDrivers + * @defgroup Group_SPI SPI Driver - LUFA/Drivers/Peripheral/SPI.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Module Description + * Driver for the hardware SPI port available on most AVR models. This module provides + * an easy to use driver for the setup of and transfer of data over the AVR's SPI port. + * + * @{ + */ + +#ifndef __SPI_H__ +#define __SPI_H__ + + /* Includes: */ + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define SPI_USE_DOUBLESPEED (1 << SPE) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name SPI Prescaler Configuration Masks */ + //@{ + /** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 2. */ + #define SPI_SPEED_FCPU_DIV_2 SPI_USE_DOUBLESPEED + + /** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 4. */ + #define SPI_SPEED_FCPU_DIV_4 0 + + /** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 8. */ + #define SPI_SPEED_FCPU_DIV_8 (SPI_USE_DOUBLESPEED | (1 << SPR0)) + + /** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 16. */ + #define SPI_SPEED_FCPU_DIV_16 (1 << SPR0) + + /** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 32. */ + #define SPI_SPEED_FCPU_DIV_32 (SPI_USE_DOUBLESPEED | (1 << SPR1)) + + /** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 64. */ + #define SPI_SPEED_FCPU_DIV_64 (SPI_USE_DOUBLESPEED | (1 << SPR1) | (1 << SPR0)) + + /** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 128. */ + #define SPI_SPEED_FCPU_DIV_128 ((1 << SPR1) | (1 << SPR0)) + //@} + + /** \name SPI SCK Polarity Configuration Masks */ + //@{ + /** SPI clock polarity mask for SPI_Init(). Indicates that the SCK should lead on the rising edge. */ + #define SPI_SCK_LEAD_RISING (0 << CPOL) + + /** SPI clock polarity mask for SPI_Init(). Indicates that the SCK should lead on the falling edge. */ + #define SPI_SCK_LEAD_FALLING (1 << CPOL) + //@} + + /** \name SPI Sample Edge Configuration Masks */ + //@{ + /** SPI data sample mode mask for SPI_Init(). Indicates that the data should sampled on the leading edge. */ + #define SPI_SAMPLE_LEADING (0 << CPHA) + + /** SPI data sample mode mask for SPI_Init(). Indicates that the data should be sampled on the trailing edge. */ + #define SPI_SAMPLE_TRAILING (1 << CPHA) + //@} + + /** \name SPI Data Ordering Configuration Masks */ + //@{ + /** SPI data order mask for SPI_Init(). Indicates that data should be shifted out MSB first. */ + #define SPI_ORDER_MSB_FIRST (0 << DORD) + + /** SPI data order mask for SPI_Init(). Indicates that data should be shifted out MSB first. */ + #define SPI_ORDER_LSB_FIRST (1 << DORD) + //@} + + /** \name SPI Mode Configuration Masks */ + //@{ + /** SPI mode mask for SPI_Init(). Indicates that the SPI interface should be initialized into slave mode. */ + #define SPI_MODE_SLAVE (0 << MSTR) + + /** SPI mode mask for SPI_Init(). Indicates that the SPI interface should be initialized into master mode. */ + #define SPI_MODE_MASTER (1 << MSTR) + //@} + + /* Inline Functions: */ + /** Initialises the SPI subsystem, ready for transfers. Must be called before calling any other + * SPI routines. + * + * \param[in] SPIOptions SPI Options, a mask consisting of one of each of the SPI_SPEED_*, + * SPI_SCK_*, SPI_SAMPLE_*, SPI_ORDER_* and SPI_MODE_* masks. + */ + static inline void SPI_Init(const uint8_t SPIOptions) + { + DDRB |= ((1 << 1) | (1 << 2)); + DDRB &= ~((1 << 0) | (1 << 3)); + PORTB |= ((1 << 0) | (1 << 3)); + + SPCR = ((1 << SPE) | SPIOptions); + + if (SPIOptions & SPI_USE_DOUBLESPEED) + SPSR |= (1 << SPI2X); + else + SPSR &= ~(1 << SPI2X); + } + + /** Turns off the SPI driver, disabling and returning used hardware to their default configuration. */ + static inline void SPI_ShutDown(void) + { + DDRB &= ~((1 << 1) | (1 << 2)); + PORTB &= ~((1 << 0) | (1 << 3)); + + SPCR = 0; + SPSR = 0; + } + + /** Sends and receives a byte through the SPI interface, blocking until the transfer is complete. + * + * \param[in] Byte Byte to send through the SPI interface. + * + * \return Response byte from the attached SPI device. + */ + static inline uint8_t SPI_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; + static inline uint8_t SPI_TransferByte(const uint8_t Byte) + { + SPDR = Byte; + while (!(SPSR & (1 << SPIF))); + return SPDR; + } + + /** Sends a byte through the SPI interface, blocking until the transfer is complete. The response + * byte sent to from the attached SPI device is ignored. + * + * \param[in] Byte Byte to send through the SPI interface. + */ + static inline void SPI_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; + static inline void SPI_SendByte(const uint8_t Byte) + { + SPDR = Byte; + while (!(SPSR & (1 << SPIF))); + } + + /** Sends a dummy byte through the SPI interface, blocking until the transfer is complete. The response + * byte from the attached SPI device is returned. + * + * \return The response byte from the attached SPI device. + */ + static inline uint8_t SPI_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; + static inline uint8_t SPI_ReceiveByte(void) + { + SPDR = 0x00; + while (!(SPSR & (1 << SPIF))); + return SPDR; + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Peripheral/Serial.c b/LUFA/Drivers/Peripheral/Serial.c new file mode 100644 index 0000000..fe41b20 --- /dev/null +++ b/LUFA/Drivers/Peripheral/Serial.c @@ -0,0 +1,54 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include "Serial.h" + +void Serial_TxString_P(const char* FlashStringPtr) +{ + uint8_t CurrByte; + + while ((CurrByte = pgm_read_byte(FlashStringPtr)) != 0x00) + { + Serial_TxByte(CurrByte); + FlashStringPtr++; + } +} + +void Serial_TxString(const char* StringPtr) +{ + uint8_t CurrByte; + + while ((CurrByte = *StringPtr) != 0x00) + { + Serial_TxByte(CurrByte); + StringPtr++; + } +} + diff --git a/LUFA/Drivers/Peripheral/Serial.h b/LUFA/Drivers/Peripheral/Serial.h new file mode 100644 index 0000000..9f42df6 --- /dev/null +++ b/LUFA/Drivers/Peripheral/Serial.h @@ -0,0 +1,167 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the USART peripheral driver. + * + * Driver for the USART subsystem on supported USB AVRs. + */ + +/** \ingroup Group_PeripheralDrivers + * @defgroup Group_Serial Serial USART Driver - LUFA/Drivers/Peripheral/Serial.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/Peripheral/Serial.c (Makefile source module name: LUFA_SRC_SERIAL) + * + * \section Module Description + * Hardware serial USART driver. This module provides an easy to use driver for + * the setup of and transfer of data over the AVR's USART port. + * + * @{ + */ + +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + + /* Includes: */ + #include + #include + #include + + #include "../../Common/Common.h" + #include "../Misc/TerminalCodes.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Macro for calculating the baud value from a given baud rate when the U2X (double speed) bit is + * not set. + */ + #define SERIAL_UBBRVAL(baud) ((((F_CPU / 16) + (baud / 2)) / (baud)) - 1) + + /** Macro for calculating the baud value from a given baud rate when the U2X (double speed) bit is + * set. + */ + #define SERIAL_2X_UBBRVAL(baud) ((((F_CPU / 8) + (baud / 2)) / (baud)) - 1) + + /* Function Prototypes: */ + /** Transmits a given string located in program space (FLASH) through the USART. + * + * \param[in] FlashStringPtr Pointer to a string located in program space. + */ + void Serial_TxString_P(const char* FlashStringPtr) ATTR_NON_NULL_PTR_ARG(1); + + /** Transmits a given string located in SRAM memory through the USART. + * + * \param[in] StringPtr Pointer to a string located in SRAM space. + */ + void Serial_TxString(const char* StringPtr) ATTR_NON_NULL_PTR_ARG(1); + + /* Inline Functions: */ + /** Initializes the USART, ready for serial data transmission and reception. This initializes the interface to + * standard 8-bit, no parity, 1 stop bit settings suitable for most applications. + * + * \param[in] BaudRate Serial baud rate, in bits per second. + * \param[in] DoubleSpeed Enables double speed mode when set, halving the sample time to double the baud rate. + */ + static inline void Serial_Init(const uint32_t BaudRate, + const bool DoubleSpeed) + { + UBRR1 = (DoubleSpeed ? SERIAL_2X_UBBRVAL(BaudRate) : SERIAL_UBBRVAL(BaudRate)); + + UCSR1C = ((1 << UCSZ11) | (1 << UCSZ10)); + UCSR1A = (DoubleSpeed ? (1 << U2X1) : 0); + UCSR1B = ((1 << TXEN1) | (1 << RXEN1)); + + DDRD |= (1 << 3); + PORTD |= (1 << 2); + } + + /** Turns off the USART driver, disabling and returning used hardware to their default configuration. */ + static inline void Serial_ShutDown(void) + { + UCSR1B = 0; + UCSR1A = 0; + UCSR1C = 0; + + UBRR1 = 0; + + DDRD &= ~(1 << 3); + PORTD &= ~(1 << 2); + } + + /** Indicates whether a character has been received through the USART. + * + * \return Boolean true if a character has been received, false otherwise. + */ + static inline bool Serial_IsCharReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Serial_IsCharReceived(void) + { + return ((UCSR1A & (1 << RXC1)) ? true : false); + } + + /** Transmits a given byte through the USART. + * + * \param[in] DataByte Byte to transmit through the USART. + */ + static inline void Serial_TxByte(const char DataByte) ATTR_ALWAYS_INLINE; + static inline void Serial_TxByte(const char DataByte) + { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = DataByte; + } + + /** Receives a byte from the USART. This function blocks until a byte has been + * received; if non-blocking behaviour is required, test for a received character + * beforehand with \ref Serial_IsCharReceived(). + * + * \return Byte received from the USART. + */ + static inline char Serial_RxByte(void) ATTR_ALWAYS_INLINE; + static inline char Serial_RxByte(void) + { + while (!(UCSR1A & (1 << RXC1))); + return UDR1; + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Peripheral/SerialStream.c b/LUFA/Drivers/Peripheral/SerialStream.c new file mode 100644 index 0000000..30aa5a4 --- /dev/null +++ b/LUFA/Drivers/Peripheral/SerialStream.c @@ -0,0 +1,54 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_SERIALSTREAM_C +#include "SerialStream.h" + +FILE USARTStream = FDEV_SETUP_STREAM(SerialStream_TxByte, SerialStream_RxByte, _FDEV_SETUP_RW); + +static int SerialStream_TxByte(char DataByte, + FILE *Stream) +{ + (void)Stream; + + Serial_TxByte(DataByte); + return 0; +} + +static int SerialStream_RxByte(FILE *Stream) +{ + (void)Stream; + + if (!(Serial_IsCharReceived())) + return _FDEV_EOF; + + return Serial_RxByte(); +} + diff --git a/LUFA/Drivers/Peripheral/SerialStream.h b/LUFA/Drivers/Peripheral/SerialStream.h new file mode 100644 index 0000000..3e37667 --- /dev/null +++ b/LUFA/Drivers/Peripheral/SerialStream.h @@ -0,0 +1,116 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Standard avr-libc character stream driver for the USART. + * + * Serial stream driver for the USART subsystem on supported USB AVRs. This makes use of the functions in the + * regular USART driver (see \ref Group_Serial), but allows the avr-libc standard stream functions (printf, + * puts, etc.) to work with the + * USART. + */ + +/** \ingroup Group_PeripheralDrivers + * @defgroup Group_SerialStream Serial Stream Driver - LUFA/Drivers/Peripheral/SerialStream.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/Peripheral/SerialStream.c (Makefile source module name: LUFA_SRC_SERIALSTREAM) + * + * \section Module Description + * Serial stream driver for the USART subsystem on supported USB AVRs. This makes use of the functions in the + * regular USART driver (see \ref Group_Serial), but allows the avr-libc standard stream functions (printf, + * puts, etc.) to work with the + * USART. + * + * @{ + */ + +#ifndef __SERIAL_STREAM_H__ +#define __SERIAL_STREAM_H__ + + /* Includes: */ + #include + #include + + #include "Serial.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* External Variables: */ + extern FILE USARTStream; + + /* Function Prototypes: */ + #if defined(__INCLUDE_FROM_SERIALSTREAM_C) + static int SerialStream_TxByte(char DataByte, + FILE *Stream) ATTR_NON_NULL_PTR_ARG(2); + static int SerialStream_RxByte(FILE *Stream) ATTR_NON_NULL_PTR_ARG(1); + #endif + #endif + + /* Public Interface - May be used in end-application: */ + /* Inline Functions: */ + /** Initialises the serial stream (and regular USART driver) so that both the stream and regular + * USART driver functions can be used. Must be called before any stream or regular USART functions. + * + * \param[in] BaudRate Baud rate to configure the USART to. + * \param[in] DoubleSpeed Enables double speed mode when set, halving the sample time to double the baud rate. + */ + static inline void SerialStream_Init(const uint32_t BaudRate, + const bool DoubleSpeed) + { + Serial_Init(BaudRate, DoubleSpeed); + + stdout = &USARTStream; + stdin = &USARTStream; + } + + /** Turns off the serial stream (and regular USART driver), disabling and returning used hardware to + * their default configuration. + */ + static inline void SerialStream_ShutDown(void) + { + Serial_ShutDown(); + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Peripheral/TWI.c b/LUFA/Drivers/Peripheral/TWI.c new file mode 100644 index 0000000..4694b0b --- /dev/null +++ b/LUFA/Drivers/Peripheral/TWI.c @@ -0,0 +1,75 @@ +/* + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +#include "TWI.h" + +bool TWI_StartTransmission(const uint8_t SlaveAddress, + const uint8_t TimeoutMS) +{ + for (;;) + { + bool BusCaptured = false; + uint16_t TimeoutRemaining; + + TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN)); + + TimeoutRemaining = (TimeoutMS * 100); + while (TimeoutRemaining-- && !(BusCaptured)) + { + if (TWCR & (1 << TWINT)) + { + switch (TWSR & TW_STATUS_MASK) + { + case TW_START: + case TW_REP_START: + BusCaptured = true; + break; + case TW_MT_ARB_LOST: + TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN)); + continue; + default: + TWCR = (1 << TWEN); + return false; + } + } + + _delay_us(10); + } + + if (!(BusCaptured)) + { + TWCR = (1 << TWEN); + return false; + } + + TWDR = SlaveAddress; + TWCR = ((1 << TWINT) | (1 << TWEN)); + + TimeoutRemaining = (TimeoutMS * 100); + while (TimeoutRemaining--) + { + if (TWCR & (1 << TWINT)) + break; + + _delay_us(10); + } + + if (!(TimeoutRemaining)) + return false; + + switch (TWSR & TW_STATUS_MASK) + { + case TW_MT_SLA_ACK: + case TW_MR_SLA_ACK: + return true; + default: + TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN)); + return false; + } + } +} + diff --git a/LUFA/Drivers/Peripheral/TWI.h b/LUFA/Drivers/Peripheral/TWI.h new file mode 100644 index 0000000..ae918c3 --- /dev/null +++ b/LUFA/Drivers/Peripheral/TWI.h @@ -0,0 +1,72 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the TWI peripheral driver. + * + * This file is the master dispatch header file for the device-specific ADC driver, for AVRs containing an ADC. + * + * User code should include this file, which will in turn include the correct ADC driver header file for the + * currently selected AVR model. + */ + +/** \ingroup Group_PeripheralDrivers + * @defgroup Group_TWI TWI Driver - LUFA/Drivers/Peripheral/TWI.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/Peripheral/TWI.c (Makefile source module name: LUFA_SRC_TWI) + * + * + * \section Module Description + * Master Mode Hardware TWI driver. This module provides an easy to use driver for the hardware + * TWI present on many AVR models, for the transmission and reception of data on a TWI bus. + */ + +#ifndef __TWI_H__ +#define __TWI_H__ + + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __INCLUDE_FROM_TWI_H + #endif + + /* Includes: */ + #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \ + defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \ + defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || \ + defined(__AVR_ATmega32U6__)) + #include "AVRU4U6U7/TWI.h" + #else + #error "TWI is not available for the currently selected AVR model." + #endif + +#endif + diff --git a/LUFA/Drivers/USB/Class/Audio.h b/LUFA/Drivers/USB/Class/Audio.h new file mode 100644 index 0000000..70ababe --- /dev/null +++ b/LUFA/Drivers/USB/Class/Audio.h @@ -0,0 +1,75 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the library USB Audio Class driver. + * + * Master include file for the library USB Audio 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 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) + * + * \section Module Description + * Audio Class Driver module. This module contains an internal implementation of the USB Audio 1.0 Class, for Device + * USB mode only. User applications can use this class driver instead of implementing the Audio 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 Class. + * + * @{ + */ + +#ifndef _AUDIO_CLASS_H_ +#define _AUDIO_CLASS_H_ + + /* Macros: */ + #define __INCLUDE_FROM_USB_DRIVER + #define __INCLUDE_FROM_AUDIO_DRIVER + + /* Includes: */ + #include "../HighLevel/USBMode.h" + + #if defined(USB_CAN_BE_DEVICE) + #include "Device/Audio.h" + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/CDC.h b/LUFA/Drivers/USB/Class/CDC.h new file mode 100644 index 0000000..d8b7b58 --- /dev/null +++ b/LUFA/Drivers/USB/Class/CDC.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../HighLevel/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/Common/Audio.h b/LUFA/Drivers/USB/Class/Common/Audio.h new file mode 100644 index 0000000..a635947 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/Audio.h @@ -0,0 +1,701 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.h" + + #include + + /* 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: */ + #if !defined(AUDIO_TOTAL_SAMPLE_RATES) || defined(__DOXYGEN__) + /** Total number of discrete audio sample rates supported by the device. This value can be overridden by defining this + * token in the project makefile to the desired value, and passing it to the compiler via the -D switch. + */ + #define AUDIO_TOTAL_SAMPLE_RATES 1 + #endif + + /** \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) {((uint32_t)freq & 0x00FFFF), (((uint32_t)freq >> 16) & 0x0000FF)} + + /** 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) + + /* 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. */ + }; + + /* 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. + */ + 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 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; /**< 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. */ + } 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. + */ + 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 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; /**< 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. */ + } 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. + */ + 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 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. */ + } 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. + */ + 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 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. */ + } 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. + */ + 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. */ + } 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. + */ + 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. */ + } 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. + */ + 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 ChanelControlls 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. */ + } 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. + */ + 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 ChanelControlls 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. */ + } 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. + */ + 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. */ + } 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. + */ + 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. */ + } USB_Audio_StdDescriptor_Interface_AS_t; + + /** \brief 24-Bit Audio Frequency Structure. + * + * Type define for a 24bit audio sample frequency structure. GCC does not contain a built in 24bit datatype, + * this this structure is used to build up the value instead. Fill this structure with the \ref AUDIO_SAMPLE_FREQ() macro. + */ + typedef struct + { + uint16_t LowWord; /**< Low 16 bits of the 24-bit value. */ + uint8_t HighByte; /**< Upper 8 bits of the 24-bit value. */ + } USB_Audio_SampleFreq_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. + * + * \see \ref USB_Audio_StdDescriptor_Format_t for the version of this type with standard element names. + */ + 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 SampleFrequencyType; /**< Total number of sample frequencies supported by the device. */ + USB_Audio_SampleFreq_t SampleFrequencies[AUDIO_TOTAL_SAMPLE_RATES]; /**< Sample frequencies supported by the device (must be 24-bit). */ + } USB_Audio_Descriptor_Format_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. + * + * \see \ref USB_Audio_Descriptor_Format_t for the version of this type with non-standard LUFA specific + * element names. + */ + 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. */ + uint8_t SampleFrequencies[AUDIO_TOTAL_SAMPLE_RATES * 3]; /**< Sample frequencies supported by the device (must be 24-bit). */ + } 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. + */ + 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). */ + } 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. + */ + 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 (EP_TYPE_*) + * and attributes (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). */ + } 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. + */ + 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 ACCEPTS_SMALL_PACKETS. */ + + 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. */ + } 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. + */ + 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 ACCEPTS_SMALL_PACKETS. */ + + 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. */ + } 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 new file mode 100644 index 0000000..dabe438 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/CDC.h @@ -0,0 +1,372 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.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 + + /* 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 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 Class value indicating that the device or interface + * belongs to no specific protocol of the CDC class. + */ + CDC_CSCP_VendorSpecificProtocol = 0xFF, /**< Descriptor Class 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 Managment 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. + */ + 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. + */ + } 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. + */ + 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. */ + } 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. + */ + 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 capabiltiies, refer + * to the CDC ACM specification. + */ + } 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. + */ + 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 capabiltiies, refer + * to the CDC ACM specification. + */ + } 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. + */ + 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. */ + } 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. + */ + 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. */ + } USB_CDC_StdDescriptor_FunctionalUnion_t; + + /** Type define for a CDC Line Encoding structure, used to hold the various encoding parameters for a virtual + * serial port. + */ + 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. */ + } 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 new file mode 100644 index 0000000..ca2212e --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/HID.h @@ -0,0 +1,451 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.h" + + #include + + /* 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_MODIFER_LEFTCTRL (1 << 0) + + /** Constant for a keyboard report modifier byte, indicating that the keyboard's left shift key is currently pressed. */ + #define HID_KEYBOARD_MODIFER_LEFTSHIFT (1 << 1) + + /** Constant for a keyboard report modifier byte, indicating that the keyboard's left alt key is currently pressed. */ + #define HID_KEYBOARD_MODIFER_LEFTALT (1 << 2) + + /** Constant for a keyboard report modifier byte, indicating that the keyboard's left GUI key is currently pressed. */ + #define HID_KEYBOARD_MODIFER_LEFTGUI (1 << 3) + + /** Constant for a keyboard report modifier byte, indicating that the keyboard's right control key is currently pressed. */ + #define HID_KEYBOARD_MODIFER_RIGHTCTRL (1 << 4) + + /** Constant for a keyboard report modifier byte, indicating that the keyboard's right shift key is currently pressed. */ + #define HID_KEYBOARD_MODIFER_RIGHTSHIFT (1 << 5) + + /** Constant for a keyboard report modifier byte, indicating that the keyboard's right alt key is currently pressed. */ + #define HID_KEYBOARD_MODIFER_RIGHTALT (1 << 6) + + /** Constant for a keyboard report modifier byte, indicating that the keyboard's right GUI key is currently pressed. */ + #define HID_KEYBOARD_MODIFER_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 Scancodes */ + //@{ + #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 0x04 + #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 0xEF + #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_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 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 + //@} + + /* 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. + */ + 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. */ + } 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. + */ + 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. */ + } 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. */ + } 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 + * 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. */ + } 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; + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Common/MIDI.h b/LUFA/Drivers/USB/Class/Common/MIDI.h new file mode 100644 index 0000000..4a3be81 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/MIDI.h @@ -0,0 +1,293 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.h" + #include "Audio.h" + + #include + + /* 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. + */ + 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. */ + } 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. + */ + 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. */ + } 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. + */ + 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 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. */ + } 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. + */ + 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 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. */ + } 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. + */ + 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 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. */ + } 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. + */ + 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 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. */ + } 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. + */ + 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. */ + } 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. + */ + 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. */ + } 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. + */ + typedef struct + { + unsigned char Command : 4; /**< Upper nibble of the MIDI command being sent or received in the event packet. */ + unsigned char 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. */ + } 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 new file mode 100644 index 0000000..fd24056 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/MassStorage.h @@ -0,0 +1,362 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.h" + + #include + + /* 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 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. */ + typedef struct + { + uint32_t Signature; /**< Command block signature, must be 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. */ + } 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. + */ + typedef struct + { + uint32_t Signature; /**< Status block signature, must be 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. */ + } 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 char SenseKey : 4; + unsigned char Reserved : 1; + unsigned char ILI : 1; + unsigned char EOM : 1; + unsigned char 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]; + } 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 char DeviceType : 5; + unsigned char PeripheralQualifier : 3; + + unsigned char Reserved : 7; + unsigned char Removable : 1; + + uint8_t Version; + + unsigned char ResponseDataFormat : 4; + unsigned char Reserved2 : 1; + unsigned char NormACA : 1; + unsigned char TrmTsk : 1; + unsigned char AERC : 1; + + uint8_t AdditionalLength; + uint8_t Reserved3[2]; + + unsigned char SoftReset : 1; + unsigned char CmdQue : 1; + unsigned char Reserved4 : 1; + unsigned char Linked : 1; + unsigned char Sync : 1; + unsigned char WideBus16Bit : 1; + unsigned char WideBus32Bit : 1; + unsigned char RelAddr : 1; + + uint8_t VendorID[8]; + uint8_t ProductID[16]; + uint8_t RevisionID[4]; + } 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 new file mode 100644 index 0000000..47a7909 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/Printer.h @@ -0,0 +1,121 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.h" + + #include + + /* 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 new file mode 100644 index 0000000..b4fb114 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/RNDIS.h @@ -0,0 +1,399 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.h" + #include "CDC.h" + + #include + + /* 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: */ + /** 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 + //@} + + #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 */ + } MAC_Address_t; + + /** \brief RNDIS Ethernet Frame Packet Information Structure. + * + * Type define for an Ethernet frame buffer data and information structure. + */ + typedef struct + { + uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents. */ + uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer. */ + bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer. */ + } Ethernet_Frame_Info_t; + + /** \brief RNDIS Common Message Header Structure. + * + * Type define for a RNDIS message header, sent before RNDIS messages. + */ + typedef struct + { + uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */ + uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */ + } 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. + */ + 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; + } RNDIS_Packet_Message_t; + + /** \brief RNDIS Initialization Message Structure. + * + * Type define for a RNDIS Initialize command message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + + uint32_t MajorVersion; + uint32_t MinorVersion; + uint32_t MaxTransferSize; + } RNDIS_Initialize_Message_t; + + /** \brief RNDIS Initialize Complete Message Structure. + * + * Type define for a RNDIS Initialize Complete response message. + */ + 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; + } RNDIS_Initialize_Complete_t; + + /** \brief RNDIS Keep Alive Message Structure. + * + * Type define for a RNDIS Keep Alive command message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + } RNDIS_KeepAlive_Message_t; + + /** \brief RNDIS Keep Alive Complete Message Structure. + * + * Type define for a RNDIS Keep Alive Complete response message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + uint32_t Status; + } RNDIS_KeepAlive_Complete_t; + + /** \brief RNDIS Reset Complete Message Structure. + * + * Type define for a RNDIS Reset Complete response message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t Status; + + uint32_t AddressingReset; + } RNDIS_Reset_Complete_t; + + /** \brief RNDIS OID Property Set Message Structure. + * + * Type define for a RNDIS OID Property Set command message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + + uint32_t Oid; + uint32_t InformationBufferLength; + uint32_t InformationBufferOffset; + uint32_t DeviceVcHandle; + } RNDIS_Set_Message_t; + + /** \brief RNDIS OID Property Set Complete Message Structure. + * + * Type define for a RNDIS OID Property Set Complete response message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + uint32_t Status; + } RNDIS_Set_Complete_t; + + /** \brief RNDIS OID Property Query Message Structure. + * + * Type define for a RNDIS OID Property Query command message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + + uint32_t Oid; + uint32_t InformationBufferLength; + uint32_t InformationBufferOffset; + uint32_t DeviceVcHandle; + } RNDIS_Query_Message_t; + + /** \brief RNDIS OID Property Query Complete Message Structure. + * + * Type define for a RNDIS OID Property Query Complete response message. + */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + uint32_t Status; + + uint32_t InformationBufferLength; + uint32_t InformationBufferOffset; + } 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 new file mode 100644 index 0000000..6347d59 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Common/StillImage.h @@ -0,0 +1,161 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../../HighLevel/StdDescriptors.h" + + #include + + /* 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 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. + */ + 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). */ + } 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 new file mode 100644 index 0000000..cc847e5 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/Audio.c @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_DEVICE) + +#define __INCLUDE_FROM_AUDIO_DRIVER +#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.wIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber) + 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); + } + + 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; + + if (EndpointNum == AudioInterfaceInfo->Config.DataINEndpointNumber) + { + Size = AudioInterfaceInfo->Config.DataINEndpointSize; + Direction = ENDPOINT_DIR_IN; + Type = EP_TYPE_ISOCHRONOUS; + } + else if (EndpointNum == AudioInterfaceInfo->Config.DataOUTEndpointNumber) + { + Size = AudioInterfaceInfo->Config.DataOUTEndpointSize; + Direction = ENDPOINT_DIR_OUT; + Type = EP_TYPE_ISOCHRONOUS; + } + else + { + continue; + } + + if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size, ENDPOINT_BANK_DOUBLE))) + { + return false; + } + } + + return true; +} + +#endif diff --git a/LUFA/Drivers/USB/Class/Device/Audio.h b/LUFA/Drivers/USB/Class/Device/Audio.h new file mode 100644 index 0000000..5ba688a --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/Audio.h @@ -0,0 +1,336 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB Audio 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 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 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" + + #include + + /* 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 + + #if defined(__INCLUDE_FROM_AUDIO_DEVICE_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #endif + + /* Public Interface - May be used in end-application: */ + /* Type Defines: */ + /** \brief Audio Class Device Mode Configuration and State Structure. + * + * Class state structure. An instance of this structure should be made for each Audio interface + * within the user application, and passed to each of the Audio class driver functions as the + * AudioInterfaceInfo parameter. This stores each Audio interface's configuration and state information. + */ + typedef struct + { + const struct + { + uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this + * structure controls. + */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming Audio Streaming data, if available + * (zero if unused). + */ + uint16_t DataINEndpointSize; /**< Size in bytes of the incoming Audio Streaming data endpoint, if available + * (zero if unused). + */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing Audio Streaming data, if available + * (zero if unused). + */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing Audio Streaming data endpoint, if available + * (zero if unused). + */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * 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. + * + * \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes. + * + * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. + * + * \return Boolean true if the endpoints were successfully configured, false otherwise. + */ + bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /** Processes incoming control requests from the host, that are directed to the given Audio class interface. This should be + * linked to the library \ref EVENT_USB_Device_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); + + /* 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 true if the given Audio interface has a sample to be read, false otherwise. + */ + static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) + 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 true if the given Audio interface is ready to accept the next sample, false otherwise. + */ + static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) + 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 + * ensure 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_Byte(); + + 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_Word_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_Byte() << 16) | Endpoint_Read_Word_LE()); + + if (!(Endpoint_BytesInEndpoint())) + Endpoint_ClearOUT(); + + return Sample; + } + + /** Writes the next 8-bit audio sample to the current audio interface. + * + * \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_Byte(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_Word_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_Byte(Sample >> 16); + Endpoint_Write_Word_LE(Sample); + + if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpointSize) + Endpoint_ClearIN(); + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c new file mode 100644 index 0000000..0da5cc6 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/CDC.c @@ -0,0 +1,332 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_DEVICE) + +#define __INCLUDE_FROM_CDC_DRIVER +#define __INCLUDE_FROM_CDC_DEVICE_C +#include "CDC.h" + +void CDC_Device_Event_Stub(void) +{ + +} + +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(); + Endpoint_Write_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding)); + Endpoint_ClearOUT(); + } + + break; + case CDC_REQ_SetLineEncoding: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + Endpoint_Read_Control_Stream_LE(&CDCInterfaceInfo->State.LineEncoding, sizeof(CDCInterfaceInfo->State.LineEncoding)); + Endpoint_ClearIN(); + + 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 Data, + const uint16_t Length) +{ + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) + return ENDPOINT_RWSTREAM_DeviceDisconnected; + + Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); + return Endpoint_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK); +} + +uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, + const uint8_t Data) +{ + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) + return ENDPOINT_RWSTREAM_DeviceDisconnected; + + Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); + + if (!(Endpoint_IsReadWriteAllowed())) + { + Endpoint_ClearIN(); + + uint8_t ErrorCode; + + if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) + return ErrorCode; + } + + Endpoint_Write_Byte(Data); + return ENDPOINT_READYWAIT_NoError; +} + +uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) +{ + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) + return ENDPOINT_RWSTREAM_DeviceDisconnected; + + uint8_t ErrorCode; + + Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber); + + if (!(Endpoint_BytesInEndpoint())) + return ENDPOINT_READYWAIT_NoError; + + bool BankFull = !(Endpoint_IsReadWriteAllowed()); + + Endpoint_ClearIN(); + + if (BankFull) + { + if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) + return ErrorCode; + + Endpoint_ClearIN(); + } + + return ENDPOINT_READYWAIT_NoError; +} + +uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) +{ + if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS)) + return 0; + + Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber); + + if (Endpoint_IsOUTReceived()) + { + if (!(Endpoint_BytesInEndpoint())) + { + Endpoint_ClearOUT(); + return 0; + } + else + { + return Endpoint_BytesInEndpoint(); + } + } + else + { + return 0; + } +} + +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_Byte(); + + 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 = 0, + .wIndex = 0, + .wLength = sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost), + }; + + Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK); + Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost, + sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost), + NO_STREAM_CALLBACK); + Endpoint_ClearIN(); +} + +void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* 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 + diff --git a/LUFA/Drivers/USB/Class/Device/CDC.h b/LUFA/Drivers/USB/Class/Device/CDC.h new file mode 100644 index 0000000..4fa823a --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/CDC.h @@ -0,0 +1,342 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB CDC Class driver. + * + * Device mode driver for the library USB CDC Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the 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 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 + #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 + + #if defined(__INCLUDE_FROM_CDC_DEVICE_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 + { + uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_* + * masks. This value is updated each time \ref CDC_Device_USBTask() is called. + */ + uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of CDC_CONTROL_LINE_IN_* + * masks - to notify the host of changes to these values, call the + * \ref CDC_Device_SendControlLineStateChange() function. + */ + } ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */ + + 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. + * + * \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes. + * + * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. + * + * \return Boolean true if the endpoints were successfully configured, false otherwise. + */ + bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /** Processes incoming control requests from the host, that are directed to the given CDC class interface. This should be + * linked to the library \ref EVENT_USB_Device_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 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 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] Data Pointer to the string to send to the host. + * \param[in] Length Size in bytes of the string to send to the host. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, + const char* const Data, + const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the + * byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the + * \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be + * packed into a single endpoint packet, increasing data throughput. + * + * \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 avr-libc library that accept a FILE stream as a destination (e.g. fprintf). The created + * stream is bidirectional and can be used for both input and output functions. + * + * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single + * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may + * be used when the read data is processed byte-per-bye (via getc()) or when the user application will implement its own + * line buffering. + * + * \note The created stream can be given as stdout if desired to direct the standard output from all functions + * to the given CDC interface. + * + * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. + * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed. + */ + void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, + FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Identical to CDC_Device_CreateStream(), except that reads are blocking until the calling stream function terminates + * the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications. + * + * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. + * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed. + */ + void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* 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) + 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); + + void CDC_Device_Event_Stub(void); + void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) + ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub); + void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) + ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub); + void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, + 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 new file mode 100644 index 0000000..f538610 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/HID.c @@ -0,0 +1,190 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_DEVICE) + +#define __INCLUDE_FROM_HID_DRIVER +#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, ReportSize); + } + + break; + case HID_REQ_GetProtocol: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + Endpoint_Write_Byte(HIDInterfaceInfo->State.UsingReportProtocol); + Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); + } + + break; + case 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(); + Endpoint_Write_Byte(HIDInterfaceInfo->State.IdleCount >> 2); + Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); + } + + break; + } +} + +bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) +{ + memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); + HIDInterfaceInfo->State.UsingReportProtocol = true; + HIDInterfaceInfo->State.IdleCount = 500; + + if (!(Endpoint_ConfigureEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber, EP_TYPE_INTERRUPT, + ENDPOINT_DIR_IN, HIDInterfaceInfo->Config.ReportINEndpointSize, + HIDInterfaceInfo->Config.ReportINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE))) + { + return false; + } + + return true; +} + +void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpointNumber); + + if (Endpoint_IsReadWriteAllowed()) + { + uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize]; + uint8_t ReportID = 0; + uint16_t ReportINSize = 0; + + memset(ReportINData, 0, sizeof(ReportINData)); + + bool ForceSend = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, 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_Byte(ReportID); + + Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NO_STREAM_CALLBACK); + + Endpoint_ClearIN(); + } + } +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Device/HID.h b/LUFA/Drivers/USB/Class/Device/HID.h new file mode 100644 index 0000000..49358f5 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/HID.h @@ -0,0 +1,222 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB HID Class driver. + * + * Device mode driver for the library USB HID Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the 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 Module Description + * Device Mode USB Class driver framework interface, for the HID USB Class driver. + * + * @{ + */ + +#ifndef _HID_CLASS_DEVICE_H_ +#define _HID_CLASS_DEVICE_H_ + + /* Includes: */ + #include "../../USB.h" + #include "../Common/HID.h" + + #include + + /* 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 + + #if defined(__INCLUDE_FROM_HID_DEVICE_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #endif + + + /* Public Interface - May be used in end-application: */ + /* Type Defines: */ + /** \brief HID Class Device Mode Configuration and State Structure. + * + * Class state structure. An instance of this structure should be made for each HID interface + * within the user application, and passed to each of the HID class driver functions as the + * HIDInterfaceInfo parameter. This stores each HID interface's configuration and state information. + * + * \note Due to technical limitations, the HID device class driver does not utilize a separate OUT + * endpoint for host->device communications. Instead, the host->device data (if any) is sent to + * the device via the control endpoint. + */ + typedef struct + { + const struct + { + uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device. */ + + uint8_t ReportINEndpointNumber; /**< Endpoint number of the HID interface's IN report endpoint. */ + uint16_t ReportINEndpointSize; /**< Size in bytes of the HID interface's IN report endpoint. */ + bool ReportINEndpointDoubleBank; /**< Indicates if the HID interface's IN report endpoint should use double banking. */ + + void* PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be + * stored by the driver, for comparison purposes to detect report changes that + * must be sent immediately to the host. This should point to a buffer big enough + * to hold the largest HID input report sent from the HID interface. If this is set + * to NULL, it is up to the user to force transfers when needed in the + * \ref CALLBACK_HID_Device_CreateHIDReport() callback function. + * + * \note Due to the single buffer, the internal driver can only correctly compare + * subsequent reports with identical report IDs. In multiple report devices, + * this buffer should be set to NULL and the decision to send reports made + * by the user application instead. + */ + uint8_t PrevReportINBufferSize; /**< Size in bytes of the given input report buffer. This is used to create a + * second buffer of the same size within the driver so that subsequent reports + * can be compared. If the user app is to determine when reports are to be sent + * exclusively (i.e. \ref PrevReportINBuffer is NULL) this value must still be + * set to the size of the largest report the device can issue to the host. + */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * 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. + * + * \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes. + * + * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. + * + * \return Boolean true if the endpoints were successfully configured, false otherwise. + */ + bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* 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 true to force the sending of the report even if it is identical to the previous report and still within + * the idle period (useful for devices which report relative movement), false otherwise. + */ + bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, + uint8_t* const ReportID, + const uint8_t ReportType, + void* ReportData, + uint16_t* 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 new file mode 100644 index 0000000..9d2a1a8 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MIDI.c @@ -0,0 +1,148 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_DEVICE) + +#define __INCLUDE_FROM_MIDI_DRIVER +#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), NO_STREAM_CALLBACK)) != ENDPOINT_RWSTREAM_NoError) + return ErrorCode; + + if (!(Endpoint_IsReadWriteAllowed())) + Endpoint_ClearIN(); + + return ENDPOINT_RWSTREAM_NoError; +} + +uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return ENDPOINT_RWSTREAM_DeviceDisconnected; + + uint8_t ErrorCode; + + Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber); + + if (Endpoint_BytesInEndpoint()) + { + Endpoint_ClearIN(); + + if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError) + return ErrorCode; + } + + return ENDPOINT_READYWAIT_NoError; +} + +bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, + MIDI_EventPacket_t* const Event) +{ + if (USB_DeviceState != DEVICE_STATE_Configured) + return false; + + Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpointNumber); + + if (!(Endpoint_IsReadWriteAllowed())) + return false; + + Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK); + + if (!(Endpoint_IsReadWriteAllowed())) + Endpoint_ClearOUT(); + + return true; +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Device/MIDI.h b/LUFA/Drivers/USB/Class/Device/MIDI.h new file mode 100644 index 0000000..8ac7146 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MIDI.h @@ -0,0 +1,189 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB MIDI Class driver. + * + * Device mode driver for the library USB MIDI Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the 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 Module Description + * Device Mode USB Class driver framework interface, for the MIDI USB Class driver. + * + * @{ + */ + +#ifndef _MIDI_CLASS_DEVICE_H_ +#define _MIDI_CLASS_DEVICE_H_ + + /* Includes: */ + #include "../../USB.h" + #include "../Common/MIDI.h" + + #include + + /* 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 + + #if defined(__INCLUDE_FROM_MIDI_DEVICE_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #endif + + /* Public Interface - May be used in end-application: */ + /* Type Define: */ + /** \brief MIDI Class Device Mode Configuration and State Structure. + * + * Class state structure. An instance of this structure should be made for each MIDI interface + * within the user application, and passed to each of the MIDI class driver functions as the + * MIDIInterfaceInfo parameter. This stores each MIDI interface's configuration and state information. + */ + typedef struct + { + const struct + { + uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls. */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the incoming MIDI data, if available (zero if unused). */ + uint16_t DataINEndpointSize; /**< Size in bytes of the incoming MIDI data endpoint, if available (zero if unused). */ + bool DataINEndpointDoubleBank; /**< Indicates if the MIDI interface's IN data endpoint should use double banking. */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the outgoing MIDI data, if available (zero if unused). */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the outgoing MIDI data endpoint, if available (zero if unused). */ + bool DataOUTEndpointDoubleBank; /**< Indicates if the MIDI interface's IN data endpoint should use double banking. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * 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. + * + * \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes. + * + * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. + * + * \return Boolean true if the endpoints were successfully configured, false otherwise. + */ + bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /** 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 true if a MIDI event packet was received, false otherwise. + */ + bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, + MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /* Inline Functions: */ + /** 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 new file mode 100644 index 0000000..64d61df --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MassStorage.c @@ -0,0 +1,247 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_DEVICE) + +#define __INCLUDE_FROM_MS_DRIVER +#define __INCLUDE_FROM_MASSSTORAGE_DEVICE_C +#include "MassStorage.h" + +static volatile bool* CallbackIsResetSource; + +void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +{ + if (!(Endpoint_IsSETUPReceived())) + return; + + if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber) + return; + + switch (USB_ControlRequest.bRequest) + { + case 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(); + Endpoint_Write_Byte(MSInterfaceInfo->Config.TotalLUNs - 1); + Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); + } + + break; + } +} + +bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +{ + memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State)); + + 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); + + MSInterfaceInfo->State.CommandStatus.Status = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo) ? + MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail; + MSInterfaceInfo->State.CommandStatus.Signature = MS_CSW_SIGNATURE; + MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag; + MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength; + + if ((MSInterfaceInfo->State.CommandStatus.Status == MS_SCSI_COMMAND_Fail) && + (MSInterfaceInfo->State.CommandStatus.DataTransferResidue)) + { + Endpoint_StallTransaction(); + } + + MS_Device_ReturnCommandStatus(MSInterfaceInfo); + } + } + + if (MSInterfaceInfo->State.IsMassStoreReset) + { + Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataOUTEndpointNumber); + Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataINEndpointNumber); + + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); + Endpoint_ClearStall(); + Endpoint_ResetDataToggle(); + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); + Endpoint_ClearStall(); + Endpoint_ResetDataToggle(); + + MSInterfaceInfo->State.IsMassStoreReset = false; + } +} + +static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +{ + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); + + CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset; + if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock, + (sizeof(MS_CommandBlockWrapper_t) - 16), + StreamCallback_MS_Device_AbortOnMassStoreReset)) + { + return false; + } + + if ((MSInterfaceInfo->State.CommandBlock.Signature != MS_CBW_SIGNATURE) || + (MSInterfaceInfo->State.CommandBlock.LUN >= MSInterfaceInfo->Config.TotalLUNs) || + (MSInterfaceInfo->State.CommandBlock.Flags & 0x1F) || + (MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0) || + (MSInterfaceInfo->State.CommandBlock.SCSICommandLength > 16)) + { + Endpoint_StallTransaction(); + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); + Endpoint_StallTransaction(); + + return false; + } + + CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset; + if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData, + MSInterfaceInfo->State.CommandBlock.SCSICommandLength, + StreamCallback_MS_Device_AbortOnMassStoreReset)) + { + return false; + } + + Endpoint_ClearOUT(); + + return true; +} + +static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +{ + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber); + + while (Endpoint_IsStalled()) + { + #if !defined(INTERRUPT_CONTROL_ENDPOINT) + USB_USBTask(); + #endif + + if (MSInterfaceInfo->State.IsMassStoreReset) + return; + } + + Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber); + + while (Endpoint_IsStalled()) + { + #if !defined(INTERRUPT_CONTROL_ENDPOINT) + USB_USBTask(); + #endif + + if (MSInterfaceInfo->State.IsMassStoreReset) + return; + } + + CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset; + if (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus, sizeof(MS_CommandStatusWrapper_t), + StreamCallback_MS_Device_AbortOnMassStoreReset)) + { + return; + } + + Endpoint_ClearIN(); +} + +static uint8_t StreamCallback_MS_Device_AbortOnMassStoreReset(void) +{ + #if !defined(INTERRUPT_CONTROL_ENDPOINT) + USB_USBTask(); + #endif + + if (*CallbackIsResetSource) + return STREAMCALLBACK_Abort; + else + return STREAMCALLBACK_Continue; +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Device/MassStorage.h b/LUFA/Drivers/USB/Class/Device/MassStorage.h new file mode 100644 index 0000000..31d3ba9 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/MassStorage.h @@ -0,0 +1,177 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB Mass Storage Class driver. + * + * Device mode driver for the library USB Mass Storage Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the 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 Module Description + * Device Mode USB Class driver framework interface, for the Mass Storage USB Class driver. + * + * @{ + */ + +#ifndef _MS_CLASS_DEVICE_H_ +#define _MS_CLASS_DEVICE_H_ + + /* Includes: */ + #include "../../USB.h" + #include "../Common/MassStorage.h" + + #include + + /* 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 + + #if defined(__INCLUDE_FROM_MASSSTORAGE_DEVICE_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #endif + + /* Public Interface - May be used in end-application: */ + /* Type Defines: */ + /** \brief Mass Storage Class Device Mode Configuration and State Structure. + * + * Class state structure. An instance of this structure should be made for each Mass Storage interface + * within the user application, and passed to each of the Mass Storage class driver functions as the + * MSInterfaceInfo parameter. This stores each Mass Storage interface's configuration and state information. + */ + typedef struct + { + const struct + { + uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device. */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the Mass Storage interface's IN data endpoint. */ + uint16_t DataINEndpointSize; /**< Size in bytes of the Mass Storage interface's IN data endpoint. */ + bool DataINEndpointDoubleBank; /**< Indicates if the Mass Storage interface's IN data endpoint should use double banking. */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the Mass Storage interface's OUT data endpoint. */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the Mass Storage interface's OUT data endpoint. */ + bool DataOUTEndpointDoubleBank; /**< Indicates if the Mass Storage interface's OUT data endpoint should use double banking. */ + + uint8_t TotalLUNs; /**< Total number of logical drives in the Mass Storage interface. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * 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. + * + * \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes. + * + * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state. + * + * \return Boolean true if the endpoints were successfully configured, false otherwise. + */ + bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /** Processes incoming control requests from the host, that are directed to the given Mass Storage class interface. This should be + * linked to the library \ref EVENT_USB_Device_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 true if the SCSI command was successfully processed, false otherwise. + */ + bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Function Prototypes: */ + #if defined(__INCLUDE_FROM_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); + static uint8_t StreamCallback_MS_Device_AbortOnMassStoreReset(void); + #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 new file mode 100644 index 0000000..c6de9e5 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/RNDIS.c @@ -0,0 +1,496 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_DEVICE) + +#define __INCLUDE_FROM_RNDIS_DRIVER +#define __INCLUDE_FROM_RNDIS_DEVICE_C +#include "RNDIS.h" + +static const uint32_t PROGMEM AdapterSupportedOIDList[] = + { + OID_GEN_SUPPORTED_LIST, + OID_GEN_PHYSICAL_MEDIUM, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_GEN_RCV_NO_BUFFER, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS, + }; + +void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) +{ + if (!(Endpoint_IsSETUPReceived())) + return; + + if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber) + return; + + switch (USB_ControlRequest.bRequest) + { + case 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 = 1; + } + + Endpoint_ClearSETUP(); + Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, MessageHeader->MessageLength); + Endpoint_ClearOUT(); + + MessageHeader->MessageLength = 0; + } + + break; + } +} + +bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) +{ + memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State)); + + 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; + + RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber); + + if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady) + { + USB_Request_Header_t Notification = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), + .bRequest = RNDIS_NOTIF_ResponseAvailable, + .wValue = 0, + .wIndex = 0, + .wLength = 0, + }; + + Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK); + + Endpoint_ClearIN(); + + RNDISInterfaceInfo->State.ResponseReady = false; + } + + if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength)) + { + RNDIS_Packet_Message_t RNDISPacketHeader; + + Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber); + + if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer)) + { + Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK); + + if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX) + { + Endpoint_StallTransaction(); + return; + } + + Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK); + + Endpoint_ClearOUT(); + + RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength; + + RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true; + } + + Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber); + + if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer) + { + memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t)); + + RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG; + RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength); + RNDISPacketHeader.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)); + RNDISPacketHeader.DataLength = RNDISInterfaceInfo->State.FrameOUT.FrameLength; + + Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK); + Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK); + Endpoint_ClearIN(); + + RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false; + } + } +} + +void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) +{ + /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of + this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */ + + RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + switch (MessageHeader->MessageType) + { + case REMOTE_NDIS_INITIALIZE_MSG: + RNDISInterfaceInfo->State.ResponseReady = true; + + RNDIS_Initialize_Message_t* INITIALIZE_Message = + (RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + RNDIS_Initialize_Complete_t* INITIALIZE_Response = + (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; + INITIALIZE_Response->MessageLength = sizeof(RNDIS_Initialize_Complete_t); + INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId; + INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + + INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR; + INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR; + INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS; + INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3; + INITIALIZE_Response->MaxPacketsPerTransfer = 1; + INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX); + INITIALIZE_Response->PacketAlignmentFactor = 0; + INITIALIZE_Response->AFListOffset = 0; + INITIALIZE_Response->AFListSize = 0; + + RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized; + + break; + case REMOTE_NDIS_HALT_MSG: + RNDISInterfaceInfo->State.ResponseReady = false; + MessageHeader->MessageLength = 0; + + RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized; + + break; + case REMOTE_NDIS_QUERY_MSG: + RNDISInterfaceInfo->State.ResponseReady = true; + + RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + uint32_t Query_Oid = QUERY_Message->Oid; + + void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + + QUERY_Message->InformationBufferOffset]; + void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)]; + uint16_t ResponseSize; + + QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT; + QUERY_Response->MessageLength = sizeof(RNDIS_Query_Complete_t); + + if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength, + ResponseData, &ResponseSize)) + { + QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + QUERY_Response->MessageLength += ResponseSize; + + QUERY_Response->InformationBufferLength = ResponseSize; + QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t)); + } + else + { + QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED; + + QUERY_Response->InformationBufferLength = 0; + QUERY_Response->InformationBufferOffset = 0; + } + + break; + case REMOTE_NDIS_SET_MSG: + RNDISInterfaceInfo->State.ResponseReady = true; + + RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + uint32_t SET_Oid = SET_Message->Oid; + + SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT; + SET_Response->MessageLength = sizeof(RNDIS_Set_Complete_t); + SET_Response->RequestId = SET_Message->RequestId; + + void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + + SET_Message->InformationBufferOffset]; + + SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, + SET_Message->InformationBufferLength) ? + REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED; + break; + case REMOTE_NDIS_RESET_MSG: + RNDISInterfaceInfo->State.ResponseReady = true; + + RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT; + RESET_Response->MessageLength = sizeof(RNDIS_Reset_Complete_t); + RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + RESET_Response->AddressingReset = 0; + + break; + case REMOTE_NDIS_KEEPALIVE_MSG: + RNDISInterfaceInfo->State.ResponseReady = true; + + RNDIS_KeepAlive_Message_t* KEEPALIVE_Message = + (RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = + (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; + KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KeepAlive_Complete_t); + KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId; + KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + + break; + } +} + +static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, + const uint32_t OId, + void* const QueryData, + const uint16_t QuerySize, + void* ResponseData, + uint16_t* const ResponseSize) +{ + (void)QueryData; + (void)QuerySize; + + switch (OId) + { + case OID_GEN_SUPPORTED_LIST: + *ResponseSize = sizeof(AdapterSupportedOIDList); + + memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList)); + + return true; + case OID_GEN_PHYSICAL_MEDIUM: + *ResponseSize = sizeof(uint32_t); + + /* Indicate that the device is a true ethernet link */ + *((uint32_t*)ResponseData) = 0; + + return true; + case OID_GEN_HARDWARE_STATUS: + *ResponseSize = sizeof(uint32_t); + + *((uint32_t*)ResponseData) = NDIS_HardwareStatus_Ready; + + return true; + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + *ResponseSize = sizeof(uint32_t); + + *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3; + + return true; + case OID_GEN_VENDOR_ID: + *ResponseSize = sizeof(uint32_t); + + /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */ + *((uint32_t*)ResponseData) = 0x00FFFFFF; + + return true; + case OID_GEN_MAXIMUM_FRAME_SIZE: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + *ResponseSize = sizeof(uint32_t); + + *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX; + + return true; + case OID_GEN_VENDOR_DESCRIPTION: + *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1); + + memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize); + + return true; + case OID_GEN_MEDIA_CONNECT_STATUS: + *ResponseSize = sizeof(uint32_t); + + *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED; + + return true; + case OID_GEN_LINK_SPEED: + *ResponseSize = sizeof(uint32_t); + + /* Indicate 10Mb/s link speed */ + *((uint32_t*)ResponseData) = 100000; + + return true; + case OID_802_3_PERMANENT_ADDRESS: + case OID_802_3_CURRENT_ADDRESS: + *ResponseSize = sizeof(MAC_Address_t); + + memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t)); + + return true; + case OID_802_3_MAXIMUM_LIST_SIZE: + *ResponseSize = sizeof(uint32_t); + + /* Indicate only one multicast address supported */ + *((uint32_t*)ResponseData) = 1; + + return true; + case OID_GEN_CURRENT_PACKET_FILTER: + *ResponseSize = sizeof(uint32_t); + + *((uint32_t*)ResponseData) = RNDISInterfaceInfo->State.CurrPacketFilter; + + return true; + case OID_GEN_XMIT_OK: + case OID_GEN_RCV_OK: + case OID_GEN_XMIT_ERROR: + case OID_GEN_RCV_ERROR: + case OID_GEN_RCV_NO_BUFFER: + case OID_802_3_RCV_ERROR_ALIGNMENT: + case OID_802_3_XMIT_ONE_COLLISION: + case OID_802_3_XMIT_MORE_COLLISIONS: + *ResponseSize = sizeof(uint32_t); + + /* Unused statistic OIDs - always return 0 for each */ + *((uint32_t*)ResponseData) = 0; + + return true; + case OID_GEN_MAXIMUM_TOTAL_SIZE: + *ResponseSize = sizeof(uint32_t); + + /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */ + *((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX); + + return true; + default: + return false; + } +} + +static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, + const uint32_t OId, + const void* SetData, + const uint16_t SetSize) +{ + (void)SetSize; + + switch (OId) + { + case OID_GEN_CURRENT_PACKET_FILTER: + RNDISInterfaceInfo->State.CurrPacketFilter = *((uint32_t*)SetData); + RNDISInterfaceInfo->State.CurrRNDISState = ((RNDISInterfaceInfo->State.CurrPacketFilter) ? + RNDIS_Data_Initialized : RNDIS_Data_Initialized); + + return true; + case OID_802_3_MULTICAST_LIST: + /* Do nothing - throw away the value from the host as it is unused */ + + return true; + default: + return false; + } +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Device/RNDIS.h b/LUFA/Drivers/USB/Class/Device/RNDIS.h new file mode 100644 index 0000000..9f24f29 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Device/RNDIS.h @@ -0,0 +1,186 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Device mode driver for the library USB RNDIS Class driver. + * + * Device mode driver for the library USB RNDIS Class driver. + * + * \note This file should not be included directly. It is automatically included as needed by the 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 Module Description + * Device Mode USB Class driver framework interface, for the RNDIS USB Class driver. + * + * @{ + */ + +#ifndef _RNDIS_CLASS_DEVICE_H_ +#define _RNDIS_CLASS_DEVICE_H_ + + /* Includes: */ + #include "../../USB.h" + #include "../Common/RNDIS.h" + + #include + + /* 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 + + #if defined(__INCLUDE_FROM_RNDIS_DEVICE_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #endif + + + /* Public Interface - May be used in end-application: */ + /* Type Defines: */ + /** \brief RNDIS Class Device Mode Configuration and State Structure. + * + * Class state structure. An instance of this structure should be made for each RNDIS interface + * within the user application, and passed to each of the RNDIS class driver functions as the + * RNDISInterfaceInfo parameter. This stores each RNDIS interface's configuration and state information. + */ + typedef struct + { + const struct + { + uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */ + + uint8_t DataINEndpointNumber; /**< Endpoint number of the CDC interface's IN data endpoint. */ + uint16_t DataINEndpointSize; /**< Size in bytes of the CDC interface's IN data endpoint. */ + bool DataINEndpointDoubleBank; /**< Indicates if the RNDIS interface's IN data endpoint should use double banking. */ + + uint8_t DataOUTEndpointNumber; /**< Endpoint number of the CDC interface's OUT data endpoint. */ + uint16_t DataOUTEndpointSize; /**< Size in bytes of the CDC interface's OUT data endpoint. */ + bool DataOUTEndpointDoubleBank; /**< Indicates if the RNDIS interface's OUT data endpoint should use double banking. */ + + uint8_t NotificationEndpointNumber; /**< Endpoint number of the CDC interface's IN notification endpoint, if used. */ + uint16_t NotificationEndpointSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used. */ + bool NotificationEndpointDoubleBank; /**< Indicates if the RNDIS interface's notification endpoint should use double banking. */ + + char* AdapterVendorDescription; /**< String description of the adapter vendor. */ + MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section. + * 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. */ + Ethernet_Frame_Info_t FrameIN; /**< Structure holding the last received Ethernet frame from the host, for user + * processing. + */ + Ethernet_Frame_Info_t FrameOUT; /**< Structure holding the next Ethernet frame to send to the host, populated by the + * user application. + */ + } State; /**< State data for the USB class interface within the device. All elements in this section + * are reset to their defaults when the interface is enumerated. + */ + } USB_ClassInfo_RNDIS_Device_t; + + /* Function Prototypes: */ + /** Configures the endpoints of a given RNDIS interface, ready for use. This should be linked to the library + * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration + * containing the given HID interface is selected. + * + * \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes. + * + * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state. + * + * \return Boolean true if the endpoints were successfully configured, false otherwise. + */ + bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /** Processes incoming control requests from the host, that are directed to the given RNDIS class interface. This should be + * linked to the library \ref EVENT_USB_Device_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 HID class interface, required for the correct operation of the interface. This should + * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask(). + * + * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state. + */ + void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Function Prototypes: */ + #if defined(__INCLUDE_FROM_RNDIS_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 new file mode 100644 index 0000000..7748f44 --- /dev/null +++ b/LUFA/Drivers/USB/Class/HID.h @@ -0,0 +1,81 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../HighLevel/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/Host/CDC.c b/LUFA/Drivers/USB/Class/Host/CDC.c new file mode 100644 index 0000000..afa4629 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/CDC.c @@ -0,0 +1,465 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_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_DESCRIPTOR_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++) + { + if (PipeNum == CDCInterfaceInfo->Config.DataINPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, + DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, + CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + CDCInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == CDCInterfaceInfo->Config.DataOUTPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, + DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, + CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + CDCInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else if (PipeNum == CDCInterfaceInfo->Config.NotificationPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, + NotificationEndpoint->EndpointAddress, NotificationEndpoint->EndpointSize, + CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + Pipe_SetInterruptPeriod(NotificationEndpoint->PollingIntervalMS); + + CDCInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; + } + } + + 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), NO_STREAM_CALLBACK); + + 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), + NO_STREAM_CALLBACK); + + 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_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, + const char* const Data, + 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(Data, Length, NO_STREAM_CALLBACK); + 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_Byte(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_Byte(); + + 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; +} + +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; +} + +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 new file mode 100644 index 0000000..4128fe1 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/CDC.h @@ -0,0 +1,334 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 + #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 + + #if defined(__INCLUDE_FROM_CDC_HOST_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 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 + { + uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_* + * masks - to notify the device of changes to these values, call the + * \ref CDC_Host_SendControlLineStateChange() function. + */ + uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of 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. */ + }; + + /* 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. + * + * \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes. + * + * \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 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 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 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 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 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 Pointer to the string to send to the device. + * \param[in] Length Size in bytes of the 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 Data, + const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Sends a given byte to the attached USB 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 avr-libc library that accept a FILE stream as a destination (e.g. fprintf). The created + * stream is bidirectional and can be used for both input and output functions. + * + * \note The created stream can be given as stdout if desired to direct the standard output from all functions + * to the given CDC interface. + * + * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. + * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed. + */ + void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, + FILE* const Stream); + + /** Identical to 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. + * + * \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 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) + 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); + + void CDC_Host_Event_Stub(void); + 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_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor) 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 new file mode 100644 index 0000000..7343631 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/HID.c @@ -0,0 +1,387 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_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_NextHID) != 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_DESCRIPTOR_DIR_IN) + DataINEndpoint = EndpointData; + else + DataOUTEndpoint = EndpointData; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, + DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, + HIDInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS); + + HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT, + DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, + HIDInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + Pipe_SetInterruptPeriod(DataOUTEndpoint->PollingIntervalMS); + + HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + HIDInterfaceInfo->State.DeviceUsesOUTPipe = true; + } + } + + HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber; + HIDInterfaceInfo->State.HIDReportSize = 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_NextHID(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_Byte(); + *(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, NO_STREAM_CALLBACK)) != 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), NO_STREAM_CALLBACK); + + if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NO_STREAM_CALLBACK)) != 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; + + 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 (!(HIDInterfaceInfo->State.SupportsBootProtocol)) + return HID_ERROR_LOGICAL; + + if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful) + return ErrorCode; + + HIDInterfaceInfo->State.LargestReportSize = 8; + HIDInterfaceInfo->State.UsingBootProtocol = true; + + return HOST_SENDCONTROL_Successful; +} + +#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; + } + + uint8_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 new file mode 100644 index 0000000..2d6fd9e --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/HID.h @@ -0,0 +1,316 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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) + * - LUFA/Drivers/USB/Class/Host/HIDParser.c (Makefile source module name: LUFA_SRC_USB) + * + * \section 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" + #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 + + #if defined(__INCLUDE_FROM_HID_HOST_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 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 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. */ + }; + + /* 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 The pipe index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes. + * \n\n + * + * \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 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 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 true if a report has been received, 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 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); + + #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 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); + 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_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_HID_Host_NextHID(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor) 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/HIDParser.c b/LUFA/Drivers/USB/Class/Host/HIDParser.c new file mode 100644 index 0000000..f0e7db8 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/HIDParser.c @@ -0,0 +1,361 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_HOST) + +#define __INCLUDE_FROM_HID_DRIVER +#include "HIDParser.h" + +uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, + uint16_t ReportSize, + HID_ReportInfo_t* const ParserData) +{ + HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH]; + HID_StateTable_t* CurrStateTable = &StateTable[0]; + HID_CollectionPath_t* CurrCollectionPath = NULL; + HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0]; + uint16_t UsageList[HID_USAGE_STACK_DEPTH]; + uint8_t UsageListSize = 0; + HID_MinMax_t UsageMinMax = {0, 0}; + + memset(ParserData, 0x00, sizeof(HID_ReportInfo_t)); + memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t)); + memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t)); + + ParserData->TotalDeviceReports = 1; + + while (ReportSize) + { + uint8_t HIDReportItem = *ReportData; + uint32_t ReportItemData = 0; + + ReportData++; + ReportSize--; + + switch (HIDReportItem & DATA_SIZE_MASK) + { + case DATA_SIZE_4: + ReportItemData = *((uint32_t*)ReportData); + ReportSize -= 4; + ReportData += 4; + break; + case DATA_SIZE_2: + ReportItemData = *((uint16_t*)ReportData); + ReportSize -= 2; + ReportData += 2; + break; + case DATA_SIZE_1: + ReportItemData = *((uint8_t*)ReportData); + ReportSize -= 1; + ReportData += 1; + break; + } + + switch (HIDReportItem & (TYPE_MASK | TAG_MASK)) + { + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1]) + return HID_PARSE_HIDStackOverflow; + + memcpy((CurrStateTable + 1), + CurrStateTable, + sizeof(HID_ReportItem_t)); + + CurrStateTable++; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + if (CurrStateTable == &StateTable[0]) + return HID_PARSE_HIDStackUnderflow; + + CurrStateTable--; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + CurrStateTable->Attributes.Usage.Page = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + CurrStateTable->Attributes.Logical.Minimum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + CurrStateTable->Attributes.Logical.Maximum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + CurrStateTable->Attributes.Physical.Minimum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + CurrStateTable->Attributes.Physical.Maximum = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + CurrStateTable->Attributes.Unit.Exponent = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + CurrStateTable->Attributes.Unit.Type = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + CurrStateTable->Attributes.BitSize = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + CurrStateTable->ReportCount = ReportItemData; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + CurrStateTable->ReportID = ReportItemData; + + if (ParserData->UsingReportIDs) + { + CurrReportIDInfo = NULL; + + for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++) + { + if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID) + { + CurrReportIDInfo = &ParserData->ReportIDSizes[i]; + break; + } + } + + if (CurrReportIDInfo == NULL) + { + if (ParserData->TotalDeviceReports == HID_MAX_REPORT_IDS) + return HID_PARSE_InsufficientReportIDItems; + + CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports++]; + memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t)); + } + } + + ParserData->UsingReportIDs = true; + + CurrReportIDInfo->ReportID = CurrStateTable->ReportID; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + if (UsageListSize == HID_USAGE_STACK_DEPTH) + return HID_PARSE_UsageListOverflow; + + UsageList[UsageListSize++] = ReportItemData; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + UsageMinMax.Minimum = ReportItemData; + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + UsageMinMax.Maximum = ReportItemData; + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + if (CurrCollectionPath == NULL) + { + CurrCollectionPath = &ParserData->CollectionPaths[0]; + } + else + { + HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath; + + CurrCollectionPath = &ParserData->CollectionPaths[1]; + + while (CurrCollectionPath->Parent != NULL) + { + if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1]) + return HID_PARSE_InsufficientCollectionPaths; + + CurrCollectionPath++; + } + + CurrCollectionPath->Parent = ParentCollectionPath; + } + + CurrCollectionPath->Type = ReportItemData; + CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page; + + if (UsageListSize) + { + CurrCollectionPath->Usage.Usage = UsageList[0]; + + for (uint8_t i = 0; i < UsageListSize; i++) + UsageList[i] = UsageList[i + 1]; + + UsageListSize--; + } + else if (UsageMinMax.Minimum <= UsageMinMax.Maximum) + { + CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++; + } + + break; + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + if (CurrCollectionPath == NULL) + return HID_PARSE_UnexpectedEndCollection; + + CurrCollectionPath = CurrCollectionPath->Parent; + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + case (TYPE_MAIN | TAG_MAIN_FEATURE): + for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++) + { + HID_ReportItem_t NewReportItem; + + memcpy(&NewReportItem.Attributes, + &CurrStateTable->Attributes, + sizeof(HID_ReportItem_Attributes_t)); + + NewReportItem.ItemFlags = ReportItemData; + NewReportItem.CollectionPath = CurrCollectionPath; + NewReportItem.ReportID = CurrStateTable->ReportID; + + if (UsageListSize) + { + NewReportItem.Attributes.Usage.Usage = UsageList[0]; + + for (uint8_t i = 0; i < UsageListSize; i++) + UsageList[i] = UsageList[i + 1]; + + UsageListSize--; + } + else if (UsageMinMax.Minimum <= UsageMinMax.Maximum) + { + NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++; + } + + uint8_t ItemTag = (HIDReportItem & TAG_MASK); + + if (ItemTag == TAG_MAIN_INPUT) + NewReportItem.ItemType = HID_REPORT_ITEM_In; + else if (ItemTag == TAG_MAIN_OUTPUT) + NewReportItem.ItemType = HID_REPORT_ITEM_Out; + else + NewReportItem.ItemType = HID_REPORT_ITEM_Feature; + + NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType]; + + CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize; + + if (ParserData->LargestReportSizeBits < NewReportItem.BitOffset) + ParserData->LargestReportSizeBits = NewReportItem.BitOffset; + + if (!(ReportItemData & IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem)) + { + if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS) + return HID_PARSE_InsufficientReportItems; + + memcpy(&ParserData->ReportItems[ParserData->TotalReportItems], + &NewReportItem, sizeof(HID_ReportItem_t)); + + ParserData->TotalReportItems++; + } + } + + break; + } + + if ((HIDReportItem & TYPE_MASK) == TYPE_MAIN) + { + UsageMinMax.Minimum = 0; + UsageMinMax.Maximum = 0; + UsageListSize = 0; + } + } + + if (!(ParserData->TotalReportItems)) + return HID_PARSE_NoUnfilteredReportItems; + + return HID_PARSE_Successful; +} + +bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, + HID_ReportItem_t* const ReportItem) +{ + uint16_t DataBitsRem = ReportItem->Attributes.BitSize; + uint16_t CurrentBit = ReportItem->BitOffset; + uint32_t BitMask = (1 << 0); + + if (ReportItem->ReportID) + { + if (ReportItem->ReportID != ReportData[0]) + return false; + + ReportData++; + } + + ReportItem->PreviousValue = ReportItem->Value; + ReportItem->Value = 0; + + while (DataBitsRem--) + { + if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8))) + ReportItem->Value |= BitMask; + + CurrentBit++; + BitMask <<= 1; + } + + return true; +} + +void USB_SetHIDReportItemInfo(uint8_t* ReportData, + HID_ReportItem_t* const ReportItem) +{ + uint16_t DataBitsRem = ReportItem->Attributes.BitSize; + uint16_t CurrentBit = ReportItem->BitOffset; + uint32_t BitMask = (1 << 0); + + if (ReportItem->ReportID) + { + ReportData[0] = ReportItem->ReportID; + ReportData++; + } + + ReportItem->PreviousValue = ReportItem->Value; + + while (DataBitsRem--) + { + if (ReportItem->Value & (1 << (CurrentBit % 8))) + ReportData[CurrentBit / 8] |= BitMask; + + CurrentBit++; + BitMask <<= 1; + } +} + +uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData, + const uint8_t ReportID, + const uint8_t ReportType) +{ + for (uint8_t i = 0; i < HID_MAX_REPORT_IDS; i++) + { + uint16_t ReportSizeBits = ParserData->ReportIDSizes[i].ReportSizeBits[ReportType]; + + if (ParserData->ReportIDSizes[i].ReportID == ReportID) + return ((ReportSizeBits >> 3) + ((ReportSizeBits & 0x07) ? 1 : 0)); + } + + return 0; +} + +#endif + diff --git a/LUFA/Drivers/USB/Class/Host/HIDParser.h b/LUFA/Drivers/USB/Class/Host/HIDParser.h new file mode 100644 index 0000000..cb3b98f --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/HIDParser.h @@ -0,0 +1,356 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB Human Interface Device (HID) Class report descriptor parser. + * + * This file allows for the easy parsing of complex HID report descriptors, which describes the data that + * a HID device transmits to the host. It also provides an easy API for extracting and processing the data + * elements inside a HID report sent from an attached HID device. + */ + +/** \ingroup Group_USB + * @defgroup Group_HIDParser HID Report Parser + * + * \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/HIDParser.c (Makefile source module name: LUFA_SRC_USB) + * + * \section Module Description + * Functions, macros, variables, enums and types related to the parsing of HID class device report descriptors. + * + * The processed HID report is presented back to the user application as a flat structure containing each report + * item's IN, OUT and FEATURE items along with each item's attributes. + * + * This library portion also allows for easy setting and retrieval of data from a HID report, including devices + * with multiple reports on the one HID interface. + * + * @{ + */ + +#ifndef __HIDPARSER_H__ +#define __HIDPARSER_H__ + + /* Includes: */ + #include + #include + + #include "HIDReportData.h" + #include "../Common/HID.h" + + #include "../../../../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Macros: */ + #if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__) + /** Constant indicating the maximum stack depth of the state table. A larger state table + * allows for more PUSH/POP report items to be nested, but consumes more memory. By default + * this is set to 2 levels (allowing non-nested PUSH items) but this can be overridden by + * defining HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the + * define to the compiler using the -D compiler switch. + */ + #define HID_STATETABLE_STACK_DEPTH 2 + #endif + + #if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__) + /** Constant indicating the maximum stack depth of the usage table. A larger usage table + * allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than + * one, but requires more stack space. By default this is set to 8 levels (allowing for a report + * item with a count of 8) but this can be overridden by defining HID_USAGE_STACK_DEPTH to another + * value in the user project makefile, passing the define to the compiler using the -D compiler + * switch. + */ + #define HID_USAGE_STACK_DEPTH 8 + #endif + + #if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__) + /** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be + * processed in the report item descriptor. A large value allows for more COLLECTION items to be + * processed, but consumes more memory. By default this is set to 10 collections, but this can be + * overridden by defining HID_MAX_COLLECTIONS to another value in the user project makefile, passing + * the define to the compiler using the -D compiler switch. + */ + #define HID_MAX_COLLECTIONS 10 + #endif + + #if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__) + /** Constant indicating the maximum number of report items (IN, OUT or FEATURE) that can be processed + * in the report item descriptor and stored in the user HID Report Info structure. A large value allows + * for more report items to be stored, but consumes more memory. By default this is set to 20 items, + * but this can be overridden by defining HID_MAX_REPORTITEMS to another value in the user project + * makefile, and passing the define to the compiler using the -D compiler switch. + */ + #define HID_MAX_REPORTITEMS 20 + #endif + + #if !defined(HID_MAX_REPORT_IDS) || defined(__DOXYGEN__) + /** Constant indicating the maximum number of unique report IDs that can be processed in the report item + * descriptor for the report size information array in the user HID Report Info structure. A large value + * allows for more report ID report sizes to be stored, but consumes more memory. By default this is set + * to 10 items, but this can be overridden by defining HID_MAX_REPORT_IDS to another value in the user project + * makefile, and passing the define to the compiler using the -D compiler switch. Note that IN, OUT and FEATURE + * items sharing the same report ID consume only one size item in the array. + */ + #define HID_MAX_REPORT_IDS 10 + #endif + + /** Returns the value a given HID report item (once its value has been fetched via \ref USB_GetHIDReportItemInfo()) + * left-aligned to the given data type. This allows for signed data to be interpreted correctly, by shifting the data + * leftwards until the data's sign bit is in the correct position. + * + * \param[in] ReportItem HID Report Item whose retrieved value is to be aligned. + * \param[in] Type Data type to align the HID report item's value to. + * + * \return Left-aligned data of the given report item's pre-retrieved value for the given datatype. + */ + #define HID_ALIGN_DATA(ReportItem, Type) ((Type)(ReportItem->Value << ((8 * sizeof(Type)) - ReportItem->Attributes.BitSize))) + + /* Public Interface - May be used in end-application: */ + /* Enums: */ + /** Enum for the possible error codes in the return value of the \ref USB_ProcessHIDReport() function. */ + enum HID_Parse_ErrorCodes_t + { + HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */ + HID_PARSE_HIDStackOverflow = 1, /**< More than \ref HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */ + HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */ + HID_PARSE_InsufficientReportItems = 3, /**< More than \ref HID_MAX_REPORTITEMS report items in the report. */ + HID_PARSE_UnexpectedEndCollection = 4, /**< An END COLLECTION item found without matching COLLECTION item. */ + HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */ + HID_PARSE_UsageListOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */ + HID_PARSE_InsufficientReportIDItems = 7, /**< More than \ref HID_MAX_REPORT_IDS report IDs in the device. */ + HID_PARSE_NoUnfilteredReportItems = 8, /**< All report items from the device were filtered by the filtering callback routine. */ + }; + + /* Type Defines: */ + /** \brief HID Parser Report Item Min/Max Structure. + * + * Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max). + */ + typedef struct + { + uint32_t Minimum; /**< Minimum value for the attribute. */ + uint32_t Maximum; /**< Maximum value for the attribute. */ + } HID_MinMax_t; + + /** \brief HID Parser Report Item Unit Structure. + * + * Type define for the Unit attributes of a report item. + */ + typedef struct + { + uint32_t Type; /**< Unit type (refer to HID specifications for details). */ + uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */ + } HID_Unit_t; + + /** \brief HID Parser Report Item Usage Structure. + * + * Type define for the Usage attributes of a report item. + */ + typedef struct + { + uint16_t Page; /**< Usage page of the report item. */ + uint16_t Usage; /**< Usage of the report item. */ + } HID_Usage_t; + + /** \brief HID Parser Report Item Collection Path Structure. + * + * Type define for a COLLECTION object. Contains the collection attributes and a reference to the + * parent collection if any. + */ + typedef struct CollectionPath + { + uint8_t Type; /**< Collection type (e.g. "Generic Desktop"). */ + HID_Usage_t Usage; /**< Collection usage. */ + struct CollectionPath* Parent; /**< Reference to parent collection, or NULL if root collection. */ + } HID_CollectionPath_t; + + /** \brief HID Parser Report Item Attributes Structure. + * + * Type define for all the data attributes of a report item, except flags. + */ + typedef struct + { + uint8_t BitSize; /**< Size in bits of the report item's data. */ + + HID_Usage_t Usage; /**< Usage of the report item. */ + HID_Unit_t Unit; /**< Unit type and exponent of the report item. */ + HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */ + HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */ + } HID_ReportItem_Attributes_t; + + /** \brief HID Parser Report Item Details Structure. + * + * Type define for a report item (IN, OUT or FEATURE) layout attributes and other details. + */ + typedef struct + { + uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */ + uint8_t ItemType; /**< Report item type, a value in HID_ReportItemTypes_t. */ + uint16_t ItemFlags; /**< Item data flags, such as constant/variable, etc. */ + uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */ + HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */ + + HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */ + + uint32_t Value; /**< Current value of the report item - use \ref HID_ALIGN_DATA() when processing + * a retrieved value so that it is aligned to a specific type. + */ + uint32_t PreviousValue; /**< Previous value of the report item. */ + } HID_ReportItem_t; + + /** \brief HID Parser Report Size Structure. + * + * Type define for a report item size information structure, to retain the size of a device's reports by ID. + */ + typedef struct + { + uint8_t ReportID; /**< Report ID of the report within the HID interface. */ + uint16_t ReportSizeBits[3]; /**< Total number of bits in each report type for the given Report ID, + * indexed by the \ref HID_ReportItemTypes_t enum. + */ + } HID_ReportSizeInfo_t; + + /** \brief HID Parser State Structure. + * + * Type define for a complete processed HID report, including all report item data and collections. + */ + typedef struct + { + uint8_t TotalReportItems; /**< Total number of report items stored in the + * ReportItems array. + */ + HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including + * all IN, OUT and FEATURE items. + */ + HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced + * by the report items. + */ + uint8_t TotalDeviceReports; /**< Number of reports within the HID interface */ + HID_ReportSizeInfo_t ReportIDSizes[HID_MAX_REPORT_IDS]; /**< Report sizes for each report in the interface */ + uint16_t LargestReportSizeBits; /**< Largest report that the attached device will generate, in bits */ + bool UsingReportIDs; /**< Indicates if the device has at least one REPORT ID + * element in its HID report descriptor. + */ + } HID_ReportInfo_t; + + /* Function Prototypes: */ + /** Function to process a given HID report returned from an attached device, and store it into a given + * \ref HID_ReportInfo_t structure. + * + * \param[in] ReportData Buffer containing the device's HID report table. + * \param[in] ReportSize Size in bytes of the HID report table. + * \param[out] ParserData Pointer to a \ref HID_ReportInfo_t instance for the parser output. + * + * \return A value in the \ref HID_Parse_ErrorCodes_t enum. + */ + uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, + uint16_t ReportSize, + HID_ReportInfo_t* const ParserData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3); + + /** Extracts the given report item's value out of the given HID report and places it into the Value + * member of the report item's \ref HID_ReportItem_t structure. + * + * When called on a report with an item that exists in that report, this copies the report item's Value + * to it's PreviousValue element for easy checking to see if an item's value has changed before processing + * a report. If the given item does not exist in the report, the function does not modify the report item's + * data. + * + * \param[in] ReportData Buffer containing an IN or FEATURE report from an attached device. + * \param[in,out] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array. + * + * \returns Boolean true if the item to retrieve was located in the given report, false otherwise. + */ + bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, + HID_ReportItem_t* const ReportItem) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Retrieves the given report item's value out of the Value member of the report item's + * \ref HID_ReportItem_t structure and places it into the correct position in the HID report + * buffer. The report buffer is assumed to have the appropriate bits cleared before calling + * this function (i.e., the buffer should be explicitly cleared before report values are added). + * + * When called, this copies the report item's Value element to it's PreviousValue element for easy + * checking to see if an item's value has changed before sending a report. + * + * If the device has multiple HID reports, the first byte in the report is set to the report ID of the given item. + * + * \param[out] ReportData Buffer holding the current OUT or FEATURE report data. + * \param[in] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array. + */ + void USB_SetHIDReportItemInfo(uint8_t* ReportData, + HID_ReportItem_t* const ReportItem) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Retrieves the size of a given HID report in bytes from it's Report ID. + * + * \param[in] ParserData Pointer to a \ref HID_ReportInfo_t instance containing the parser output. + * \param[in] ReportID Report ID of the report whose size is to be retrieved. + * \param[in] ReportType Type of the report whose size is to be determined, a valued from the + * \ref HID_ReportItemTypes_t enum. + * + * \return Size of the report in bytes, or 0 if the report does not exist. + */ + uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData, + const uint8_t ReportID, + const uint8_t ReportType) ATTR_CONST ATTR_NON_NULL_PTR_ARG(1); + + /** Callback routine for the HID Report Parser. This callback must be implemented by the user code when + * the parser is used, to determine what report IN, OUT and FEATURE item's information is stored into the user + * HID_ReportInfo_t structure. This can be used to filter only those items the application will be using, so that + * no RAM is wasted storing the attributes for report items which will never be referenced by the application. + * + * \param[in] CurrentItem Pointer to the current report item for user checking. + * + * \return Boolean true if the item should be stored into the HID_ReportInfo_t structure, false if it should be ignored. + */ + bool CALLBACK_HIDParser_FilterHIDReportItem(HID_ReportItem_t* const CurrentItem); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Type Defines: */ + typedef struct + { + HID_ReportItem_Attributes_t Attributes; + uint8_t ReportCount; + uint8_t ReportID; + } HID_StateTable_t; + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/Host/HIDReportData.h b/LUFA/Drivers/USB/Class/Host/HIDReportData.h new file mode 100644 index 0000000..6ce6b8a --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/HIDReportData.h @@ -0,0 +1,142 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Constants for HID report item attributes. + * + * HID report item constants for report item attributes. Refer to the HID specification for + * details on each flag's meaning when applied to an IN, OUT or FEATURE item. + */ + +/** \ingroup Group_HIDParser + * @defgroup Group_HIDIOFConst Input/Output/Feature Masks + * + * Masks indicating the type of Input, Output of Feature HID report item. + * + * @{ + */ + +#ifndef __HIDREPORTDATA_H__ +#define __HIDREPORTDATA_H__ + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \ref HID_ReportItem_t.ItemFlags flag for constant data. */ + #define IOF_CONSTANT (1 << 0) + + /** \ref HID_ReportItem_t.ItemFlags flag for data. */ + #define IOF_DATA (0 << 0) + + /** \ref HID_ReportItem_t.ItemFlags flag for variable data. */ + #define IOF_VARIABLE (1 << 1) + + /** \ref HID_ReportItem_t.ItemFlags flag for array data. */ + #define IOF_ARRAY (0 << 1) + + /** \ref HID_ReportItem_t.ItemFlags flag for relative data. */ + #define IOF_RELATIVE (1 << 2) + + /** \ref HID_ReportItem_t.ItemFlags flag for absolute data. */ + #define IOF_ABSOLUTE (0 << 2) + + /** \ref HID_ReportItem_t.ItemFlags flag for wrapped value data. */ + #define IOF_WRAP (1 << 3) + + /** \ref HID_ReportItem_t.ItemFlags flag for non-wrapped value data. */ + #define IOF_NOWRAP (0 << 3) + + /** \ref HID_ReportItem_t.ItemFlags flag for non linear data. */ + #define IOF_NONLINEAR (1 << 4) + + /** \ref HID_ReportItem_t.ItemFlags flag for linear data. */ + #define IOF_LINEAR (0 << 4) + + /** \ref HID_ReportItem_t.ItemFlags flag for no preferred state. */ + #define IOF_NOPREFERRED (1 << 5) + + /** \ref HID_ReportItem_t.ItemFlags flag for preferred state items. */ + #define IOF_PREFERREDSTATE (0 << 5) + + /** \ref HID_ReportItem_t.ItemFlags flag for null state items. */ + #define IOF_NULLSTATE (1 << 6) + + /** \ref HID_ReportItem_t.ItemFlags flag for no null position data. */ + #define IOF_NONULLPOSITION (0 << 6) + + /** \ref HID_ReportItem_t.ItemFlags flag for buffered bytes. */ + #define IOF_BUFFEREDBYTES (1 << 8) + + /** \ref HID_ReportItem_t.ItemFlags flag for bit field data. */ + #define IOF_BITFIELD (0 << 8) + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define DATA_SIZE_MASK 0x03 + #define TYPE_MASK 0x0C + #define TAG_MASK 0xF0 + + #define DATA_SIZE_0 0x00 + #define DATA_SIZE_1 0x01 + #define DATA_SIZE_2 0x02 + #define DATA_SIZE_4 0x03 + + #define TYPE_MAIN 0x00 + #define TYPE_GLOBAL 0x04 + #define TYPE_LOCAL 0x08 + + #define TAG_MAIN_INPUT 0x80 + #define TAG_MAIN_OUTPUT 0x90 + #define TAG_MAIN_COLLECTION 0xA0 + #define TAG_MAIN_FEATURE 0xB0 + #define TAG_MAIN_ENDCOLLECTION 0xC0 + + #define TAG_GLOBAL_USAGEPAGE 0x00 + #define TAG_GLOBAL_LOGICALMIN 0x10 + #define TAG_GLOBAL_LOGICALMAX 0x20 + #define TAG_GLOBAL_PHYSMIN 0x30 + #define TAG_GLOBAL_PHYSMAX 0x40 + #define TAG_GLOBAL_UNITEXP 0x50 + #define TAG_GLOBAL_UNIT 0x60 + #define TAG_GLOBAL_REPORTSIZE 0x70 + #define TAG_GLOBAL_REPORTID 0x80 + #define TAG_GLOBAL_REPORTCOUNT 0x90 + #define TAG_GLOBAL_PUSH 0xA0 + #define TAG_GLOBAL_POP 0xB0 + + #define TAG_LOCAL_USAGE 0x00 + #define TAG_LOCAL_USAGEMIN 0x10 + #define TAG_LOCAL_USAGEMAX 0x20 + #endif + +/** @} */ + +#endif + diff --git a/LUFA/Drivers/USB/Class/Host/MIDI.c b/LUFA/Drivers/USB/Class/Host/MIDI.c new file mode 100644 index 0000000..4877dbe --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MIDI.c @@ -0,0 +1,215 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_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_DESCRIPTOR_DIR_IN) + DataINEndpoint = EndpointData; + else + DataOUTEndpoint = EndpointData; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + if (PipeNum == MIDIInterfaceInfo->Config.DataINPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, + DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, + MIDIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + MIDIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == MIDIInterfaceInfo->Config.DataOUTPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, + DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, + MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + MIDIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + } + + 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), NO_STREAM_CALLBACK)) != 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), NO_STREAM_CALLBACK); + + 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 new file mode 100644 index 0000000..0cb778f --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MIDI.h @@ -0,0 +1,201 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 + + #if defined(__INCLUDE_FROM_MIDI_HOST_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 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. */ + }; + + /* 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. + * + * \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes. + * + * \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 true if a MIDI event packet was received, 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_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor) 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 new file mode 100644 index 0000000..0ecaca9 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MassStorage.c @@ -0,0 +1,629 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_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_DESCRIPTOR_DIR_IN) + DataINEndpoint = EndpointData; + else + DataOUTEndpoint = EndpointData; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + if (PipeNum == MSInterfaceInfo->Config.DataINPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, + DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, + MSInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + MSInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == MSInterfaceInfo->Config.DataOUTPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, + DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, + MSInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + MSInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + } + + 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; + + SCSICommandBlock->Signature = MS_CBW_SIGNATURE; + SCSICommandBlock->Tag = ++MSInterfaceInfo->State.TransactionTag; + + if (MSInterfaceInfo->State.TransactionTag == 0xFFFFFFFF) + MSInterfaceInfo->State.TransactionTag = 1; + + Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); + Pipe_Unfreeze(); + + if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t), + NO_STREAM_CALLBACK)) != 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_ClearPipeStall(MSInterfaceInfo->Config.DataOUTPipeNumber); + + return PIPE_RWSTREAM_PipeStalled; + } + + Pipe_Freeze(); + Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); + Pipe_Unfreeze(); + + if (Pipe_IsStalled()) + { + USB_Host_ClearPipeStall(MSInterfaceInfo->Config.DataINPipeNumber); + + 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 = 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, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + Pipe_ClearIN(); + } + else + { + Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipeNumber); + Pipe_Unfreeze(); + + if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem, NO_STREAM_CALLBACK)) != 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), + NO_STREAM_CALLBACK)) != 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) +{ + 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); + + return USB_Host_SendControlRequest(NULL); +} + +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_Successful) + { + *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 = 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 = 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 = 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; + + SwapEndian_n(&DeviceCapacity->Blocks, sizeof(DeviceCapacity->Blocks)); + SwapEndian_n(&DeviceCapacity->BlockSize, sizeof(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 = 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 = 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 = ((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 = ((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 new file mode 100644 index 0000000..ad4286d --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/MassStorage.h @@ -0,0 +1,344 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 + + #if defined(__INCLUDE_FROM_MASSSTORAGE_HOST_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 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 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. */ + }; + + /* 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. + * + * \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes. + * + * \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. + * + * \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 true if the device should be locked from removal, 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); + 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 DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); + + 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); + #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 new file mode 100644 index 0000000..ddcece8 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/Printer.c @@ -0,0 +1,392 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_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_DESCRIPTOR_DIR_IN) + DataINEndpoint = EndpointData; + else + DataOUTEndpoint = EndpointData; + } + + for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) + { + if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, + DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, + PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, + DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, + PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + } + + 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; + + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE), + .bRequest = REQ_SetInterface, + .wValue = PRNTInterfaceInfo->State.AlternateSetting, + .wIndex = PRNTInterfaceInfo->State.InterfaceNumber, + .wLength = 0, + }; + + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != 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_Byte(Data); + Pipe_Freeze(); + + return PIPE_READYWAIT_NoError; +} + +uint8_t PRNT_Host_SendString(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, NO_STREAM_CALLBACK)) != 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_Byte(); + + 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 = SwapEndian_16(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 new file mode 100644 index 0000000..cc77e96 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/Printer.h @@ -0,0 +1,282 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 + + #if defined(__INCLUDE_FROM_PRINTER_HOST_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 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 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. */ + }; + + /* Function Prototypes: */ + /** 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); + + /** 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. + * + * \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes. + * + * \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); + + /** 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 + * 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 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_SendString(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_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* const CurrentDescriptor) 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 new file mode 100644 index 0000000..11f7d9e --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/RNDIS.c @@ -0,0 +1,480 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_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_DESCRIPTOR_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++) + { + if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, + DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, + RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, + DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, + RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, + NotificationEndpoint->EndpointAddress, NotificationEndpoint->EndpointSize, + RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + Pipe_SetInterruptPeriod(NotificationEndpoint->PollingIntervalMS); + + RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; + } + } + + 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 = REMOTE_NDIS_KEEPALIVE_MSG; + KeepAliveMessage.MessageLength = sizeof(RNDIS_KeepAlive_Message_t); + KeepAliveMessage.RequestId = 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 = REMOTE_NDIS_INITIALIZE_MSG; + InitMessage.MessageLength = sizeof(RNDIS_Initialize_Message_t); + InitMessage.RequestId = RNDISInterfaceInfo->State.RequestID++; + + InitMessage.MajorVersion = REMOTE_NDIS_VERSION_MAJOR; + InitMessage.MinorVersion = REMOTE_NDIS_VERSION_MINOR; + InitMessage.MaxTransferSize = 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 != REMOTE_NDIS_STATUS_SUCCESS) + return RNDIS_COMMAND_FAILED; + + RNDISInterfaceInfo->State.DeviceMaxPacketSize = 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 = REMOTE_NDIS_SET_MSG; + SetMessageData.SetMessage.MessageLength = sizeof(RNDIS_Set_Message_t) + Length; + SetMessageData.SetMessage.RequestId = RNDISInterfaceInfo->State.RequestID++; + + SetMessageData.SetMessage.Oid = Oid; + SetMessageData.SetMessage.InformationBufferLength = Length; + SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t)); + SetMessageData.SetMessage.DeviceVcHandle = 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 != REMOTE_NDIS_STATUS_SUCCESS) + return RNDIS_COMMAND_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 = REMOTE_NDIS_QUERY_MSG; + QueryMessage.MessageLength = sizeof(RNDIS_Query_Message_t); + QueryMessage.RequestId = RNDISInterfaceInfo->State.RequestID++; + + QueryMessage.Oid = Oid; + QueryMessage.InformationBufferLength = 0; + QueryMessage.InformationBufferOffset = 0; + QueryMessage.DeviceVcHandle = 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 != REMOTE_NDIS_STATUS_SUCCESS) + return RNDIS_COMMAND_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), + NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError) + { + return ErrorCode; + } + + *PacketLength = (uint16_t)DeviceMessage.DataLength; + + Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)), + NO_STREAM_CALLBACK); + + Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK); + + 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 = REMOTE_NDIS_PACKET_MSG; + DeviceMessage.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength); + DeviceMessage.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)); + DeviceMessage.DataLength = PacketLength; + + Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber); + Pipe_Unfreeze(); + + if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t), + NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError) + { + return ErrorCode; + } + + Pipe_Write_Stream_LE(Buffer, PacketLength, NO_STREAM_CALLBACK); + 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 new file mode 100644 index 0000000..611e59e --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/RNDIS.h @@ -0,0 +1,290 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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" + + #include + #include + + /* 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 + + #if defined(__INCLUDE_FROM_RNDIS_HOST_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 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. */ + }; + + /* Macros: */ + /** Additional error code for RNDIS functions when a device returns a logical command failure. */ + #define RNDIS_COMMAND_FAILED 0xC0 + + /* 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. + * + * \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes. + * + * \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_COMMAND_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); + + /** Initialises 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_COMMAND_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_COMMAND_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_COMMAND_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 true if a packet is waiting to be read in by the host, 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); + 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_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor) 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 new file mode 100644 index 0000000..7b31e10 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/StillImage.c @@ -0,0 +1,443 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../../HighLevel/USBMode.h" +#if defined(USB_CAN_BE_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)) + { + 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_DESCRIPTOR_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++) + { + if (PipeNum == SIInterfaceInfo->Config.DataINPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, + DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, + SIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + SIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; + } + else if (PipeNum == SIInterfaceInfo->Config.DataOUTPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, + DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, + SIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + + SIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; + } + else if (PipeNum == SIInterfaceInfo->Config.EventsPipeNumber) + { + Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, + EventsEndpoint->EndpointAddress, EventsEndpoint->EndpointSize, + SIInterfaceInfo->Config.EventsPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); + Pipe_SetInterruptPeriod(EventsEndpoint->PollingIntervalMS); + + SIInterfaceInfo->State.EventsPipeSize = EventsEndpoint->EndpointSize; + } + } + + 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 = SIInterfaceInfo->State.TransactionID++; + + Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); + Pipe_Unfreeze(); + + if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != 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, NO_STREAM_CALLBACK)) != 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_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber); + return PIPE_RWSTREAM_PipeStalled; + } + + Pipe_Freeze(); + Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); + Pipe_Unfreeze(); + + if (Pipe_IsStalled()) + { + USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber); + return PIPE_RWSTREAM_PipeStalled; + } + + if (USB_HostState == HOST_STATE_Unattached) + return PIPE_RWSTREAM_DeviceDisconnected; + } + + Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK); + + if (PIMAHeader->Type == PIMA_CONTAINER_ResponseBlock) + { + uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0)); + + if (ParamBytes) + Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK); + + 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, NO_STREAM_CALLBACK); + + 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, NO_STREAM_CALLBACK); + + 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), NO_STREAM_CALLBACK); + + 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 HOST_SENDCONTROL_DeviceDisconnected; + + uint8_t ErrorCode; + + SIInterfaceInfo->State.TransactionID = 0; + SIInterfaceInfo->State.IsSessionOpen = false; + + PIMA_Container_t PIMABlock = (PIMA_Container_t) + { + .DataLength = PIMA_COMMAND_SIZE(1), + .Type = PIMA_CONTAINER_CommandBlock, + .Code = 0x1002, + .Params = {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 != PIMA_CONTAINER_ResponseBlock) || (PIMABlock.Code != 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 HOST_SENDCONTROL_DeviceDisconnected; + + uint8_t ErrorCode; + + PIMA_Container_t PIMABlock = (PIMA_Container_t) + { + .DataLength = PIMA_COMMAND_SIZE(1), + .Type = PIMA_CONTAINER_CommandBlock, + .Code = 0x1003, + .Params = {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 != PIMA_CONTAINER_ResponseBlock) || (PIMABlock.Code != 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 HOST_SENDCONTROL_DeviceDisconnected; + + uint8_t ErrorCode; + + PIMA_Container_t PIMABlock = (PIMA_Container_t) + { + .DataLength = PIMA_COMMAND_SIZE(TotalParams), + .Type = PIMA_CONTAINER_CommandBlock, + .Code = 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 HOST_SENDCONTROL_DeviceDisconnected; + + if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError) + return ErrorCode; + + if ((PIMABlock.Type != PIMA_CONTAINER_ResponseBlock) || (PIMABlock.Code != 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 new file mode 100644 index 0000000..5a6de02 --- /dev/null +++ b/LUFA/Drivers/USB/Class/Host/StillImage.h @@ -0,0 +1,331 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 + + #if defined(__INCLUDE_FROM_STILLIMAGE_HOST_C) && defined(NO_STREAM_CALLBACKS) + #error The NO_STREAM_CALLBACKS compile time option cannot be used in projects using the library Class drivers. + #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 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 Mass Storage 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. + */ + }; + + /* 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. + * + * \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other + * interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes + * within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes. + * + * \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 to 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 PIMA 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 true if an event is waiting to be read, 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); + 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_NON_NULL_PTR_ARG(1); + static uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor) 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 new file mode 100644 index 0000000..d26c5f7 --- /dev/null +++ b/LUFA/Drivers/USB/Class/MIDI.h @@ -0,0 +1,83 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../HighLevel/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/MassStorage.h b/LUFA/Drivers/USB/Class/MassStorage.h new file mode 100644 index 0000000..c4b03dd --- /dev/null +++ b/LUFA/Drivers/USB/Class/MassStorage.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../HighLevel/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/Printer.h b/LUFA/Drivers/USB/Class/Printer.h new file mode 100644 index 0000000..2d5504f --- /dev/null +++ b/LUFA/Drivers/USB/Class/Printer.h @@ -0,0 +1,77 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../HighLevel/USBMode.h" + + #if defined(USB_CAN_BE_HOST) + #include "Host/Printer.h" + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/Class/RNDIS.h b/LUFA/Drivers/USB/Class/RNDIS.h new file mode 100644 index 0000000..98dbda4 --- /dev/null +++ b/LUFA/Drivers/USB/Class/RNDIS.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../HighLevel/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/StillImage.h b/LUFA/Drivers/USB/Class/StillImage.h new file mode 100644 index 0000000..dd1b16b --- /dev/null +++ b/LUFA/Drivers/USB/Class/StillImage.h @@ -0,0 +1,75 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief 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 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 "../HighLevel/USBMode.h" + + #if defined(USB_CAN_BE_HOST) + #include "Host/StillImage.h" + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c new file mode 100644 index 0000000..977d9e1 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c @@ -0,0 +1,142 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "ConfigDescriptor.h" + +#if defined(USB_CAN_BE_HOST) +uint8_t USB_Host_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const ConfigSizePtr, + void* BufferPtr, uint16_t BufferSize) +{ + uint8_t ErrorCode; + uint8_t ConfigHeader[sizeof(USB_Descriptor_Configuration_Header_t)]; + + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), + .bRequest = REQ_GetDescriptor, + .wValue = ((DTYPE_Configuration << 8) | (ConfigNumber - 1)), + .wIndex = 0, + .wLength = sizeof(USB_Descriptor_Configuration_Header_t), + }; + + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful) + return ErrorCode; + + *ConfigSizePtr = DESCRIPTOR_PCAST(ConfigHeader, USB_Descriptor_Configuration_Header_t)->TotalConfigurationSize; + + if (*ConfigSizePtr > BufferSize) + return HOST_GETCONFIG_BuffOverflow; + + USB_ControlRequest.wLength = *ConfigSizePtr; + + if ((ErrorCode = USB_Host_SendControlRequest(BufferPtr)) != HOST_SENDCONTROL_Successful) + return ErrorCode; + + if (DESCRIPTOR_TYPE(BufferPtr) != DTYPE_Configuration) + return HOST_GETCONFIG_InvalidData; + + return HOST_GETCONFIG_Successful; +} +#endif + +void USB_GetNextDescriptorOfType(uint16_t* const BytesRem, + void** const CurrConfigLoc, + const uint8_t Type) +{ + while (*BytesRem) + { + USB_GetNextDescriptor(BytesRem, CurrConfigLoc); + + if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) + return; + } +} + +void USB_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem, + void** const CurrConfigLoc, + const uint8_t Type, + const uint8_t BeforeType) +{ + while (*BytesRem) + { + USB_GetNextDescriptor(BytesRem, CurrConfigLoc); + + if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) + { + return; + } + else if (DESCRIPTOR_TYPE(*CurrConfigLoc) == BeforeType) + { + *BytesRem = 0; + return; + } + } +} + +void USB_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem, + void** const CurrConfigLoc, + const uint8_t Type, + const uint8_t AfterType) +{ + USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, AfterType); + + if (*BytesRem) + USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, Type); +} + +uint8_t USB_GetNextDescriptorComp(uint16_t* const BytesRem, void** const CurrConfigLoc, ConfigComparatorPtr_t const ComparatorRoutine) +{ + uint8_t ErrorCode; + + while (*BytesRem) + { + uint8_t* PrevDescLoc = *CurrConfigLoc; + uint16_t PrevBytesRem = *BytesRem; + + USB_GetNextDescriptor(BytesRem, CurrConfigLoc); + + if ((ErrorCode = ComparatorRoutine(*CurrConfigLoc)) != DESCRIPTOR_SEARCH_NotFound) + { + if (ErrorCode == DESCRIPTOR_SEARCH_Fail) + { + *CurrConfigLoc = PrevDescLoc; + *BytesRem = PrevBytesRem; + } + + return ErrorCode; + } + } + + return DESCRIPTOR_SEARCH_COMP_EndOfDescriptor; +} + diff --git a/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h new file mode 100644 index 0000000..dc33391 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.h @@ -0,0 +1,287 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Configuration descriptor parser API. + * + * This section of the library gives a friendly API which can be used in host applications to easily + * parse an attached device's configuration descriptor so that endpoint, interface and other descriptor + * data can be extracted and used as needed. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_Descriptors + * @defgroup Group_ConfigDescriptorParser Configuration Descriptor Parser + * + * Functions, macros, variables, enums and types related to the parsing of Configuration Descriptors. + * + * @{ + */ + +#ifndef __CONFIGDESCRIPTOR_H__ +#define __CONFIGDESCRIPTOR_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + #include "HostStandardReq.h" + #include "USBMode.h" + #include "StdDescriptors.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for determining the type of an endpoint from an endpoint descriptor. This should then be compared + * with the EP_TYPE_* masks to determine the exact type of the endpoint. + */ + #define EP_TYPE_MASK 0x03 + + /** Casts a pointer to a descriptor inside the configuration descriptor into a pointer to the given + * descriptor type. + * + * Usage Example: + * \code + * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header + * USB_Descriptor_Configuration_Header_t* ConfigHeaderPtr = DESCRIPTOR_PCAST(CurrDescriptor, + * USB_Descriptor_Configuration_Header_t); + * + * // Can now access elements of the configuration header struct using the -> indirection operator + * \endcode + */ + #define DESCRIPTOR_PCAST(DescriptorPtr, Type) ((Type*)(DescriptorPtr)) + + /** Casts a pointer to a descriptor inside the configuration descriptor into the given descriptor + * type (as an actual struct instance rather than a pointer to a struct). + * + * Usage Example: + * \code + * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header + * USB_Descriptor_Configuration_Header_t ConfigHeader = DESCRIPTOR_CAST(CurrDescriptor, + * USB_Descriptor_Configuration_Header_t); + * + * // Can now access elements of the configuration header struct using the . operator + * \endcode + */ + #define DESCRIPTOR_CAST(DescriptorPtr, Type) (*DESCRIPTOR_PCAST(DescriptorPtr, Type)) + + /** Returns the descriptor's type, expressed as the 8-bit type value in the header of the descriptor. + * This value's meaning depends on the descriptor's placement in the descriptor, but standard type + * values can be accessed in the \ref USB_DescriptorTypes_t enum. + */ + #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_PCAST(DescriptorPtr, USB_Descriptor_Header_t)->Type + + /** Returns the descriptor's size, expressed as the 8-bit value indicating the number of bytes. */ + #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_PCAST(DescriptorPtr, USB_Descriptor_Header_t)->Size + + /* Type Defines: */ + /** Type define for a Configuration Descriptor comparator function (function taking a pointer to an array + * of type void, returning a uint8_t value). + * + * \see \ref USB_GetNextDescriptorComp function for more details. + */ + typedef uint8_t (* ConfigComparatorPtr_t)(void*); + + /* Enums: */ + /** Enum for the possible return codes of the \ref USB_Host_GetDeviceConfigDescriptor() function. */ + enum USB_Host_GetConfigDescriptor_ErrorCodes_t + { + HOST_GETCONFIG_Successful = 0, /**< No error occurred while retrieving the configuration descriptor. */ + HOST_GETCONFIG_DeviceDisconnect = 1, /**< The attached device was disconnected while retrieving the configuration + * descriptor. + */ + HOST_GETCONFIG_PipeError = 2, /**< An error occurred in the pipe while sending the request. */ + HOST_GETCONFIG_SetupStalled = 3, /**< The attached device stalled the request to retrieve the configuration + * descriptor. + */ + HOST_GETCONFIG_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */ + HOST_GETCONFIG_BuffOverflow = 5, /**< The device's configuration descriptor is too large to fit into the allocated + * buffer. + */ + HOST_GETCONFIG_InvalidData = 6, /**< The device returned invalid configuration descriptor data. */ + }; + + /** Enum for return values of a descriptor comparator function. */ + enum DSearch_Return_ErrorCodes_t + { + DESCRIPTOR_SEARCH_Found = 0, /**< Current descriptor matches comparator criteria. */ + DESCRIPTOR_SEARCH_Fail = 1, /**< No further descriptor could possibly match criteria, fail the search. */ + DESCRIPTOR_SEARCH_NotFound = 2, /**< Current descriptor does not match comparator criteria. */ + }; + + /** Enum for return values of \ref USB_GetNextDescriptorComp(). */ + enum DSearch_Comp_Return_ErrorCodes_t + { + DESCRIPTOR_SEARCH_COMP_Found = 0, /**< Configuration descriptor now points to descriptor which matches + * search criteria of the given comparator function. */ + DESCRIPTOR_SEARCH_COMP_Fail = 1, /**< Comparator function returned Descriptor_Search_Fail. */ + DESCRIPTOR_SEARCH_COMP_EndOfDescriptor = 2, /**< End of configuration descriptor reached before match found. */ + }; + + /* Function Prototypes: */ + /** Retrieves the configuration descriptor data from an attached device via a standard request into a buffer, + * including validity and size checking to prevent a buffer overflow. + * + * \param[in] ConfigNumber Device configuration descriptor number to fetch from the device (usually set to 1 for + * single configuration devices). + * \param[in,out] ConfigSizePtr Pointer to a uint16_t for storing the retrieved configuration descriptor size. + * \param[out] BufferPtr Pointer to the buffer for storing the configuration descriptor data. + * \param[out] BufferSize Size of the allocated buffer where the configuration descriptor is to be stored. + * + * \return A value from the \ref USB_Host_GetConfigDescriptor_ErrorCodes_t enum. + */ + uint8_t USB_Host_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const ConfigSizePtr, void* BufferPtr, + uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3); + + /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value. + * The bytes remaining value is automatically decremented. + * + * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor. + * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor. + * \param[in] Type Descriptor type value to search for. + */ + void USB_GetNextDescriptorOfType(uint16_t* const BytesRem, + void** const CurrConfigLoc, + const uint8_t Type) + ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value, + * which must come before a descriptor of the second given type value. If the BeforeType type + * descriptor is reached first, the number of bytes remaining to process is set to zero and the + * function exits. The bytes remaining value is automatically decremented. + * + * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor. + * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor. + * \param[in] Type Descriptor type value to search for. + * \param[in] BeforeType Descriptor type value which must not be reached before the given Type descriptor. + */ + void USB_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem, + void** const CurrConfigLoc, + const uint8_t Type, + const uint8_t BeforeType) + ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value, + * which must come after a descriptor of the second given type value. The bytes remaining value is + * automatically decremented. + * + * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor. + * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor. + * \param[in] Type Descriptor type value to search for. + * \param[in] AfterType Descriptor type value which must be reached before the given Type descriptor. + */ + void USB_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem, + void** const CurrConfigLoc, + const uint8_t Type, + const uint8_t AfterType) + ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + + /** Searches for the next descriptor in the given configuration descriptor using a pre-made comparator + * function. The routine updates the position and remaining configuration descriptor bytes values + * automatically. If a comparator routine fails a search, the descriptor pointer is retreated back + * so that the next descriptor search invocation will start from the descriptor which first caused the + * original search to fail. This behaviour allows for one comparator to be used immediately after another + * has failed, starting the second search from the descriptor which failed the first. + * + * Comparator functions should be standard functions which accept a pointer to the header of the current + * descriptor inside the configuration descriptor which is being compared, and should return a value from + * the \ref DSearch_Return_ErrorCodes_t enum as a uint8_t value. + * + * \note This function is available in USB Host mode only. + * + * \param[in,out] BytesRem Pointer to an int storing the remaining bytes in the configuration descriptor. + * \param[in,out] CurrConfigLoc Pointer to the current position in the configuration descriptor. + * \param[in] ComparatorRoutine Name of the comparator search function to use on the configuration descriptor. + * + * \return Value of one of the members of the \ref DSearch_Comp_Return_ErrorCodes_t enum. + * + * Usage Example: + * \code + * uint8_t EndpointSearcher(void* CurrentDescriptor); // Comparator Prototype + * + * uint8_t EndpointSearcher(void* CurrentDescriptor) + * { + * if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) + * return DESCRIPTOR_SEARCH_Found; + * else + * return DESCRIPTOR_SEARCH_NotFound; + * } + * + * //... + * // After retrieving configuration descriptor: + * if (USB_Host_GetNextDescriptorComp(&BytesRemaining, &CurrentConfigLoc, EndpointSearcher) == + * Descriptor_Search_Comp_Found) + * { + * // Do something with the endpoint descriptor + * } + * \endcode + */ + uint8_t USB_GetNextDescriptorComp(uint16_t* const BytesRem, + void** const CurrConfigLoc, + ConfigComparatorPtr_t const ComparatorRoutine); + + /* Inline Functions: */ + /** Skips over the current sub-descriptor inside the configuration descriptor, so that the pointer then + points to the next sub-descriptor. The bytes remaining value is automatically decremented. + * + * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor. + * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor. + */ + static inline void USB_GetNextDescriptor(uint16_t* const BytesRem, + void** CurrConfigLoc) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2); + static inline void USB_GetNextDescriptor(uint16_t* const BytesRem, + void** CurrConfigLoc) + { + uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).Size; + + *CurrConfigLoc = ((uint8_t*)*CurrConfigLoc) + CurrDescriptorSize; + *BytesRem -= CurrDescriptorSize; + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/DeviceStandardReq.c b/LUFA/Drivers/USB/HighLevel/DeviceStandardReq.c new file mode 100644 index 0000000..a27151e --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/DeviceStandardReq.c @@ -0,0 +1,382 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "USBMode.h" + +#if defined(USB_CAN_BE_DEVICE) + +#define __INCLUDE_FROM_DEVICESTDREQ_C +#include "DeviceStandardReq.h" + +uint8_t USB_ConfigurationNumber; + +#if !defined(NO_DEVICE_SELF_POWER) +bool USB_CurrentlySelfPowered; +#endif + +#if !defined(NO_DEVICE_REMOTE_WAKEUP) +bool USB_RemoteWakeupEnabled; +#endif + +void USB_Device_ProcessControlRequest(void) +{ + uint8_t* RequestHeader = (uint8_t*)&USB_ControlRequest; + + for (uint8_t RequestHeaderByte = 0; RequestHeaderByte < sizeof(USB_Request_Header_t); RequestHeaderByte++) + *(RequestHeader++) = Endpoint_Read_Byte(); + + EVENT_USB_Device_ControlRequest(); + + if (Endpoint_IsSETUPReceived()) + { + uint8_t bmRequestType = USB_ControlRequest.bmRequestType; + + switch (USB_ControlRequest.bRequest) + { + case REQ_GetStatus: + if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) || + (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT))) + { + USB_Device_GetStatus(); + } + + break; + case REQ_ClearFeature: + case REQ_SetFeature: + if ((bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) || + (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT))) + { + USB_Device_ClearSetFeature(); + } + + break; + case REQ_SetAddress: + if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) + USB_Device_SetAddress(); + + break; + case REQ_GetDescriptor: + if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) || + (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE))) + { + USB_Device_GetDescriptor(); + } + + break; + case REQ_GetConfiguration: + if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) + USB_Device_GetConfiguration(); + + break; + case REQ_SetConfiguration: + if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) + USB_Device_SetConfiguration(); + + break; + } + } + + if (Endpoint_IsSETUPReceived()) + { + Endpoint_StallTransaction(); + Endpoint_ClearSETUP(); + } +} + +static void USB_Device_SetAddress(void) +{ + uint8_t DeviceAddress = (USB_ControlRequest.wValue & 0x7F); + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Endpoint_ClearSETUP(); + + Endpoint_ClearStatusStage(); + + while (!(Endpoint_IsINReady())); + + USB_DeviceState = (DeviceAddress) ? DEVICE_STATE_Addressed : DEVICE_STATE_Default; + + USB_Device_SetDeviceAddress(DeviceAddress); + } +} + +static void USB_Device_SetConfiguration(void) +{ + #if defined(FIXED_NUM_CONFIGURATIONS) + if ((uint8_t)USB_ControlRequest.wValue > FIXED_NUM_CONFIGURATIONS) + return; + #else + USB_Descriptor_Device_t* DevDescriptorPtr; + + #if defined(USE_FLASH_DESCRIPTORS) + #define MemoryAddressSpace MEMSPACE_FLASH + #elif defined(USE_EEPROM_DESCRIPTORS) + #define MemoryAddressSpace MEMSPACE_EEPROM + #elif defined(USE_SRAM_DESCRIPTORS) + #define MemoryAddressSpace MEMSPACE_SRAM + #else + uint8_t MemoryAddressSpace; + #endif + + if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr + #if !defined(USE_FLASH_DESCRIPTORS) && !defined(USE_EEPROM_DESCRIPTORS) && !defined(USE_RAM_DESCRIPTORS) + , &MemoryAddressSpace + #endif + ) == NO_DESCRIPTOR) + { + return; + } + + if (MemoryAddressSpace == MEMSPACE_FLASH) + { + if (((uint8_t)USB_ControlRequest.wValue > pgm_read_byte(&DevDescriptorPtr->NumberOfConfigurations))) + return; + } + else if (MemoryAddressSpace == MEMSPACE_EEPROM) + { + if (((uint8_t)USB_ControlRequest.wValue > eeprom_read_byte(&DevDescriptorPtr->NumberOfConfigurations))) + return; + } + else + { + if ((uint8_t)USB_ControlRequest.wValue > DevDescriptorPtr->NumberOfConfigurations) + return; + } + #endif + + Endpoint_ClearSETUP(); + + USB_ConfigurationNumber = (uint8_t)USB_ControlRequest.wValue; + + Endpoint_ClearStatusStage(); + + if (USB_ConfigurationNumber) + USB_DeviceState = DEVICE_STATE_Configured; + else + USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Configured : DEVICE_STATE_Powered; + + EVENT_USB_Device_ConfigurationChanged(); +} + +static void USB_Device_GetConfiguration(void) +{ + Endpoint_ClearSETUP(); + + Endpoint_Write_Byte(USB_ConfigurationNumber); + Endpoint_ClearIN(); + + Endpoint_ClearStatusStage(); +} + +#if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR) +static void USB_Device_GetInternalSerialDescriptor(void) +{ + struct + { + USB_Descriptor_Header_t Header; + wchar_t UnicodeString[20]; + } SignatureDescriptor; + + SignatureDescriptor.Header.Type = DTYPE_String; + SignatureDescriptor.Header.Size = sizeof(SignatureDescriptor); + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + uint8_t SigReadAddress = 0x0E; + + for (uint8_t SerialCharNum = 0; SerialCharNum < 20; SerialCharNum++) + { + uint8_t SerialByte = boot_signature_byte_get(SigReadAddress); + + if (SerialCharNum & 0x01) + { + SerialByte >>= 4; + SigReadAddress++; + } + + SerialByte &= 0x0F; + + SignatureDescriptor.UnicodeString[SerialCharNum] = (SerialByte >= 10) ? + (('A' - 10) + SerialByte) : ('0' + SerialByte); + } + } + + Endpoint_ClearSETUP(); + + Endpoint_Write_Control_Stream_LE(&SignatureDescriptor, sizeof(SignatureDescriptor)); + + Endpoint_ClearOUT(); +} +#endif + +static void USB_Device_GetDescriptor(void) +{ + const void* DescriptorPointer; + uint16_t DescriptorSize; + + #if !defined(USE_FLASH_DESCRIPTORS) && !defined(USE_EEPROM_DESCRIPTORS) && !defined(USE_RAM_DESCRIPTORS) + uint8_t DescriptorAddressSpace; + #endif + + #if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR) + if (USB_ControlRequest.wValue == ((DTYPE_String << 8) | USE_INTERNAL_SERIAL)) + { + USB_Device_GetInternalSerialDescriptor(); + return; + } + #endif + + if ((DescriptorSize = CALLBACK_USB_GetDescriptor(USB_ControlRequest.wValue, USB_ControlRequest.wIndex, + &DescriptorPointer + #if !defined(USE_FLASH_DESCRIPTORS) && !defined(USE_EEPROM_DESCRIPTORS) && !defined(USE_RAM_DESCRIPTORS) + , &DescriptorAddressSpace + #endif + )) == NO_DESCRIPTOR) + { + return; + } + + Endpoint_ClearSETUP(); + + #if defined(USE_RAM_DESCRIPTORS) + Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize); + #elif defined(USE_EEPROM_DESCRIPTORS) + Endpoint_Write_Control_EStream_LE(DescriptorPointer, DescriptorSize); + #elif defined(USE_FLASH_DESCRIPTORS) + Endpoint_Write_Control_PStream_LE(DescriptorPointer, DescriptorSize); + #else + if (DescriptorAddressSpace == MEMSPACE_FLASH) + Endpoint_Write_Control_PStream_LE(DescriptorPointer, DescriptorSize); + else if (DescriptorAddressSpace == MEMSPACE_EEPROM) + Endpoint_Write_Control_EStream_LE(DescriptorPointer, DescriptorSize); + else + Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize); + #endif + + Endpoint_ClearOUT(); +} + +static void USB_Device_GetStatus(void) +{ + uint8_t CurrentStatus = 0; + + switch (USB_ControlRequest.bmRequestType) + { + #if !defined(NO_DEVICE_SELF_POWER) || !defined(NO_DEVICE_REMOTE_WAKEUP) + case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE): + #if !defined(NO_DEVICE_SELF_POWER) + if (USB_CurrentlySelfPowered) + CurrentStatus |= FEATURE_SELFPOWERED_ENABLED; + #endif + + #if !defined(NO_DEVICE_REMOTE_WAKEUP) + if (USB_RemoteWakeupEnabled) + CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED; + #endif + break; + #endif + #if !defined(CONTROL_ONLY_DEVICE) + case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT): + Endpoint_SelectEndpoint((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK); + + CurrentStatus = Endpoint_IsStalled(); + + Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); + + break; + #endif + default: + return; + } + + Endpoint_ClearSETUP(); + + Endpoint_Write_Word_LE(CurrentStatus); + Endpoint_ClearIN(); + + Endpoint_ClearStatusStage(); +} + +static void USB_Device_ClearSetFeature(void) +{ + switch (USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) + { + #if !defined(NO_DEVICE_REMOTE_WAKEUP) + case REQREC_DEVICE: + if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_DeviceRemoteWakeup) + USB_RemoteWakeupEnabled = (USB_ControlRequest.bRequest == REQ_SetFeature); + else + return; + + break; + #endif + #if !defined(CONTROL_ONLY_DEVICE) + case REQREC_ENDPOINT: + if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_EndpointHalt) + { + uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK); + + if (EndpointIndex == ENDPOINT_CONTROLEP) + return; + + Endpoint_SelectEndpoint(EndpointIndex); + + if (Endpoint_IsEnabled()) + { + if (USB_ControlRequest.bRequest == REQ_SetFeature) + { + Endpoint_StallTransaction(); + } + else + { + Endpoint_ClearStall(); + Endpoint_ResetFIFO(EndpointIndex); + Endpoint_ResetDataToggle(); + } + } + } + + break; + #endif + default: + return; + } + + Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); + + Endpoint_ClearSETUP(); + + Endpoint_ClearStatusStage(); +} + +#endif + diff --git a/LUFA/Drivers/USB/HighLevel/DeviceStandardReq.h b/LUFA/Drivers/USB/HighLevel/DeviceStandardReq.h new file mode 100644 index 0000000..df5a79a --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/DeviceStandardReq.h @@ -0,0 +1,165 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB device standard request management. + * + * This file contains the function prototypes necessary for the processing of incoming standard control requests + * when the library is in USB device mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +#ifndef __DEVICESTDREQ_H__ +#define __DEVICESTDREQ_H__ + + /* Includes: */ + #include + #include + #include + #include + #include + #include + + #include "StdDescriptors.h" + #include "Events.h" + #include "StdRequestType.h" + #include "USBTask.h" + #include "../LowLevel/USBController.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + #if defined(USE_SINGLE_DEVICE_CONFIGURATION) + #define FIXED_NUM_CONFIGURATIONS 1 + #endif + + /* Enums: */ + #if !defined(USE_FLASH_DESCRIPTORS) && !defined(USE_EEPROM_DESCRIPTORS) && !defined(USE_RAM_DESCRIPTORS) + /** Enum for the possible descriptor memory spaces, for the MemoryAddressSpace of the + * \ref CALLBACK_USB_GetDescriptor() function. This can be used when none of the USE_*_DESCRIPTORS + * compile time options are used, to indicate in which memory space the descriptor is stored. + * + * \ingroup Group_Device + */ + enum USB_DescriptorMemorySpaces_t + { + MEMSPACE_FLASH = 0, /**< Indicates the requested descriptor is located in FLASH memory. */ + MEMSPACE_EEPROM = 1, /**< Indicates the requested descriptor is located in EEPROM memory. */ + MEMSPACE_RAM = 2, /**< Indicates the requested descriptor is located in RAM memory. */ + }; + #endif + + /* Global Variables: */ + /** Indicates the currently set configuration number of the device. USB devices may have several + * different configurations which the host can select between; this indicates the currently selected + * value, or 0 if no configuration has been selected. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + * + * \ingroup Group_Device + */ + extern uint8_t USB_ConfigurationNumber; + + #if !defined(NO_DEVICE_REMOTE_WAKEUP) + /** Indicates if the host is currently allowing the device to issue remote wakeup events. If this + * flag is cleared, the device should not issue remote wakeup events to the host. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + * \n\n + * + * \note To reduce FLASH usage of the compiled applications where Remote Wakeup is not supported, + * this global and the underlying management code can be disabled by defining the + * NO_DEVICE_REMOTE_WAKEUP token in the project makefile and passing it to the compiler via + * the -D switch. + * + * \ingroup Group_Device + */ + extern bool USB_RemoteWakeupEnabled; + #endif + + #if !defined(NO_DEVICE_SELF_POWER) + /** Indicates if the device is currently being powered by its own power supply, rather than being + * powered by the host's USB supply. This flag should remain cleared if the device does not + * support self powered mode, as indicated in the device descriptors. + * + * \ingroup Group_Device + */ + extern bool USB_CurrentlySelfPowered; + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + #if defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS) + #error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive. + #elif defined(USE_RAM_DESCRIPTORS) && defined(USE_FLASH_DESCRIPTORS) + #error USE_RAM_DESCRIPTORS and USE_FLASH_DESCRIPTORS are mutually exclusive. + #elif defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS) + #error USE_FLASH_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive. + #elif defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS) && defined(USE_RAM_DESCRIPTORS) + #error Only one of the USE_*_DESCRIPTORS modes should be selected. + #endif + + /* Function Prototypes: */ + void USB_Device_ProcessControlRequest(void); + + #if defined(__INCLUDE_FROM_DEVICESTDREQ_C) + static void USB_Device_SetAddress(void); + static void USB_Device_SetConfiguration(void); + static void USB_Device_GetConfiguration(void); + static void USB_Device_GetDescriptor(void); + static void USB_Device_GetStatus(void); + static void USB_Device_ClearSetFeature(void); + + #if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR) + static void USB_Device_GetInternalSerialDescriptor(void); + #endif + #endif + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + diff --git a/LUFA/Drivers/USB/HighLevel/EndpointStream.c b/LUFA/Drivers/USB/HighLevel/EndpointStream.c new file mode 100644 index 0000000..7e92b7e --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/EndpointStream.c @@ -0,0 +1,233 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "USBMode.h" + +#if defined(USB_CAN_BE_DEVICE) + +#include "EndpointStream.h" + +#if !defined(CONTROL_ONLY_DEVICE) +uint8_t Endpoint_Discard_Stream(uint16_t Length + __CALLBACK_PARAM) +{ + uint8_t ErrorCode; + + if ((ErrorCode = Endpoint_WaitUntilReady())) + return ErrorCode; + + #if defined(FAST_STREAM_TRANSFERS) + uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07); + + if (Length >= 8) + { + Length -= BytesRemToAlignment; + + switch (BytesRemToAlignment) + { + default: + do + { + if (!(Endpoint_IsReadWriteAllowed())) + { + Endpoint_ClearOUT(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return ENDPOINT_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Endpoint_WaitUntilReady())) + return ErrorCode; + } + + Length -= 8; + + Endpoint_Discard_Byte(); + case 7: Endpoint_Discard_Byte(); + case 6: Endpoint_Discard_Byte(); + case 5: Endpoint_Discard_Byte(); + case 4: Endpoint_Discard_Byte(); + case 3: Endpoint_Discard_Byte(); + case 2: Endpoint_Discard_Byte(); + case 1: Endpoint_Discard_Byte(); + } while (Length >= 8); + } + } + #endif + + while (Length) + { + if (!(Endpoint_IsReadWriteAllowed())) + { + Endpoint_ClearOUT(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return ENDPOINT_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Endpoint_WaitUntilReady())) + return ErrorCode; + } + else + { + Endpoint_Discard_Byte(); + Length--; + } + } + + return ENDPOINT_RWSTREAM_NoError; +} + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_LE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(*((uint8_t*)BufferPtr++)) +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_LE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr++)) +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_LE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr++)) +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_BE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(*((uint8_t*)BufferPtr--)) +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_BE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr--)) +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_BE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr--)) +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_LE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *((uint8_t*)BufferPtr++) = Endpoint_Read_Byte() +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_LE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte((uint8_t*)BufferPtr++, Endpoint_Read_Byte()) +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_BE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *((uint8_t*)BufferPtr--) = Endpoint_Read_Byte() +#include "Template/Template_Endpoint_RW.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_BE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte((uint8_t*)BufferPtr--, Endpoint_Read_Byte()) +#include "Template/Template_Endpoint_RW.c" + +#endif + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_LE +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(*((uint8_t*)BufferPtr++)) +#include "Template/Template_Endpoint_Control_W.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_LE +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr++)) +#include "Template/Template_Endpoint_Control_W.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_LE +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr++)) +#include "Template/Template_Endpoint_Control_W.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_BE +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(*((uint8_t*)BufferPtr--)) +#include "Template/Template_Endpoint_Control_W.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_BE +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr--)) +#include "Template/Template_Endpoint_Control_W.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_BE +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr--)) +#include "Template/Template_Endpoint_Control_W.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_LE +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *((uint8_t*)BufferPtr++) = Endpoint_Read_Byte() +#include "Template/Template_Endpoint_Control_R.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_LE +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte((uint8_t*)BufferPtr++, Endpoint_Read_Byte()) +#include "Template/Template_Endpoint_Control_R.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_BE +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *((uint8_t*)BufferPtr--) = Endpoint_Read_Byte() +#include "Template/Template_Endpoint_Control_R.c" + +#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_BE +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte((uint8_t*)BufferPtr--, Endpoint_Read_Byte()) +#include "Template/Template_Endpoint_Control_R.c" + +#endif diff --git a/LUFA/Drivers/USB/HighLevel/EndpointStream.h b/LUFA/Drivers/USB/HighLevel/EndpointStream.h new file mode 100644 index 0000000..a8b9021 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/EndpointStream.h @@ -0,0 +1,524 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB device endpoint stream function definitions. + * + * This file contains structures, function prototypes and macros related to the sending and receiving of + * arbitrary data streams through the device's data endpoints when the library is initialized in USB device mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_EndpointRW + * @defgroup Group_EndpointStreamRW Read/Write of Multi-Byte Streams + * + * Functions, macros, variables, enums and types related to data reading and writing of data streams from + * and to endpoints. + * + * @{ + */ + +#ifndef __ENDPOINT_STREAM_H__ +#define __ENDPOINT_STREAM_H__ + + /* Includes: */ + #include + #include + #include + + #include "../../../Common/Common.h" + #include "USBTask.h" + + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + #include "StreamCallbacks.h" + #endif + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + #define __CALLBACK_PARAM , StreamCallbackPtr_t Callback + #else + #define __CALLBACK_PARAM + #endif + + /* Public Interface - May be used in end-application: */ + /* Enums: */ + /** Enum for the possible error return codes of the Endpoint_*_Stream_* functions. */ + enum Endpoint_Stream_RW_ErrorCodes_t + { + ENDPOINT_RWSTREAM_NoError = 0, /**< Command completed successfully, no error. */ + ENDPOINT_RWSTREAM_EndpointStalled = 1, /**< The endpoint was stalled during the stream + * transfer by the host or device. + */ + ENDPOINT_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during + * the transfer. + */ + ENDPOINT_RWSTREAM_BusSuspended = 3, /**< The USB bus has been suspended by the host and + * no USB endpoint traffic can occur until the bus + * has resumed. + */ + ENDPOINT_RWSTREAM_Timeout = 4, /**< The host failed to accept or send the next packet + * within the software timeout period set by the + * \ref USB_STREAM_TIMEOUT_MS macro. + */ + ENDPOINT_RWSTREAM_CallbackAborted = 5, /**< Indicates that the stream's callback function + * aborted the transfer early. + */ + }; + + /** Enum for the possible error return codes of the Endpoint_*_Control_Stream_* functions. */ + enum Endpoint_ControlStream_RW_ErrorCodes_t + { + ENDPOINT_RWCSTREAM_NoError = 0, /**< Command completed successfully, no error. */ + ENDPOINT_RWCSTREAM_HostAborted = 1, /**< The aborted the transfer prematurely. */ + ENDPOINT_RWCSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during + * the transfer. + */ + ENDPOINT_RWCSTREAM_BusSuspended = 3, /**< The USB bus has been suspended by the host and + * no USB endpoint traffic can occur until the bus + * has resumed. + */ + }; + + /* Function Prototypes: */ + /** Reads and discards the given number of bytes from the endpoint from the given buffer, + * discarding fully read packets from the host as needed. The last packet is not automatically + * discarded once the remaining bytes has been read; the user is responsible for manually + * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro. Between + * each USB packet, the given stream callback function is executed repeatedly until the next + * packet is ready, allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Discard_Stream(uint16_t Length + __CALLBACK_PARAM); + + /** Writes the given number of bytes to the endpoint from the given buffer in little endian, + * sending full packets to the host as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * \ref Endpoint_ClearIN() macro. Between each USB packet, the given stream callback function + * is executed repeatedly until the endpoint is ready to accept the next packet, allowing for early + * aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Stream_LE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Endpoint_Write_Stream_LE(). + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_EStream_LE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** FLASH buffer source version of \ref Endpoint_Write_Stream_LE(). + * + * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_PStream_LE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** Writes the given number of bytes to the endpoint from the given buffer in big endian, + * sending full packets to the host as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * \ref Endpoint_ClearIN() macro. Between each USB packet, the given stream callback function + * is executed repeatedly until the endpoint is ready to accept the next packet, allowing for early + * aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Stream_BE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Endpoint_Write_Stream_BE(). + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_EStream_BE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** FLASH buffer source version of \ref Endpoint_Write_Stream_BE(). + * + * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_PStream_BE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the endpoint from the given buffer in little endian, + * discarding fully read packets from the host as needed. The last packet is not automatically + * discarded once the remaining bytes has been read; the user is responsible for manually + * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro. Between + * each USB packet, the given stream callback function is executed repeatedly until the endpoint + * is ready to accept the next packet, allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param[out] Buffer Pointer to the destination data buffer to write to. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Stream_LE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Endpoint_Read_Stream_LE(). + * + * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_EStream_LE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the endpoint from the given buffer in big endian, + * discarding fully read packets from the host as needed. The last packet is not automatically + * discarded once the remaining bytes has been read; the user is responsible for manually + * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro. Between + * each USB packet, the given stream callback function is executed repeatedly until the endpoint + * is ready to accept the next packet, allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param[out] Buffer Pointer to the destination data buffer to write to. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Stream_BE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Endpoint_Read_Stream_BE(). + * + * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_EStream_BE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in little endian, + * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared + * in both failure and success states; the user is responsible for manually clearing the setup OUT to + * finalize the transfer via the \ref Endpoint_ClearOUT() macro. + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_Stream_LE(const void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of Endpoint_Write_Control_Stream_LE. + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_EStream_LE(const void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_LE(). + * + * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly. + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_PStream_LE(const void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in big endian, + * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared + * in both failure and success states; the user is responsible for manually clearing the setup OUT to + * finalize the transfer via the \ref Endpoint_ClearOUT() macro. + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_Stream_BE(const void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Endpoint_Write_Control_Stream_BE(). + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_EStream_BE(const void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_BE(). + * + * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly. + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_PStream_BE(const void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in little endian, + * discarding fully read packets from the host as needed. The device IN acknowledgement is not + * automatically sent after success or failure states; the user is responsible for manually sending the + * setup IN to finalize the transfer via the \ref Endpoint_ClearIN() macro. + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[out] Buffer Pointer to the destination data buffer to write to. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_LE(). + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[out] Buffer Pointer to the destination data buffer to write to. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Control_EStream_LE(void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in big endian, + * discarding fully read packets from the host as needed. The device IN acknowledgement is not + * automatically sent after success or failure states; the user is responsible for manually sending the + * setup IN to finalize the transfer via the \ref Endpoint_ClearIN() macro. + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[out] Buffer Pointer to the destination data buffer to write to. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_BE(). + * + * \note This function automatically clears the control transfer's status stage. Do not manually attempt + * to clear the status stage when using this routine in a control transaction. + * \n\n + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param[out] Buffer Pointer to the destination data buffer to write to. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * + * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Control_EStream_BE(void* Buffer, + uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/Events.c b/LUFA/Drivers/USB/HighLevel/Events.c new file mode 100644 index 0000000..b73a7d1 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Events.c @@ -0,0 +1,39 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_EVENTS_C +#define __INCLUDE_FROM_USB_DRIVER +#include "Events.h" + +void USB_Event_Stub(void) +{ + +} + diff --git a/LUFA/Drivers/USB/HighLevel/Events.h b/LUFA/Drivers/USB/HighLevel/Events.h new file mode 100644 index 0000000..a7d3543 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Events.h @@ -0,0 +1,375 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB controller events manager. + * + * This file contains macros and functions relating to the management of library events, which are small + * pieces of code similar to ISRs which are run when a given condition is met. Each event can be fired from + * multiple places in the user or library code, which may or may not be inside an ISR, thus each handler + * should be written to be as small and fast as possible to prevent possible problems. + * + * Events can be hooked by the user application by declaring a handler function with the same name and parameters + * listed here. If an event with no user-associated handler is fired within the library, it by default maps to an + * internal empty stub function. + * + * Each event must only have one associated event handler, but can be raised by multiple sources by calling the + * event handler function (with any required event parameters). + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_Events USB Events + * + * This module contains macros and functions relating to the management of library events, which are small + * pieces of code similar to ISRs which are run when a given condition is met. Each event can be fired from + * multiple places in the user or library code, which may or may not be inside an ISR, thus each handler + * should be written to be as small and fast as possible to prevent possible problems. + * + * Events can be hooked by the user application by declaring a handler function with the same name and parameters + * listed here. If an event with no user-associated handler is fired within the library, it by default maps to an + * internal empty stub function. + * + * Each event must only have one associated event handler, but can be raised by multiple sources by calling the + * event handler function (with any required event parameters). + * + * @{ + */ + +#ifndef __USBEVENTS_H__ +#define __USBEVENTS_H__ + + /* Includes: */ + #include + + #include "../../../Common/Common.h" + #include "USBMode.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Pseudo-Functions for Doxygen: */ + #if !defined(__INCLUDE_FROM_EVENTS_C) || defined(__DOXYGEN__) + /** Event for USB mode pin level change. This event fires when the USB interface is set to dual role + * mode, and the UID pin level has changed to indicate a new mode (device or host). This event fires + * before the mode is switched to the newly indicated mode but after the \ref EVENT_USB_Device_Disconnect + * event has fired (if connected before the role change). + * + * \note This event only exists on USB AVR models which support dual role modes. + * \n\n + * + * \note This event does not exist if the USB_DEVICE_ONLY or USB_HOST_ONLY tokens have been supplied + * to the compiler (see \ref Group_USBManagement documentation). + */ + void EVENT_USB_UIDChange(void); + + /** Event for USB host error. This event fires when a hardware fault has occurred whilst the USB + * interface is in host mode. + * + * \param[in] ErrorCode Error code indicating the failure reason, a value in \ref USB_Host_ErrorCodes_t. + * + * \note This event only exists on USB AVR models which supports host mode. + * \n\n + * + * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + */ + void EVENT_USB_Host_HostError(const uint8_t ErrorCode); + + /** Event for USB device attachment. This event fires when a the USB interface is in host mode, and + * a USB device has been connected to the USB interface. This is interrupt driven, thus fires before + * the standard \ref EVENT_USB_Device_Connect() event and so can be used to programmatically start the USB + * management task to reduce CPU consumption. + * + * \note This event only exists on USB AVR models which supports host mode. + * \n\n + * + * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + * + * \see \ref USB_USBTask() for more information on the USB management task and reducing CPU usage. + */ + void EVENT_USB_Host_DeviceAttached(void); + + /** Event for USB device removal. This event fires when a the USB interface is in host mode, and + * a USB device has been removed the USB interface whether or not it has been enumerated. This + * can be used to programmatically stop the USB management task to reduce CPU consumption. + * + * \note This event only exists on USB AVR models which supports host mode. + * \n\n + * + * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + * + * \see \ref USB_USBTask() for more information on the USB management task and reducing CPU usage. + */ + void EVENT_USB_Host_DeviceUnattached(void); + + /** Event for USB device enumeration failure. This event fires when a the USB interface is + * in host mode, and an attached USB device has failed to enumerate completely. + * + * \param[in] ErrorCode Error code indicating the failure reason, a value in + * \ref USB_Host_EnumerationErrorCodes_t. + * + * \param[in] SubErrorCode Sub error code indicating the reason for failure - for example, if the + * ErrorCode parameter indicates a control error, this will give the error + * code returned by the \ref USB_Host_SendControlRequest() function. + * + * \note This event only exists on USB AVR models which supports host mode. + * \n\n + * + * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + */ + void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode, + const uint8_t SubErrorCode); + + /** Event for USB device enumeration completion. This event fires when a the USB interface is + * in host mode and an attached USB device has been completely enumerated and is ready to be + * controlled by the user application. + * + * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around + * 1 second) when a transaction is waiting to be processed by the device will prevent break communications + * and cause the host to reset the USB bus. + */ + void EVENT_USB_Host_DeviceEnumerationComplete(void); + + /** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB + * frame, once per millisecond, and is synchronized to the USB bus. This can be used as an accurate + * millisecond timer source when the USB bus is not suspended while in host mode. + * + * This event is time-critical; it is run once per millisecond and thus long handlers will significantly + * degrade device performance. This event should only be enabled when needed to reduce device wake-ups. + * + * \note This event is not normally active - it must be manually enabled and disabled via the + * \ref USB_Host_EnableSOFEvents() and \ref USB_Host_DisableSOFEvents() commands after enumeration of + * a USB device. + * \n\n + * + * \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + */ + void EVENT_USB_Host_StartOfFrame(void); + + /** Event for USB device connection. This event fires when the AVR in device mode and the device is connected + * to a host, beginning the enumeration process, measured by a rising level on the AVR's VBUS pin. + * + * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around + * two seconds) will prevent the device from enumerating correctly. + * + * \note For the smaller series 2 USB AVRs with limited USB controllers, VBUS is not available to the USB controller. + * this means that the current connection state is derived from the bus suspension and wake up events by default, + * which is not always accurate (host may suspend the bus while still connected). If the actual connection state + * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by + * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection + * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually. + * \n\n + * + * \note This event may fire multiple times during device enumeration on the series 2 USB AVRs with limited USB controllers + * if NO_LIMITED_CONTROLLER_CONNECT is not defined. + * + * \see USBTask.h for more information on the USB management task and reducing CPU usage. + */ + void EVENT_USB_Device_Connect(void); + + /** Event for USB device disconnection. This event fires when the AVR in device mode and the device is disconnected + * from a host, measured by a falling level on the AVR's VBUS pin. + * + * \note For the smaller series 2 USB AVRs with limited USB controllers, VBUS is not available to the USB controller. + * this means that the current connection state is derived from the bus suspension and wake up events by default, + * which is not always accurate (host may suspend the bus while still connected). If the actual connection state + * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behaviour turned off by + * passing the NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection + * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually. + * \n\n + * + * \note This event may fire multiple times during device enumeration on the series 2 USB AVRs with limited USB controllers + * if NO_LIMITED_CONTROLLER_CONNECT is not defined. + * + * \see USBTask.h for more information on the USB management task and reducing CPU usage. + */ + void EVENT_USB_Device_Disconnect(void); + + /** Event for control requests. This event fires when a the USB host issues a control request + * to the mandatory device control endpoint (of address 0). This may either be a standard + * request that the library may have a handler code for internally, or a class specific request + * issued to the device which must be handled appropriately. If a request is not processed in the + * user application via this event, it will be passed to the library for processing internally + * if a suitable handler exists. + * + * This event is time-critical; each packet within the request transaction must be acknowledged or + * sent within 50ms or the host will abort the transfer. + * + * The library internally handles all standard control requests with the exceptions of SYNC FRAME, + * SET DESCRIPTOR and SET INTERFACE. These and all other non-standard control requests will be left + * for the user to process via this event if desired. If not handled in the user application or by + * the library internally, unknown requests are automatically STALLed. + * + * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + * \n\n + * + * \note Requests should be handled in the same manner as described in the USB 2.0 Specification, + * or appropriate class specification. In all instances, the library has already read the + * request SETUP parameters into the \ref USB_ControlRequest structure which should then be used + * by the application to determine how to handle the issued request. + */ + void EVENT_USB_Device_ControlRequest(void); + + /** Event for USB configuration number changed. This event fires when a the USB host changes the + * selected configuration number while in device mode. This event should be hooked in device + * applications to create the endpoints and configure the device for the selected configuration. + * + * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around + * one second) will prevent the device from enumerating correctly. + * + * This event fires after the value of \ref USB_ConfigurationNumber has been changed. + * + * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + */ + void EVENT_USB_Device_ConfigurationChanged(void); + + /** Event for USB suspend. This event fires when a the USB host suspends the device by halting its + * transmission of Start Of Frame pulses to the device. This is generally hooked in order to move + * the device over to a low power state until the host wakes up the device. If the USB interface is + * enumerated with the \ref USB_OPT_AUTO_PLL option set, the library will automatically suspend the + * USB PLL before the event is fired to save power. + * + * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + * \n\n + * + * \note This event does not exist on the series 2 USB AVRs when the NO_LIMITED_CONTROLLER_CONNECT + * compile time token is not set - see \ref EVENT_USB_Device_Disconnect. + * + * \see \ref EVENT_USB_Device_WakeUp() event for accompanying Wake Up event. + */ + void EVENT_USB_Device_Suspend(void); + + /** Event for USB wake up. This event fires when a the USB interface is suspended while in device + * mode, and the host wakes up the device by supplying Start Of Frame pulses. This is generally + * hooked to pull the user application out of a low power state and back into normal operating + * mode. If the USB interface is enumerated with the \ref USB_OPT_AUTO_PLL option set, the library + * will automatically restart the USB PLL before the event is fired. + * + * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + * \n\n + * + * \note This event does not exist on the series 2 USB AVRs when the NO_LIMITED_CONTROLLER_CONNECT + * compile time token is not set - see \ref EVENT_USB_Device_Connect. + * + * \see \ref EVENT_USB_Device_Suspend() event for accompanying Suspend event. + */ + void EVENT_USB_Device_WakeUp(void); + + /** Event for USB interface reset. This event fires when the USB interface is in device mode, and + * a the USB host requests that the device reset its interface. This event fires after the control + * endpoint has been automatically configured by the library. + * + * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around + * two seconds) will prevent the device from enumerating correctly. + * + * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + */ + void EVENT_USB_Device_Reset(void); + + /** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB + * frame, once per millisecond, and is synchronized to the USB bus. This can be used as an accurate + * millisecond timer source when the USB bus is enumerated in device mode to a USB host. + * + * This event is time-critical; it is run once per millisecond and thus long handlers will significantly + * degrade device performance. This event should only be enabled when needed to reduce device wake-ups. + * + * \note This event is not normally active - it must be manually enabled and disabled via the + * \ref USB_Device_EnableSOFEvents() and \ref USB_Device_DisableSOFEvents() commands after enumeration. + * \n\n + * + * \note This event does not exist if the USB_HOST_ONLY token is supplied to the compiler (see + * \ref Group_USBManagement documentation). + */ + void EVENT_USB_Device_StartOfFrame(void); + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Function Prototypes: */ + #if defined(__INCLUDE_FROM_EVENTS_C) + void USB_Event_Stub(void) ATTR_CONST; + + #if defined(USB_CAN_BE_BOTH) + void EVENT_USB_UIDChange(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + #endif + + #if defined(USB_CAN_BE_HOST) + void EVENT_USB_Host_HostError(const uint8_t ErrorCode) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Host_DeviceAttached(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Host_DeviceUnattached(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Host_DeviceEnumerationComplete(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode, + const uint8_t SubErrorCode) + ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Host_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + #endif + + #if defined(USB_CAN_BE_DEVICE) + void EVENT_USB_Device_Connect(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Device_Disconnect(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Device_ControlRequest(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Device_ConfigurationChanged(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Device_Suspend(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Device_WakeUp(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Device_Reset(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + void EVENT_USB_Device_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); + #endif + #endif + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/HostStandardReq.c b/LUFA/Drivers/USB/HighLevel/HostStandardReq.c new file mode 100644 index 0000000..2eee726 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/HostStandardReq.c @@ -0,0 +1,180 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "USBMode.h" + +#if defined(USB_CAN_BE_HOST) + +#define __INCLUDE_FROM_HOSTSTDREQ_C +#include "HostStandardReq.h" + +uint8_t USB_Host_SendControlRequest(void* const BufferPtr) +{ + uint8_t* HeaderStream = (uint8_t*)&USB_ControlRequest; + uint8_t* DataStream = (uint8_t*)BufferPtr; + bool BusSuspended = USB_Host_IsBusSuspended(); + uint8_t ReturnStatus = HOST_SENDCONTROL_Successful; + uint16_t DataLen = USB_ControlRequest.wLength; + + USB_Host_ResumeBus(); + + if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) + goto End_Of_Control_Send; + + Pipe_SetPipeToken(PIPE_TOKEN_SETUP); + Pipe_ClearErrorFlags(); + + Pipe_Unfreeze(); + + for (uint8_t HeaderByte = 0; HeaderByte < sizeof(USB_Request_Header_t); HeaderByte++) + Pipe_Write_Byte(*(HeaderStream++)); + + Pipe_ClearSETUP(); + + if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_SetupSent)) != HOST_SENDCONTROL_Successful) + goto End_Of_Control_Send; + + Pipe_Freeze(); + + if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) + goto End_Of_Control_Send; + + if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST) + { + Pipe_SetPipeToken(PIPE_TOKEN_IN); + + if (DataStream != NULL) + { + while (DataLen) + { + Pipe_Unfreeze(); + + if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful) + goto End_Of_Control_Send; + + if (!(Pipe_BytesInPipe())) + DataLen = 0; + + while (Pipe_BytesInPipe() && DataLen) + { + *(DataStream++) = Pipe_Read_Byte(); + DataLen--; + } + + Pipe_Freeze(); + Pipe_ClearIN(); + } + } + + Pipe_SetPipeToken(PIPE_TOKEN_OUT); + Pipe_Unfreeze(); + + if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) + goto End_Of_Control_Send; + + Pipe_ClearOUT(); + + if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) + goto End_Of_Control_Send; + } + else + { + if (DataStream != NULL) + { + Pipe_SetPipeToken(PIPE_TOKEN_OUT); + Pipe_Unfreeze(); + + while (DataLen) + { + if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) + goto End_Of_Control_Send; + + while (DataLen && (Pipe_BytesInPipe() < USB_ControlPipeSize)) + { + Pipe_Write_Byte(*(DataStream++)); + DataLen--; + } + + Pipe_ClearOUT(); + } + + if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful) + goto End_Of_Control_Send; + + Pipe_Freeze(); + } + + Pipe_SetPipeToken(PIPE_TOKEN_IN); + Pipe_Unfreeze(); + + if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful) + goto End_Of_Control_Send; + + Pipe_ClearIN(); + } + +End_Of_Control_Send: + Pipe_Freeze(); + + if (BusSuspended) + USB_Host_SuspendBus(); + + Pipe_ResetPipe(PIPE_CONTROLPIPE); + + return ReturnStatus; +} + +static uint8_t USB_Host_WaitForIOS(const uint8_t WaitType) +{ + #if (USB_HOST_TIMEOUT_MS < 0xFF) + uint8_t TimeoutCounter = USB_HOST_TIMEOUT_MS; + #else + uint16_t TimeoutCounter = USB_HOST_TIMEOUT_MS; + #endif + + while (!(((WaitType == USB_HOST_WAITFOR_SetupSent) && Pipe_IsSETUPSent()) || + ((WaitType == USB_HOST_WAITFOR_InReceived) && Pipe_IsINReceived()) || + ((WaitType == USB_HOST_WAITFOR_OutReady) && Pipe_IsOUTReady()))) + { + uint8_t ErrorCode; + + if ((ErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) + return ErrorCode; + + if (!(TimeoutCounter--)) + return HOST_SENDCONTROL_SoftwareTimeOut; + } + + return HOST_SENDCONTROL_Successful; +} + +#endif + diff --git a/LUFA/Drivers/USB/HighLevel/HostStandardReq.h b/LUFA/Drivers/USB/HighLevel/HostStandardReq.h new file mode 100644 index 0000000..4b9b3dc --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/HostStandardReq.h @@ -0,0 +1,118 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB host standard request management. + * + * This file contains the function prototypes necessary for the issuing of outgoing standard control requests + * when the library is in USB host mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +#ifndef __HOSTSTDREQ_H__ +#define __HOSTSTDREQ_H__ + + /* Includes: */ + #include + #include + + #include "USBMode.h" + #include "StdRequestType.h" + #include "../LowLevel/USBController.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Enums: */ + /** Enum for the \ref USB_Host_SendControlRequest() return code, indicating the reason for the error + * if the transfer of the request is unsuccessful. + * + * \ingroup Group_PipeControlReq + */ + enum USB_Host_SendControlErrorCodes_t + { + HOST_SENDCONTROL_Successful = 0, /**< No error occurred in the request transfer. */ + HOST_SENDCONTROL_DeviceDisconnected = 1, /**< The attached device was disconnected during the + * request transfer. + */ + HOST_SENDCONTROL_PipeError = 2, /**< An error occurred in the pipe while sending the request. */ + HOST_SENDCONTROL_SetupStalled = 3, /**< The attached device stalled the request, usually + * indicating that the request is unsupported on the device. + */ + HOST_SENDCONTROL_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */ + }; + + /* Function Prototypes: */ + /** Sends the request stored in the \ref USB_ControlRequest global structure to the attached device, + * and transfers the data stored in the buffer to the device, or from the device to the buffer + * as requested. The transfer is made on the currently selected pipe. + * + * \ingroup Group_PipeControlReq + * + * \param[in] BufferPtr Pointer to the start of the data buffer if the request has a data stage, or + * NULL if the request transfers no data to or from the device. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_SendControlRequest(void* const BufferPtr); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Enums: */ + enum USB_WaitForTypes_t + { + USB_HOST_WAITFOR_SetupSent, + USB_HOST_WAITFOR_InReceived, + USB_HOST_WAITFOR_OutReady, + }; + + /* Function Prototypes: */ + #if defined(__INCLUDE_FROM_HOSTSTDREQ_C) + static uint8_t USB_Host_WaitForIOS(const uint8_t WaitType); + #endif + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + diff --git a/LUFA/Drivers/USB/HighLevel/PipeStream.c b/LUFA/Drivers/USB/HighLevel/PipeStream.c new file mode 100644 index 0000000..25100ca --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/PipeStream.c @@ -0,0 +1,196 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "USBMode.h" + +#if defined(USB_CAN_BE_HOST) + +#include "PipeStream.h" + +uint8_t Pipe_Discard_Stream(uint16_t Length + __CALLBACK_PARAM) +{ + uint8_t ErrorCode; + + Pipe_SetPipeToken(PIPE_TOKEN_IN); + + if ((ErrorCode = Pipe_WaitUntilReady())) + return ErrorCode; + + #if defined(FAST_STREAM_TRANSFERS) + uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07); + + if (Length >= 8) + { + Length -= BytesRemToAlignment; + + switch (BytesRemToAlignment) + { + default: + do + { + if (!(Pipe_IsReadWriteAllowed())) + { + Pipe_ClearIN(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return PIPE_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Pipe_WaitUntilReady())) + return ErrorCode; + } + + Length -= 8; + + Pipe_Discard_Byte(); + case 7: Pipe_Discard_Byte(); + case 6: Pipe_Discard_Byte(); + case 5: Pipe_Discard_Byte(); + case 4: Pipe_Discard_Byte(); + case 3: Pipe_Discard_Byte(); + case 2: Pipe_Discard_Byte(); + case 1: Pipe_Discard_Byte(); + } while (Length >= 8); + } + } + #endif + + while (Length) + { + if (!(Pipe_IsReadWriteAllowed())) + { + Pipe_ClearIN(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return PIPE_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Pipe_WaitUntilReady())) + return ErrorCode; + } + else + { + Pipe_Discard_Byte(); + Length--; + } + } + + return PIPE_RWSTREAM_NoError; +} + +/* The following abuses the C preprocessor in order to copy-past common code with slight alterations, + * so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */ + +#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_LE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_TOKEN PIPE_TOKEN_OUT +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_Byte(*((uint8_t*)BufferPtr++)) +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Write_PStream_LE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_TOKEN PIPE_TOKEN_OUT +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr++)) +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Write_EStream_LE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_TOKEN PIPE_TOKEN_OUT +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr++)) +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_BE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_TOKEN PIPE_TOKEN_OUT +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_Byte(*((uint8_t*)BufferPtr--)) +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Write_PStream_BE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_TOKEN PIPE_TOKEN_OUT +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_Byte(pgm_read_byte((uint8_t*)BufferPtr--)) +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Write_EStream_BE +#define TEMPLATE_BUFFER_TYPE const void* +#define TEMPLATE_TOKEN PIPE_TOKEN_OUT +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_Byte(eeprom_read_byte((uint8_t*)BufferPtr--)) +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_LE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_TOKEN PIPE_TOKEN_IN +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *((uint8_t*)BufferPtr++) = Pipe_Read_Byte() +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Read_EStream_LE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_TOKEN PIPE_TOKEN_IN +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) 0 +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte((uint8_t*)BufferPtr++, Pipe_Read_Byte()) +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_BE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_TOKEN PIPE_TOKEN_IN +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *((uint8_t*)BufferPtr--) = Pipe_Read_Byte() +#include "Template/Template_Pipe_RW.c" + +#define TEMPLATE_FUNC_NAME Pipe_Read_EStream_BE +#define TEMPLATE_BUFFER_TYPE void* +#define TEMPLATE_TOKEN PIPE_TOKEN_IN +#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN() +#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1) +#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte((uint8_t*)BufferPtr--, Pipe_Read_Byte()) +#include "Template/Template_Pipe_RW.c" + +#endif + diff --git a/LUFA/Drivers/USB/HighLevel/PipeStream.h b/LUFA/Drivers/USB/HighLevel/PipeStream.h new file mode 100644 index 0000000..730a338 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/PipeStream.h @@ -0,0 +1,298 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB host pipe stream function definitions. + * + * This file contains structures, function prototypes and macros related to the sending and receiving of + * arbitrary data streams through the device's data pipes when the library is initialized in USB host mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_PipeRW + * @defgroup Group_PipeStreamRW Read/Write of Multi-Byte Streams + * + * Functions, macros, variables, enums and types related to data reading and writing of data streams from + * and to pipes. + * + * @{ + */ + +#ifndef __PIPE_STREAM_H__ +#define __PIPE_STREAM_H__ + + /* Includes: */ + #include + #include + #include + + #include "../../../Common/Common.h" + #include "USBTask.h" + + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + #include "StreamCallbacks.h" + #endif + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + #define __CALLBACK_PARAM , StreamCallbackPtr_t Callback + #else + #define __CALLBACK_PARAM + #endif + + /* Public Interface - May be used in end-application: */ + /* Enums: */ + /** Enum for the possible error return codes of the Pipe_*_Stream_* functions. */ + enum Pipe_Stream_RW_ErrorCodes_t + { + PIPE_RWSTREAM_NoError = 0, /**< Command completed successfully, no error. */ + PIPE_RWSTREAM_PipeStalled = 1, /**< The device stalled the pipe during the transfer. */ + PIPE_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during + * the transfer. + */ + PIPE_RWSTREAM_Timeout = 3, /**< The device failed to accept or send the next packet + * within the software timeout period set by the + * \ref USB_STREAM_TIMEOUT_MS macro. + */ + PIPE_RWSTREAM_CallbackAborted = 4, /**< Indicates that the stream's callback function aborted + * the transfer early. + */ + }; + + /* Function Prototypes: */ + /** Reads and discards the given number of bytes from the pipe, discarding fully read packets from the host + * as needed. The last packet is not automatically discarded once the remaining bytes has been read; the + * user is responsible for manually discarding the last packet from the device via the \ref Pipe_ClearIN() macro. + * Between each USB packet, the given stream callback function is executed repeatedly until the next packet is ready, + * allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * The pipe token is set automatically, thus this can be used on bi-directional pipes directly without + * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken(). + * + * \param[in] Length Number of bytes to send via the currently selected pipe. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Discard_Stream(uint16_t Length + __CALLBACK_PARAM); + + /** Writes the given number of bytes to the pipe from the given buffer in little endian, + * sending full packets to the device as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is + * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * The pipe token is set automatically, thus this can be used on bi-directional pipes directly without + * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken(). + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Write_Stream_LE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Pipe_Write_Stream_LE(). + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Write_EStream_LE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** FLASH buffer source version of \ref Pipe_Write_Stream_LE(). + * + * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Write_PStream_LE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** Writes the given number of bytes to the pipe from the given buffer in big endian, + * sending full packets to the device as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is + * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * The pipe token is set automatically, thus this can be used on bi-directional pipes directly without + * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken(). + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Write_Stream_BE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Pipe_Write_Stream_BE(). + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Write_EStream_BE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** FLASH buffer source version of \ref Pipe_Write_Stream_BE(). + * + * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly. + * + * \param[in] Buffer Pointer to the source data buffer to read from. + * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Write_PStream_BE(const void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the pipe into the given buffer in little endian, + * sending full packets to the device as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is + * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * The pipe token is set automatically, thus this can be used on bi-directional pipes directly without + * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken(). + * + * \param[out] Buffer Pointer to the source data buffer to write to. + * \param[in] Length Number of bytes to read for the currently selected pipe to read from. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Read_Stream_LE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Pipe_Read_Stream_LE(). + * + * \param[out] Buffer Pointer to the source data buffer to write to. + * \param[in] Length Number of bytes to read for the currently selected pipe to read from. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Read_EStream_LE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the pipe into the given buffer in big endian, + * sending full packets to the device as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is + * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers. + * + * The callback routine should be created according to the information in \ref Group_StreamCallbacks. + * If the token NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are + * disabled and this function has the Callback parameter omitted. + * + * The pipe token is set automatically, thus this can be used on bi-directional pipes directly without + * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken(). + * + * \param[out] Buffer Pointer to the source data buffer to write to. + * \param[in] Length Number of bytes to read for the currently selected pipe to read from. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Read_Stream_BE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /** EEPROM buffer source version of \ref Pipe_Read_Stream_BE(). + * + * \param[out] Buffer Pointer to the source data buffer to write to. + * \param[in] Length Number of bytes to read for the currently selected pipe to read from. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * + * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Pipe_Read_EStream_BE(void* Buffer, + uint16_t Length + __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/StdDescriptors.h b/LUFA/Drivers/USB/HighLevel/StdDescriptors.h new file mode 100644 index 0000000..6001325 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/StdDescriptors.h @@ -0,0 +1,692 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB standard descriptor definitions. + * + * This file contains structures and macros for the easy creation of standard USB descriptors in USB device projects. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_Descriptors USB Descriptors + * + * Standard USB device descriptor defines and retrieval routines, for USB devices. This module contains + * structures and macros for the easy creation of standard USB descriptors in USB device projects. + * + * @{ + */ + +#ifndef __USBDESCRIPTORS_H__ +#define __USBDESCRIPTORS_H__ + + /* Includes: */ + #include + #include + #include + #include + + #include "../../../Common/Common.h" + #include "USBMode.h" + #include "Events.h" + + #if defined(USB_CAN_BE_DEVICE) + #include "../LowLevel/Device.h" + #endif + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Indicates that a given descriptor does not exist in the device. This can be used inside descriptors + * for string descriptor indexes, or may be use as a return value for GetDescriptor when the specified + * descriptor does not exist. + */ + #define NO_DESCRIPTOR 0 + + #if (!defined(NO_INTERNAL_SERIAL) && \ + (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__) || \ + defined(__AVR_ATmega32U6__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || \ + defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__))) + /** String descriptor index for the device's unique serial number string descriptor within the device. + * This unique serial number is used by the host to associate resources to the device (such as drivers or COM port + * number allocations) to a device regardless of the port it is plugged in to on the host. Some USB AVRs contain + * a unique serial number internally, and setting the device descriptors serial number string index to this value + * will cause it to use the internal serial number. + * + * On unsupported devices, this will evaluate to NO_DESCRIPTOR and so will force the host to create a pseudo-serial + * number for the device. + */ + #define USE_INTERNAL_SERIAL 0xDC + #else + #define USE_INTERNAL_SERIAL NO_DESCRIPTOR + #endif + + /** Macro to calculate the power value for the configuration descriptor, from a given number of milliamperes. */ + #define USB_CONFIG_POWER_MA(mA) ((mA) >> 1) + + /** Macro to calculate the Unicode length of a string with a given number of Unicode characters. + * Should be used in string descriptor's headers for giving the string descriptor's byte length. + */ + #define USB_STRING_LEN(str) (sizeof(USB_Descriptor_Header_t) + ((str) << 1)) + + /** Macro to encode a given four digit floating point version number (e.g. 01.23) into Binary Coded + * Decimal format for descriptor fields requiring BCD encoding, such as the USB version number in the + * standard device descriptor. + */ + #define VERSION_BCD(x) ((((VERSION_TENS(x) << 4) | VERSION_ONES(x)) << 8) | \ + ((VERSION_TENTHS(x) << 4) | VERSION_HUNDREDTHS(x))) + + /** String language ID for the English language. Should be used in \ref USB_Descriptor_String_t descriptors + * to indicate that the English language is supported by the device in its string descriptors. + */ + #define LANGUAGE_ID_ENG 0x0409 + + /** \name Endpoint Address Direction Masks */ + //@{ + /** Can be masked with an endpoint address for a \ref USB_Descriptor_Endpoint_t endpoint descriptor's + * EndpointAddress value to indicate to the host that the endpoint is of the IN direction (i.e, from + * device to host). + */ + #define ENDPOINT_DESCRIPTOR_DIR_IN 0x80 + + /** Can be masked with an endpoint address for a \ref USB_Descriptor_Endpoint_t endpoint descriptor's + * EndpointAddress value to indicate to the host that the endpoint is of the OUT direction (i.e, from + * host to device). + */ + #define ENDPOINT_DESCRIPTOR_DIR_OUT 0x00 + //@} + + /** \name USB Configuration Descriptor Attribute Masks */ + //@{ + /** Can be masked with other configuration descriptor attributes for a \ref USB_Descriptor_Configuration_Header_t + * descriptor's ConfigAttributes value to indicate that the specified configuration can draw its power + * from the host's VBUS line. + */ + #define USB_CONFIG_ATTR_BUSPOWERED 0x80 + + /** Can be masked with other configuration descriptor attributes for a \ref USB_Descriptor_Configuration_Header_t + * descriptor's ConfigAttributes value to indicate that the specified configuration can draw its power + * from the device's own power source. + */ + #define USB_CONFIG_ATTR_SELFPOWERED 0x40 + + /** Can be masked with other configuration descriptor attributes for a \ref USB_Descriptor_Configuration_Header_t + * descriptor's ConfigAttributes value to indicate that the specified configuration supports the + * remote wakeup feature of the USB standard, allowing a suspended USB device to wake up the host upon + * request. + */ + #define USB_CONFIG_ATTR_REMOTEWAKEUP 0x20 + //@} + + /** \name Endpoint Descriptor Attribute Masks */ + //@{ + /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's + * Attributes value to indicate that the specified endpoint is not synchronized. + * + * \see The USB specification for more details on the possible Endpoint attributes. + */ + #define ENDPOINT_ATTR_NO_SYNC (0 << 2) + + /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's + * Attributes value to indicate that the specified endpoint is asynchronous. + * + * \see The USB specification for more details on the possible Endpoint attributes. + */ + #define ENDPOINT_ATTR_ASYNC (1 << 2) + + /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's + * Attributes value to indicate that the specified endpoint is adaptive. + * + * \see The USB specification for more details on the possible Endpoint attributes. + */ + #define ENDPOINT_ATTR_ADAPTIVE (2 << 2) + + /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's + * Attributes value to indicate that the specified endpoint is synchronized. + * + * \see The USB specification for more details on the possible Endpoint attributes. + */ + #define ENDPOINT_ATTR_SYNC (3 << 2) + //@} + + /** \name Endpoint Descriptor Usage Masks */ + //@{ + /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's + * Attributes value to indicate that the specified endpoint is used for data transfers. + * + * \see The USB specification for more details on the possible Endpoint usage attributes. + */ + #define ENDPOINT_USAGE_DATA (0 << 4) + + /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's + * Attributes value to indicate that the specified endpoint is used for feedback. + * + * \see The USB specification for more details on the possible Endpoint usage attributes. + */ + #define ENDPOINT_USAGE_FEEDBACK (1 << 4) + + /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's + * Attributes value to indicate that the specified endpoint is used for implicit feedback. + * + * \see The USB specification for more details on the possible Endpoint usage attributes. + */ + #define ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << 4) + //@} + + /* Enums: */ + /** Enum for the possible standard descriptor types, as given in each descriptor's header. */ + enum USB_DescriptorTypes_t + { + DTYPE_Device = 0x01, /**< Indicates that the descriptor is a device descriptor. */ + DTYPE_Configuration = 0x02, /**< Indicates that the descriptor is a configuration descriptor. */ + DTYPE_String = 0x03, /**< Indicates that the descriptor is a string descriptor. */ + DTYPE_Interface = 0x04, /**< Indicates that the descriptor is an interface descriptor. */ + DTYPE_Endpoint = 0x05, /**< Indicates that the descriptor is an endpoint descriptor. */ + DTYPE_DeviceQualifier = 0x06, /**< Indicates that the descriptor is a device qualifier descriptor. */ + DTYPE_Other = 0x07, /**< Indicates that the descriptor is of other type. */ + DTYPE_InterfacePower = 0x08, /**< Indicates that the descriptor is an interface power descriptor. */ + DTYPE_InterfaceAssociation = 0x0B, /**< Indicates that the descriptor is an interface association descriptor. */ + DTYPE_CSInterface = 0x24, /**< Indicates that the descriptor is a class specific interface descriptor. */ + DTYPE_CSEndpoint = 0x25, /**< Indicates that the descriptor is a class specific endpoint descriptor. */ + }; + + /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors. */ + enum USB_Descriptor_ClassSubclassProtocol_t + { + USB_CSCP_NoDeviceClass = 0x00, /**< Descriptor Class value indicating that the device does not belong + * to a particular class at the device level. + */ + USB_CSCP_NoDeviceSubclass = 0x00, /**< Descriptor Subclass value indicating that the device does not belong + * to a particular subclass at the device level. + */ + USB_CSCP_NoDeviceProtocol = 0x00, /**< Descriptor Protocol value indicating that the device does not belong + * to a particular protocol at the device level. + */ + USB_CSCP_VendorSpecificClass = 0xFF, /**< Descriptor Class value indicating that the device/interface belongs + * to a vendor specific class. + */ + USB_CSCP_VendorSpecificSubclass = 0xFF, /**< Descriptor Subclass value indicating that the device/interface belongs + * to a vendor specific subclass. + */ + USB_CSCP_VendorSpecificProtocol = 0xFF, /**< Descriptor Protocol value indicating that the device/interface belongs + * to a vendor specific protocol. + */ + USB_CSCP_IADDeviceClass = 0xEF, /**< Descriptor Class value indicating that the device belongs to the + * Interface Association Descriptor class. + */ + USB_CSCP_IADDeviceSubclass = 0x02, /**< Descriptor Subclass value indicating that the device belongs to the + * Interface Association Descriptor subclass. + */ + USB_CSCP_IADDeviceProtocol = 0x01, /**< Descriptor Protocol value indicating that the device belongs to the + * Interface Association Descriptor protocol. + */ + }; + + /* Type Defines: */ + /** \brief Standard USB Descriptor Header (LUFA naming conventions). + * + * Type define for all descriptors' standard header, indicating the descriptor's length and type. This structure + * uses LUFA-specific element names to make each element's purpose clearer. + * + * \see \ref USB_StdDescriptor_Header_t for the version of this type with standard element names. + */ + typedef struct + { + uint8_t Size; /**< Size of the descriptor, in bytes. */ + uint8_t Type; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value + * given by the specific class. + */ + } USB_Descriptor_Header_t; + + /** \brief Standard USB Descriptor Header (USB-IF naming conventions). + * + * Type define for all descriptors' standard header, indicating the descriptor's length and type. This structure + * uses the relevant standard's given element names to ensure compatibility with the standard. + * + * \see \ref USB_Descriptor_Header_t for the version of this type with non-standard LUFA specific element names. + */ + 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. + */ + } USB_StdDescriptor_Header_t; + + /** \brief Standard USB Device Descriptor (LUFA naming conventions). + * + * Type define for a standard Device Descriptor. This structure uses LUFA-specific element names to make each + * element's purpose clearer. + * + * \see \ref USB_StdDescriptor_Device_t for the version of this type with standard element names. + */ + typedef struct + { + USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */ + + uint16_t USBSpecification; /**< BCD of the supported USB specification. */ + uint8_t Class; /**< USB device class. */ + uint8_t SubClass; /**< USB device subclass. */ + uint8_t Protocol; /**< USB device protocol. */ + + uint8_t Endpoint0Size; /**< Size of the control (address 0) endpoint's bank in bytes. */ + + uint16_t VendorID; /**< Vendor ID for the USB product. */ + uint16_t ProductID; /**< Unique product ID for the USB product. */ + uint16_t ReleaseNumber; /**< Product release (version) number. */ + + uint8_t ManufacturerStrIndex; /**< String index for the manufacturer's name. The + * host will request this string via a separate + * control request for the string descriptor. + * + * \note If no string supplied, use \ref NO_DESCRIPTOR. + */ + uint8_t ProductStrIndex; /**< String index for the product name/details. + * + * \see ManufacturerStrIndex structure entry. + */ + uint8_t SerialNumStrIndex; /**< String index for the product's globally unique hexadecimal + * serial number, in uppercase Unicode ASCII. + * + * \note On some AVR models, there is an embedded serial number + * in the chip which can be used for the device serial number. + * To use this serial number, set this to USE_INTERNAL_SERIAL. + * On unsupported devices, this will evaluate to 0 and will cause + * the host to generate a pseudo-unique value for the device upon + * insertion. + * + * \see ManufacturerStrIndex structure entry. + */ + uint8_t NumberOfConfigurations; /**< Total number of configurations supported by + * the device. + */ + } USB_Descriptor_Device_t; + + /** \brief Standard USB Device Descriptor (USB-IF naming conventions). + * + * Type define for a standard Device Descriptor. This structure uses the relevant standard's given element names + * to ensure compatibility with the standard. + * + * \see \ref USB_Descriptor_Device_t for the version of this type with non-standard LUFA specific element names. + */ + 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 bcdUSB; /**< BCD of the supported USB specification. */ + uint8_t bDeviceClass; /**< USB device class. */ + uint8_t bDeviceSubClass; /**< USB device subclass. */ + uint8_t bDeviceProtocol; /**< USB device protocol. */ + uint8_t bMaxPacketSize0; /**< Size of the control (address 0) endpoint's bank in bytes. */ + uint16_t idVendor; /**< Vendor ID for the USB product. */ + uint16_t idProduct; /**< Unique product ID for the USB product. */ + uint16_t bcdDevice; /**< Product release (version) number. */ + uint8_t iManufacturer; /**< String index for the manufacturer's name. The + * host will request this string via a separate + * control request for the string descriptor. + * + * \note If no string supplied, use \ref NO_DESCRIPTOR. + */ + uint8_t iProduct; /**< String index for the product name/details. + * + * \see ManufacturerStrIndex structure entry. + */ + uint8_t iSerialNumber; /**< String index for the product's globally unique hexadecimal + * serial number, in uppercase Unicode ASCII. + * + * \note On some AVR models, there is an embedded serial number + * in the chip which can be used for the device serial number. + * To use this serial number, set this to USE_INTERNAL_SERIAL. + * On unsupported devices, this will evaluate to 0 and will cause + * the host to generate a pseudo-unique value for the device upon + * insertion. + * + * \see ManufacturerStrIndex structure entry. + */ + uint8_t bNumConfigurations; /**< Total number of configurations supported by + * the device. + */ + } USB_StdDescriptor_Device_t; + + /** \brief Standard USB Configuration Descriptor (LUFA naming conventions). + * + * Type define for a standard Configuration Descriptor header. This structure uses LUFA-specific element names + * to make each element's purpose clearer. + * + * \see \ref USB_StdDescriptor_Configuration_Header_t for the version of this type with standard element names. + */ + typedef struct + { + USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */ + + uint16_t TotalConfigurationSize; /**< Size of the configuration descriptor header, + * and all sub descriptors inside the configuration. + */ + uint8_t TotalInterfaces; /**< Total number of interfaces in the configuration. */ + + uint8_t ConfigurationNumber; /**< Configuration index of the current configuration. */ + uint8_t ConfigurationStrIndex; /**< Index of a string descriptor describing the configuration. */ + + uint8_t ConfigAttributes; /**< Configuration attributes, comprised of a mask of zero or + * more USB_CONFIG_ATTR_* masks. + */ + + uint8_t MaxPowerConsumption; /**< Maximum power consumption of the device while in the + * current configuration, calculated by the \ref USB_CONFIG_POWER_MA() + * macro. + */ + } USB_Descriptor_Configuration_Header_t; + + /** \brief Standard USB Configuration Descriptor (USB-IF naming conventions). + * + * Type define for a standard Configuration Descriptor header. This structure uses the relevant standard's given element names + * to ensure compatibility with the standard. + * + * \see \ref USB_Descriptor_Device_t for the version of this type with non-standard LUFA specific element names. + */ + 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 wTotalLength; /**< Size of the configuration descriptor header, + * and all sub descriptors inside the configuration. + */ + uint8_t bNumInterfaces; /**< Total number of interfaces in the configuration. */ + uint8_t bConfigurationValue; /**< Configuration index of the current configuration. */ + uint8_t iConfiguration; /**< Index of a string descriptor describing the configuration. */ + uint8_t bmAttributes; /**< Configuration attributes, comprised of a mask of zero or + * more USB_CONFIG_ATTR_* masks. + */ + uint8_t bMaxPower; /**< Maximum power consumption of the device while in the + * current configuration, calculated by the \ref USB_CONFIG_POWER_MA() + * macro. + */ + } USB_StdDescriptor_Configuration_Header_t; + + /** \brief Standard USB Interface Descriptor (LUFA naming conventions). + * + * Type define for a standard Interface Descriptor. This structure uses LUFA-specific element names + * to make each element's purpose clearer. + * + * \see \ref USB_StdDescriptor_Interface_t for the version of this type with standard element names. + */ + typedef struct + { + USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */ + + uint8_t InterfaceNumber; /**< Index of the interface in the current configuration. */ + uint8_t AlternateSetting; /**< Alternate setting for the interface number. The same + * interface number can have multiple alternate settings + * with different endpoint configurations, which can be + * selected by the host. + */ + uint8_t TotalEndpoints; /**< Total number of endpoints in the interface. */ + + uint8_t Class; /**< Interface class ID. */ + uint8_t SubClass; /**< Interface subclass ID. */ + uint8_t Protocol; /**< Interface protocol ID. */ + + uint8_t InterfaceStrIndex; /**< Index of the string descriptor describing the interface. */ + } USB_Descriptor_Interface_t; + + /** \brief Standard USB Interface Descriptor (USB-IF naming conventions). + * + * Type define for a standard Interface Descriptor. This structure uses the relevant standard's given element names + * to ensure compatibility with the standard. + * + * \see \ref USB_Descriptor_Interface_t for the version of this type with non-standard LUFA specific element names. + */ + 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 bInterfaceNumber; /**< Index of the interface in the current configuration. */ + uint8_t bAlternateSetting; /**< Alternate setting for the interface number. The same + * interface number can have multiple alternate settings + * with different endpoint configurations, which can be + * selected by the host. + */ + uint8_t bNumEndpoints; /**< Total number of endpoints in the interface. */ + uint8_t bInterfaceClass; /**< Interface class ID. */ + uint8_t bInterfaceSubClass; /**< Interface subclass ID. */ + uint8_t bInterfaceProtocol; /**< Interface protocol ID. */ + uint8_t iInterface; /**< Index of the string descriptor describing the + * interface. + */ + } USB_StdDescriptor_Interface_t; + + /** \brief Standard USB Interface Association Descriptor (LUFA naming conventions). + * + * Type define for a standard Interface Association Descriptor. This structure uses LUFA-specific element names + * to make each element's purpose clearer. + * + * This descriptor has been added as a supplement to the USB2.0 standard, in the ECN located at + * http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf. It allows composite + * devices with multiple interfaces related to the same function to have the multiple interfaces bound + * together at the point of enumeration, loading one generic driver for all the interfaces in the single + * function. Read the ECN for more information. + * + * \see \ref USB_StdDescriptor_Interface_Association_t for the version of this type with standard element names. + */ + typedef struct + { + USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */ + + uint8_t FirstInterfaceIndex; /**< Index of the first associated interface. */ + uint8_t TotalInterfaces; /**< Total number of associated interfaces. */ + + uint8_t Class; /**< Interface class ID. */ + uint8_t SubClass; /**< Interface subclass ID. */ + uint8_t Protocol; /**< Interface protocol ID. */ + + uint8_t IADStrIndex; /**< Index of the string descriptor describing the + * interface association. + */ + } USB_Descriptor_Interface_Association_t; + + /** \brief Standard USB Interface Association Descriptor (USB-IF naming conventions). + * + * Type define for a standard Interface Association Descriptor. This structure uses the relevant standard's given + * element names to ensure compatibility with the standard. + * + * This descriptor has been added as a supplement to the USB2.0 standard, in the ECN located at + * http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf. It allows composite + * devices with multiple interfaces related to the same function to have the multiple interfaces bound + * together at the point of enumeration, loading one generic driver for all the interfaces in the single + * function. Read the ECN for more information. + * + * \see \ref USB_Descriptor_Interface_Association_t for the version of this type with non-standard LUFA specific + * element names. + */ + 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 bFirstInterface; /**< Index of the first associated interface. */ + uint8_t bInterfaceCount; /**< Total number of associated interfaces. */ + uint8_t bFunctionClass; /**< Interface class ID. */ + uint8_t bFunctionSubClass; /**< Interface subclass ID. */ + uint8_t bFunctionProtocol; /**< Interface protocol ID. */ + uint8_t iFunction; /**< Index of the string descriptor describing the + * interface association. + */ + } USB_StdDescriptor_Interface_Association_t; + + /** \brief Standard USB Endpoint Descriptor (LUFA naming conventions). + * + * Type define for a standard Endpoint Descriptor. This structure uses LUFA-specific element names + * to make each element's purpose clearer. + * + * \see \ref USB_StdDescriptor_Endpoint_t for the version of this type with standard element names. + */ + typedef struct + { + USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */ + + uint8_t EndpointAddress; /**< Logical address of the endpoint within the device for the current + * configuration, including direction mask. + */ + uint8_t Attributes; /**< Endpoint attributes, comprised of a mask of the endpoint type (EP_TYPE_*) + * and attributes (ENDPOINT_ATTR_*) masks. + */ + uint16_t EndpointSize; /**< Size of the endpoint bank, in bytes. This indicates the maximum packet + * size that the endpoint can receive at a time. + */ + uint8_t PollingIntervalMS; /**< Polling interval in milliseconds for the endpoint if it is an INTERRUPT + * or ISOCHRONOUS type. + */ + } USB_Descriptor_Endpoint_t; + + /** \brief Standard USB Endpoint Descriptor (USB-IF naming conventions). + * + * Type define for a standard Endpoint Descriptor. This structure uses the relevant standard's given + * element names to ensure compatibility with the standard. + * + * \see \ref USB_Descriptor_Endpoint_t for the version of this type with non-standard LUFA specific + * element names. + */ + 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 (EP_TYPE_*) + * and attributes (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. + */ + } USB_StdDescriptor_Endpoint_t; + + /** \brief Standard USB String Descriptor (LUFA naming conventions). + * + * Type define for a standard string descriptor. Unlike other standard descriptors, the length + * of the descriptor for placement in the descriptor header must be determined by the \ref USB_STRING_LEN() + * macro rather than by the size of the descriptor structure, as the length is not fixed. + * + * This structure should also be used for string index 0, which contains the supported language IDs for + * the device as an array. + * + * This structure uses LUFA-specific element names to make each element's purpose clearer. + * + * \see \ref USB_StdDescriptor_String_t for the version of this type with standard element names. + */ + typedef struct + { + USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */ + + wchar_t UnicodeString[]; /**< String data, as unicode characters (alternatively, + * string language IDs). If normal ASCII characters are + * to be used, they must be added as an array of characters + * rather than a normal C string so that they are widened to + * Unicode size. + * + * Under GCC, strings prefixed with the "L" character (before + * the opening string quotation mark) are considered to be + * Unicode strings, and may be used instead of an explicit + * array of ASCII characters. + */ + } USB_Descriptor_String_t; + + /** \brief Standard USB String Descriptor (USB-IF naming conventions). + * + * Type define for a standard string descriptor. Unlike other standard descriptors, the length + * of the descriptor for placement in the descriptor header must be determined by the \ref USB_STRING_LEN() + * macro rather than by the size of the descriptor structure, as the length is not fixed. + * + * This structure should also be used for string index 0, which contains the supported language IDs for + * the device as an array. + * + * This structure uses the relevant standard's given element names to ensure compatibility with the standard. + * + * \see \ref USB_Descriptor_String_t for the version of this type with with non-standard LUFA specific + * element names. + */ + 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. + */ + int16_t bString[]; /**< String data, as unicode characters (alternatively, string language IDs). + * If normal ASCII characters are to be used, they must be added as an array + * of characters rather than a normal C string so that they are widened to + * Unicode size. + * + * Under GCC, strings prefixed with the "L" character (before the opening string + * quotation mark) are considered to be Unicode strings, and may be used instead + * of an explicit array of ASCII characters. + */ + } USB_StdDescriptor_String_t; + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define VERSION_TENS(x) (int)((x) / 10) + #define VERSION_ONES(x) (int)((x) - (10 * VERSION_TENS(x))) + #define VERSION_TENTHS(x) (int)(((x) - (int)(x)) * 10) + #define VERSION_HUNDREDTHS(x) (int)((((x) - (int)(x)) * 100) - (10 * VERSION_TENTHS(x))) + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/StdRequestType.h b/LUFA/Drivers/USB/HighLevel/StdRequestType.h new file mode 100644 index 0000000..7c18ead --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/StdRequestType.h @@ -0,0 +1,247 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB control endpoint request definitions. + * + * This file contains structures and macros for the easy creation and parsing of standard USB control requests. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_StdRequest Standard USB Requests + * + * This module contains definitions for the various control request parameters, so that the request + * details (such as data direction, request recipient, etc.) can be extracted via masking. + * + * @{ + */ + +#ifndef __STDREQTYPE_H__ +#define __STDREQTYPE_H__ + + /* Includes: */ + #include + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for the request type parameter, to indicate the direction of the request data (Host to Device + * or Device to Host). The result of this mask should then be compared to the request direction masks. + * + * \see REQDIR_* macros for masks indicating the request data direction. + */ + #define CONTROL_REQTYPE_DIRECTION 0x80 + + /** Mask for the request type parameter, to indicate the type of request (Device, Class or Vendor + * Specific). The result of this mask should then be compared to the request type masks. + * + * \see REQTYPE_* macros for masks indicating the request type. + */ + #define CONTROL_REQTYPE_TYPE 0x60 + + /** Mask for the request type parameter, to indicate the recipient of the request (Standard, Class + * or Vendor Specific). The result of this mask should then be compared to the request recipient + * masks. + * + * \see REQREC_* macros for masks indicating the request recipient. + */ + #define CONTROL_REQTYPE_RECIPIENT 0x1F + + /** \name Control Request Data Direction Masks */ + //@{ + /** Request data direction mask, indicating that the request data will flow from host to device. + * + * \see \ref CONTROL_REQTYPE_DIRECTION macro. + */ + #define REQDIR_HOSTTODEVICE (0 << 7) + + /** Request data direction mask, indicating that the request data will flow from device to host. + * + * \see \ref CONTROL_REQTYPE_DIRECTION macro. + */ + #define REQDIR_DEVICETOHOST (1 << 7) + //@} + + /** \name Control Request Type Masks */ + //@{ + /** Request type mask, indicating that the request is a standard request. + * + * \see \ref CONTROL_REQTYPE_TYPE macro. + */ + #define REQTYPE_STANDARD (0 << 5) + + /** Request type mask, indicating that the request is a class-specific request. + * + * \see \ref CONTROL_REQTYPE_TYPE macro. + */ + #define REQTYPE_CLASS (1 << 5) + + /** Request type mask, indicating that the request is a vendor specific request. + * + * \see \ref CONTROL_REQTYPE_TYPE macro. + */ + #define REQTYPE_VENDOR (2 << 5) + //@} + + /** \name Control Request Recipient Masks */ + //@{ + /** Request recipient mask, indicating that the request is to be issued to the device as a whole. + * + * \see \ref CONTROL_REQTYPE_RECIPIENT macro. + */ + #define REQREC_DEVICE (0 << 0) + + /** Request recipient mask, indicating that the request is to be issued to an interface in the + * currently selected configuration. + * + * \see \ref CONTROL_REQTYPE_RECIPIENT macro. + */ + #define REQREC_INTERFACE (1 << 0) + + /** Request recipient mask, indicating that the request is to be issued to an endpoint in the + * currently selected configuration. + * + * \see \ref CONTROL_REQTYPE_RECIPIENT macro. + */ + #define REQREC_ENDPOINT (2 << 0) + + /** Request recipient mask, indicating that the request is to be issued to an unspecified element + * in the currently selected configuration. + * + * \see \ref CONTROL_REQTYPE_RECIPIENT macro. + */ + #define REQREC_OTHER (3 << 0) + //@} + + /* Type Defines: */ + /** \brief Standard USB Control Request + * + * Type define for a standard USB control request. + * + * \see The USB 2.0 specification for more information on standard control requests. + */ + typedef struct + { + uint8_t bmRequestType; /**< Type of the request. */ + uint8_t bRequest; /**< Request command code. */ + uint16_t wValue; /**< wValue parameter of the request. */ + uint16_t wIndex; /**< wIndex parameter of the request. */ + uint16_t wLength; /**< Length of the data to transfer in bytes. */ + } USB_Request_Header_t; + + /* Enums: */ + /** Enumeration for the various standard request commands. These commands are applicable when the + * request type is \ref REQTYPE_STANDARD (with the exception of \ref REQ_GetDescriptor, which is always + * handled regardless of the request type value). + * + * \see Chapter 9 of the USB 2.0 Specification. + */ + enum USB_Control_Request_t + { + REQ_GetStatus = 0, /**< Implemented in the library for device, endpoint and interface + * recipients. Passed to the user application for other recipients + * via the \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_ClearFeature = 1, /**< Implemented in the library for device, endpoint and interface + * recipients. Passed to the user application for other recipients + * via the \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_SetFeature = 3, /**< Implemented in the library for device, endpoint and interface + * recipients. Passed to the user application for other recipients + * via the \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_SetAddress = 5, /**< Implemented in the library for the device recipient. Passed + * to the user application for other recipients via the + * \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_GetDescriptor = 6, /**< Implemented in the library for device and interface recipients. Passed to the + * user application for other recipients via the + * \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_SetDescriptor = 7, /**< Not implemented in the library, passed to the user application + * via the \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_GetConfiguration = 8, /**< Implemented in the library for the device recipient. Passed + * to the user application for other recipients via the + * \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_SetConfiguration = 9, /**< Implemented in the library for the device recipient. Passed + * to the user application for other recipients via the + * \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_GetInterface = 10, /**< Not implemented in the library, passed to the user application + * via the \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_SetInterface = 11, /**< Not implemented in the library, passed to the user application + * via the \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + REQ_SynchFrame = 12, /**< Not implemented in the library, passed to the user application + * via the \ref EVENT_USB_Device_ControlRequest() event when received in + * device mode. */ + }; + + /** Feature Selector values for Set Feature and Clear Feature standard control requests directed to the device, interface + * and endpoint recipients. + */ + enum USB_Feature_Selectors_t + { + FEATURE_SEL_EndpointHalt = 0x00, /**< Feature selector for Clear Feature or Set Feature commands. When + * used in a Set Feature or Clear Feature request this indicates that an + * endpoint (whose address is given elsewhere in the request should have + * its stall condition changed. + */ + FEATURE_SEL_DeviceRemoteWakeup = 0x01, /**< Feature selector for Device level Remote Wakeup enable set or clear. + * This feature can be controlled by the host on devices which indicate + * remote wakeup support in their descriptors to selectively disable or + * enable remote wakeup. + */ + FEATURE_SEL_TestMode = 0x02, /**< Feature selector for Test Mode features, used to test the USB controller + * to check for incorrect operation. + */ + }; + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define FEATURE_SELFPOWERED_ENABLED (1 << 0) + #define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1) + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/StreamCallbacks.h b/LUFA/Drivers/USB/HighLevel/StreamCallbacks.h new file mode 100644 index 0000000..6109de5 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/StreamCallbacks.h @@ -0,0 +1,87 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB endpoint/pipe stream callback management. + * + * This file contains definitions for the creation of optional callback routines which can be passed to the + * endpoint and/or pipe stream APIs, to abort the transfer currently in progress when a condition is met. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_StreamCallbacks Endpoint and Pipe Stream Callbacks + * + * Macros and enums for the stream callback routines. This module contains the code required to easily set up + * stream callback functions which can be used to force early abort of a stream read/write process. Each callback + * should take no arguments, and return a value from the \ref StreamCallback_Return_ErrorCodes_t enum. + * + * @{ + */ + +#ifndef __STREAMCALLBACK_H__ +#define __STREAMCALLBACK_H__ + + /* Includes: */ + #include + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Used with the Endpoint and Pipe stream functions as the callback function parameter, indicating that the stream + * call has no callback function to be called between USB packets. + */ + #define NO_STREAM_CALLBACK NULL + + /* Enums: */ + /** Enum for the possible error return codes of a stream callback function. */ + enum StreamCallback_Return_ErrorCodes_t + { + STREAMCALLBACK_Continue = 0, /**< Continue sending or receiving the stream. */ + STREAMCALLBACK_Abort = 1, /**< Abort the stream send or receiving process. */ + }; + + /* Type Defines: */ + /** Type define for a Stream Callback function (function taking no arguments and retuning a + * uint8_t value). Stream callback functions should have an identical function signature if they + * are to be used as the callback parameter of the stream functions. + */ + typedef uint8_t (* const StreamCallbackPtr_t)(void); + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_R.c b/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_R.c new file mode 100644 index 0000000..893a390 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_R.c @@ -0,0 +1,48 @@ +uint8_t TEMPLATE_FUNC_NAME (void* Buffer, + uint16_t Length) +{ + uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length)); + + if (!(Length)) + Endpoint_ClearOUT(); + + while (Length) + { + uint8_t USB_DeviceState_LCL = USB_DeviceState; + + if (USB_DeviceState_LCL == DEVICE_STATE_Unattached) + return ENDPOINT_RWCSTREAM_DeviceDisconnected; + else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended) + return ENDPOINT_RWCSTREAM_BusSuspended; + else if (Endpoint_IsSETUPReceived()) + return ENDPOINT_RWCSTREAM_HostAborted; + + if (Endpoint_IsOUTReceived()) + { + while (Length && Endpoint_BytesInEndpoint()) + { + TEMPLATE_TRANSFER_BYTE(DataStream); + Length--; + } + + Endpoint_ClearOUT(); + } + } + + while (!(Endpoint_IsINReady())) + { + uint8_t USB_DeviceState_LCL = USB_DeviceState; + + if (USB_DeviceState_LCL == DEVICE_STATE_Unattached) + return ENDPOINT_RWCSTREAM_DeviceDisconnected; + else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended) + return ENDPOINT_RWCSTREAM_BusSuspended; + } + + return ENDPOINT_RWCSTREAM_NoError; +} + + +#undef TEMPLATE_BUFFER_OFFSET +#undef TEMPLATE_FUNC_NAME +#undef TEMPLATE_TRANSFER_BYTE diff --git a/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_W.c b/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_W.c new file mode 100644 index 0000000..1bc550f --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_Control_W.c @@ -0,0 +1,56 @@ +uint8_t TEMPLATE_FUNC_NAME (const void* Buffer, + uint16_t Length) +{ + uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length)); + bool LastPacketFull = false; + + if (Length > USB_ControlRequest.wLength) + Length = USB_ControlRequest.wLength; + else if (!(Length)) + Endpoint_ClearIN(); + + while (Length || LastPacketFull) + { + uint8_t USB_DeviceState_LCL = USB_DeviceState; + + if (USB_DeviceState_LCL == DEVICE_STATE_Unattached) + return ENDPOINT_RWCSTREAM_DeviceDisconnected; + else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended) + return ENDPOINT_RWCSTREAM_BusSuspended; + else if (Endpoint_IsSETUPReceived()) + return ENDPOINT_RWCSTREAM_HostAborted; + else if (Endpoint_IsOUTReceived()) + break; + + if (Endpoint_IsINReady()) + { + uint16_t BytesInEndpoint = Endpoint_BytesInEndpoint(); + + while (Length && (BytesInEndpoint < USB_ControlEndpointSize)) + { + TEMPLATE_TRANSFER_BYTE(DataStream); + Length--; + BytesInEndpoint++; + } + + LastPacketFull = (BytesInEndpoint == USB_ControlEndpointSize); + Endpoint_ClearIN(); + } + } + + while (!(Endpoint_IsOUTReceived())) + { + uint8_t USB_DeviceState_LCL = USB_DeviceState; + + if (USB_DeviceState_LCL == DEVICE_STATE_Unattached) + return ENDPOINT_RWCSTREAM_DeviceDisconnected; + else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended) + return ENDPOINT_RWCSTREAM_BusSuspended; + } + + return ENDPOINT_RWCSTREAM_NoError; +} + +#undef TEMPLATE_BUFFER_OFFSET +#undef TEMPLATE_FUNC_NAME +#undef TEMPLATE_TRANSFER_BYTE diff --git a/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_RW.c b/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_RW.c new file mode 100644 index 0000000..a1a1e4b --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Template/Template_Endpoint_RW.c @@ -0,0 +1,79 @@ +uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE Buffer, + uint16_t Length + __CALLBACK_PARAM) +{ + uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length)); + uint8_t ErrorCode; + + if ((ErrorCode = Endpoint_WaitUntilReady())) + return ErrorCode; + + #if defined(FAST_STREAM_TRANSFERS) + uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07); + + if (Length >= 8) + { + Length -= BytesRemToAlignment; + + switch (BytesRemToAlignment) + { + default: + do + { + if (!(Endpoint_IsReadWriteAllowed())) + { + TEMPLATE_CLEAR_ENDPOINT(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return ENDPOINT_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Endpoint_WaitUntilReady())) + return ErrorCode; + } + + Length -= 8; + + TEMPLATE_TRANSFER_BYTE(DataStream); + case 7: TEMPLATE_TRANSFER_BYTE(DataStream); + case 6: TEMPLATE_TRANSFER_BYTE(DataStream); + case 5: TEMPLATE_TRANSFER_BYTE(DataStream); + case 4: TEMPLATE_TRANSFER_BYTE(DataStream); + case 3: TEMPLATE_TRANSFER_BYTE(DataStream); + case 2: TEMPLATE_TRANSFER_BYTE(DataStream); + case 1: TEMPLATE_TRANSFER_BYTE(DataStream); + } while (Length >= 8); + } + } + #endif + + while (Length) + { + if (!(Endpoint_IsReadWriteAllowed())) + { + TEMPLATE_CLEAR_ENDPOINT(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return ENDPOINT_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Endpoint_WaitUntilReady())) + return ErrorCode; + } + else + { + TEMPLATE_TRANSFER_BYTE(DataStream); + Length--; + } + } + + return ENDPOINT_RWSTREAM_NoError; +} + +#undef TEMPLATE_FUNC_NAME +#undef TEMPLATE_BUFFER_TYPE +#undef TEMPLATE_TRANSFER_BYTE +#undef TEMPLATE_CLEAR_ENDPOINT +#undef TEMPLATE_BUFFER_OFFSET diff --git a/LUFA/Drivers/USB/HighLevel/Template/Template_Pipe_RW.c b/LUFA/Drivers/USB/HighLevel/Template/Template_Pipe_RW.c new file mode 100644 index 0000000..3f8d91f --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/Template/Template_Pipe_RW.c @@ -0,0 +1,83 @@ +uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE Buffer, + uint16_t Length + __CALLBACK_PARAM) +{ + uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length)); + uint8_t ErrorCode; + + Pipe_SetPipeToken(TEMPLATE_TOKEN); + + if ((ErrorCode = Pipe_WaitUntilReady())) + return ErrorCode; + + #if defined(FAST_STREAM_TRANSFERS) + uint8_t BytesRemToAlignment = (Pipe_BytesInPipe() & 0x07); + + if (Length >= 8) + { + Length -= BytesRemToAlignment; + + switch (BytesRemToAlignment) + { + default: + do + { + if (!(Pipe_IsReadWriteAllowed())) + { + TEMPLATE_CLEAR_PIPE(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return PIPE_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Pipe_WaitUntilReady())) + return ErrorCode; + } + + Length -= 8; + + TEMPLATE_TRANSFER_BYTE(DataStream); + case 7: TEMPLATE_TRANSFER_BYTE(DataStream); + case 6: TEMPLATE_TRANSFER_BYTE(DataStream); + case 5: TEMPLATE_TRANSFER_BYTE(DataStream); + case 4: TEMPLATE_TRANSFER_BYTE(DataStream); + case 3: TEMPLATE_TRANSFER_BYTE(DataStream); + case 2: TEMPLATE_TRANSFER_BYTE(DataStream); + case 1: TEMPLATE_TRANSFER_BYTE(DataStream); + } while (Length >= 8); + } + } + #endif + + while (Length) + { + if (!(Pipe_IsReadWriteAllowed())) + { + TEMPLATE_CLEAR_PIPE(); + + #if !defined(NO_STREAM_CALLBACKS) + if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort)) + return PIPE_RWSTREAM_CallbackAborted; + #endif + + if ((ErrorCode = Pipe_WaitUntilReady())) + return ErrorCode; + } + else + { + TEMPLATE_TRANSFER_BYTE(DataStream); + Length--; + } + } + + return PIPE_RWSTREAM_NoError; +} + +#undef TEMPLATE_FUNC_NAME +#undef TEMPLATE_BUFFER_TYPE +#undef TEMPLATE_TOKEN +#undef TEMPLATE_TRANSFER_BYTE +#undef TEMPLATE_CLEAR_PIPE +#undef TEMPLATE_BUFFER_OFFSET + diff --git a/LUFA/Drivers/USB/HighLevel/USBMode.h b/LUFA/Drivers/USB/HighLevel/USBMode.h new file mode 100644 index 0000000..09d3631 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/USBMode.h @@ -0,0 +1,138 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB mode and capability macros. + * + * This file defines macros indicating the type of USB controller the library is being compiled for, and its + * capabilities. These macros may then be referenced in the user application to selectively enable or disable + * code sections depending on if they are defined or not. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_USBMode USB Mode Tokens + * + * After the inclusion of the master USB driver header, one or more of the following + * tokens may be defined, to allow the user code to conditionally enable or disable + * code based on the USB controller family and allowable USB modes. These tokens may + * be tested against to eliminate code relating to a USB mode which is not enabled for + * the given compilation. + * + * @{ + */ + +#ifndef __USBMODE_H__ +#define __USBMODE_H__ + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + #if defined(__DOXYGEN__) + /** Indicates that the target AVR microcontroller belongs to the Series 2 USB controller + * (i.e. AT90USBxxx2 or ATMEGAxxU2) when defined. + */ + #define USB_SERIES_2_AVR + + /** Indicates that the target AVR microcontroller belongs to the Series 4 USB controller + * (i.e. ATMEGAxxU4) when defined. + */ + #define USB_SERIES_4_AVR + + /** Indicates that the target AVR microcontroller belongs to the Series 6 USB controller + * (i.e. AT90USBxxx6) when defined. + */ + #define USB_SERIES_6_AVR + + /** Indicates that the target AVR microcontroller belongs to the Series 7 USB controller + * (i.e. AT90USBxxx7) when defined. + */ + #define USB_SERIES_7_AVR + + /** Indicates that the target AVR microcontroller and compilation settings allow for the + * target to be configured in USB Device mode when defined. + */ + #define USB_CAN_BE_DEVICE + + /** Indicates that the target AVR microcontroller and compilation settings allow for the + * target to be configured in USB Host mode when defined. + */ + #define USB_CAN_BE_HOST + + /** Indicates that the target AVR microcontroller and compilation settings allow for the + * target to be configured in either USB Device or Host mode when defined. + */ + #define USB_CAN_BE_BOTH + #else + /* Macros: */ + #if (defined(__AVR_AT90USB162__) || defined(__AVR_AT90USB82__) || \ + defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)) + #define USB_SERIES_2_AVR + #elif (defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)) + #define USB_SERIES_4_AVR + #elif (defined(__AVR_ATmega32U6__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) + #define USB_SERIES_6_AVR + #elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)) + #define USB_SERIES_7_AVR + #endif + + #if !defined(USB_SERIES_7_AVR) + #if defined(USB_HOST_ONLY) + #error USB_HOST_ONLY is not available for the currently selected USB AVR model. + #endif + + #if !defined(USB_DEVICE_ONLY) + #define USB_DEVICE_ONLY + #endif + #endif + + #if (!defined(USB_DEVICE_ONLY) && !defined(USB_HOST_ONLY)) + #define USB_CAN_BE_BOTH + #define USB_CAN_BE_HOST + #define USB_CAN_BE_DEVICE + #elif defined(USB_HOST_ONLY) + #define USB_CAN_BE_HOST + #elif defined(USB_DEVICE_ONLY) + #define USB_CAN_BE_DEVICE + #endif + + #if (defined(USB_HOST_ONLY) && defined(USB_DEVICE_ONLY)) + #error USB_HOST_ONLY and USB_DEVICE_ONLY are mutually exclusive. + #endif + #endif + +#endif + +/** @} */ diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.c b/LUFA/Drivers/USB/HighLevel/USBTask.c new file mode 100644 index 0000000..6967283 --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/USBTask.c @@ -0,0 +1,89 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USBTASK_C +#define __INCLUDE_FROM_USB_DRIVER +#include "USBTask.h" + +volatile bool USB_IsInitialized; +USB_Request_Header_t USB_ControlRequest; + +#if defined(USB_CAN_BE_HOST) && !defined(HOST_STATE_AS_GPIOR) +volatile uint8_t USB_HostState; +#endif + +#if defined(USB_CAN_BE_DEVICE) && !defined(DEVICE_STATE_AS_GPIOR) +volatile uint8_t USB_DeviceState; +#endif + +void USB_USBTask(void) +{ + #if defined(USB_HOST_ONLY) + USB_HostTask(); + #elif defined(USB_DEVICE_ONLY) + USB_DeviceTask(); + #else + if (USB_CurrentMode == USB_MODE_Device) + USB_DeviceTask(); + else if (USB_CurrentMode == USB_MODE_Host) + USB_HostTask(); + #endif +} + +#if defined(USB_CAN_BE_DEVICE) +static void USB_DeviceTask(void) +{ + if (USB_DeviceState != DEVICE_STATE_Unattached) + { + uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint(); + + Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); + + if (Endpoint_IsSETUPReceived()) + USB_Device_ProcessControlRequest(); + + Endpoint_SelectEndpoint(PrevEndpoint); + } +} +#endif + +#if defined(USB_CAN_BE_HOST) +static void USB_HostTask(void) +{ + uint8_t PrevPipe = Pipe_GetCurrentPipe(); + + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + USB_Host_ProcessNextHostState(); + + Pipe_SelectPipe(PrevPipe); +} +#endif + diff --git a/LUFA/Drivers/USB/HighLevel/USBTask.h b/LUFA/Drivers/USB/HighLevel/USBTask.h new file mode 100644 index 0000000..0af39bf --- /dev/null +++ b/LUFA/Drivers/USB/HighLevel/USBTask.h @@ -0,0 +1,206 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Main USB service task management. + * + * This file contains the function definitions required for the main USB service task, which must be called + * from the user application to ensure that the USB connection to or from a connected USB device is maintained. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +#ifndef __USBTASK_H__ +#define __USBTASK_H__ + + /* Includes: */ + #include + #include + #include + + #include "../LowLevel/USBController.h" + #include "Events.h" + #include "StdRequestType.h" + #include "StdDescriptors.h" + #include "USBMode.h" + + #if defined(USB_CAN_BE_DEVICE) + #include "DeviceStandardReq.h" + #endif + + #if defined(USB_CAN_BE_HOST) + #include "HostStandardReq.h" + #endif + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Global Variables: */ + /** Indicates if the USB interface is currently initialized but not necessarily connected to a host + * or device (i.e. if \ref USB_Init() has been run). If this is false, all other library globals related + * to the USB driver are invalid. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + * + * \ingroup Group_USBManagement + */ + extern volatile bool USB_IsInitialized; + + /** Structure containing the last received Control request when in Device mode (for use in user-applications + * inside of the \ref EVENT_USB_Device_ControlRequest() event, or for filling up with a control request to + * issue when in Host mode before calling \ref USB_Host_SendControlRequest(). + * + * \ingroup Group_USBManagement + */ + extern USB_Request_Header_t USB_ControlRequest; + + #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__) + #if !defined(HOST_STATE_AS_GPIOR) || defined(__DOXYGEN__) + /** Indicates the current host state machine state. When in host mode, this indicates the state + * via one of the values of the \ref USB_Host_States_t enum values. + * + * This value may be altered by the user application to implement the \ref HOST_STATE_Addressed, + * \ref HOST_STATE_Configured and \ref HOST_STATE_Suspended states which are not implemented by + * the library internally. + * + * To reduce program size and speed up checks of this global, it can be placed into one of the AVR's + * GPIOR hardware registers instead of RAM by defining the HOST_STATE_AS_GPIOR token to a value + * between 0 and 2 in the project makefile and passing it to the compiler via the -D switch. When + * defined, the corresponding GPIOR register should not be used in the user application except + * implicitly via the library APIs. + * + * \note This global is only present if the user application can be a USB host. + * + * \see \ref USB_Host_States_t for a list of possible device states. + * + * \ingroup Group_Host + */ + extern volatile uint8_t USB_HostState; + #else + #define _GET_HOST_GPIOR_NAME2(y) GPIOR ## y + #define _GET_HOST_GPIOR_NAME(x) _GET_HOST_GPIOR_NAME2(x) + #define USB_HostState _GET_HOST_GPIOR_NAME(HOST_STATE_AS_GPIOR) + #endif + #endif + + #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__) + #if !defined(DEVICE_STATE_AS_GPIOR) || defined(__DOXYGEN__) + /** Indicates the current device state machine state. When in device mode, this indicates the state + * via one of the values of the \ref USB_Device_States_t enum values. + * + * This value should not be altered by the user application as it is handled automatically by the + * library. The only exception to this rule is if the NO_LIMITED_CONTROLLER_CONNECT token is used + * (see \ref EVENT_USB_Device_Connect() and \ref EVENT_USB_Device_Disconnect() events). + * + * To reduce program size and speed up checks of this global, it can be placed into one of the AVR's + * GPIOR hardware registers instead of RAM by defining the DEVICE_STATE_AS_GPIOR token to a value + * between 0 and 2 in the project makefile and passing it to the compiler via the -D switch. When + * defined, the corresponding GPIOR register should not be used in the user application except + * implicitly via the library APIs. + * + * \note This global is only present if the user application can be a USB device. + * \n\n + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value except in the circumstances outlined above. + * + * \see \ref USB_Device_States_t for a list of possible device states. + * + * \ingroup Group_Device + */ + extern volatile uint8_t USB_DeviceState; + #else + #define _GET_DEVICE_GPIOR_NAME2(y) GPIOR ## y + #define _GET_DEVICE_GPIOR_NAME(x) _GET_DEVICE_GPIOR_NAME2(x) + #define USB_DeviceState _GET_DEVICE_GPIOR_NAME(DEVICE_STATE_AS_GPIOR) + #endif + #endif + + /* Function Prototypes: */ + /** This is the main USB management task. The USB driver requires this task to be executed + * continuously when the USB system is active (device attached in host mode, or attached to a host + * in device mode) in order to manage USB communications. This task may be executed inside an RTOS, + * fast timer ISR or the main user application loop. + * + * The USB task must be serviced within 30ms while in device mode, or within 1ms while in host mode. + * The task may be serviced at all times, or (for minimum CPU consumption): + * + * - In device mode, it may be disabled at start-up, enabled on the firing of the \ref EVENT_USB_Device_Connect() + * event and disabled again on the firing of the \ref EVENT_USB_Device_Disconnect() event. + * + * - In host mode, it may be disabled at start-up, enabled on the firing of the \ref EVENT_USB_Host_DeviceAttached() + * event and disabled again on the firing of the \ref EVENT_USB_Host_DeviceEnumerationComplete() or + * \ref EVENT_USB_Host_DeviceEnumerationFailed() events. + * + * If in device mode (only), the control endpoint can instead be managed via interrupts entirely by the library + * by defining the INTERRUPT_CONTROL_ENDPOINT token and passing it to the compiler via the -D switch. + * + * \see \ref Group_Events for more information on the USB events. + * + * \ingroup Group_USBManagement + */ + void USB_USBTask(void); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Function Prototypes: */ + #if defined(__INCLUDE_FROM_USBTASK_C) + #if defined(USB_CAN_BE_HOST) + static void USB_HostTask(void); + #endif + + #if defined(USB_CAN_BE_DEVICE) + static void USB_DeviceTask(void); + #endif + #endif + + /* Macros: */ + #define HOST_TASK_NONBLOCK_WAIT(Duration, NextState) MACROS{ USB_HostState = HOST_STATE_WaitForDevice; \ + WaitMSRemaining = (Duration); \ + PostWaitState = (NextState); }MACROE + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + diff --git a/LUFA/Drivers/USB/LowLevel/Device.c b/LUFA/Drivers/USB/LowLevel/Device.c new file mode 100644 index 0000000..917fc19 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Device.c @@ -0,0 +1,53 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../HighLevel/USBMode.h" + +#if defined(USB_CAN_BE_DEVICE) + +#include "Device.h" + +void USB_Device_SendRemoteWakeup(void) +{ + if (!(USB_Options & USB_OPT_MANUAL_PLL)) + { + USB_PLL_On(); + while (!(USB_PLL_IsReady())); + } + + USB_CLK_Unfreeze(); + + UDCON |= (1 << RMWKUP); + while (!(UDCON & (1 << RMWKUP))); +} + +#endif + diff --git a/LUFA/Drivers/USB/LowLevel/Device.h b/LUFA/Drivers/USB/LowLevel/Device.h new file mode 100644 index 0000000..631c883 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Device.h @@ -0,0 +1,247 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB device mode definitions. + * + * This file contains structures, function prototypes and macros related to USB device mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_Device Device Management + * + * USB Device mode related macros and enums. This module contains macros and enums which are used when + * the USB controller is initialized in device mode. + * + * @{ + */ + +#ifndef __USBDEVICE_H__ +#define __USBDEVICE_H__ + + /* Includes: */ + #include + #include + #include + + #include "../../../Common/Common.h" + #include "../HighLevel/StdDescriptors.h" + #include "USBInterrupt.h" + #include "Endpoint.h" + + /* Preprocessor Checks: */ + #if (defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS)) + #error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive. + #endif + + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name USB Device Mode Option Masks */ + //@{ + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__) + /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the + * USB interface should be initialized in low speed (1.5Mb/s) mode. + * + * \note Low Speed mode is not available on all USB AVR models. + * \n + * + * \note Restrictions apply on the number, size and type of endpoints which can be used + * when running in low speed mode - refer to the USB 2.0 specification. + */ + #define USB_DEVICE_OPT_LOWSPEED (1 << 0) + #endif + + /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the + * USB interface should be initialized in full speed (12Mb/s) mode. + */ + #define USB_DEVICE_OPT_FULLSPEED (0 << 0) + //@} + + /* Function Prototypes: */ + /** Sends a Remote Wakeup request to the host. This signals to the host that the device should + * be taken out of suspended mode, and communications should resume. + * + * Typically, this is implemented so that HID devices (mice, keyboards, etc.) can wake up the + * host computer when the host has suspended all USB devices to enter a low power state. + * + * \note This macro should only be used if the device has indicated to the host that it + * supports the Remote Wakeup feature in the device descriptors, and should only be + * issued if the host is currently allowing remote wakeup events from the device (i.e., + * the \ref USB_RemoteWakeupEnabled flag is set). When the NO_DEVICE_REMOTE_WAKEUP compile + * time option is used, this macro is unavailable. + * \n\n + * + * \note The USB clock must be running for this function to operate. If the stack is initialized with + * the \ref USB_OPT_MANUAL_PLL option enabled, the user must ensure that the PLL is running + * before attempting to call this function. + * + * \see \ref Group_Descriptors for more information on the RMWAKEUP feature and device descriptors. + */ + void USB_Device_SendRemoteWakeup(void); + + /* Type Defines: */ + enum USB_Device_States_t + { + DEVICE_STATE_Unattached = 0, /**< Internally implemented by the library. This state indicates + * that the device is not currently connected to a host. + */ + DEVICE_STATE_Powered = 1, /**< Internally implemented by the library. This state indicates + * that the device is connected to a host, but enumeration has not + * yet begun. + */ + DEVICE_STATE_Default = 2, /**< Internally implemented by the library. This state indicates + * that the device's USB bus has been reset by the host and it is + * now waiting for the host to begin the enumeration process. + */ + DEVICE_STATE_Addressed = 3, /**< Internally implemented by the library. This state indicates + * that the device has been addressed by the USB Host, but is not + * yet configured. + */ + DEVICE_STATE_Configured = 4, /**< May be implemented by the user project. This state indicates + * that the device has been enumerated by the host and is ready + * for USB communications to begin. + */ + DEVICE_STATE_Suspended = 5, /**< May be implemented by the user project. This state indicates + * that the USB bus has been suspended by the host, and the device + * should power down to a minimal power level until the bus is + * resumed. + */ + }; + + /* Inline Functions: */ + /** Returns the current USB frame number, when in device mode. Every millisecond the USB bus is active (i.e. enumerated to a host) + * the frame number is incremented by one. + */ + static inline uint16_t USB_Device_GetFrameNumber(void) + { + return UDFNUM; + } + + #if !defined(NO_SOF_EVENTS) + /** Enables the device mode Start Of Frame events. When enabled, this causes the + * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus, + * at the start of each USB frame when enumerated in device mode. + * + * \note Not available when the NO_SOF_EVENTS compile time token is defined. + */ + static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_EnableSOFEvents(void) + { + USB_INT_Enable(USB_INT_SOFI); + } + + /** Disables the device mode Start Of Frame events. When disabled, this stops the firing of the + * \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode. + * + * \note Not available when the NO_SOF_EVENTS compile time token is defined. + */ + static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_DisableSOFEvents(void) + { + USB_INT_Disable(USB_INT_SOFI); + } + #endif + + /* Function Prototypes: */ + /** Function to retrieve a given descriptor's size and memory location from the given descriptor type value, + * index and language ID. This function MUST be overridden in the user application (added with full, identical + * prototype and name so that the library can call it to retrieve descriptor data. + * + * \param[in] wValue The type of the descriptor to retrieve in the upper byte, and the index in the + * lower byte (when more than one descriptor of the given type exists, such as the + * case of string descriptors). The type may be one of the standard types defined + * in the DescriptorTypes_t enum, or may be a class-specific descriptor type value. + * \param[in] wIndex The language ID of the string to return if the wValue type indicates DTYPE_String, + * otherwise zero for standard descriptors, or as defined in a class-specific + * standards. + * \param[out] DescriptorAddress Pointer to the descriptor in memory. This should be set by the routine to + * the address of the descriptor. + * \param[out] MemoryAddressSpace A value from the \ref USB_DescriptorMemorySpaces_t enum to indicate the memory + * space in which the descriptor is stored. This parameter does not exist when one + * of the USE_*_DESCRIPTORS compile time options is used. + * + * \note By default, the library expects all descriptors to be located in flash memory via the PROGMEM attribute. + * If descriptors should be located in RAM or EEPROM instead (to speed up access in the case of RAM, or to + * allow the descriptors to be changed dynamically at runtime) either the USE_RAM_DESCRIPTORS or the + * USE_EEPROM_DESCRIPTORS tokens may be defined in the project makefile and passed to the compiler by the -D + * switch. + * + * \return Size in bytes of the descriptor if it exists, zero or \ref NO_DESCRIPTOR otherwise. + */ + uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, + const uint8_t wIndex, + const void** const DescriptorAddress + #if !defined(USE_FLASH_DESCRIPTORS) && !defined(USE_EEPROM_DESCRIPTORS) && !defined(USE_RAM_DESCRIPTORS) + , uint8_t* MemoryAddressSpace + #endif + ) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Inline Functions: */ + #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) + static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_SetLowSpeed(void) + { + UDCON |= (1 << LSM); + } + + static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_SetFullSpeed(void) + { + UDCON &= ~(1 << LSM); + } + #endif + + static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void USB_Device_SetDeviceAddress(const uint8_t Address) + { + UDADDR = ((UDADDR & (1 << ADDEN)) | (Address & 0x7F)); + UDADDR |= (1 << ADDEN); + } + + static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE; + static inline bool USB_Device_IsAddressSet(void) + { + return (UDADDR & (1 << ADDEN)); + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.c b/LUFA/Drivers/USB/LowLevel/Endpoint.c new file mode 100644 index 0000000..6fb842b --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Endpoint.c @@ -0,0 +1,141 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../HighLevel/USBMode.h" + +#if defined(USB_CAN_BE_DEVICE) + +#include "Endpoint.h" + +#if !defined(FIXED_CONTROL_ENDPOINT_SIZE) +uint8_t USB_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE; +#endif + +bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number, + const uint8_t UECFG0XData, + const uint8_t UECFG1XData) +{ + Endpoint_SelectEndpoint(Number); + Endpoint_EnableEndpoint(); + + UECFG1X = 0; + UECFG0X = UECFG0XData; + UECFG1X = UECFG1XData; + + return Endpoint_IsConfigured(); +} + +void Endpoint_ClearEndpoints(void) +{ + UEINT = 0; + + for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++) + { + Endpoint_SelectEndpoint(EPNum); + UEIENX = 0; + UEINTX = 0; + UECFG1X = 0; + Endpoint_DisableEndpoint(); + } +} + +void Endpoint_ClearStatusStage(void) +{ + if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST) + { + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + + Endpoint_ClearOUT(); + } + else + { + while (!(Endpoint_IsINReady())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + + Endpoint_ClearIN(); + } +} + +#if !defined(CONTROL_ONLY_DEVICE) +uint8_t Endpoint_WaitUntilReady(void) +{ + #if (USB_STREAM_TIMEOUT_MS < 0xFF) + uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; + #else + uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; + #endif + + uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber(); + + for (;;) + { + if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN) + { + if (Endpoint_IsINReady()) + return ENDPOINT_READYWAIT_NoError; + } + else + { + if (Endpoint_IsOUTReceived()) + return ENDPOINT_READYWAIT_NoError; + } + + uint8_t USB_DeviceState_LCL = USB_DeviceState; + + if (USB_DeviceState_LCL == DEVICE_STATE_Unattached) + return ENDPOINT_READYWAIT_DeviceDisconnected; + else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended) + return ENDPOINT_READYWAIT_BusSuspended; + else if (Endpoint_IsStalled()) + return ENDPOINT_READYWAIT_EndpointStalled; + + uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber(); + + if (CurrentFrameNumber != PreviousFrameNumber) + { + PreviousFrameNumber = CurrentFrameNumber; + + if (!(TimeoutMSRem--)) + return ENDPOINT_READYWAIT_Timeout; + } + } +} +#endif + +#endif + diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.h b/LUFA/Drivers/USB/LowLevel/Endpoint.h new file mode 100644 index 0000000..88856d8 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Endpoint.h @@ -0,0 +1,892 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB device endpoint management definitions. + * + * This file contains structures, function prototypes and macros related to the management of the device's + * data endpoints when the library is initialized in USB device mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_EndpointManagement + * @defgroup Group_EndpointRW Endpoint Data Reading and Writing + * + * Functions, macros, variables, enums and types related to data reading and writing from and to endpoints. + */ + +/** \ingroup Group_EndpointRW + * @defgroup Group_EndpointPrimitiveRW Read/Write of Primitive Data Types + * + * Functions, macros, variables, enums and types related to data reading and writing of primitive data types + * from and to endpoints. + */ + +/** \ingroup Group_EndpointManagement + * @defgroup Group_EndpointPacketManagement Endpoint Packet Management + * + * Functions, macros, variables, enums and types related to packet management of endpoints. + */ + +/** \ingroup Group_USB + * @defgroup Group_EndpointManagement Endpoint Management + * + * Functions, macros and enums related to endpoint management when in USB Device mode. This + * module contains the endpoint management macros, as well as endpoint interrupt and data + * send/receive functions for various data types. + * + * @{ + */ + +#ifndef __ENDPOINT_H__ +#define __ENDPOINT_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + #include "../HighLevel/USBTask.h" + #include "USBInterrupt.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define _ENDPOINT_GET_MAXSIZE(EPIndex) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex) + #define _ENDPOINT_GET_MAXSIZE2(EPDetails) _ENDPOINT_GET_MAXSIZE3(EPDetails) + #define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize) + + #define _ENDPOINT_GET_BANKS(EPIndex) _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex) + #define _ENDPOINT_GET_BANKS2(EPDetails) _ENDPOINT_GET_BANKS3(EPDetails) + #define _ENDPOINT_GET_BANKS3(MaxSize, Banks) (Banks) + + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + #define ENDPOINT_DETAILS_MAXEP 7 + + #define ENDPOINT_DETAILS_EP0 64, 2 + #define ENDPOINT_DETAILS_EP1 256, 2 + #define ENDPOINT_DETAILS_EP2 64, 2 + #define ENDPOINT_DETAILS_EP3 64, 2 + #define ENDPOINT_DETAILS_EP4 64, 2 + #define ENDPOINT_DETAILS_EP5 64, 2 + #define ENDPOINT_DETAILS_EP6 64, 2 + #else + #define ENDPOINT_DETAILS_MAXEP 5 + + #define ENDPOINT_DETAILS_EP0 64, 2 + #define ENDPOINT_DETAILS_EP1 64, 1 + #define ENDPOINT_DETAILS_EP2 64, 1 + #define ENDPOINT_DETAILS_EP3 64, 2 + #define ENDPOINT_DETAILS_EP4 64, 2 + #endif + + /* Inline Functions: */ + static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST + ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) + { + uint8_t MaskVal = 0; + uint16_t CheckBytes = 8; + + while (CheckBytes < Bytes) + { + MaskVal++; + CheckBytes <<= 1; + } + + return (MaskVal << EPSIZE0); + } + + /* Function Prototypes: */ + void Endpoint_ClearEndpoints(void); + bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number, + const uint8_t UECFG0XData, + const uint8_t UECFG1XData); + + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name Endpoint Direction Masks */ + //@{ + /** Endpoint data direction mask for \ref Endpoint_ConfigureEndpoint(). This indicates that the endpoint + * should be initialized in the OUT direction - i.e. data flows from host to device. + */ + #define ENDPOINT_DIR_OUT (0 << EPDIR) + + /** Endpoint data direction mask for \ref Endpoint_ConfigureEndpoint(). This indicates that the endpoint + * should be initialized in the IN direction - i.e. data flows from device to host. + */ + #define ENDPOINT_DIR_IN (1 << EPDIR) + //@} + + /** \name Endpoint Bank Mode Masks */ + //@{ + /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates + * that the endpoint should have one single bank, which requires less USB FIFO memory but results + * in slower transfers as only one USB device (the AVR or the host) can access the endpoint's + * bank at the one time. + */ + #define ENDPOINT_BANK_SINGLE (0 << EPBK0) + + /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates + * that the endpoint should have two banks, which requires more USB FIFO memory but results + * in faster transfers as one USB device (the AVR or the host) can access one bank while the other + * accesses the second bank. + */ + #define ENDPOINT_BANK_DOUBLE (1 << EPBK0) + //@} + + /** Endpoint address for the default control endpoint, which always resides in address 0. This is + * defined for convenience to give more readable code when used with the endpoint macros. + */ + #define ENDPOINT_CONTROLEP 0 + + #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) + /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size + * value in the device descriptor. Not available if the FIXED_CONTROL_ENDPOINT_SIZE token is defined. + */ + #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8 + #endif + + /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's + * numerical address in the device. + */ + #define ENDPOINT_EPNUM_MASK 0x07 + + /** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's + * direction for comparing with the ENDPOINT_DESCRIPTOR_DIR_* masks. + */ + #define ENDPOINT_EPDIR_MASK 0x80 + + /** Endpoint bank size mask, for masking against endpoint addresses to retrieve the endpoint's + * bank size in the device. + */ + #define ENDPOINT_EPSIZE_MASK 0x7F + + /** Maximum size in bytes of a given endpoint. + * + * \param[in] EPIndex Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1) + */ + #define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex) + + /** Indicates the total number of banks supported by the given endpoint. + * + * \param[in] EPIndex Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1) + */ + #define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex) + + #if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__) + /** Total number of endpoints (including the default control endpoint at address 0) which may + * be used in the device. Different USB AVR models support different amounts of endpoints, + * this value reflects the maximum number of endpoints for the currently selected AVR model. + */ + #define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP + #else + #define ENDPOINT_TOTAL_ENDPOINTS 1 + #endif + + /* Enums: */ + /** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function. + * + * \ingroup Group_EndpointRW + */ + enum Endpoint_WaitUntilReady_ErrorCodes_t + { + ENDPOINT_READYWAIT_NoError = 0, /**< Endpoint is ready for next packet, no error. */ + ENDPOINT_READYWAIT_EndpointStalled = 1, /**< The endpoint was stalled during the stream + * transfer by the host or device. + */ + ENDPOINT_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while + * waiting for the endpoint to become ready. + */ + ENDPOINT_READYWAIT_BusSuspended = 3, /**< The USB bus has been suspended by the host and + * no USB endpoint traffic can occur until the bus + * has resumed. + */ + ENDPOINT_READYWAIT_Timeout = 4, /**< The host failed to accept or send the next packet + * within the software timeout period set by the + * \ref USB_STREAM_TIMEOUT_MS macro. + */ + }; + + /* Inline Functions: */ + /** Configures the specified endpoint number with the given endpoint type, direction, bank size + * and banking mode. Once configured, the endpoint may be read from or written to, depending + * on its direction. + * + * \param[in] Number Endpoint number to configure. This must be more than 0 and less than + * \ref ENDPOINT_TOTAL_ENDPOINTS. + * + * \param[in] Type Type of endpoint to configure, a EP_TYPE_* mask. Not all endpoint types + * are available on Low Speed USB devices - refer to the USB 2.0 specification. + * + * \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN. + * All endpoints (except Control type) are unidirectional - data may only be read + * from or written to the endpoint bank based on its direction, not both. + * + * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted + * to the USB host, or after they have been received from the USB host (depending on + * the endpoint's data direction). The bank size must indicate the maximum packet size + * that the endpoint can handle. + * + * \param[in] Banks Number of banks to use for the endpoint being configured, an ENDPOINT_BANK_* mask. + * More banks uses more USB DPRAM, but offers better performance. Isochronous type + * endpoints must have at least two banks. + * + * \note Endpoints must be configured in ascending order, or bank corruption will occur. + * \n\n + * + * \note Certain models of USB AVR's endpoints may have different maximum packet sizes based on the endpoint's + * index - refer to the chosen USB AVR's datasheet to determine the maximum bank size for each endpoint. + * \n\n + * + * \note The default control endpoint should not be manually configured by the user application, as + * it is automatically configured by the library internally. + * \n\n + * + * \note This routine will automatically select the specified endpoint upon success. Upon failure, the endpoint + * which failed to reconfigure correctly will be selected. + * + * \return Boolean true if the configuration succeeded, false otherwise. + */ + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + const uint8_t Type, + const uint8_t Direction, + const uint16_t Size, + const uint8_t Banks) ATTR_ALWAYS_INLINE; + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + const uint8_t Type, + const uint8_t Direction, + const uint16_t Size, + const uint8_t Banks) + { + return Endpoint_ConfigureEndpoint_Prv(Number, (((Type) << EPTYPE0) | (Direction)), + ((1 << ALLOC) | Banks | Endpoint_BytesToEPSizeMask(Size))); + } + + /** Indicates the number of bytes currently stored in the current endpoint's selected bank. + * + * \note The return width of this function may differ, depending on the maximum endpoint bank size + * of the selected AVR model. + * + * \ingroup Group_EndpointRW + * + * \return Total number of bytes in the currently selected Endpoint's FIFO buffer. + */ + static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t Endpoint_BytesInEndpoint(void) + { + #if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + return UEBCX; + #elif defined(USB_SERIES_4_AVR) + return (((uint16_t)UEBCHX << 8) | UEBCLX); + #elif defined(USB_SERIES_2_AVR) + return UEBCLX; + #endif + } + + /** Get the endpoint address of the currently selected endpoint. This is typically used to save + * the currently selected endpoint number so that it can be restored after another endpoint has + * been manipulated. + * + * \return Index of the currently selected endpoint. + */ + static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_GetCurrentEndpoint(void) + { + #if !defined(CONTROL_ONLY_DEVICE) + return (UENUM & ENDPOINT_EPNUM_MASK); + #else + return ENDPOINT_CONTROLEP; + #endif + } + + /** Selects the given endpoint number. If the address from the device descriptors is used, the + * value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint + * number (and discarding the endpoint direction bit). + * + * Any endpoint operations which do not require the endpoint number to be indicated will operate on + * the currently selected endpoint. + * + * \param[in] EndpointNumber Endpoint number to select. + */ + static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; + static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) + { + #if !defined(CONTROL_ONLY_DEVICE) + UENUM = EndpointNumber; + #endif + } + + /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's + * In and Out pointers to the bank's contents. + * + * \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset. + */ + static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber) + { + UERST = (1 << EndpointNumber); + UERST = 0; + } + + /** Enables the currently selected endpoint so that data can be sent and received through it to + * and from a host. + * + * \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint(). + */ + static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_EnableEndpoint(void) + { + UECONX |= (1 << EPEN); + } + + /** Disables the currently selected endpoint so that data cannot be sent and received through it + * to and from a host. + */ + static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_DisableEndpoint(void) + { + UECONX &= ~(1 << EPEN); + } + + /** Determines if the currently selected endpoint is enabled, but not necessarily configured. + * + * \return Boolean True if the currently selected endpoint is enabled, false otherwise. + */ + static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsEnabled(void) + { + return ((UECONX & (1 << EPEN)) ? true : false); + } + + /** Aborts all pending IN transactions on the currently selected endpoint, once the bank + * has been queued for transmission to the host via \ref Endpoint_ClearIN(). This function + * will terminate all queued transactions, resetting the endpoint banks ready for a new + * packet. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_AbortPendingIN(void) + { + while (UESTA0X & (0x03 << NBUSYBK0)) + { + UEINTX |= (1 << RXOUTI); + while (UEINTX & (1 << RXOUTI)); + } + } + + /** Retrieves the number of busy banks in the currently selected endpoint, which have been queued for + * transmission via the \ref Endpoint_ClearIN() command, or are awaiting acknowledgement via the + * \ref Endpoint_ClearOUT() command. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Total number of busy banks in the selected endpoint. + */ + static inline uint8_t Endpoint_GetBusyBanks(void) + { + return (UESTA0X & (0x03 << NBUSYBK0)); + } + + /** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint + * bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN + * direction). This function will return false if an error has occurred in the endpoint, if the endpoint + * is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN + * direction and the endpoint bank is full. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the currently selected endpoint may be read from or written to, depending on its direction. + */ + static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsReadWriteAllowed(void) + { + return ((UEINTX & (1 << RWAL)) ? true : false); + } + + /** Determines if the currently selected endpoint is configured. + * + * \return Boolean true if the currently selected endpoint has been configured, false otherwise. + */ + static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsConfigured(void) + { + return ((UESTA0X & (1 << CFGOK)) ? true : false); + } + + /** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their + * interrupt duration has elapsed. Which endpoints have interrupted can be determined by + * masking the return value against (1 << {Endpoint Number}). + * + * \return Mask whose bits indicate which endpoints have interrupted. + */ + static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_GetEndpointInterrupts(void) + { + return UEINT; + } + + /** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type + * endpoints). + * + * \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested. + * + * \return Boolean true if the specified endpoint has interrupted, false otherwise. + */ + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) + { + return ((UEINT & (1 << EndpointNumber)) ? true : false); + } + + /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the current endpoint is ready for an IN packet, false otherwise. + */ + static inline bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsINReady(void) + { + return ((UEINTX & (1 << TXINI)) ? true : false); + } + + /** Determines if the selected OUT endpoint has received new packet from the host. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if current endpoint is has received an OUT packet, false otherwise. + */ + static inline bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsOUTReceived(void) + { + return ((UEINTX & (1 << RXOUTI)) ? true : false); + } + + /** Determines if the current CONTROL type endpoint has received a SETUP packet. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the selected endpoint has received a SETUP packet, false otherwise. + */ + static inline bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsSETUPReceived(void) + { + return ((UEINTX & (1 << RXSTPI)) ? true : false); + } + + /** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the + * endpoint for the next packet. + * + * \ingroup Group_EndpointPacketManagement + * + * \note This is not applicable for non CONTROL type endpoints. + */ + static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearSETUP(void) + { + UEINTX &= ~(1 << RXSTPI); + } + + /** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the + * next packet and switching to the alternative endpoint bank if double banked. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearIN(void) + { + #if !defined(CONTROL_ONLY_DEVICE) + UEINTX &= ~((1 << TXINI) | (1 << FIFOCON)); + #else + UEINTX &= ~(1 << TXINI); + #endif + } + + /** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint + * for the next packet and switching to the alternative endpoint bank if double banked. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearOUT(void) + { + #if !defined(CONTROL_ONLY_DEVICE) + UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON)); + #else + UEINTX &= ~(1 << RXOUTI); + #endif + } + + /** Stalls the current endpoint, indicating to the host that a logical problem occurred with the + * indicated endpoint and that the current transfer sequence should be aborted. This provides a + * way for devices to indicate invalid commands to the host so that the current transfer can be + * aborted and the host can begin its own recovery sequence. + * + * The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro + * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected + * endpoint. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_StallTransaction(void) + { + UECONX |= (1 << STALLRQ); + } + + /** Clears the STALL condition on the currently selected endpoint. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearStall(void) + { + UECONX |= (1 << STALLRQC); + } + + /** Determines if the currently selected endpoint is stalled, false otherwise. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the currently selected endpoint is stalled, false otherwise. + */ + static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsStalled(void) + { + return ((UECONX & (1 << STALLRQ)) ? true : false); + } + + /** Resets the data toggle of the currently selected endpoint. */ + static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ResetDataToggle(void) + { + UECONX |= (1 << RSTDT); + } + + /** Determines the currently selected endpoint's direction. + * + * \return The currently selected endpoint's direction, as a ENDPOINT_DIR_* mask. + */ + static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_GetEndpointDirection(void) + { + return (UECFG0X & ENDPOINT_DIR_IN); + } + + /** Sets the direction of the currently selected endpoint. + * + * \param[in] DirectionMask New endpoint direction, as a ENDPOINT_DIR_* mask. + */ + static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask) ATTR_ALWAYS_INLINE; + static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask) + { + UECFG0X = ((UECFG0X & ~ENDPOINT_DIR_IN) | DirectionMask); + } + + /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \return Next byte in the currently selected endpoint's FIFO buffer. + */ + static inline uint8_t Endpoint_Read_Byte(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_Read_Byte(void) + { + return UEDATX; + } + + /** Writes one byte from the currently selected endpoint's bank, for IN direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \param[in] Byte Next byte to write into the the currently selected endpoint's FIFO buffer. + */ + static inline void Endpoint_Write_Byte(const uint8_t Byte) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Write_Byte(const uint8_t Byte) + { + UEDATX = Byte; + } + + /** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + */ + static inline void Endpoint_Discard_Byte(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Discard_Byte(void) + { + uint8_t Dummy; + + Dummy = UEDATX; + } + + /** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \return Next word in the currently selected endpoint's FIFO buffer. + */ + static inline uint16_t Endpoint_Read_Word_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t Endpoint_Read_Word_LE(void) + { + union + { + uint16_t Word; + uint8_t Bytes[2]; + } Data; + + Data.Bytes[0] = UEDATX; + Data.Bytes[1] = UEDATX; + + return Data.Word; + } + + /** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \return Next word in the currently selected endpoint's FIFO buffer. + */ + static inline uint16_t Endpoint_Read_Word_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t Endpoint_Read_Word_BE(void) + { + union + { + uint16_t Word; + uint8_t Bytes[2]; + } Data; + + Data.Bytes[1] = UEDATX; + Data.Bytes[0] = UEDATX; + + return Data.Word; + } + + /** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \param[in] Word Next word to write to the currently selected endpoint's FIFO buffer. + */ + static inline void Endpoint_Write_Word_LE(const uint16_t Word) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Write_Word_LE(const uint16_t Word) + { + UEDATX = (Word & 0xFF); + UEDATX = (Word >> 8); + } + + /** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \param[in] Word Next word to write to the currently selected endpoint's FIFO buffer. + */ + static inline void Endpoint_Write_Word_BE(const uint16_t Word) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Write_Word_BE(const uint16_t Word) + { + UEDATX = (Word >> 8); + UEDATX = (Word & 0xFF); + } + + /** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + */ + static inline void Endpoint_Discard_Word(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Discard_Word(void) + { + uint8_t Dummy; + + Dummy = UEDATX; + Dummy = UEDATX; + } + + /** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \return Next double word in the currently selected endpoint's FIFO buffer. + */ + static inline uint32_t Endpoint_Read_DWord_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint32_t Endpoint_Read_DWord_LE(void) + { + union + { + uint32_t DWord; + uint8_t Bytes[4]; + } Data; + + Data.Bytes[0] = UEDATX; + Data.Bytes[1] = UEDATX; + Data.Bytes[2] = UEDATX; + Data.Bytes[3] = UEDATX; + + return Data.DWord; + } + + /** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \return Next double word in the currently selected endpoint's FIFO buffer. + */ + static inline uint32_t Endpoint_Read_DWord_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint32_t Endpoint_Read_DWord_BE(void) + { + union + { + uint32_t DWord; + uint8_t Bytes[4]; + } Data; + + Data.Bytes[3] = UEDATX; + Data.Bytes[2] = UEDATX; + Data.Bytes[1] = UEDATX; + Data.Bytes[0] = UEDATX; + + return Data.DWord; + } + + /** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \param[in] DWord Next double word to write to the currently selected endpoint's FIFO buffer. + */ + static inline void Endpoint_Write_DWord_LE(const uint32_t DWord) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Write_DWord_LE(const uint32_t DWord) + { + UEDATX = (DWord & 0xFF); + UEDATX = (DWord >> 8); + UEDATX = (DWord >> 16); + UEDATX = (DWord >> 24); + } + + /** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN + * direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + * + * \param[in] DWord Next double word to write to the currently selected endpoint's FIFO buffer. + */ + static inline void Endpoint_Write_DWord_BE(const uint32_t DWord) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Write_DWord_BE(const uint32_t DWord) + { + UEDATX = (DWord >> 24); + UEDATX = (DWord >> 16); + UEDATX = (DWord >> 8); + UEDATX = (DWord & 0xFF); + } + + /** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints. + * + * \ingroup Group_EndpointPrimitiveRW + */ + static inline void Endpoint_Discard_DWord(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_Discard_DWord(void) + { + uint8_t Dummy; + + Dummy = UEDATX; + Dummy = UEDATX; + Dummy = UEDATX; + Dummy = UEDATX; + } + + /* External Variables: */ + /** Global indicating the maximum packet size of the default control endpoint located at address + * 0 in the device. This value is set to the value indicated in the device descriptor in the user + * project once the USB interface is initialized into device mode. + * + * If space is an issue, it is possible to fix this to a static value by defining the control + * endpoint size in the FIXED_CONTROL_ENDPOINT_SIZE token passed to the compiler in the makefile + * via the -D switch. When a fixed control endpoint size is used, the size is no longer dynamically + * read from the descriptors at runtime and instead fixed to the given value. When used, it is + * important that the descriptor control endpoint size value matches the size given as the + * FIXED_CONTROL_ENDPOINT_SIZE token - it is recommended that the FIXED_CONTROL_ENDPOINT_SIZE token + * be used in the descriptors to ensure this. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + */ + #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) + extern uint8_t USB_ControlEndpointSize; + #else + #define USB_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE + #endif + + /* Function Prototypes: */ + /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically, + * with respect to the data direction. This is a convenience function which can be used to + * simplify user control request handling. + */ + void Endpoint_ClearStatusStage(void); + + /** Spin-loops until the currently selected non-control endpoint is ready for the next packet of data + * to be read or written to it. + * + * \note This routine should not be called on CONTROL type endpoints. + * + * \ingroup Group_EndpointRW + * + * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum. + */ + uint8_t Endpoint_WaitUntilReady(void); + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/LowLevel/Host.c b/LUFA/Drivers/USB/LowLevel/Host.c new file mode 100644 index 0000000..7f76a1c --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Host.c @@ -0,0 +1,355 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../HighLevel/USBMode.h" + +#if defined(USB_CAN_BE_HOST) + +#define __INCLUDE_FROM_HOST_C +#include "Host.h" + +void USB_Host_ProcessNextHostState(void) +{ + uint8_t ErrorCode = HOST_ENUMERROR_NoError; + uint8_t SubErrorCode = HOST_ENUMERROR_NoError; + + static uint16_t WaitMSRemaining; + static uint8_t PostWaitState; + + switch (USB_HostState) + { + case HOST_STATE_WaitForDevice: + if (WaitMSRemaining) + { + if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful) + { + USB_HostState = PostWaitState; + ErrorCode = HOST_ENUMERROR_WaitStage; + break; + } + + if (!(--WaitMSRemaining)) + USB_HostState = PostWaitState; + } + + break; + case HOST_STATE_Powered: + WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS; + + USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle; + break; + case HOST_STATE_Powered_WaitForDeviceSettle: + if (WaitMSRemaining--) + { + _delay_ms(1); + break; + } + else + { + USB_Host_VBUS_Manual_Off(); + + USB_OTGPAD_On(); + USB_Host_VBUS_Auto_Enable(); + USB_Host_VBUS_Auto_On(); + + USB_HostState = HOST_STATE_Powered_WaitForConnect; + } + + break; + case HOST_STATE_Powered_WaitForConnect: + if (USB_INT_HasOccurred(USB_INT_DCONNI)) + { + USB_INT_Clear(USB_INT_DCONNI); + USB_INT_Clear(USB_INT_DDISCI); + + USB_INT_Clear(USB_INT_VBERRI); + USB_INT_Enable(USB_INT_VBERRI); + + USB_Host_ResumeBus(); + Pipe_ClearPipes(); + + HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset); + } + + break; + case HOST_STATE_Powered_DoReset: + USB_Host_ResetDevice(); + + HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe); + break; + case HOST_STATE_Powered_ConfigPipe: + Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, + PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, + PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE); + + if (!(Pipe_IsConfigured())) + { + ErrorCode = HOST_ENUMERROR_PipeConfigError; + SubErrorCode = 0; + break; + } + + USB_HostState = HOST_STATE_Default; + break; + case HOST_STATE_Default: + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), + .bRequest = REQ_GetDescriptor, + .wValue = (DTYPE_Device << 8), + .wIndex = 0, + .wLength = 8, + }; + + uint8_t DataBuffer[8]; + + if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful) + { + ErrorCode = HOST_ENUMERROR_ControlError; + break; + } + + USB_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)]; + + USB_Host_ResetDevice(); + + HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset); + break; + case HOST_STATE_Default_PostReset: + Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, + PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, + USB_ControlPipeSize, PIPE_BANK_SINGLE); + + if (!(Pipe_IsConfigured())) + { + ErrorCode = HOST_ENUMERROR_PipeConfigError; + SubErrorCode = 0; + break; + } + + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE), + .bRequest = REQ_SetAddress, + .wValue = USB_HOST_DEVICEADDRESS, + .wIndex = 0, + .wLength = 0, + }; + + if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful) + { + ErrorCode = HOST_ENUMERROR_ControlError; + break; + } + + HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet); + break; + case HOST_STATE_Default_PostAddressSet: + USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS); + + EVENT_USB_Host_DeviceEnumerationComplete(); + USB_HostState = HOST_STATE_Addressed; + break; + } + + if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached)) + { + EVENT_USB_Host_DeviceEnumerationFailed(ErrorCode, SubErrorCode); + + USB_Host_VBUS_Auto_Off(); + + EVENT_USB_Host_DeviceUnattached(); + + USB_ResetInterface(); + } +} + +uint8_t USB_Host_WaitMS(uint8_t MS) +{ + bool BusSuspended = USB_Host_IsBusSuspended(); + uint8_t ErrorCode = HOST_WAITERROR_Successful; + bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI); + + USB_INT_Disable(USB_INT_HSOFI); + USB_INT_Clear(USB_INT_HSOFI); + + USB_Host_ResumeBus(); + + while (MS) + { + if (USB_INT_HasOccurred(USB_INT_HSOFI)) + { + USB_INT_Clear(USB_INT_HSOFI); + MS--; + } + + if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode != USB_MODE_Host)) + { + ErrorCode = HOST_WAITERROR_DeviceDisconnect; + + break; + } + + if (Pipe_IsError() == true) + { + Pipe_ClearError(); + ErrorCode = HOST_WAITERROR_PipeError; + + break; + } + + if (Pipe_IsStalled() == true) + { + Pipe_ClearStall(); + ErrorCode = HOST_WAITERROR_SetupStalled; + + break; + } + } + + if (BusSuspended) + USB_Host_SuspendBus(); + + if (HSOFIEnabled) + USB_INT_Enable(USB_INT_HSOFI); + + return ErrorCode; +} + +static void USB_Host_ResetDevice(void) +{ + bool BusSuspended = USB_Host_IsBusSuspended(); + + USB_INT_Disable(USB_INT_DDISCI); + + USB_Host_ResetBus(); + while (!(USB_Host_IsBusResetComplete())); + USB_Host_ResumeBus(); + + bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI); + + USB_INT_Disable(USB_INT_HSOFI); + USB_INT_Clear(USB_INT_HSOFI); + + for (uint8_t MSRem = 10; MSRem != 0; MSRem--) + { + /* Workaround for powerless-pull-up devices. After a USB bus reset, + all disconnection interrupts are suppressed while a USB frame is + looked for - if it is found within 10ms, the device is still + present. */ + + if (USB_INT_HasOccurred(USB_INT_HSOFI)) + { + USB_INT_Clear(USB_INT_HSOFI); + USB_INT_Clear(USB_INT_DDISCI); + break; + } + + _delay_ms(1); + } + + if (HSOFIEnabled) + USB_INT_Enable(USB_INT_HSOFI); + + if (BusSuspended) + USB_Host_SuspendBus(); + + USB_INT_Enable(USB_INT_DDISCI); +} + +uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber) +{ + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE), + .bRequest = REQ_SetConfiguration, + .wValue = ConfigNumber, + .wIndex = 0, + .wLength = 0, + }; + + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + return USB_Host_SendControlRequest(NULL); +} + +uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr) +{ + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), + .bRequest = REQ_GetDescriptor, + .wValue = (DTYPE_Device << 8), + .wIndex = 0, + .wLength = sizeof(USB_Descriptor_Device_t), + }; + + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + return USB_Host_SendControlRequest(DeviceDescriptorPtr); +} + +uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index, + void* const Buffer, + const uint8_t BufferLength) +{ + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), + .bRequest = REQ_GetDescriptor, + .wValue = (DTYPE_String << 8) | Index, + .wIndex = 0, + .wLength = BufferLength, + }; + + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + return USB_Host_SendControlRequest(Buffer); +} + +uint8_t USB_Host_ClearPipeStall(const uint8_t EndpointNum) +{ + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT), + .bRequest = REQ_ClearFeature, + .wValue = FEATURE_SEL_EndpointHalt, + .wIndex = EndpointNum, + .wLength = 0, + }; + + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + return USB_Host_SendControlRequest(NULL); +} + +#endif + diff --git a/LUFA/Drivers/USB/LowLevel/Host.h b/LUFA/Drivers/USB/LowLevel/Host.h new file mode 100644 index 0000000..dce3a95 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Host.h @@ -0,0 +1,527 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB host mode definitions. + * + * This file contains structures, function prototypes and macros related to USB host mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_Host Host Management + * + * USB Host mode related macros and enums. This module contains macros and enums which are used when + * the USB controller is initialized in host mode. + * + * @{ + */ + +#ifndef __USBHOST_H__ +#define __USBHOST_H__ + + /* Includes: */ + #include + #include + #include + + #include "../../../Common/Common.h" + #include "../HighLevel/StdDescriptors.h" + #include "Pipe.h" + #include "USBInterrupt.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Indicates the fixed USB device address which any attached device is enumerated to when in + * host mode. As only one USB device may be attached to the AVR in host mode at any one time + * and that the address used is not important (other than the fact that it is non-zero), a + * fixed value is specified by the library. + */ + #define USB_HOST_DEVICEADDRESS 1 + + #if !defined(USB_HOST_TIMEOUT_MS) || defined(__DOXYGEN__) + /** Constant for the maximum software timeout period of sent USB control transactions to an attached + * device. If a device fails to respond to a sent control request within this period, the + * library will return a timeout error code. + * + * This value may be overridden in the user project makefile as the value of the + * \ref USB_HOST_TIMEOUT_MS token, and passed to the compiler using the -D switch. + */ + #define USB_HOST_TIMEOUT_MS 1000 + #endif + + #if !defined(HOST_DEVICE_SETTLE_DELAY_MS) || defined(__DOXYGEN__) + /** Constant for the delay in milliseconds after a device is connected before the library + * will start the enumeration process. Some devices require a delay of up to 5 seconds + * after connection before the enumeration process can start or incorrect operation will + * occur. + * + * The default delay value may be overridden in the user project makefile by definining the + * HOST_DEVICE_SETTLE_DELAY_MS token to tbe required delay in milliseconds, and passed to the + * compiler using the -D switch. + */ + #define HOST_DEVICE_SETTLE_DELAY_MS 1000 + #endif + + /* Enums: */ + /** Enum for the various states of the USB Host state machine. Only some states are + * implemented in the LUFA library - other states are left to the user to implement. + * + * For information on each possible USB host state, refer to the USB 2.0 specification. + * Several of the USB host states are broken up further into multiple smaller sub-states, + * so that they can be internally implemented inside the library in an efficient manner. + * + * \see \ref USB_HostState, which stores the current host state machine state. + */ + enum USB_Host_States_t + { + HOST_STATE_WaitForDeviceRemoval = 0, /**< Internally implemented by the library. This state can be + * used by the library to wait until the attached device is + * removed by the user - useful for when an error occurs or + * further communication with the device is not needed. This + * allows for other code to run while the state machine is + * effectively disabled. + */ + HOST_STATE_WaitForDevice = 1, /**< Internally implemented by the library. This state indicates + * that the stack is waiting for an interval to elapse before + * continuing with the next step of the device enumeration + * process. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Unattached = 2, /**< Internally implemented by the library. This state indicates + * that the host state machine is waiting for a device to be + * attached so that it can start the enumeration process. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Powered = 3, /**< Internally implemented by the library. This state indicates + * that a device has been attached, and the library's internals + * are being configured to begin the enumeration process. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Powered_WaitForDeviceSettle = 4, /**< Internally implemented by the library. This state indicates + * that the stack is waiting for the initial settling period to + * elapse before beginning the enumeration process. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Powered_WaitForConnect = 5, /**< Internally implemented by the library. This state indicates + * that the stack is waiting for a connection event from the USB + * controller to indicate a valid USB device has been attached to + * the bus and is ready to be enumerated. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Powered_DoReset = 6, /**< Internally implemented by the library. This state indicates + * that a valid USB device has been attached, and that it is + * will now be reset to ensure it is ready for enumeration. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Powered_ConfigPipe = 7, /**< Internally implemented by the library. This state indicates + * that the attached device is currently powered and reset, and + * that the control pipe is now being configured by the stack. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Default = 8, /**< Internally implemented by the library. This state indicates + * that the stack is currently retrieving the control endpoint's + * size from the device, so that the control pipe can be altered + * to match. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Default_PostReset = 9, /**< Internally implemented by the library. This state indicates that + * the control pipe is being reconfigured to match the retrieved + * control endpoint size from the device, and the device's USB bus + * address is being set. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Default_PostAddressSet = 10, /**< Internally implemented by the library. This state indicates that + * the device's address has now been set, and the stack is has now + * completed the device enumeration process. This state causes the + * stack to change the current USB device address to that set for + * the connected device, before progressing to the user-implemented + * \ref HOST_STATE_Addressed state for further communications. + * + * \note Do not manually change to this state in the user code. + */ + HOST_STATE_Addressed = 11, /**< May be implemented by the user project. This state should + * set the device configuration before progressing to the + * \ref HOST_STATE_Configured state. Other processing (such as the + * retrieval and processing of the device descriptor) should also + * be placed in this state. + */ + HOST_STATE_Configured = 12, /**< May be implemented by the user project. This state should implement the + * actual work performed on the attached device and changed to the + * \ref HOST_STATE_Suspended or \ref HOST_STATE_WaitForDeviceRemoval states as needed. + */ + HOST_STATE_Suspended = 15, /**< May be implemented by the user project. This state should be maintained + * while the bus is suspended, and changed to either the \ref HOST_STATE_Configured + * (after resuming the bus with the USB_Host_ResumeBus() macro) or the + * \ref HOST_STATE_WaitForDeviceRemoval states as needed. + */ + }; + + /** Enum for the error codes for the \ref EVENT_USB_Host_HostError() event. + * + * \see \ref Group_Events for more information on this event. + */ + enum USB_Host_ErrorCodes_t + { + HOST_ERROR_VBusVoltageDip = 0, /**< VBUS voltage dipped to an unacceptable level. This + * error may be the result of an attached device drawing + * too much current from the VBUS line, or due to the + * AVR's power source being unable to supply sufficient + * current. + */ + }; + + /** Enum for the error codes for the \ref EVENT_USB_Host_DeviceEnumerationFailed() event. + * + * \see \ref Group_Events for more information on this event. + */ + enum USB_Host_EnumerationErrorCodes_t + { + HOST_ENUMERROR_NoError = 0, /**< No error occurred. Used internally, this is not a valid + * ErrorCode parameter value for the \ref EVENT_USB_Host_DeviceEnumerationFailed() + * event. + */ + HOST_ENUMERROR_WaitStage = 1, /**< One of the delays between enumeration steps failed + * to complete successfully, due to a timeout or other + * error. + */ + HOST_ENUMERROR_NoDeviceDetected = 2, /**< No device was detected, despite the USB data lines + * indicating the attachment of a device. + */ + HOST_ENUMERROR_ControlError = 3, /**< One of the enumeration control requests failed to + * complete successfully. + */ + HOST_ENUMERROR_PipeConfigError = 4, /**< The default control pipe (address 0) failed to + * configure correctly. + */ + }; + + /* Inline Functions: */ + /** Returns the current USB frame number, when in host mode. Every millisecond the USB bus is active (i.e. not suspended) + * the frame number is incremented by one. + */ + static inline uint16_t USB_Host_GetFrameNumber(void) + { + return UHFNUM; + } + + #if !defined(NO_SOF_EVENTS) + /** Enables the host mode Start Of Frame events. When enabled, this causes the + * \ref EVENT_USB_Host_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus, + * at the start of each USB frame when a device is enumerated while in host mode. + * + * \note Not available when the NO_SOF_EVENTS compile time token is defined. + */ + static inline void USB_Host_EnableSOFEvents(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_EnableSOFEvents(void) + { + USB_INT_Enable(USB_INT_HSOFI); + } + + /** Disables the host mode Start Of Frame events. When disabled, this stops the firing of the + * \ref EVENT_USB_Host_StartOfFrame() event when enumerated in host mode. + * + * \note Not available when the NO_SOF_EVENTS compile time token is defined. + */ + static inline void USB_Host_DisableSOFEvents(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_DisableSOFEvents(void) + { + USB_INT_Disable(USB_INT_HSOFI); + } + #endif + + /** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host. + * USB bus resets leave the default control pipe configured (if already configured). + * + * If the USB bus has been suspended prior to issuing a bus reset, the attached device will be + * woken up automatically and the bus resumed after the reset has been correctly issued. + */ + static inline void USB_Host_ResetBus(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ResetBus(void) + { + UHCON |= (1 << RESET); + } + + /** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has + * completed. + * + * \return Boolean true if no bus reset is currently being sent, false otherwise. + */ + static inline bool USB_Host_IsBusResetComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsBusResetComplete(void) + { + return ((UHCON & (1 << RESET)) ? false : true); + } + + /** Resumes USB communications with an attached and enumerated device, by resuming the transmission + * of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the + * host and attached device may occur. + */ + static inline void USB_Host_ResumeBus(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ResumeBus(void) + { + UHCON |= (1 << SOFEN); + } + + /** Suspends the USB bus, preventing any communications from occurring between the host and attached + * device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame + * messages to the device. + */ + static inline void USB_Host_SuspendBus(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_SuspendBus(void) + { + UHCON &= ~(1 << SOFEN); + } + + /** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro, + * false otherwise. While suspended, no USB communications can occur until the bus is resumed, + * except for the Remote Wakeup event from the device if supported. + * + * \return Boolean true if the bus is currently suspended, false otherwise. + */ + static inline bool USB_Host_IsBusSuspended(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsBusSuspended(void) + { + return ((UHCON & (1 << SOFEN)) ? false : true); + } + + /** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or + * false if the attached device is enumerated in Low Speed mode (1.5Mb/s). + * + * \return Boolean true if the attached device is enumerated in Full Speed mode, false otherwise. + */ + static inline bool USB_Host_IsDeviceFullSpeed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsDeviceFullSpeed(void) + { + return ((USBSTA & (1 << SPEED)) ? true : false); + } + + /** Determines if the attached device is currently issuing a Remote Wakeup request, requesting + * that the host resume the USB bus and wake up the device, false otherwise. + * + * \return Boolean true if the attached device has sent a Remote Wakeup request, false otherwise. + */ + static inline bool USB_Host_IsRemoteWakeupSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsRemoteWakeupSent(void) + { + return ((UHINT & (1 << RXRSMI)) ? true : false); + } + + /** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */ + static inline void USB_Host_ClearRemoteWakeupSent(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ClearRemoteWakeupSent(void) + { + UHINT &= ~(1 << RXRSMI); + } + + /** Accepts a Remote Wakeup request from an attached device. This must be issued in response to + * a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to + * be resumed. + */ + static inline void USB_Host_ResumeFromWakeupRequest(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ResumeFromWakeupRequest(void) + { + UHCON |= (1 << RESUME); + } + + /** Determines if a resume from Remote Wakeup request is currently being sent to an attached + * device. + * + * \return Boolean true if no resume request is currently being sent, false otherwise. + */ + static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) + { + return ((UHCON & (1 << RESUME)) ? false : true); + } + + /* Function Prototypes: */ + /** Convenience function. This routine sends a SetConfiguration standard request to the attached + * device, with the given configuration index. This can be used to easily set the device + * configuration without creating and sending the request manually. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[in] ConfigNumber Configuration index to send to the device. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber); + + /** Convenience function. This routine sends a GetDescriptor standard request to the attached + * device, requesting the device descriptor. This can be used to easily retrieve information + * about the device such as its VID, PID and power requirements. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where + * the read data is to be stored. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr); + + /** Convenience function. This routine sends a GetDescriptor standard request to the attached + * device, requesting the string descriptor of the specified index. This can be used to easily + * retrieve string descriptors from the device by index, after the index is obtained from the + * Device or Configuration descriptors. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[in] Index Index of the string index to retrieve. + * \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is + * to be stored. + * \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index, + void* const Buffer, + const uint8_t BufferLength); + + /** Clears a stall condition on the given pipe, via a ClearFeature request to the attached device. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[in] EndpointIndex Index of the endpoint to clear, including the endpoint's direction. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_ClearPipeStall(const uint8_t EndpointIndex); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + static inline void USB_Host_HostMode_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_HostMode_On(void) + { + USBCON |= (1 << HOST); + } + + static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_HostMode_Off(void) + { + USBCON &= ~(1 << HOST); + } + + static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Auto_Enable(void) + { + OTGCON &= ~(1 << VBUSHWC); + UHWCON |= (1 << UVCONE); + } + + static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Manual_Enable(void) + { + OTGCON |= (1 << VBUSHWC); + UHWCON &= ~(1 << UVCONE); + + DDRE |= (1 << 7); + } + + static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Auto_On(void) + { + OTGCON |= (1 << VBUSREQ); + } + + static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Manual_On(void) + { + PORTE |= (1 << 7); + } + + static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Auto_Off(void) + { + OTGCON |= (1 << VBUSRQC); + } + + static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Manual_Off(void) + { + PORTE &= ~(1 << 7); + } + + static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void USB_Host_SetDeviceAddress(const uint8_t Address) + { + UHADDR = (Address & 0x7F); + } + + /* Enums: */ + enum USB_Host_WaitMSErrorCodes_t + { + HOST_WAITERROR_Successful = 0, + HOST_WAITERROR_DeviceDisconnect = 1, + HOST_WAITERROR_PipeError = 2, + HOST_WAITERROR_SetupStalled = 3, + }; + + /* Function Prototypes: */ + void USB_Host_ProcessNextHostState(void); + uint8_t USB_Host_WaitMS(uint8_t MS); + + #if defined(__INCLUDE_FROM_HOST_C) + static void USB_Host_ResetDevice(void); + #endif + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/LowLevel/OTG.h b/LUFA/Drivers/USB/LowLevel/OTG.h new file mode 100644 index 0000000..d213552 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/OTG.h @@ -0,0 +1,155 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB OTG mode definitions. + * + * This file contains structures, function prototypes and macros related to USB OTG mode, where two USB devices + * may be linked directly together and exchange host/device roles as needed. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_OTG USB On The Go (OTG) Management + * + * This module contains macros for embedded USB hosts with dual role On The Go capabilities, for managing role + * exchange. OTG is a way for two USB dual role devices to talk to one another directly without fixed device/host + * roles. + * + * @{ + */ + +#ifndef __USBOTG_H__ +#define __USBOTG_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Mask for the VBUS pulsing method of SRP, supported by some OTG devices. + * + * \see \ref USB_OTG_Device_InitiateSRP(). + */ + #define USB_OTG_SRP_VBUS (1 << SRPSEL) + + /** Mask for the Data + pulsing method of SRP, supported by some OTG devices. + * + * \see \ref USB_OTG_Device_InitiateSRP(). + */ + #define USB_OTG_STP_DATA 0 + + /* Inline Functions: */ + /** Initiate a Host Negotiation Protocol request. This indicates to the other connected device + * that the device wishes to change device/host roles. + */ + static inline void USB_OTG_Device_RequestHNP(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Device_RequestHNP(void) + { + OTGCON |= (1 << HNPREQ); + } + + /** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other + * connected device. + */ + static inline void USB_OTG_Device_CancelHNPRequest(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Device_CancelHNPRequest(void) + { + OTGCON &= ~(1 << HNPREQ); + } + + /** Determines if the device is currently sending a HNP to an attached host. + * + * \return Boolean true if currently sending a HNP to the other connected device, false otherwise + */ + static inline bool USB_OTG_Device_IsSendingHNP(void) ATTR_ALWAYS_INLINE; + static inline bool USB_OTG_Device_IsSendingHNP(void) + { + return ((OTGCON & (1 << HNPREQ)) ? true : false); + } + + /** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB + * interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in + * host mode indicates that VBUS should be applied and a session started. + * + * There are two different methods of sending a SRP - either pulses on the VBUS line, or by + * pulsing the Data + line via the internal pull-up resistor. + * + * \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or + * \ref USB_OTG_STP_DATA. + */ + static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) + { + OTGCON = ((OTGCON & ~(1 << SRPSEL)) | (SRPTypeMask | (1 << SRPREQ))); + } + + /** Accepts a HNP from a connected device, indicating that both devices should exchange + * device/host roles. + */ + static inline void USB_OTG_Host_AcceptHNP(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Host_AcceptHNP(void) + { + OTGCON |= (1 << HNPREQ); + } + + /** Rejects a HNP from a connected device, indicating that both devices should remain in their + * current device/host roles. + */ + static inline void USB_OTG_Host_RejectHNP(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Host_RejectHNP(void) + { + OTGCON &= ~(1 << HNPREQ); + } + + /** Indicates if the connected device is not currently sending a HNP request. + * + * \return Boolean true if a HNP is currently being issued by the connected device, false otherwise. + */ + static inline bool USB_OTG_Host_IsHNPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_OTG_Host_IsHNPReceived(void) + { + return ((OTGCON & (1 << HNPREQ)) ? true : false); + } + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.c b/LUFA/Drivers/USB/LowLevel/Pipe.c new file mode 100644 index 0000000..c414129 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Pipe.c @@ -0,0 +1,140 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "../HighLevel/USBMode.h" + +#if defined(USB_CAN_BE_HOST) + +#include "Pipe.h" + +uint8_t USB_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE; + +bool Pipe_ConfigurePipe(const uint8_t Number, + const uint8_t Type, + const uint8_t Token, + const uint8_t EndpointNumber, + const uint16_t Size, + const uint8_t Banks) +{ + Pipe_SelectPipe(Number); + Pipe_EnablePipe(); + + UPCFG1X = 0; + + UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0)); + UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size)); + + Pipe_SetInfiniteINRequests(); + + return Pipe_IsConfigured(); +} + +void Pipe_ClearPipes(void) +{ + UPINT = 0; + + for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++) + { + Pipe_SelectPipe(PNum); + UPIENX = 0; + UPINTX = 0; + UPCFG1X = 0; + Pipe_DisablePipe(); + } +} + +bool Pipe_IsEndpointBound(const uint8_t EndpointAddress) +{ + uint8_t PrevPipeNumber = Pipe_GetCurrentPipe(); + + for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++) + { + Pipe_SelectPipe(PNum); + + if (!(Pipe_IsConfigured())) + continue; + + uint8_t PipeToken = Pipe_GetPipeToken(); + bool PipeTokenCorrect = true; + + if (PipeToken != PIPE_TOKEN_SETUP) + PipeTokenCorrect = (PipeToken == ((EndpointAddress & PIPE_EPDIR_MASK) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT)); + + if (PipeTokenCorrect && (Pipe_BoundEndpointNumber() == (EndpointAddress & PIPE_EPNUM_MASK))) + return true; + } + + Pipe_SelectPipe(PrevPipeNumber); + return false; +} + +uint8_t Pipe_WaitUntilReady(void) +{ + #if (USB_STREAM_TIMEOUT_MS < 0xFF) + uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; + #else + uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; + #endif + + uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber(); + + for (;;) + { + if (Pipe_GetPipeToken() == PIPE_TOKEN_IN) + { + if (Pipe_IsINReceived()) + return PIPE_READYWAIT_NoError; + } + else + { + if (Pipe_IsOUTReady()) + return PIPE_READYWAIT_NoError; + } + + if (Pipe_IsStalled()) + return PIPE_READYWAIT_PipeStalled; + else if (USB_HostState == HOST_STATE_Unattached) + return PIPE_READYWAIT_DeviceDisconnected; + + uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber(); + + if (CurrentFrameNumber != PreviousFrameNumber) + { + PreviousFrameNumber = CurrentFrameNumber; + + if (!(TimeoutMSRem--)) + return PIPE_READYWAIT_Timeout; + } + } +} + +#endif + diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.h b/LUFA/Drivers/USB/LowLevel/Pipe.h new file mode 100644 index 0000000..7bdb508 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/Pipe.h @@ -0,0 +1,941 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB host pipe management definitions. + * + * This file contains structures, function prototypes and macros related to the management of the device's + * data pipes when the library is initialized in USB host mode. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_PipeManagement + * @defgroup Group_PipeRW Pipe Data Reading and Writing + * + * Functions, macros, variables, enums and types related to data reading and writing from and to pipes. + */ + +/** \ingroup Group_PipeRW + * @defgroup Group_PipePrimitiveRW Read/Write of Primitive Data Types + * + * Functions, macros, variables, enums and types related to data reading and writing of primitive data types + * from and to pipes. + */ + +/** \ingroup Group_PipeManagement + * @defgroup Group_PipePacketManagement Pipe Packet Management + * + * Functions, macros, variables, enums and types related to packet management of pipes. + */ + +/** \ingroup Group_PipeManagement + * @defgroup Group_PipeControlReq Pipe Control Request Management + * + * Module for host mode request processing. This module allows for the transmission of standard, class and + * vendor control requests to the default control endpoint of an attached device while in host mode. + * + * \see Chapter 9 of the USB 2.0 specification. + */ + +/** \ingroup Group_USB + * @defgroup Group_PipeManagement Pipe Management + * + * This module contains functions, macros and enums related to pipe management when in USB Host mode. This + * module contains the pipe management macros, as well as pipe interrupt and data send/receive functions + * for various data types. + * + * @{ + */ + +#ifndef __PIPE_H__ +#define __PIPE_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + #include "../HighLevel/USBTask.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name Pipe Error Flag Masks */ + //@{ + /** Mask for \ref Pipe_GetErrorFlags(), indicating that an overflow error occurred in the pipe on the received data. */ + #define PIPE_ERRORFLAG_OVERFLOW (1 << 6) + + /** Mask for \ref Pipe_GetErrorFlags(), indicating that an underflow error occurred in the pipe on the received data. */ + #define PIPE_ERRORFLAG_UNDERFLOW (1 << 5) + + /** Mask for \ref Pipe_GetErrorFlags(), indicating that a CRC error occurred in the pipe on the received data. */ + #define PIPE_ERRORFLAG_CRC16 (1 << 4) + + /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware timeout error occurred in the pipe. */ + #define PIPE_ERRORFLAG_TIMEOUT (1 << 3) + + /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware PID error occurred in the pipe. */ + #define PIPE_ERRORFLAG_PID (1 << 2) + + /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data PID error occurred in the pipe. */ + #define PIPE_ERRORFLAG_DATAPID (1 << 1) + + /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data toggle error occurred in the pipe. */ + #define PIPE_ERRORFLAG_DATATGL (1 << 0) + //@} + + /** \name Pipe Token Masks */ + //@{ + /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a SETUP token (for CONTROL type pipes), + * which will trigger a control request on the attached device when data is written to the pipe. + */ + #define PIPE_TOKEN_SETUP (0 << PTOKEN0) + + /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a IN token (for non-CONTROL type pipes), + * indicating that the pipe data will flow from device to host. + */ + #define PIPE_TOKEN_IN (1 << PTOKEN0) + + /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a OUT token (for non-CONTROL type pipes), + * indicating that the pipe data will flow from host to device. + */ + #define PIPE_TOKEN_OUT (2 << PTOKEN0) + //@} + + /** \name Pipe Bank Mode Masks */ + //@{ + /** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe + * should have one single bank, which requires less USB FIFO memory but results in slower transfers as + * only one USB device (the AVR or the attached device) can access the pipe's bank at the one time. + */ + #define PIPE_BANK_SINGLE (0 << EPBK0) + + /** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe + * should have two banks, which requires more USB FIFO memory but results in faster transfers as one + * USB device (the AVR or the attached device) can access one bank while the other accesses the second + * bank. + */ + #define PIPE_BANK_DOUBLE (1 << EPBK0) + //@} + + /** Pipe address for the default control pipe, which always resides in address 0. This is + * defined for convenience to give more readable code when used with the pipe macros. + */ + #define PIPE_CONTROLPIPE 0 + + /** Default size of the default control pipe's bank, until altered by the Endpoint0Size value + * in the device descriptor of the attached device. + */ + #define PIPE_CONTROLPIPE_DEFAULT_SIZE 64 + + /** Pipe number mask, for masking against pipe addresses to retrieve the pipe's numerical address + * in the device. + */ + #define PIPE_PIPENUM_MASK 0x07 + + /** Total number of pipes (including the default control pipe at address 0) which may be used in + * the device. Different USB AVR models support different amounts of pipes, this value reflects + * the maximum number of pipes for the currently selected AVR model. + */ + #define PIPE_TOTAL_PIPES 7 + + /** Size in bytes of the largest pipe bank size possible in the device. Not all banks on each AVR + * model supports the largest bank size possible on the device; different pipe numbers support + * different maximum bank sizes. This value reflects the largest possible bank of any pipe on the + * currently selected USB AVR model. + */ + #define PIPE_MAX_SIZE 256 + + /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's + * numerical address in the attached device. + */ + #define PIPE_EPNUM_MASK 0x0F + + /** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's + * direction for comparing with the ENDPOINT_DESCRIPTOR_DIR_* masks. + */ + #define PIPE_EPDIR_MASK 0x80 + + /* Enums: */ + /** Enum for the possible error return codes of the Pipe_WaitUntilReady function. + * + * \ingroup Group_PipeRW + */ + enum Pipe_WaitUntilReady_ErrorCodes_t + { + PIPE_READYWAIT_NoError = 0, /**< Pipe ready for next packet, no error. */ + PIPE_READYWAIT_PipeStalled = 1, /**< The device stalled the pipe while waiting. */ + PIPE_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while waiting. */ + PIPE_READYWAIT_Timeout = 3, /**< The device failed to accept or send the next packet + * within the software timeout period set by the + * \ref USB_STREAM_TIMEOUT_MS macro. + */ + }; + + /* Inline Functions: */ + /** Indicates the number of bytes currently stored in the current pipes's selected bank. + * + * \note The return width of this function may differ, depending on the maximum pipe bank size + * of the selected AVR model. + * + * \ingroup Group_PipeRW + * + * \return Total number of bytes in the currently selected Pipe's FIFO buffer. + */ + static inline uint16_t Pipe_BytesInPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t Pipe_BytesInPipe(void) + { + return UPBCX; + } + + /** Returns the pipe address of the currently selected pipe. This is typically used to save the + * currently selected pipe number so that it can be restored after another pipe has been manipulated. + * + * \return Index of the currently selected pipe. + */ + static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetCurrentPipe(void) + { + return (UPNUM & PIPE_PIPENUM_MASK); + } + + /** Selects the given pipe number. Any pipe operations which do not require the pipe number to be + * indicated will operate on the currently selected pipe. + * + * \param[in] PipeNumber Index of the pipe to select. + */ + static inline void Pipe_SelectPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE; + static inline void Pipe_SelectPipe(const uint8_t PipeNumber) + { + UPNUM = PipeNumber; + } + + /** Resets the desired pipe, including the pipe banks and flags. + * + * \param[in] PipeNumber Index of the pipe to reset. + */ + static inline void Pipe_ResetPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE; + static inline void Pipe_ResetPipe(const uint8_t PipeNumber) + { + UPRST = (1 << PipeNumber); + UPRST = 0; + } + + /** Enables the currently selected pipe so that data can be sent and received through it to and from + * an attached device. + * + * \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe(). + */ + static inline void Pipe_EnablePipe(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_EnablePipe(void) + { + UPCONX |= (1 << PEN); + } + + /** Disables the currently selected pipe so that data cannot be sent and received through it to and + * from an attached device. + */ + static inline void Pipe_DisablePipe(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_DisablePipe(void) + { + UPCONX &= ~(1 << PEN); + } + + /** Determines if the currently selected pipe is enabled, but not necessarily configured. + * + * \return Boolean True if the currently selected pipe is enabled, false otherwise. + */ + static inline bool Pipe_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsEnabled(void) + { + return ((UPCONX & (1 << PEN)) ? true : false); + } + + /** Gets the current pipe token, indicating the pipe's data direction and type. + * + * \return The current pipe token, as a PIPE_TOKEN_* mask. + */ + static inline uint8_t Pipe_GetPipeToken(void) ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetPipeToken(void) + { + return (UPCFG0X & (0x03 << PTOKEN0)); + } + + /** Sets the token for the currently selected pipe to one of the tokens specified by the PIPE_TOKEN_* + * masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during + * control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices + * which have two endpoints of opposite direction sharing the same endpoint address within the device. + * + * \param[in] Token New pipe token to set the selected pipe to, as a PIPE_TOKEN_* mask. + */ + static inline void Pipe_SetPipeToken(const uint8_t Token) ATTR_ALWAYS_INLINE; + static inline void Pipe_SetPipeToken(const uint8_t Token) + { + UPCFG0X = ((UPCFG0X & ~(0x03 << PTOKEN0)) | Token); + } + + /** Configures the currently selected pipe to allow for an unlimited number of IN requests. */ + static inline void Pipe_SetInfiniteINRequests(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_SetInfiniteINRequests(void) + { + UPCONX |= (1 << INMODE); + } + + /** Configures the currently selected pipe to only allow the specified number of IN requests to be + * accepted by the pipe before it is automatically frozen. + * + * \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing. + */ + static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) ATTR_ALWAYS_INLINE; + static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) + { + UPCONX &= ~(1 << INMODE); + UPINRQX = TotalINRequests; + } + + /** Determines if the currently selected pipe is configured. + * + * \return Boolean true if the selected pipe is configured, false otherwise. + */ + static inline bool Pipe_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsConfigured(void) + { + return ((UPSTAX & (1 << CFGOK)) ? true : false); + } + + /** Retrieves the endpoint number of the endpoint within the attached device that the currently selected + * pipe is bound to. + * + * \return Endpoint number the currently selected pipe is bound to. + */ + static inline uint8_t Pipe_BoundEndpointNumber(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_BoundEndpointNumber(void) + { + return ((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK); + } + + /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds. + * + * \param[in] Milliseconds Number of milliseconds between each pipe poll. + */ + static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds) ATTR_ALWAYS_INLINE; + static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds) + { + UPCFG2X = Milliseconds; + } + + /** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should + * be serviced. + * + * \return Mask whose bits indicate which pipes have interrupted. + */ + static inline uint8_t Pipe_GetPipeInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetPipeInterrupts(void) + { + return UPINT; + } + + /** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type + * pipes). + * + * \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested. + * + * \return Boolean true if the specified pipe has interrupted, false otherwise. + */ + static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber) + { + return ((UPINT & (1 << PipeNumber)) ? true : false); + } + + /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */ + static inline void Pipe_Unfreeze(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_Unfreeze(void) + { + UPCONX &= ~(1 << PFREEZE); + } + + /** Freezes the selected pipe, preventing it from communicating with an attached device. */ + static inline void Pipe_Freeze(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_Freeze(void) + { + UPCONX |= (1 << PFREEZE); + } + + /** Determines if the currently selected pipe is frozen, and not able to accept data. + * + * \return Boolean true if the currently selected pipe is frozen, false otherwise. + */ + static inline bool Pipe_IsFrozen(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsFrozen(void) + { + return ((UPCONX & (1 << PFREEZE)) ? true : false); + } + + /** Clears the master pipe error flag. */ + static inline void Pipe_ClearError(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearError(void) + { + UPINTX &= ~(1 << PERRI); + } + + /** Determines if the master pipe error flag is set for the currently selected pipe, indicating that + * some sort of hardware error has occurred on the pipe. + * + * \see \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag. + * + * \return Boolean true if an error has occurred on the selected pipe, false otherwise. + */ + static inline bool Pipe_IsError(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsError(void) + { + return ((UPINTX & (1 << PERRI)) ? true : false); + } + + /** Clears all the currently selected pipe's hardware error flags, but does not clear the master error + * flag for the pipe. + */ + static inline void Pipe_ClearErrorFlags(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearErrorFlags(void) + { + UPERRX = 0; + } + + /** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This + * value can then be masked against the PIPE_ERRORFLAG_* masks to determine what error has occurred. + * + * \return Mask comprising of PIPE_ERRORFLAG_* bits indicating what error has occurred on the selected pipe. + */ + static inline uint8_t Pipe_GetErrorFlags(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetErrorFlags(void) + { + return ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT | + PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID | + PIPE_ERRORFLAG_DATATGL)) | + (UPSTAX & (PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW))); + } + + /** Retrieves the number of busy banks in the currently selected pipe, which have been queued for + * transmission via the \ref Pipe_ClearOUT() command, or are awaiting acknowledgement via the + * \ref Pipe_ClearIN() command. + * + * \ingroup Group_PipePacketManagement + * + * \return Total number of busy banks in the selected pipe. + */ + static inline uint8_t Pipe_GetBusyBanks(void) + { + return (UPSTAX & (0x03 << NBUSYBK0)); + } + + /** Determines if the currently selected pipe may be read from (if data is waiting in the pipe + * bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT + * direction). This function will return false if an error has occurred in the pipe, or if the pipe + * is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT + * direction and the pipe bank is full. + * + * \note This function is not valid on CONTROL type pipes. + * + * \ingroup Group_PipePacketManagement + * + * \return Boolean true if the currently selected pipe may be read from or written to, depending on its direction. + */ + static inline bool Pipe_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsReadWriteAllowed(void) + { + return ((UPINTX & (1 << RWAL)) ? true : false); + } + + /** Determines if a packet has been received on the currently selected IN pipe from the attached device. + * + * \ingroup Group_PipePacketManagement + * + * \return Boolean true if the current pipe has received an IN packet, false otherwise. + */ + static inline bool Pipe_IsINReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsINReceived(void) + { + return ((UPINTX & (1 << RXINI)) ? true : false); + } + + /** Determines if the currently selected OUT pipe is ready to send an OUT packet to the attached device. + * + * \ingroup Group_PipePacketManagement + * + * \return Boolean true if the current pipe is ready for an OUT packet, false otherwise. + */ + static inline bool Pipe_IsOUTReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsOUTReady(void) + { + return ((UPINTX & (1 << TXOUTI)) ? true : false); + } + + /** Determines if no SETUP request is currently being sent to the attached device on the selected + * CONTROL type pipe. + * + * \ingroup Group_PipePacketManagement + * + * \return Boolean true if the current pipe is ready for a SETUP packet, false otherwise. + */ + static inline bool Pipe_IsSETUPSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsSETUPSent(void) + { + return ((UPINTX & (1 << TXSTPI)) ? true : false); + } + + /** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet. + * + * \ingroup Group_PipePacketManagement + */ + static inline void Pipe_ClearSETUP(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearSETUP(void) + { + UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON)); + } + + /** Acknowledges the reception of a setup IN request from the attached device on the currently selected + * pipe, freeing the bank ready for the next packet. + * + * \ingroup Group_PipePacketManagement + */ + static inline void Pipe_ClearIN(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearIN(void) + { + UPINTX &= ~((1 << RXINI) | (1 << FIFOCON)); + } + + /** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing + * the bank ready for the next packet. + * + * \ingroup Group_PipePacketManagement + */ + static inline void Pipe_ClearOUT(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearOUT(void) + { + UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON)); + } + + /** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on + * the currently selected pipe. This occurs when the host sends a packet to the device, but the device + * is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been + * received, it must be cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet + * can be re-sent. + * + * \ingroup Group_PipePacketManagement + * + * \return Boolean true if an NAK has been received on the current pipe, false otherwise. + */ + static inline bool Pipe_IsNAKReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsNAKReceived(void) + { + return ((UPINTX & (1 << NAKEDI)) ? true : false); + } + + /** Clears the NAK condition on the currently selected pipe. + * + * \ingroup Group_PipePacketManagement + * + * \see \ref Pipe_IsNAKReceived() for more details. + */ + static inline void Pipe_ClearNAKReceived(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearNAKReceived(void) + { + UPINTX &= ~(1 << NAKEDI); + } + + /** Determines if the currently selected pipe has had the STALL condition set by the attached device. + * + * \ingroup Group_PipePacketManagement + * + * \return Boolean true if the current pipe has been stalled by the attached device, false otherwise. + */ + static inline bool Pipe_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsStalled(void) + { + return ((UPINTX & (1 << RXSTALLI)) ? true : false); + } + + /** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the + * STALL condition itself (this must be done via a ClearFeature control request to the device). + * + * \ingroup Group_PipePacketManagement + */ + static inline void Pipe_ClearStall(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearStall(void) + { + UPINTX &= ~(1 << RXSTALLI); + } + + /** Reads one byte from the currently selected pipe's bank, for OUT direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \return Next byte in the currently selected pipe's FIFO buffer. + */ + static inline uint8_t Pipe_Read_Byte(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_Read_Byte(void) + { + return UPDATX; + } + + /** Writes one byte from the currently selected pipe's bank, for IN direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \param[in] Byte Next byte to write into the the currently selected pipe's FIFO buffer. + */ + static inline void Pipe_Write_Byte(const uint8_t Byte) ATTR_ALWAYS_INLINE; + static inline void Pipe_Write_Byte(const uint8_t Byte) + { + UPDATX = Byte; + } + + /** Discards one byte from the currently selected pipe's bank, for OUT direction pipes. + * + * \ingroup Group_PipePrimitiveRW + */ + static inline void Pipe_Discard_Byte(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_Discard_Byte(void) + { + uint8_t Dummy; + + Dummy = UPDATX; + } + + /** Reads two bytes from the currently selected pipe's bank in little endian format, for OUT + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \return Next word in the currently selected pipe's FIFO buffer. + */ + static inline uint16_t Pipe_Read_Word_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t Pipe_Read_Word_LE(void) + { + union + { + uint16_t Word; + uint8_t Bytes[2]; + } Data; + + Data.Bytes[0] = UPDATX; + Data.Bytes[1] = UPDATX; + + return Data.Word; + } + + /** Reads two bytes from the currently selected pipe's bank in big endian format, for OUT + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \return Next word in the currently selected pipe's FIFO buffer. + */ + static inline uint16_t Pipe_Read_Word_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t Pipe_Read_Word_BE(void) + { + union + { + uint16_t Word; + uint8_t Bytes[2]; + } Data; + + Data.Bytes[1] = UPDATX; + Data.Bytes[0] = UPDATX; + + return Data.Word; + } + + /** Writes two bytes to the currently selected pipe's bank in little endian format, for IN + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \param[in] Word Next word to write to the currently selected pipe's FIFO buffer. + */ + static inline void Pipe_Write_Word_LE(const uint16_t Word) ATTR_ALWAYS_INLINE; + static inline void Pipe_Write_Word_LE(const uint16_t Word) + { + UPDATX = (Word & 0xFF); + UPDATX = (Word >> 8); + } + + /** Writes two bytes to the currently selected pipe's bank in big endian format, for IN + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \param[in] Word Next word to write to the currently selected pipe's FIFO buffer. + */ + static inline void Pipe_Write_Word_BE(const uint16_t Word) ATTR_ALWAYS_INLINE; + static inline void Pipe_Write_Word_BE(const uint16_t Word) + { + UPDATX = (Word >> 8); + UPDATX = (Word & 0xFF); + } + + /** Discards two bytes from the currently selected pipe's bank, for OUT direction pipes. + * + * \ingroup Group_PipePrimitiveRW + */ + static inline void Pipe_Discard_Word(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_Discard_Word(void) + { + uint8_t Dummy; + + Dummy = UPDATX; + Dummy = UPDATX; + } + + /** Reads four bytes from the currently selected pipe's bank in little endian format, for OUT + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \return Next double word in the currently selected pipe's FIFO buffer. + */ + static inline uint32_t Pipe_Read_DWord_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint32_t Pipe_Read_DWord_LE(void) + { + union + { + uint32_t DWord; + uint8_t Bytes[4]; + } Data; + + Data.Bytes[0] = UPDATX; + Data.Bytes[1] = UPDATX; + Data.Bytes[2] = UPDATX; + Data.Bytes[3] = UPDATX; + + return Data.DWord; + } + + /** Reads four bytes from the currently selected pipe's bank in big endian format, for OUT + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \return Next double word in the currently selected pipe's FIFO buffer. + */ + static inline uint32_t Pipe_Read_DWord_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint32_t Pipe_Read_DWord_BE(void) + { + union + { + uint32_t DWord; + uint8_t Bytes[4]; + } Data; + + Data.Bytes[3] = UPDATX; + Data.Bytes[2] = UPDATX; + Data.Bytes[1] = UPDATX; + Data.Bytes[0] = UPDATX; + + return Data.DWord; + } + + /** Writes four bytes to the currently selected pipe's bank in little endian format, for IN + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \param[in] DWord Next double word to write to the currently selected pipe's FIFO buffer. + */ + static inline void Pipe_Write_DWord_LE(const uint32_t DWord) ATTR_ALWAYS_INLINE; + static inline void Pipe_Write_DWord_LE(const uint32_t DWord) + { + UPDATX = (DWord & 0xFF); + UPDATX = (DWord >> 8); + UPDATX = (DWord >> 16); + UPDATX = (DWord >> 24); + } + + /** Writes four bytes to the currently selected pipe's bank in big endian format, for IN + * direction pipes. + * + * \ingroup Group_PipePrimitiveRW + * + * \param[in] DWord Next double word to write to the currently selected pipe's FIFO buffer. + */ + static inline void Pipe_Write_DWord_BE(const uint32_t DWord) ATTR_ALWAYS_INLINE; + static inline void Pipe_Write_DWord_BE(const uint32_t DWord) + { + UPDATX = (DWord >> 24); + UPDATX = (DWord >> 16); + UPDATX = (DWord >> 8); + UPDATX = (DWord & 0xFF); + } + + /** Discards four bytes from the currently selected pipe's bank, for OUT direction pipes. + * + * \ingroup Group_PipePrimitiveRW + */ + static inline void Pipe_Discard_DWord(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_Discard_DWord(void) + { + uint8_t Dummy; + + Dummy = UPDATX; + Dummy = UPDATX; + Dummy = UPDATX; + Dummy = UPDATX; + } + + /* External Variables: */ + /** Global indicating the maximum packet size of the default control pipe located at address + * 0 in the device. This value is set to the value indicated in the attached device's device + * descriptor once the USB interface is initialized into host mode and a device is attached + * to the USB bus. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + */ + extern uint8_t USB_ControlPipeSize; + + /* Function Prototypes: */ + /** Configures the specified pipe number with the given pipe type, token, target endpoint number in the + * attached device, bank size and banking mode. + * + * A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze() + * before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or + * sending data to the device in OUT mode. IN type pipes are also automatically configured to accept infinite + * numbers of IN requests without automatic freezing - this can be overridden by a call to + * \ref Pipe_SetFiniteINRequests(). + * + * \param[in] Number Pipe number to configure. This must be more than 0 and less than \ref PIPE_TOTAL_PIPES. + * + * \param[in] Type Type of pipe to configure, a EP_TYPE_* mask. Not all pipe types are available on Low + * Speed USB devices - refer to the USB 2.0 specification. + * + * \param[in] Token Pipe data token, either \ref PIPE_TOKEN_SETUP, \ref PIPE_TOKEN_OUT or \ref PIPE_TOKEN_IN. + * All pipes (except Control type) are unidirectional - data may only be read from or + * written to the pipe bank based on its direction, not both. + * + * \param[in] EndpointNumber Endpoint index within the attached device that the pipe should interface to. + * + * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to + * the USB device, or after they have been received from the USB device (depending on + * the pipe's data direction). The bank size must indicate the maximum packet size that + * the pipe can handle. + * + * \param[in] Banks Number of banks to use for the pipe being configured, a PIPE_BANK_* mask. More banks + * uses more USB DPRAM, but offers better performance. Isochronous type pipes must + * have at least two banks. + * + * \note Endpoints must be configured in ascending order, or bank corruption will occur. + * \n\n + * + * \note Certain models of USB AVR's pipes may have different maximum packet sizes based on the pipe's + * index - refer to the chosen USB AVR's datasheet to determine the maximum bank size for each pipe. + * \n\n + * + * \note The default control pipe should not be manually configured by the user application, as it is + * automatically configured by the library internally. + * \n\n + * + * \note This routine will automatically select the specified pipe upon success. Upon failure, the pipe which + * failed to reconfigure correctly will be selected. + * + * \return Boolean true if the configuration succeeded, false otherwise. + */ + bool Pipe_ConfigurePipe(const uint8_t Number, + const uint8_t Type, + const uint8_t Token, + const uint8_t EndpointNumber, + const uint16_t Size, + const uint8_t Banks); + + /** Spin-loops until the currently selected non-control pipe is ready for the next packed of data to be read + * or written to it, aborting in the case of an error condition (such as a timeout or device disconnect). + * + * \ingroup Group_PipeRW + * + * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum. + */ + uint8_t Pipe_WaitUntilReady(void); + + /** Determines if a pipe has been bound to the given device endpoint address. If a pipe which is bound to the given + * endpoint is found, it is automatically selected. + * + * \param[in] EndpointAddress Address and direction mask of the endpoint within the attached device to check. + * + * \return Boolean true if a pipe bound to the given endpoint address of the specified direction is found, false + * otherwise. + */ + bool Pipe_IsEndpointBound(const uint8_t EndpointAddress); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #if !defined(ENDPOINT_CONTROLEP) + #define ENDPOINT_CONTROLEP 0 + #endif + + /* Inline Functions: */ + static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes) + { + uint8_t MaskVal = 0; + uint16_t CheckBytes = 8; + + while ((CheckBytes < Bytes) && (CheckBytes < PIPE_MAX_SIZE)) + { + MaskVal++; + CheckBytes <<= 1; + } + + return (MaskVal << EPSIZE0); + } + + /* Function Prototypes: */ + void Pipe_ClearPipes(void); + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/LowLevel/USBController.c b/LUFA/Drivers/USB/LowLevel/USBController.c new file mode 100644 index 0000000..b7f6bc7 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/USBController.c @@ -0,0 +1,232 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#define __INCLUDE_FROM_USB_CONTROLLER_C +#include "USBController.h" + +#if (!defined(USB_HOST_ONLY) && !defined(USB_DEVICE_ONLY)) +volatile uint8_t USB_CurrentMode = USB_MODE_None; +#endif + +#if !defined(USE_STATIC_OPTIONS) +volatile uint8_t USB_Options; +#endif + +void USB_Init( + #if defined(USB_CAN_BE_BOTH) + const uint8_t Mode + #endif + + #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS)) + , + #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS)) + void + #endif + + #if !defined(USE_STATIC_OPTIONS) + const uint8_t Options + #endif + ) +{ + #if !defined(USE_STATIC_OPTIONS) + USB_Options = Options; + #endif + + if (!(USB_Options & USB_OPT_REG_DISABLED)) + USB_REG_On(); + else + USB_REG_Off(); + + #if defined(USB_CAN_BE_BOTH) + if (Mode == USB_MODE_UID) + { + UHWCON |= (1 << UIDE); + USB_INT_Enable(USB_INT_IDTI); + USB_CurrentMode = USB_GetUSBModeFromUID(); + } + else + { + USB_CurrentMode = Mode; + } + #endif + + USB_IsInitialized = true; + + USB_ResetInterface(); +} + +void USB_ShutDown(void) +{ + USB_INT_DisableAllInterrupts(); + USB_INT_ClearAllInterrupts(); + + USB_Detach(); + USB_Controller_Disable(); + + if (!(USB_Options & USB_OPT_MANUAL_PLL)) + USB_PLL_Off(); + + USB_REG_Off(); + + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + USB_OTGPAD_Off(); + #endif + + #if defined(USB_CAN_BE_BOTH) + USB_CurrentMode = USB_MODE_None; + #endif + + USB_IsInitialized = false; +} + +void USB_ResetInterface(void) +{ + #if defined(USB_CAN_BE_BOTH) + bool UIDModeSelectEnabled = ((UHWCON & (1 << UIDE)) != 0); + #endif + + USB_INT_DisableAllInterrupts(); + USB_INT_ClearAllInterrupts(); + + USB_Controller_Reset(); + + if (!(USB_Options & USB_OPT_MANUAL_PLL)) + { + #if defined(USB_SERIES_4_AVR) + PLLFRQ = ((1 << PLLUSB) | (1 << PDIV3) | (1 << PDIV1)); + #endif + + USB_PLL_On(); + while (!(USB_PLL_IsReady())); + } + + #if defined(USB_CAN_BE_BOTH) + if (UIDModeSelectEnabled) + { + UHWCON |= (1 << UIDE); + USB_INT_Enable(USB_INT_IDTI); + } + #endif + + USB_CLK_Unfreeze(); + + if (USB_CurrentMode == USB_MODE_Device) + { + #if defined(USB_CAN_BE_DEVICE) + #if (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) + UHWCON |= (1 << UIMOD); + #endif + + USB_Init_Device(); + #endif + } + else if (USB_CurrentMode == USB_MODE_Host) + { + #if defined(USB_CAN_BE_HOST) + UHWCON &= ~(1 << UIMOD); + USB_Init_Host(); + #endif + } + + #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) + USB_OTGPAD_On(); + #endif +} + +#if defined(USB_CAN_BE_DEVICE) +static void USB_Init_Device(void) +{ + USB_DeviceState = DEVICE_STATE_Unattached; + USB_ConfigurationNumber = 0; + + #if !defined(NO_DEVICE_REMOTE_WAKEUP) + USB_RemoteWakeupEnabled = false; + #endif + + #if !defined(NO_DEVICE_SELF_POWER) + USB_CurrentlySelfPowered = false; + #endif + + #if !defined(FIXED_CONTROL_ENDPOINT_SIZE) + USB_Descriptor_Device_t* DeviceDescriptorPtr; + + if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR) + { + #if defined(USE_RAM_DESCRIPTORS) + USB_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size; + #elif defined(USE_EEPROM_DESCRIPTORS) + USB_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size); + #else + USB_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size); + #endif + } + #endif + + #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) + if (USB_Options & USB_DEVICE_OPT_LOWSPEED) + USB_Device_SetLowSpeed(); + else + USB_Device_SetFullSpeed(); + + USB_INT_Enable(USB_INT_VBUS); + #endif + + Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, + ENDPOINT_DIR_OUT, USB_ControlEndpointSize, + ENDPOINT_BANK_SINGLE); + + USB_INT_Clear(USB_INT_SUSPI); + USB_INT_Enable(USB_INT_SUSPI); + USB_INT_Enable(USB_INT_EORSTI); + + USB_Attach(); +} +#endif + +#if defined(USB_CAN_BE_HOST) +static void USB_Init_Host(void) +{ + USB_HostState = HOST_STATE_Unattached; + USB_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE; + + USB_Host_HostMode_On(); + + USB_Host_VBUS_Auto_Off(); + USB_Host_VBUS_Manual_Enable(); + USB_Host_VBUS_Manual_On(); + + USB_INT_Enable(USB_INT_SRPI); + USB_INT_Enable(USB_INT_BCERRI); + + USB_Attach(); +} +#endif + diff --git a/LUFA/Drivers/USB/LowLevel/USBController.h b/LUFA/Drivers/USB/LowLevel/USBController.h new file mode 100644 index 0000000..3ac73aa --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/USBController.h @@ -0,0 +1,471 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB low level USB controller definitions. + * + * This file contains structures, function prototypes and macros related to the low level configuration of the + * USB controller, to start, stop and reset the USB library core. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +/** \ingroup Group_USB + * @defgroup Group_USBManagement USB Interface Management + * + * Functions, macros, variables, enums and types related to the setup and management of the USB interface. + * + * @{ + */ + +#ifndef __USBCONTROLLER_H__ +#define __USBCONTROLLER_H__ + + /* Includes: */ + #include + #include + #include + + #include "../HighLevel/USBMode.h" + + #include "../../../Common/Common.h" + #include "../HighLevel/USBMode.h" + #include "../HighLevel/Events.h" + #include "../HighLevel/USBTask.h" + #include "USBInterrupt.h" + + #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__) + #include "Host.h" + #include "OTG.h" + #include "Pipe.h" + #include "../HighLevel/HostStandardReq.h" + #include "../HighLevel/PipeStream.h" + #endif + + #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__) + #include "Device.h" + #include "Endpoint.h" + #include "../HighLevel/DeviceStandardReq.h" + #include "../HighLevel/EndpointStream.h" + #endif + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks and Defines: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + #if !defined(F_CLOCK) + #error F_CLOCK is not defined. You must define F_CLOCK to the frequency of the unprescaled input clock in your project makefile. + #endif + + #if (F_CLOCK == 8000000) + #if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \ + defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \ + defined(__AVR_ATmega32U2__)) + #define USB_PLL_PSC 0 + #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) + #define USB_PLL_PSC 0 + #elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega32U6__)) + #define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0)) + #elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)) + #define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0)) + #endif + #elif (F_CLOCK == 16000000) + #if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \ + defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \ + defined(__AVR_ATmega32U2__)) + #define USB_PLL_PSC (1 << PLLP0) + #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) + #define USB_PLL_PSC (1 << PINDIV) + #elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_ATmega32U6__)) + #define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP1)) + #elif (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)) + #define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP0)) + #endif + #endif + + #if !defined(USB_PLL_PSC) + #error No PLL prescale value available for chosen F_CLOCK value and AVR model. + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name USB Controller Option Masks */ + //@{ + /** Regulator disable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad + * regulator should be enabled to regulate the data pin voltages to within the USB standard. + * + * \note See USB AVR data sheet for more information on the internal pad regulator. + */ + #define USB_OPT_REG_DISABLED (1 << 1) + + /** Regulator enable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad + * regulator should be disabled and the AVR's VCC level used for the data pads. + * + * \note See USB AVR data sheet for more information on the internal pad regulator. + */ + #define USB_OPT_REG_ENABLED (0 << 1) + + /** Manual PLL control option mask for \ref USB_Init(). This indicates to the library that the user application + * will take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock + * that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations. + */ + #define USB_OPT_MANUAL_PLL (1 << 2) + + /** Automatic PLL control option mask for \ref USB_Init(). This indicates to the library that the library should + * take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock + * that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations. + */ + #define USB_OPT_AUTO_PLL (0 << 2) + //@} + + /** \name Endpoint/Pipe Type Masks */ + //@{ + /** Mask for a CONTROL type endpoint or pipe. + * + * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions. + */ + #define EP_TYPE_CONTROL 0x00 + + /** Mask for an ISOCHRONOUS type endpoint or pipe. + * + * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions. + */ + #define EP_TYPE_ISOCHRONOUS 0x01 + + /** Mask for a BULK type endpoint or pipe. + * + * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions. + */ + #define EP_TYPE_BULK 0x02 + + /** Mask for an INTERRUPT type endpoint or pipe. + * + * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions. + */ + #define EP_TYPE_INTERRUPT 0x03 + //@} + + #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__) + /** Constant for the maximum software timeout period of the USB data stream transfer functions + * (both control and standard) when in either device or host mode. If the next packet of a stream + * is not received or acknowledged within this time period, the stream function will fail. + * + * This value may be overridden in the user project makefile as the value of the + * \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch. + */ + #define USB_STREAM_TIMEOUT_MS 100 + #endif + + /* Inline Functions: */ + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__) + /** Returns boolean true if the VBUS line is currently high (i.e. the USB host is supplying power), + * otherwise returns false. + * + * \note This function is not available on some AVR models which do not support hardware VBUS monitoring. + */ + static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_VBUS_GetStatus(void) + { + return ((USBSTA & (1 << VBUS)) ? true : false); + } + #endif + + /** Detaches the device from the USB bus. This has the effect of removing the device from any + * attached host, ceasing USB communications. If no host is present, this prevents any host from + * enumerating the device once attached until \ref USB_Attach() is called. + */ + static inline void USB_Detach(void) ATTR_ALWAYS_INLINE; + static inline void USB_Detach(void) + { + UDCON |= (1 << DETACH); + } + + /** Attaches the device to the USB bus. This announces the device's presence to any attached + * USB host, starting the enumeration process. If no host is present, attaching the device + * will allow for enumeration once a host is connected to the device. + * + * This is inexplicably also required for proper operation while in host mode, to enable the + * attachment of a device to the host. This is despite the bit being located in the device-mode + * register and despite the datasheet making no mention of its requirement in host mode. + */ + static inline void USB_Attach(void) ATTR_ALWAYS_INLINE; + static inline void USB_Attach(void) + { + UDCON &= ~(1 << DETACH); + } + + /* Function Prototypes: */ + /** Main function to initialize and start the USB interface. Once active, the USB interface will + * allow for device connection to a host when in device mode, or for device enumeration while in + * host mode. + * + * As the USB library relies on interrupts for the device and host mode enumeration processes, + * the user must enable global interrupts before or shortly after this function is called. In + * device mode, interrupts must be enabled within 500ms of this function being called to ensure + * that the host does not time out whilst enumerating the device. In host mode, interrupts may be + * enabled at the application's leisure however enumeration will not begin of an attached device + * until after this has occurred. + * + * Calling this function when the USB interface is already initialized will cause a complete USB + * interface reset and re-enumeration. + * + * \param[in] Mode This is a mask indicating what mode the USB interface is to be initialized to, a value + * from the \ref USB_Modes_t enum. + * + * \param[in] Options Mask indicating the options which should be used when initializing the USB + * interface to control the USB interface's behaviour. This should be comprised of + * a USB_OPT_REG_* mask to control the regulator, a USB_OPT_*_PLL mask to control the + * PLL, and a USB_DEVICE_OPT_* mask (when the device mode is enabled) to set the device + * mode speed. + * + * \note To reduce the FLASH requirements of the library if only device or host mode is required, + * the mode can be statically set in the project makefile by defining the token USB_DEVICE_ONLY + * (for device mode) or USB_HOST_ONLY (for host mode), passing the token to the compiler + * via the -D switch. If the mode is statically set, this parameter does not exist in the + * function prototype. + * \n\n + * + * \note To reduce the FLASH requirements of the library if only fixed settings are are required, + * the options may be set statically in the same manner as the mode (see the Mode parameter of + * this function). To statically set the USB options, pass in the USE_STATIC_OPTIONS token, + * defined to the appropriate options masks. When the options are statically set, this + * parameter does not exist in the function prototype. + * \n\n + * + * \note The mode parameter does not exist on devices where only one mode is possible, such as USB + * AVR models which only implement the USB device mode in hardware. + * + * \see Device.h for the USB_DEVICE_OPT_* masks. + */ + void USB_Init( + #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__) + const uint8_t Mode + #endif + + #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS)) || defined(__DOXYGEN__) + , + #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS)) + void + #endif + + #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__) + const uint8_t Options + #endif + ); + + /** Shuts down the USB interface. This turns off the USB interface after deallocating all USB FIFO + * memory, endpoints and pipes. When turned off, no USB functionality can be used until the interface + * is restarted with the \ref USB_Init() function. + */ + void USB_ShutDown(void); + + /** Resets the interface, when already initialized. This will re-enumerate the device if already connected + * to a host, or re-enumerate an already attached device when in host mode. + */ + void USB_ResetInterface(void); + + /* Global Variables: */ + #if (!defined(USB_HOST_ONLY) && !defined(USB_DEVICE_ONLY)) || defined(__DOXYGEN__) + /** Indicates the mode that the USB interface is currently initialized to, a value from the + * \ref USB_Modes_t enum. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + * \n\n + * + * \note When the controller is initialized into UID autodetection mode, this variable will hold the + * currently selected USB mode (i.e. \ref USB_MODE_Device or \ref USB_MODE_Host). If the controller + * is fixed into a specific mode (either through the USB_DEVICE_ONLY or USB_HOST_ONLY compile time + * options, or a limitation of the USB controller in the chosen device model) this will evaluate to + * a constant of the appropriate value and will never evaluate to \ref USB_MODE_None even when the + * USB interface is not initialized. + */ + extern volatile uint8_t USB_CurrentMode; + #elif defined(USB_HOST_ONLY) + #define USB_CurrentMode USB_MODE_Host + #elif defined(USB_DEVICE_ONLY) + #define USB_CurrentMode USB_MODE_Device + #endif + + #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__) + /** Indicates the current USB options that the USB interface was initialized with when \ref USB_Init() + * was called. This value will be one of the USB_MODE_* masks defined elsewhere in this module. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + */ + extern volatile uint8_t USB_Options; + #elif defined(USE_STATIC_OPTIONS) + #define USB_Options USE_STATIC_OPTIONS + #endif + + /* Enums: */ + /** Enum for the possible USB controller modes, for initialization via \ref USB_Init() and indication back to the + * user application via \ref USB_CurrentMode. + */ + enum USB_Modes_t + { + USB_MODE_None = 0, /**< Indicates that the controller is currently not initialized in any specific USB mode. */ + USB_MODE_Device = 1, /**< Indicates that the controller is currently initialized in USB Device mode. */ + USB_MODE_Host = 2, /**< Indicates that the controller is currently initialized in USB Host mode. */ + USB_MODE_UID = 3, /**< Indicates that the controller should determine the USB mode from the UID pin of the + * USB connector. + */ + }; + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Function Prototypes: */ + #if defined(__INCLUDE_FROM_USB_CONTROLLER_C) + #if defined(USB_CAN_BE_DEVICE) + static void USB_Init_Device(void); + #endif + + #if defined(USB_CAN_BE_HOST) + static void USB_Init_Host(void); + #endif + #endif + + /* Inline Functions: */ + static inline void USB_PLL_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_PLL_On(void) + { + PLLCSR = USB_PLL_PSC; + PLLCSR |= (1 << PLLE); + } + + static inline void USB_PLL_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_PLL_Off(void) + { + PLLCSR = 0; + } + + static inline bool USB_PLL_IsReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_PLL_IsReady(void) + { + return ((PLLCSR & (1 << PLOCK)) ? true : false); + } + + static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_REG_On(void) + { + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + UHWCON |= (1 << UVREGE); + #else + REGCR &= ~(1 << REGDIS); + #endif + } + + static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_REG_Off(void) + { + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + UHWCON &= ~(1 << UVREGE); + #else + REGCR |= (1 << REGDIS); + #endif + } + + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + static inline void USB_OTGPAD_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTGPAD_On(void) + { + USBCON |= (1 << OTGPADE); + } + + static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTGPAD_Off(void) + { + USBCON &= ~(1 << OTGPADE); + } + #endif + + static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE; + static inline void USB_CLK_Freeze(void) + { + USBCON |= (1 << FRZCLK); + } + + static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE; + static inline void USB_CLK_Unfreeze(void) + { + USBCON &= ~(1 << FRZCLK); + } + + static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Controller_Enable(void) + { + USBCON |= (1 << USBE); + } + + static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Controller_Disable(void) + { + USBCON &= ~(1 << USBE); + } + + static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE; + static inline void USB_Controller_Reset(void) + { + const uint8_t Temp = USBCON; + + USBCON = (Temp & ~(1 << USBE)); + USBCON = (Temp | (1 << USBE)); + } + + #if defined(USB_CAN_BE_BOTH) + static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t USB_GetUSBModeFromUID(void) + { + if (USBSTA & (1 << ID)) + return USB_MODE_Device; + else + return USB_MODE_Host; + } + #endif + + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/USB/LowLevel/USBInterrupt.c b/LUFA/Drivers/USB/LowLevel/USBInterrupt.c new file mode 100644 index 0000000..c3e87e3 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/USBInterrupt.c @@ -0,0 +1,269 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#define __INCLUDE_FROM_USB_DRIVER +#include "USBInterrupt.h" + +void USB_INT_DisableAllInterrupts(void) +{ + #if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + USBCON &= ~((1 << VBUSTE) | (1 << IDTE)); + #elif defined(USB_SERIES_4_AVR) + USBCON &= ~(1 << VBUSTE); + #endif + + #if defined(USB_CAN_BE_BOTH) + OTGIEN = 0; + #endif + + #if defined(USB_CAN_BE_HOST) + UHIEN = 0; + #endif + + #if defined(USB_CAN_BE_DEVICE) + UDIEN = 0; + #endif +} + +void USB_INT_ClearAllInterrupts(void) +{ + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + USBINT = 0; + #endif + + #if defined(USB_CAN_BE_BOTH) + OTGINT = 0; + #endif + + #if defined(USB_CAN_BE_HOST) + UHINT = 0; + #endif + + #if defined(USB_CAN_BE_DEVICE) + UDINT = 0; + #endif +} + +ISR(USB_GEN_vect, ISR_BLOCK) +{ + #if defined(USB_CAN_BE_DEVICE) + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + if (USB_INT_HasOccurred(USB_INT_VBUS) && USB_INT_IsEnabled(USB_INT_VBUS)) + { + USB_INT_Clear(USB_INT_VBUS); + + if (USB_VBUS_GetStatus()) + { + USB_DeviceState = DEVICE_STATE_Powered; + EVENT_USB_Device_Connect(); + } + else + { + USB_DeviceState = DEVICE_STATE_Unattached; + EVENT_USB_Device_Disconnect(); + } + } + #endif + + if (USB_INT_HasOccurred(USB_INT_SUSPI) && USB_INT_IsEnabled(USB_INT_SUSPI)) + { + USB_INT_Clear(USB_INT_SUSPI); + + USB_INT_Disable(USB_INT_SUSPI); + USB_INT_Enable(USB_INT_WAKEUPI); + + USB_CLK_Freeze(); + + if (!(USB_Options & USB_OPT_MANUAL_PLL)) + USB_PLL_Off(); + + #if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT) + USB_DeviceState = DEVICE_STATE_Unattached; + EVENT_USB_Device_Disconnect(); + #else + USB_DeviceState = DEVICE_STATE_Suspended; + EVENT_USB_Device_Suspend(); + #endif + } + + if (USB_INT_HasOccurred(USB_INT_WAKEUPI) && USB_INT_IsEnabled(USB_INT_WAKEUPI)) + { + if (!(USB_Options & USB_OPT_MANUAL_PLL)) + { + USB_PLL_On(); + while (!(USB_PLL_IsReady())); + } + + USB_CLK_Unfreeze(); + + USB_INT_Clear(USB_INT_WAKEUPI); + + USB_INT_Disable(USB_INT_WAKEUPI); + USB_INT_Enable(USB_INT_SUSPI); + + if (USB_ConfigurationNumber) + USB_DeviceState = DEVICE_STATE_Configured; + else + USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Configured : DEVICE_STATE_Powered; + + #if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT) + EVENT_USB_Device_Connect(); + #else + EVENT_USB_Device_WakeUp(); + #endif + } + + if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI)) + { + USB_INT_Clear(USB_INT_EORSTI); + + USB_DeviceState = DEVICE_STATE_Default; + USB_ConfigurationNumber = 0; + + USB_INT_Clear(USB_INT_SUSPI); + USB_INT_Disable(USB_INT_SUSPI); + USB_INT_Enable(USB_INT_WAKEUPI); + + Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, + ENDPOINT_DIR_OUT, USB_ControlEndpointSize, + ENDPOINT_BANK_SINGLE); + + #if defined(INTERRUPT_CONTROL_ENDPOINT) + USB_INT_Enable(USB_INT_RXSTPI); + #endif + + EVENT_USB_Device_Reset(); + } + + #if !defined(NO_SOF_EVENTS) + if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI)) + { + USB_INT_Clear(USB_INT_SOFI); + + EVENT_USB_Device_StartOfFrame(); + } + #endif + #endif + + #if defined(USB_CAN_BE_HOST) + if (USB_INT_HasOccurred(USB_INT_DDISCI) && USB_INT_IsEnabled(USB_INT_DDISCI)) + { + USB_INT_Clear(USB_INT_DDISCI); + USB_INT_Clear(USB_INT_DCONNI); + USB_INT_Disable(USB_INT_DDISCI); + + EVENT_USB_Host_DeviceUnattached(); + + USB_ResetInterface(); + } + + if (USB_INT_HasOccurred(USB_INT_VBERRI) && USB_INT_IsEnabled(USB_INT_VBERRI)) + { + USB_INT_Clear(USB_INT_VBERRI); + + USB_Host_VBUS_Manual_Off(); + USB_Host_VBUS_Auto_Off(); + + EVENT_USB_Host_HostError(HOST_ERROR_VBusVoltageDip); + EVENT_USB_Host_DeviceUnattached(); + + USB_HostState = HOST_STATE_Unattached; + } + + if (USB_INT_HasOccurred(USB_INT_SRPI) && USB_INT_IsEnabled(USB_INT_SRPI)) + { + USB_INT_Clear(USB_INT_SRPI); + USB_INT_Disable(USB_INT_SRPI); + + EVENT_USB_Host_DeviceAttached(); + + USB_INT_Enable(USB_INT_DDISCI); + + USB_HostState = HOST_STATE_Powered; + } + + if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI)) + { + USB_INT_Clear(USB_INT_BCERRI); + + EVENT_USB_Host_DeviceEnumerationFailed(HOST_ENUMERROR_NoDeviceDetected, 0); + EVENT_USB_Host_DeviceUnattached(); + + USB_ResetInterface(); + } + + #if !defined(NO_SOF_EVENTS) + if (USB_INT_HasOccurred(USB_INT_HSOFI) && USB_INT_IsEnabled(USB_INT_HSOFI)) + { + USB_INT_Clear(USB_INT_HSOFI); + + EVENT_USB_Host_StartOfFrame(); + } + #endif + #endif + + #if defined(USB_CAN_BE_BOTH) + if (USB_INT_HasOccurred(USB_INT_IDTI) && USB_INT_IsEnabled(USB_INT_IDTI)) + { + USB_INT_Clear(USB_INT_IDTI); + + if (USB_DeviceState != DEVICE_STATE_Unattached) + EVENT_USB_Device_Disconnect(); + + if (USB_HostState != HOST_STATE_Unattached) + EVENT_USB_Host_DeviceUnattached(); + + USB_CurrentMode = USB_GetUSBModeFromUID(); + USB_ResetInterface(); + + EVENT_USB_UIDChange(); + } + #endif +} + +#if defined(INTERRUPT_CONTROL_ENDPOINT) && defined(USB_CAN_BE_DEVICE) +ISR(USB_COM_vect, ISR_BLOCK) +{ + uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint(); + + Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); + USB_INT_Disable(USB_INT_RXSTPI); + + NONATOMIC_BLOCK(NONATOMIC_FORCEOFF) + { + USB_Device_ProcessControlRequest(); + } + + Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); + USB_INT_Enable(USB_INT_RXSTPI); + Endpoint_SelectEndpoint(PrevSelectedEndpoint); +} +#endif + diff --git a/LUFA/Drivers/USB/LowLevel/USBInterrupt.h b/LUFA/Drivers/USB/LowLevel/USBInterrupt.h new file mode 100644 index 0000000..5d0c991 --- /dev/null +++ b/LUFA/Drivers/USB/LowLevel/USBInterrupt.h @@ -0,0 +1,106 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief USB controller interrupt service routine management. + * + * This file contains definitions required for the correct handling of low level USB service routine interrupts + * from the USB controller. + * + * \note This file should not be included directly. It is automatically included as needed by the USB driver + * dispatch header located in LUFA/Drivers/USB/USB.h. + */ + +#ifndef __USBINTERRUPT_H__ +#define __USBINTERRUPT_H__ + + /* Includes: */ + #include + #include + #include + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_USB_DRIVER) + #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define USB_INT_Enable(int) MACROS{ USB_INT_GET_EN_REG(int) |= USB_INT_GET_EN_MASK(int); }MACROE + #define USB_INT_Disable(int) MACROS{ USB_INT_GET_EN_REG(int) &= ~(USB_INT_GET_EN_MASK(int)); }MACROE + #define USB_INT_Clear(int) MACROS{ USB_INT_GET_INT_REG(int) &= ~(USB_INT_GET_INT_MASK(int)); }MACROE + #define USB_INT_IsEnabled(int) ((USB_INT_GET_EN_REG(int) & USB_INT_GET_EN_MASK(int)) ? true : false) + #define USB_INT_HasOccurred(int) ((USB_INT_GET_INT_REG(int) & USB_INT_GET_INT_MASK(int)) ? true : false) + + #define USB_INT_GET_EN_REG(a, b, c, d) a + #define USB_INT_GET_EN_MASK(a, b, c, d) b + #define USB_INT_GET_INT_REG(a, b, c, d) c + #define USB_INT_GET_INT_MASK(a, b, c, d) d + + #define USB_INT_VBUS USBCON, (1 << VBUSTE) , USBINT, (1 << VBUSTI) + #define USB_INT_IDTI USBCON, (1 << IDTE) , USBINT, (1 << IDTI) + #define USB_INT_WAKEUPI UDIEN , (1 << WAKEUPE), UDINT , (1 << WAKEUPI) + #define USB_INT_SUSPI UDIEN , (1 << SUSPE) , UDINT , (1 << SUSPI) + #define USB_INT_EORSTI UDIEN , (1 << EORSTE) , UDINT , (1 << EORSTI) + #define USB_INT_DCONNI UHIEN , (1 << DCONNE) , UHINT , (1 << DCONNI) + #define USB_INT_DDISCI UHIEN , (1 << DDISCE) , UHINT , (1 << DDISCI) + #define USB_INT_BCERRI OTGIEN, (1 << BCERRE) , OTGINT, (1 << BCERRI) + #define USB_INT_VBERRI OTGIEN, (1 << VBERRE) , OTGINT, (1 << VBERRI) + #define USB_INT_SOFI UDIEN, (1 << SOFE) , UDINT , (1 << SOFI) + #define USB_INT_HSOFI UHIEN, (1 << HSOFE) , UHINT , (1 << HSOFI) + #define USB_INT_RSTI UHIEN , (1 << RSTE) , UHINT , (1 << RSTI) + #define USB_INT_SRPI OTGIEN, (1 << SRPE) , OTGINT, (1 << SRPI) + #define USB_INT_RXSTPI UEIENX, (1 << RXSTPE) , UEINTX, (1 << RXSTPI) + + /* Includes: */ + #include "../../../Common/Common.h" + #include "../HighLevel/USBMode.h" + #include "../HighLevel/Events.h" + #include "USBController.h" + + /* Function Prototypes: */ + void USB_INT_ClearAllInterrupts(void); + void USB_INT_DisableAllInterrupts(void); + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + diff --git a/LUFA/Drivers/USB/USB.h b/LUFA/Drivers/USB/USB.h new file mode 100644 index 0000000..71a337c --- /dev/null +++ b/LUFA/Drivers/USB/USB.h @@ -0,0 +1,408 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Master include file for the library USB functionality. + * + * Master include file for the library USB functionality. + * + * This file should be included in all user projects making use of the USB portions of the library, instead of + * including any headers in the USB/LowLevel/ or USB/HighLevel/ subdirectories. + */ + +/** @defgroup Group_USB USB Core - LUFA/Drivers/USB/USB.h + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Drivers/USB/LowLevel/Device.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/LowLevel/Endpoint.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/LowLevel/Host.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/LowLevel/Pipe.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/LowLevel/USBController.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/LowLevel/USBInterrupt.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/HighLevel/DeviceStandardReq.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/HighLevel/Events.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/HighLevel/EndpointStream.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/HighLevel/HostStandardReq.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/HighLevel/PipeStream.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/HighLevel/USBTask.c (Makefile source module name: LUFA_SRC_USB) + * + * \section Module Description + * Driver and framework for the USB controller hardware on the USB series of AVR microcontrollers. This module + * consists of many submodules, and is designed to provide an easy way to configure and control USB host, device + * or OTG mode USB applications. + * + * The USB stack requires the sole control over the USB controller in the microcontroller only; i.e. it does not + * require any additional AVR timers, etc. to operate. This ensures that the USB stack requires as few resources + * as possible. + * + * The USB stack can be used in Device Mode for connections to USB Hosts (see \ref Group_Device), in Host mode for + * hosting of other USB devices (see \ref Group_Host), or as a dual role device which can either act as a USB host + * or device depending on what peripheral is connected (see \ref Group_OTG). Both modes also require a common set + * of USB management functions found \ref Group_USBManagement. + */ + +/** @defgroup Group_USBClassDrivers USB Class Drivers + * + * Drivers for both host and device mode of the standard USB classes, for rapid application development. + * Class drivers give a framework which sits on top of the low level library API, allowing for standard + * USB classes to be implemented in a project with minimal user code. These drivers can be used in + * conjunction with the library low level APIs to implement interfaces both via the class drivers and via + * the standard library APIs. + * + * Multiple device mode class drivers can be used within a project, including multiple instances of the + * same class driver. In this way, USB Hosts and Devices can be made quickly using the internal class drivers + * so that more time and effort can be put into the end application instead of the USB protocol. + * + * The available class drivers and their modes are listed below. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * +* + * + * + * + * + * + * + * + * + * + * + * + *
USB ClassDevice ModeHost Mode
AudioYesNo
CDCYesYes
HIDYesYes
MIDIYesYes
Mass StorageYesYes
PrinterNoYes
RNDISYesYes
Still ImageNoYes
+ * + * + * \section Sec_UsingClassDrivers Using the Class Drivers + * To make the Class drivers easy to integrate into a user application, they all implement a standardized + * design with similarly named/used function, enums, defines and types. The two different modes are implemented + * slightly differently, and thus will be explained separately. For information on a specific class driver, read + * the class driver's module documentation. + * + * \subsection SSec_ClassDriverDevice Device Mode Class Drivers + * Implementing a Device Mode Class Driver in a user application requires a number of steps to be followed. Firstly, + * the module configuration and state structure must be added to the project source. These structures are named in a + * similar manner between classes, that of USB_ClassInfo_{Class Name}_Device_t, and are used to hold the + * complete state and configuration for each class instance. Multiple class instances is where the power of the class + * drivers lie; multiple interfaces of the same class simply require more instances of the Class Driver's ClassInfo + * structure. + * + * Inside the ClassInfo structure lies two sections, a Config section, and a State section. The Config + * section contains the instance's configuration parameters, and must have all fields set by the user application + * before the class driver is used. Each Device mode Class driver typically contains a set of configuration parameters + * for the endpoint size/number of the associated logical USB interface, plus any class-specific configuration parameters. + * + * The State section of the ClassInfo structures are designed to be controlled by the Class Drivers only for + * maintaining the Class Driver instance's state, and should not normally be set by the user application. + * + * The following is an example of a properly initialized instance of the Audio Class Driver structure: + * + * \code + * USB_ClassInfo_Audio_Device_t My_Audio_Interface = + * { + * .Config = + * { + * .StreamingInterfaceNumber = 1, + * + * .DataINEndpointNumber = 1, + * .DataINEndpointSize = 256, + * }, + * }; + * \endcode + * + * \note The class driver's configuration parameters should match those used in the device's descriptors that are + * sent to the host. + * + * To initialize the Class driver instance, the driver's {Class Name}_Device_ConfigureEndpoints() function + * should be called in response to the \ref EVENT_USB_Device_ConfigurationChanged() event. This function will return a + * boolean value if the driver successfully initialized the instance. Like all the class driver functions, this function + * takes in the address of the specific instance you wish to initialize - in this manner, multiple separate instances of + * the same class type can be initialized like thus: + * + * \code + * void EVENT_USB_Device_ConfigurationChanged(void) + * { + * LEDs_SetAllLEDs(LEDMASK_USB_READY); + * + * if (!(Audio_Device_ConfigureEndpoints(&My_Audio_Interface))) + * LEDs_SetAllLEDs(LEDMASK_USB_ERROR); + * } + * \endcode + * + * Once initialized, it is important to maintain the class driver's state by repeatedly calling the Class Driver's + * {Class Name}_Device_USBTask() function in the main program loop. The exact implementation of this + * function varies between class drivers, and can be used for any internal class driver purpose to maintain each + * instance. Again, this function uses the address of the instance to operate on, and thus needs to be called for each + * separate instance, just like the main USB maintenance routine \ref USB_USBTask(): + * + * \code + * int main(void) + * { + * SetupHardware(); + * + * LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); + * + * for (;;) + * { + * Create_And_Process_Samples(); + * + * Audio_Device_USBTask(&My_Audio_Interface); + * USB_USBTask(); + * } + * } + * \endcode + * + * The final standardized Device Class Driver function is the Control Request handler function + * {Class Name}_Device_ProcessControlRequest(), which should be called when the + * \ref EVENT_USB_Device_ControlRequest() event fires. This function should also be called for + * each class driver instance, using the address of the instance to operate on as the function's + * parameter. The request handler will abort if it is determined that the current request is not + * targeted at the given class driver instance, thus these methods can safely be called + * one-after-another in the event handler with no form of error checking: + * + * \code + * void EVENT_USB_Device_ControlRequest(void) + * { + * Audio_Device_ProcessControlRequest(&My_Audio_Interface); + * } + * \endcode + * + * Each class driver may also define a set of callback functions (which are prefixed by "CALLBACK_" + * in the function's name) which must also be added to the user application - refer to each + * individual class driver's documentation for mandatory callbacks. In addition, each class driver may + * also define a set of events (identifiable by their prefix of "EVENT_" in the function's name), which + * the user application may choose to implement, or ignore if not needed. + * + * The individual Device Mode Class Driver documentation contains more information on the non-standardized, + * class-specific functions which the user application can then use on the driver instances, such as data + * read and write routines. See each driver's individual documentation for more information on the + * class-specific functions. + * + * \subsection SSec_ClassDriverHost Host Mode Class Drivers + * Implementing a Host Mode Class Driver in a user application requires a number of steps to be followed. Firstly, + * the module configuration and state structure must be added to the project source. These structures are named in a + * similar manner between classes, that of USB_ClassInfo_{Class Name}_Host_t, and are used to hold the + * complete state and configuration for each class instance. Multiple class instances is where the power of the class + * drivers lie; multiple interfaces of the same class simply require more instances of the Class Driver's ClassInfo + * structure. + * + * Inside the ClassInfo structure lies two sections, a Config section, and a State section. The Config + * section contains the instance's configuration parameters, and must have all fields set by the user application + * before the class driver is used. Each Device mode Class driver typically contains a set of configuration parameters + * for the endpoint size/number of the associated logical USB interface, plus any class-specific configuration parameters. + * + * The State section of the ClassInfo structures are designed to be controlled by the Class Drivers only for + * maintaining the Class Driver instance's state, and should not normally be set by the user application. + * + * The following is an example of a properly initialized instance of the MIDI Class Driver structure: + * + * \code + * USB_ClassInfo_MIDI_Host_t My_MIDI_Interface = + * { + * .Config = + * { + * .DataINPipeNumber = 1, + * .DataINPipeDoubleBank = false, + * + * .DataOUTPipeNumber = 2, + * .DataOUTPipeDoubleBank = false, + * }, + * }; + * \endcode + * + * To initialize the Class driver instance, the driver's {Class Name}_Host_ConfigurePipes() function + * should be called in response to the host state machine entering the \ref HOST_STATE_Addressed state. This function + * will return an error code from the class driver's {Class Name}_EnumerationFailure_ErrorCodes_t enum + * to indicate if the driver successfully initialized the instance and bound it to an interface in the attached device. + * Like all the class driver functions, this function takes in the address of the specific instance you wish to initialize - + * in this manner, multiple separate instances of the same class type can be initialized. A fragment of a Class Driver + * based Host mode application may look like the following: + * + * \code + * switch (USB_HostState) + * { + * case HOST_STATE_Addressed: + * LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); + * + * uint16_t ConfigDescriptorSize; + * uint8_t ConfigDescriptorData[512]; + * + * if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData, + * sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful) + * { + * LEDs_SetAllLEDs(LEDMASK_USB_ERROR); + * USB_HostState = HOST_STATE_WaitForDeviceRemoval; + * break; + * } + * + * if (MIDI_Host_ConfigurePipes(&My_MIDI_Interface, + * ConfigDescriptorSize, ConfigDescriptorData) != MIDI_ENUMERROR_NoError) + * { + * LEDs_SetAllLEDs(LEDMASK_USB_ERROR); + * USB_HostState = HOST_STATE_WaitForDeviceRemoval; + * break; + * } + * + * // Other state handler code here + * \endcode + * + * Note that the function also required the device's configuration descriptor so that it can determine which interface + * in the device to bind to - this can be retrieved as shown in the above fragment using the + * \ref USB_Host_GetDeviceConfigDescriptor() function. If the device does not implement the interface the class driver + * is looking for, if all the matching interfaces are already bound to class driver instances or if an error occurs while + * binding to a device interface (for example, a device endpoint bank larger that the maximum supported bank size is used) + * the configuration will fail. + * + * Once initialized, it is important to maintain the class driver's state by repeatedly calling the Class Driver's + * {Class Name}_Host_USBTask() function in the main program loop. The exact implementation of this + * function varies between class drivers, and can be used for any internal class driver purpose to maintain each + * instance. Again, this function uses the address of the instance to operate on, and thus needs to be called for each + * separate instance, just like the main USB maintenance routine \ref USB_USBTask(): + * + * \code + * int main(void) + * { + * SetupHardware(); + * + * LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); + * + * for (;;) + * { + * switch (USB_HostState) + * { + * // Host state machine handling here + * } + * + * MIDI_Host_USBTask(&My_Audio_Interface); + * USB_USBTask(); + * } + * } + * \endcode + * + * Each class driver may also define a set of callback functions (which are prefixed by "CALLBACK_" + * in the function's name) which must also be added to the user application - refer to each + * individual class driver's documentation for mandatory callbacks. In addition, each class driver may + * also define a set of events (identifiable by their prefix of "EVENT_" in the function's name), which + * the user application may choose to implement, or ignore if not needed. + * + * The individual Host Mode Class Driver documentation contains more information on the non-standardized, + * class-specific functions which the user application can then use on the driver instances, such as data + * read and write routines. See each driver's individual documentation for more information on the + * class-specific functions. + */ + +#ifndef __USB_H__ +#define __USB_H__ + + /* Macros: */ + #if !defined(__DOXYGEN__) + #define __INCLUDE_FROM_USB_DRIVER + #endif + + /* Includes: */ + #include "HighLevel/USBMode.h" + + /* Preprocessor Checks: */ + #if (!defined(USB_SERIES_2_AVR) && !defined(USB_SERIES_4_AVR) && \ + !defined(USB_SERIES_6_AVR) && !defined(USB_SERIES_7_AVR)) + #error The currently selected AVR model is not supported under the USB component of the LUFA library. + #endif + + /* Includes: */ + #include "HighLevel/USBTask.h" + #include "HighLevel/Events.h" + #include "HighLevel/StdDescriptors.h" + #include "HighLevel/ConfigDescriptor.h" + + #include "LowLevel/USBController.h" + #include "LowLevel/USBInterrupt.h" + + #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__) + #include "LowLevel/Host.h" + #include "LowLevel/Pipe.h" + #include "HighLevel/HostStandardReq.h" + #include "HighLevel/PipeStream.h" + #endif + + #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__) + #include "LowLevel/Device.h" + #include "LowLevel/Endpoint.h" + #include "HighLevel/DeviceStandardReq.h" + #include "HighLevel/EndpointStream.h" + #endif + + #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__) + #include "LowLevel/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" + +#endif + -- cgit v1.2.3