Добрый день.
Пытаюсь сделать HID-устройство из платы stm32f4DISCOVERY. За основу взят девайс (тоже HID) на AT89C5131, который работает стабильно и для которого есть прога на ПК.
Проект делаю в ЧибиСтудии.
При разработке проекта решил перепилить пример с использованием CDC+Shell, путем избавления от Serialхх-интерфейсов.
На данный момент добился завершения энумерации без ошибок, т.е. винда видит устройство как HID с нужными параметрами (такими же как и для устройства на AT89C5131).
Долго мучался с этим моментом, пока не поправил обработчик в файле usb.c:
Код
static bool_t default_handler(USBDriver *usbp) {
...
case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_DESCRIPTOR << 8):
case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_GET_DESCRIPTOR << 8):
case USB_RTYPE_RECIPIENT_ENDPOINT| (USB_REQ_GET_DESCRIPTOR << 8): /* !!добавил эту строчку!! */
/* Handling descriptor requests from the host.*/
dp = usbp->config->get_descriptor_cb(
usbp, usbp->setup[3], usbp->setup[2],
usbFetchWord(&usbp->setup[4]));
if (dp == NULL)
return FALSE;
usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
return TRUE;
...
}
до этого запрос дескриптора HID и его конечной точки игнорировался.
Сейчас уперся в проблему обработки OUT-транзакции. Не могу понять, что где подкрутить, чтобы принять о обработать данные.
Используя программу BusHound наблюдаю следующее (работаю со "старым" девайсом на AT89C5131 и с "новым"):
- инициализация завершается нормально для "старого" и "нового" устройств;
- при отправке OUT-данных на "старое" устройство, на экране проги BusHound вижу OUT-данные;
- при отправке OUT-данных на "новое" устройство, на экран BusHound ничего не выводится, а программа ПК, из которой производится передача данных, вообще зависает, до тех пор, пока не отключишь девайс.
Я понимаю. что где-то в СТМке не отрабатывается этот OUT-запрос, но вот ГДЕ, не могу найти уже несколько дней.
Вот основной файл с описанием дескрипторов (и попыткой навешивания какого-то обработчика приема данных):
CODE
#include "ch.h"
#include "hal.h"
bool_t myRequestsHook(USBDriver *usbp) {
if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) {
switch (usbp->setup[1]) {
case 1:
usbSetupTransfer(usbp, NULL, 0, NULL);
return TRUE;
default:
return FALSE;
}
}
return FALSE;
}
void myEP1Transmitter(USBDriver *usbp, usbep_t ep)
{
(void)usbp;
(void)ep;
}
void myEP1Receiver(USBDriver *usbp, usbep_t ep)
{
size_t n, maxsize;
// SerialUSBDriver *sdup = usbp->out_params[ep - 1];
// if (sdup == NULL)
// return;
chSysLockFromIsr();
// chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
/* Writes to the input queue can only happen when there is enough space
to hold at least one packet.*/
maxsize = usbp->epc[ep]->out_maxsize;
// if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) {
/* The endpoint cannot be busy, we are in the context of the callback,
so a packet is in the buffer for sure.*/
chSysUnlockFromIsr();
n = (n / maxsize) * maxsize;
// usbPrepareQueuedReceive(usbp, ep, &sdup->iqueue, n);
chSysLockFromIsr();
usbStartReceiveI(usbp, ep);
// }
chSysUnlockFromIsr();
}
/*
* USB Device Descriptor.
*/
static const uint8_t vcom_device_descriptor_data[18] = {
USB_DESC_DEVICE (0x0001, /* bcdUSB (1.0). */
0x00, /* bDeviceClass (HID). */
0x00, /* bDeviceSubClass. */
0x00, /* bDeviceProtocol. */
0x40, /* bMaxPacketSize for ep0. */
0x03EB, /* idVendor (Atmel vendor ID = 03EBh). */
0x5703, /* idProduct. */
0x0000, /* bcdDevice. */
1, /* iManufacturer. */
2, /* iProduct. */
3, /* iSerialNumber. */
1) /* bNumConfigurations. */
};
/*
* Device Descriptor wrapper.
*/
static const USBDescriptor vcom_device_descriptor = {
sizeof(vcom_device_descriptor_data),
vcom_device_descriptor_data
};
/* Configuration Descriptor tree for a CDC.*/
static const uint8_t vcom_configuration_descriptor_data[41] = {
/* Configuration Descriptor.*/
USB_DESC_CONFIGURATION(41, /* wTotalLength. */
0x01, /* bNumInterfaces. */
0x01, /* bConfigurationValue. */
0, /* iConfiguration. */
0xC0, /* bmAttributes (self powered). */
50), /* bMaxPower (100mA). */
/* Interface Descriptor.*/
USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x01, /* bNumEndpoints. */
0x03, /* bInterfaceClass (HID). */
0xff, /* bInterfaceSubClass (xx). */
0xff, /* bInterfaceProtocol (xx). */
0x00), /* iInterface. */
/* Дескриптор HID */
USB_DESC_BYTE (9),
USB_DESC_BYTE (0x21), /* дескриптор HID */
USB_DESC_BYTE (0x00), USB_DESC_BYTE(0x01), /* версия HID */
USB_DESC_BYTE (0), /* числовой код страны для локальных устройств */
USB_DESC_BYTE (1), /* число дескрипторов репорта */
USB_DESC_BYTE (0x22), /* номер дескриптора репорта */
USB_DESC_WORD (47), /* размер дескриптора репорта */
/* Дескриптор первой конечной точки */
USB_DESC_BYTE (7),
USB_DESC_BYTE (0x05), /* дескриптор ENDPOINT */
USB_DESC_BYTE (0x01), /* номер конечной точки OUT */
USB_DESC_BYTE (0x03), /* аттрибуты конечной точки */ // !!!! INTERRUPT !!!!
USB_DESC_WORD (0x0040), /* максимальный размер пакета(32) */
// USB_DESC_WORD (0x0008), /* максимальный размер пакета(32) */
USB_DESC_BYTE (10),
/* Дескриптор второй конечной точки */
USB_DESC_BYTE (7),
USB_DESC_BYTE (0x05), /* дескриптор ENDPOINT */
USB_DESC_BYTE (0x01|0x80), /* номер конечной точки IN */
USB_DESC_BYTE (0x03), /* аттрибуты конечной точки */ // !!!! INTERRUPT !!!!
USB_DESC_WORD (0x0040), /* максимальный размер пакета(32) */
// USB_DESC_WORD (0x0008), /* максимальный размер пакета(32) */
USB_DESC_BYTE (10)
};
/*
* Configuration Descriptor wrapper.
*/
static const USBDescriptor vcom_configuration_descriptor = {
sizeof(vcom_configuration_descriptor_data),
vcom_configuration_descriptor_data
};
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
static const uint8_t vcom_HID_descriptor_data[8] = {
/* Дескриптор HID */
USB_DESC_BYTE (0x21), /* дескриптор HID */
USB_DESC_BYTE (0x00), USB_DESC_BYTE(0x01), /* версия HID */
USB_DESC_BYTE (0), /* числовой код страны для локальных устройств */
USB_DESC_BYTE (1), /* число дескрипторов репорта */
USB_DESC_BYTE (0x22), /* номер дескриптора репорта */
USB_DESC_WORD (47) /* размер дескриптора репорта */
};
/*
* Configuration Descriptor wrapper.
*/
static const USBDescriptor vcom_HID_descriptor = {
sizeof(vcom_HID_descriptor_data),
vcom_HID_descriptor_data
};
static const uint8_t vcom_HID_report_descriptor_data[47] = {
USB_DESC_BYTE(0x06), USB_DESC_BYTE(0x00), USB_DESC_BYTE(0xff), /* USAGE_PAGE (Generic Desktop) */
USB_DESC_BYTE(0x09), USB_DESC_BYTE(0x01), /* USAGE (Vendor Usage 1) */
USB_DESC_BYTE(0xa1), USB_DESC_BYTE(0x01), /* COLLECTION (Application) */
USB_DESC_BYTE(0x19), USB_DESC_BYTE(0x01), /* USAGE_MINIMUM (Vendor Usage 1) */
USB_DESC_BYTE(0x29), USB_DESC_BYTE(0x01), /* USAGE_MAXIMUM (Vendor Usage 1) */
USB_DESC_BYTE(0x15), USB_DESC_BYTE(0x00), /* LOGICAL_MINIMUM (0) */
USB_DESC_BYTE(0x26), USB_DESC_BYTE(0xff), USB_DESC_BYTE(0x00), /* LOGICAL_MAXIMUM (255) */
USB_DESC_BYTE(0x85), USB_DESC_BYTE(0x01), /* REPORT_ID (1) */
USB_DESC_BYTE(0x75), USB_DESC_BYTE(0x20), /* REPORT_SIZE (32) МОЁ НОВШЕСТВО */
USB_DESC_BYTE(0x95), USB_DESC_BYTE(0x08), /* REPORT_COUNT(8) */
USB_DESC_BYTE(0xB1), USB_DESC_BYTE(0x02), /* FEATURE (Data,Var,Abs) МОЁ НОВШЕСТВО */
USB_DESC_BYTE(0xc0), /* END_COLLECTION */
USB_DESC_BYTE(0x09), USB_DESC_BYTE(0x01), /* USAGE (Vendor Usage 1) */
USB_DESC_BYTE(0xa1), USB_DESC_BYTE(0x01), /* COLLECTION (Application) */
USB_DESC_BYTE(0x19), USB_DESC_BYTE(0x01), /* USAGE_MINIMUM (Vendor Usage 1) */
USB_DESC_BYTE(0x29), USB_DESC_BYTE(0x01), /* USAGE_MAXIMUM (Vendor Usage 1) */
USB_DESC_BYTE(0x15), USB_DESC_BYTE(0x00), /* LOGICAL_MINIMUM (0) */
USB_DESC_BYTE(0x26), USB_DESC_BYTE(0xff), USB_DESC_BYTE(0x00), /* LOGICAL_MAXIMUM (255) */
USB_DESC_BYTE(0x85), USB_DESC_BYTE(0x02), /* REPORT_ID (2) */
USB_DESC_BYTE(0x75), USB_DESC_BYTE(0x0f), /* REPORT_SIZE (15) */
USB_DESC_BYTE(0x95), USB_DESC_BYTE(0x08), /* REPORT_COUNT(8) */
USB_DESC_BYTE(0x91), USB_DESC_BYTE(0x02), /* OUTPUT (Data,Var,Abs) */
USB_DESC_BYTE(0xc0) /* END_COLLECTION */
};
/*
* Configuration Descriptor wrapper.
*/
static const USBDescriptor vcom_HID_report_descriptor = {
sizeof(vcom_HID_report_descriptor_data),
vcom_HID_report_descriptor_data
};
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/*
* U.S. English language identifier.
*/
static const uint8_t vcom_string0[] = {
USB_DESC_BYTE(4), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
};
/*
* Vendor string.
*/
static const uint8_t vcom_string1[] = {
USB_DESC_BYTE(38), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,
'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
'c', 0, 's', 0
};
/*
* Device Description string.
*/
static const uint8_t vcom_string2[] = {
USB_DESC_BYTE(56), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0,
'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0,
'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0,
'o', 0, 'r', 0, 't', 0
};
/*
* Serial Number string.
*/
static const uint8_t vcom_string3[] = {
USB_DESC_BYTE(8), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'0' + CH_KERNEL_MAJOR, 0,
'0' + CH_KERNEL_MINOR, 0,
'0' + CH_KERNEL_PATCH, 0
};
/*
* Strings wrappers array.
*/
static const USBDescriptor vcom_strings[] = {
{sizeof(vcom_string0), vcom_string0},
{sizeof(vcom_string1), vcom_string1},
{sizeof(vcom_string2), vcom_string2},
{sizeof(vcom_string3), vcom_string3}
};
/*
* Handles the GET_DESCRIPTOR callback. All required descriptors must be
* handled here.
*/
static const USBDescriptor *get_descriptor(USBDriver *usbp,
uint8_t dtype,
uint8_t dindex,
uint16_t lang) {
(void)usbp;
(void)lang;
switch (dtype) {
case USB_DESCRIPTOR_DEVICE:
return &vcom_device_descriptor;
case USB_DESCRIPTOR_CONFIGURATION:
return &vcom_configuration_descriptor;
case USB_DESCRIPTOR_STRING:
if (dindex < 4)
return &vcom_strings[dindex];
// HID-дескриптор
case 0x21:
return &vcom_HID_descriptor;
// дескриптор репорта
case 0x22:
return &vcom_HID_report_descriptor;
}
return NULL;
}
/**
* @brief IN EP1 state.
*/
static USBInEndpointState ep1instate;
/**
* @brief OUT EP1 state.
*/
static USBOutEndpointState ep1outstate;
/**
* @brief EP1 initialization structure (OUT).
*/
static const USBEndpointConfig ep1config = {
USB_EP_MODE_TYPE_INTR,
NULL,
myEP1Transmitter,
myEP1Receiver,
0x0040,
0x0040,
&ep1instate,
&ep1outstate,
2,
NULL
};
/**
* @brief IN EP2 state.
*/
static USBInEndpointState ep2instate;
/**
* @brief EP2 initialization structure (IN only).
*/
static const USBEndpointConfig ep2config = {
USB_EP_MODE_TYPE_INTR,
NULL,
myEP1Transmitter,
NULL,
0x0040,
0x0000,
&ep2instate,
NULL,
1,
NULL
};
/*
* Handles the USB driver global events.
*/
static void usb_event(USBDriver *usbp, usbevent_t event) {
// extern SerialUSBDriver SDU1;
switch (event) {
case USB_EVENT_RESET:
return;
case USB_EVENT_ADDRESS:
return;
case USB_EVENT_CONFIGURED:
chSysLockFromIsr();
/* Enables the endpoints specified into the configuration.
Note, this callback is invoked from an ISR so I-Class functions
must be used.*/
usbInitEndpointI(usbp, 1, &ep1config);
// usbInitEndpointI(usbp, 2, &ep2config);
/* Resetting the state of the CDC subsystem.*/
// sduConfigureHookI(&SDU1);
chSysUnlockFromIsr();
return;
case USB_EVENT_SUSPEND:
return;
case USB_EVENT_WAKEUP:
return;
case USB_EVENT_STALLED:
return;
}
return;
}
/*
* USB driver configuration.
*/
const USBConfig usbcfg = {
usb_event,
get_descriptor,
myRequestsHook,
NULL
};
Файлы проекта прикладываю ниже.
hid_bad.rar ( 13.17 килобайт )
Кол-во скачиваний: 54