Единственный ключ на клавиатуре производит дополнительные нажатия клавиш для каждой одновременно нажатой клавиши

hpanel :-)

hpanel(1)                        User Commands                       hpanel(1)

NAME
       hpanel - a minimalist panel for X

SYNOPSIS
         hpanel [options]

DESCRIPTION
       hpanel is a minimalist panel for X. Hpanel is version of fspanel
       (handles maximized windows better). It contains a small panel that
       lists windows and allows switching workspaces for use with a window
       manager that supports NETWM specification. Known working window
       managers are pekwm and aewm++.

4
28.08.2013, 11:43
2 ответа

Я попытался сделать правильный патч для этой ошибки. Это проблема в ядре, а не в клавиатуре, хотя можно утверждать, что клавиатура ведет себя странным образом. В любом случае, патч отправляется в список ввода linux для проверки, но пока к нему нет комментариев.

Это должно решить проблему, упомянутую здесь, с QPAD MK-85, но такая же проблема существует с Corsair K70, Gigabyte Osmium и другими подобными клавиатурами. Если у вас есть клавиатура с ошибкой, было бы здорово, если бы вы могли протестировать патч. Если вы протестируете его, дайте мне знать, работает ли он, а также какая у вас клавиатура, также важно, какую языковую версию вы используете, клавиатуры для США и других стран будут вести себя по-разному. Обратите внимание, что клавиша обратной косой черты на клавиатурах США будет иметь другие метки на других версиях клавиатуры.

Вот письмо от linux-input с патчем:

http://article.gmane.org/gmane.linux.kernel.input/37583

4
27.01.2020, 20:52

Хорошо, мне удалось соединить взлом, который решает проблему. Я запишу это здесь в случае, если кто-то спотыкается с той же проблемой.

Прежде всего, если Вы не интересуетесь тонкой настройкой источника ядра, у Вас могла бы быть другая опция: http://kbd-mangler.sourceforge.net/ - я не протестировал его, но описание выглядит довольно многообещающим. Это позволяет Вам настраивать вход, прежде чем это будет передано системе.

Мое решение состояло в том, чтобы отредактировать файл drivers/hid/hid-input.c. В начале файла я добавил три новых определения переменной;

static bool CODE43TRUE = 0; // If true, code43 has been pressed
static bool CODEXXTRUE = 0; // If true, any other key has been pressed
static int  CODESKIP = 0;   // Counter for skipping extra code43 events

Найдите функцию

void hidinput_hid_event

У основания этой функции

input_event(input, usage->type, usage->code, value);

Вход является контроллером, тип относится к типу события (1, нажатие клавиши.. 2 движение мыши?), код является кодом клавиши, и значение любой 0 для подавленного и 1 для нажатого.

При любом нажатии клавиши системные циклы HID 4 раза через все клавиши на клавиатуре. Почему это делает это 4 раза, я не знаю, но 4 соответствует объему дополнительных нажатий клавиш, которые я получил со своим проблематичным ключом. На первом цикле нажатая клавиша имеет значение 0 на втором значении 1, и на третьем, и четвертые снова оценивают 0.

Решение состояло в том, чтобы изменить эту функцию так, чтобы это не позволяло проблематичному ключу быть нажатым снова, когда другие клавиши будут нажаты OR в 4 циклах исходного нажатия клавиши. Это было достигнуто следующим кодом (Я упоминал, что не кодировал C, по крайней мере, в течение десятилетия? Извините)

/* report the usage code as scancode if the key status has changed */
if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
    input_event(input, EV_MSC, MSC_SCAN, usage->hid);

// NEW CODE STARTS HERE
if (usage->type == 1 && value == 1) // Keypress ahead
{
    if (usage->code == 43) { // Keypress is code 43
        if (CODE43TRUE == 0) {  // Key not yet pressed 
            CODE43TRUE = 1;
            printk(KERN_INFO "CODE43 SET TRUE\n");
        }
    else { // Key already pressed, so force value 1
        printk(KERN_INFO "CODE43 ALREADY TRUE SET VALUE 1\n");
        value = 0;
    }
}
else { // Some other key pressed, set XX true
    CODEXXTRUE = 1;
    printk(KERN_INFO "CODEXX SET TRUE\n");  
}
printk(KERN_INFO "Keypress type:%u code:%u value%d\n", (unsigned int) usage->type, (unsigned int) usage->code, (int) value);
}

if (usage->type == 1 && value == 0) { // Non-pressed key ahead
    if (usage->code == 43) { // If its a 43
        printk(KERN_INFO "43 call..\n");
        if (CODE43TRUE == 1) { // And 43 is fake pressed still
            if (CODEXXTRUE == 1 || CODESKIP < 4) { // If other buttons are pressed OR we are less than 5 ticks into the press..
                printk(KERN_INFO "FAKE PRESS 43. CODESKIP %d\n",CODESKIP);
                value = 0;
                CODESKIP ++;
            }
            else { // No other buttons pressed and over five ticks have passed
                printk(KERN_INFO "43 RELEASED\n");
                CODE43TRUE = 0;
                CODESKIP = 0;   
            }
        }
        // Reset the CODEXXTRUE (next time we get info about 43, we have looped through all the other keys so we know if something is pressed)
        CODEXXTRUE = 0;
    }   
}

// NEW CODE ENDS HERE
input_event(input, usage->type, usage->code, value);

При реализации этого, Вы могли бы хотеть удалить printk операторы, после того как Вы проверили, что это работает, как предназначено. Они должны просто там помочь отладке.

2
27.01.2020, 20:52

Теги

Похожие вопросы