]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - keyboard/lufa/lufa.c
Add sendchar with Generic HID to support debug print.
[max/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 }