diff options
Diffstat (limited to 'tmk_core/protocol/vusb/vusb.c')
| -rw-r--r-- | tmk_core/protocol/vusb/vusb.c | 144 |
1 files changed, 64 insertions, 80 deletions
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 5feff889a..77bbbd7bd 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c | |||
| @@ -15,10 +15,12 @@ You should have received a copy of the GNU General Public License | |||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <avr/wdt.h> | ||
| 19 | #include <util/delay.h> | ||
| 20 | #include <stdint.h> | 18 | #include <stdint.h> |
| 19 | |||
| 20 | #include <avr/wdt.h> | ||
| 21 | |||
| 21 | #include <usbdrv/usbdrv.h> | 22 | #include <usbdrv/usbdrv.h> |
| 23 | |||
| 22 | #include "usbconfig.h" | 24 | #include "usbconfig.h" |
| 23 | #include "host.h" | 25 | #include "host.h" |
| 24 | #include "report.h" | 26 | #include "report.h" |
| @@ -26,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 26 | #include "vusb.h" | 28 | #include "vusb.h" |
| 27 | #include "print.h" | 29 | #include "print.h" |
| 28 | #include "debug.h" | 30 | #include "debug.h" |
| 31 | #include "wait.h" | ||
| 29 | #include "usb_descriptor_common.h" | 32 | #include "usb_descriptor_common.h" |
| 30 | 33 | ||
| 31 | #ifdef RAW_ENABLE | 34 | #ifdef RAW_ENABLE |
| @@ -56,16 +59,20 @@ enum usb_interfaces { | |||
| 56 | #ifdef CONSOLE_ENABLE | 59 | #ifdef CONSOLE_ENABLE |
| 57 | CONSOLE_INTERFACE = NEXT_INTERFACE, | 60 | CONSOLE_INTERFACE = NEXT_INTERFACE, |
| 58 | #endif | 61 | #endif |
| 59 | TOTAL_INTERFACES = NEXT_INTERFACE, | 62 | TOTAL_INTERFACES = NEXT_INTERFACE |
| 60 | }; | 63 | }; |
| 61 | 64 | ||
| 62 | #define MAX_INTERFACES 2 | 65 | #define MAX_INTERFACES 3 |
| 63 | 66 | ||
| 64 | #if (NEXT_INTERFACE - 1) > MAX_INTERFACES | 67 | #if (NEXT_INTERFACE - 1) > MAX_INTERFACES |
| 65 | # error There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console | 68 | # error There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console |
| 66 | #endif | 69 | #endif |
| 67 | 70 | ||
| 68 | static uint8_t vusb_keyboard_leds = 0; | 71 | #if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && CONSOLE_ENABLE |
| 72 | # error Mouse/Extra Keys share an endpoint with Console. Please disable one of the two. | ||
| 73 | #endif | ||
| 74 | |||
| 75 | static uint8_t keyboard_led_state = 0; | ||
| 69 | static uint8_t vusb_idle_rate = 0; | 76 | static uint8_t vusb_idle_rate = 0; |
| 70 | 77 | ||
| 71 | /* Keyboard report send buffer */ | 78 | /* Keyboard report send buffer */ |
| @@ -74,13 +81,7 @@ static report_keyboard_t kbuf[KBUF_SIZE]; | |||
| 74 | static uint8_t kbuf_head = 0; | 81 | static uint8_t kbuf_head = 0; |
| 75 | static uint8_t kbuf_tail = 0; | 82 | static uint8_t kbuf_tail = 0; |
| 76 | 83 | ||
| 77 | typedef struct { | 84 | static report_keyboard_t keyboard_report_sent; |
| 78 | uint8_t modifier; | ||
| 79 | uint8_t reserved; | ||
| 80 | uint8_t keycode[6]; | ||
| 81 | } keyboard_report_t; | ||
| 82 | |||
| 83 | static keyboard_report_t keyboard_report; // sent to PC | ||
| 84 | 85 | ||
| 85 | #define VUSB_TRANSFER_KEYBOARD_MAX_TRIES 10 | 86 | #define VUSB_TRANSFER_KEYBOARD_MAX_TRIES 10 |
| 86 | 87 | ||
| @@ -92,19 +93,13 @@ void vusb_transfer_keyboard(void) { | |||
| 92 | usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); | 93 | usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); |
| 93 | kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; | 94 | kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; |
| 94 | if (debug_keyboard) { | 95 | if (debug_keyboard) { |
| 95 | print("V-USB: kbuf["); | 96 | dprintf("V-USB: kbuf[%d->%d](%02X)\n", kbuf_tail, kbuf_head, (kbuf_head < kbuf_tail) ? (KBUF_SIZE - kbuf_tail + kbuf_head) : (kbuf_head - kbuf_tail)); |
| 96 | pdec(kbuf_tail); | ||
| 97 | print("->"); | ||
| 98 | pdec(kbuf_head); | ||
| 99 | print("]("); | ||
| 100 | phex((kbuf_head < kbuf_tail) ? (KBUF_SIZE - kbuf_tail + kbuf_head) : (kbuf_head - kbuf_tail)); | ||
| 101 | print(")\n"); | ||
| 102 | } | 97 | } |
| 103 | } | 98 | } |
| 104 | break; | 99 | break; |
| 105 | } | 100 | } |
| 106 | usbPoll(); | 101 | usbPoll(); |
| 107 | _delay_ms(1); | 102 | wait_ms(1); |
| 108 | } | 103 | } |
| 109 | } | 104 | } |
| 110 | 105 | ||
| @@ -125,16 +120,16 @@ void raw_hid_send(uint8_t *data, uint8_t length) { | |||
| 125 | 120 | ||
| 126 | uint8_t *temp = data; | 121 | uint8_t *temp = data; |
| 127 | for (uint8_t i = 0; i < 4; i++) { | 122 | for (uint8_t i = 0; i < 4; i++) { |
| 128 | while (!usbInterruptIsReady3()) { | 123 | while (!usbInterruptIsReady4()) { |
| 129 | usbPoll(); | 124 | usbPoll(); |
| 130 | } | 125 | } |
| 131 | usbSetInterrupt3(temp, 8); | 126 | usbSetInterrupt4(temp, 8); |
| 132 | temp += 8; | 127 | temp += 8; |
| 133 | } | 128 | } |
| 134 | while (!usbInterruptIsReady3()) { | 129 | while (!usbInterruptIsReady4()) { |
| 135 | usbPoll(); | 130 | usbPoll(); |
| 136 | } | 131 | } |
| 137 | usbSetInterrupt3(0, 0); | 132 | usbSetInterrupt4(0, 0); |
| 138 | } | 133 | } |
| 139 | 134 | ||
| 140 | __attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { | 135 | __attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { |
| @@ -218,7 +213,7 @@ static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_sy | |||
| 218 | 213 | ||
| 219 | host_driver_t *vusb_driver(void) { return &driver; } | 214 | host_driver_t *vusb_driver(void) { return &driver; } |
| 220 | 215 | ||
| 221 | static uint8_t keyboard_leds(void) { return vusb_keyboard_leds; } | 216 | static uint8_t keyboard_leds(void) { return keyboard_led_state; } |
| 222 | 217 | ||
| 223 | static void send_keyboard(report_keyboard_t *report) { | 218 | static void send_keyboard(report_keyboard_t *report) { |
| 224 | uint8_t next = (kbuf_head + 1) % KBUF_SIZE; | 219 | uint8_t next = (kbuf_head + 1) % KBUF_SIZE; |
| @@ -226,12 +221,13 @@ static void send_keyboard(report_keyboard_t *report) { | |||
| 226 | kbuf[kbuf_head] = *report; | 221 | kbuf[kbuf_head] = *report; |
| 227 | kbuf_head = next; | 222 | kbuf_head = next; |
| 228 | } else { | 223 | } else { |
| 229 | debug("kbuf: full\n"); | 224 | dprint("kbuf: full\n"); |
| 230 | } | 225 | } |
| 231 | 226 | ||
| 232 | // NOTE: send key strokes of Macro | 227 | // NOTE: send key strokes of Macro |
| 233 | usbPoll(); | 228 | usbPoll(); |
| 234 | vusb_transfer_keyboard(); | 229 | vusb_transfer_keyboard(); |
| 230 | keyboard_report_sent = *report; | ||
| 235 | } | 231 | } |
| 236 | 232 | ||
| 237 | typedef struct { | 233 | typedef struct { |
| @@ -288,36 +284,35 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) { | |||
| 288 | 284 | ||
| 289 | if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { /* class request type */ | 285 | if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { /* class request type */ |
| 290 | if (rq->bRequest == USBRQ_HID_GET_REPORT) { | 286 | if (rq->bRequest == USBRQ_HID_GET_REPORT) { |
| 291 | debug("GET_REPORT:"); | 287 | dprint("GET_REPORT:"); |
| 292 | /* we only have one report type, so don't look at wValue */ | 288 | if (rq->wIndex.word == KEYBOARD_INTERFACE) { |
| 293 | usbMsgPtr = (usbMsgPtr_t)&keyboard_report; | 289 | usbMsgPtr = (usbMsgPtr_t)&keyboard_report_sent; |
| 294 | return sizeof(keyboard_report); | 290 | return sizeof(keyboard_report_sent); |
| 291 | } | ||
| 295 | } else if (rq->bRequest == USBRQ_HID_GET_IDLE) { | 292 | } else if (rq->bRequest == USBRQ_HID_GET_IDLE) { |
| 296 | debug("GET_IDLE: "); | 293 | dprint("GET_IDLE:"); |
| 297 | // debug_hex(vusb_idle_rate); | ||
| 298 | usbMsgPtr = (usbMsgPtr_t)&vusb_idle_rate; | 294 | usbMsgPtr = (usbMsgPtr_t)&vusb_idle_rate; |
| 299 | return 1; | 295 | return 1; |
| 300 | } else if (rq->bRequest == USBRQ_HID_SET_IDLE) { | 296 | } else if (rq->bRequest == USBRQ_HID_SET_IDLE) { |
| 301 | vusb_idle_rate = rq->wValue.bytes[1]; | 297 | vusb_idle_rate = rq->wValue.bytes[1]; |
| 302 | debug("SET_IDLE: "); | 298 | dprintf("SET_IDLE: %02X", vusb_idle_rate); |
| 303 | debug_hex(vusb_idle_rate); | ||
| 304 | } else if (rq->bRequest == USBRQ_HID_SET_REPORT) { | 299 | } else if (rq->bRequest == USBRQ_HID_SET_REPORT) { |
| 305 | debug("SET_REPORT: "); | 300 | dprint("SET_REPORT:"); |
| 306 | // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard) | 301 | // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard) |
| 307 | if (rq->wValue.word == 0x0200 && rq->wIndex.word == 0) { | 302 | if (rq->wValue.word == 0x0200 && rq->wIndex.word == KEYBOARD_INTERFACE) { |
| 308 | debug("SET_LED: "); | 303 | dprint("SET_LED:"); |
| 309 | last_req.kind = SET_LED; | 304 | last_req.kind = SET_LED; |
| 310 | last_req.len = rq->wLength.word; | 305 | last_req.len = rq->wLength.word; |
| 311 | } | 306 | } |
| 312 | return USB_NO_MSG; // to get data in usbFunctionWrite | 307 | return USB_NO_MSG; // to get data in usbFunctionWrite |
| 313 | } else { | 308 | } else { |
| 314 | debug("UNKNOWN:"); | 309 | dprint("UNKNOWN:"); |
| 315 | } | 310 | } |
| 316 | } else { | 311 | } else { |
| 317 | debug("VENDOR:"); | 312 | dprint("VENDOR:"); |
| 318 | /* no vendor specific requests implemented */ | 313 | /* no vendor specific requests implemented */ |
| 319 | } | 314 | } |
| 320 | debug("\n"); | 315 | dprint("\n"); |
| 321 | return 0; /* default for not implemented requests: return no data back to host */ | 316 | return 0; /* default for not implemented requests: return no data back to host */ |
| 322 | } | 317 | } |
| 323 | 318 | ||
| @@ -327,10 +322,8 @@ uchar usbFunctionWrite(uchar *data, uchar len) { | |||
| 327 | } | 322 | } |
| 328 | switch (last_req.kind) { | 323 | switch (last_req.kind) { |
| 329 | case SET_LED: | 324 | case SET_LED: |
| 330 | debug("SET_LED: "); | 325 | dprintf("SET_LED: %02X\n", data[0]); |
| 331 | debug_hex(data[0]); | 326 | keyboard_led_state = data[0]; |
| 332 | debug("\n"); | ||
| 333 | vusb_keyboard_leds = data[0]; | ||
| 334 | last_req.len = 0; | 327 | last_req.len = 0; |
| 335 | return 1; | 328 | return 1; |
| 336 | break; | 329 | break; |
| @@ -346,13 +339,13 @@ void usbFunctionWriteOut(uchar *data, uchar len) { | |||
| 346 | #ifdef RAW_ENABLE | 339 | #ifdef RAW_ENABLE |
| 347 | // Data from host must be divided every 8bytes | 340 | // Data from host must be divided every 8bytes |
| 348 | if (len != 8) { | 341 | if (len != 8) { |
| 349 | debug("RAW: invalid length"); | 342 | dprint("RAW: invalid length\n"); |
| 350 | raw_output_received_bytes = 0; | 343 | raw_output_received_bytes = 0; |
| 351 | return; | 344 | return; |
| 352 | } | 345 | } |
| 353 | 346 | ||
| 354 | if (raw_output_received_bytes + len > RAW_BUFFER_SIZE) { | 347 | if (raw_output_received_bytes + len > RAW_BUFFER_SIZE) { |
| 355 | debug("RAW: buffer full"); | 348 | dprint("RAW: buffer full\n"); |
| 356 | raw_output_received_bytes = 0; | 349 | raw_output_received_bytes = 0; |
| 357 | } else { | 350 | } else { |
| 358 | for (uint8_t i = 0; i < 8; i++) { | 351 | for (uint8_t i = 0; i < 8; i++) { |
| @@ -408,29 +401,6 @@ const PROGMEM uchar keyboard_hid_report[] = { | |||
| 408 | 0xC0 // End Collection | 401 | 0xC0 // End Collection |
| 409 | }; | 402 | }; |
| 410 | 403 | ||
| 411 | #ifdef RAW_ENABLE | ||
| 412 | const PROGMEM uchar raw_hid_report[] = { | ||
| 413 | 0x06, RAW_USAGE_PAGE_LO, RAW_USAGE_PAGE_HI, // Usage Page (Vendor Defined) | ||
| 414 | 0x09, RAW_USAGE_ID, // Usage (Vendor Defined) | ||
| 415 | 0xA1, 0x01, // Collection (Application) | ||
| 416 | // Data to host | ||
| 417 | 0x09, 0x62, // Usage (Vendor Defined) | ||
| 418 | 0x15, 0x00, // Logical Minimum (0) | ||
| 419 | 0x26, 0xFF, 0x00, // Logical Maximum (255) | ||
| 420 | 0x95, RAW_BUFFER_SIZE, // Report Count | ||
| 421 | 0x75, 0x08, // Report Size (8) | ||
| 422 | 0x81, 0x02, // Input (Data, Variable, Absolute) | ||
| 423 | // Data from host | ||
| 424 | 0x09, 0x63, // Usage (Vendor Defined) | ||
| 425 | 0x15, 0x00, // Logical Minimum (0) | ||
| 426 | 0x26, 0xFF, 0x00, // Logical Maximum (255) | ||
| 427 | 0x95, RAW_BUFFER_SIZE, // Report Count | ||
| 428 | 0x75, 0x08, // Report Size (8) | ||
| 429 | 0x91, 0x02, // Output (Data, Variable, Absolute) | ||
| 430 | 0xC0 // End Collection | ||
| 431 | }; | ||
| 432 | #endif | ||
| 433 | |||
| 434 | #if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) | 404 | #if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) |
| 435 | const PROGMEM uchar mouse_extra_hid_report[] = { | 405 | const PROGMEM uchar mouse_extra_hid_report[] = { |
| 436 | # ifdef MOUSE_ENABLE | 406 | # ifdef MOUSE_ENABLE |
| @@ -515,6 +485,29 @@ const PROGMEM uchar mouse_extra_hid_report[] = { | |||
| 515 | }; | 485 | }; |
| 516 | #endif | 486 | #endif |
| 517 | 487 | ||
| 488 | #ifdef RAW_ENABLE | ||
| 489 | const PROGMEM uchar raw_hid_report[] = { | ||
| 490 | 0x06, RAW_USAGE_PAGE_LO, RAW_USAGE_PAGE_HI, // Usage Page (Vendor Defined) | ||
| 491 | 0x09, RAW_USAGE_ID, // Usage (Vendor Defined) | ||
| 492 | 0xA1, 0x01, // Collection (Application) | ||
| 493 | // Data to host | ||
| 494 | 0x09, 0x62, // Usage (Vendor Defined) | ||
| 495 | 0x15, 0x00, // Logical Minimum (0) | ||
| 496 | 0x26, 0xFF, 0x00, // Logical Maximum (255) | ||
| 497 | 0x95, RAW_BUFFER_SIZE, // Report Count | ||
| 498 | 0x75, 0x08, // Report Size (8) | ||
| 499 | 0x81, 0x02, // Input (Data, Variable, Absolute) | ||
| 500 | // Data from host | ||
| 501 | 0x09, 0x63, // Usage (Vendor Defined) | ||
| 502 | 0x15, 0x00, // Logical Minimum (0) | ||
| 503 | 0x26, 0xFF, 0x00, // Logical Maximum (255) | ||
| 504 | 0x95, RAW_BUFFER_SIZE, // Report Count | ||
| 505 | 0x75, 0x08, // Report Size (8) | ||
| 506 | 0x91, 0x02, // Output (Data, Variable, Absolute) | ||
| 507 | 0xC0 // End Collection | ||
| 508 | }; | ||
| 509 | #endif | ||
| 510 | |||
| 518 | #if defined(CONSOLE_ENABLE) | 511 | #if defined(CONSOLE_ENABLE) |
| 519 | const PROGMEM uchar console_hid_report[] = { | 512 | const PROGMEM uchar console_hid_report[] = { |
| 520 | 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined - PJRC Teensy compatible) | 513 | 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined - PJRC Teensy compatible) |
| @@ -694,7 +687,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = { | |||
| 694 | .bLength = sizeof(usbEndpointDescriptor_t), | 687 | .bLength = sizeof(usbEndpointDescriptor_t), |
| 695 | .bDescriptorType = USBDESCR_ENDPOINT | 688 | .bDescriptorType = USBDESCR_ENDPOINT |
| 696 | }, | 689 | }, |
| 697 | .bEndpointAddress = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP3_NUMBER), | 690 | .bEndpointAddress = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP4_NUMBER), |
| 698 | .bmAttributes = 0x03, | 691 | .bmAttributes = 0x03, |
| 699 | .wMaxPacketSize = RAW_EPSIZE, | 692 | .wMaxPacketSize = RAW_EPSIZE, |
| 700 | .bInterval = USB_POLLING_INTERVAL_MS | 693 | .bInterval = USB_POLLING_INTERVAL_MS |
| @@ -704,7 +697,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = { | |||
| 704 | .bLength = sizeof(usbEndpointDescriptor_t), | 697 | .bLength = sizeof(usbEndpointDescriptor_t), |
| 705 | .bDescriptorType = USBDESCR_ENDPOINT | 698 | .bDescriptorType = USBDESCR_ENDPOINT |
| 706 | }, | 699 | }, |
| 707 | .bEndpointAddress = (USBRQ_DIR_HOST_TO_DEVICE | USB_CFG_EP3_NUMBER), | 700 | .bEndpointAddress = (USBRQ_DIR_HOST_TO_DEVICE | USB_CFG_EP4_NUMBER), |
| 708 | .bmAttributes = 0x03, | 701 | .bmAttributes = 0x03, |
| 709 | .wMaxPacketSize = RAW_EPSIZE, | 702 | .wMaxPacketSize = RAW_EPSIZE, |
| 710 | .bInterval = USB_POLLING_INTERVAL_MS | 703 | .bInterval = USB_POLLING_INTERVAL_MS |
| @@ -805,14 +798,6 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = { | |||
| 805 | USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { | 798 | USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { |
| 806 | usbMsgLen_t len = 0; | 799 | usbMsgLen_t len = 0; |
| 807 | 800 | ||
| 808 | /* | ||
| 809 | debug("usbFunctionDescriptor: "); | ||
| 810 | debug_hex(rq->bmRequestType); debug(" "); | ||
| 811 | debug_hex(rq->bRequest); debug(" "); | ||
| 812 | debug_hex16(rq->wValue.word); debug(" "); | ||
| 813 | debug_hex16(rq->wIndex.word); debug(" "); | ||
| 814 | debug_hex16(rq->wLength.word); debug("\n"); | ||
| 815 | */ | ||
| 816 | switch (rq->wValue.bytes[1]) { | 801 | switch (rq->wValue.bytes[1]) { |
| 817 | case USBDESCR_DEVICE: | 802 | case USBDESCR_DEVICE: |
| 818 | usbMsgPtr = (usbMsgPtr_t)&usbDeviceDescriptor; | 803 | usbMsgPtr = (usbMsgPtr_t)&usbDeviceDescriptor; |
| @@ -896,6 +881,5 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { | |||
| 896 | } | 881 | } |
| 897 | break; | 882 | break; |
| 898 | } | 883 | } |
| 899 | // debug("desc len: "); debug_hex(len); debug("\n"); | ||
| 900 | return len; | 884 | return len; |
| 901 | } | 885 | } |
