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.c181
1 files changed, 68 insertions, 113 deletions
diff --git a/firmware/usbstack/usb_hid.c b/firmware/usbstack/usb_hid.c
index 213f97180e..46baff8222 100644
--- a/firmware/usbstack/usb_hid.c
+++ b/firmware/usbstack/usb_hid.c
@@ -252,17 +252,16 @@ static unsigned char buf_dump_ar[BUF_DUMP_NUM_LINES][BUF_DUMP_LINE_SIZE + 1]
252 252
253void buf_dump(unsigned char *buf, size_t size, char *msg) 253void buf_dump(unsigned char *buf, size_t size, char *msg)
254{ 254{
255 size_t i;
256 int line;
257 static const char v[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 255 static const char v[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
258 'A', 'B', 'C', 'D', 'E', 'F' }; 256 'A', 'B', 'C', 'D', 'E', 'F' };
259 257
260 for (i = 0, line = 0; i < size; line++) 258 size_t i = 0;
259 for (int line = 0; i < size; line++)
261 { 260 {
262 int j, i0 = i; 261 int i0 = i;
263 char *b = buf_dump_ar[line]; 262 char *b = buf_dump_ar[line];
264 263
265 for (j = 0; j < BUF_DUMP_ITEMS_IN_LINE && i < size; j++, i++) 264 for (int j = 0; j < BUF_DUMP_ITEMS_IN_LINE && i < size; j++, i++)
266 { 265 {
267 *b++ = v[buf[i] >> 4]; 266 *b++ = v[buf[i] >> 4];
268 *b++ = v[buf[i] & 0xF]; 267 *b++ = v[buf[i] & 0xF];
@@ -555,32 +554,30 @@ static size_t descriptor_report_get(unsigned char *dest)
555 return (size_t)(report - dest); 554 return (size_t)(report - dest);
556} 555}
557 556
558static void descriptor_hid_get(unsigned char **dest) 557static void descriptor_hid_get(unsigned char *dest)
559{ 558{
560 hid_descriptor.wDescriptorLength0 = 559 hid_descriptor.wDescriptorLength0= descriptor_report_get(report_descriptor);
561 (uint16_t)descriptor_report_get(report_descriptor);
562 560
563 logf("hid: desc len %u", hid_descriptor.wDescriptorLength0); 561 logf("hid: desc len %u", hid_descriptor.wDescriptorLength0);
564 buf_dump(report_descriptor, hid_descriptor.wDescriptorLength0, "desc"); 562 buf_dump(report_descriptor, hid_descriptor.wDescriptorLength0, "desc");
565 563
566 PACK_DATA(*dest, hid_descriptor); 564 PACK_DATA(dest, hid_descriptor);
567} 565}
568 566
569int usb_hid_get_config_descriptor(unsigned char *dest, int max_packet_size) 567int usb_hid_get_config_descriptor(unsigned char *dest, int max_packet_size)
570{ 568{
569 (void)max_packet_size;
570
571 unsigned char *orig_dest = dest; 571 unsigned char *orig_dest = dest;
572 572
573 logf("hid: config desc."); 573 logf("hid: config desc.");
574 574
575 /* Ignore given max_packet_size */
576 (void)max_packet_size;
577
578 /* Interface descriptor */ 575 /* Interface descriptor */
579 interface_descriptor.bInterfaceNumber = usb_interface; 576 interface_descriptor.bInterfaceNumber = usb_interface;
580 PACK_DATA(dest, interface_descriptor); 577 PACK_DATA(dest, interface_descriptor);
581 578
582 /* HID descriptor */ 579 /* HID descriptor */
583 descriptor_hid_get(&dest); 580 descriptor_hid_get(dest);
584 581
585 /* Endpoint descriptor */ 582 /* Endpoint descriptor */
586 endpoint_descriptor.wMaxPacketSize = 8; 583 endpoint_descriptor.wMaxPacketSize = 8;
@@ -602,11 +599,9 @@ void usb_hid_init_connection(void)
602/* called by usb_core_init() */ 599/* called by usb_core_init() */
603void usb_hid_init(void) 600void usb_hid_init(void)
604{ 601{
605 int i;
606
607 logf("hid: init"); 602 logf("hid: init");
608 603
609 for (i = 0; i < HID_NUM_BUFFERS; i++) 604 for (int i = 0; i < HID_NUM_BUFFERS; i++)
610 send_buffer_len[i] = 0; 605 send_buffer_len[i] = 0;
611 606
612 cur_buf_prepare = 0; 607 cur_buf_prepare = 0;
@@ -627,26 +622,15 @@ void usb_hid_disconnect(void)
627void usb_hid_transfer_complete(int ep, int dir, int status, int length) 622void usb_hid_transfer_complete(int ep, int dir, int status, int length)
628{ 623{
629 (void)ep; 624 (void)ep;
630 (void)dir;
631 (void)status;
632 (void)length; 625 (void)length;
633 626
634 logf("HID: transfer complete: %d %d %d %d",ep,dir,status,length); 627 logf("HID: transfer complete: %d %d %d %d",ep,dir,status,length);
635 switch (dir) 628 if (dir == USB_DIR_IN && !status)
636 { 629 {
637 case USB_DIR_OUT: 630 send_buffer_len[cur_buf_send] = 0;
638 break; 631 HID_BUF_INC(cur_buf_send);
639 case USB_DIR_IN: 632 currently_sending = false;
640 { 633 usb_hid_try_send_drv();
641 if (status)
642 break;
643
644 send_buffer_len[cur_buf_send] = 0;
645 HID_BUF_INC(cur_buf_send);
646 currently_sending = false;
647 usb_hid_try_send_drv();
648 break;
649 }
650 } 634 }
651} 635}
652 636
@@ -660,32 +644,27 @@ static int usb_hid_set_report(struct usb_ctrlrequest *req)
660 static unsigned char buf[SET_REPORT_BUF_LEN] USB_DEVBSS_ATTR 644 static unsigned char buf[SET_REPORT_BUF_LEN] USB_DEVBSS_ATTR
661 __attribute__((aligned(32))); 645 __attribute__((aligned(32)));
662 int length; 646 int length;
663 int rc = 0;
664 647
665 if ((req->wValue >> 8) != REPORT_TYPE_OUTPUT) 648 if ((req->wValue >> 8) != REPORT_TYPE_OUTPUT)
666 { 649 {
667 logf("Unsopported report type"); 650 logf("Unsopported report type");
668 rc = 1; 651 return 1;
669 goto Exit;
670 } 652 }
671 if ((req->wValue & 0xff) != REPORT_ID_KEYBOARD) 653 if ((req->wValue & 0xff) != REPORT_ID_KEYBOARD)
672 { 654 {
673 logf("Wrong report id"); 655 logf("Wrong report id");
674 rc = 2; 656 return 2;
675 goto Exit;
676 } 657 }
677 if (req->wIndex != (uint16_t)usb_interface) 658 if (req->wIndex != (uint16_t)usb_interface)
678 { 659 {
679 logf("Wrong interface"); 660 logf("Wrong interface");
680 rc = 3; 661 return 3;
681 goto Exit;
682 } 662 }
683 length = req->wLength; 663 length = req->wLength;
684 if (length != SET_REPORT_BUF_LEN) 664 if (length != SET_REPORT_BUF_LEN)
685 { 665 {
686 logf("Wrong length"); 666 logf("Wrong length");
687 rc = 4; 667 return 4;
688 goto Exit;
689 } 668 }
690 669
691 memset(buf, 0, length); 670 memset(buf, 0, length);
@@ -706,83 +685,64 @@ static int usb_hid_set_report(struct usb_ctrlrequest *req)
706 685
707 /* Defining other LEDs and setting them from the USB host (OS) can be used 686 /* Defining other LEDs and setting them from the USB host (OS) can be used
708 * to send messages to the DAP */ 687 * to send messages to the DAP */
709 688 return 0;
710Exit:
711 return rc;
712} 689}
713 690
714/* called by usb_core_control_request() */ 691/* called by usb_core_control_request() */
715bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest) 692bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest)
716{ 693{
717 bool handled = false;
718
719 switch (req->bRequestType & USB_TYPE_MASK) 694 switch (req->bRequestType & USB_TYPE_MASK)
720 { 695 {
721 case USB_TYPE_STANDARD: 696 case USB_TYPE_STANDARD:
697 {
698 unsigned char *orig_dest = dest;
699 uint8_t type = req->wValue >> 8;
700 size_t len;
701 logf("hid: type %d %s", type, (type == USB_DT_HID) ? "hid" :
702 ((type == USB_DT_REPORT) ? "report" : ""));
703 switch (type)
722 { 704 {
723 unsigned char *orig_dest = dest; 705 case USB_DT_HID:
724 706 descriptor_hid_get(dest);
725 switch (req->wValue>>8) /* type */ 707 break;
726 { 708 case USB_DT_REPORT:
727 case USB_DT_HID: 709 len = descriptor_report_get(report_descriptor);
728 { 710 memcpy(dest, &report_descriptor, len);
729 logf("hid: type hid"); 711 dest += len;
730 descriptor_hid_get(&dest);
731 break;
732 }
733 case USB_DT_REPORT:
734 {
735 int len;
736
737 logf("hid: type report");
738
739 len = descriptor_report_get(report_descriptor);
740 memcpy(dest, &report_descriptor, len);
741 dest += len;
742 break;
743 }
744 default:
745 logf("hid: unsup. std. req");
746 break;
747 }
748 if (dest != orig_dest)
749 {
750 usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */
751 usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest);
752 handled = true;
753 }
754 break; 712 break;
755 } 713 }
756 714
757 case USB_TYPE_CLASS: 715 if (dest != orig_dest)
758 { 716 {
759 switch (req->bRequest) 717 usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */
760 { 718 usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest);
761 case USB_HID_SET_IDLE: 719 return true;
762 logf("hid: set idle");
763 usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
764 handled = true;
765 break;
766 case USB_HID_SET_REPORT:
767 logf("hid: set report");
768 if (!usb_hid_set_report(req))
769 {
770 usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
771 handled = true;
772 }
773 break;
774 default:
775 logf("%d: unsup. cls. req", req->bRequest);
776 break;
777 }
778 break;
779 } 720 }
721 break;
722 }
780 723
781 case USB_TYPE_VENDOR: 724 case USB_TYPE_CLASS:
782 logf("hid: unsup. ven. req"); 725 {
783 break; 726 logf("req %d %s", req->bRequest,
727 (req->bRequest == USB_HID_SET_IDLE) ? "set idle" :
728 ((req->bRequest == USB_HID_SET_REPORT) ? "set report" : ""));
729 switch (req->bRequest)
730 {
731 case USB_HID_SET_REPORT:
732 if (usb_hid_set_report(req))
733 break;
734 case USB_HID_SET_IDLE:
735 usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
736 return true;
737 }
738 break;
784 } 739 }
785 return handled; 740
741 case USB_TYPE_VENDOR:
742 logf("hid: unsup. ven. req");
743 break;
744 }
745 return false;
786} 746}
787 747
788static void usb_hid_try_send_drv(void) 748static void usb_hid_try_send_drv(void)
@@ -803,10 +763,7 @@ static void usb_hid_try_send_drv(void)
803 rc = usb_drv_send_nonblocking(ep_in, send_buffer[cur_buf_send], length); 763 rc = usb_drv_send_nonblocking(ep_in, send_buffer[cur_buf_send], length);
804 currently_sending = true; 764 currently_sending = true;
805 if (rc) 765 if (rc)
806 {
807 send_buffer_len[cur_buf_send] = 0; 766 send_buffer_len[cur_buf_send] = 0;
808 return;
809 }
810} 767}
811 768
812static void usb_hid_queue(unsigned char *data, int length) 769static void usb_hid_queue(unsigned char *data, int length)
@@ -829,19 +786,19 @@ static void usb_hid_queue(unsigned char *data, int length)
829 786
830void usb_hid_send(usage_page_t usage_page, int id) 787void usb_hid_send(usage_page_t usage_page, int id)
831{ 788{
832 uint8_t report_id, length; 789 uint8_t length;
833 static unsigned char buf[HID_BUF_SIZE_CMD] USB_DEVBSS_ATTR 790 static unsigned char buf[HID_BUF_SIZE_CMD] USB_DEVBSS_ATTR
834 __attribute__((aligned(32))); 791 __attribute__((aligned(32)));
835 usb_hid_report_t *report = NULL; 792 usb_hid_report_t *report = NULL;
836 793
837 for (report_id = 1; report_id < REPORT_ID_COUNT; report_id++) 794 for (uint8_t report_id = 1; report_id < REPORT_ID_COUNT; report_id++)
838 {
839 if (usb_hid_reports[report_id].usage_page == usage_page) 795 if (usb_hid_reports[report_id].usage_page == usage_page)
840 { 796 {
841 report = &usb_hid_reports[report_id]; 797 report = &usb_hid_reports[report_id];
798 buf[0] = report_id;
842 break; 799 break;
843 } 800 }
844 } 801
845 if (!report) 802 if (!report)
846 { 803 {
847 logf("Unsupported usage_page"); 804 logf("Unsupported usage_page");
@@ -849,7 +806,6 @@ void usb_hid_send(usage_page_t usage_page, int id)
849 } 806 }
850 807
851 logf("Sending cmd 0x%x", id); 808 logf("Sending cmd 0x%x", id);
852 buf[0] = report_id;
853 length = report->buf_set(&buf[1], id) + 1; 809 length = report->buf_set(&buf[1], id) + 1;
854 logf("length %u", length); 810 logf("length %u", length);
855 811
@@ -863,8 +819,7 @@ void usb_hid_send(usage_page_t usage_page, int id)
863 if (report->is_key_released) 819 if (report->is_key_released)
864 { 820 {
865 /* Key released */ 821 /* Key released */
866 memset(buf, 0, length); 822 memset(&buf[1], 0, length-1);
867 buf[0] = report_id;
868 823
869 buf_dump(buf, length, "key release"); 824 buf_dump(buf, length, "key release");
870 usb_hid_queue(buf, length); 825 usb_hid_queue(buf, length);