Автор Тема: Создание собственной раскладки клавиатуры  (Прочитано 2327 раз)

Оффлайн keremet

  • Global Moderator
  • ROOT
  • *****
  • Сообщений: 462
  • Репутация: +237/-0
    • Просмотр профиля
    • OpenSolaris
Мне подарили ноут с частично работающей клавиатурой. Все неработающие клавиши я поделил на 2 группы

1. Пусть не работают, потому что есть дублирующие клавиши или комбинации
доп Delete - обычный Delete
правый ALT - левый ALT
влево   - доп_4
вниз           - доп_2
вправо   - доп_6
доп_умножение   - shift+8
доп_3   - 3

2. У этих клавиш нет дублирующих клавиш или комбинаций, но для них можно задействовать избыточные:
пробел   - доп_5
B   - доп_9
N   - доп_1
русская_точка=лат_слеш   - доп_7

Решение - внести изменения в драйвер клавиатуры, чтобы в момент определения, какая клавиша нажата, этот считанный код клавиши изменялся.
Сначала определим, как называется этот драйвер:
prtconf -D
...
            i8042, instance #0 (driver name: i8042)
                keyboard, instance #0 (driver name: kb8042)
                mouse, instance #0 (driver name: mouse8042)
....

keremet@openindiana:~$ modinfo |grep kb8042
100 fffffffff7da0000   3570  53   1  kb8042 (PS/2 keyboard driver)


Поисследуем, что происходит при нажатии клавиши
root@openindiana:~# dtrace -n 'fbt:kb8042::entry{} fbt:kb8042::return{}'
dtrace: description 'fbt:kb8042::entry' matched 62 probes
CPU     ID                    FUNCTION:NAME
  1  61088                kb8042_intr:entry
  1  61108       kb8042_received_byte:entry
  1  61120        KeyboardConvertScan:entry
  1  61062   KeyboardConvertScan_set1:entry
  1  61063  KeyboardConvertScan_set1:return
  1  61121       KeyboardConvertScan:return
  1  61110   kb8042_autorepeat_detect:entry
  1  61111  kb8042_autorepeat_detect:return
  1  61112         kb8042_process_key:entry
  1  61113        kb8042_process_key:return
  1  61109      kb8042_received_byte:return
  1  61089               kb8042_intr:return
  1  61088                kb8042_intr:entry
  1  61108       kb8042_received_byte:entry
  1  61120        KeyboardConvertScan:entry
  1  61062   KeyboardConvertScan_set1:entry
  1  61063  KeyboardConvertScan_set1:return
  1  61121       KeyboardConvertScan:return
  1  61110   kb8042_autorepeat_detect:entry
  1  61111  kb8042_autorepeat_detect:return
  1  61112         kb8042_process_key:entry
  1  61113        kb8042_process_key:return
  1  61109      kb8042_received_byte:return
  1  61089               kb8042_intr:return


root@openindiana:~# cat 1.d
#!/usr/sbin/dtrace -s
#pragma D option flowindent
fbt:kb8042::entry,
fbt:kb8042::return
{
}

root@openindiana:~# ./1.d
dtrace: script './1.d' matched 62 probes
CPU FUNCTION                                 
  1  -> kb8042_intr                           
  1    -> kb8042_received_byte               
  1      -> KeyboardConvertScan               
  1        -> KeyboardConvertScan_set1       
  1        <- KeyboardConvertScan_set1       
  1      <- KeyboardConvertScan               
  1      -> kb8042_autorepeat_detect         
  1      <- kb8042_autorepeat_detect         
  1      -> kb8042_process_key               
  1      <- kb8042_process_key               
  1    <- kb8042_received_byte               
  1  <- kb8042_intr                           
  1  -> kb8042_intr                           
  1    -> kb8042_received_byte               
  1      -> KeyboardConvertScan               
  1        -> KeyboardConvertScan_set1       
  1        <- KeyboardConvertScan_set1       
  1      <- KeyboardConvertScan               
  1      -> kb8042_autorepeat_detect         
  1      <- kb8042_autorepeat_detect         
  1      -> kb8042_process_key               
  1      <- kb8042_process_key               
  1    <- kb8042_received_byte               
  1  <- kb8042_intr         

Функция kb8042_intr  вызывается дважды: на нажатие и на отпускание.

Получение скан-кодов
sudo dtrace -n 'fbt:kb8042:kb8042_received_byte:entry{printf("scancode: %d", arg1);}'
5  0  45904       kb8042_received_byte:entry scancode: 76
  0  45904       kb8042_received_byte:entry scancode: 204
   0  45904       kb8042_received_byte:entry scancode: 57
  0  45904       kb8042_received_byte:entry scancode: 185

1  0  45904       kb8042_received_byte:entry scancode: 79
  0  45904       kb8042_received_byte:entry scancode: 207
n  0  45904       kb8042_received_byte:entry scancode: 49
  0  45904       kb8042_received_byte:entry scancode: 177

9  0  45904       kb8042_received_byte:entry scancode: 73
  0  45904       kb8042_received_byte:entry scancode: 201
b  0  45904       kb8042_received_byte:entry scancode: 48
  0  45904       kb8042_received_byte:entry scancode: 176

7  0  45904       kb8042_received_byte:entry scancode: 71
  0  45904       kb8042_received_byte:entry scancode: 199
/  0  45904       kb8042_received_byte:entry scancode: 53
  0  45904       kb8042_received_byte:entry scancode: 181






На сайте http://src.illumos.org/ нашел, где находятся исходники модуля

keremet@openindiana:/code1/illumos-gate/usr/src/uts$ gedit ./common/io/kb8042/kb8042.c


Изменения в функцию kb8042_intr: преобразуем scancode перед отправкой в kb8042_received_byte

static uint_t
kb8042_intr(caddr_t arg)
{
   uchar_t scancode;   /* raw scan code */
   int rc;
   struct kb8042 *kb8042 = (struct kb8042 *)arg;

   rc = DDI_INTR_UNCLAIMED;

   if (kb8042->init_state == KB8042_UNINITIALIZED)
      return (DDI_INTR_UNCLAIMED);

   /* don't care if drv_setparm succeeds */
   (void) drv_setparm(SYSRINT, 1);

   while (ddi_get8(kb8042->handle, kb8042->addr + I8042_INT_INPUT_AVAIL)
       != 0) {
      rc = DDI_INTR_CLAIMED;

      scancode = ddi_get8(kb8042->handle,
          kb8042->addr + I8042_INT_INPUT_DATA);

+      switch (scancode & 0x7F){
+         case 76: scancode = (scancode & 0x80)|57; break;
+         case 79: scancode = (scancode & 0x80)|49; break;
+         case 73: scancode = (scancode & 0x80)|48; break;
+         case 71: scancode = (scancode & 0x80)|53; break;
+      }

      kb8042_received_byte(kb8042, scancode);
   }

   return (rc);
}

Команды компиляции возьму из .make.state, который создается при сборке illumos:
/code1/illumos-gate/usr/src/uts/intel/kb8042/.make.state

/code1/illumos-gate/usr/src/tools/proto/root_i386-nd/opt/onbld/bin/i386/cw -_gcc -m64 -Ui386 -U__i386 -xO3 ../../intel/amd64/ml/amd64.il -D_ASM_INLINES -Xa -xspace  -xmodel=kernel -_gcc=-mno-mmx -_gcc=-mno-sse -Wu,-save_args -v -xildoff  -g -xc99=%all -W0,-noglobal  -Wu,-save_args -xdebugformat=stabs -errtags=yes -errwarn=%all -_gcc=-Wno-missing-braces -_gcc=-Wno-sign-compare -_gcc=-Wno-unknown-pragmas -_gcc=-Wno-unused-parameter -_gcc=-Wno-missing-field-initializers -_gcc=-fno-inline-small-functions  -_gcc=-fno-inline-functions-called-once  -_gcc=-fno-ipa-cp -W0,-xglobalstatic    -xstrconst -D_KERNEL -D_SYSCALL32 -D_SYSCALL32_IMPL -D_ELF64  -D_DDI_STRICT -Dsun -D__sun -D__SVR4 -DDEBUG    -I../../intel -Y I,../../common  -c -o debug64/kb8042.o ../../common/io/kb8042/kb8042.c

/usr/ccs/bin/ld -r -dy -Nmisc/kbtrans -o debug64/kb8042 debug64/at_keyprocess.o    debug64/kb8042.o    debug64/kb8042_keytables.o


После компиляции
sudo install -s -m 755 -f /kernel/drv/amd64 debug64/kb8042
sudo bootadm update-archive



Наверно будут интересными эти ссылки
http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/loadkeys/
https://github.com/joyent/illumos-joyent/blob/master/usr/src/cmd/kbd/keymap
http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/io/kb8042/