]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - keyboard/lufa/lufa.c
clean descriptor setting. Remove keyboard OUT Endpoint.
[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
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 Generic_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         Generic_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 Generic_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 GenericData[GENERIC_REPORT_SIZE];
130
131                         /* Read Generic Report Data */
132                         Endpoint_Read_Stream_LE(&GenericData, sizeof(GenericData), NULL);
133
134                         /* Process Generic Report Data */
135                         //ProcessGenericHIDReport(GenericData);
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 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);
183 }
184
185 /** Event handler for the USB_ControlRequest event.
186  *  This is fired before passing along unhandled control requests to the library for processing internally.
187  */
188 void EVENT_USB_Device_ControlRequest(void)
189 {
190     uint8_t* ReportData = NULL;
191     uint8_t  ReportSize = 0;
192
193     /* Handle HID Class specific requests */
194     switch (USB_ControlRequest.bRequest)
195     {
196         case HID_REQ_GetReport:
197             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
198             {
199                 Endpoint_ClearSETUP();
200
201                 // Interface
202                 switch (USB_ControlRequest.wIndex) {
203                 case KEYBOARD_INTERFACE:
204                     // TODO: test/check
205                     ReportData = (uint8_t*)&keyboard_report_sent;
206                     ReportSize = sizeof(keyboard_report_sent);
207                     break;
208                 case MOUSE_INTERFACE:
209                     // TODO: test/check
210                     ReportData = (uint8_t*)&mouse_report_sent;
211                     ReportSize = sizeof(mouse_report_sent);
212                     break;
213                 case GENERIC_INTERFACE:
214                     break;
215                 }
216
217                 /* Write the report data to the control endpoint */
218                 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
219                 Endpoint_ClearOUT();
220             }
221
222             break;
223         case HID_REQ_SetReport:
224             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
225             {
226                 Endpoint_ClearSETUP();
227
228                 /* Wait until the LED report has been sent by the host */
229                 while (!(Endpoint_IsOUTReceived()))
230                 {
231                     if (USB_DeviceState == DEVICE_STATE_Unattached)
232                       return;
233                 }
234
235                 // Interface
236                 switch (USB_ControlRequest.wIndex) {
237                 case KEYBOARD_INTERFACE:
238                     // TODO: test/check
239                     /* Read in the LED report from the host */
240                     keyboard_led_stats = Endpoint_Read_8();
241                     break;
242                 case MOUSE_INTERFACE:
243                     break;
244                 case GENERIC_INTERFACE:
245                     break;
246                 }
247
248                 Endpoint_ClearOUT();
249                 Endpoint_ClearStatusStage();
250             }
251
252             break;
253     }
254 }
255
256 /*******************************************************************************
257  * Host driver 
258  ******************************************************************************/
259 static uint8_t keyboard_leds(void)
260 {
261     return keyboard_led_stats;
262 }
263
264 static void send_keyboard(report_keyboard_t *report)
265 {
266     // TODO: handle NKRO report
267     /* Select the Keyboard Report Endpoint */
268     Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
269
270     /* Check if Keyboard Endpoint Ready for Read/Write */
271     if (Endpoint_IsReadWriteAllowed())
272     {
273         /* Write Keyboard Report Data */
274         Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
275
276         /* Finalize the stream transfer to send the last packet */
277         Endpoint_ClearIN();
278     }
279     keyboard_report_sent = *report;
280 }
281
282 static void send_mouse(report_mouse_t *report)
283 {
284     /* Select the Mouse Report Endpoint */
285     Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
286
287     /* Check if Mouse Endpoint Ready for Read/Write */
288     if (Endpoint_IsReadWriteAllowed())
289     {
290         /* Write Mouse Report Data */
291         Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
292
293         /* Finalize the stream transfer to send the last packet */
294         Endpoint_ClearIN();
295     }
296     mouse_report_sent = *report;
297 }
298
299 static void send_system(uint16_t data)
300 {
301 }
302
303 static void send_consumer(uint16_t data)
304 {
305 }
306
307
308 /*******************************************************************************
309  * sendchar
310  ******************************************************************************/
311 int8_t sendchar(uint8_t c)
312 {
313     if (USB_DeviceState != DEVICE_STATE_Configured)
314       return -1;
315
316     Endpoint_SelectEndpoint(GENERIC_IN_EPNUM);
317
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:
324             return -1;
325         }
326         if (Endpoint_IsStalled())
327             return -1;
328         if (prevFN != USB_Device_GetFrameNumber()) {
329             if (!(timeout--))
330                 return -1;
331             prevFN = USB_Device_GetFrameNumber();
332         }
333     }
334
335     Endpoint_Write_8(c);
336
337     // send when packet is full
338     if (!Endpoint_IsReadWriteAllowed())
339         Endpoint_ClearIN();
340
341     return 0;
342 }