Hi Werner

I try to add the GET_REPORT to softusb-input. attach it the patch.
this patch not working. please help me take a look why it always
give me 'RX timeout error'.

one question on the GET_REPORT.
    before get the HID report descriptor. how do I know the REPORT ID
    since issue the GET_REPORT needs a Report ID as parameter.

my plan is first get the HID report. then try to parser it add support to 'poll'

any advice will be great.

thanks
xiangfu
>From 57488242060a620c476dc1c44a624dc2d38b6924 Mon Sep 17 00:00:00 2001
From: Xiangfu Liu <[email protected]>
Date: Thu, 2 Feb 2012 17:05:03 +0800
Subject: [PATCH] softusb-input: add get_report support

---
 softusb-input/main.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/softusb-input/main.c b/softusb-input/main.c
index a0ffb70..756fdc0 100644
--- a/softusb-input/main.c
+++ b/softusb-input/main.c
@@ -57,6 +57,7 @@ enum {
 	USB_DT_CONFIG		= 2,
 	USB_DT_INTERFACE	= 4,
 	USB_DT_ENDPOINT		= 5,
+	USB_DT_HID		= 33,
 };
 
 enum {
@@ -86,6 +87,7 @@ enum {
 	PORT_STATE_GET_DEVICE_DESCRIPTOR,
 	PORT_STATE_GET_CONFIGURATION_DESCRIPTOR,
 	PORT_STATE_SET_CONFIGURATION,
+	PORT_STATE_GET_REPORT,
 	PORT_STATE_RUNNING,
 	PORT_STATE_UNSUPPORTED
 };
@@ -94,6 +96,8 @@ enum {
 
 struct ep_status {
 	char ep;
+	char itf;
+	unsigned int report_len;
 	unsigned char expected_data;
 };
 
@@ -101,6 +105,7 @@ struct port_status {
 	char state;
 	char full_speed;
 	char retry_count;
+	char itf_count;
 	unsigned int unreset_frame;
 	unsigned char ep0_size;
 	struct ep_status keyboard;
@@ -555,8 +560,10 @@ static struct ep_status *identify_protocol(const unsigned char *itf,
 	if (itf[5] == USB_CLASS_HID && itf[6] == USB_SUBCLASS_BOOT)
 		switch(itf[7]) { /* check bInterfaceProtocol */
 			case USB_PROTO_KEYBOARD:
+				p->keyboard.itf = itf[2];
 				return &p->keyboard;
 			case USB_PROTO_MOUSE:
+				p->mouse.itf = itf[2];
 				return &p->mouse;
 			default:
 				/* unknown protocol, fail */
@@ -574,16 +581,32 @@ static const char mouse[] PROGMEM = "mouse\n";
 static const char keyboard[] PROGMEM = "keyboard\n";
 static const char midi[] PROGMEM = "MIDI\n";
 
+static char validate_report_descriptor(const unsigned char *descriptor,
+    char len, struct port_status *p)
+{
+	dump_hex((unsigned char *)descriptor, len);
+	return 1;
+}
+
 static char validate_configuration_descriptor(const unsigned char *descriptor,
     char len, struct port_status *p)
 {
 	struct ep_status *ep = NULL;
 	char offset;
 
+	p->itf_count = 0;
+	p->keyboard.report_len = 0;
+	p->mouse.report_len = 0;
+
 	offset = 0;
 	while(offset < len) {
-		if(descriptor[offset+1] == USB_DT_INTERFACE) {
+		if(descriptor[offset+1] == USB_DT_CONFIG) {
+			p->itf_count = descriptor[offset+4];
+		} else if(descriptor[offset+1] == USB_DT_INTERFACE) {
 			ep = identify_protocol(descriptor+offset, p);
+		} else if(descriptor[offset+1] == USB_DT_HID) {
+			ep->report_len = descriptor[offset+8] << 8 |
+					 descriptor[offset+7];
 		} else if(descriptor[offset+1] == USB_DT_ENDPOINT &&
 		    (descriptor[offset+2] & 0x80) && ep) {
 				ep->ep = descriptor[offset+2] & 0x7f;
@@ -808,8 +831,41 @@ static void port_service(struct port_status *p, char name)
 			if(control_transfer(ADDR, &packet, 1, NULL, 0,
 			    p->ep0_size) == 0) {
 				p->retry_count = 0;
+				p->state = PORT_STATE_GET_REPORT;
+			}
+			check_retry(p);
+			break;
+		}
+		case PORT_STATE_GET_REPORT: {
+			struct setup_packet packet;
+			unsigned char report_descriptor[6144];
+			char len;
+
+			if(!p->mouse.ep) {
 				p->state = PORT_STATE_RUNNING;
+				break;
 			}
+
+			packet.bmRequestType = 0xa1;
+			packet.bRequest = 0x01;
+			packet.wValue[0] = 0x01; /* Report ID */
+			packet.wValue[1] = 0x01; /* type: Input */
+			packet.wIndex[0] = p->mouse.itf; /* Interface */
+			packet.wIndex[1] = 0x00;
+			packet.wLength[0] = p->mouse.report_len & 0x00ff;
+			packet.wLength[1] = (p->mouse.report_len & 0xff00) >> 8;
+
+			len = control_transfer(ADDR, &packet, 0,
+					       report_descriptor,
+					       p->mouse.report_len,
+					       p->ep0_size);
+			if(len >= 0) {
+				p->retry_count = 0;
+				validate_report_descriptor(report_descriptor,
+							   len, p);
+			}
+
+			p->state = PORT_STATE_RUNNING;;
 			check_retry(p);
 			break;
 		}
-- 
1.7.5.4

_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode

Reply via email to