From cc68adeb5744cba9e8650bab04ff0f0a4033db9f Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 28 Jun 2012 23:05:21 +0900 Subject: Add protocol/lufa. LUFA supported now. --- protocol/lufa/lufa.c | 386 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 protocol/lufa/lufa.c (limited to 'protocol/lufa/lufa.c') diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c new file mode 100644 index 0000000000..09da96b2e5 --- /dev/null +++ b/protocol/lufa/lufa.c @@ -0,0 +1,386 @@ +/* + * Copyright 2012 Jun Wako + * This file is based on: + * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse + * LUFA-120219/Demos/Device/Lowlevel/GenericHID + */ + +/* + LUFA Library + Copyright (C) Dean Camera, 2012. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) + Copyright 2010 Denver Gingerich (denver [at] ossguy [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 "report.h" +#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; + +// 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 send_keyboard(report_keyboard_t *report); +static void send_mouse(report_mouse_t *report); +static void send_system(uint16_t data); +static void send_consumer(uint16_t data); +static host_driver_t lufa_driver = { + keyboard_leds, + send_keyboard, + send_mouse, + send_system, + send_consumer +}; + + +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(); + + Console_HID_Task(); + USB_USBTask(); + } +} + +void SetupHardware(void) +{ + /* Disable watchdog if enabled by bootloader/fuses */ + MCUSR &= ~(1 << WDRF); + wdt_disable(); + + /* Disable clock division */ + clock_prescale_set(clock_div_1); + + 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) +{ +} + +/** Event handler for the USB_Disconnect event. */ +void EVENT_USB_Device_Disconnect(void) +{ +} + +/** Event handler for the USB_ConfigurationChanged event. + * This is fired when the host sets the current configuration of the USB device after enumeration. + */ +void EVENT_USB_Device_ConfigurationChanged(void) +{ + bool ConfigSuccess = true; + + /* Setup Keyboard HID Report Endpoints */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, + KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); + + /* Setup Mouse HID Report Endpoint */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, + 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 = NULL; + uint8_t ReportSize = 0; + + /* Handle HID Class specific requests */ + switch (USB_ControlRequest.bRequest) + { + case HID_REQ_GetReport: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + + // Interface + switch (USB_ControlRequest.wIndex) { + case KEYBOARD_INTERFACE: + // TODO: test/check + ReportData = (uint8_t*)&keyboard_report_sent; + ReportSize = sizeof(keyboard_report_sent); + 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 */ + Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); + Endpoint_ClearOUT(); + } + + break; + case HID_REQ_SetReport: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + + /* Wait until the LED report has been sent by the host */ + while (!(Endpoint_IsOUTReceived())) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + + // 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(); + } + + break; + } +} + +/******************************************************************************* + * Host driver + ******************************************************************************/ +static uint8_t keyboard_leds(void) +{ + return keyboard_led_stats; +} + +static void send_keyboard(report_keyboard_t *report) +{ + // TODO: handle NKRO report + /* Select the Keyboard Report Endpoint */ + Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); + + /* Check if Keyboard Endpoint Ready for Read/Write */ + if (Endpoint_IsReadWriteAllowed()) + { + /* Write Keyboard Report Data */ + Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearIN(); + } + keyboard_report_sent = *report; +} + +static void send_mouse(report_mouse_t *report) +{ + /* Select the Mouse Report Endpoint */ + Endpoint_SelectEndpoint(MOUSE_IN_EPNUM); + + /* Check if Mouse Endpoint Ready for Read/Write */ + if (Endpoint_IsReadWriteAllowed()) + { + /* Write Mouse Report Data */ + Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearIN(); + } + 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; +} -- cgit v1.2.3 From f2ebac101d367ee091f54b8d43b39a4d74f3b90e Mon Sep 17 00:00:00 2001 From: tmk Date: Fri, 29 Jun 2012 03:33:59 +0900 Subject: Add conditional compile for MOUSE_ENABLE and EXTRAKEY_ENABLE. --- protocol/lufa/lufa.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'protocol/lufa/lufa.c') diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index 09da96b2e5..f485e24bf0 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c @@ -50,7 +50,9 @@ static uint8_t keyboard_led_stats = 0; // TODO: impl Control Request GET_REPORT static report_keyboard_t keyboard_report_sent; +#ifdef MOUSE_ENABLE static report_mouse_t mouse_report_sent; +#endif /* Host driver */ static uint8_t keyboard_leds(void); @@ -171,19 +173,23 @@ void EVENT_USB_Device_ConfigurationChanged(void) ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); +#ifdef MOUSE_ENABLE /* Setup Mouse HID Report Endpoint */ ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); +#endif + +#ifdef EXTRAKEY_ENABLE + /* Setup Extra HID Report Endpoint */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(EXTRA_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, + EXTRA_EPSIZE, ENDPOINT_BANK_SINGLE); +#endif /* 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); } /* @@ -222,15 +228,19 @@ void EVENT_USB_Device_ControlRequest(void) ReportData = (uint8_t*)&keyboard_report_sent; ReportSize = sizeof(keyboard_report_sent); break; +#ifdef MOUSE_ENABLE case MOUSE_INTERFACE: // TODO: test/check ReportData = (uint8_t*)&mouse_report_sent; ReportSize = sizeof(mouse_report_sent); break; - case CONSOLE_INTERFACE: - break; +#endif +#ifdef EXTRAKEY_ENABLE case EXTRA_INTERFACE: break; +#endif + case CONSOLE_INTERFACE: + break; } /* Write the report data to the control endpoint */ @@ -258,12 +268,16 @@ void EVENT_USB_Device_ControlRequest(void) /* Read in the LED report from the host */ keyboard_led_stats = Endpoint_Read_8(); break; +#ifdef MOUSE_ENABLE case MOUSE_INTERFACE: break; - case CONSOLE_INTERFACE: - break; +#endif +#ifdef EXTRAKEY_ENABLE case EXTRA_INTERFACE: break; +#endif + case CONSOLE_INTERFACE: + break; } Endpoint_ClearOUT(); @@ -302,6 +316,7 @@ static void send_keyboard(report_keyboard_t *report) static void send_mouse(report_mouse_t *report) { +#ifdef MOUSE_ENABLE /* Select the Mouse Report Endpoint */ Endpoint_SelectEndpoint(MOUSE_IN_EPNUM); @@ -315,6 +330,7 @@ static void send_mouse(report_mouse_t *report) Endpoint_ClearIN(); } mouse_report_sent = *report; +#endif } typedef struct { -- cgit v1.2.3 From a112f3614e0e3204ce35dcdfbf2723c3382c4c35 Mon Sep 17 00:00:00 2001 From: tmk Date: Fri, 29 Jun 2012 16:48:36 +0900 Subject: confirm SetReport LED. --- protocol/lufa/lufa.c | 122 +++++++++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 58 deletions(-) (limited to 'protocol/lufa/lufa.c') diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index f485e24bf0..8fa719bc95 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c @@ -46,13 +46,12 @@ #include "descriptor.h" #include "lufa.h" +static uint8_t idle_duration = 0; +static uint8_t protocol_report = 1; static uint8_t keyboard_led_stats = 0; -// TODO: impl Control Request GET_REPORT static report_keyboard_t keyboard_report_sent; -#ifdef MOUSE_ENABLE -static report_mouse_t mouse_report_sent; -#endif + /* Host driver */ static uint8_t keyboard_leds(void); @@ -83,12 +82,8 @@ int main(void) debug_keyboard = true; debug_mouse = true; -/* TODO: can't print here - _delay_ms(5000); - USB_USBTask(); - print("abcdefg\n"); - USB_USBTask(); -*/ + // TODO: can't print here + debug("LUFA init\n"); keyboard_init(); host_set_driver(&lufa_driver); @@ -228,19 +223,6 @@ void EVENT_USB_Device_ControlRequest(void) ReportData = (uint8_t*)&keyboard_report_sent; ReportSize = sizeof(keyboard_report_sent); break; -#ifdef MOUSE_ENABLE - case MOUSE_INTERFACE: - // TODO: test/check - ReportData = (uint8_t*)&mouse_report_sent; - ReportSize = sizeof(mouse_report_sent); - break; -#endif -#ifdef EXTRAKEY_ENABLE - case EXTRA_INTERFACE: - break; -#endif - case CONSOLE_INTERFACE: - break; } /* Write the report data to the control endpoint */ @@ -252,35 +234,65 @@ void EVENT_USB_Device_ControlRequest(void) case HID_REQ_SetReport: if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { - Endpoint_ClearSETUP(); - - /* Wait until the LED report has been sent by the host */ - while (!(Endpoint_IsOUTReceived())) - { - if (USB_DeviceState == DEVICE_STATE_Unattached) - return; - } // Interface switch (USB_ControlRequest.wIndex) { case KEYBOARD_INTERFACE: - // TODO: test/check - /* Read in the LED report from the host */ + Endpoint_ClearSETUP(); + + while (!(Endpoint_IsOUTReceived())) { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } keyboard_led_stats = Endpoint_Read_8(); - break; -#ifdef MOUSE_ENABLE - case MOUSE_INTERFACE: - break; -#endif -#ifdef EXTRAKEY_ENABLE - case EXTRA_INTERFACE: - break; -#endif - case CONSOLE_INTERFACE: + + Endpoint_ClearOUT(); + Endpoint_ClearStatusStage(); break; } - Endpoint_ClearOUT(); + } + + break; + + case HID_REQ_GetProtocol: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + while (!(Endpoint_IsINReady())); + Endpoint_Write_8(protocol_report); + Endpoint_ClearIN(); + Endpoint_ClearStatusStage(); + } + + break; + case HID_REQ_SetProtocol: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + Endpoint_ClearStatusStage(); + + protocol_report = ((USB_ControlRequest.wValue & 0xFF) != 0x00); + } + + break; + case HID_REQ_SetIdle: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + Endpoint_ClearStatusStage(); + + idle_duration = ((USB_ControlRequest.wValue & 0xFF00) >> 8); + } + + break; + case HID_REQ_GetIdle: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + while (!(Endpoint_IsINReady())); + Endpoint_Write_8(idle_duration); + Endpoint_ClearIN(); Endpoint_ClearStatusStage(); } @@ -329,23 +341,17 @@ static void send_mouse(report_mouse_t *report) /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); } - mouse_report_sent = *report; #endif } -typedef struct { - uint8_t report_id; - uint16_t usage; -} __attribute__ ((packed)) report_extra_t; - static void send_system(uint16_t data) { + report_extra_t r = { + .report_id = REPORT_ID_SYSTEM, + .usage = 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(); } @@ -353,12 +359,12 @@ static void send_system(uint16_t data) static void send_consumer(uint16_t data) { + report_extra_t r = { + .report_id = REPORT_ID_CONSUMER, + .usage = 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(); } -- cgit v1.2.3