Mercurial > louis > kiibohd-controller
comparison Output/pjrcUSB/arm/usb_dev.c @ 368:06a54d582bf8
FIxing Media Keys and general USB compatibilty
- Media keys tested working on Linux/Windows/Mac (use Consumer control)
- Fixed enumeration delays
- Fixed virtual serial port configuration issues
- Fixed GET_REPORT and SET_REPORT
- Added intial descriptors and endpoints for Mouse and Joystick devices
- Split out the consumer and system control endpoint
- Added more fault debugging messages
- Added interface names to endpoints (visible in Windows Device Manager)
- Added KLL define for keyboard locale
author | Jacob Alexander <haata@kiibohd.com> |
---|---|
date | Wed, 19 Aug 2015 00:01:15 -0700 |
parents | 136e47478441 |
children | 39e338a6733d |
comparison
equal
deleted
inserted
replaced
367:8a6c2d410ad9 | 368:06a54d582bf8 |
---|---|
171 | 171 |
172 // ----- Functions ----- | 172 // ----- Functions ----- |
173 | 173 |
174 static void endpoint0_stall() | 174 static void endpoint0_stall() |
175 { | 175 { |
176 #ifdef UART_DEBUG_UNKNOWN | |
177 print("STALL" NL ); | |
178 #endif | |
176 USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; | 179 USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; |
177 } | 180 } |
178 | 181 |
179 static void endpoint0_transmit( const void *data, uint32_t len ) | 182 static void endpoint0_transmit( const void *data, uint32_t len ) |
180 { | 183 { |
196 int i; | 199 int i; |
197 | 200 |
198 switch ( setup.wRequestAndType ) | 201 switch ( setup.wRequestAndType ) |
199 { | 202 { |
200 case 0x0500: // SET_ADDRESS | 203 case 0x0500: // SET_ADDRESS |
201 break; | 204 goto send; |
205 | |
202 case 0x0900: // SET_CONFIGURATION | 206 case 0x0900: // SET_CONFIGURATION |
203 #ifdef UART_DEBUG | 207 #ifdef UART_DEBUG |
204 print("CONFIGURE - "); | 208 print("CONFIGURE - "); |
205 #endif | 209 #endif |
206 usb_configuration = setup.wValue; | 210 usb_configuration = setup.wValue; |
286 } | 290 } |
287 } | 291 } |
288 table[ index( i, TX, EVEN ) ].desc = 0; | 292 table[ index( i, TX, EVEN ) ].desc = 0; |
289 table[ index( i, TX, ODD ) ].desc = 0; | 293 table[ index( i, TX, ODD ) ].desc = 0; |
290 } | 294 } |
291 break; | 295 goto send; |
296 | |
292 case 0x0880: // GET_CONFIGURATION | 297 case 0x0880: // GET_CONFIGURATION |
293 reply_buffer[0] = usb_configuration; | 298 reply_buffer[0] = usb_configuration; |
294 datalen = 1; | 299 datalen = 1; |
295 data = reply_buffer; | 300 data = reply_buffer; |
296 break; | 301 goto send; |
302 | |
297 case 0x0080: // GET_STATUS (device) | 303 case 0x0080: // GET_STATUS (device) |
298 reply_buffer[0] = 0; | 304 reply_buffer[0] = 0; |
299 reply_buffer[1] = 0; | 305 reply_buffer[1] = 0; |
300 datalen = 2; | 306 datalen = 2; |
301 data = reply_buffer; | 307 data = reply_buffer; |
302 break; | 308 goto send; |
309 | |
303 case 0x0082: // GET_STATUS (endpoint) | 310 case 0x0082: // GET_STATUS (endpoint) |
304 if ( setup.wIndex > NUM_ENDPOINTS ) | 311 if ( setup.wIndex > NUM_ENDPOINTS ) |
305 { | 312 { |
306 // TODO: do we need to handle IN vs OUT here? | 313 // TODO: do we need to handle IN vs OUT here? |
307 endpoint0_stall(); | 314 endpoint0_stall(); |
311 reply_buffer[1] = 0; | 318 reply_buffer[1] = 0; |
312 if ( *(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4) & 0x02 ) | 319 if ( *(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4) & 0x02 ) |
313 reply_buffer[0] = 1; | 320 reply_buffer[0] = 1; |
314 data = reply_buffer; | 321 data = reply_buffer; |
315 datalen = 2; | 322 datalen = 2; |
316 break; | 323 goto send; |
324 | |
317 case 0x0100: // CLEAR_FEATURE (device) | 325 case 0x0100: // CLEAR_FEATURE (device) |
318 case 0x0101: // CLEAR_FEATURE (interface) | 326 case 0x0101: // CLEAR_FEATURE (interface) |
319 // TODO: Currently ignoring, perhaps useful? -HaaTa | 327 // TODO: Currently ignoring, perhaps useful? -HaaTa |
328 warn_print("CLEAR_FEATURE - Device/Interface"); | |
320 endpoint0_stall(); | 329 endpoint0_stall(); |
321 return; | 330 return; |
331 | |
322 case 0x0102: // CLEAR_FEATURE (interface) | 332 case 0x0102: // CLEAR_FEATURE (interface) |
323 i = setup.wIndex & 0x7F; | 333 i = setup.wIndex & 0x7F; |
324 if ( i > NUM_ENDPOINTS || setup.wValue != 0 ) | 334 if ( i > NUM_ENDPOINTS || setup.wValue != 0 ) |
325 { | 335 { |
326 endpoint0_stall(); | 336 endpoint0_stall(); |
327 return; | 337 return; |
328 } | 338 } |
339 warn_print("CLEAR_FEATURE - Interface"); | |
329 //(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02; | 340 //(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02; |
330 // TODO: do we need to clear the data toggle here? | 341 // TODO: do we need to clear the data toggle here? |
331 //break; | 342 //break; |
332 | 343 |
333 // FIXME: Clearing causes keyboard to freeze, likely an invalid clear | 344 // FIXME: Clearing causes keyboard to freeze, likely an invalid clear |
334 // XXX: Ignoring seems to work, though this may not be the ideal behaviour -HaaTa | 345 // XXX: Ignoring seems to work, though this may not be the ideal behaviour -HaaTa |
335 endpoint0_stall(); | 346 endpoint0_stall(); |
336 return; | 347 return; |
348 | |
337 case 0x0300: // SET_FEATURE (device) | 349 case 0x0300: // SET_FEATURE (device) |
338 case 0x0301: // SET_FEATURE (interface) | 350 case 0x0301: // SET_FEATURE (interface) |
339 // TODO: Currently ignoring, perhaps useful? -HaaTa | 351 // TODO: Currently ignoring, perhaps useful? -HaaTa |
352 warn_print("SET_FEATURE"); | |
340 endpoint0_stall(); | 353 endpoint0_stall(); |
341 return; | 354 return; |
355 | |
342 case 0x0302: // SET_FEATURE (endpoint) | 356 case 0x0302: // SET_FEATURE (endpoint) |
343 i = setup.wIndex & 0x7F; | 357 i = setup.wIndex & 0x7F; |
344 if ( i > NUM_ENDPOINTS || setup.wValue != 0 ) | 358 if ( i > NUM_ENDPOINTS || setup.wValue != 0 ) |
345 { | 359 { |
346 // TODO: do we need to handle IN vs OUT here? | 360 // TODO: do we need to handle IN vs OUT here? |
347 endpoint0_stall(); | 361 endpoint0_stall(); |
348 return; | 362 return; |
349 } | 363 } |
350 (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) |= 0x02; | 364 (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) |= 0x02; |
351 // TODO: do we need to clear the data toggle here? | 365 // TODO: do we need to clear the data toggle here? |
352 break; | 366 goto send; |
367 | |
353 case 0x0680: // GET_DESCRIPTOR | 368 case 0x0680: // GET_DESCRIPTOR |
354 case 0x0681: | 369 case 0x0681: |
355 #ifdef UART_DEBUG | 370 #ifdef UART_DEBUG |
356 print("desc:"); | 371 print("desc:"); |
357 printHex( setup.wValue ); | 372 printHex( setup.wValue ); |
399 return; | 414 return; |
400 | 415 |
401 case 0x2221: // CDC_SET_CONTROL_LINE_STATE | 416 case 0x2221: // CDC_SET_CONTROL_LINE_STATE |
402 usb_cdc_line_rtsdtr = setup.wValue; | 417 usb_cdc_line_rtsdtr = setup.wValue; |
403 //serial_print("set control line state\n"); | 418 //serial_print("set control line state\n"); |
404 endpoint0_stall(); | 419 goto send; |
405 return; | |
406 | 420 |
407 case 0x21A1: // CDC_GET_LINE_CODING | 421 case 0x21A1: // CDC_GET_LINE_CODING |
408 data = (uint8_t*)usb_cdc_line_coding; | 422 data = (uint8_t*)usb_cdc_line_coding; |
409 datalen = sizeof( usb_cdc_line_coding ); | 423 datalen = sizeof( usb_cdc_line_coding ); |
410 goto send; | 424 goto send; |
411 | 425 |
412 case 0x2021: // CDC_SET_LINE_CODING | 426 case 0x2021: // CDC_SET_LINE_CODING |
413 // XXX Needed? | 427 // XXX Needed? |
414 //serial_print("set coding, waiting...\n"); | 428 //serial_print("set coding, waiting...\n"); |
415 endpoint0_stall(); | 429 return; |
416 return; // Cannot stall here (causes issues) | |
417 | 430 |
418 case 0x0921: // HID SET_REPORT | 431 case 0x0921: // HID SET_REPORT |
419 #ifdef UART_DEBUG | 432 #ifdef UART_DEBUG |
420 print("SET_REPORT - "); | 433 warn_msg("SET_REPORT - "); |
421 printHex( setup.wValue ); | 434 printHex( setup.wValue ); |
422 print(" - "); | 435 print(" - "); |
423 printHex( setup.wValue & 0xFF ); | 436 printHex( setup.wValue & 0xFF ); |
424 print( NL ); | 437 print( NL ); |
425 #endif | 438 #endif |
426 USBKeys_LEDs = setup.wValue & 0xFF; | 439 USBKeys_LEDs = setup.wValue & 0xFF; |
440 | |
441 // Must be stall for some reason... -HaaTa | |
427 endpoint0_stall(); | 442 endpoint0_stall(); |
428 return; | 443 return; |
429 | 444 |
430 case 0x01A1: // HID GET_REPORT | 445 case 0x01A1: // HID GET_REPORT |
431 #ifdef UART_DEBUG | 446 #ifdef UART_DEBUG |
432 print("GET_REPORT - "); | 447 print("GET_REPORT - "); |
433 printHex( USBKeys_LEDs ); | 448 printHex( setup.wIndex ); |
434 print(NL); | 449 print(NL); |
435 #endif | 450 #endif |
436 data = (uint8_t*)&USBKeys_LEDs; | 451 // Search through descriptors returning necessary info |
437 datalen = 1; | 452 for ( list = usb_descriptor_list; 1; list++ ) |
438 goto send; | 453 { |
454 if ( list->addr == NULL ) | |
455 break; | |
456 if ( list->wValue != 0x2200 ) | |
457 continue; | |
458 if ( setup.wIndex == list->wIndex ) | |
459 { | |
460 data = list->addr; | |
461 datalen = list->length; | |
462 goto send; | |
463 } | |
464 } | |
465 endpoint0_stall(); | |
466 return; | |
439 | 467 |
440 case 0x0A21: // HID SET_IDLE | 468 case 0x0A21: // HID SET_IDLE |
441 #ifdef UART_DEBUG | 469 #ifdef UART_DEBUG |
442 print("SET_IDLE - "); | 470 print("SET_IDLE - "); |
443 printHex( setup.wValue ); | 471 printHex( setup.wValue ); |
444 print(NL); | 472 print(NL); |
445 #endif | 473 #endif |
446 USBKeys_Idle_Config = (setup.wValue >> 8); | 474 USBKeys_Idle_Config = (setup.wValue >> 8); |
447 USBKeys_Idle_Count = 0; | 475 USBKeys_Idle_Count = 0; |
448 endpoint0_stall(); | 476 goto send; |
449 return; | |
450 | 477 |
451 case 0x0B21: // HID SET_PROTOCOL | 478 case 0x0B21: // HID SET_PROTOCOL |
452 #ifdef UART_DEBUG | 479 #ifdef UART_DEBUG |
453 print("SET_PROTOCOL - "); | 480 print("SET_PROTOCOL - "); |
454 printHex( setup.wValue ); | 481 printHex( setup.wValue ); |
455 print(" - "); | 482 print(" - "); |
456 printHex( setup.wValue & 0xFF ); | 483 printHex( setup.wValue & 0xFF ); |
457 print(NL); | 484 print(NL); |
458 #endif | 485 #endif |
459 USBKeys_Protocol = setup.wValue & 0xFF; // 0 - Boot Mode, 1 - NKRO Mode | 486 USBKeys_Protocol = setup.wValue & 0xFF; // 0 - Boot Mode, 1 - NKRO Mode |
460 endpoint0_stall(); | 487 goto send; |
461 return; | |
462 | 488 |
463 // case 0xC940: | 489 // case 0xC940: |
464 default: | 490 default: |
465 #ifdef UART_DEBUG_UNKNOWN | 491 #ifdef UART_DEBUG_UNKNOWN |
466 print("UNKNOWN"); | 492 print("UNKNOWN"); |
470 } | 496 } |
471 | 497 |
472 send: | 498 send: |
473 #ifdef UART_DEBUG | 499 #ifdef UART_DEBUG |
474 print("setup send "); | 500 print("setup send "); |
475 printHex32((uint32_t)data); | 501 printHex32( (uint32_t)data ); |
476 print(","); | 502 print(","); |
477 printHex(datalen); | 503 for ( uint8_t c = 0; c < datalen; c++ ) |
478 print(NL); | 504 { |
505 printHex( data[c] ); | |
506 print(" "); | |
507 } | |
508 print(","); | |
509 printHex( datalen ); | |
510 print( NL ); | |
479 #endif | 511 #endif |
480 | 512 |
481 if ( datalen > setup.wLength ) | 513 if ( datalen > setup.wLength ) |
482 datalen = setup.wLength; | 514 datalen = setup.wLength; |
483 | 515 |
590 // actually "do" the setup request | 622 // actually "do" the setup request |
591 usb_setup(); | 623 usb_setup(); |
592 // unfreeze the USB, now that we're ready | 624 // unfreeze the USB, now that we're ready |
593 USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit | 625 USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit |
594 break; | 626 break; |
627 | |
595 case 0x01: // OUT transaction received from host | 628 case 0x01: // OUT transaction received from host |
596 case 0x02: | 629 case 0x02: |
597 #ifdef UART_DEBUG | 630 #ifdef UART_DEBUG |
598 print("PID=OUT"NL); | 631 print("PID=OUT"NL); |
599 #endif | 632 #endif |
661 #endif | 694 #endif |
662 USB0_ADDR = setup.wValue; | 695 USB0_ADDR = setup.wValue; |
663 } | 696 } |
664 | 697 |
665 break; | 698 break; |
699 | |
666 default: | 700 default: |
667 #ifdef UART_DEBUG | 701 #ifdef UART_DEBUG |
668 print("PID=unknown:"); | 702 print("PID=unknown:"); |
669 printHex(pid); | 703 printHex(pid); |
670 print(NL); | 704 print(NL); |