summaryrefslogtreecommitdiff
path: root/firmware/usbstack/usb_hid.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/usb_hid.c')
-rw-r--r--firmware/usbstack/usb_hid.c86
1 files changed, 63 insertions, 23 deletions
diff --git a/firmware/usbstack/usb_hid.c b/firmware/usbstack/usb_hid.c
index 0b672e6452..5885b60e32 100644
--- a/firmware/usbstack/usb_hid.c
+++ b/firmware/usbstack/usb_hid.c
@@ -42,6 +42,7 @@
42/* HID main items (HID1_11.pdf, page 38) */ 42/* HID main items (HID1_11.pdf, page 38) */
43#define INPUT 0x80 43#define INPUT 0x80
44#define OUTPUT 0x90 44#define OUTPUT 0x90
45#define FEATURE 0xB0
45#define COLLECTION 0xA0 46#define COLLECTION 0xA0
46#define COLLECTION_PHYSICAL 0x00 47#define COLLECTION_PHYSICAL 0x00
47#define COLLECTION_APPLICATION 0x01 48#define COLLECTION_APPLICATION 0x01
@@ -90,6 +91,7 @@
90#define HID_BUF_SIZE_REPORT 160 91#define HID_BUF_SIZE_REPORT 160
91#define HID_NUM_BUFFERS 5 92#define HID_NUM_BUFFERS 5
92#define SET_REPORT_BUF_LEN 2 93#define SET_REPORT_BUF_LEN 2
94#define GET_REPORT_BUF_LEN 2
93 95
94#ifdef LOGF_ENABLE 96#ifdef LOGF_ENABLE
95 97
@@ -103,6 +105,8 @@
103#define HID_BUF_INC(i) do { (i) = ((i) + 1) % HID_NUM_BUFFERS; } while (0) 105#define HID_BUF_INC(i) do { (i) = ((i) + 1) % HID_NUM_BUFFERS; } while (0)
104#define PACK_VAL(dest, val) *(dest)++ = (val) & 0xff 106#define PACK_VAL(dest, val) *(dest)++ = (val) & 0xff
105 107
108#define REPORT_ID_BACKGROUND REPORT_ID_COUNT
109
106typedef enum 110typedef enum
107{ 111{
108 REPORT_ID_KEYBOARD = 1, 112 REPORT_ID_KEYBOARD = 1,
@@ -110,7 +114,6 @@ typedef enum
110#ifdef HAVE_USB_HID_MOUSE 114#ifdef HAVE_USB_HID_MOUSE
111 REPORT_ID_MOUSE, 115 REPORT_ID_MOUSE,
112#endif 116#endif
113 REPORT_ID_BACKGROUND,
114 REPORT_ID_COUNT, 117 REPORT_ID_COUNT,
115} report_id_t; 118} report_id_t;
116 119
@@ -452,15 +455,6 @@ static uint8_t buf_set_mouse(unsigned char *buf, int id)
452} 455}
453#endif /* HAVE_USB_HID_MOUSE */ 456#endif /* HAVE_USB_HID_MOUSE */
454 457
455#define BUF_LEN_BACKGROUND 1
456static uint8_t buf_set_background(unsigned char *buf, int id)
457{
458 memset(buf, 0, BUF_LEN_BACKGROUND);
459 buf[0] = (uint8_t)id;
460
461 return BUF_LEN_BACKGROUND;
462}
463
464static size_t descriptor_report_get(unsigned char *dest) 458static size_t descriptor_report_get(unsigned char *dest)
465{ 459{
466 unsigned char *report = dest; 460 unsigned char *report = dest;
@@ -562,22 +556,25 @@ static size_t descriptor_report_get(unsigned char *dest)
562 PACK_VAL(report, END_COLLECTION); 556 PACK_VAL(report, END_COLLECTION);
563#endif /* HAVE_USB_HID_MOUSE */ 557#endif /* HAVE_USB_HID_MOUSE */
564 558
565 /* Background controls */ 559 /* Background reports */
566 usb_hid_report = &usb_hid_reports[REPORT_ID_BACKGROUND];
567 usb_hid_report->usage_page = HID_USAGE_PAGE_GENERIC_DEVICE_CONTROLS;
568 usb_hid_report->buf_set = buf_set_background;
569 usb_hid_report->is_key_released = 0;
570
571 pack_parameter(&report, 0, 1, USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DEVICE_CONTROLS); 560 pack_parameter(&report, 0, 1, USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DEVICE_CONTROLS);
572 pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_BACKGROUND_CONTROLS); 561 pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_BACKGROUND_CONTROLS);
573 pack_parameter(&report, 0, 1, COLLECTION, COLLECTION_APPLICATION); 562 pack_parameter(&report, 0, 1, COLLECTION, COLLECTION_APPLICATION);
574 pack_parameter(&report, 0, 1, REPORT_ID, REPORT_ID_BACKGROUND); 563 pack_parameter(&report, 0, 1, REPORT_ID, REPORT_ID_BACKGROUND);
564 /* Padding */
565 pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_UNDEFINED);
566 pack_parameter(&report, 0, 1, LOGICAL_MINIMUM, 0);
567 pack_parameter(&report, 0, 1, LOGICAL_MAXIMUM, 255);
568 pack_parameter(&report, 0, 1, REPORT_SIZE, 8);
569 pack_parameter(&report, 0, 1, REPORT_COUNT, 1);
570 pack_parameter(&report, 0, 1, FEATURE, MAIN_ITEM_CONSTANT);
571 /* Battery percentage */
575 pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_BATTERY_STRENGTH); 572 pack_parameter(&report, 0, 0, CONSUMER_USAGE, HID_GENERIC_DEVICE_BATTERY_STRENGTH);
576 pack_parameter(&report, 0, 1, LOGICAL_MINIMUM, 0); 573 pack_parameter(&report, 0, 1, LOGICAL_MINIMUM, 0);
577 pack_parameter(&report, 0, 1, LOGICAL_MAXIMUM, 100); 574 pack_parameter(&report, 0, 1, LOGICAL_MAXIMUM, 100);
578 pack_parameter(&report, 0, 1, REPORT_SIZE, 8); 575 pack_parameter(&report, 0, 1, REPORT_SIZE, 8);
579 pack_parameter(&report, 0, 1, REPORT_COUNT, 1); 576 pack_parameter(&report, 0, 1, REPORT_COUNT, 1);
580 pack_parameter(&report, 0, 1, INPUT, MAIN_ITEM_VARIABLE); 577 pack_parameter(&report, 0, 1, FEATURE, MAIN_ITEM_VARIABLE);
581 PACK_VAL(report, END_COLLECTION); 578 PACK_VAL(report, END_COLLECTION);
582 579
583 return (size_t)(report - dest); 580 return (size_t)(report - dest);
@@ -622,7 +619,6 @@ void usb_hid_init_connection(void)
622 logf("hid: init connection"); 619 logf("hid: init connection");
623 active = true; 620 active = true;
624 currently_sending = false; 621 currently_sending = false;
625 set_battery_reporting(true);
626} 622}
627 623
628/* called by usb_core_init() */ 624/* called by usb_core_init() */
@@ -643,7 +639,6 @@ void usb_hid_init(void)
643void usb_hid_disconnect(void) 639void usb_hid_disconnect(void)
644{ 640{
645 logf("hid: disconnect"); 641 logf("hid: disconnect");
646 set_battery_reporting(false);
647 active = false; 642 active = false;
648 currently_sending = false; 643 currently_sending = false;
649} 644}
@@ -677,7 +672,7 @@ static int usb_hid_set_report(struct usb_ctrlrequest *req)
677 672
678 if ((req->wValue >> 8) != REPORT_TYPE_OUTPUT) 673 if ((req->wValue >> 8) != REPORT_TYPE_OUTPUT)
679 { 674 {
680 logf("Unsopported report type"); 675 logf("Unsupported report type");
681 return 1; 676 return 1;
682 } 677 }
683 if ((req->wValue & 0xff) != REPORT_ID_KEYBOARD) 678 if ((req->wValue & 0xff) != REPORT_ID_KEYBOARD)
@@ -718,14 +713,47 @@ static int usb_hid_set_report(struct usb_ctrlrequest *req)
718 return 0; 713 return 0;
719} 714}
720 715
716static int usb_hid_get_report(struct usb_ctrlrequest *req, unsigned char** dest)
717{
718 if ((req->wValue >> 8) != REPORT_TYPE_FEATURE)
719 {
720 logf("Unsupported report type");
721 return 1;
722 }
723
724 if ((req->wValue & 0xff) != REPORT_ID_BACKGROUND)
725 {
726 logf("Wrong report id");
727 return 2;
728 }
729
730 if (req->wIndex != (uint16_t)usb_interface)
731 {
732 logf("Wrong interface");
733 return 3;
734 }
735
736 if (req->wLength < GET_REPORT_BUF_LEN)
737 {
738 logf("Wrong length");
739 return 4;
740 }
741
742 (*dest)[0] = 0;
743 (*dest)[1] = battery_level();
744 *dest += GET_REPORT_BUF_LEN;
745
746 return 0;
747}
748
721/* called by usb_core_control_request() */ 749/* called by usb_core_control_request() */
722bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest) 750bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest)
723{ 751{
752 unsigned char *orig_dest = dest;
724 switch (req->bRequestType & USB_TYPE_MASK) 753 switch (req->bRequestType & USB_TYPE_MASK)
725 { 754 {
726 case USB_TYPE_STANDARD: 755 case USB_TYPE_STANDARD:
727 { 756 {
728 unsigned char *orig_dest = dest;
729 uint8_t type = req->wValue >> 8; 757 uint8_t type = req->wValue >> 8;
730 size_t len; 758 size_t len;
731 logf("hid: type %d %s", type, (type == USB_DT_HID) ? "hid" : 759 logf("hid: type %d %s", type, (type == USB_DT_HID) ? "hid" :
@@ -755,14 +783,26 @@ bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest)
755 { 783 {
756 logf("req %d %s", req->bRequest, 784 logf("req %d %s", req->bRequest,
757 (req->bRequest == USB_HID_SET_IDLE) ? "set idle" : 785 (req->bRequest == USB_HID_SET_IDLE) ? "set idle" :
758 ((req->bRequest == USB_HID_SET_REPORT) ? "set report" : "")); 786 ((req->bRequest == USB_HID_SET_REPORT) ? "set report" :
787 ((req->bRequest == USB_HID_GET_REPORT) ? "get report" : "")));
759 switch (req->bRequest) 788 switch (req->bRequest)
760 { 789 {
761 case USB_HID_SET_REPORT: 790 case USB_HID_SET_REPORT:
762 if (usb_hid_set_report(req)) 791 if (usb_hid_set_report(req))
763 break; 792 break;
793 case USB_HID_GET_REPORT:
794 if (usb_hid_get_report(req, &dest))
795 break;
764 case USB_HID_SET_IDLE: 796 case USB_HID_SET_IDLE:
765 usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ 797 if (dest != orig_dest)
798 {
799 usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */
800 usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest);
801 }
802 else
803 {
804 usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
805 }
766 return true; 806 return true;
767 } 807 }
768 break; 808 break;