Здравствуйте!
Возможно, вы подскажете по такой узкой теме, как передача данных через hid, используя модуль V-USB.
Суть задачи примерно такова: есть составное hid-устройство и необходимо к нему добавить и передачу данных на 128 байт.
Двигаюсь по примеру в папке examples, но где-то запутался..
Соответственно, добавляю к hid-дескриптору такой блок:
Код
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x85, 0x04, // REPORT_ID (4)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x80, // REPORT_COUNT (128)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0xc0 // END_COLLECTION
Так как внутри программы я использую несколько массивов (и эти данные мне надо отправить на комп), я решил воспользоваться массивом указателей. Вот его определение и определения других переменных:
Код
static uchar usbreportid = 4;
static uchar* dataout[128];
static uchar currentAddress;
static uchar bytesRemaining;
static uchar buttonsADC[32];
static uchar keycodes[76];
static uchar canHoldButtons[17];
Перед началом работы определяем ссылки на данные:
Код
static void dataoutInit(void)
{
uchar i=0;
// 0
dataout[0] = &usbreportid; // Первый байт - номер отчета
//1-32
for(i=0; i<32; i++)
{
dataout[i+1] = &buttonsADC[i];
}
//33-48
for(i=0; i<16; i++)
{
dataout[i+33] = &canHoldButtons[i+1];
}
//49-124
for(i=0; i<76; i++)
{
dataout[i+ 49] = &keycodes[i];
}
}
В соответствии с изменением дескриптора изменяется и функция usbFunctionSetup (здесь я убрал часть, отвечающую за идентификацию трех предыдущих отчетов):
Код
uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
if (rq->wValue.bytes[0] == 1)
// ...
else if (rq->wValue.bytes[0] == 4) // Если отчет №4 - передача данных
{
bytesRemaining = 128;
currentAddress = 0;
return USB_NO_MSG;
}
return 0;
}
else if(rq->bRequest == USBRQ_HID_SET_REPORT)
{
if (rq->wValue.bytes[0] == 4)
{
bytesRemaining = 128;
currentAddress = 0;
return USB_NO_MSG;
}
}
// Здесь уже в принципе не интересно
else if(rq->bRequest == USBRQ_HID_GET_IDLE)
{
usbMsgPtr = &idleRate;
return 1;
}
else if(rq->bRequest == USBRQ_HID_SET_IDLE)
{
idleRate = rq->wValue.bytes[1];
}
}
else
{
/* no vendor specific requests implemented */
}
return 0;
}
Пока пытаюсь наладить передачу данных на копмьютер, вот функция usbFunctionRead:
Код
uchar usbFunctionRead(uchar *data, uchar len)
{
if(len > bytesRemaining)
len = bytesRemaining;
uchar i=0;
for (i=0; i<len; i++)
{
if (currentAddress + i <= 124)
{
data[i] = *dataout[currentAddress + i];
}
else
{
data[i] = 123; // Если вышли за пределы важных данных, просто посылаем ерунду
}
}
currentAddress += len;
bytesRemaining -= len;
return len;
}
Приложение на стороне компьютера - децл измененный пример из тех же примеров от v-usb:
Код
#define USBREPORTBUFFERLEN 129
#define USB_REPORT_ID 4
usbDevice_t* usbDevice;
char usbReportBuffer[USBREPORTBUFFERLEN];
void read_hid_device()
{
int len = USBREPORTBUFFERLEN;
int err = usbhidGetReport(usbDevice, USB_REPORT_ID, usbReportBuffer, &len);
if (err != 0)
{
cout<<"Error reading data: "<<usbErrorMessage(err)<<endl; // Это если ошибка, а ошибка у меня всегда =(
}
else
{
//Успешный прием и обработка данных
}
}
Устройство по своему основному функционалу работает, на заголовки компьютер не ругается, все замечательно.
Моя программа на компьютере нормально открывает и закрывает устройство, но никак не удается передать данные на компьютер - я все время получаю "Error reading data: communication error with device", т.е. (err != 0).
Где у меня может быть ошибка?