Commit ecf75384 authored by Dean Camera's avatar Dean Camera
Browse files

Combined Keyboad and Mouse normal and interrupt driven host demos into unified...

Combined Keyboad and Mouse normal and interrupt driven host demos into unified Keyboard and Mouse host demos.
parent ee7bd568
......@@ -177,7 +177,6 @@ CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD)
CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY
CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)
......
......@@ -77,7 +77,7 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Get the keyboard interface's data endpoint descriptor */
if (USB_Host_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
NextInterfaceKeyboardDataEndpoint))
NextInterfaceKeyboardDataEndpoint))
{
/* Descriptor not found, error out */
return NoEndpointFound;
......@@ -91,6 +91,15 @@ uint8_t ProcessConfigurationDescriptor(void)
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
Pipe_SetInfiniteINRequests();
#if defined(INTERRUPT_DATA_PIPE)
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
/* Enable the pipe IN interrupt for the data pipe */
USB_INT_Enable(PIPE_INT_IN);
#endif
Pipe_Unfreeze();
/* Valid data found, return success */
return SuccessfulConfigRead;
......
......@@ -176,6 +176,56 @@ void UpdateStatus(uint8_t CurrentStatus)
LEDs_SetAllLEDs(LEDMask);
}
/** Reads in and processes the next report from the attached device, displaying the report
* contents on the board LEDs and via the serial port.
*/
void ReadNextReport(void)
{
USB_KeyboardReport_Data_t KeyboardReport;
/* Select the keyboard report data in pipe */
Pipe_SelectPipe(KEYBOARD_DATAPIPE);
/* Ensure pipe contains data and is ready to be read before continuing */
if (!(Pipe_ReadWriteAllowed()))
return;
/* Read in keyboard report data */
Pipe_Read_Stream_LE(&KeyboardReport, sizeof(KeyboardReport));
/* Clear the IN endpoint, ready for next data packet */
Pipe_ClearCurrentBank();
/* Indicate if the modifier byte is non-zero (special key such as shift is being pressed) */
LEDs_ChangeLEDs(LEDS_LED1, (KeyboardReport.Modifier) ? LEDS_LED1 : 0);
/* Check if a key has been pressed */
if (KeyboardReport.KeyCode)
{
/* Toggle status LED to indicate keypress */
if (LEDs_GetLEDs() & LEDS_LED2)
LEDs_TurnOffLEDs(LEDS_LED2);
else
LEDs_TurnOnLEDs(LEDS_LED2);
char PressedKey = 0;
/* Retrieve pressed key character if alphanumeric */
if ((KeyboardReport.KeyCode >= 0x04) && (KeyboardReport.KeyCode <= 0x1D))
PressedKey = (KeyboardReport.KeyCode - 0x04) + 'A';
else if ((KeyboardReport.KeyCode >= 0x1E) && (KeyboardReport.KeyCode <= 0x27))
PressedKey = (KeyboardReport.KeyCode - 0x1E) + '0';
else if (KeyboardReport.KeyCode == 0x2C)
PressedKey = ' ';
else if (KeyboardReport.KeyCode == 0x28)
PressedKey = '\n';
/* Print the pressed key character out through the serial port if valid */
if (PressedKey)
putchar(PressedKey);
}
}
/** Task to set the configuration of the attached device after it has been enumerated, and to read and process
* HID reports from the device and display the results onto the board LEDs.
*/
......@@ -261,54 +311,44 @@ TASK(USB_Keyboard_Host)
USB_HostState = HOST_STATE_Ready;
break;
#if !defined(INTERRUPT_DATA_PIPE)
case HOST_STATE_Ready:
/* Select and unfreeze keyboard data pipe */
Pipe_SelectPipe(KEYBOARD_DATAPIPE);
Pipe_Unfreeze();
/* Check if data has been received from the attached keyboard */
/* If a report has been received, read and process it */
if (Pipe_ReadWriteAllowed())
{
USB_KeyboardReport_Data_t KeyboardReport;
/* Read in keyboard report data */
Pipe_Read_Stream_LE(&KeyboardReport, sizeof(KeyboardReport));
/* Clear the IN endpoint, ready for next data packet */
Pipe_ClearCurrentBank();
/* Indicate if the modifier byte is non-zero */
LEDs_ChangeLEDs(LEDS_LED1, (KeyboardReport.Modifier) ? LEDS_LED1 : 0);
/* Check if a key has been pressed */
if (KeyboardReport.KeyCode)
{
/* Toggle status LED to indicate keypress */
if (LEDs_GetLEDs() & LEDS_LED2)
LEDs_TurnOffLEDs(LEDS_LED2);
else
LEDs_TurnOnLEDs(LEDS_LED2);
char PressedKey = 0;
/* Retrieve pressed key character if alphanumeric */
if ((KeyboardReport.KeyCode >= 0x04) && (KeyboardReport.KeyCode <= 0x1D))
PressedKey = (KeyboardReport.KeyCode - 0x04) + 'A';
else if ((KeyboardReport.KeyCode >= 0x1E) && (KeyboardReport.KeyCode <= 0x27))
PressedKey = (KeyboardReport.KeyCode - 0x1E) + '0';
else if (KeyboardReport.KeyCode == 0x2C)
PressedKey = ' ';
else if (KeyboardReport.KeyCode == 0x28)
PressedKey = '\n';
/* Print the pressed key character out through the serial port if valid */
if (PressedKey)
putchar(PressedKey);
}
}
ReadNextReport();
/* Freeze keyboard data pipe */
Pipe_Freeze();
break;
#endif
}
}
#if defined(INTERRUPT_DATA_PIPE)
/** Interrupt handler for the Endpoint/Pipe interrupt vector. This interrupt fires each time an enabled
* pipe interrupt occurs on a pipe which has had that interrupt enabled.
*/
ISR(ENDPOINT_PIPE_vect, ISR_BLOCK)
{
/* Check to see if the keyboard data pipe has caused the interrupt */
if (Pipe_HasPipeInterrupted(KEYBOARD_DATAPIPE))
{
/* Clear the pipe interrupt, and select the keyboard pipe */
Pipe_ClearPipeInterrupt(KEYBOARD_DATAPIPE);
Pipe_SelectPipe(KEYBOARD_DATAPIPE);
/* Check to see if the pipe IN interrupt has fired */
if (USB_INT_HasOccurred(PIPE_INT_IN) && USB_INT_IsEnabled(PIPE_INT_IN))
{
/* Clear interrupt flag */
USB_INT_Clear(PIPE_INT_IN);
/* Read and process the next report from the device */
ReadNextReport();
}
}
#endif
......@@ -41,6 +41,7 @@
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <LUFA/Version.h> // Library Version Information
......@@ -92,5 +93,6 @@
/* Function Prototypes: */
void UpdateStatus(uint8_t CurrentStatus);
void ReadNextReport(void);
#endif
......@@ -56,9 +56,16 @@
*
* <table>
* <tr>
* <td>
* None
* </td>
* <td><b>Define Name:</b></td>
* <td><b>Location:</b></td>
* <td><b>Description:</b></td>
* </tr>
* <tr>
* <td>INTERRUPT_DATA_ENDPOINT</td>
* <td>Makefile CDEFS</td>
* <td>When defined, this causes the demo to enable interrupts for the data pipe,
* which services reports from the device. If not defined, the data pipe is
* serviced via polling using the task scheduler.</td>
* </tr>
* </table>
*/
\ No newline at end of file
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
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.
*
* \return An error code from the KeyboardHostViaInt_GetConfigDescriptorDataCodes_t enum.
*/
uint8_t ProcessConfigurationDescriptor(void)
{
uint8_t* ConfigDescriptorData;
uint16_t ConfigDescriptorSize;
/* Get Configuration Descriptor size from the device */
if (USB_Host_GetDeviceConfigDescriptor(&ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful)
return ControlError;
/* Ensure that the Configuration Descriptor isn't too large */
if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE)
return DescriptorTooLarge;
/* Allocate enough memory for the entire config descriptor */
ConfigDescriptorData = alloca(ConfigDescriptorSize);
/* Retrieve the entire configuration descriptor into the allocated buffer */
USB_Host_GetDeviceConfigDescriptor(&ConfigDescriptorSize, ConfigDescriptorData);
/* Validate returned data - ensure first entry is a configuration header descriptor */
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return InvalidConfigDataReturned;
/* Get the keyboard interface from the configuration descriptor */
if (USB_Host_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, NextKeyboardInterface))
{
/* Descriptor not found, error out */
return NoHIDInterfaceFound;
}
/* Get the keyboard interface's data endpoint descriptor */
if (USB_Host_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
NextInterfaceKeyboardDataEndpoint))
{
/* Descriptor not found, error out */
return NoEndpointFound;
}
/* Retrieve the endpoint address from the endpoint descriptor */
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
/* Configure the keyboard data pipe */
Pipe_ConfigurePipe(KEYBOARD_DATAPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
Pipe_SetInfiniteINRequests();
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
Pipe_Unfreeze();
/* Enable the pipe IN interrupt for the data pipe */
USB_INT_Enable(PIPE_INT_IN);
/* 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 Keyboard HID Class and Protocol values.
*
* \return A value from the DSEARCH_Return_ErrorCodes_t enum
*/
DESCRIPTOR_COMPARATOR(NextKeyboardInterface)
{
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
{
/* Check the HID descriptor class and protocol, break out if correct class/protocol interface found */
if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == KEYBOARD_CLASS) &&
(DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == KEYBOARD_PROTOCOL))
{
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 IN 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
*/
DESCRIPTOR_COMPARATOR(NextInterfaceKeyboardDataEndpoint)
{
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
{
if (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Endpoint_t).EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
return Descriptor_Search_Found;
}
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
{
return Descriptor_Search_Fail;
}
return Descriptor_Search_NotFound;
}
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
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> // USB Functionality
#include <LUFA/Drivers/USB/Class/ConfigDescriptor.h> // Configuration Descriptor Parser
#include "KeyboardHostViaInt.h"
/* Macros: */
/** Interface Class value for the Human Interface Device class */
#define KEYBOARD_CLASS 0x03
/** Interface Protocol value for a Boot Protocol Keyboard compliant device */
#define KEYBOARD_PROTOCOL 0x01
/** Maximum size of a device configuration descriptor which can be processed by the host, in bytes */
#define MAX_CONFIG_DESCRIPTOR_SIZE 512
/* Enums: */
/** Enum for the possible return codes of the ProcessConfigurationDescriptor() function. */
enum KeyboardHostViaInt_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 */
NoHIDInterfaceFound = 4, /**< A compatible HID interface was not found in the device's Configuration Descriptor */
NoEndpointFound = 5, /**< A compatible HID IN endpoint was not found in the device's HID interface */
};
/* Configuration Descriptor Comparison Functions: */
DESCRIPTOR_COMPARATOR(NextKeyboardInterface);
DESCRIPTOR_COMPARATOR(NextInterfaceKeyboardDataEndpoint);
/* Function Prototypes: */
uint8_t ProcessConfigurationDescriptor(void);
#endif
This diff is collapsed.
<AVRStudio><MANAGEMENT><ProjectName>KeyboardHostViaInt</ProjectName><Created>30-Sep-2008 14:09:23</Created><LastEdit>30-Sep-2008 14:09:46</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>30-Sep-2008 14:09:23</Created><Version>4</Version><Build>4, 14, 0, 589</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile></ObjectFile><EntryFile></EntryFile><SaveFolder>C:\Users\Dean\Documents\Electronics\Projects\WORK\MyUSBWORK\Demos\KeyboardHostViaInt\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>JTAGICE mkII</CURRENT_TARGET><CURRENT_PART>AT90USB1287.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>ConfigDescriptor.c</SOURCEFILE><SOURCEFILE>KeyboardHostViaInt.c</SOURCEFILE><HEADERFILE>ConfigDescriptor.h</HEADERFILE><HEADERFILE>KeyboardHostViaInt.h</HEADERFILE><OTHERFILE>makefile</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>YES</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE>makefile</EXTERNALMAKEFILE><PART>at90usb1287</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>KeyboardHostViaInt.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS/><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR-20080512\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR-20080512\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>
/*
LUFA Library
Copyright (C) Dean Camera, 2009.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
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 KeyboardHostViaInt demo. This file contains the main tasks of
* the demo and is responsible for the initial application hardware configuration.
*/
#include "KeyboardHostViaInt.h"
/* Project Tags, for reading out using the ButtLoad project */
BUTTLOADTAG(ProjName, "LUFA KBD Host App");
BUTTLOADTAG(BuildTime, __TIME__);
BUTTLOADTAG(BuildDate, __DATE__);
BUTTLOADTAG(LUFAVersion, "LUFA V" LUFA_VERSION_STRING);
/* Scheduler Task List */
TASK_LIST
{
{ Task: USB_USBTask , TaskStatus: TASK_STOP },
{ Task: USB_Keyboard_Host , TaskStatus: TASK_STOP },
};
/** Main program entry point. This routine configures the hardware required by the application, then
* starts the scheduler to run the application tasks.
*/
int main(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
/* Hardware Initialization */
SerialStream_Init(9600, false);
LEDs_Init();
/* Indicate USB not ready */
UpdateStatus(Status_USBNotReady);
/* Initialize Scheduler so that it can be used */
Scheduler_Init();
/* Initialize USB Subsystem */
USB_Init();
/* Startup message */
puts_P(PSTR(ESC_RESET ESC_BG_WHITE ESC_INVERSE_ON ESC_ERASE_DISPLAY
"Keyboard Host Demo running.\r\n" ESC_INVERSE_OFF));
/* Scheduling - routine never returns, so put this last in the main function */
Scheduler_Start();
}
/** 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.
*/
EVENT_HANDLER(USB_DeviceAttached)
{
puts_P(PSTR("Device Attached.\r\n"));
UpdateStatus(Status_USBEnumerating);
/* Start USB management task to enumerate the device */
Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
}
/** 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.
*/
EVENT_HANDLER(USB_DeviceUnattached)
{
/* Stop keyboard and USB management task */
Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
Scheduler_SetTaskMode(USB_Keyboard_Host, TASK_STOP);
puts_P(PSTR("\r\nDevice Unattached.\r\n"));
UpdateStatus(Status_USBNotReady);
}
/** 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.
*/
EVENT_HANDLER(USB_DeviceEnumerationComplete)
{
/* Start Keyboard Host task */
Scheduler_SetTaskMode(USB_Keyboard_Host, TASK_RUN);
/* Indicate device enumeration complete */
UpdateStatus(Status_USBReady);
}
/** Event handler for the USB_HostError event. This indicates that a hardware error occurred while in host mode. */
EVENT_HANDLER(USB_HostError)
{
USB_ShutDown();
puts_P(PSTR(ESC_BG_RED "Host Mode Error\r\n"));
printf_P(PSTR(" -- Error Code %d\r\n"), ErrorCode);
UpdateStatus(Status_HardwareError);
for(;;);
}
/** Event handler for the USB_DeviceEnumerationFailed event. This indicates that a problem occured while
* enumerating an attached USB device.
*/
EVENT_HANDLER(USB_DeviceEnumerationFailed)
{
puts_P(PSTR(ESC_BG_RED "Dev Enum Error\r\n"));
printf_P(PSTR(" -- Error Code %d\r\n"), ErrorCode);
printf_P(PSTR(" -- Sub Error Code %d\r\n"), SubErrorCode);
printf_P(PSTR(" -- In State %d\r\n"), USB_HostState);
UpdateStatus(Status_EnumerationError);
}
/** Task to set the configuration of the attached device after it has been enumerated, and to enable the pipe
* interrupts so that reports can be processed as they arrive from the device.
*/
TASK(USB_Keyboard_Host)
{
uint8_t ErrorCode;
switch (USB_HostState)
{
case HOST_STATE_Addressed:
/* Standard request to set the device configuration to configuration 1 */
USB_HostRequest = (USB_Host_Request_Header_t)
{
bmRequestType: (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
bRequest: REQ_SetConfiguration,
wValue: 1,
wIndex: 0,
wLength: 0,
};
/* Send the request, display error and wait for device detatch if request fails */
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
{
puts_P(PSTR("Control Error (Set Configuration).\r\n"));
printf_P(PSTR(" -- Error Code: %d\r\n"), ErrorCode);
/* Indicate error via status LEDs */
UpdateStatus(Status_EnumerationError);