|
|
View previous topic :: View next topic |
Author |
Message |
acs4design
Joined: 26 May 2016 Posts: 4
|
USB HID set feature report [RESOLVED] |
Posted: Tue Nov 01, 2016 2:34 pm |
|
|
Has anyone had any luck filling in the code for the USB_HID_REQUEST_SET_REPORT? I'm writing code for an HID temperature sensor and windows is trying to set the state of the sensor through the SET FEATURE REPORT request. I can't however seem to figure out how to get the feature report that it is trying to send to me.
Any Thoughts?
Code: |
void usb_isr_tkn_setup_ClassInterface(void)
{
switch(usb_ep0_rx_buffer[1])
{
//JSG
case USB_HID_REQUEST_GET_REPORT: //01
debug_usb_token(debug_putc,"GR");
switch(usb_ep0_rx_buffer[3])
{
case 0x01: //Input Report
usb_getInput_len = usb_ep0_rx_buffer[7];
usb_getInput_len <<= 8;
usb_getInput_len |= usb_ep0_rx_buffer[6];
//JSG // may need to parse a byte to figure out which interface this is for
usb_getInput_intf = usb_ep0_rx_buffer[4];
usb_getInput_repid = usb_ep0_rx_buffer[2];
//usb_getfeature_ptr = //USB_HID_FEATURE_REPORTS_INDEXES[usb_getfeature_intf][usb_getfeature_repid];
usb_getInput_ptr = USB_HID_INPUT_REPORTS_INDEXES[usb_getInput_intf][usb_getInput_repid];
fprintf(PIC16, "GIR - PTR 0x%04.4lX", usb_getInput_ptr);
fprintf(PIC16, " REPID %ld, INTF %ld, LEN %ld\r\n", usb_getInput_repid, usb_getInput_intf, usb_getInput_len);
if(usb_getfeature_ptr != 0xFFFFL)
{
USB_stack_status.dev_req=GET_INPUT_REPORT;
usb_copy_input_report_to_ep();
}
else
{
usb_request_stall();
}
break;
case 0x03: //Feature Report
usb_getfeature_len = usb_ep0_rx_buffer[7];
usb_getfeature_len <<= 8;
usb_getfeature_len |= usb_ep0_rx_buffer[6];
//JSG // may need to parse a byte to figure out which interface this is for
usb_getfeature_intf = usb_ep0_rx_buffer[4];
usb_getfeature_repid = usb_ep0_rx_buffer[2];
usb_getfeature_ptr = USB_HID_FEATURE_REPORTS_INDEXES[usb_getfeature_intf][usb_getfeature_repid];
fprintf(PIC16, "GFR - PTR 0x%04.4lX", usb_getfeature_ptr);
fprintf(PIC16, " REPID %ld, INTF %ld, LEN %ld\r\n", usb_getfeature_repid, usb_getfeature_intf, usb_getfeature_len);
if(usb_getfeature_ptr != 0xFFFFL)
{
USB_stack_status.dev_req=GET_FEATURE_REPORT;
usb_copy_report_to_ep();
}
else
{
usb_request_stall();
}
break;
default:
usb_request_stall();
break;
}
break;
case USB_HID_REQUEST_SET_REPORT:
/***** WHAT GOES HERE??? *****/
/***** WHAT GOES HERE??? *****/
/***** WHAT GOES HERE??? *****/
break;
//JSG
#IF USB_HID_BOOT_PROTOCOL
case USB_HID_REQUEST_GET_PROTOCOL: //03
debug_usb_token(debug_putc,"GP");
usb_ep0_tx_buffer[0]=hid_protocol[usb_ep0_rx_buffer[4]];
usb_request_send_response(1);
break;
#ENDIF
|
Last edited by acs4design on Wed Nov 02, 2016 4:44 pm; edited 1 time in total |
|
|
acs4design
Joined: 26 May 2016 Posts: 4
|
|
Posted: Wed Nov 02, 2016 12:34 pm |
|
|
It looks as though the *data* for the HID REQUEST SET REPORT is actually sent *before* the actual SET Request. I do actually receive the SET request, but I can't find the actual data that is supposed to go with it.
If it is in the next packet, how do I flag it as part of the set feature report request? If it comes before, how could I possibly know what that data is to be used for and be able to discern that data from anything else?
As you can see in lines marked in pink as 1 and 2, this is the data I need. It comes before the Set Report request in lines marked as 3 and 4 |
|
|
acs4design
Joined: 26 May 2016 Posts: 4
|
UPDATE |
Posted: Wed Nov 02, 2016 3:21 pm |
|
|
So the Set request data *does* come after the the actual set request. I get the Set Feature Request and print 16 bytes of ep0_rx_buffer and the data past the 8th byte has not changed and is all zeros. However, on the next EP0 setup packet, I print the same 16 bytes and you can see that the buffer had ,at one time, the data that I was looking for.
the "00 D0 07 00 00 01 01 00" is part of the data that I was looking for.
EP0 SETUP: A1 01 03 03 03 00 16 00 00 00 00 00 00 00 00 00
GFR - PTR 0x0102 REPID 3, INTF 3, LEN 22
EP0 SETUP: A1 01 03 03 03 00 16 00 00 00 00 00 00 00 00 00
GFR - PTR 0x0102 REPID 3, INTF 3, LEN 22
EP0 SETUP: 21 09 03 03 03 00 16 00 00 00 00 00 00 00 00 00
SFR - PTR 0x0102 REPID 3, INTF 3, LEN 22
SFR PKT: 21 09 03 03 03 00 16 00 00 00 00 00 00 00 00 00
EP0 SETUP: A1 01 03 03 03 00 16 00 00 D0 07 00 00 01 01 00
GFR - PTR 0x0102 REPID 3, INTF 3, LEN 22
EP0 SETUP: A1 01 03 03 03 00 16 00 00 D0 07 00 00 01 01 00
GFR - PTR 0x0102 REPID 3, INTF 3, LEN 22
EP0 SETUP: 21 09 03 03 03 00 16 00 00 D0 07 00 00 01 01 00
SFR - PTR 0x0102 REPID 3, INTF 3, LEN 22
Somewhere along the way the data is not getting to usb_isr_tok_dne(); Since the buffer for ep0_rx_buffer is dual port RAM, the USB engine is writing to that ram and it has written the data I'm looking for. The question is, why isn't it getting passed up? or am I just missing it? |
|
|
acs4design
Joined: 26 May 2016 Posts: 4
|
RESOLVED!!! |
Posted: Wed Nov 02, 2016 3:59 pm |
|
|
In the SET REPORT inside of usb_isr_tkn_setup_ClassInterface() I set a flag in USB_stack_status.dev_req=SET_FEATURE_REPORT. This is a new flag that I have added. I also have to call usb_request_get_data(); in order to make sure I setup EP0_OUT ready to take another packet. Although, I'm not 100% sure it's necessary.
Code: |
case USB_HID_REQUEST_SET_REPORT:
switch(usb_ep0_rx_buffer[3])
{
case 0x03: //Feature Report
//Take down all of the information because our data is in the next packet and we need to remember
//all of the pertinents
usb_setfeature_len = usb_ep0_rx_buffer[7];
usb_setfeature_len <<= 8;
usb_setfeature_len |= usb_ep0_rx_buffer[6];
usb_setfeature_intf = usb_ep0_rx_buffer[4];
usb_setfeature_repid = usb_ep0_rx_buffer[2];
usb_setfeature_ptr = USB_HID_FEATURE_REPORTS_INDEXES[usb_setfeature_intf][usb_setfeature_repid];
if(usb_setfeature_ptr != 0xFFFFL)
{
usb_request_get_data();
//I'll set this variable and wait for it to come through in usb_isr_tok_out_dne()
//that's where it should come out
USB_stack_status.dev_req=SET_FEATURE_REPORT;
}
else
{
fprintf(PIC16, "*** STALLED ***\r\n");
usb_request_stall();
}
break;
default:
usb_request_stall();
break;
}
break;
//JSG
|
Then in usb_isr_tok_out_dne() the next packet to come in (through the OUT) should be the one I'm looking for and there is no header, it's just raw data.
Below is the corrected usb_isr_tok_setup_dne() function that I ended up using. For now, I'm just printing the bytes I received in the feature report. Notice that I use "__usb_cdc_state" to check the state to make sure the raw data packet doesn't need to go there first. There is probably a better way to do this, but for now it is working.
Code: |
extern usb_cdc_state_e __usb_cdc_state;
void usb_isr_tok_out_dne(unsigned int8 endpoint)
{
if (endpoint==0)
{
#if USB_CDC_DEVICE
if(__usb_cdc_state != USB_CDC_OUT_NOTHING)
{
usb_isr_tok_out_cdc_control_dne();
}
#endif
if(USB_stack_status.dev_req == SET_FEATURE_REPORT)
{
fprintf(PIC16, "EP0 TOUT: ");
for(int i = 0; i < 16; i++)
{
fprintf(PIC16, "%X ", usb_ep0_rx_buffer[i]);
}
fprintf(PIC16, "\r\n");
usb_copy_ep_to_report();
}
}
#if USB_CDC_DEVICE
else if (endpoint==USB_CDC_DATA_OUT_ENDPOINT)//see ex_usb_serial.c example and usb_cdc.h driver
{
usb_isr_tok_out_cdc_data_dne();
}
#endif
}
|
Here is the function that actually copies the report data into the actual feature report location.
Code: |
void usb_copy_ep_to_report(void)
{
unsigned int i=0;
while ((usb_setfeature_len)&&(i<USB_MAX_EP0_PACKET_LENGTH))
{
usb_setfeature_len--;
USB_HID_FEATURE_REPORTS[usb_setfeature_ptr++] = usb_ep0_rx_buffer[i++];
}
if ((!usb_getdesc_len)&&(i!=USB_MAX_EP0_PACKET_LENGTH))
{
USB_stack_status.dev_req = NONE;
}
}
|
PLEASE NOTE: The code snippets shown here are not the only changes that were necessary to get this working. There is lots going on behind the scenes necessary to get feature reports working in general. The device I have created has a CDC interface and two HID interfaces. So the code has been heavily modified to deal with all of these interfaces and configurations. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|