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