Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 [2]  Все   Вниз
  Печать  
Автор Тема: Драйвер связывает Приложение с клавиатурой напрямую ?  (Прочитано 46553 раз)
0 Пользователей и 15 Гостей смотрят эту тему.
sss
Специалист

ru
Offline Offline

« Ответ #30 : 10-09-2008 08:04 » 

buisyhanh, пишите с нуля. Итак - есть скелет драйвера, с кодом обработки кодов от DeviceIoControl?
Записан

while (8==8)
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #31 : 10-09-2008 08:32 » 

Есть у меня все в руках, коды всякие DeviceIoControl, Drivers DDK, SDK. Но для написания еще наверно недостачное знание обо Kernel mode программировании. Читал - читаю но еще не нашел то, что нужно.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #32 : 11-09-2008 08:54 » 

buisyhanh, я покопался в дизассемблированном примере. в общем отстой. Пример использует устаревшие функции IoQueryDeviceDescription, HalGetInterruptVector и я не могу понять чего они передают. Причем нигде не видно перезаписи вектора прерывания клавиатуры напрямую. Похоже на то, что пример не так прост и работает не заменой вентиля в IDT, а поиском (IoQueryDeviceDescription) контроллеров определенного типа, вызывает для них HalGetInterruptVector и что то делает с ними.
Записан

while (8==8)
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #33 : 12-09-2008 16:30 » 


- к сожалению подробный разбор дизасемблированного листинга требует много времени. и честно говоря не очень интересно.
если в кратце, то судя по наличию комадны iret он должен модифицировать IDT и подставлять свой обработчик прерывания. впрочем могу ошибаться. в какой последовательности он действует дальше - разбираться долго.
[/quote]
 Тут же сказали что будет модификация IDT, и по моему правильно. И IoQueryDeviceDescription просто получает информацию о неком устройстве, HalGetInterruptVector -  получает вектор указанного в параметре типа прерывания. Мне интересно там есть HalBegin and HalEndSystemInterrupt, что могут использовали для изменения хода прерывания.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #34 : 12-09-2008 19:23 » 

HalBeginSystemInterrupt и HalEndSystemInterrupt
- если не ошибаюсь, эти функции устанавливают IRQL==DIRQL. А после обработки восстанавливают предшествующий IRQL.
побробнее об этом(с разбором асемблерного кода функций):
http://ext2fsd.sourceforge.net/documents/irql.htm

и пару слов на microsoft: http://technet.microsoft.com/en-us/sysinternals/bb963898.aspx

PS на китайском)
 http://www.inkings.cn/blog/?p=1052

PPS кстати первая ссылка - очень интересно. сам буду изучать))) а то у меня с матчастью плохо)
« Последнее редактирование: 12-09-2008 19:32 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #35 : 14-09-2008 13:03 » 

Видно,что параметр ULONG Vector функции HalBeginSystemInterrupt (KIRQL Irql, ULONG Vector, PKIRQL OldIrql) дольно представить какой - то Vector прерывания. Причем по назнванию функции, то будет происходить какое - то прерывание. А сам вектор прерывания при этом указывается в ULONG Vector. Результат прерывания возвращается как 0 или 1.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #36 : 15-09-2008 00:51 » 

buisyhanh, IoQueryDeviceDescription в принципе корневая функция. Ищет ресурс прерывания для контроллера (клавиатуры?). Интересно, с USB клавиатурой будет работать?  Вот этот Vector ей и находиться. А про HalBeginSystemInterrupt вообще ничего документированного. Что это? Пролог ISR?
Записан

while (8==8)
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #37 : 15-09-2008 15:21 » 

buisyhanh,
Нет, сама функция HalBeginSystemInterrupt - не генерирует прерываний! Она маскирует прерывания через APIC.
И устанавливает в системе новый IRQL. Это необходимо для синхронизации работы "одновременно" пришедших разных прерываний с разными приоритетами (с разными IRQL).
А так же для корректного выполнения некоторых системных функций. В случае если они будут вызваны в обработчике ISR.

PS судя по первому взгляду на ссылку выше.

sss, с USB не должно... там механизм несколько другой, формат другой. по тем же прерываниям много чего валится. с USB надо через HID. либо через фильтр клавиатурный - тогда будет универсально...
« Последнее редактирование: 15-09-2008 15:32 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #38 : 16-09-2008 07:46 » 

buisyhanh,
Нет, сама функция HalBeginSystemInterrupt - не генерирует прерываний! Она маскирует прерывания через APIC.
И устанавливает в системе новый IRQL. Это необходимо для синхронизации работы "одновременно" пришедших разных прерываний с разными приоритетами (с разными IRQL).
А так же для корректного выполнения некоторых системных функций. В случае если они будут вызваны в обработчике ISR.
Таким образом, наверно написанный уменя драйвер имеет мехнизм для обработки прерывания следующий:

 - Имеется при прерывании ISR and DPC (здесь использовали HalGetInterruptVector), В ISR будет вызваться DPC(KeInitializeDpc, KeInsertQueueDPC), в этом же DPC будет как-то передать KEYBOARD_INPUT_DATA в буффер (Irp->AssociatedIrp.SystemBuffer;), предназначенный для Приложения .
 -  Использовали HalBeginSystemInterrupt для повышения IRQL данного конкретного ISR(DPC). Т.е и DPC будет выпольнятся первым перед других  возможных DPC (так как символы сразу появятся на экране при нажатии клавищ).
 - После обработки DPC нужно уменьшить IRQL ниже предоставляя процессор другим DPC использованием: HalEndSystemInterrupt.
 - В завершении DPC нужно установить событие синхронизации (KesetEvent) информируя Приложению обо наличии данных в Irp->AssociatedIrp.SystemBuffer и можно их забрать.
 
 Но уменя тут же возникается вопрос как можно получать KEYBOARD_INPUT_DATA с вводимым данными. Эти данные автоматически где - то хранятся или сам напишем обработчик для них. Но если будет обработчик  - то он должен не короткий и как реализовать его. Видно, что мой драйвер как - то получает эти данные и передать их в буффер без серезьной обработки.
 
Записан
sss
Специалист

ru
Offline Offline

« Ответ #39 : 17-09-2008 05:52 » 

buisyhanh Вы когда нибудь писали драйвера ?  В ISR не будет вызваться DPC.  DPC никогда не вызываются напрямую, по определению. И никогда не выполниться на повышенных IRQL.

Насчет KEYBOARD_INPUT_DATA. Основная подпрограмма чтения байта буфера клавиатуры и возврат его на место SUB_L0001038E.

Использует:
  SUB_L00010377 - Ожидание опустошения буфера
  SUB_L00010382 - Ожидание заполнения буфера

Всего лишь проанализируйте логику подпрограммы.

Вот ссылка http://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html#kcc60 для анализа работы с клавиатурными портами.

Ochkarik, вроде будет работать с USB. Не уверен однако.
Записан

while (8==8)
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #40 : 17-09-2008 08:49 » 

buisyhanh Вы когда нибудь писали драйвера ?  В ISR не будет вызваться DPC.  DPC никогда не вызываются напрямую, по определению. И никогда не выполниться на повышенных IRQL.
  Наверно мне там в тексте не хватает слово: РУТИН, т.е DPC - Routine. Извините меня из - за этого.
  Нужно в ISR написать KeInsertQueueDPC и тогда будет отложить обработку прерывания на нижный IRQL.

  На счет INPUT_DATA  для разных устройств, например для LPT(COM) порт использовали макроопределением типа:  READ_PORT_UCHAR( pDeviceExtension->portBase + STATUS_REG ), которое выдается HAL  определением.
 Помоему для KEYBOARD также существуют разные макроопределения для обработки вводимой информации.
 Но какие я еще не знаю.
Записан
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #41 : 17-09-2008 08:56 » 

Насчет KEYBOARD_INPUT_DATA. Основная подпрограмма чтения байта буфера клавиатуры и возврат его на место SUB_L0001038E.

Использует:
  SUB_L00010377 - Ожидание опустошения буфера
  SUB_L00010382 - Ожидание заполнения буфера
Спасибо sss

 Тут же в ассемблере - да, но как в С этот реализован, какие команды ?. Дела в том, что мне не сильно разбираться в ассемблере. Нужно найти логику написания драйвера и переписать заново в С. Основный подход реализации драйвера понятно, сейчас я должен реализовать драйвер частями.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #42 : 18-09-2008 01:42 » 

buisyhanh. Я расскажу как вижу работу такого драйвера.

1. Происходит прерывание.
2. Вызывается ISR.
3. ISR читает байт буфера клавиатуры в буфер драйвера.
4. Ставит в очередь DPC.
5. Блокирует прерывания для клавиатуры.
6. Записывает байт обратно в буфер клавиатуры
7. Разрешает прерывания для клавиатуры.
8. Вызывает предыдущий обработчик.
9. После понижения IRQL вызывается DPC.
10. В DPC устанавливается событие "буфер готов".
11. Приложение в usermode реагирует на событие  и вызывает DeviceIoControl для чтения буфера.
Записан

while (8==8)
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #43 : 18-09-2008 02:23 » 

buisyhanh. Я расскажу как вижу работу такого драйвера.

1. Происходит прерывание.
2. Вызывается ISR.
3. ISR читает байт буфера клавиатуры в буфер драйвера.
4. Ставит в очередь DPC.
5. Блокирует прерывания для клавиатуры.
6. Записывает байт обратно в буфер клавиатуры
7. Разрешает прерывания для клавиатуры.
8. Вызывает предыдущий обработчик.
9. После понижения IRQL вызывается DPC.
10. В DPC устанавливается событие "буфер готов".
11. Приложение в usermode реагирует на событие  и вызывает DeviceIoControl для чтения буфера.

 Отлично, sss Вы очень сильно разбираете в ассемблере. Спасибо большое.

 Как по этой списке, я предлагаю такой код сооветственно:

 В DriverEntry напишу: После создания Обьекта устройства.

  - Ставить код HalgetInterruptVector(...) для получения адрес вектор прерывания клавиатуры, после чего использовать IoConnectInterrupt(...) для регистрации ISR для данного прерывания и дальше:

 1. Происходить прерывание от клавиатуры.
 2. Вызывается ISR, в котором имеется фунция KeInsertQueueDPC
 3. ISR читает байт буффера порта 0х60
 4. Ставит в очередь DPC.
 5. Блокирует прерывания для клавиатуры. - Но не знаю зачем блокировать прерывания клавиатуры, и как в С реализовать, видно что нет такой функции в диассемблерном коде.
 6. Обратная запись в буффер клавиатуры - наверно это и есть байт состояния, информируя о завершении обработки, точно в буффер или в другой порт.
 7. Разрешает прерывания, какие функции не знаю, и не вижу таких там же в коде.
 8. Вызывает предыдущий обработчик. - Наверно где - то должно сохранить предыдущий обработчик, как вызывать ?
 9. DPC автоматически вызывается при понижении IRQL.
 10. В DPC устанавливается событие "буфер готов". - Тут иформируют Приложению - пользователя о готовность данной для вывода (KeSetEvent).
 11. Приложение в usermode реагирует на событие  и вызывает DeviceIoControl для чтения буфера. DeviceIoControl (...GET_BUFFER,...,OutputBuffer,size(),...);

 Как вы думаете в этой процедуре?.

 - Тут у меня тоже возникают некоторые вопросы:
    + Обратная запись байта в буффер клавиатуры - это и есть байт состояния или нет, какой был? Или использовали для     блокировки прерывания.
    + Разблокировать прерывание - как реализовать и после чего вызывается уже сохраненный где-то предыдущий обработчик.
    + Может быть при написании драйвера использовали и ассемблер и С.
 
Записан
sss
Специалист

ru
Offline Offline

« Ответ #44 : 18-09-2008 08:00 » 

buisyhanh, из DriverEntry вызывается SUB_L00010D14, где готовиться вызов
IoQueryDeviceDescription.

Код:

SUB_L00010D14:
push ebp
mov ebp,esp
       
        ...

L00010D3D:
push esi // Context (NULL)
push ebx // CalloutRoutine
push esi // PeripheralNumber  (NULL)
push esi // PeripheralType  (NULL)
push esi // ControllerNumber   (NULL)
lea eax,[ebp-04h]    // eax = &[ebp-04h]
push esi                // ControllerType  (NULL)
push eax // BusNumber 
lea eax,[ebp-0Ch] //&[ebp-0Ch]
push eax                // BusType
call edi

Что приводит к вызову CalloutRoutine ( L00010D8A), которая после проверки неких условий вызывает и выборов параметров вызывает HalgetInterruptVector. Я еще раз повторю у меня нет описаний этих функций. Поэтому дальше только можно гадать, но я предполагаю что там выясняется только адрес следующего обработчика. Переписывание таблицы векторов происходит в SUB_L000106E2 в районе метки L000106FA:
Код:
	call jmp_ntoskrnl.exe!KeGetCurrentThread
push 00000001h
mov cl,bl
pop edx
shl edx,cl
push edx
push eax
call jmp_ntoskrnl.exe!KeSetAffinityThread
sidt [L000111F0_IdtTable]
mov eax,[L00010F68]
mov eax,[eax+02h]
cli
mov edx,[L00010F60]
mov ecx,esi
mov [eax+edx*8],cx
mov ecx,[L00010F60]
mov [eax+ecx*8+06h],di
sti

Причем вызов запрятан на вызов таймера, созданного в DriverEntry. Тот, если активирован кодом 0x830020EC в обработчике L000109C8(IoControlDispatcher), постоянно проверяет, установлен ли перехватчик и если чего переустанавливает. Там же в подпрограмме таймера идет и некая проверка постановка DPC.

Цитата: MSDN
A driver’s IoTimer routine is called once per second after the driver enables the timer by calling IoStartTimer.


P.S.: Я не знаю buisyhanh в чем мне помочь Вам разобраться? Нужен скелет драйвера? Присоединяю... И еще, я на работе и дома работаю над своими проектами, поэтому извините не могу тратить много времени.

* 0002.rar (4.14 Кб - загружено 842 раз.)
Записан

while (8==8)
buisyhanh
Постоялец

vn
Offline Offline

« Ответ #45 : 18-09-2008 08:40 » 

P.S.: Я не знаю buisyhanh в чем мне помочь Вам разобраться? Нужен скелет драйвера? Присоединяю... И еще, я на работе и дома работаю над своими проектами, поэтому извините не могу тратить много времени.
Вы очень меня помогли, большое вам спасибо. Если вы сильно занятен, то занимайтесть своими делами. Если когда нибудь у вас будет свободное время, то заходите к мне в форуме. Отставьте мне ценные замечания, я вам очень блогадарю.
 Тут я буду постепенно разбирать проект, хотя трудно, но результативно.
 Если что обращайтесь к мне, хорошо?
Записан
sss
Специалист

ru
Offline Offline

« Ответ #46 : 18-09-2008 08:58 » 

OK
Записан

while (8==8)
Страниц: 1 [2]  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines