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