]> git.gir.st - tmk_keyboard.git/blob - keyboard/lufa/lufa.c
Add LUFA mouse feature and fix mouse report.
[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
46 #include "descriptor.h"
47 #include "lufa.h"
48
49 static uint8_t keyboard_led_stats = 0;
50
51 // TODO: impl Control Request GET_REPORT
52 static report_keyboard_t keyboard_report_sent;
53 static report_mouse_t mouse_report_sent;
54
55 /* Host driver */
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 = {
62 keyboard_leds,
63 send_keyboard,
64 send_mouse,
65 send_system,
66 send_consumer
67 };
68
69
70 static void SetupHardware(void);
71 static void Console_HID_Task(void);
72
73 int main(void)
74 {
75 SetupHardware();
76 sei();
77
78 print_enable = true;
79 debug_enable = true;
80 debug_matrix = true;
81 debug_keyboard = true;
82 debug_mouse = true;
83
84 /* TODO: can't print here
85 _delay_ms(5000);
86 USB_USBTask();
87 print("abcdefg\n");
88 USB_USBTask();
89 */
90
91 keyboard_init();
92 host_set_driver(&lufa_driver);
93 while (1) {
94 keyboard_proc();
95
96 Console_HID_Task();
97 USB_USBTask();
98 }
99 }
100
101 void SetupHardware(void)
102 {
103 /* Disable watchdog if enabled by bootloader/fuses */
104 MCUSR &= ~(1 << WDRF);
105 wdt_disable();
106
107 /* Disable clock division */
108 clock_prescale_set(clock_div_1);
109
110 USB_Init();
111 }
112
113 static void Console_HID_Task(void)
114 {
115 /* Device must be connected and configured for the task to run */
116 if (USB_DeviceState != DEVICE_STATE_Configured)
117 return;
118
119 // TODO: impl receivechar()/recvchar()
120 Endpoint_SelectEndpoint(GENERIC_OUT_EPNUM);
121
122 /* Check to see if a packet has been sent from the host */
123 if (Endpoint_IsOUTReceived())
124 {
125 /* Check to see if the packet contains data */
126 if (Endpoint_IsReadWriteAllowed())
127 {
128 /* Create a temporary buffer to hold the read in report from the host */
129 uint8_t ConsoleData[GENERIC_REPORT_SIZE];
130
131 /* Read Console Report Data */
132 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
133
134 /* Process Console Report Data */
135 //ProcessConsoleHIDReport(ConsoleData);
136 }
137
138 /* Finalize the stream transfer to send the last packet */
139 Endpoint_ClearOUT();
140 }
141
142 /* IN packet */
143 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
144 // send IN packet
145 if (Endpoint_IsINReady())
146 Endpoint_ClearIN();
147 }
148
149
150 /*******************************************************************************
151 * USB Events
152 ******************************************************************************/
153 /** Event handler for the USB_Connect event. */
154 void EVENT_USB_Device_Connect(void)
155 {
156 }
157
158 /** Event handler for the USB_Disconnect event. */
159 void EVENT_USB_Device_Disconnect(void)
160 {
161 }
162
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.
165 */
166 void EVENT_USB_Device_ConfigurationChanged(void)
167 {
168 bool ConfigSuccess = true;
169
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);
173
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);
177
178 /* Setup Console 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);
183 }
184
185 /*
186 Appendix G: HID Request Support Requirements
187
188 The following table enumerates the requests that need to be supported by various types of HID class devices.
189
190 Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
191 ------------------------------------------------------------------------------------------
192 Boot Mouse Required Optional Optional Optional Required Required
193 Non-Boot Mouse Required Optional Optional Optional Optional Optional
194 Boot Keyboard Required Optional Required Required Required Required
195 Non-Boot Keybrd Required Optional Required Required Optional Optional
196 Other Device Required Optional Optional Optional Optional Optional
197 */
198 /** Event handler for the USB_ControlRequest event.
199 * This is fired before passing along unhandled control requests to the library for processing internally.
200 */
201 void EVENT_USB_Device_ControlRequest(void)
202 {
203 uint8_t* ReportData = NULL;
204 uint8_t ReportSize = 0;
205
206 /* Handle HID Class specific requests */
207 switch (USB_ControlRequest.bRequest)
208 {
209 case HID_REQ_GetReport:
210 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
211 {
212 Endpoint_ClearSETUP();
213
214 // Interface
215 switch (USB_ControlRequest.wIndex) {
216 case KEYBOARD_INTERFACE:
217 // TODO: test/check
218 ReportData = (uint8_t*)&keyboard_report_sent;
219 ReportSize = sizeof(keyboard_report_sent);
220 break;
221 case MOUSE_INTERFACE:
222 // TODO: test/check
223 ReportData = (uint8_t*)&mouse_report_sent;
224 ReportSize = sizeof(mouse_report_sent);
225 break;
226 case GENERIC_INTERFACE:
227 break;
228 }
229
230 /* Write the report data to the control endpoint */
231 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
232 Endpoint_ClearOUT();
233 }
234
235 break;
236 case HID_REQ_SetReport:
237 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
238 {
239 Endpoint_ClearSETUP();
240
241 /* Wait until the LED report has been sent by the host */
242 while (!(Endpoint_IsOUTReceived()))
243 {
244 if (USB_DeviceState == DEVICE_STATE_Unattached)
245 return;
246 }
247
248 // Interface
249 switch (USB_ControlRequest.wIndex) {
250 case KEYBOARD_INTERFACE:
251 // TODO: test/check
252 /* Read in the LED report from the host */
253 keyboard_led_stats = Endpoint_Read_8();
254 break;
255 case MOUSE_INTERFACE:
256 break;
257 case GENERIC_INTERFACE:
258 break;
259 }
260
261 Endpoint_ClearOUT();
262 Endpoint_ClearStatusStage();
263 }
264
265 break;
266 }
267 }
268
269 /*******************************************************************************
270 * Host driver
271 ******************************************************************************/
272 static uint8_t keyboard_leds(void)
273 {
274 return keyboard_led_stats;
275 }
276
277 static void send_keyboard(report_keyboard_t *report)
278 {
279 // TODO: handle NKRO report
280 /* Select the Keyboard Report Endpoint */
281 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
282
283 /* Check if Keyboard Endpoint Ready for Read/Write */
284 if (Endpoint_IsReadWriteAllowed())
285 {
286 /* Write Keyboard Report Data */
287 Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
288
289 /* Finalize the stream transfer to send the last packet */
290 Endpoint_ClearIN();
291 }
292 keyboard_report_sent = *report;
293 }
294
295 static void send_mouse(report_mouse_t *report)
296 {
297 /* Select the Mouse Report Endpoint */
298 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
299
300 /* Check if Mouse Endpoint Ready for Read/Write */
301 if (Endpoint_IsReadWriteAllowed())
302 {
303 /* Write Mouse Report Data */
304 /* Mouse report data structure
305 * LUFA: { buttons, x, y }
306 * tmk: { buttons, x, y, v, h }
307 */
308 //Endpoint_Write_Stream_LE((uint8_t *)report+1, 3, NULL);
309 Endpoint_Write_Stream_LE(report, 3, NULL);
310
311 /* Finalize the stream transfer to send the last packet */
312 Endpoint_ClearIN();
313 }
314 mouse_report_sent = *report;
315 }
316
317 static void send_system(uint16_t data)
318 {
319 }
320
321 static void send_consumer(uint16_t data)
322 {
323 }
324
325
326 /*******************************************************************************
327 * sendchar
328 ******************************************************************************/
329 int8_t sendchar(uint8_t c)
330 {
331 if (USB_DeviceState != DEVICE_STATE_Configured)
332 return -1;
333
334 Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
335
336 uint8_t timeout = 10;
337 uint16_t prevFN = USB_Device_GetFrameNumber();
338 while (!Endpoint_IsINReady()) {
339 switch (USB_DeviceState) {
340 case DEVICE_STATE_Unattached:
341 case DEVICE_STATE_Suspended:
342 return -1;
343 }
344 if (Endpoint_IsStalled())
345 return -1;
346 if (prevFN != USB_Device_GetFrameNumber()) {
347 if (!(timeout--))
348 return -1;
349 prevFN = USB_Device_GetFrameNumber();
350 }
351 }
352
353 Endpoint_Write_8(c);
354
355 // send when packet is full
356 if (!Endpoint_IsReadWriteAllowed())
357 Endpoint_ClearIN();
358
359 return 0;
360 }
Imprint / Impressum