]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - ps2_vusb/host_vusb.c
added protocol stack: pjrc, vusb
[max/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 }