tmk / tmk_keyboard

Keyboard firmwares for Atmel AVR and Cortex-M
3.98k stars 1.7k forks source link

Shift weirdness with pipe | #117

Closed mattharrison closed 6 years ago

mattharrison commented 10 years ago

I've been running the tmk fw on my ergodox for a bit now. Am running into an issue where when I hit pipe (|), a backslash is usually entered as well (ie |). (I had to delete the backslash from the pipe back there :)).

This does not appear to happen with other shifted keys, nor did it happen with Ben's fw.

Any ideas?

tmk commented 10 years ago

No idea. I never had problem like that on my HHKB.

Test again with very simple keymap which doesn't have any Fn key.

You can enable debug of matrix(x) and keyboard report(k) with Magic command and see what happens in you keyboard with hid_listen. This may help. https://github.com/tmk/tmk_keyboard#magic-commands

slashfoo commented 10 years ago

I believe I'm running into the same issue, but may be different. When NKRO is enabled and I do:

Pless "/"
Press "\"
Release "/"
Press "/"
Release "/"
Release "/"

I get /\\\/\ when that should be /\/. Also, an interesting thing is that \ doesn't send repeats so if I hold down / for a while, I get /////////////////////////// but if I press / for a while, I only get one.

Granted I'm using a fork of a fork of this project, I think "multiple keystrokes on a BSLS" is enough to catch my eye.

@mattharrison have you tried to reproduce with/without NKRO being enabled?

I'm using https://github.com/shayneholmes/tmk_keyboard/compare/tmk:master...simon_layout on my ergodox as well ; and find that disabling NKRO makes the keyboard behave as expected.

I'm going to try cub-uanic's and see if it was in shayneholmes' changes that the bug was introduced, I still wanted to throw my 2c in.

tmk commented 10 years ago

hmm, interesting. EDIT: wait, I'm not sure I can understand what exactly you said... but it looks likebackslash is problematic.

What's your OS? Linux? IIRC, Soarer said how to handle \ is tricky on Linux somewhere. His firmware uses tweaked report descriptor to avoid this issue. But I may have bad memory.

slashfoo commented 10 years ago

do you have a URL? yes, this is Linux... also I'll need a bit of clarification on what "tricky on linux" bit, I don't know what would be the problem really... I'll also try on a Win8 machine.

tmk commented 10 years ago

Unfortunately I cant find it anymore, maybe deleted its discussion due to Geekhack database malfucntion.

You may want to see report descriptor of Soarer's converter. I think his NKRO descriptor is not so straight unlike simple one of TMK.

mattharrison commented 10 years ago

My attempts on Linux (ubuntu 14.4) to follow @slashfoo's instructions. (Am assuming last Release "/" is Release "\": ////\//////////////\ //////\///////////////////////\

slashfoo commented 10 years ago

nope that press one, press the second, release the first guy and tap it again while leaving the "problem key" pressed.

The thing is, every time you press and release / while having \ down will yield \/\ instead of just a single / when NKRO is on. I'm unsure if this has to do with bounce/debouncing/chatter.

mattharrison commented 10 years ago

My results on Mac 10.9.3:

//////////////\\\//////////////

Am seeing same as @slashfoo : On Linux holding down "\" does NOT repeat. This appears to be the only character where that is the case. (Also it repeats on Mac).

mattharrison commented 10 years ago

(More linux) Results of holding down "\" while tapping another key: \a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\

Also a long hold on "a" while holding down "\" only enter one a. Again not the case with other keys: //////////aaaaaaaaaaaaa (long hold a)

//////////aaaa (tap a 4 times)

slashfoo commented 10 years ago

so is it indeed a \ only issue and only on linux then? I'll try to take some time to debug on windows side of things too, but this is pretty disconcerting as the keyboard should perform the same on all OSs :S

BenBergman commented 10 years ago

I was having some issues with my custom keyboard build and the backslash key and had assumed it was my own error, but this is making me think I am not the only one. I am also using Linux, but with a regular keyboard '\' repeats fine. On my TMK board, '\' does not register at all. I have not had time to debug it yet, but it sounds like it might be at least somewhat related.

slashfoo commented 10 years ago

@tmk do you have a way to verify? I don't happen to have any of the keyboards on this original repo (as opposed to forks, like cubuanic and shayneholmes' that support the ergodox).

tmk commented 10 years ago

With enabling NKRO feature I confirmed these problems. I'm on Linux with my HHKB and firmware built with LUFA and NKRO. 1) \ is not auto-repeated. 2) weirdness while \ key is pressed down, like \a\\a\\a\\a\\

Again, looks like to me report descriptor is a problem. Someone can look into Soarer's converter and Linux?

WORKAROUND: disable NKRO feature

BenBergman commented 10 years ago

I just reflashed my TMK board and it seems I am experiencing the same issues as everyone else now. I'm not sure what my issue was before that blocked backslash entirely.

tmk commented 10 years ago

PROBLEM: On Linux some HID key usages are converted into same internal keycode wrongly. Backslash and Delete are affected.

SOLUTION: Tweaked Report Descriptor. (TMK won't use this solution because of laziness.)

WORKAROUND: Use 6KRO.

Soarer described this pretty well.

The problem was that the backslash key would not repeat, and if another key was pressed while it was held down, extra backslashes appeared.

My converter's HID report is a bitmap, and each bit represents a specific HID key code. The codes are all unique in HID land, but not when mapped to Linux scan codes. The HID codes for backslash and 'Europe 1' are both mapped to the Linux code for backslash (by Linux). 'Europe 1' comes later in the report than backslash. So, Linux scans the report, sees backslash down and registers it, but then sees 'Europe 1' up and clears the backslash state. It would register a press and release of backslash every time it received a report from the keyboard while backslash was held down, but otherwise would not repeat it (since most of the time, it thought the key wasn't pressed).

The fix is that the 'Europe 1' code has been removed from the report. (It really wasn't useful anyway, even to Europeans!).

I'd call it a flaw in Linux, not my converter, but still it had to be fixed!

Backslash/Non-US# problem: http://geekhack.org/index.php?topic=17458.msg339706#msg339706

Delete/Clear problem: http://geekhack.org/index.php?topic=17458.msg927471#msg927471

This is Linux HID usage to internal code conversion table. https://github.com/torvalds/linux/blob/437f3b199c437e2a9ac01b9ab733c78e5fc7c720/drivers/hid/hid-input.c#L37

static const unsigned char hid_keyboard[256] = {
      0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
     50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
      4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
     27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
     65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
    105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
     72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
    191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
    115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
    122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
    unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
    unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
    unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
    unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
     29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
    150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};

Backslash(0x31) and Non-US Hash(0x32) are translated into one keycode(43) in Linux kernel, also Delete(0x4C), Clear(0x9C) and Keypad Clear(0xD8) are translated into one keycode(111). Those keys can't be distinguished each other on Linux input system, this fact itself is not problem. The problem is Linux cannot handle event of those keys in NKRO report correctly.


Soarer's tweaked descriptors. [ How to get report descriptor in Linux: http://www.slashdev.ca/2010/05/08/get-usb-report-descriptor-with-linux/ ]

Interface 2 is interesing NKRO report descriptor, which avoids sending usage Keyboard Non-US # and ~(50/0x32) and Keyboard Clear(156/0x9C) to host. With this you cannot send those two keycodes in NKRO mode but it will not be much problem.

NOTE: tmk does not support Clear, though.

Report descriptor of NKRO part:

          Report Descriptor: (length is 220)
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x06 ] 6
                            Keyboard
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x08 ] 8
            Item(Global): Usage Page, data= [ 0x07 ] 7
                            Keyboard
            Item(Local ): Usage Minimum, data= [ 0xe0 ] 224
                            Control Left
            Item(Local ): Usage Maximum, data= [ 0xe7 ] 231
                            GUI Right
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x05 ] 5
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Usage Page, data= [ 0x08 ] 8
                            LEDs
            Item(Local ): Usage Minimum, data= [ 0x01 ] 1
                            NumLock
            Item(Local ): Usage Maximum, data= [ 0x05 ] 5
                            Kana
            Item(Main  ): Output, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x03 ] 3
            Item(Main  ): Output, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x31 ] 49
            Item(Global): Usage Page, data= [ 0x07 ] 7
                            Keyboard
            Item(Local ): Usage Minimum, data= [ 0x01 ] 1
                            Keyboard ErrorRollOver
            Item(Local ): Usage Maximum, data= [ 0x31 ] 49
                            \ and | (Backslash and Bar)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x69 ] 105
            Item(Global): Usage Page, data= [ 0x07 ] 7
                            Keyboard
            Item(Local ): Usage Minimum, data= [ 0x33 ] 51
                            ; and : (Semicolon and Colon)
            Item(Local ): Usage Maximum, data= [ 0x9b ] 155
                            Cancel
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x08 ] 8
            Item(Global): Usage Page, data= [ 0x07 ] 7
                            Keyboard
            Item(Local ): Usage Minimum, data= [ 0x9d ] 157
                            Prior
            Item(Local ): Usage Maximum, data= [ 0xa4 ] 164
                            ExSel
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x04 ] 4
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x80 ] 128
                            System Control
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
tmk commented 8 years ago

It seems like Linux no longer have this problem now, on 4.4.0-36(Ubuntu 16.04 LTS) at least.

tmk commented 6 years ago

Seems that this commit of Linux kernel fixed this issue on Dec 29, 2014. Its comment is really worth reading. https://github.com/torvalds/linux/commit/6ce901eb61aa30ba8565c62049ee80c90728ef14

and this supplied proper conditional clause. https://github.com/torvalds/linux/commit/8e7b341037db1835ee6eea64663013cbfcf33575#diff-f35f6b78ead6796aeaf38a7414178d43

Current Linux(4.0 and up ?) doesn't have this issue.

tmk commented 6 years ago

WARN: With old Linux you may suffer from this problem.

This won't be solved anymore because Linux was fixed fortunately and current kernel doesn't have the problem anymore.