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"
46 #include "descriptor.h"
49 static uint8_t keyboard_led_stats = 0;
51 // TODO: impl Control Request GET_REPORT
52 static report_keyboard_t keyboard_report_sent;
53 static report_mouse_t mouse_report_sent;
56 static uint8_t keyboard_leds(void);
57 static void send_keyboard(report_keyboard_t *report);
58 static void send_mouse(report_mouse_t *report);
59 static void send_system(uint16_t data);
60 static void send_consumer(uint16_t data);
61 static host_driver_t lufa_driver = {
70 static void SetupHardware(void);
71 static void Generic_HID_Task(void);
81 debug_keyboard = true;
84 /* TODO: can't print here
92 host_set_driver(&lufa_driver);
101 void SetupHardware(void)
103 /* Disable watchdog if enabled by bootloader/fuses */
104 MCUSR &= ~(1 << WDRF);
107 /* Disable clock division */
108 clock_prescale_set(clock_div_1);
113 static void Generic_HID_Task(void)
115 /* Device must be connected and configured for the task to run */
116 if (USB_DeviceState != DEVICE_STATE_Configured)
119 // TODO: impl receivechar()/recvchar()
120 Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
122 /* Check to see if a packet has been sent from the host */
123 if (Endpoint_IsOUTReceived())
125 /* Check to see if the packet contains data */
126 if (Endpoint_IsReadWriteAllowed())
128 /* Create a temporary buffer to hold the read in report from the host */
129 uint8_t GenericData[GENERIC_REPORT_SIZE];
131 /* Read Generic Report Data */
132 Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL);
134 /* Process Generic Report Data */
135 //ProcessGenericHIDReport(GenericData);
138 /* Finalize the stream transfer to send the last packet */
143 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
145 if (Endpoint_IsINReady())
150 /*******************************************************************************
152 ******************************************************************************/
153 /** Event handler for the USB_Connect event. */
154 void EVENT_USB_Device_Connect(void)
158 /** Event handler for the USB_Disconnect event. */
159 void EVENT_USB_Device_Disconnect(void)
163 /** Event handler for the USB_ConfigurationChanged event.
164 * This is fired when the host sets the current configuration of the USB device after enumeration.
166 void EVENT_USB_Device_ConfigurationChanged(void)
168 bool ConfigSuccess = true;
170 /* Setup Keyboard HID Report Endpoints */
171 ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
172 HID_EPSIZE, ENDPOINT_BANK_SINGLE);
174 /* Setup Mouse HID Report Endpoint */
175 ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
176 HID_EPSIZE, ENDPOINT_BANK_SINGLE);
178 /* Setup Generic HID Report Endpoints */
179 ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
180 GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE);
181 ConfigSuccess &= Endpoint_ConfigureEndpoint(GENERIC_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
182 GENERIC_EPSIZE, ENDPOINT_BANK_SINGLE);
185 /** Event handler for the USB_ControlRequest event.
186 * This is fired before passing along unhandled control requests to the library for processing internally.
188 void EVENT_USB_Device_ControlRequest(void)
190 uint8_t* ReportData = NULL;
191 uint8_t ReportSize = 0;
193 /* Handle HID Class specific requests */
194 switch (USB_ControlRequest.bRequest)
196 case HID_REQ_GetReport:
197 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
199 Endpoint_ClearSETUP();
202 switch (USB_ControlRequest.wIndex) {
203 case KEYBOARD_INTERFACE:
205 ReportData = (uint8_t*)&keyboard_report_sent;
206 ReportSize = sizeof(keyboard_report_sent);
208 case MOUSE_INTERFACE:
210 ReportData = (uint8_t*)&mouse_report_sent;
211 ReportSize = sizeof(mouse_report_sent);
213 case GENERIC_INTERFACE:
217 /* Write the report data to the control endpoint */
218 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
223 case HID_REQ_SetReport:
224 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
226 Endpoint_ClearSETUP();
228 /* Wait until the LED report has been sent by the host */
229 while (!(Endpoint_IsOUTReceived()))
231 if (USB_DeviceState == DEVICE_STATE_Unattached)
236 switch (USB_ControlRequest.wIndex) {
237 case KEYBOARD_INTERFACE:
239 /* Read in the LED report from the host */
240 keyboard_led_stats = Endpoint_Read_8();
242 case MOUSE_INTERFACE:
244 case GENERIC_INTERFACE:
249 Endpoint_ClearStatusStage();
256 /*******************************************************************************
258 ******************************************************************************/
259 static uint8_t keyboard_leds(void)
261 return keyboard_led_stats;
264 static void send_keyboard(report_keyboard_t *report)
266 // TODO: handle NKRO report
267 /* Select the Keyboard Report Endpoint */
268 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
270 /* Check if Keyboard Endpoint Ready for Read/Write */
271 if (Endpoint_IsReadWriteAllowed())
273 /* Write Keyboard Report Data */
274 Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
276 /* Finalize the stream transfer to send the last packet */
279 keyboard_report_sent = *report;
282 static void send_mouse(report_mouse_t *report)
284 /* Select the Mouse Report Endpoint */
285 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
287 /* Check if Mouse Endpoint Ready for Read/Write */
288 if (Endpoint_IsReadWriteAllowed())
290 /* Write Mouse Report Data */
291 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
293 /* Finalize the stream transfer to send the last packet */
296 mouse_report_sent = *report;
299 static void send_system(uint16_t data)
303 static void send_consumer(uint16_t data)
308 /*******************************************************************************
310 ******************************************************************************/
311 int8_t sendchar(uint8_t c)
313 if (USB_DeviceState != DEVICE_STATE_Configured)
316 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
318 uint8_t timeout = 10;
319 uint16_t prevFN = USB_Device_GetFrameNumber();
320 while (!Endpoint_IsINReady()) {
321 switch (USB_DeviceState) {
322 case DEVICE_STATE_Unattached:
323 case DEVICE_STATE_Suspended:
326 if (Endpoint_IsStalled())
328 if (prevFN != USB_Device_GetFrameNumber()) {
331 prevFN = USB_Device_GetFrameNumber();
337 // send when packet is full
338 if (!Endpoint_IsReadWriteAllowed())