/*
* Copyright 2012 Jun Wako <wakojun@gmail.com>
- * This file is based on LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse.
+ * This file is based on:
+ * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
+ * LUFA-120219/Demos/Device/Lowlevel/GenericHID
*/
/*
#include "host.h"
#include "host_driver.h"
#include "keyboard.h"
+#include "sendchar.h"
+#include "debug.h"
+
+#include "descriptor.h"
#include "lufa.h"
static uint8_t keyboard_led_stats = 0;
-report_keyboard_t keyboard_report_sent;
-report_mouse_t mouse_report_sent;
+
+// TODO: impl Control Request GET_REPORT
+static report_keyboard_t keyboard_report_sent;
+static report_mouse_t mouse_report_sent;
/* Host driver */
static uint8_t keyboard_leds(void);
};
+static void SetupHardware(void);
+static void Console_HID_Task(void);
+
int main(void)
{
SetupHardware();
sei();
+ print_enable = true;
+ debug_enable = true;
+ debug_matrix = true;
+ debug_keyboard = true;
+ debug_mouse = true;
+
+/* TODO: can't print here
+ _delay_ms(5000);
+ USB_USBTask();
+ print("abcdefg\n");
+ USB_USBTask();
+*/
+
keyboard_init();
host_set_driver(&lufa_driver);
while (1) {
keyboard_proc();
- Keyboard_HID_Task();
+
+ Console_HID_Task();
USB_USBTask();
}
}
-/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
USB_Init();
}
+static void Console_HID_Task(void)
+{
+ /* Device must be connected and configured for the task to run */
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ // TODO: impl receivechar()/recvchar()
+ Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
+
+ /* Check to see if a packet has been sent from the host */
+ if (Endpoint_IsOUTReceived())
+ {
+ /* Check to see if the packet contains data */
+ if (Endpoint_IsReadWriteAllowed())
+ {
+ /* Create a temporary buffer to hold the read in report from the host */
+ uint8_t ConsoleData[CONSOLE_EPSIZE];
+
+ /* Read Console Report Data */
+ Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
+
+ /* Process Console Report Data */
+ //ProcessConsoleHIDReport(ConsoleData);
+ }
+
+ /* Finalize the stream transfer to send the last packet */
+ Endpoint_ClearOUT();
+ }
+
+ /* IN packet */
+ Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
+ // send IN packet
+ if (Endpoint_IsINReady())
+ Endpoint_ClearIN();
+}
+
+
+/*******************************************************************************
+ * USB Events
+ ******************************************************************************/
/** Event handler for the USB_Connect event. */
void EVENT_USB_Device_Connect(void)
{
/* Setup Keyboard HID Report Endpoints */
ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
- HID_EPSIZE, ENDPOINT_BANK_SINGLE);
- ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
- HID_EPSIZE, ENDPOINT_BANK_SINGLE);
+ KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
/* Setup Mouse HID Report Endpoint */
ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
- HID_EPSIZE, ENDPOINT_BANK_SINGLE);
+ MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
+
+ /* Setup Console HID Report Endpoints */
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
+ CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
+
+ /* Setup Extra HID Report Endpoint */
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(EXTRA_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ EXTRA_EPSIZE, ENDPOINT_BANK_SINGLE);
}
+/*
+Appendix G: HID Request Support Requirements
+
+The following table enumerates the requests that need to be supported by various types of HID class devices.
+
+Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
+------------------------------------------------------------------------------------------
+Boot Mouse Required Optional Optional Optional Required Required
+Non-Boot Mouse Required Optional Optional Optional Optional Optional
+Boot Keyboard Required Optional Required Required Required Required
+Non-Boot Keybrd Required Optional Required Required Optional Optional
+Other Device Required Optional Optional Optional Optional Optional
+*/
/** Event handler for the USB_ControlRequest event.
* This is fired before passing along unhandled control requests to the library for processing internally.
*/
void EVENT_USB_Device_ControlRequest(void)
{
- uint8_t* ReportData;
- uint8_t ReportSize;
+ uint8_t* ReportData = NULL;
+ uint8_t ReportSize = 0;
/* Handle HID Class specific requests */
switch (USB_ControlRequest.bRequest)
{
Endpoint_ClearSETUP();
- /* Determine if it is the mouse or the keyboard data that is being requested */
- if (!(USB_ControlRequest.wIndex))
- {
+ // Interface
+ switch (USB_ControlRequest.wIndex) {
+ case KEYBOARD_INTERFACE:
+ // TODO: test/check
ReportData = (uint8_t*)&keyboard_report_sent;
ReportSize = sizeof(keyboard_report_sent);
- }
- else
- {
+ break;
+ case MOUSE_INTERFACE:
+ // TODO: test/check
ReportData = (uint8_t*)&mouse_report_sent;
ReportSize = sizeof(mouse_report_sent);
+ break;
+ case CONSOLE_INTERFACE:
+ break;
+ case EXTRA_INTERFACE:
+ break;
}
/* Write the report data to the control endpoint */
return;
}
- /* Read in the LED report from the host */
- keyboard_led_stats = Endpoint_Read_8();
+ // Interface
+ switch (USB_ControlRequest.wIndex) {
+ case KEYBOARD_INTERFACE:
+ // TODO: test/check
+ /* Read in the LED report from the host */
+ keyboard_led_stats = Endpoint_Read_8();
+ break;
+ case MOUSE_INTERFACE:
+ break;
+ case CONSOLE_INTERFACE:
+ break;
+ case EXTRA_INTERFACE:
+ break;
+ }
Endpoint_ClearOUT();
Endpoint_ClearStatusStage();
}
}
-/** Keyboard task.
- * This processes host LED status reports sent to the device via the keyboard OUT reporting endpoint.
- */
-void Keyboard_HID_Task(void)
-{
- /* Select the Keyboard LED Report Endpoint */
- Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);
-
- /* Check if Keyboard LED Endpoint Ready for Read/Write */
- if (Endpoint_IsReadWriteAllowed())
- {
- /* Read in the LED report from the host */
- keyboard_led_stats = Endpoint_Read_8();
-
- /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
- Endpoint_ClearOUT();
- }
-}
-
-
/*******************************************************************************
* Host driver
******************************************************************************/
mouse_report_sent = *report;
}
+typedef struct {
+ uint8_t report_id;
+ uint16_t usage;
+} __attribute__ ((packed)) report_extra_t;
+
static void send_system(uint16_t data)
{
+ Endpoint_SelectEndpoint(EXTRA_IN_EPNUM);
+ if (Endpoint_IsReadWriteAllowed()) {
+ report_extra_t r = {
+ .report_id = REPORT_ID_SYSTEM,
+ .usage = data
+ };
+ Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
+ Endpoint_ClearIN();
+ }
}
static void send_consumer(uint16_t data)
{
+ Endpoint_SelectEndpoint(EXTRA_IN_EPNUM);
+ if (Endpoint_IsReadWriteAllowed()) {
+ report_extra_t r = {
+ .report_id = REPORT_ID_CONSUMER,
+ .usage = data
+ };
+ Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
+ Endpoint_ClearIN();
+ }
+}
+
+
+/*******************************************************************************
+ * sendchar
+ ******************************************************************************/
+int8_t sendchar(uint8_t c)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return -1;
+
+ Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
+
+ uint8_t timeout = 10;
+ uint16_t prevFN = USB_Device_GetFrameNumber();
+ while (!Endpoint_IsINReady()) {
+ switch (USB_DeviceState) {
+ case DEVICE_STATE_Unattached:
+ case DEVICE_STATE_Suspended:
+ return -1;
+ }
+ if (Endpoint_IsStalled())
+ return -1;
+ if (prevFN != USB_Device_GetFrameNumber()) {
+ if (!(timeout--))
+ return -1;
+ prevFN = USB_Device_GetFrameNumber();
+ }
+ }
+
+ Endpoint_Write_8(c);
+
+ // send when packet is full
+ if (!Endpoint_IsReadWriteAllowed())
+ Endpoint_ClearIN();
+
+ return 0;
}