]> git.gir.st - tmk_keyboard.git/blob - keyboard/lufa/lufa.c
Add sendchar with Generic HID to support debug print.
[tmk_keyboard.git] / keyboard / lufa / lufa.c
1 /*
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
6 */
7
8 /*
9 LUFA Library
10 Copyright (C) Dean Camera, 2012.
11
12 dean [at] fourwalledcubicle [dot] com
13 www.lufa-lib.org
14 */
15
16 /*
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
19
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.
28
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
36 this software.
37 */
38
39 #include "report.h"
40 #include "host.h"
41 #include "host_driver.h"
42 #include "keyboard.h"
43 #include "sendchar.h"
44 #include "debug.h"
45 #include "lufa.h"
46
47 static uint8_t keyboard_led_stats = 0;
48 report_keyboard_t keyboard_report_sent;
49 report_mouse_t mouse_report_sent;
50
51 /* Host driver */
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 = {
58 keyboard_leds,
59 send_keyboard,
60 send_mouse,
61 send_system,
62 send_consumer
63 };
64
65
66 int main(void)
67 {
68 SetupHardware();
69 sei();
70
71 print_enable = true;
72 debug_enable = true;
73 debug_matrix = true;
74 debug_keyboard = true;
75 debug_mouse = true;
76
77 _delay_ms(3000);
78 print("abcdefg\n");
79
80 keyboard_init();
81 host_set_driver(&lufa_driver);
82 while (1) {
83 keyboard_proc();
84 Keyboard_HID_Task();
85 Generic_HID_Task();
86 USB_USBTask();
87 }
88 }
89
90 /** Configures the board hardware and chip peripherals for the demo's functionality. */
91 void SetupHardware(void)
92 {
93 /* Disable watchdog if enabled by bootloader/fuses */
94 MCUSR &= ~(1 << WDRF);
95 wdt_disable();
96
97 /* Disable clock division */
98 clock_prescale_set(clock_div_1);
99
100 USB_Init();
101 }
102
103 /** Event handler for the USB_Connect event. */
104 void EVENT_USB_Device_Connect(void)
105 {
106 }
107
108 /** Event handler for the USB_Disconnect event. */
109 void EVENT_USB_Device_Disconnect(void)
110 {
111 }
112
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.
115 */
116 void EVENT_USB_Device_ConfigurationChanged(void)
117 {
118 bool ConfigSuccess = true;
119
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);
125
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);
129
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);
135 }
136
137 /** Event handler for the USB_ControlRequest event.
138 * This is fired before passing along unhandled control requests to the library for processing internally.
139 */
140 void EVENT_USB_Device_ControlRequest(void)
141 {
142 uint8_t* ReportData = NULL;
143 uint8_t ReportSize = 0;
144
145 /* Handle HID Class specific requests */
146 switch (USB_ControlRequest.bRequest)
147 {
148 case HID_REQ_GetReport:
149 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
150 {
151 Endpoint_ClearSETUP();
152
153 // Interface
154 switch (USB_ControlRequest.wIndex) {
155 case 1: // Keyboard
156 ReportData = (uint8_t*)&keyboard_report_sent;
157 ReportSize = sizeof(keyboard_report_sent);
158 break;
159 case 2: // Mouse
160 ReportData = (uint8_t*)&mouse_report_sent;
161 ReportSize = sizeof(mouse_report_sent);
162 break;
163 case 3: // Generic
164 break;
165 }
166
167 /* Write the report data to the control endpoint */
168 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
169 Endpoint_ClearOUT();
170 }
171
172 break;
173 case HID_REQ_SetReport:
174 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
175 {
176 Endpoint_ClearSETUP();
177
178 /* Wait until the LED report has been sent by the host */
179 while (!(Endpoint_IsOUTReceived()))
180 {
181 if (USB_DeviceState == DEVICE_STATE_Unattached)
182 return;
183 }
184
185 // Interface
186 switch (USB_ControlRequest.wIndex) {
187 case 1: // Keyboard
188 /* Read in the LED report from the host */
189 keyboard_led_stats = Endpoint_Read_8();
190 break;
191 case 2: // Mouse
192 break;
193 case 3: // Generic
194 break;
195 }
196
197 Endpoint_ClearOUT();
198 Endpoint_ClearStatusStage();
199 }
200
201 break;
202 }
203 }
204
205 /** Keyboard task.
206 * This processes host LED status reports sent to the device via the keyboard OUT reporting endpoint.
207 */
208 void Keyboard_HID_Task(void)
209 {
210 /* Device must be connected and configured for the task to run */
211 if (USB_DeviceState != DEVICE_STATE_Configured)
212 return;
213
214 /* Select the Keyboard LED Report Endpoint */
215 Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM);
216
217 /* Check if Keyboard LED Endpoint Ready for Read/Write */
218 if (Endpoint_IsReadWriteAllowed())
219 {
220 /* Read in the LED report from the host */
221 keyboard_led_stats = Endpoint_Read_8();
222
223 /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
224 Endpoint_ClearOUT();
225 }
226 }
227
228 void Generic_HID_Task(void)
229 {
230 /* Device must be connected and configured for the task to run */
231 if (USB_DeviceState != DEVICE_STATE_Configured)
232 return;
233
234 Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
235
236 /* Check to see if a packet has been sent from the host */
237 if (Endpoint_IsOUTReceived())
238 {
239 /* Check to see if the packet contains data */
240 if (Endpoint_IsReadWriteAllowed())
241 {
242 /* Create a temporary buffer to hold the read in report from the host */
243 uint8_t GenericData[GENERIC_REPORT_SIZE];
244
245 /* Read Generic Report Data */
246 Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL);
247
248 /* Process Generic Report Data */
249 //TODO: ProcessGenericHIDReport(GenericData);
250 }
251
252 /* Finalize the stream transfer to send the last packet */
253 Endpoint_ClearOUT();
254 }
255
256 /* IN packet */
257 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
258 // send IN packet
259 if (Endpoint_IsINReady())
260 Endpoint_ClearIN();
261 }
262
263 /*******************************************************************************
264 * Host driver
265 ******************************************************************************/
266 static uint8_t keyboard_leds(void)
267 {
268 return keyboard_led_stats;
269 }
270
271 static void send_keyboard(report_keyboard_t *report)
272 {
273 // TODO: handle NKRO report
274 /* Select the Keyboard Report Endpoint */
275 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
276
277 /* Check if Keyboard Endpoint Ready for Read/Write */
278 if (Endpoint_IsReadWriteAllowed())
279 {
280 /* Write Keyboard Report Data */
281 Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
282
283 /* Finalize the stream transfer to send the last packet */
284 Endpoint_ClearIN();
285 }
286 keyboard_report_sent = *report;
287 }
288
289 static void send_mouse(report_mouse_t *report)
290 {
291 /* Select the Mouse Report Endpoint */
292 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
293
294 /* Check if Mouse Endpoint Ready for Read/Write */
295 if (Endpoint_IsReadWriteAllowed())
296 {
297 /* Write Mouse Report Data */
298 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
299
300 /* Finalize the stream transfer to send the last packet */
301 Endpoint_ClearIN();
302 }
303 mouse_report_sent = *report;
304 }
305
306 static void send_system(uint16_t data)
307 {
308 }
309
310 static void send_consumer(uint16_t data)
311 {
312 }
313
314
315 /*******************************************************************************
316 * sendchar
317 ******************************************************************************/
318 int8_t sendchar(uint8_t c)
319 {
320 if (USB_DeviceState != DEVICE_STATE_Configured)
321 return -1;
322
323 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
324
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:
331 return -1;
332 }
333 if (Endpoint_IsStalled())
334 return -1;
335 uint16_t currFN = USB_Device_GetFrameNumber();
336 if (prevFN != USB_Device_GetFrameNumber()) {
337 if (!(timeout--))
338 return -1;
339 prevFN = USB_Device_GetFrameNumber();
340 }
341 }
342
343 Endpoint_Write_8(c);
344
345 // send when packet is full
346 if (!Endpoint_IsReadWriteAllowed())
347 Endpoint_ClearIN();
348
349 return 0;
350 }
Imprint / Impressum