Мне подарили ноут с частично работающей клавиатурой. Все неработающие клавиши я поделил на 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 kb8042100 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.ddtrace: 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/keymaphttp://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/io/kb8042/