diff options
Diffstat (limited to 'usb.c')
| -rw-r--r-- | usb.c | 53 |
1 files changed, 45 insertions, 8 deletions
| @@ -21,6 +21,8 @@ | |||
| 21 | * THE SOFTWARE. | 21 | * THE SOFTWARE. |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include <stdint.h> | ||
| 25 | #include <stdbool.h> | ||
| 24 | #include <avr/io.h> | 26 | #include <avr/io.h> |
| 25 | #include <avr/pgmspace.h> | 27 | #include <avr/pgmspace.h> |
| 26 | #include <avr/interrupt.h> | 28 | #include <avr/interrupt.h> |
| @@ -82,6 +84,9 @@ | |||
| 82 | 84 | ||
| 83 | #define ENDPOINT0_SIZE 32 | 85 | #define ENDPOINT0_SIZE 32 |
| 84 | 86 | ||
| 87 | bool remote_wakeup = false; | ||
| 88 | bool suspend = false; | ||
| 89 | |||
| 85 | // 0:control endpoint is enabled automatically by controller. | 90 | // 0:control endpoint is enabled automatically by controller. |
| 86 | static const uint8_t PROGMEM endpoint_config_table[] = { | 91 | static const uint8_t PROGMEM endpoint_config_table[] = { |
| 87 | // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation) | 92 | // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation) |
| @@ -250,7 +255,7 @@ static uint8_t PROGMEM debug_hid_report_desc[] = { | |||
| 250 | 0xC0 // end collection | 255 | 0xC0 // end collection |
| 251 | }; | 256 | }; |
| 252 | 257 | ||
| 253 | // audio controls(consumer page) | 258 | // audio controls & system controls |
| 254 | // http://www.microsoft.com/whdc/archive/w2kbd.mspx | 259 | // http://www.microsoft.com/whdc/archive/w2kbd.mspx |
| 255 | static uint8_t PROGMEM extra_hid_report_desc[] = { | 260 | static uint8_t PROGMEM extra_hid_report_desc[] = { |
| 256 | 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) | 261 | 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) |
| @@ -272,6 +277,18 @@ static uint8_t PROGMEM extra_hid_report_desc[] = { | |||
| 272 | 0x81, 0x06, // INPUT (Data,Var,Rel) | 277 | 0x81, 0x06, // INPUT (Data,Var,Rel) |
| 273 | 0x95, 0x05, // REPORT_COUNT (5) | 278 | 0x95, 0x05, // REPORT_COUNT (5) |
| 274 | 0x81, 0x07, // INPUT (Cnst,Var,Abs) | 279 | 0x81, 0x07, // INPUT (Cnst,Var,Abs) |
| 280 | 0xc0, // END_COLLECTION | ||
| 281 | |||
| 282 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) | ||
| 283 | 0x09, 0x80, // USAGE (System Control) | ||
| 284 | 0xa1, 0x01, // COLLECTION (Application) | ||
| 285 | 0x85, 0x02, // REPORT_ID (2) | ||
| 286 | 0x19, 0x81, // USAGE_MINIMUM (System Power Down) | ||
| 287 | 0x29, 0x83, // USAGE_MAXIMUM (System Wake Up) | ||
| 288 | 0x95, 0x03, // REPORT_COUNT (3) | ||
| 289 | 0x81, 0x06, // INPUT (Data,Var,Rel) | ||
| 290 | 0x95, 0x05, // REPORT_COUNT (5) | ||
| 291 | 0x81, 0x07, // INPUT (Cnst,Var,Rel) | ||
| 275 | 0xc0 // END_COLLECTION | 292 | 0xc0 // END_COLLECTION |
| 276 | }; | 293 | }; |
| 277 | 294 | ||
| @@ -289,7 +306,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { | |||
| 289 | 4, // bNumInterfaces | 306 | 4, // bNumInterfaces |
| 290 | 1, // bConfigurationValue | 307 | 1, // bConfigurationValue |
| 291 | 0, // iConfiguration | 308 | 0, // iConfiguration |
| 292 | 0xC0, // bmAttributes | 309 | 0xA0, // bmAttributes |
| 293 | 50, // bMaxPower | 310 | 50, // bMaxPower |
| 294 | 311 | ||
| 295 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | 312 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 |
| @@ -484,7 +501,7 @@ void usb_init(void) | |||
| 484 | USB_CONFIG(); // start USB clock | 501 | USB_CONFIG(); // start USB clock |
| 485 | UDCON = 0; // enable attach resistor | 502 | UDCON = 0; // enable attach resistor |
| 486 | usb_configuration = 0; | 503 | usb_configuration = 0; |
| 487 | UDIEN = (1<<EORSTE)|(1<<SOFE); | 504 | UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE); |
| 488 | sei(); | 505 | sei(); |
| 489 | } | 506 | } |
| 490 | 507 | ||
| @@ -492,7 +509,12 @@ void usb_init(void) | |||
| 492 | // number selected by the HOST | 509 | // number selected by the HOST |
| 493 | uint8_t usb_configured(void) | 510 | uint8_t usb_configured(void) |
| 494 | { | 511 | { |
| 495 | return usb_configuration; | 512 | return usb_configuration && !suspend; |
| 513 | } | ||
| 514 | |||
| 515 | void usb_remote_wakeup(void) | ||
| 516 | { | ||
| 517 | UDCON |= (1<<RMWKUP); | ||
| 496 | } | 518 | } |
| 497 | 519 | ||
| 498 | 520 | ||
| @@ -515,6 +537,11 @@ ISR(USB_GEN_vect) | |||
| 515 | 537 | ||
| 516 | intbits = UDINT; | 538 | intbits = UDINT; |
| 517 | UDINT = 0; | 539 | UDINT = 0; |
| 540 | if (intbits & (1<<SUSPI)) { | ||
| 541 | suspend = true; | ||
| 542 | } else { | ||
| 543 | suspend = false; | ||
| 544 | } | ||
| 518 | if (intbits & (1<<EORSTI)) { | 545 | if (intbits & (1<<EORSTI)) { |
| 519 | UENUM = 0; | 546 | UENUM = 0; |
| 520 | UECONX = 1; | 547 | UECONX = 1; |
| @@ -693,9 +720,9 @@ ISR(USB_COM_vect) | |||
| 693 | usb_send_in(); | 720 | usb_send_in(); |
| 694 | return; | 721 | return; |
| 695 | } | 722 | } |
| 696 | #ifdef SUPPORT_ENDPOINT_HALT | 723 | if (bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) { |
| 697 | if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) | 724 | #ifdef SUPPORT_ENDPOINT_HALT |
| 698 | && bmRequestType == 0x02 && wValue == 0) { | 725 | if (bmRequestType == 0x02 && wValue == ENDPOINT_HALT) { |
| 699 | i = wIndex & 0x7F; | 726 | i = wIndex & 0x7F; |
| 700 | if (i >= 1 && i <= MAX_ENDPOINT) { | 727 | if (i >= 1 && i <= MAX_ENDPOINT) { |
| 701 | usb_send_in(); | 728 | usb_send_in(); |
| @@ -709,8 +736,18 @@ ISR(USB_COM_vect) | |||
| 709 | } | 736 | } |
| 710 | return; | 737 | return; |
| 711 | } | 738 | } |
| 739 | } | ||
| 740 | #endif | ||
| 741 | if (bmRequestType == 0x00 && wValue == DEVICE_REMOTE_WAKEUP) { | ||
| 742 | if (bRequest == SET_FEATURE) { | ||
| 743 | remote_wakeup = true; | ||
| 744 | } else { | ||
| 745 | remote_wakeup = false; | ||
| 746 | } | ||
| 747 | usb_send_in(); | ||
| 748 | return; | ||
| 749 | } | ||
| 712 | } | 750 | } |
| 713 | #endif | ||
| 714 | if (wIndex == KEYBOARD_INTERFACE) { | 751 | if (wIndex == KEYBOARD_INTERFACE) { |
| 715 | if (bmRequestType == 0xA1) { | 752 | if (bmRequestType == 0xA1) { |
| 716 | if (bRequest == HID_GET_REPORT) { | 753 | if (bRequest == HID_GET_REPORT) { |
