Bug 1660

Summary: Разработка поддержки драйверов USB-устройств
Product: WINE@Etersoft Reporter: Александр Морозов <amorozov>
Component: ОбщееAssignee: Александр Морозов <amorozov>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P5 CC: lav, triada123
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on:    
Bug Blocks: 775, 54    
Attachments: Записи в реестре, необходимые для использования под Wine ключа Eutron с драйвером eusk3usb.sys
Записи в реестре, необходимые для использования под Wine ключа SafeNet USB SuperPro/UltraPro с драйвером sntnlusb.sys

Description Александр Морозов 2008-04-09 19:56:10 MSD
В Wine нет поддержки WinNT-драйверов USB-устройств. Теоретически её можно реализовать с помощью libusb, позволяющей работать с устройствами в Linux в user-mode.
Comment 1 Александр Морозов 2008-04-09 20:04:21 MSD
Написан "пустой" тестовый драйвер, работающий в WinXP, и обращающаяся к нему программа. Драйвер создаёт файл устройства и обрабатывает вызовы CreateFile, DeviceIoControl и CloseHandle. Под Wine драйвер обрабатывает DeviceIoControl, а обработчики для CreateFile и CloseHandle не вызываются.

Драйвер собирался с помощью WinDDK в Windows.
Comment 2 Александр Морозов 2008-04-11 20:03:08 MSD
Драйвер был модифицирован. Добавлены обработка IOCTL-запроса, при которой происходит получение дескриптора USB-устройства, и процедура AddDevice (её добавление вызвано необходимостью подключения к объекту устройства нижележащего драйвера). После модификации драйвер перестал корректно запускаться с помощью добавления записи в раздел реестра Services. По-видимому, надо создать inf-файл и установить драйвер для какого-нибудь USB-устройства.
Comment 3 Александр Морозов 2008-04-14 19:30:14 MSD
Драйвер успешно установлен в Windows с помощью INF-файла. При обработке IOCTL_DESCRIPTOR_REQUEST_TEST он успешно получает vid и pid устройства.
Comment 4 Александр Морозов 2008-04-15 15:45:26 MSD
Установка драйвера с помощью inf-файла в Wine, по-видимому, не поддерживается (нет "Диспетчера устройств" и не реализована UpdateDriverForPlugAndPlayDevices). Поэтому драйвер в Wine был уставновлен с помощью экспорта записей реестра, создаваемых при установке драйвера в Windows, и копирования файла драйвера в windows\system32\drivers.

Под Wine не выполняется AddDevice. В Windows она выполняется при добавлении устройства и при его включении.
Comment 5 Александр Морозов 2008-04-16 19:32:20 MSD
Функции AddDevice необходимо передать в качестве аргументов указатели на объект драйвера (DRIVER_OBJECT) и на объект устройства (DEVICE_OBJECT) нижележащего драйвера. Экземпляр структуры объекта драйвера является глобальной переменной в device.c (programs/winedevice).

Принято решение реализовать вызов AddDevice через запросы к wineserver. Когда надо будет вызвать AddDevice, будет совершаться запрос к серверу с указанием имени драйвера, для которого надо вызвать AddDevice. winedevice будет периодически опрашивать сервер, есть ли запросы на выполнение AddDevice для драйвера с таким именем.
Comment 6 Александр Морозов 2008-04-17 19:23:09 MSD
Вызов AddDevice реализован. Реализация неидеальна, AddDevice пока можно вызвать для каждого драйвера только один раз. Перед вторым вызовом AddDevice надо ещё раз загрузить драйвер.
Comment 7 Александр Морозов 2008-04-18 20:20:47 MSD
Добавлено некоторое количество функций в ntoskrnl.exe (в основном это стабы), изменена функция IofCompleteRequest (теперь она вызывает IoFreeIrp). Загрузка драйвера и выполнение работающей с ним программы проходят без крэша wine.

Надо реализовать несколько функций для работы с IRP, IoAttachDeviceToDeviceStack и IofCallDriver. После этого можно будет приступать к доработке wineusb.
Comment 8 Александр Морозов 2008-04-18 20:24:04 MSD
wineusb - сервис, который будет вызывать AddDevice для USB-устройств и, если необходимо, загружать драйверы. Сейчас он вызывает AddDevice для тестового драйвера.
Comment 9 Александр Морозов 2008-04-18 20:31:44 MSD
Кроме того wineusb будет обрабатывать IRP, предназначенные для драйвера, расположенного в стеке под функциональным драйвером USB-устройства.
Comment 10 Александр Морозов 2008-04-21 20:49:44 MSD
Небольшие изменения уже реализованных функций из ntoskrnl.exe. Начата реализация IofCallDriver.
Comment 11 Александр Морозов 2008-04-22 20:25:05 MSD
Добавлена DLL wineusbhub. Она обрабатывает запросы к драйверу более низкого уровня. На данный момент работает получение выполняющимся в Wine WDM-драйвером VID и PID USB-устройства. При этом драйвер работает с первым попавшимся USB-устройством. В будущем wineusb будет сообщать драйверу, с каким устройством ему следует работать.

Имеется проблема с запуском драйвера. Программа может обратиться к файлу устройства до того, как он будет создан драйвером. Пока проблема решена переносом вызовов usb_init() и т.п. в DllMain wineusbhub.c.

Есть небольшой баг при получении размеров данных, передаваемых wineserver`у при запросе call_add_device.
Comment 12 Александр Морозов 2008-04-23 19:25:28 MSD
Исправлен баг в запросе к wineserver.

Добавлены dlls/usbd.sys и несколько стабов в ntoskrnl.exe. Это позволило запустить драйвер ключа Eutron 3. Драйвер падает при выполнении AddDevice при записи по нулевому указателю:
0012:Call KERNEL32.InterlockedExchange(00000000,0011b970) ret=0056398e
Comment 13 Александр Морозов 2008-04-24 19:21:29 MSD
Проблема с InterlockedExchange решена. Добавлено ещё несколько стабов. Теперь выполнение AddDevice для драйвера eusk3usb.sys (ключ Eutron 3) проходит до конца без падений.

Попробовал запустить тестовую программу из Гектор`а под Wine вместе с родным драйвером (кстати, проверил, что под Windows всё работает). Программа не находит ключа. При этом происходит обращение к создаваемому драйвером устройству Skey----. Подозрительно, что при этом в логах есть лишь вызовы KeWaitForSingleObject и KeReleaseMutex и нет, например, обращений к нижележащему драйверу с помощью IofCallDriver. Скорее всего это связано с неполным (или неправильным) заполнением структуры IRP. Происходит также обращение к отсутствующим устройствам SkeyDev0, ..., SkeyDev2. В Windows эти устройства драйвером не создаются (это можно увидеть с помощью DeviceTree), так что скорее всего это не является причиной проблемы под Wine.
Comment 14 Александр Морозов 2008-04-25 19:20:41 MSD
В ntoskrnl.exe добавлено ещё несколько стабов. В programs/winedevice/device.c после AddDevice добавлен вызов MajorFunction[IRP_MJ_PNP] с IRP_MN_START_DEVICE. При его выполнении таки вызывается IofCallDriver. Но при обработке IOCTL драйвер пока ещё не хочет обращаться к ключу.
Comment 15 Александр Морозов 2008-04-28 20:13:40 MSD
Немного модифицирован programs/winedevice/device.c (более корректное поведение при отсутствии USB-устройств и при неудачном завершении AddDevice). Реализовано получение дескриптора конфигурации (для случая num_altsetting == 1). Добавлено 2 стаба в usbd.sys.
Comment 16 Александр Морозов 2008-04-29 20:19:52 MSD
Реализованы USBD_CreateConfigurationRequestEx и обработка URB_FUNCTION_VENDOR_DEVICE. Функция драйвера, обрабатывающая IRP_MN_START_DEVICE, теперь завершается нормально. Но тем не менее тестовая программа ключ по-прежнему не видит.
Comment 17 Александр Морозов 2008-04-30 21:24:08 MSD
Добавил вызов IofCompleteRequest в обработчики IRP_MJ_INTERNAL_DEVICE_CONTROL и IRP_MJ_PNP в wineusbhub (драйвер, находящийся в стеке под драйвером USB-ключа). При этом для вызова IofCompleteRequest пришлось сделать обёртку, так как это fastcall-функция. Добавил вызов CompletionRoutine в IofCompleteRequest.

Добиться правильной работы обращающейся к драйверу тестовой программы пока не удалось. Возможно, стоит создать тестовый драйвер, создающий те же объекты устройств, запустить тестовую программу вместе с ним под Windows, посмотреть, какие структуры IRP получает драйвер, и воспроизвести их в Wine.

Надо как-то освобождать память, выделенную для IRP, например, с помощью IoBuildDeviceIoControlRequest. И делать это надо тогда, когда IRP уже никем не используется. Пока что в ряде случаев происходит утечка памяти.
Comment 18 Александр Морозов 2008-05-04 19:32:49 MSD
Тестовая программа ключ не видит.

Написан тестовый драйвер, выводящий передаваемые ему структуры IRP, DEVICE_OBJECT и DRIVER_OBJECT.
Comment 19 Александр Морозов 2008-05-05 19:48:38 MSD
Тестовый драйвер запущен под Windows. Теперь известно, какие функции Windows вызывает при инициализации драйвера. Соответственно изменена инициализация драйвера в winedevice. Улучшена реализация IoAttachDeviceToDeviceStack.

Тестовая программа ключ не видит.
Comment 20 Александр Морозов 2008-05-06 19:18:16 MSD
Добиться работы тестовой программы с ключом Eutron пока не удалось.
Comment 21 Александр Морозов 2008-05-07 19:47:01 MSD
Тестовая программа ключ не видит.
Comment 22 Александр Морозов 2008-05-08 20:27:30 MSD
Пока не ясно, что надо изменить в Wine, чтобы тестовая программа не возвращала ошибку.
Comment 23 Александр Морозов 2008-05-12 16:08:09 MSD
В IofCompleteRequest теперь освобождается память, выделяемая для IRP в IoBuildDeviceIoControlRequest.
Comment 24 Александр Морозов 2008-05-14 15:44:04 MSD
Добавлены проверки на возврат NULL из функций выделения памяти в IoAllocateIrp и IoBuildDeviceIoControlRequest.
Comment 25 Александр Морозов 2008-05-27 14:28:30 MSD
Попробовал запустить Инфо-Бухгалтер 8.5 с ключом Sentinel UltraPro. Инициализация ключа проходит нормально. Драйвер создаёт файлы устройств skeysusb и SntnlUsb. При запуске программы происходит обращение к RNBODRV0, SntnlUsb и NVKEYNT, удачно завершается, разумеется, только для второго. Для SntnlUsb несколько раз вызывается DeviceIoControl. При его обработке обращения к устройству не происходит. Инфо-Бухгалтер говорит, что ключ не обнаружен.
Comment 26 Александр Морозов 2008-05-27 14:49:39 MSD
На машине с Windows кроме использовавшегося при запуске под Wine sntnlusb.sys есть ещё sentinel.sys и nvkeynt.sys. Я, правда, не уверен, имеют ли они отношение к данному ключу.
Comment 27 Михаил Карпухин 2008-05-27 15:01:46 MSD
(In reply to comment #26)
> На машине с Windows кроме использовавшегося
> при запуске под Wine sntnlusb.sys есть ещё sentinel.sys и
> nvkeynt.sys. Я, правда, не уверен, имеют ли они
> отношение к данному ключу.
> 

For Windows NT, 2000 and XP (32-bit), Server 2003 (32-bit) and Vista (32-bit) the
following driver files will be installed in the C:\Windows\system32\drivers directory.
• Sentinel.sys (Sentinel parallel driver) and
• Sntnlusb.sys (Sentinel USB driver).
Comment 28 Михаил Карпухин 2008-05-27 15:06:19 MSD
Драйверы Guardant и вспомогательные программы
Программы для управления драйверами:

INSTDRV.EXE – программа установки, конфигурации
и удаления драйверов.
INSTDRV.DLL – 16 битная библиотека, содержащая
функции API по управлению драйверами из
приложений.
INSTDRV.INI – конфигурационный файл.

Драйверы для Windows 95/98/ME:

NVKEY95.VX_         драйвер для Windows 95/98,
NVKEYU95.SYS        драйвер USB для Windows 95 OSR 2.x,
NVKEYUSB.SYS        драйвер USB для Windows 98,
NVKEY98U.SYS        вспомогательный драйвер USB для
Windows 98,
GSNUSB.IN_          служебный файл для драйверов USB.

Драйверы для Windows NT/2000/XP:

NVKEYNT.SYS         драйвер ядра,
NVKEYVDD.DLL        виртуальный драйвер для DOS,
NVKEY4NT.SYS        DOS драйвер устройства,
NVKEYUSB.SYS        драйвер USB для Windows 2000,
GSNUSB.IN_          служебный файл для драйвера USB
Comment 29 Александр Морозов 2008-05-27 19:11:20 MSD
Кроме 2 упомянутых выше устройств драйвер создаёт ещё одно безымянное, для которого он вызывает IoAttachDeviceToDeviceStack.
Comment 30 Александр Морозов 2008-05-28 17:56:29 MSD
Улучшена обработка запроса дескриптора конфигурации
Comment 31 Александр Морозов 2008-05-29 19:13:08 MSD
Небольшие изменения в инициализации IRP и DEVICE_OBJECT.

Изменено выравнивание структур дескрипторов в usb100.h, чтобы их размер был как в Windows. После этого изменения sntnlusb.sys стал падать с такой ошибкой:

wine: Unhandled page fault on read access to 0xcd290b26 at address 0x7eb89d8e (thread 001b), starting debugger...
err:seh:raise_exception Unhandled exception code c0000005 flags 0 addr 0x7bc40674

Адрес 0xcd290b26 каждый раз разный.
Comment 32 Александр Морозов 2008-05-30 19:17:13 MSD
Добавлена поддержка специфичных для конкретного устройства дескрипторов. sntnlusb.sys теперь не падает
Comment 33 Александр Морозов 2008-06-02 19:17:49 MSD
В KeInitializeEvent структура события теперь инициализируется почти как в Windows. В посылаемых драйверам IRP irp.IoStatus.u.Status устанавливается в STATUS_NOT_SUPPORTED.
Comment 34 Александр Морозов 2008-06-03 18:56:08 MSD
Добавил в тестовый драйвер вывод результатов обработки IRP_MN_QUERY_CAPABILITIES нижележащим драйвером.
Comment 35 Александр Морозов 2008-06-04 12:29:59 MSD
Частично реализована обработка IRP_MN_QUERY_CAPABILITIES
Comment 36 Александр Морозов 2008-06-05 18:28:40 MSD
Для идентификации USB-устройств теперь используются location из struct usb_bus и devnum из struct usb_device (это лучше использования vid и pid, так как позволит избежать проблем при исползовании 2-х одинаковых устройств). PDO для USB-устройств теперь именуются как в WinXP. При создании DEVICE_OBJECT теперь инициализируется поле Flags.
Comment 37 Александр Морозов 2008-06-06 17:43:08 MSD
Под WinXP Инфо-Бухгалтер передаёт драйверу ключа Sentinel не такой код IOCTL, как в Wine
Comment 38 Александр Морозов 2008-06-07 16:34:41 MSD
Если в WinXP отключить загрузку SENTINEL.SYS, то SNTNLUSB.SYS получает коды IOCTL такие же, как и в Wine.
Comment 39 Александр Морозов 2008-06-10 19:33:43 MSD
В Windows в зависимости от 2 младших бит кода IOCTL используются различные методы передачи данных между вызывающей DeviceIoControl функцией и драйвером. Код 22001c, с которым Инфо-Бухгалтер обращается к драйверу, соответствует METHOD_BUFFERED. В Wine нет выбора метода передачи в зависимости от кода IOCTL и используемый метод не METHOD_BUFFERED.
Comment 40 Александр Морозов 2008-06-11 18:42:26 MSD
Добавлена поддержка METHOD_BUFFERED в process_ioctl и URB_FUNCTION_VENDOR_INTERFACE в wineusbhub, добавлен KeResetEvent, а также произведено ещё несколько небольших исправлений.

Теперь работают Инфо-Бухгалтер с ключом Sentinel (драйвер sntnlusb.sys) и тестовая программа из Гектор`а с ключом Eutron (драйвер eusk3usb.sys). Для того чтобы пользоваться ключом, надо поместить его драйвер в system32/drivers и добавить в реестр запись о сервисе драйвера (в HKLM\System\CurrentControlSet\Services) и об устройстве (в HKLM\System\CurrentControlSet\Enum\USB).
Comment 41 Александр Морозов 2008-06-11 19:05:41 MSD
Created attachment 482 [details]
Записи в реестре, необходимые для использования под Wine ключа Eutron с драйвером eusk3usb.sys
Comment 42 Михаил Карпухин 2008-06-11 19:27:02 MSD
В какой сборке можно потестить сие чудо ?
Comment 43 Александр Морозов 2008-06-16 13:17:49 MSD
Когда будет сборка, не знаю, но думаю, что скоро
Comment 44 Александр Морозов 2008-06-16 13:20:33 MSD
Created attachment 485 [details]
Записи в реестре, необходимые для использования под Wine ключа SafeNet USB SuperPro/UltraPro с драйвером sntnlusb.sys
Comment 45 Vitaly Lipatov 2008-06-19 18:29:45 MSD
Сборка готова. На данный момент нужно проследить, чтобы были права доступа к usb-устройству ключа, ключ вставлен до запуска wine, а нужный драйвер лежал в system32/drivers
Comment 46 Александр Морозов 2008-07-14 16:45:45 MSD
Начато написание тестов для включения патчей в оригинальный wine. Создана основа тестов для ntoskrnl.exe: драйвер и загружающая его программа.
Comment 47 Александр Морозов 2008-07-16 20:00:21 MSD
Написал тест на обработку IOCTL. Правда, более-менее полноценно тестируется в нём только METHOD_BUFFERED, так как для тестирования METHOD_IN_DIRECT, METHOD_OUT_DIRECT и METHOD_NEITHER в Wine не хватает некоторых функций.
Comment 48 Александр Морозов 2008-07-18 18:17:08 MSD
Написал несколько тестов для IofCompleteRequest. Тесты проходят на WinXP. Оказалось, что реализованное в eterhack поведение достаточно плохо соответствует поведению Windows. Изменил IofCompleteRequest и IofCallDriver, чтобы они соответствовали тестам.
Comment 49 Александр Морозов 2008-07-22 19:58:16 MSD
Написан тест для IoAttachDeviceToDeviceStack
Comment 50 Александр Морозов 2008-07-29 18:26:53 MSD
Изменил Makefile.in тестов для ntoskrnl.exe. Теперь используемый в кросстесте драйвер собирается с использование библиотек из wine, а не из mingw. Оказалось, что при таком способе сборки нельзя использовать функции, определённые в ntoskrnl.exe.spec таким образом:
@ cdecl -private strcpy(ptr str) msvcrt.strcpy
Кросстест при их использовании не собирается. Зато теперь драйвер из кросстеста загружается и под Wine.

Сделал основу для тестов usbd.sys.
Comment 51 Александр Морозов 2008-07-30 20:11:08 MSD
Написал несколько тестов для USBD_CreateConfigurationRequest
Comment 52 Александр Морозов 2008-07-31 13:24:52 MSD
Написал тесты для USBD_CreateConfigurationRequestEx
Comment 53 Александр Морозов 2008-07-31 15:53:56 MSD
Благодаря тестам выяснилось, что реализованная в eterhack USBD_CreateConfigurationRequestEx при определённых условиях зацикливается.
Comment 54 Александр Морозов 2008-07-31 19:27:14 MSD
Реализована функция USBD_CreateConfigurationRequest
Comment 55 Александр Морозов 2008-10-03 20:28:25 MSD
Несколько незначительных изменений:
winedevice: Add missing WINAPI.
winedevice: Call IRP_MJ_PNP handler only with IRP_MN_START_DEVICE.
wineusbhub: Simplify __wine_usbhub_dispatch_pnp.
include: Add IO_TYPE_* defines.
ntoskrnl.exe: Use IO_TYPE_* defines.
ntoskrnl.exe: Use debugstr_guid and debugstr_us.
Comment 56 Александр Морозов 2008-10-06 17:32:59 MSD
Сделал и отправил в wine-devel@lists.etersoft.ru небольшой патч, удаляющий \ перед @ в spec-файле, чтобы потом не было проблем с синхронизаций с winehq, если они добавят usbd.sys.
Comment 57 Александр Морозов 2008-10-13 16:46:57 MSD
Исправлена пара ошибок. Патчи "Fix pdo_info size." и "wineusb: Do not call AddDevice some times for one device." Ошибка, исправленная вторым патчем проявляется, если в реестре есть несколько записей об устройстве с одинаковыми vid и pid, но с различными instance id.
Comment 58 Михаил Карпухин 2008-12-15 08:42:22 MSK
А как насчет поддержки gdi принтеров МФУ ? Sharp, Canon etc ?

p.s.
просто решил пока в отдельную багу не писать...
Comment 59 Vitaly Lipatov 2008-12-15 18:45:44 MSK
(In reply to comment #58)
> А как насчет поддержки gdi принтеров МФУ ?
> Sharp, Canon etc ?
Как до луны.
Проблема больше в отсутствии подсистемы для загрузки драйверов принтеров.

P.S.
А вопросы и не надо в отдельную багу писать, для этого support@etersoft.ru есть.
Comment 60 Vitaly Lipatov 2009-04-03 22:46:26 MSD
Я думаю, багу можно закрыть. Поставленная задача решена.
Comment 61 Александр Морозов 2009-04-30 16:02:30 MSD
*** Bug 776 has been marked as a duplicate of this bug. ***