В Wine нет поддержки WinNT-драйверов USB-устройств. Теоретически её можно реализовать с помощью libusb, позволяющей работать с устройствами в Linux в user-mode.
Написан "пустой" тестовый драйвер, работающий в WinXP, и обращающаяся к нему программа. Драйвер создаёт файл устройства и обрабатывает вызовы CreateFile, DeviceIoControl и CloseHandle. Под Wine драйвер обрабатывает DeviceIoControl, а обработчики для CreateFile и CloseHandle не вызываются. Драйвер собирался с помощью WinDDK в Windows.
Драйвер был модифицирован. Добавлены обработка IOCTL-запроса, при которой происходит получение дескриптора USB-устройства, и процедура AddDevice (её добавление вызвано необходимостью подключения к объекту устройства нижележащего драйвера). После модификации драйвер перестал корректно запускаться с помощью добавления записи в раздел реестра Services. По-видимому, надо создать inf-файл и установить драйвер для какого-нибудь USB-устройства.
Драйвер успешно установлен в Windows с помощью INF-файла. При обработке IOCTL_DESCRIPTOR_REQUEST_TEST он успешно получает vid и pid устройства.
Установка драйвера с помощью inf-файла в Wine, по-видимому, не поддерживается (нет "Диспетчера устройств" и не реализована UpdateDriverForPlugAndPlayDevices). Поэтому драйвер в Wine был уставновлен с помощью экспорта записей реестра, создаваемых при установке драйвера в Windows, и копирования файла драйвера в windows\system32\drivers. Под Wine не выполняется AddDevice. В Windows она выполняется при добавлении устройства и при его включении.
Функции AddDevice необходимо передать в качестве аргументов указатели на объект драйвера (DRIVER_OBJECT) и на объект устройства (DEVICE_OBJECT) нижележащего драйвера. Экземпляр структуры объекта драйвера является глобальной переменной в device.c (programs/winedevice). Принято решение реализовать вызов AddDevice через запросы к wineserver. Когда надо будет вызвать AddDevice, будет совершаться запрос к серверу с указанием имени драйвера, для которого надо вызвать AddDevice. winedevice будет периодически опрашивать сервер, есть ли запросы на выполнение AddDevice для драйвера с таким именем.
Вызов AddDevice реализован. Реализация неидеальна, AddDevice пока можно вызвать для каждого драйвера только один раз. Перед вторым вызовом AddDevice надо ещё раз загрузить драйвер.
Добавлено некоторое количество функций в ntoskrnl.exe (в основном это стабы), изменена функция IofCompleteRequest (теперь она вызывает IoFreeIrp). Загрузка драйвера и выполнение работающей с ним программы проходят без крэша wine. Надо реализовать несколько функций для работы с IRP, IoAttachDeviceToDeviceStack и IofCallDriver. После этого можно будет приступать к доработке wineusb.
wineusb - сервис, который будет вызывать AddDevice для USB-устройств и, если необходимо, загружать драйверы. Сейчас он вызывает AddDevice для тестового драйвера.
Кроме того wineusb будет обрабатывать IRP, предназначенные для драйвера, расположенного в стеке под функциональным драйвером USB-устройства.
Небольшие изменения уже реализованных функций из ntoskrnl.exe. Начата реализация IofCallDriver.
Добавлена DLL wineusbhub. Она обрабатывает запросы к драйверу более низкого уровня. На данный момент работает получение выполняющимся в Wine WDM-драйвером VID и PID USB-устройства. При этом драйвер работает с первым попавшимся USB-устройством. В будущем wineusb будет сообщать драйверу, с каким устройством ему следует работать. Имеется проблема с запуском драйвера. Программа может обратиться к файлу устройства до того, как он будет создан драйвером. Пока проблема решена переносом вызовов usb_init() и т.п. в DllMain wineusbhub.c. Есть небольшой баг при получении размеров данных, передаваемых wineserver`у при запросе call_add_device.
Исправлен баг в запросе к wineserver. Добавлены dlls/usbd.sys и несколько стабов в ntoskrnl.exe. Это позволило запустить драйвер ключа Eutron 3. Драйвер падает при выполнении AddDevice при записи по нулевому указателю: 0012:Call KERNEL32.InterlockedExchange(00000000,0011b970) ret=0056398e
Проблема с InterlockedExchange решена. Добавлено ещё несколько стабов. Теперь выполнение AddDevice для драйвера eusk3usb.sys (ключ Eutron 3) проходит до конца без падений. Попробовал запустить тестовую программу из Гектор`а под Wine вместе с родным драйвером (кстати, проверил, что под Windows всё работает). Программа не находит ключа. При этом происходит обращение к создаваемому драйвером устройству Skey----. Подозрительно, что при этом в логах есть лишь вызовы KeWaitForSingleObject и KeReleaseMutex и нет, например, обращений к нижележащему драйверу с помощью IofCallDriver. Скорее всего это связано с неполным (или неправильным) заполнением структуры IRP. Происходит также обращение к отсутствующим устройствам SkeyDev0, ..., SkeyDev2. В Windows эти устройства драйвером не создаются (это можно увидеть с помощью DeviceTree), так что скорее всего это не является причиной проблемы под Wine.
В ntoskrnl.exe добавлено ещё несколько стабов. В programs/winedevice/device.c после AddDevice добавлен вызов MajorFunction[IRP_MJ_PNP] с IRP_MN_START_DEVICE. При его выполнении таки вызывается IofCallDriver. Но при обработке IOCTL драйвер пока ещё не хочет обращаться к ключу.
Немного модифицирован programs/winedevice/device.c (более корректное поведение при отсутствии USB-устройств и при неудачном завершении AddDevice). Реализовано получение дескриптора конфигурации (для случая num_altsetting == 1). Добавлено 2 стаба в usbd.sys.
Реализованы USBD_CreateConfigurationRequestEx и обработка URB_FUNCTION_VENDOR_DEVICE. Функция драйвера, обрабатывающая IRP_MN_START_DEVICE, теперь завершается нормально. Но тем не менее тестовая программа ключ по-прежнему не видит.
Добавил вызов IofCompleteRequest в обработчики IRP_MJ_INTERNAL_DEVICE_CONTROL и IRP_MJ_PNP в wineusbhub (драйвер, находящийся в стеке под драйвером USB-ключа). При этом для вызова IofCompleteRequest пришлось сделать обёртку, так как это fastcall-функция. Добавил вызов CompletionRoutine в IofCompleteRequest. Добиться правильной работы обращающейся к драйверу тестовой программы пока не удалось. Возможно, стоит создать тестовый драйвер, создающий те же объекты устройств, запустить тестовую программу вместе с ним под Windows, посмотреть, какие структуры IRP получает драйвер, и воспроизвести их в Wine. Надо как-то освобождать память, выделенную для IRP, например, с помощью IoBuildDeviceIoControlRequest. И делать это надо тогда, когда IRP уже никем не используется. Пока что в ряде случаев происходит утечка памяти.
Тестовая программа ключ не видит. Написан тестовый драйвер, выводящий передаваемые ему структуры IRP, DEVICE_OBJECT и DRIVER_OBJECT.
Тестовый драйвер запущен под Windows. Теперь известно, какие функции Windows вызывает при инициализации драйвера. Соответственно изменена инициализация драйвера в winedevice. Улучшена реализация IoAttachDeviceToDeviceStack. Тестовая программа ключ не видит.
Добиться работы тестовой программы с ключом Eutron пока не удалось.
Тестовая программа ключ не видит.
Пока не ясно, что надо изменить в Wine, чтобы тестовая программа не возвращала ошибку.
В IofCompleteRequest теперь освобождается память, выделяемая для IRP в IoBuildDeviceIoControlRequest.
Добавлены проверки на возврат NULL из функций выделения памяти в IoAllocateIrp и IoBuildDeviceIoControlRequest.
Попробовал запустить Инфо-Бухгалтер 8.5 с ключом Sentinel UltraPro. Инициализация ключа проходит нормально. Драйвер создаёт файлы устройств skeysusb и SntnlUsb. При запуске программы происходит обращение к RNBODRV0, SntnlUsb и NVKEYNT, удачно завершается, разумеется, только для второго. Для SntnlUsb несколько раз вызывается DeviceIoControl. При его обработке обращения к устройству не происходит. Инфо-Бухгалтер говорит, что ключ не обнаружен.
На машине с Windows кроме использовавшегося при запуске под Wine sntnlusb.sys есть ещё sentinel.sys и nvkeynt.sys. Я, правда, не уверен, имеют ли они отношение к данному ключу.
(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).
Драйверы 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
Кроме 2 упомянутых выше устройств драйвер создаёт ещё одно безымянное, для которого он вызывает IoAttachDeviceToDeviceStack.
Улучшена обработка запроса дескриптора конфигурации
Небольшие изменения в инициализации 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 каждый раз разный.
Добавлена поддержка специфичных для конкретного устройства дескрипторов. sntnlusb.sys теперь не падает
В KeInitializeEvent структура события теперь инициализируется почти как в Windows. В посылаемых драйверам IRP irp.IoStatus.u.Status устанавливается в STATUS_NOT_SUPPORTED.
Добавил в тестовый драйвер вывод результатов обработки IRP_MN_QUERY_CAPABILITIES нижележащим драйвером.
Частично реализована обработка IRP_MN_QUERY_CAPABILITIES
Для идентификации USB-устройств теперь используются location из struct usb_bus и devnum из struct usb_device (это лучше использования vid и pid, так как позволит избежать проблем при исползовании 2-х одинаковых устройств). PDO для USB-устройств теперь именуются как в WinXP. При создании DEVICE_OBJECT теперь инициализируется поле Flags.
Под WinXP Инфо-Бухгалтер передаёт драйверу ключа Sentinel не такой код IOCTL, как в Wine
Если в WinXP отключить загрузку SENTINEL.SYS, то SNTNLUSB.SYS получает коды IOCTL такие же, как и в Wine.
В Windows в зависимости от 2 младших бит кода IOCTL используются различные методы передачи данных между вызывающей DeviceIoControl функцией и драйвером. Код 22001c, с которым Инфо-Бухгалтер обращается к драйверу, соответствует METHOD_BUFFERED. В Wine нет выбора метода передачи в зависимости от кода IOCTL и используемый метод не METHOD_BUFFERED.
Добавлена поддержка 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).
Created attachment 482 [details] Записи в реестре, необходимые для использования под Wine ключа Eutron с драйвером eusk3usb.sys
В какой сборке можно потестить сие чудо ?
Когда будет сборка, не знаю, но думаю, что скоро
Created attachment 485 [details] Записи в реестре, необходимые для использования под Wine ключа SafeNet USB SuperPro/UltraPro с драйвером sntnlusb.sys
Сборка готова. На данный момент нужно проследить, чтобы были права доступа к usb-устройству ключа, ключ вставлен до запуска wine, а нужный драйвер лежал в system32/drivers
Начато написание тестов для включения патчей в оригинальный wine. Создана основа тестов для ntoskrnl.exe: драйвер и загружающая его программа.
Написал тест на обработку IOCTL. Правда, более-менее полноценно тестируется в нём только METHOD_BUFFERED, так как для тестирования METHOD_IN_DIRECT, METHOD_OUT_DIRECT и METHOD_NEITHER в Wine не хватает некоторых функций.
Написал несколько тестов для IofCompleteRequest. Тесты проходят на WinXP. Оказалось, что реализованное в eterhack поведение достаточно плохо соответствует поведению Windows. Изменил IofCompleteRequest и IofCallDriver, чтобы они соответствовали тестам.
Написан тест для IoAttachDeviceToDeviceStack
Изменил Makefile.in тестов для ntoskrnl.exe. Теперь используемый в кросстесте драйвер собирается с использование библиотек из wine, а не из mingw. Оказалось, что при таком способе сборки нельзя использовать функции, определённые в ntoskrnl.exe.spec таким образом: @ cdecl -private strcpy(ptr str) msvcrt.strcpy Кросстест при их использовании не собирается. Зато теперь драйвер из кросстеста загружается и под Wine. Сделал основу для тестов usbd.sys.
Написал несколько тестов для USBD_CreateConfigurationRequest
Написал тесты для USBD_CreateConfigurationRequestEx
Благодаря тестам выяснилось, что реализованная в eterhack USBD_CreateConfigurationRequestEx при определённых условиях зацикливается.
Реализована функция USBD_CreateConfigurationRequest
Несколько незначительных изменений: 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.
Сделал и отправил в wine-devel@lists.etersoft.ru небольшой патч, удаляющий \ перед @ в spec-файле, чтобы потом не было проблем с синхронизаций с winehq, если они добавят usbd.sys.
Исправлена пара ошибок. Патчи "Fix pdo_info size." и "wineusb: Do not call AddDevice some times for one device." Ошибка, исправленная вторым патчем проявляется, если в реестре есть несколько записей об устройстве с одинаковыми vid и pid, но с различными instance id.
А как насчет поддержки gdi принтеров МФУ ? Sharp, Canon etc ? p.s. просто решил пока в отдельную багу не писать...
(In reply to comment #58) > А как насчет поддержки gdi принтеров МФУ ? > Sharp, Canon etc ? Как до луны. Проблема больше в отсутствии подсистемы для загрузки драйверов принтеров. P.S. А вопросы и не надо в отдельную багу писать, для этого support@etersoft.ru есть.
Я думаю, багу можно закрыть. Поставленная задача решена.
*** Bug 776 has been marked as a duplicate of this bug. ***