Jump to content

    
Sign in to follow this  
galjoen

Linux: работа с USB HID устройством - чтение Input Report (Interrupr In EP).

Recommended Posts

Подключаю свой самодельный Full Speed HID к Linux. У него имеются 3 вида репортов SetFeature, GetFeature и Input. SetFeature и GetFeature через шлются контрольный канал (адрес EP = 0) и работают без проблем. Даже лучше чем под Win т.к. позволяют задавать таймаут, а под Win таймаут =5 секундам и изменить невозможно. Input Report шлётся от устройства в комп через EP, работающую в режиме Interrupt In с интервалом опроса 2 милисекунды (так у меня в дескрипторе EP). И с ним проблемма.

В Win всё корректно - после подключения моего устройства хост как и положено шлёт запросы 1 раз за 2 кадра (2 милисекунды). Причём даже если никто это устройство не использует. И буферизирует посланные мной Input репорты. Причём кол-во буферов можно задавать.

Linux по своей инициативе вообще не шлёт никаких запросов. Если подключиться к устройству, то можно слать запросы (ReadFile). Но ни о каких 2 милисекундах и речи нет. Выполняешь ReadFile - запрос посылается. И буферизации никакой нет. Из-за этого Input репорты теряются. Особенно почему-то при выводе на экран. Т.е. какое-то время не опрашивали Interrupt In EP (переключились на другую задачу) - буфер в устройстве переполняется - данные теряются.

Выходов из этой ситуации 2.

Первый (лучший): сказать Linux чтоб он опрашивал Interrupt In EP (как и написано в её дескрипторе) и буферизировал прочитанные данные (как Win). Но как это сделать я не знаю (невозможно?).

Второй (вынужденный): повесить на таймер программку, которая будет запускаться 1 раз в 2 милисекунды (реал тайм!). И будет читать Interrupt In EP (ReadFile) и буферизировать прочитанное. Как это сделать я тоже не знаю, но наверное смогу разобраться.

 

А может ещё какие способы имеются?

Share this post


Link to post
Share on other sites
Первый (лучший): сказать Linux чтоб он опрашивал Interrupt In EP (как и написано в её дескрипторе) и буферизировал прочитанные данные (как Win). Но как это сделать я не знаю (невозможно?).

Второй (вынужденный): повесить на таймер программку, которая будет запускаться 1 раз в 2 милисекунды (реал тайм!). И будет читать Interrupt In EP (ReadFile) и буферизировать прочитанное. Как это сделать я тоже не знаю, но наверное смогу разобраться.

 

А может ещё какие способы имеются?

При втыкании устройства Вы получаетет в логах сообщение типа

Apr  9 11:02:16 fox kernel: HID device claimed by neither input, hiddev nor hidraw

Если ни один драйвер не "зацепился" за Ваше устройство, то Linux переведет его в Suspend и забудет о его существовании до тех пор, пока кто нибудь не зацепится за него.

Это может быть как драйвер, так и userspace программа, например через libusb usb_clame_interface.

Вероятно Ваше устройство не соответствует ни одному из драйверов. Драйверы как правило выполняют clame_interface если устройство получается "законченным", например клавиатура или мышь. А Ваше устройство не поддерживает всех ожидаемых драйвером запросов и репортов.

Третий вариант - посмотрите на кой из драйверов наиболее вероятно "зацепить" Ваше устройство (см. hiddev) и либо прописать ему Ваш VID/PID либо передать Ваш VID/PID при загрузке драйвера через modprobe.

Share this post


Link to post
Share on other sites
Подключаю свой самодельный Full Speed HID к Linux. У него имеются 3 вида репортов SetFeature, GetFeature и Input. SetFeature и GetFeature через шлются контрольный канал (адрес EP = 0) и работают без проблем. Даже лучше чем под Win т.к. позволяют задавать таймаут, а под Win таймаут =5 секундам и изменить невозможно. Input Report шлётся от устройства в комп через EP, работающую в режиме Interrupt In с интервалом опроса 2 милисекунды (так у меня в дескрипторе EP). И с ним проблемма.

Linux по своей инициативе вообще не шлёт никаких запросов. Если подключиться к устройству, то можно слать запросы (ReadFile). Но ни о каких 2 милисекундах и речи нет. Выполняешь ReadFile - запрос посылается. И буферизации никакой нет. Из-за этого Input репорты теряются. Особенно почему-то при выводе на экран. Т.е. какое-то время не опрашивали Interrupt In EP (переключились на другую задачу) - буфер в устройстве переполняется - данные теряются.

Выходов из этой ситуации 2.

Первый (лучший): сказать Linux чтоб он опрашивал Interrupt In EP (как и написано в её дескрипторе) и буферизировал прочитанные данные (как Win). Но как это сделать я не знаю (невозможно?).

Второй (вынужденный): повесить на таймер программку, которая будет запускаться 1 раз в 2 милисекунды (реал тайм!). И будет читать Interrupt In EP (ReadFile) и буферизировать прочитанное. Как это сделать я тоже не знаю, но наверное смогу разобраться.

 

А может ещё какие способы имеются?

Судя по исходникам драйвера hiddev в Linux'е, он умеет буферизовать принятые Interrupt данные (фиксированный буфер на 64 сообщения), но для этого устройство должно быть открыто (open).

Share this post


Link to post
Share on other sites
Вероятно Ваше устройство не соответствует ни одному из драйверов. Драйверы как правило выполняют clame_interface если устройство получается "законченным", например клавиатура или мышь. А Ваше устройство не поддерживает всех ожидаемых драйвером запросов и репортов.

Да, не поддерживает. У Linux на уровне ядра, как я понял, из HID устройств поддерживаются только

 47 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
48                                 "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};

И больше вариантов вроде как и нет. Т.е. они взяли Generic Desktop Page (0x01) и из неё 8 первых устройств:

00 Undefined
01 Pointer CP 4.1
02 Mouse CA 4.1
03 Reserved
04 Joystick CA 4.1
05 Game Pad CA 4.1
06 Keyboard CA 4.1
07 Keypad CA 4.1
08 Multi-axis Controller CA 4.1

Попробую я чем нибудь из этого списка заделаться, но не уверен, что получится. Сейчас у меня: FF00-FFFF Vendor-defined Usage Page.

 

2 XVR - А где вы буферизацию input репортов в hiddev нашли? Я что-то не нашёл.

Третий вариант - посмотрите на кой из драйверов наиболее вероятно "зацепить" Ваше устройство (см. hiddev) и либо прописать ему Ваш VID/PID либо передать Ваш VID/PID при загрузке драйвера через modprobe.

У моего устройства VID=PID=0 и под Win драйвер для него грузится по коду класса (3=HID) в дескрипторе интерфейса. Кроме того моё устройство должно работать при втыкании в любой компьютер без к.л. настроек, чтоб его мог запустить любой чайник. Оно составное и помимо HID содержит в себе ещё Mass Storage. И вот с этого Mass Stogage программа-то и должна запускаться. Причём на каком компьютере я не знаю и соотв-нно настраивать там ничего нельзя. Под Win всё проходит на ура. А сейчас Linux стал распостранятся, вот я и под Linux версию решил сделать. И под Linux работало до тех пор пока я Input Report (через Interrupt In EP) не ввёл. Хотя под Linux приходится задавать права доступа в файле udev.rules, что не есть гуд.

А вот, что пишется в dmesg:

usb 2-1: new full speed USB device using uhci_hcd and address 7
usb 2-1: device descriptor read/all, error -71
usb 2-1: new full speed USB device using uhci_hcd and address 9
usb 2-1: device not accepting address 9, error -32
usb 2-1: new full speed USB device using uhci_hcd and address 10
usb 2-1: configuration #1 chosen from 1 choice
scsi7 : SCSI emulation for USB Mass Storage devices
usb-storage: device found at 10
usb-storage: waiting for device to settle before scanning
drivers/usb/input/hid-core.c: ctrl urb status -75 received
drivers/usb/input/hid-core.c: ctrl urb status -75 received
HID device not claimed by input or hiddev
  Vendor: Dinas     Model: Build-in F-Disk   Rev: 1.00
    Type:   Direct-Access                      ANSI SCSI revision: 00
    SCSI device sdh: 8192 1024-byte hdwr sectors (8 MB)
    sdh: Write Protect is on
    sdh: Mode Sense: 23 00 80 00
    sdh: assuming drive cache: write through
    SCSI device sdh: 8192 1024-byte hdwr sectors (8 MB)
    sdh: Write Protect is on
    sdh: Mode Sense: 23 00 80 00
    sdh: assuming drive cache: write through
     sdh: unknown partition table
     sd 7:0:0:0: Attached scsi removable disk sdh
     usb-storage: device scan complete

Ошибки в начале - это когда я STALL посылаю в ответ на запросы GetFeaure репортов. Некоторые из репортов у меня только для записи, а Linux прочесть пытается. Зачем? Для кэширования что-ли?

 

Думаю, что так и придётся по таймеру чтение Input репортов делать. Вроде никаких граблей там не предвидится. Или я сильно заблуждаюсь?

Share this post


Link to post
Share on other sites
2 XVR - А где вы буферизацию input репортов в hiddev нашли? Я что-то не нашёл.

 

hid_irq_in (usbhid/hid-core.c) -> hid_input_report (hid-core.c) -> hid_input_field (hid-core.c) -> hid_process_event (hid-core.c) -> hiddev_hid_event (usbhid/hid-core.c) -> hiddev_send_event (usbhid/hid-core.c)

 

строка 171

 

list->buffer[list->head] = *uref;

list->head = (list->head + 1) &

(HIDDEV_BUFFER_SIZE - 1);

 

HIDDEV_BUFFER_SIZE равен 64

Потом hiddev_read читает из этого списка

 

event.hid = list->buffer[list->tail].usage_code;

event.value = list->buffer[list->tail].value;

if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))

return -EFAULT;

Edited by XVR

Share this post


Link to post
Share on other sites
Да, не поддерживает. У Linux на уровне ядра, как я понял, из HID устройств поддерживаются только

 47 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
48                                 "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};

Да. Правильно поняли.

Но!

Если Вы не хотите делать полный поддерживаемый девайс - не делайте.

Об этом чуть ниже.

У моего устройства VID=PID=0 и под Win драйвер для него грузится по коду класса (3=HID) в дескрипторе интерфейса.

Ну это не есть хорошо. Фактически Вы используете глюк в ОС. Известный глюк и им многие ползуются и, видимо, это будет продолжаться долго, потому как сама Windows этим глюком ползуется.

А вот, что пишется в dmesg:

usb 2-1: new full speed USB device using uhci_hcd and address 7
usb 2-1: device descriptor read/all, error -71
usb 2-1: new full speed USB device using uhci_hcd and address 9
usb 2-1: device not accepting address 9, error -32
usb 2-1: new full speed USB device using uhci_hcd and address 10

Ошибки в начале - это когда я STALL посылаю в ответ на запросы GetFeaure репортов. Некоторые из репортов у меня только для записи, а Linux прочесть пытается. Зачем? Для кэширования что-ли?

Это плохо. Это не похоже на то о чем Вы говорите. Хотя я не работал с "репортами только для чтения".

Это точно сами репорты? Или это попытка прочитать ReportDescriptor? Дескриптор то должен читаться.

Думаю, что так и придётся по таймеру чтение Input репортов делать. Вроде никаких граблей там не предвидится. Или я сильно заблуждаюсь?

Я не проверял на постоянность опроса нестандартного USB HID но такое устройство делал.

Попробуйте вот что.

Возмите libusb, она есть во всех дистрах Linux. Там есть пример. Попробуйте просто открыть Ваш USB HID и посмотреть, идет ли опрос с нужным интервалом, если Вы не запрашиваетет из программы его.

То есть просто открыть и все. Не читать и не писать.

Если идут - дальше уже решайте сами. Если нет, ну тоже решайте сами, но я бы порекомендовал написать драйвер. Возмите пример и модифицируйте его. Пример лежит прямо в дереве исходников ядра. drivers/usb/usb-skeleton.c. Но не пытайтесь повторить один из HID драйверов, а делайте как Вам надо.

 

Да еще вот что. В Lnux RootHUB можно открыть с помощью libusb по VID/PID = 0. Так что Вы пока поменяйте VID/PID на что нибудь отличное от нуля и 0xFFFF. И проверте опрос.

 

А в Windows устройство опрашивается всегда, не зависимо от того, есть ли штатный драйвер именно этого устройства или нет.

В Linux если нет драйвера - то об устройстве ОС "забывает до востребования", то есть пока кто нибудь не откроет это устройство.

Edited by amw

Share this post


Link to post
Share on other sites
Это плохо. Это не похоже на то о чем Вы говорите. Хотя я не работал с "репортами только для чтения".

Это точно сами репорты? Или это попытка прочитать ReportDescriptor? Дескриптор то должен читаться.

ReportDescriptor (USAGE) точно читается правильно. Во первых, никаких посылок STALL, повторов и т.п. нет. Во вторых, под Win всё работает, а Win не даст пользоваться Set(Get)Feature репортом если он в USAGE неправильно описан и, скорее всего, всем устройством не даст пользоваться (жёлтый вопросительный знак поставит в диспетчере устройств). В третьих, Linux последовательно читает все мой Feature репорты, причём сразу-же с правильной длиной в пакете запроса (SETUP). А эту длину он мог узнать только из моих ReportDescriptor (USAGE). Откуда же ещё?

А Feature репорты можно описать как "только для чтения", но как "только для записи" невозможно. Я сделал так, как мне удобно было, поэтому некоторые только GetFeature, некоторые Get и Set, а некоторые только Set у меня получились. Я-то считал, что никто кроме меня этим пользоваться не будет. И если приходит запрос (SETUP пакет) на чтение (GetFeature) такого репорта (который у меня только для записи) я STALL возвращаю. Не на SETUP пакет конечно, а на маркер IN. В логах (под Linux) это отлично видно. Попробую конечно какую-нибудь ерунду в данных вернуть, но не думаю, что от этого что-то изменится.

Я не проверял на постоянность опроса нестандартного USB HID но такое устройство делал.

Попробуйте вот что.

Возмите libusb, она есть во всех дистрах Linux. Там есть пример. Попробуйте просто открыть Ваш USB HID и посмотреть, идет ли опрос с нужным интервалом, если Вы не запрашиваетет из программы его.

То есть просто открыть и все. Не читать и не писать.

Если идут - дальше уже решайте сами. Если нет, ну тоже решайте сами, но я бы порекомендовал написать драйвер. Возмите пример и модифицируйте его. Пример лежит прямо в дереве исходников ядра. drivers/usb/usb-skeleton.c. Но не пытайтесь повторить один из HID драйверов, а делайте как Вам надо.

Обязательно попробую, и о результатах сообщу, но попозже. Т.к. вариант с драйвером не устроит заказчиков. Им надо чтоб любой чайник без специалистов (секретарша, которая кроме ворда ничего не знает) мог бы наше устойство в свой комп воткнуть, мышкой на экзешник нажать, и логи прочесть. А драйвер устанавливать это слишком сложно и долго. Они боятся нашего устройства будут. Хотя если у них Linux стоит...

 

Насчёт VID=PID=0. Ну не хочу я по $4000 каждые 2 года платить. Из принципа не хочу, т.к. VID мне и не нужен совсем.

 

А вообще 'amw' и 'XVR', спасибо за ответы. Я сейчас сильно занят, и много времени этой теме уделять не могу. Сейчас заказчику другую тему сдаём... Поэтому за задержки заранее извиняюсь. Но недельки через две обязательно займусь вплотную.

Share this post


Link to post
Share on other sites
А Feature репорты можно описать как "только для чтения", но как "только для записи" невозможно.

А понял, ну тогда понятно откуда в логах ошибки.

Насчёт VID=PID=0. Ну не хочу я по $4000 каждые 2 года платить. Из принципа не хочу, т.к. VID мне и не нужен совсем.

Ну Вы для пробы поставте что-нибудь отличное от нуля, для проверки.

Но недельки через две обязательно займусь вплотную.

Это будет весьма полезно узнать.

Share this post


Link to post
Share on other sites
А понял, ну тогда понятно откуда в логах ошибки.

Переделал свой HID так, чтоб он на запросы GetFeature всегда отвечал. Всякой ерундой. Ну чтоб ошибок не было.

Вот что получил:

localhost:/sys/kernel/debug/usbmon# cat ./4t
da83ac40 3676751407 C Ii:001:01 0 1 = 02; Что это такое - мой NAK на Interrupt In что-ли?
da83ac40 3676751423 S Ii:001:01 -115 2 <; #define    EINPROGRESS    115    /* Operation now in progress */ - не понял
cec1d840 3676751443 S Ci:001:00 s a3 00 0000 0001 0004 4 <
cec1d840 3676751448 C Ci:001:00 0 4 = 01010100
cec1d840 3676751451 S Co:001:00 s 23 01 0010 0001 0000 0
cec1d840 3676751454 C Co:001:00 0 0
cec1d840 3676751457 S Ci:001:00 s a3 00 0000 0001 0004 4 <
cec1d840 3676751461 C Ci:001:00 0 4 = 01010000
d4f2b1c0 3676783188 S Ci:001:00 s a3 00 0000 0001 0004 4 <
d4f2b1c0 3676783212 C Ci:001:00 0 4 = 01010000
d4f2b1c0 3676815189 S Ci:001:00 s a3 00 0000 0001 0004 4 <
d4f2b1c0 3676815212 C Ci:001:00 0 4 = 01010000
d4f2b1c0 3676847141 S Ci:001:00 s a3 00 0000 0001 0004 4 <
d4f2b1c0 3676847163 C Ci:001:00 0 4 = 01010000
d4f2b1c0 3676879183 S Ci:001:00 s a3 00 0000 0001 0004 4 <
d4f2b1c0 3676879200 C Ci:001:00 0 4 = 01010000
d4f2b1c0 3676879240 S Co:001:00 s 23 03 0004 0001 0000 0
d4f2b1c0 3676879247 C Co:001:00 0 0
d4f2b1c0 3676935136 S Ci:001:00 s a3 00 0000 0001 0004 4 <
d4f2b1c0 3676935168 C Ci:001:00 0 4 = 03010000
d4f2b1c0 3676991145 S Co:001:00 s 23 01 0014 0001 0000 0
d4f2b1c0 3676991156 C Co:001:00 0 0
d4f2b1c0 3676991186 S Ci:000:00 s 80 06 0100 0000 0040 64 <
d4f2b1c0 3676995400 C Ci:000:00 0 18 = 12010001 00000040 00000000 04010102 0301
d4f2b1c0 3676995429 S Co:001:00 s 23 03 0004 0001 0000 0
d4f2b1c0 3676995434 C Co:001:00 0 0
da83ac40 3677003146 C Ii:001:01 0 1 = 02; Вот здесь тоже
da83ac40 3677003165 S Ii:001:01 -115 2 <
d4f2b1c0 3677051186 S Ci:001:00 s a3 00 0000 0001 0004 4 <
d4f2b1c0 3677051235 C Ci:001:00 0 4 = 03010000
d4f2b1c0 3677107114 S Co:001:00 s 23 01 0014 0001 0000 0
d4f2b1c0 3677107124 C Co:001:00 0 0
d4f2b1c0 3677107132 S Co:000:00 s 00 05 001b 0000 0000 0
d4f2b1c0 3677109406 C Co:000:00 0 0
d4f2b1c0 3677127115 S Ci:027:00 s 80 06 0100 0000 0012 18 <
d4f2b1c0 3677130403 C Ci:027:00 0 18 = 12010001 00000040 00000000 04010102 0301
d4f2b1c0 3677130441 S Ci:027:00 s 80 06 0200 0000 0009 9 <
d4f2b1c0 3677134394 C Ci:027:00 0 9 = 09023900 02010080 31
d4f2b1c0 3677134422 S Ci:027:00 s 80 06 0200 0000 0039 57 <
d4f2b1c0 3677138421 C Ci:027:00 0 57 = 09023900 02010080 31090400 00020806 50000705 81024000 00070502 02400000
ca2b9540 3677138485 S Ci:027:00 s 80 06 0300 0000 00ff 255 <
ca2b9540 3677143403 C Ci:027:00 0 6 = 06030904 1904
ca2b9540 3677143459 S Ci:027:00 s 80 06 0302 0409 00ff 255 <
ca2b9540 3677149394 C Ci:027:00 0 68 = 44034100 6e007400 65006c00 2d005200 53003400 38003500 20007600 31002e00
ca2b9540 3677149468 S Ci:027:00 s 80 06 0301 0409 00ff 255 <
ca2b9540 3677154393 C Ci:027:00 0 22 = 16034400 69006e00 61007300 20004c00 74006400 2e00
ca2b9540 3677154438 S Ci:027:00 s 80 06 0303 0409 00ff 255 <
ca2b9540 3677159394 C Ci:027:00 0 26 = 1a033000 30003000 30003000 30003000 30003100 30003000 3000
ca2b9540 3677159660 S Co:027:00 s 00 09 0001 0000 0000 0
ca2b9540 3677162392 C Co:027:00 0 0
ca2b96c0 3677171797 S Co:027:00 s 21 0a 0000 0001 0000 0
ca2b96c0 3677173394 C Co:027:00 0 0
ca2b96c0 3677173415 S Ci:027:00 s 81 06 2200 0001 00dd 221 <
ca2b96c0 3677174388 C Ci:027:00 0 221 = 0610ff09 01a10209 20850175 08150026 ff00963f 00b18209 21850296 1300b182
c9c73540 3677174633 S Ci:027:00 s 80 06 0303 0409 00ff 255 <
c9c73540 3677176392 C Ci:027:00 0 26 = 1a033000 30003000 30003000 30003000 30003100 30003000 3000
c9c73540 3677176419 S Ci:027:00 s a1 01 0118 0001 0040 64 <;это у меня Input репорт, но через EP 0 тоже выдаётся (для совместимости)
c9c73540 3677177389 C Ci:027:00 0 64 = 18033000 30003000 30003000 30003000 30003100 30003000 30000000 00000500
c9c73540 3677177406 S Ci:027:00 s a1 01 0301 0001 0040 64 <; начались GetFeature ...
c9c73540 3677178393 C Ci:027:00 0 64 = 010201e8 03020202 08020301 01040400 00e10000 00000000 00000000 00000000
c9c73540 3677178404 S Ci:027:00 s a1 01 0302 0001 0014 64 <
c9c73540 3677180399 C Ci:027:00 0 20 = 020105fa 000000ff 01000005 090000e8 0317fcaa
c9c73540 3677180418 S Ci:027:00 s a1 01 0303 0001 0006 64 <
c9c73540 3677182395 C Ci:027:00 0 6 = 03000000 0000
c9c73540 3677182411 S Ci:027:00 s a1 01 0304 0001 0006 64 <
c9c73540 3677184400 C Ci:027:00 0 6 = 04000000 0000
c9c73540 3677184414 S Ci:027:00 s a1 01 0305 0001 000c 64 <
c9c73540 3677186395 C Ci:027:00 0 12 = 05000f00 9600c800 32000000
c9c73540 3677186409 S Ci:027:00 s a1 01 0306 0001 0040 64 <
c9c73540 3677187391 C Ci:027:00 0 64 = 06048025 0000004b 00000096 000000e1 00000000 00000000 00000000 00000000
c9c73540 3677187401 S Ci:027:00 s a1 01 0307 0001 0009 64 <
c9c73540 3677189394 C Ci:027:00 0 9 = 07000103 08020200 00
c9c73540 3677189405 S Ci:027:00 s a1 01 0308 0001 0009 64 <
c9c73540 3677191391 C Ci:027:00 0 9 = 0800ff01 08000200 00
c9c73540 3677191403 S Ci:027:00 s a1 01 0309 0001 0022 64 <
c9c73540 3677193392 C Ci:027:00 0 34 = 09080000 00000000 00000000 07000000 00000000 00000000 00000000 00000000
c9c73540 3677193407 S Ci:027:00 s a1 01 030a 0001 0040 64 <
c9c73540 3677194397 C Ci:027:00 0 64 = 0a0b0c0d 14457461 20667566 656c2070 7265646e 617a6e61 34656e61 2032204c
c9c73540 3677194411 S Ci:027:00 s a1 01 030b 0001 0103 320 <; Вот здесь размер буфера больше (0x103=259)
c9c73540 3677196392 C Ci:027:00 0 259 = 0b0c0d14 45746120 66756665 6c207072 65646e61 7a6e6134 656e6120 32204c69
c9c73540 3677196421 S Ci:027:00 s a1 01 030c 0001 0040 64 <
c9c73540 3677197388 C Ci:027:00 0 64 = 0c0d1445 74612066 7566656c 20707265 646e617a 6e613465 6e612032 204c696e
c9c73540 3677197402 S Ci:027:00 s a1 01 030d 0001 0103 320 <; Вот здесь размер буфера больше (0x103=259)
c9c73540 3677199389 C Ci:027:00 0 259 = 0d144574 61206675 66656c20 70726564 6e617a6e 6134656e 61203220 4c696e75
c9c73540 3677199411 S Ci:027:00 s a1 01 030e 0001 0040 64 <
c9c73540 3677200390 C Ci:027:00 0 64 = 0e000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
c9c73540 3677200400 S Ci:027:00 s a1 01 030f 0001 0080 128 <
c9c73540 3677201388 C Ci:027:00 0 128 = 0f000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
c9c73540 3677201403 S Ci:027:00 s a1 01 0310 0001 0204 515 <;Вот здесь глюк (0x204=516), а буфер 515 байт - не хватает
c9c73540 3677203411 C Ci:027:00 -75 515 = 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
c9c73540 3677203443 S Ci:027:00 s a1 01 0311 0001 0040 64 <
c9c73540 3677204392 C Ci:027:00 0 64 = 11000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
c9c73540 3677204413 S Ci:027:00 s a1 01 0312 0001 0080 128 <
c9c73540 3677205401 C Ci:027:00 0 128 = 12000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
c9c73540 3677205422 S Ci:027:00 s a1 01 0313 0001 0204 515 <;Вот здесь такой-же глюк
c9c73540 3677207419 C Ci:027:00 -75 515 = 13000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
c9c73540 3677207461 S Ci:027:00 s a1 01 0314 0001 0040 64 <
c9c73540 3677208399 C Ci:027:00 0 64 = 14457461 20667566 656c2070 7265646e 617a6e61 34656e61 2032204c 696e7578
c9c73540 3677208416 S Ci:027:00 s a1 01 0316 0001 0180 384 <
c9c73540 3677210421 C Ci:027:00 0 384 = 16000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
c9c73540 3677210462 S Ci:027:00 s a1 01 0317 0001 0009 64 <;это последний GetFeature (тоже округлил)
c9c73540 3677212388 C Ci:027:00 0 9 = 17000000 00000000 00
c9c73540 3677212625 S Ci:001:00 s a3 00 0000 0001 0004 4 <
c9c73540 3677212633 C Ci:001:00 0 4 = 03010000
ca2b9540 3682170474 S Ci:027:00 s a1 fe 0000 0000 0001 1 <;это уже Mass Storage
И дальше пошли Mass Storage дела...

Ошибка 75 это:

#define EOVERFLOW 75 /* Value too large for defined data type */

Linux запросил 0x204=516 байта (как и д.б.), а буфер только 515 байт почему-то предоставил. Видимо этот глюк из-за того, что в дескрипторе репортов длина на 1 байт меньше описывается (0й байт у Feature всегда ReportID). И там у меня 515. Но в запросе-то 516 байт длина (правильная)! Я ему 516 байт и отправил. А он ошибку пишет.

А когда размер маленький он почему-то буфер в большую сторону до 64 округляет.

Но когда я в программе (под Linux) этим GetFeature пользуюсь - никакой ошибки нет. Видимо из-за того, что я сам размер буфера устанавливаю.

Наверное без ошибок (с точки зрения Linux) при больших размерах данных - вообще сделать невозможно.

Share this post


Link to post
Share on other sites
da83ac40 3676751407 C Ii:001:01 0 1 = 02; Что это такое - мой NAK на Interrupt In что-ли?

Устройство передало 1 байт равный 0x02. Что это - Вам решать.

da83ac40 3676751423 S Ii:001:01 -115 2 <; #define    EINPROGRESS    115    /* Operation now in progress */ - не понял

Поставлено в очередь. На очередном SOF (ближайшем свободном) будет инициирована USB транзакция.

da83ac40 3677003146 C Ii:001:01 0 1 = 02; Вот здесь тоже
da83ac40 3677003165 S Ii:001:01 -115 2 <

То же самое.

c9c73540 3677194411 S Ci:027:00 s a1 01 030b 0001 0103 320 <; Вот здесь размер буфера больше (0x103=259)

Больше чего? Больше запрашивает чем есть в наличии? Тогда нормально.

Меньше чем есть? Тогда выдавать сколько просит.

c9c73540 3677201403 S Ci:027:00 s a1 01 0310 0001 0204 515 <;Вот здесь глюк (0x204=516), а буфер 515 байт - не хватает

Не понял. Запрашивается 0x204 = 516 байт. Чего именно нехватает?

c9c73540 3677210462 S Ci:027:00 s a1 01 0317 0001 0009 64 <;это последний GetFeature (тоже округлил)

В большую сторону? Выдавайте сколько есть. А вообще то wLength = 9.

 

 

Ваше устройство HID значительно сложнее моего :) .

Вот снял с USB. На всякий случай.

usbmon.zip

Share this post


Link to post
Share on other sites
Устройство передало 1 байт равный 0x02. Что это - Вам решать.

 

Поставлено в очередь. На очередном SOF (ближайшем свободном) будет инициирована USB транзакция.

Разберусь токо чуть позже. EP N1 у меня Mass Storage это к нему относится видимо. Это ведь к EP N1 относится? А вообще похоже на NAK.

Больше чего? Больше запрашивает чем есть в наличии? Тогда нормально.

Меньше чем есть? Тогда выдавать сколько просит.

Нет, длина запроса верная. Я и шлю 259 байт. А 320 буфер в Linux видимо.

Не понял. Запрашивается 0x204 = 516 байт. Чего именно нехватает?

Размера буфера не хватает (внутреннего буфера у Linux). 515, как я понял, это размер буфера (из URB запроса?). Я как и положено 516 байт шлю - в буфер не лезет - отсюда и ошибка. Пытаюсь разобраться с исходниками - похоже там глюк. В случае Feature +1 не добавляется (в случае Input добавляется). Там какие-то мраки с выяснением кому буфер самый большой нужен. В моём случае это д.б. Feature - 516 байт. Сейчас только поверхностно глянул - некогда.

В большую сторону? Выдавайте сколько есть. А вообще то wLength = 9.

Да именно так и делаю - 9 байт передаю. Тут буфера (64) хватает - ошибки нет.

Ваше устройство HID значительно сложнее моего :) .

Вот снял с USB. На всякий случай.

У вас Feature нет. И ещё кой-какие вопросики имеются. Разберусь получше, и позже напишу - сейчас занят.

 

вот что теперь в dmesg:

usb 2-1: new full speed USB device using uhci_hcd and address 2
usb 2-1: configuration #1 chosen from 1 choice
scsi3 : SCSI emulation for USB Mass Storage devices
usb-storage: device found at 2; а это не та ли двойка ?
usb-storage: waiting for device to settle before scanning
drivers/usb/input/hid-core.c: ctrl urb status -75 received; вот ошибка N1
drivers/usb/input/hid-core.c: ctrl urb status -75 received; вот N2
HID device not claimed by input or hiddev
  Vendor: Dinas     Model: Build-in F-Disk   Rev: 1.00
  Type:   Direct-Access                      ANSI SCSI revision: 00
SCSI device sdf: 8192 1024-byte hdwr sectors (8 MB)
sdf: Write Protect is on
sdf: Mode Sense: 23 00 80 00
sdf: assuming drive cache: write through
SCSI device sdf: 8192 1024-byte hdwr sectors (8 MB)
sdf: Write Protect is on
sdf: Mode Sense: 23 00 80 00
sdf: assuming drive cache: write through
sdf: unknown partition table
sd 3:0:0:0: Attached scsi removable disk sdf
usb-storage: device scan complete

Share this post


Link to post
Share on other sites
Разберусь токо чуть позже. EP N1 у меня Mass Storage это к нему относится видимо. Это ведь к EP N1 относится? А вообще похоже на NAK.

da83ac40 3676751407 C Ii:001:01 0 1 = 02; Что это такое - мой NAK на Interrupt In что-ли?

Ну первые 2 числа пропускаем, они нам не интересны сейчас.

Дальше:

C - CallBack. - Эта строка получена из CallBack функции драйвера.

Ii - Interrupt In транзакция.

001 - Адрес Устройства. Вроде адр=1 должен быть у корневого хаба. Он первым подключается на шину и ему и попадает адрес 1.

01 - номер конечной точки.

0 - статус, проускаем.

1 - количество байт.

= - значит дальше данные.

02 - собственно данные.

 

Убедитесь, что адрес - вашего устройства.

 

вот что теперь в dmesg:

usb 2-1: new full speed USB device using uhci_hcd and address 2
...
usb-storage: device found at 2; а это не та ли двойка ?

Оставил только двойки. Вот эта двойка.

Не помню точно, либо адрес либо шина.

 

Перевтыкните и посмотрите, будет ли тройка.

И потом воткните в другой порт. И посмотрите на четверку.

:) .

Share this post


Link to post
Share on other sites
Насчёт VID=PID=0. Ну не хочу я по $4000 каждые 2 года платить. Из принципа не хочу, т.к. VID мне и не нужен совсем.

 

Замечу, что VID покупается один раз за 2000$ Он остается у вас и ничего больше платить не надо.

 

Если же вы захотите использовать USB логотип, то тогда вам надо заплатить 4000$ за членство в USB SIG. Его надо возобновлять каждые два года. Вместе с этим членством автоматом выдается и VID. Кстати, еще необходимо пройти сертификцию, что ваш прибор удовлетворяет USB спецификации и "быть готовым по требованию предоставить несколько приборов для проверки в любое время"

Share this post


Link to post
Share on other sites
Замечу, что VID покупается один раз за 2000$ Он остается у вас и ничего больше платить не надо.

А вы сами купили VID, или знаете тех, кто купил? В России купить можно? $2000 конечно тоже жалко выбрасывать, но это лучше чем $4000 раз в 2 года.

Если же вы захотите использовать USB логотип

Не, логотип мне не нужен.

Share this post


Link to post
Share on other sites
Вот снял с USB. На всякий случай.

Это оттуда:

    MaxPower              100mA; Рекомендую ставить 98mA.
......
            Item(Global): Report Count, data= [ 0x40 ] 64
            Item(Global): Report Size, data= [ 0x08 ] 8
           ; тут желательно описать Logical Minimum = 0 (0x15, 0x00) и
           ; Logical Maximum = FF (0x26, 0xFF, 0x00)
......
            Item(Main  ): Input, data= [ 0x00 ] 0; для него есть Interrupt In EP
......
            Item(Global): Report Count, data= [ 0x40 ] 64
            Item(Global): Report Size, data= [ 0x08 ] 8; Второй раз описывать не обязательно
            Item(Main  ): Output, data= [ 0x00 ] 0; Output репорт обычно передаётся через Interrupt Out
......

У вас описаны Input и Output репорты. Для Input репорта имеется Interrupt In EP, а для Output репорта нет Interrupt Out EP. Т.е. Output будет передаваться через контрольный канал (EP N0). В таком случае я не вижу никаких преимуществ перед Feature репортом. Хотя с Output репортами не работал (именно из-за того, что преимуществ не нашёл). Единственное отличие - вместо WriteFile у Output, у Feature работа через API.

C - CallBack. - Эта строка получена из CallBack функции драйвера.

Ii - Interrupt In транзакция.

001 - Адрес Устройства. Вроде адр=1 должен быть у корневого хаба. Он первым подключается на шину и ему и попадает адрес 1.

01 - номер конечной точки.

0 - статус, проускаем.

1 - количество байт.

= - значит дальше данные.

02 - собственно данные.

Спасибо за разъяснения. Вы это узнали копаясь в исходниках, или документация имеется? Мне только догадываться приходилось.

Кстати насчёт размера буфера - это я правильно догадался? Если правильно - надо будет сообщение в Linux послать. Пусть ошибку у себя исправят.

 

Сейчас пытаюсь опрос Interrupt In EP по таймеру сделать. Что-то в этом случае ReadFile очень долго выполняется - чуть-ли не 5 милисекунд. Видимо планировщику кадров USB задание даётся, а он только в следующий кадр USB опрос Interrupt In EP вставляет. А всё это время весь поток висит. Хотя это только 2 милисекунды д.б. максимум.

Сейчас разбираюсь нет-ли какого способа по прерыванию от USB всё это сделать. Или это только драйвер так работать может?

Или по другому: сначала опрос инициировать, а потом через 2 милисекунды результаты прочесть.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this