2 * Copyright 2012 Jun Wako <wakojun@gmail.com>
3 * This file is based on:
4 * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
5 * LUFA-120219/Demos/Device/Lowlevel/GenericHID
10 Copyright (C) Dean Camera, 2012.
12 dean [at] fourwalledcubicle [dot] com
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
20 Permission to use, copy, modify, distribute, and sell this
21 software and its documentation for any purpose is hereby granted
22 without fee, provided that the above copyright notice appear in
23 all copies and that both that the copyright notice and this
24 permission notice and warranty disclaimer appear in supporting
25 documentation, and that the name of the author not be used in
26 advertising or publicity pertaining to distribution of the
27 software without specific, written prior permission.
29 The author disclaim all warranties with regard to this
30 software, including all implied warranties of merchantability
31 and fitness. In no event shall the author be liable for any
32 special, indirect or consequential damages or any damages
33 whatsoever resulting from loss of use, data or profits, whether
34 in an action of contract, negligence or other tortious action,
35 arising out of or in connection with the use or performance of
41 #include "host_driver.h"
47 static uint8_t keyboard_led_stats = 0;
48 report_keyboard_t keyboard_report_sent;
49 report_mouse_t mouse_report_sent;
52 static uint8_t keyboard_leds(void);
53 static void send_keyboard(report_keyboard_t *report);
54 static void send_mouse(report_mouse_t *report);
55 static void send_system(uint16_t data);
56 static void send_consumer(uint16_t data);
57 static host_driver_t lufa_driver = {
74 debug_keyboard = true;
81 host_set_driver(&lufa_driver);
90 /** Configures the board hardware and chip peripherals for the demo's functionality. */
91 void SetupHardware(void)
93 /* Disable watchdog if enabled by bootloader/fuses */
94 MCUSR &= ~(1 << WDRF);
97 /* Disable clock division */
98 clock_prescale_set(clock_div_1);
103 /** Event handler for the USB_Connect event. */
104 void EVENT_USB_Device_Connect(void)
108 /** Event handler for the USB_Disconnect event. */
109 void EVENT_USB_Device_Disconnect(void)
113 /** Event handler for the USB_ConfigurationChanged event.
114 * This is fired when the host sets the current configuration of the USB device after enumeration.
116 void EVENT_USB_Device_ConfigurationChanged(void)
118 bool ConfigSuccess = true;
120 /* Setup Keyboard HID Report Endpoints */
121 ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
122 HID_EPSIZE, ENDPOINT_BANK_SINGLE);
123 ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
124 HID_EPSIZE, ENDPOINT_BANK_SINGLE);
126 /* Setup Mouse HID Report Endpoint */
127 ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
128 HID_EPSIZE, ENDPOINT_BANK_SINGLE);
130 /* Setup Generic HID Report Endpoints */
131 ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
132 GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE);
133 ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
134 GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE);
137 /** Event handler for the USB_ControlRequest event.
138 * This is fired before passing along unhandled control requests to the library for processing internally.
140 void EVENT_USB_Device_ControlRequest(void)
142 uint8_t* ReportData = NULL;
143 uint8_t ReportSize = 0;
145 /* Handle HID Class specific requests */
146 switch (USB_ControlRequest.bRequest)
148 case HID_REQ_GetReport:
149 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
151 Endpoint_ClearSETUP();
154 switch (USB_ControlRequest.wIndex) {
156 ReportData = (uint8_t*)&keyboard_report_sent;
157 ReportSize = sizeof(keyboard_report_sent);
160 ReportData = (uint8_t*)&mouse_report_sent;
161 ReportSize = sizeof(mouse_report_sent);
167 /* Write the report data to the control endpoint */
168 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
173 case HID_REQ_SetReport:
174 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
176 Endpoint_ClearSETUP();
178 /* Wait until the LED report has been sent by the host */
179 while (!(Endpoint_IsOUTReceived()))
181 if (USB_DeviceState == DEVICE_STATE_Unattached)
186 switch (USB_ControlRequest.wIndex) {
188 /* Read in the LED report from the host */
189 keyboard_led_stats = Endpoint_Read_8();
198 Endpoint_ClearStatusStage();
206 * This processes host LED status reports sent to the device via the keyboard OUT reporting endpoint.
208 void Keyboard_HID_Task(void)
210 /* Device must be connected and configured for the task to run */
211 if (USB_DeviceState != DEVICE_STATE_Configured)
214 /* Select the Keyboard LED Report Endpoint */
215 Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);
217 /* Check if Keyboard LED Endpoint Ready for Read/Write */
218 if (Endpoint_IsReadWriteAllowed())
220 /* Read in the LED report from the host */
221 keyboard_led_stats = Endpoint_Read_8();
223 /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
228 void Generic_HID_Task(void)
230 /* Device must be connected and configured for the task to run */
231 if (USB_DeviceState != DEVICE_STATE_Configured)
234 Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
236 /* Check to see if a packet has been sent from the host */
237 if (Endpoint_IsOUTReceived())
239 /* Check to see if the packet contains data */
240 if (Endpoint_IsReadWriteAllowed())
242 /* Create a temporary buffer to hold the read in report from the host */
243 uint8_t GenericData[GENERIC_REPORT_SIZE];
245 /* Read Generic Report Data */
246 Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL);
248 /* Process Generic Report Data */
249 //TODO: ProcessGenericHIDReport(GenericData);
252 /* Finalize the stream transfer to send the last packet */
257 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
259 if (Endpoint_IsINReady())
263 /*******************************************************************************
265 ******************************************************************************/
266 static uint8_t keyboard_leds(void)
268 return keyboard_led_stats;
271 static void send_keyboard(report_keyboard_t *report)
273 // TODO: handle NKRO report
274 /* Select the Keyboard Report Endpoint */
275 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
277 /* Check if Keyboard Endpoint Ready for Read/Write */
278 if (Endpoint_IsReadWriteAllowed())
280 /* Write Keyboard Report Data */
281 Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
283 /* Finalize the stream transfer to send the last packet */
286 keyboard_report_sent = *report;
289 static void send_mouse(report_mouse_t *report)
291 /* Select the Mouse Report Endpoint */
292 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
294 /* Check if Mouse Endpoint Ready for Read/Write */
295 if (Endpoint_IsReadWriteAllowed())
297 /* Write Mouse Report Data */
298 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
300 /* Finalize the stream transfer to send the last packet */
303 mouse_report_sent = *report;
306 static void send_system(uint16_t data)
310 static void send_consumer(uint16_t data)
315 /*******************************************************************************
317 ******************************************************************************/
318 int8_t sendchar(uint8_t c)
320 if (USB_DeviceState != DEVICE_STATE_Configured)
323 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
325 uint8_t timeout = 10;
326 uint16_t prevFN = USB_Device_GetFrameNumber();
327 while (!Endpoint_IsINReady()) {
328 switch (USB_DeviceState) {
329 case DEVICE_STATE_Unattached:
330 case DEVICE_STATE_Suspended:
333 if (Endpoint_IsStalled())
335 uint16_t currFN = USB_Device_GetFrameNumber();
336 if (prevFN != USB_Device_GetFrameNumber()) {
339 prevFN = USB_Device_GetFrameNumber();
345 // send when packet is full
346 if (!Endpoint_IsReadWriteAllowed())