]> git.gir.st - tmk_keyboard.git/blob - ps2_vusb/host_vusb.c
added protocol stack: pjrc, vusb
[tmk_keyboard.git] / ps2_vusb / host_vusb.c
1 #include "usbdrv.h"
2 #include "usbconfig.h"
3 #include "keyboard.h"
4 #include "print.h"
5 #include "host.h"
6 #include "host_vusb.h"
7
8
9 #define KBUF_SIZE 16
10 static report_keyboard_t kbuf[KBUF_SIZE];
11 static uint8_t kbuf_head = 0;
12 static uint8_t kbuf_tail = 0;
13
14
15 void host_vusb_keyboard_send()
16 {
17 while (usbInterruptIsReady() && kbuf_head != kbuf_tail) {
18 usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
19 kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
20 }
21 }
22
23 void host_keyboard_send(report_keyboard_t *report)
24 {
25 uint8_t next = (kbuf_head + 1) % KBUF_SIZE;
26 if (next != kbuf_tail) {
27 kbuf[kbuf_head] = *report;
28 kbuf_head = next;
29 print("kbuf: "); phex(kbuf_head); phex(kbuf_tail); print("\n");
30 } else {
31 print("kbuf: full\n");
32 }
33 }
34
35 void host_mouse_send(report_mouse_t *report)
36 {
37 if (usbInterruptIsReady3()) {
38 usbSetInterrupt3((void *)report, sizeof(*report));
39 } else {
40 print("Int3 not ready\n");
41 }
42 }
43
44
45
46
47 static struct {
48 uint16_t len;
49 enum {
50 NONE,
51 SET_LED
52 } kind;
53 } last_req;
54
55 uint8_t host_keyboard_led = 0;
56 static uchar idleRate;
57
58 usbMsgLen_t usbFunctionSetup(uchar data[8])
59 {
60 usbRequest_t *rq = (void *)data;
61
62 //print("Setup: ");
63 if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
64 /*
65 print("CLASS: ");
66 phex(rq->bRequest); print(" ");
67 phex16(rq->wValue.word); print(" ");
68 phex16(rq->wIndex.word); print(" ");
69 phex16(rq->wLength.word); print(" ");
70 */
71 if(rq->bRequest == USBRQ_HID_GET_REPORT){
72 print(" GET_REPORT");
73 /* we only have one report type, so don't look at wValue */
74 usbMsgPtr = (void *)keyboard_report;
75 return sizeof(*keyboard_report);
76 }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
77 print(" GET_IDLE: ");
78 phex(idleRate);
79 usbMsgPtr = &idleRate;
80 return 1;
81 }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
82 idleRate = rq->wValue.bytes[1];
83 print(" SET_IDLE: ");
84 phex(idleRate);
85 }else if(rq->bRequest == USBRQ_HID_SET_REPORT){
86 //print(" SET_REPORT: ");
87 if (rq->wValue.word == 0x0200 && rq->wIndex.word == 0) {
88 last_req.kind = SET_LED;
89 last_req.len = rq->wLength.word;
90 }
91 return USB_NO_MSG; // to get data in usbFunctionWrite
92 }
93 print("\n");
94 }else{
95 print("VENDOR\n");
96 /* no vendor specific requests implemented */
97 }
98 return 0; /* default for not implemented requests: return no data back to host */
99 }
100
101 uchar usbFunctionWrite(uchar *data, uchar len)
102 {
103 if (last_req.len == 0) {
104 return -1;
105 }
106 switch (last_req.kind) {
107 case SET_LED:
108 //print("SET_LED\n");
109 host_keyboard_led = data[0];
110 last_req.len = 0;
111 return 1;
112 break;
113 case NONE:
114 default:
115 return -1;
116 break;
117 }
118 return 1;
119 }
120
121
122 PROGMEM uchar keyboard_hid_report[] = {
123 0x05, 0x01, // Usage Page (Generic Desktop),
124 0x09, 0x06, // Usage (Keyboard),
125 0xA1, 0x01, // Collection (Application),
126 0x75, 0x01, // Report Size (1),
127 0x95, 0x08, // Report Count (8),
128 0x05, 0x07, // Usage Page (Key Codes),
129 0x19, 0xE0, // Usage Minimum (224),
130 0x29, 0xE7, // Usage Maximum (231),
131 0x15, 0x00, // Logical Minimum (0),
132 0x25, 0x01, // Logical Maximum (1),
133 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
134 0x95, 0x01, // Report Count (1),
135 0x75, 0x08, // Report Size (8),
136 0x81, 0x03, // Input (Constant), ;Reserved byte
137 0x95, 0x05, // Report Count (5),
138 0x75, 0x01, // Report Size (1),
139 0x05, 0x08, // Usage Page (LEDs),
140 0x19, 0x01, // Usage Minimum (1),
141 0x29, 0x05, // Usage Maximum (5),
142 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
143 0x95, 0x01, // Report Count (1),
144 0x75, 0x03, // Report Size (3),
145 0x91, 0x03, // Output (Constant), ;LED report padding
146 0x95, 0x06, // Report Count (6),
147 0x75, 0x08, // Report Size (8),
148 0x15, 0x00, // Logical Minimum (0),
149 0x25, 0xFF, // Logical Maximum(255),
150 0x05, 0x07, // Usage Page (Key Codes),
151 0x19, 0x00, // Usage Minimum (0),
152 0x29, 0xFF, // Usage Maximum (255),
153 0x81, 0x00, // Input (Data, Array),
154 0xc0 // End Collection
155 };
156
157 // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
158 // http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
159 // http://www.keil.com/forum/15671/
160 // http://www.microsoft.com/whdc/device/input/wheel.mspx
161 PROGMEM uchar mouse_hid_report[] = {
162 /* from HID 1.11 spec example */
163 0x05, 0x01, // Usage Page (Generic Desktop),
164 0x09, 0x02, // Usage (Mouse),
165 0xA1, 0x01, // Collection (Application),
166 0x09, 0x01, // Usage (Pointer),
167 0xA1, 0x00, // Collection (Physical),
168 0x05, 0x09, // Usage Page (Buttons),
169 0x19, 0x01, // Usage Minimum (01),
170 0x29, 0x03, // Usage Maximun (03),
171 0x15, 0x00, // Logical Minimum (0),
172 0x25, 0x01, // Logical Maximum (1),
173 0x95, 0x03, // Report Count (3),
174 0x75, 0x01, // Report Size (1),
175 0x81, 0x02, // Input (Data, Variable, Absolute), ;3 button bits
176 0x95, 0x01, // Report Count (1),
177 0x75, 0x05, // Report Size (5),
178 0x81, 0x01, // Input (Constant), ;5 bit padding
179 0x05, 0x01, // Usage Page (Generic Desktop),
180 0x09, 0x30, // Usage (X),
181 0x09, 0x31, // Usage (Y),
182 0x15, 0x81, // Logical Minimum (-127),
183 0x25, 0x7F, // Logical Maximum (127),
184 0x75, 0x08, // Report Size (8),
185 0x95, 0x02, // Report Count (2),
186 0x81, 0x06, // Input (Data, Variable, Relative), ;2 position bytes (X & Y)
187 0xC0, // End Collection,
188 0xC0, // End Collection
189 /*
190 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
191 0x09, 0x02, // USAGE (Mouse)
192 0xa1, 0x01, // COLLECTION (Application)
193 0x09, 0x02, // USAGE (Mouse)
194 0xa1, 0x02, // COLLECTION (Logical)
195 0x09, 0x01, // USAGE (Pointer)
196 0xa1, 0x00, // COLLECTION (Physical)
197 // ------------------------------ Buttons
198 0x05, 0x09, // USAGE_PAGE (Button)
199 0x19, 0x01, // USAGE_MINIMUM (Button 1)
200 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
201 0x15, 0x00, // LOGICAL_MINIMUM (0)
202 0x25, 0x01, // LOGICAL_MAXIMUM (1)
203 0x75, 0x01, // REPORT_SIZE (1)
204 0x95, 0x05, // REPORT_COUNT (5)
205 0x81, 0x02, // INPUT (Data,Var,Abs)
206 // ------------------------------ Padding
207 0x75, 0x03, // REPORT_SIZE (3)
208 0x95, 0x01, // REPORT_COUNT (1)
209 0x81, 0x03, // INPUT (Cnst,Var,Abs)
210 // ------------------------------ X,Y position
211 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
212 0x09, 0x30, // USAGE (X)
213 0x09, 0x31, // USAGE (Y)
214 0x15, 0x81, // LOGICAL_MINIMUM (-127)
215 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
216 0x75, 0x08, // REPORT_SIZE (8)
217 0x95, 0x02, // REPORT_COUNT (2)
218 0x81, 0x06, // INPUT (Data,Var,Rel)
219 0xa1, 0x02, // COLLECTION (Logical)
220 // ------------------------------ Vertical wheel res multiplier
221 0x09, 0x48, // USAGE (Resolution Multiplier)
222 0x15, 0x00, // LOGICAL_MINIMUM (0)
223 0x25, 0x01, // LOGICAL_MAXIMUM (1)
224 0x35, 0x01, // PHYSICAL_MINIMUM (1)
225 0x45, 0x04, // PHYSICAL_MAXIMUM (4)
226 0x75, 0x02, // REPORT_SIZE (2)
227 0x95, 0x01, // REPORT_COUNT (1)
228 0xa4, // PUSH
229 0xb1, 0x02, // FEATURE (Data,Var,Abs)
230 // ------------------------------ Vertical wheel
231 0x09, 0x38, // USAGE (Wheel)
232 0x15, 0x81, // LOGICAL_MINIMUM (-127)
233 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
234 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
235 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
236 0x75, 0x08, // REPORT_SIZE (8)
237 0x81, 0x06, // INPUT (Data,Var,Rel)
238 0xc0, // END_COLLECTION
239 0xa1, 0x02, // COLLECTION (Logical)
240 // ------------------------------ Horizontal wheel res multiplier
241 0x09, 0x48, // USAGE (Resolution Multiplier)
242 0xb4, // POP
243 0xb1, 0x02, // FEATURE (Data,Var,Abs)
244 // ------------------------------ Padding for Feature report
245 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
246 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
247 0x75, 0x04, // REPORT_SIZE (4)
248 0xb1, 0x03, // FEATURE (Cnst,Var,Abs)
249 // ------------------------------ Horizontal wheel
250 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
251 0x0a, 0x38, 0x02, // USAGE (AC Pan)
252 0x15, 0x81, // LOGICAL_MINIMUM (-127)
253 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
254 0x75, 0x08, // REPORT_SIZE (8)
255 0x81, 0x06, // INPUT (Data,Var,Rel)
256 0xc0, // END_COLLECTION
257 0xc0, // END_COLLECTION
258 0xc0, // END_COLLECTION
259 0xc0 // END_COLLECTION
260 */
261 };
262
263
264 /* Descriptor for compite device: Keyboard + Mouse */
265 #if USB_CFG_DESCR_PROPS_CONFIGURATION
266 PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
267 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
268 USBDESCR_CONFIG, /* descriptor type */
269 9 + (9 + 9 + 7) + (9 + 9 + 7), 0,
270 //18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0,
271 /* total length of data returned (including inlined descriptors) */
272 2, /* number of interfaces in this configuration */
273 1, /* index of this configuration */
274 0, /* configuration name string index */
275 #if USB_CFG_IS_SELF_POWERED
276 (1 << 7) | USBATTR_SELFPOWER, /* attributes */
277 #else
278 (1 << 7), /* attributes */
279 #endif
280 USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
281
282 /*
283 * Keyboard interface
284 */
285 /* Interface descriptor */
286 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
287 USBDESCR_INTERFACE, /* descriptor type */
288 0, /* index of this interface */
289 0, /* alternate setting for this interface */
290 USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
291 USB_CFG_INTERFACE_CLASS,
292 USB_CFG_INTERFACE_SUBCLASS,
293 USB_CFG_INTERFACE_PROTOCOL,
294 0, /* string index for interface */
295 /* HID descriptor */
296 9, /* sizeof(usbDescrHID): length of descriptor in bytes */
297 USBDESCR_HID, /* descriptor type: HID */
298 0x01, 0x01, /* BCD representation of HID version */
299 0x00, /* target country code */
300 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
301 0x22, /* descriptor type: report */
302 sizeof(keyboard_hid_report), 0, /* total length of report descriptor */
303 /* Endpoint descriptor */
304 #if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
305 7, /* sizeof(usbDescrEndpoint) */
306 USBDESCR_ENDPOINT, /* descriptor type = endpoint */
307 (char)0x81, /* IN endpoint number 1 */
308 0x03, /* attrib: Interrupt endpoint */
309 8, 0, /* maximum packet size */
310 USB_CFG_INTR_POLL_INTERVAL, /* in ms */
311 #endif
312
313 /*
314 * Mouse interface
315 */
316 /* Interface descriptor */
317 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
318 USBDESCR_INTERFACE, /* descriptor type */
319 1, /* index of this interface */
320 0, /* alternate setting for this interface */
321 USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
322 0x03, /* CLASS: HID */
323 0, /* SUBCLASS: none */
324 0, /* PROTOCOL: none */
325 0, /* string index for interface */
326 /* HID descriptor */
327 9, /* sizeof(usbDescrHID): length of descriptor in bytes */
328 USBDESCR_HID, /* descriptor type: HID */
329 0x01, 0x01, /* BCD representation of HID version */
330 0x00, /* target country code */
331 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
332 0x22, /* descriptor type: report */
333 sizeof(mouse_hid_report), 0, /* total length of report descriptor */
334 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
335 /* Endpoint descriptor */
336 7, /* sizeof(usbDescrEndpoint) */
337 USBDESCR_ENDPOINT, /* descriptor type = endpoint */
338 (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
339 0x03, /* attrib: Interrupt endpoint */
340 8, 0, /* maximum packet size */
341 USB_CFG_INTR_POLL_INTERVAL, /* in ms */
342 #endif
343 };
344 #endif
345
346 USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
347 {
348 usbMsgLen_t len = 0;
349
350 print("usbFunctionDescriptor: ");
351 phex(rq->bmRequestType); print(" ");
352 phex(rq->bRequest); print(" ");
353 phex16(rq->wValue.word); print(" ");
354 phex16(rq->wIndex.word); print(" ");
355 phex16(rq->wLength.word); print("\n");
356
357 switch (rq->wValue.bytes[1]) {
358 #if USB_CFG_DESCR_PROPS_CONFIGURATION
359 case USBDESCR_CONFIG:
360 usbMsgPtr = (unsigned char *)usbDescriptorConfiguration;
361 len = sizeof(usbDescriptorConfiguration);
362 break;
363 #endif
364 case USBDESCR_HID:
365 usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 18);
366 len = 9;
367 break;
368 case USBDESCR_HID_REPORT:
369 /* interface index */
370 switch (rq->wIndex.word) {
371 case 0:
372 usbMsgPtr = keyboard_hid_report;
373 len = sizeof(keyboard_hid_report);
374 break;
375 case 1:
376 usbMsgPtr = mouse_hid_report;
377 len = sizeof(mouse_hid_report);
378 break;
379 }
380 break;
381 }
382 print("desc len: "); phex(len); print("\n");
383 return len;
384 }
Imprint / Impressum