Тестируем поддержку USB

Drivers for periphery equipment
  • CleverMouse
    А причем здесь драйверное API ? И разве нынешнее решение не сделано специально для USB ?

    У тебя ведь драйвер уже работает в своём потоке ? Что мешает ему обработать в этом потоке событие таймера ? Почему это должен делать поток OS/IDLE ? Потому что так проще ? На эти грабли уже наступали.
  • Функции TimerHS/CancelTimerHS? Нет, в них нет вообще ничего специфичного для USB. Одним из планов использования, между прочим, является замена check_fdd_motor_status и check_ATAPI_device_event при выносе соответствующего кода в драйвера. Соответственно, я не понимаю, почему ты предлагаешь заняться этим потоку USB, и где ты видишь грабли.
    Сделаем мир лучше!
  • CleverMouse
    Ага, значит мы друг друга не понимаем. Совсем ничего не имею против TimerHS/CancelTimerHS. Наоборот таймеры нужны, вопрос в реализации. Моя идея:

    Code: Select all

    usb_thread()
    {
        while(1)
        {
            kevent_t event;
    
            get_event_ex(&event);
            switch(event.code)
            {
                case EV_IRQ:
                ;постобработка irq.
                break;
                case EV_TIMER:
                ;обрабатываем таймеры
                break;
            };
        };
    };
  • В реализации чего именно?
    На что, по-твоему, нужно заменить вот эти два фрагмента из usbhid.asm, который на данный момент является единственным пользователем TimerHS/CancelTimerHS?

    Code: Select all

    ; 5h. Start the auto-repeat timer.
            pop     ecx     ; restore keycode
            mov     [ebx+keyboard_data.repeatkey], cl
            stdcall TimerHS, 25, 5, autorepeat_timer, ebx
            mov     [ebx+keyboard_data.timer], eax
    

    Code: Select all

    ; Timer function for auto-repeat.
    autorepeat_timer:
            mov     eax, [esp+4]
            movzx   ecx, [eax+keyboard_data.repeatkey]
            test    cl, cl
            jns     @f
            push    ecx
            mov     ecx, 0xE0
            call    SetKeyboardData
            pop     ecx
            and     cl, not 0x80
    @@:
            call    SetKeyboardData
            ret     4
    
    Сделаем мир лучше!
  • Не надо ничего менять. autorepeat_timer надо вызывать из потока usb (в обработчике EV_TIMER), а не из osloop.
    Может я и не прав. Просто мне нравится идея Minix, где каждый сервис работает в своём потоке.
  • Хорошо. Теперь предположим, что завтра появляется драйвер PS/2-клавиатуры, автор которого посчитал механизм автоповтора в PS/2 недостаточно гибким и тоже использует программную эмуляцию. Естественно, в этом драйвере тоже будут два вышеприведённых фрагмента кода, причём дословно те же самые. Если мы против копипаста, предположим заодно, что загрузчик PE-драйверов умеет обрабатывать импорт не только из ядра, тогда можно считать, что два драйвера просто вызывают одну функцию общей библиотеки. Должен ли поток USB захватывать autorepeat_timer и для этого драйвера? Если да, то что будет, если подсистема USB не загружена, поскольку USB-устройств нет? Если нет, то почему два логически абсолютно идентичных фрагмента кода должны исполняться в двух логически совершенно разных местах?

    Я определённо предпочитаю Windows, а не Minix. Там KeSetTimerEx/KeCancelTimer позволяют поставить процедуру на выполнение и не думать, какой именно поток её будет выполнять.
    Сделаем мир лучше!
  • Отлично. А теперь предположим, что у нас есть общий сервис (процесс), который принимает от драйверов устройств события (нажатие клавиш, перемещение мыши и джойстика) обрабатывает, сам генерирует автоповтор для клавиатуры, и пересылает приложениям. И этот сервис является частью оконной системы, как и должно быть. Очень похоже на osloop. Должен ли этот процесс обрабатывать таймеры для совершенно посторонних устройств, как флоппи ?
    Ответ на твой вопрос зависит от того, создаст ли автор драйвера для PS/2 отдельный процесс. Если нет, он не сможет обработать событие таймера и TimerHS() ему не поможет. Если да, то он будет выполнять autorepeat_timer независимо от usb. Это вопрос принципов устройства драйверной модели.
    Я определённо предпочитаю Windows, а не Minix. Там KeSetTimerEx/KeCancelTimer позволяют поставить процедуру на выполнение и не думать, какой именно поток её будет выполнять.
    И действительно, зачем нам всякие KeWaitForSingleObject и KeWaitForMultipleObjects если есть замечательные DPC которые блокируют остальные потоки
    Spoiler:
    Note The CustomTimerDpc routine, like all DPC routines, is called at IRQL = DISPATCH_LEVEL. While a DPC routine runs, all threads are prevented from running on the same processor. Driver developers should carefully design their CustomTimerDpc routines to run for as brief a time as possible.
    Есть ещё Threaded DPC но это же Vista :(
    Я кстати именно эту схему предлагаю, только название у KeWaitForMultipleObjects другое.
  • Ага. Значит, в ситуации "как и должно быть" всё-таки автоповтор обрабатывается не потоком, который, как сложилось, породил драйвер клавиатуры, а потоком-частью оконной системы, который имеет непосредственное отношение к содержимому autorepeat_timer. С этим я соглашусь. Разумеется, в этой ситуации поток-часть оконной системы не должен обрабатывать посторонние таймеры. Я даже соглашусь, что идеологически osloop не должен обрабатывать посторонние таймеры. Тем не менее, сейчас он их по факту обрабатывает, и я считаю, что сейчас это правильно.

    Для реализации второго способа работы с KeSetTimerEx - через объекты ядра, на которых могут ждать потоки, - как в винде, нужен планировщик, как в винде. Сейчас каждый новый поток - это заметная нагрузка на систему: планировщик просматривает этот поток, даже если он просто спит, на каждом тике - в предположении ненагруженности системы, когда за тик успевает прокрутиться вся карусель потоков; в CPU этот поток даёт ещё один невнятный вход; если он создан не при загрузке системы и попал в середину карусели с пользовательскими потоками, то получаем плюс одну перезагрузку CR3; каждый новый поток приближает предел в 255 потоков. Мне кажется, что ты это понимаешь и поэтому настаиваешь на включении таймеров в поток usb вместо создания отдельных потоков, хотя идеологически там они столь же неуместны, сколь и в osloop.

    Если планировщик не будет вообще обращаться к спящим потокам, будет отдавать предпочтение потокам текущего процесса и система будет чётко осознавать разницу между процессами и потоками - хотя бы для CPU, чтобы он давал внятные показания, - я только за выделение различных сущностей в различные потоки. Но поскольку этого нет, я настаиваю на включении всех мелких задач в osloop, который по факту уже и есть обработчик кучи мелких задач; это экономит время планировщика, ограниченное число потоков, перезагрузки CR3, а в качестве минусов задерживает на миллисекунды отрисовку курсора - с моей точки зрения в текущей ситуации плюсы явно существеннее.
    Сделаем мир лучше!
  • Планировщик не переключается на блокированные потоки. Поиск по всем TASKDATA и проверка событий для ожидающих потоков занимает незначительное время. Хотя разбирать события в планировщике не лучшее решение.
  • Приношу извинения за поднятие такой старой темы, но я только сейчас добрался до ковыряния кода usbhid.asm. Я так понимаю, что этот драйвер вызывается только тогда, когда ядро уже определило, что устройство - это HID? Потому что я добавляю в драйвер отладочную строчку, и не вижу ее:

    Code: Select all

    AddDevice:
    
            mov     edx, [esp+12]
    
            push    ebx     ; save used register to be stdcall
    
            mov     cx, word [edx+interface_descr.bInterfaceSubClass]
    
            DEBUGF 1,'K : unknown device: %x\n',cx
    
    Впрочем, я вообще никаких строчек не вижу, получаю сообщение ядра о том, что что-то не так с SET_ADDRESS, и USB-устройство будет отключено. Использовал ядро и исходник драйвера с ftp. Как сделать так, чтобы ядро и с другими Class/Subclass/Protocol работало? Нашел наконец исходники драйвера, через который работает мой 3G-модем, хочу попробовать для начала хотя бы совершать звонки.
  • SoUrcerer,
    CleverMouse в usbapi.txt wrote:For every interface the kernel looks for class code of this interface and loads the corresponding COFF driver. Currently the correspondence is hardcoded into the kernel code and looks as follows: 3 = usbhid.obj.
    CleverMouse,
    мне тоже интересно попробовать свои силы в драйверописании. Исходники ядра с usb были бы как нельзя кстати, пусть и не на svn.
    Last edited by dunkaist on Fri Mar 02, 2012 12:16 pm, edited 1 time in total.
  • Да, я именно об этом и подумал. Спасибо за уточнение. Все равно, поэкспериментировать желание имеется.
  • Ядро http://ftp.kolibrios.org/users/CleverMo ... kernel.mnt синхронизировано с транком. Драйвера usbhid.obj и usbstor.obj не пострадали. В процессе синхронизации произошло выпиливание старых мьютексов и замена их новыми, так что могли появиться глюки.

    Я напоминаю, что ядро умеет работать с существующими и вновь подключаемыми usb1-устройствами, определяя их class/subclass/protocol и выводя информацию на доску отладки, а также - при существовании usbhid.obj и usbstor.obj в папке drivers - поддерживать мышки и клавиатуры и распечатывать первые несколько байт первого сектора флешки для проверки работы с аппаратной частью. USB2-устройства в зависимости от настроек BIOSа и конкретного порта, к которому они подключены, могут либо работать на скорости usb1, либо захватываться BIOSом, в последнем случае ядро либо не увидит их совсем, либо произойдёт ошибка на первой стадии конфигурации aka SET_ADDRESS. При динамическом переподключении USB2-устройства могут в зависимости от тех же условий либо быть, либо не быть захваченными BIOSом.
    Сделаем мир лучше!
  • Мышка, я разницы при байтовом сравнение trunk'ов не увидел. Сможешь покакать где проблемная часть возникла?
    Или могла возникнуть, случаем :)
    Программист не тот, кто постоянно пишет КОД, а тот кто сможет понять чужой КОД!!!
  • Who is online

    Users browsing this forum: No registered users and 0 guests