HID device won't communicate under windows.
Posted: Mon Oct 19, 2009 3:07 pm
I've based a hardware PWM RGB controller on USB-HID, mostly copied from the Automator example.
Under Linux I've got almost everything working (GET_REPORT still acts funny, but I don't really have to use that)
Under windows is another story, It detects the device (no error on connect) but if I try to send a report I get USB_ERROR_IO back from usb-windows.c.
I compile the windows application using mingw with the usb files from Automator.
Here are what I think are the relevant code segments for this problem:
Control app (set-led.c)
The pieces of relevant firmware code:
The rest is just some includes and register settings for the pwm timers and stuff.
Almost all of the HID stuff is like a 1-on-1 copy from Automator, but I can't really get it to work at all.
Under Linux I've got almost everything working (GET_REPORT still acts funny, but I don't really have to use that)
Under windows is another story, It detects the device (no error on connect) but if I try to send a report I get USB_ERROR_IO back from usb-windows.c.
I compile the windows application using mingw with the usb files from Automator.
Here are what I think are the relevant code segments for this problem:
Control app (set-led.c)
Code: Select all
#include "usbcalls.h"
[...]
if(usbOpenDevice(&dev, vid, vendor, pid, product, 1) != 0){
fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
exit(1);
}
[...]
buffer[0] = CUSTOM_RQ_SET_RED;
buffer[1] = atoi(argv[2]);
if((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer, 2)) != 0){
fprintf(stderr, "Error sending value: %s\n", usbErrorMessage(err));
goto errorOccurred;
}
[...]
errorOccurred:
if(dev != NULL)
usbCloseDevice(dev);
return 0;
}
The pieces of relevant firmware code:
Code: Select all
static uchar expectWrite;
/* ------------------------------------------------------------------------- */
/* ------------------------ interface to USB driver ------------------------ */
/* ------------------------------------------------------------------------- */
PROGMEM char usbHidReportDescriptor[33] = { /* USB report descriptor */
0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x85, 0x01, // REPORT_ID (1)
0x95, 0x02, // REPORT_COUNT (2)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x02, // REPORT_ID (2)
0x95, 0x80, // REPORT_COUNT (128)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0xc0 // END_COLLECTION
};
uchar usbFunctionRead(uchar *data, uchar len)
{
data[0] = CUSTOM_RQ_GET_STATUS;
data[1] = 255 - OCR0B;
data[2] = 255 - OCR0A;
data[3] = 255 - OCR1B;
return 4;
}
uchar usbFunctionWrite(uchar *data, uchar len)
{
if (expectWrite == 0) return 1;
if ((expectWrite == CUSTOM_RQ_SET_RED)|(expectWrite == CUSTOM_RQ_SET_GREEN)|(expectWrite == CUSTOM_RQ_SET_BLUE)) {
expectWrite = 0;
if(len < 2)
return 0xff; /* stall */
switch (data[0]) {
case CUSTOM_RQ_SET_RED:
OCR0B = 255 - data[1];
break;
case CUSTOM_RQ_SET_GREEN:
OCR0A = 255 - data[1];
break;
case CUSTOM_RQ_SET_BLUE:
OCR1B = 255 - data[1];
break;
}
return 1;
}
if (expectWrite == CUSTOM_RQ_SET_ALL) {
expectWrite = 0;
if(len < 4)
return 0xff; /* stall */
OCR0B = 255 - data[1];
OCR0A = 255 - data[2];
OCR1B = 255 - data[3];
return 1;
}
return 0;
}
uchar usbFunctionSetup(uchar data[8])
{
static uchar replyBuf[4];
usbRequest_t *rq = (void *)data;
usbMsgPtr = replyBuf;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
if(rq->bRequest == USBRQ_HID_GET_REPORT){
if(rq->wValue.bytes[0] == CUSTOM_RQ_GET_STATUS){
return 0xff;
}
}else if(rq->bRequest == USBRQ_HID_SET_REPORT){
expectWrite = rq->wValue.bytes[0];
return 0xff;
}
}
return 0;
}
The rest is just some includes and register settings for the pwm timers and stuff.
Almost all of the HID stuff is like a 1-on-1 copy from Automator, but I can't really get it to work at all.