diff options
Diffstat (limited to 'Demos/Host/LowLevel/MouseHostWithParser')
11 files changed, 3473 insertions, 0 deletions
diff --git a/Demos/Host/LowLevel/MouseHostWithParser/Config/LUFAConfig.h b/Demos/Host/LowLevel/MouseHostWithParser/Config/LUFAConfig.h new file mode 100644 index 0000000000..197122fce1 --- /dev/null +++ b/Demos/Host/LowLevel/MouseHostWithParser/Config/LUFAConfig.h @@ -0,0 +1,93 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2017. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief LUFA Library Configuration Header File + * + * This header file is used to configure LUFA's compile time options, + * as an alternative to the compile time constants supplied through + * a makefile. + * + * For information on what each token does, refer to the LUFA + * manual section "Summary of Compile Tokens". + */ + +#ifndef _LUFA_CONFIG_H_ +#define _LUFA_CONFIG_H_ + + #if (ARCH == ARCH_AVR8) + + /* Non-USB Related Configuration Tokens: */ +// #define DISABLE_TERMINAL_CODES + + /* USB Class Driver Related Tokens: */ +// #define HID_HOST_BOOT_PROTOCOL_ONLY +// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here} +// #define HID_USAGE_STACK_DEPTH {Insert Value Here} +// #define HID_MAX_COLLECTIONS {Insert Value Here} +// #define HID_MAX_REPORTITEMS {Insert Value Here} +// #define HID_MAX_REPORT_IDS {Insert Value Here} +// #define NO_CLASS_DRIVER_AUTOFLUSH + + /* General USB Driver Related Tokens: */ +// #define ORDERED_EP_CONFIG + #define USE_STATIC_OPTIONS (USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL) +// #define USB_DEVICE_ONLY + #define USB_HOST_ONLY +// #define USB_STREAM_TIMEOUT_MS {Insert Value Here} +// #define NO_LIMITED_CONTROLLER_CONNECT +// #define NO_SOF_EVENTS + + /* USB Device Mode Driver Related Tokens: */ +// #define USE_RAM_DESCRIPTORS +// #define USE_FLASH_DESCRIPTORS +// #define USE_EEPROM_DESCRIPTORS +// #define NO_INTERNAL_SERIAL +// #define FIXED_CONTROL_ENDPOINT_SIZE {Insert Value Here} +// #define DEVICE_STATE_AS_GPIOR {Insert Value Here} +// #define FIXED_NUM_CONFIGURATIONS {Insert Value Here} +// #define CONTROL_ONLY_DEVICE +// #define INTERRUPT_CONTROL_ENDPOINT +// #define NO_DEVICE_REMOTE_WAKEUP +// #define NO_DEVICE_SELF_POWER + + /* USB Host Mode Driver Related Tokens: */ +// #define HOST_STATE_AS_GPIOR {Insert Value Here} +// #define USB_HOST_TIMEOUT_MS {Insert Value Here} +// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here} +// #define NO_AUTO_VBUS_MANAGEMENT +// #define INVERTED_VBUS_ENABLE_LINE + + #else + + #error Unsupported architecture for this LUFA configuration file. + + #endif +#endif diff --git a/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.c b/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.c new file mode 100644 index 0000000000..c2c6301e09 --- /dev/null +++ b/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.c @@ -0,0 +1,187 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2017. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * USB Device Configuration Descriptor processing routines, to determine the correct pipe configurations + * needed to communication with an attached USB device. Descriptors are special computer-readable structures + * which the host requests upon device enumeration, to determine the device's capabilities and functions. + */ + +#include "ConfigDescriptor.h" + +/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This + * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate + * with compatible devices. + * + * This routine searches for a HID interface descriptor containing at least one Interrupt type IN endpoint and HID descriptor. + * + * \return An error code from the \ref MouseHostWithParser_GetConfigDescriptorDataCodes_t enum. + */ +uint8_t ProcessConfigurationDescriptor(void) +{ + uint8_t ConfigDescriptorData[512]; + void* CurrConfigLocation = ConfigDescriptorData; + uint16_t CurrConfigBytesRem; + + USB_Descriptor_Interface_t* HIDInterface = NULL; + USB_HID_Descriptor_HID_t* HIDDescriptor = NULL; + USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; + + /* Retrieve the entire configuration descriptor into the allocated buffer */ + switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) + { + case HOST_GETCONFIG_Successful: + break; + case HOST_GETCONFIG_InvalidData: + return InvalidConfigDataReturned; + case HOST_GETCONFIG_BuffOverflow: + return DescriptorTooLarge; + default: + return ControlError; + } + + while (!(DataINEndpoint)) + { + /* See if we've found a likely compatible interface, and if there is an endpoint within that interface */ + if (!(HIDInterface) || + USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, + DComp_NextMouseInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) + { + /* Get the next HID interface from the configuration descriptor */ + if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, + DComp_NextMouseInterface) != DESCRIPTOR_SEARCH_COMP_Found) + { + /* Descriptor not found, error out */ + return NoCompatibleInterfaceFound; + } + + /* Save the interface in case we need to refer back to it later */ + HIDInterface = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t); + + /* Get the HID descriptor from the configuration descriptor */ + if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, + DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found) + { + /* Descriptor not found, error out */ + return NoCompatibleInterfaceFound; + } + + /* Save the HID descriptor for later use */ + HIDDescriptor = DESCRIPTOR_PCAST(CurrConfigLocation, USB_HID_Descriptor_HID_t); + + /* Skip the remainder of the loop as we have not found an endpoint yet */ + continue; + } + + /* Retrieve the endpoint address from the endpoint descriptor */ + USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); + + /* If the endpoint is a IN type endpoint */ + if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) + DataINEndpoint = EndpointData; + } + + /* Configure the HID data IN pipe */ + Pipe_ConfigurePipe(MOUSE_DATA_IN_PIPE, EP_TYPE_INTERRUPT, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, 1); + Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS); + + /* Get the HID report size from the HID report descriptor */ + HIDReportSize = HIDDescriptor->HIDReportLength; + + /* Valid data found, return success */ + return SuccessfulConfigRead; +} + +/** Descriptor comparator function. This comparator function is can be called while processing an attached USB device's + * configuration descriptor, to search for a specific sub descriptor. It can also be used to abort the configuration + * descriptor processing if an incompatible descriptor configuration is found. + * + * This comparator searches for the next Interface descriptor of the correct Mouse HID Class and Protocol values. + * + * \return A value from the DSEARCH_Return_ErrorCodes_t enum + */ +uint8_t DComp_NextMouseInterface(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); + + /* Check the HID descriptor class, break out if correct class interface found */ + if (Interface->Class == HID_CSCP_HIDClass) + { + return DESCRIPTOR_SEARCH_Found; + } + } + + return DESCRIPTOR_SEARCH_NotFound; +} + +/** Descriptor comparator function. This comparator function is can be called while processing an attached USB device's + * configuration descriptor, to search for a specific sub descriptor. It can also be used to abort the configuration + * descriptor processing if an incompatible descriptor configuration is found. + * + * This comparator searches for the next Endpoint descriptor inside the current interface descriptor, aborting the + * search if another interface descriptor is found before the required endpoint. + * + * \return A value from the DSEARCH_Return_ErrorCodes_t enum + */ +uint8_t DComp_NextMouseInterfaceDataEndpoint(void* CurrentDescriptor) +{ + USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t); + + if (Header->Type == DTYPE_Endpoint) + return DESCRIPTOR_SEARCH_Found; + else if (Header->Type == DTYPE_Interface) + return DESCRIPTOR_SEARCH_Fail; + else + return DESCRIPTOR_SEARCH_NotFound; +} + +/** Descriptor comparator function. This comparator function is can be called while processing an attached USB device's + * configuration descriptor, to search for a specific sub descriptor. It can also be used to abort the configuration + * descriptor processing if an incompatible descriptor configuration is found. + * + * This comparator searches for the next HID descriptor within the current HID interface descriptor. + * + * \return A value from the DSEARCH_Return_ErrorCodes_t enum + */ +uint8_t DComp_NextHID(void* CurrentDescriptor) +{ + USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t); + + if (Header->Type == HID_DTYPE_HID) + return DESCRIPTOR_SEARCH_Found; + else + return DESCRIPTOR_SEARCH_NotFound; +} + diff --git a/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.h b/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.h new file mode 100644 index 0000000000..c43e176265 --- /dev/null +++ b/Demos/Host/LowLevel/MouseHostWithParser/ConfigDescriptor.h @@ -0,0 +1,67 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2017. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for ConfigDescriptor.c. + */ + +#ifndef _CONFIGDESCRIPTOR_H_ +#define _CONFIGDESCRIPTOR_H_ + + /* Includes: */ + #include <LUFA/Drivers/USB/USB.h> + + #include "HIDReport.h" + + /* Macros: */ + /** Pipe address for the mouse report data IN pipe. */ + #define MOUSE_DATA_IN_PIPE (ENDPOINT_DIR_IN | 1) + + /* Enums: */ + /** Enum for the possible return codes of the \ref ProcessConfigurationDescriptor() function. */ + enum MouseHostWithParser_GetConfigDescriptorDataCodes_t + { + SuccessfulConfigRead = 0, /**< Configuration Descriptor was processed successfully */ + ControlError = 1, /**< A control request to the device failed to complete successfully */ + DescriptorTooLarge = 2, /**< The device's Configuration Descriptor is too large to process */ + InvalidConfigDataReturned = 3, /**< The device returned an invalid Configuration Descriptor */ + NoCompatibleInterfaceFound = 4, /**< A compatible interface with the required endpoints was not found */ + }; + + /* Function Prototypes: */ + uint8_t ProcessConfigurationDescriptor(void); + + uint8_t DComp_NextMouseInterface(void* CurrentDescriptor); + uint8_t DComp_NextMouseInterfaceDataEndpoint(void* CurrentDescriptor); + uint8_t DComp_NextHID(void* CurrentDescriptor); + +#endif + diff --git a/Demos/Host/LowLevel/MouseHostWithParser/HIDReport.c b/Demos/Host/LowLevel/MouseHostWithParser/HIDReport.c new file mode 100644 index 0000000000..3ec766fbdd --- /dev/null +++ b/Demos/Host/LowLevel/MouseHostWithParser/HIDReport.c @@ -0,0 +1,111 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2017. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include "HIDReport.h" + +/** Size in bytes of the attached device's HID report descriptor */ +uint16_t HIDReportSize; + +/** Processed HID report descriptor items structure, containing information on each HID report element */ +HID_ReportInfo_t HIDReportInfo; + + +/** Function to read in the HID report descriptor from the attached device, and process it into easy-to-read + * structures via the HID parser routines in the LUFA library. + * + * \return A value from the \ref MouseHostWithParser_GetHIDReportDataCodes_t enum + */ +uint8_t GetHIDReportData(void) +{ + /* Create a buffer big enough to hold the entire returned HID report */ + uint8_t HIDReportData[HIDReportSize]; + + USB_ControlRequest = (USB_Request_Header_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE), + .bRequest = REQ_GetDescriptor, + .wValue = (HID_DTYPE_Report << 8), + .wIndex = 0, + .wLength = HIDReportSize, + }; + + /* Select the control pipe for the request transfer */ + Pipe_SelectPipe(PIPE_CONTROLPIPE); + + /* Send control request to retrieve the HID report from the attached device */ + if (USB_Host_SendControlRequest(HIDReportData) != HOST_SENDCONTROL_Successful) + return ParseControlError; + + /* Send the HID report to the parser for processing */ + if (USB_ProcessHIDReport(HIDReportData, HIDReportSize, &HIDReportInfo) != HID_PARSE_Successful) + return ParseError; + + return ParseSuccessful; +} + +/** Callback for the HID Report Parser. This function is called each time the HID report parser is about to store + * an IN, OUT or FEATURE item into the HIDReportInfo structure. To save on RAM, we are able to filter out items + * we aren't interested in (preventing us from being able to extract them later on, but saving on the RAM they would + * have occupied). + * + * \param[in] CurrentItem Pointer to the item the HID report parser is currently working with + * + * \return Boolean \c true if the item should be stored into the HID report structure, \c false if it should be discarded + */ +bool CALLBACK_HIDParser_FilterHIDReportItem(HID_ReportItem_t* const CurrentItem) +{ + bool IsMouse = false; + + /* Iterate through the item's collection path, until either the root collection node or a collection with the + * Mouse Usage is found - this prevents Joysticks, which use identical descriptors except for the Joystick usage + * parent node, from being erroneously treated as a mouse + */ + for (HID_CollectionPath_t* CurrPath = CurrentItem->CollectionPath; CurrPath != NULL; CurrPath = CurrPath->Parent) + { + if ((CurrPath->Usage.Page == USAGE_PAGE_GENERIC_DCTRL) && + (CurrPath->Usage.Usage == USAGE_MOUSE)) + { + IsMouse = true; + break; + } + } + + /* If a collection with the mouse usage was not found, indicate that we are not interested in this item */ + if (!IsMouse) + return false; + + /* Check the attributes of the current mouse item - see if we are interested in it or not; + * only store BUTTON and GENERIC_DESKTOP_CONTROL items into the Processed HID Report + * structure to save RAM and ignore the rest + */ + return ((CurrentItem->Attributes.Usage.Page == USAGE_PAGE_BUTTON) || + (CurrentItem->Attributes.Usage.Page == USAGE_PAGE_GENERIC_DCTRL)); +} + diff --git a/Demos/Host/LowLevel/MouseHostWithParser/HIDReport.h b/Demos/Host/LowLevel/MouseHostWithParser/HIDReport.h new file mode 100644 index 0000000000..1296f57a71 --- /dev/null +++ b/Demos/Host/LowLevel/MouseHostWithParser/HIDReport.h @@ -0,0 +1,82 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2017. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for HIDReport.c. + */ + +#ifndef _HID_REPORT_H_ +#define _HID_REPORT_H_ + + /* Includes: */ + #include <LUFA/Drivers/USB/USB.h> + + #include "MouseHostWithParser.h" + + /* Macros: */ + /** HID Report Descriptor Usage for a Mouse. */ + #define USAGE_MOUSE 0x02 + + /** HID Report Descriptor Usage Page value for a toggle button. */ + #define USAGE_PAGE_BUTTON 0x09 + + /** HID Report Descriptor Usage Page value for a Generic Desktop Control. */ + #define USAGE_PAGE_GENERIC_DCTRL 0x01 + + /** HID Report Descriptor Usage value for a X axis movement. */ + #define USAGE_X 0x30 + + /** HID Report Descriptor Usage value for a Y axis movement. */ + #define USAGE_Y 0x31 + + /** HID Report Descriptor Usage value for a Scroll Wheel movement. */ + #define USAGE_SCROLL_WHEEL 0x38 + + /* Enums: */ + /** Enum for the possible return codes of the \ref GetHIDReportData() function. */ + enum MouseHostWithParser_GetHIDReportDataCodes_t + { + ParseSuccessful = 0, /**< HID report descriptor parsed successfully */ + ParseError = 1, /**< Failed to fully process the HID report descriptor */ + ParseControlError = 2, /**< Control error occurred while trying to read the device HID descriptor */ + }; + + /* External Variables: */ + extern uint16_t HIDReportSize; + extern HID_ReportInfo_t HIDReportInfo; + + /* Function Prototypes: */ + uint8_t GetHIDReportData(void); + + bool CALLBACK_HIDParser_FilterHIDReportItem(HID_ReportItem_t* const CurrentItem); + +#endif + diff --git a/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c b/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c new file mode 100644 index 0000000000..4ad4d580e7 --- /dev/null +++ b/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.c @@ -0,0 +1,289 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2017. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Main source file for the MouseHostWithParser demo. This file contains the main tasks of + * the demo and is responsible for the initial application hardware configuration. + */ + +#include "MouseHostWithParser.h" + +/** Main program entry point. This routine configures the hardware required by the application, then + * enters a loop to run the application tasks in sequence. + */ +int main(void) +{ + SetupHardware(); + + puts_P(PSTR(ESC_FG_CYAN "Mouse HID Parser Host Demo running.\r\n" ESC_FG_WHITE)); + + LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); + GlobalInterruptEnable(); + + for (;;) + { + MouseHost_Task(); + + USB_USBTask(); + } +} + +/** Configures the board hardware and chip peripherals for the demo's functionality. */ +void SetupHardware(void) +{ +#if (ARCH == ARCH_AVR8) + /* Disable watchdog if enabled by bootloader/fuses */ + MCUSR &= ~(1 << WDRF); + wdt_disable(); + + /* Disable clock division */ + clock_prescale_set(clock_div_1); +#endif + + /* Hardware Initialization */ + Serial_Init(9600, false); + LEDs_Init(); + USB_Init(); + + /* Create a stdio stream for the serial port for stdin and stdout */ + Serial_CreateStream(NULL); +} + +/** Event handler for the USB_DeviceAttached event. This indicates that a device has been attached to the host, and + * starts the library USB task to begin the enumeration and USB management process. + */ +void EVENT_USB_Host_DeviceAttached(void) +{ + puts_P(PSTR(ESC_FG_GREEN "Device Attached.\r\n" ESC_FG_WHITE)); + LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); +} + +/** Event handler for the USB_DeviceUnattached event. This indicates that a device has been removed from the host, and + * stops the library USB task management process. + */ +void EVENT_USB_Host_DeviceUnattached(void) +{ + puts_P(PSTR(ESC_FG_GREEN "Device Unattached.\r\n" ESC_FG_WHITE)); + LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); +} + +/** Event handler for the USB_DeviceEnumerationComplete event. This indicates that a device has been successfully + * enumerated by the host and is now ready to be used by the application. + */ +void EVENT_USB_Host_DeviceEnumerationComplete(void) +{ + puts_P(PSTR("Getting Config Data.\r\n")); + + uint8_t ErrorCode; + + /* Get and process the configuration descriptor data */ + if ((ErrorCode = ProcessConfigurationDescriptor()) != SuccessfulConfigRead) + { + if (ErrorCode == ControlError) + puts_P(PSTR(ESC_FG_RED "Control Error (Get Configuration).\r\n")); + else + puts_P(PSTR(ESC_FG_RED "Invalid Device.\r\n")); + + printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); + + LEDs_SetAllLEDs(LEDMASK_USB_ERROR); + return; + } + + /* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */ + if ((ErrorCode = USB_Host_SetDeviceConfiguration(1)) != HOST_SENDCONTROL_Successful) + { + printf_P(PSTR(ESC_FG_RED "Control Error (Set Configuration).\r\n" + " -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); + + LEDs_SetAllLEDs(LEDMASK_USB_ERROR); + return; + } + + printf_P(PSTR("Processing HID Report (Size %d Bytes).\r\n"), HIDReportSize); + + /* Get and process the device's first HID report descriptor */ + if ((ErrorCode = GetHIDReportData()) != ParseSuccessful) + { + puts_P(PSTR(ESC_FG_RED "Report Parse Error.\r\n")); + + if (!(HIDReportInfo.TotalReportItems)) + puts_P(PSTR("Not a valid Mouse." ESC_FG_WHITE)); + else + printf_P(PSTR(" -- Error Code: %d\r\n" ESC_FG_WHITE), ErrorCode); + + LEDs_SetAllLEDs(LEDMASK_USB_ERROR); + USB_Host_SetDeviceConfiguration(0); + return; + } + + puts_P(PSTR("Mouse Enumerated.\r\n")); + LEDs_SetAllLEDs(LEDMASK_USB_READY); +} + +/** Event handler for the USB_HostError event. This indicates that a hardware error occurred while in host mode. */ +void EVENT_USB_Host_HostError(const uint8_t ErrorCode) +{ + USB_Disable(); + + printf_P(PSTR(ESC_FG_RED "Host Mode Error\r\n" + " -- Error Code %d\r\n" ESC_FG_WHITE), ErrorCode); + + LEDs_SetAllLEDs(LEDMASK_USB_ERROR); + for(;;); +} + +/** Event handler for the USB_DeviceEnumerationFailed event. This indicates that a problem occurred while + * enumerating an attached USB device. + */ +void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode, + const uint8_t SubErrorCode) +{ + printf_P(PSTR(ESC_FG_RED "Dev Enum Error\r\n" + " -- Error Code %d\r\n" + " -- Sub Error Code %d\r\n" + " -- In State %d\r\n" ESC_FG_WHITE), ErrorCode, SubErrorCode, USB_HostState); + + LEDs_SetAllLEDs(LEDMASK_USB_ERROR); +} + +/** Task to read and process the HID report descriptor and HID reports from the device and display the + * results onto the board LEDs. + */ +void MouseHost_Task(void) +{ + if (USB_HostState != HOST_STATE_Configured) + return; + + /* Select and unfreeze mouse data pipe */ + Pipe_SelectPipe(MOUSE_DATA_IN_PIPE); + Pipe_Unfreeze(); + + /* Check to see if a packet has been received */ + if (Pipe_IsINReceived()) + { + /* Check if data has been received from the attached mouse */ + if (Pipe_IsReadWriteAllowed()) + { + /* Create buffer big enough for the report */ + uint8_t MouseReport[Pipe_BytesInPipe()]; + + /* Load in the mouse report */ + Pipe_Read_Stream_LE(MouseReport, Pipe_BytesInPipe(), NULL); + + /* Process the read in mouse report from the device */ + ProcessMouseReport(MouseReport); + } + + /* Clear the IN endpoint, ready for next data packet */ + Pipe_ClearIN(); + } + + /* Freeze mouse data pipe */ + Pipe_Freeze(); +} + +/** Processes a read HID report from an attached mouse, extracting out elements via the HID parser results + * as required and displays movement and button presses on the board LEDs. + * + * \param[in] MouseReport Pointer to a HID report from an attached mouse device + */ +void ProcessMouseReport(uint8_t* MouseReport) +{ + uint8_t LEDMask = LEDS_NO_LEDS; + + /* Check each HID report item in turn, looking for mouse X/Y/button reports */ + for (uint8_t ReportNumber = 0; ReportNumber < HIDReportInfo.TotalReportItems; ReportNumber++) + { + /* Create a temporary item pointer to the next report item */ + HID_ReportItem_t* ReportItem = &HIDReportInfo.ReportItems[ReportNumber]; + + bool FoundData; + + if ((ReportItem->Attributes.Usage.Page == USAGE_PAGE_BUTTON) && + (ReportItem->ItemType == HID_REPORT_ITEM_In)) + { + /* Get the mouse button value */ + FoundData = USB_GetHIDReportItemInfo(MouseReport, ReportItem); + + /* For multi-report devices - if the requested data was not in the issued report, continue */ + if (!(FoundData)) + continue; + + /* If button is pressed, all LEDs are turned on */ + if (ReportItem->Value) + LEDMask = LEDS_ALL_LEDS; + } + else if ((ReportItem->Attributes.Usage.Page == USAGE_PAGE_GENERIC_DCTRL) && + (ReportItem->Attributes.Usage.Usage == USAGE_SCROLL_WHEEL) && + (ReportItem->ItemType == HID_REPORT_ITEM_In)) + { + /* Get the mouse wheel value if it is contained within the current + * report, if not, skip to the next item in the parser list + */ + if (!(USB_GetHIDReportItemInfo(MouseReport, ReportItem))) + continue; + + int16_t WheelDelta = HID_ALIGN_DATA(ReportItem, int16_t); + + if (WheelDelta) + LEDMask = (LEDS_LED1 | LEDS_LED2 | ((WheelDelta > 0) ? LEDS_LED3 : LEDS_LED4)); + } + else if ((ReportItem->Attributes.Usage.Page == USAGE_PAGE_GENERIC_DCTRL) && + ((ReportItem->Attributes.Usage.Usage == USAGE_X) || + (ReportItem->Attributes.Usage.Usage == USAGE_Y)) && + (ReportItem->ItemType == HID_REPORT_ITEM_In)) + { + /* Get the mouse relative position value */ + FoundData = USB_GetHIDReportItemInfo(MouseReport, ReportItem); + + /* For multi-report devices - if the requested data was not in the issued report, continue */ + if (!(FoundData)) + continue; + + int16_t DeltaMovement = HID_ALIGN_DATA(ReportItem, int16_t); + + /* Check to see if a (non-zero) delta movement has been indicated */ + if (DeltaMovement) + { + /* Determine if the report is for the X or Y delta movement, light LEDs as appropriate */ + if (ReportItem->Attributes.Usage.Usage == USAGE_X) + LEDMask |= ((DeltaMovement > 0) ? LEDS_LED1 : LEDS_LED2); + else + LEDMask |= ((DeltaMovement > 0) ? LEDS_LED3 : LEDS_LED4); + } + } + } + + /* Display the button information on the board LEDs */ + LEDs_SetAllLEDs(LEDMask); +} + diff --git a/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.h b/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.h new file mode 100644 index 0000000000..8812cacbea --- /dev/null +++ b/Demos/Host/LowLevel/MouseHostWithParser/MouseHostWithParser.h @@ -0,0 +1,83 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2017. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for MouseHostWithParser.c. + */ + +#ifndef _MOUSE_HOST_H_ +#define _MOUSE_HOST_H_ + + /* Includes: */ + #include <avr/io.h> + #include <avr/wdt.h> + #include <avr/pgmspace.h> + #include <avr/power.h> + #include <avr/interrupt.h> + #include <stdio.h> + + #include <LUFA/Drivers/Misc/TerminalCodes.h> + #include <LUFA/Drivers/Peripheral/Serial.h> + #include < |