Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop LIRC in favor of ir-ctl #5

Open
crutonjohn opened this issue May 19, 2022 · 14 comments
Open

Drop LIRC in favor of ir-ctl #5

crutonjohn opened this issue May 19, 2022 · 14 comments
Assignees

Comments

@crutonjohn
Copy link
Owner

crutonjohn commented May 19, 2022

Details

Describe the solution you'd like:

Ideally I'd like to move away from using LIRC - patched or unpatched - due to it's uncertain future. As per the discussion in pikvm/pikvm#291 it seems like we can capture raw codes from ir-ctl and implement them as essentially raw TX.

In agile terms this could be viewed as a SPIKE, but may transform over the issue's lifetime.

Anything else you would like to add:

I've repurposed GPIO 19 as TX, and GPIO 16 as RX for the time being.

Some prelim testing indicates that this should be possible, but the config files are not nearly as user-friendly as the LIRC-based configs. I'd be happy to make that sacrifice so that the project can be on more stable ground instead of depending on 3 year old software.

Additional Information:

This may wind up encompassing #4 as well

@crutonjohn crutonjohn self-assigned this May 19, 2022
@petrkr
Copy link

petrkr commented May 19, 2022

it seems like we can capture raw codes from ir-ctl and implement them as essentially raw TX.

Actually you can also use kernel decoder of generic IR protocols like NEC, RC5, RC6, Sony.... and then you do not need to guess pulses and TX them, just say you want transmit IR code 0x0E with NEC protocol and kernel will do it for you.

With one ir-* command you will tell to kernel "now use this decoder" and then if you run some "rx" (I think it was that ir-keytab) and you press on RC some buttons, you already see scan codes instead RAW pulses (as LIRC done). But of course you can access to RAW pulses as-well

I have to find my text file, where I had recorded SF4008 satellite receiver's remote

I had idea to reuse remote XML files from Enigma2 OpenWebIf project, because they have also pictures for remotes with mapping in HTML and we need only extend those buttons/XML files by attributes like RC Protocol="NEC" and every button like Play button scancode=0x0e

<rc model="my remote" protocol="nec" image="myremote.png">
  <button label="play" coordinates="10 10 20 20" scancode="0x0e" />
</rc>

but seems Enigma2 community again fighting each other, so almost everyone made their repositories private. :(

@petrkr
Copy link

petrkr commented May 19, 2022

and if I remember well, there could be some mapping file scancode vs keycode (check https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h ) and if I remember well it can be used as /dev/input device then.

But I do not know if I do not merging two things at once, because that time I also played with that Linux based satellite receiver

@crutonjohn
Copy link
Owner Author

thanks @petrkr

i've got a working POC by capturing codes with ir-ctl --device=/dev/lirc1 -r > file for each key, then re-transmitting those codes with ir-ctl --device=/dev/lirc0 --send=./file

so it's clear we don't need the old LIRC daemon anymore.

i'm trying to come up with a user-friendly way to capture codes, stumbled upon https://github.com/Rafostar/ir-gen which i am now adapting to work (it's only slightly functional).

hopefully i can get an MR going soon once i fix the script.

@crutonjohn
Copy link
Owner Author

so far i'm having troubles building the keymap file. the aforementioned ir-gen command outputs something like this:

EKL-81UA.toml

[[protocols]]
name = "autogenerated_1653081700"
protocol = "pulse_length"
bits = "33"
header_pulse = "963"
header_space = "328"
trailer_pulse = "547"
bit_space = "4551"
bit_0_pulse = "7481"
bit_1_pulse = "521"
[protocols.scancodes]
0x0123456 = 'KEY_POWER'

this seems good at first, but you diff that with my working LIRC-based config we start to see some stark contrasts:

EKL-81UA.lircd.conf

begin remote

  name  EKL-81UA
  bits           24
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       8901  4518
  one           518  1719
  zero          518   612
  ptrail        526
  repeat       8904  2296
  pre_data_bits   8
  pre_data       0x0
  gap          107346
  toggle_bit_mask 0x0
  frequency    38000

      begin codes
          KEY_1                    0xFF629D 0x000000
          KEY_2                    0xFF22DD 0x000000
          KEY_3                    0xFF02FD 0x000000
          KEY_4                    0xFFC23D 0x000000
          KEY_5                    0xFFE01F 0x000000
          KEY_6                    0xFFA857 0x000000
          KEY_7                    0xFF906F 0x000000
          KEY_8                    0xFF6897 0x000000
      end codes

end remote

the bits aren't even calculated the same, but i went ahead and pressed on. i fed EKL-81UA.toml into ir-keytable like so to capture the codes:
ir-keytable -c -w /etc/rc_keymaps/EKL-81UA.toml -t

returned codes are as follows:

[root@pikvm(g:master) g:/]# ir-keytable -c -w /etc/rc_keymaps/EKL-81UA.toml -t
Read autogenerated_1653081700 table
Old keytable cleared
Wrote 1 keycode(s) to driver
Protocols changed to
Can't find pulse_length bpf protocol in /etc/rc_keymaps/protocols or /usr/lib/udev/rc_keymaps/protocols
Testing events. Please, press CTRL-C to abort.

clearly we need a valid protocol, so i changed protocol = "pulse_length" to be protocol = "nec". this resulted in me being able to capture codes:

[root@pikvm(g:master) g:/]# ir-keytable -c -w /etc/rc_keymaps/EKL-81UA.toml -t
Read autogenerated_1653081700 table
Old keytable cleared
Wrote 1 keycode(s) to driver
Protocols changed to nec
Testing events. Please, press CTRL-C to abort.
108017.850095: lirc protocol(nec): scancode = 0x46
108017.850115: event type EV_MSC(0x04): scancode = 0x46
108017.850115: event type EV_SYN(0x00).
108017.920033: lirc protocol(nec): scancode = 0x46 repeat
108017.920055: event type EV_MSC(0x04): scancode = 0x46
108017.920055: event type EV_SYN(0x00).
108023.310044: lirc protocol(nec): scancode = 0x46 repeat
108023.310064: event type EV_MSC(0x04): scancode = 0x46
108023.310064: event type EV_SYN(0x00).
108024.240053: lirc protocol(nec): scancode = 0x7
108024.240078: event type EV_MSC(0x04): scancode = 0x07
108024.240078: event type EV_SYN(0x00).
108024.290053: lirc protocol(nec): scancode = 0x7 repeat
108024.290068: event type EV_MSC(0x04): scancode = 0x07
108024.290068: event type EV_SYN(0x00).
108024.410046: lirc protocol(nec): scancode = 0x7 repeat
108024.410067: event type EV_MSC(0x04): scancode = 0x07
108024.410067: event type EV_SYN(0x00).
108025.510030: lirc protocol(nec): scancode = 0x15
108025.510052: event type EV_MSC(0x04): scancode = 0x15
108025.510052: event type EV_SYN(0x00).
108025.560036: lirc protocol(nec): scancode = 0x15 repeat
108025.560055: event type EV_MSC(0x04): scancode = 0x15
108025.560055: event type EV_SYN(0x00).
108025.650051: lirc protocol(nec): scancode = 0x15 repeat
108025.650068: event type EV_MSC(0x04): scancode = 0x15
108025.650068: event type EV_SYN(0x00).

feeding these back into our EKL-81UA.toml as so to create an actual keymap:

[[protocols]]
name = "autogenerated_1653081700"
protocol = "nec"
bits = "33"
header_pulse = "963"
header_space = "328"
trailer_pulse = "547"
bit_space = "4551"
bit_0_pulse = "7481"
bit_1_pulse = "521"
[protocols.scancodes]
0x46 = 'KEY_1'
0x44 = 'KEY_2'
0x40 = 'KEY_3'
0x43 = 'KEY_4'
0x7  = 'KEY_5'
0x15 = 'KEY_6'
0x9  = 'KEY_7'
0x16 = 'KEY=8'

unfortunately however, when going back to transmit the captured codes the KVM does not respond:
ir-ctl --device=/dev/lirc0 -K KEY_1 -k /etc/rc_keymaps/EKL-81UA.toml

if we compare the keycodes from the working LIRC config EKL-81UA.lircd.conf and the ones mapped from ir-keytable, there is clearly something awry:

ir-keytable

0x46 = 'KEY_1'
0x44 = 'KEY_2'
0x40 = 'KEY_3'
0x43 = 'KEY_4'
0x7  = 'KEY_5'
0x15 = 'KEY_6'
0x9  = 'KEY_7'
0x16 = 'KEY=8'

EKL-81UA.lircd.conf

KEY_1                    0xFF629D 0x000000
KEY_2                    0xFF22DD 0x000000
KEY_3                    0xFF02FD 0x000000
KEY_4                    0xFFC23D 0x000000
KEY_5                    0xFFE01F 0x000000
KEY_6                    0xFFA857 0x000000
KEY_7                    0xFF906F 0x000000
KEY_8                    0xFF6897 0x000000

@petrkr if you have any clue where to begin with this or any resources that would aid me in this hex code purgatory, that would be most welcomed.

@petrkr
Copy link

petrkr commented May 21, 2022

if I remember well, there are two separated devices in /dev (lirc0, lirc1) one for RX one for TX (as you loaded two GPIO modules). So be sure you use that TX one.

and this is command which I've used to send actuall key... If you recorded scan code 0x15 of NEC protocol, then try to use
ir-ctl -d /dev/lirc1 -S nec:0x15 -v

change /dev/lircX according to your TX device. Also you can check camera if that diode really transmits (flashing)

@petrkr
Copy link

petrkr commented May 21, 2022

Finally I found time to get photo of my TX/RX...

I used transistor to drive LED. Notice also SMD resistor on bottom.
IMG_20220521_110820505_scale
IMG_20220521_110841832_scale
image

quick PCB
image

@crutonjohn
Copy link
Owner Author

MUCH appreciated, @petrkr

I have it wired up correctly as when I am using the LIRC daemon, everything is working. Confirmed the LED is flashing on submission of TX, and I'm able to capture accurate codes when using the daemon as well (after switching the correct device as you mention in your post).

I just can't figure out why ir-keytable is able to "see" that something is transmitting, but unable to accurately capture what codes are being sent.

@seanyoung
Copy link

so far i'm having troubles building the keymap file. the aforementioned ir-gen command outputs something like this:

EKL-81UA.toml

[[protocols]]
name = "autogenerated_1653081700"
protocol = "pulse_length"
bits = "33"
header_pulse = "963"
header_space = "328"
trailer_pulse = "547"
bit_space = "4551"
bit_0_pulse = "7481"
bit_1_pulse = "521"
[protocols.scancodes]
0x0123456 = 'KEY_POWER'

this seems good at first, but you diff that with my working LIRC-based config we start to see some stark contrasts:

EKL-81UA.lircd.conf

begin remote

  name  EKL-81UA
  bits           24
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       8901  4518
  one           518  1719
  zero          518   612
  ptrail        526
  repeat       8904  2296
  pre_data_bits   8
  pre_data       0x0
  gap          107346
  toggle_bit_mask 0x0
  frequency    38000

      begin codes
          KEY_1                    0xFF629D 0x000000
          KEY_2                    0xFF22DD 0x000000
          KEY_3                    0xFF02FD 0x000000
          KEY_4                    0xFFC23D 0x000000
          KEY_5                    0xFFE01F 0x000000
          KEY_6                    0xFFA857 0x000000
          KEY_7                    0xFF906F 0x000000
          KEY_8                    0xFF6897 0x000000
      end codes

end remote

This lircd.conf file is describing the nec protocol. You can convert this lircd.conf to toml using lircd2toml.py. You will get:

[[protocols]]
name = 'EKL-81UA'
protocol = 'nec'
[protocols.scancodes]
0x46 = 'KEY_1'
0x00 = 'KEY_8'
0x44 = 'KEY_2'
0x40 = 'KEY_3'
0x43 = 'KEY_4'
0x07 = 'KEY_5'
0x15 = 'KEY_6'
0x09 = 'KEY_7'
0x16 = 'KEY_8'

the bits aren't even calculated the same, but i went ahead and pressed on. i fed EKL-81UA.toml into ir-keytable like so to capture the codes: ir-keytable -c -w /etc/rc_keymaps/EKL-81UA.toml -t

returned codes are as follows:

[root@pikvm(g:master) g:/]# ir-keytable -c -w /etc/rc_keymaps/EKL-81UA.toml -t
Read autogenerated_1653081700 table
Old keytable cleared
Wrote 1 keycode(s) to driver
Protocols changed to
Can't find pulse_length bpf protocol in /etc/rc_keymaps/protocols or /usr/lib/udev/rc_keymaps/protocols

This is a problem in the v4l-utils package. The BPF decoders are missing.

Note that you can still use this toml file for transmitting. That should be unaffected by the packaging bug.

Testing events. Please, press CTRL-C to abort.


clearly we need a valid protocol, so i changed `protocol = "pulse_length"` to be `protocol = "nec"`. this resulted in me being able to capture codes:

[root@pikvm(g:master) g:/]# ir-keytable -c -w /etc/rc_keymaps/EKL-81UA.toml -t
Read autogenerated_1653081700 table
Old keytable cleared
Wrote 1 keycode(s) to driver
Protocols changed to nec
Testing events. Please, press CTRL-C to abort.
108017.850095: lirc protocol(nec): scancode = 0x46
108017.850115: event type EV_MSC(0x04): scancode = 0x46
108017.850115: event type EV_SYN(0x00).
108017.920033: lirc protocol(nec): scancode = 0x46 repeat
108017.920055: event type EV_MSC(0x04): scancode = 0x46
108017.920055: event type EV_SYN(0x00).
108023.310044: lirc protocol(nec): scancode = 0x46 repeat
108023.310064: event type EV_MSC(0x04): scancode = 0x46
108023.310064: event type EV_SYN(0x00).
108024.240053: lirc protocol(nec): scancode = 0x7
108024.240078: event type EV_MSC(0x04): scancode = 0x07
108024.240078: event type EV_SYN(0x00).
108024.290053: lirc protocol(nec): scancode = 0x7 repeat
108024.290068: event type EV_MSC(0x04): scancode = 0x07
108024.290068: event type EV_SYN(0x00).
108024.410046: lirc protocol(nec): scancode = 0x7 repeat
108024.410067: event type EV_MSC(0x04): scancode = 0x07
108024.410067: event type EV_SYN(0x00).
108025.510030: lirc protocol(nec): scancode = 0x15
108025.510052: event type EV_MSC(0x04): scancode = 0x15
108025.510052: event type EV_SYN(0x00).
108025.560036: lirc protocol(nec): scancode = 0x15 repeat
108025.560055: event type EV_MSC(0x04): scancode = 0x15
108025.560055: event type EV_SYN(0x00).
108025.650051: lirc protocol(nec): scancode = 0x15 repeat
108025.650068: event type EV_MSC(0x04): scancode = 0x15
108025.650068: event type EV_SYN(0x00).


feeding these back into our `EKL-81UA.toml` as so to create an actual keymap:

[[protocols]]
name = "autogenerated_1653081700"
protocol = "nec"
bits = "33"
header_pulse = "963"
header_space = "328"
trailer_pulse = "547"
bit_space = "4551"
bit_0_pulse = "7481"
bit_1_pulse = "521"
[protocols.scancodes]
0x46 = 'KEY_1'
0x44 = 'KEY_2'
0x40 = 'KEY_3'
0x43 = 'KEY_4'
0x7 = 'KEY_5'
0x15 = 'KEY_6'
0x9 = 'KEY_7'
0x16 = 'KEY=8'

This looks good except for there are lots of pointless fields like bits, bit_space etc.

unfortunately however, when going back to transmit the captured codes the KVM does not respond: ir-ctl --device=/dev/lirc0 -K KEY_1 -k /etc/rc_keymaps/EKL-81UA.toml

It might be worth transmitting it using the toml file with the pulse_length protocol. Does that work?

Your original code did irsend --count=5. I suspect that is the problem; the device may only respond after receiving the code N times. ir-ctl doesn't have a count option. What happens if you try ir-ctl --device=/dev/lirc0 -K KEY_1 -K KEY_1 -K KEY_1 -k /etc/rc_keymaps/EKL-81UA.toml ?

I'm working on IR tooling which can read lircd.conf files directly, but
this is fairly new code and largely untested. This is written in rust, so
has to be installed via cargo install cir. Once the cir tool is installed,
you can run:

cir transmit lircd --repeats 5 -v EKL-81UA.lircd.conf KEY_1

Does that help in any way?

@seanyoung
Copy link

this seems good at first, but you diff that with my working LIRC-based config we start to see some stark contrasts:
EKL-81UA.lircd.conf

begin remote

  name  EKL-81UA
  bits           24
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       8901  4518
  one           518  1719
  zero          518   612
  ptrail        526
  repeat       8904  2296
  pre_data_bits   8
  pre_data       0x0
  gap          107346
  toggle_bit_mask 0x0
  frequency    38000

      begin codes
          KEY_1                    0xFF629D 0x000000
          KEY_2                    0xFF22DD 0x000000
          KEY_3                    0xFF02FD 0x000000
          KEY_4                    0xFFC23D 0x000000
          KEY_5                    0xFFE01F 0x000000
          KEY_6                    0xFFA857 0x000000
          KEY_7                    0xFF906F 0x000000
          KEY_8                    0xFF6897 0x000000
      end codes

end remote

So actually I missed this earlier, but this lircd.conf file sends two codes for each key: there is a trailing 0 code. So, if you want to this with ir-ctl it should be something like:
``ir-ctl --device=/dev/lirc0 -K KEY_1 -k /etc/rc_keymaps/EKL-81UA.toml -S nec:0`

Using this toml file:

[[protocols]]
name = 'EKL-81UA'
protocol = 'nec'
[protocols.scancodes]
0x46 = 'KEY_1'
0x00 = 'KEY_8'
0x44 = 'KEY_2'
0x40 = 'KEY_3'
0x43 = 'KEY_4'
0x07 = 'KEY_5'
0x15 = 'KEY_6'
0x09 = 'KEY_7'
0x16 = 'KEY_8'

I'm working on IR tooling which can read lircd.conf files directly, but this is fairly new code and largely untested. This is written in rust, so has to be installed via cargo install cir. Once the cir tool is installed, you can run:

cir transmit lircd --repeats 5 -v EKL-81UA.lircd.conf KEY_1

If you install cir via cargo install cir then this won't work. There is a bug which is fixed in git: https://github.com/seanyoung/cir/

@crutonjohn
Copy link
Owner Author

crutonjohn commented May 23, 2022

thanks for having a look @seanyoung

This lircd.conf file is describing the nec protocol. You can convert this lircd.conf to toml using lircd2toml.py.

This looks good except for there are lots of pointless fields like bits, bit_space etc.

ok so i've reduced my config(s) to the following based on your recommendations:

pulse_length.toml

[[protocols]]
name = "autogenerated_1653081700"
protocol = "pulse_length"
[protocols.scancodes]
0x46 = 'KEY_1'
0x44 = 'KEY_2'
0x40 = 'KEY_3'
0x43 = 'KEY_4'
0x07 = 'KEY_5'
0x15 = 'KEY_6'
0x09 = 'KEY_7'
0x16 = 'KEY=8'

nec.toml

[[protocols]]
name = 'EKL-81UA'
protocol = 'nec'
[protocols.scancodes]
0x46 = 'KEY_1'
0x44 = 'KEY_2'
0x40 = 'KEY_3'
0x43 = 'KEY_4'
0x07 = 'KEY_5'
0x15 = 'KEY_6'
0x09 = 'KEY_7'
0x16 = 'KEY_8'

minding that the scancodes are matching and have been pulled from the aforementioned ir-keycodes, i went ahead and tried to submit codes using ir-ctl.

[root@pikvm ~]# ir-ctl -d /dev/lirc0 -K KEY_1 -K KEY_1 -K KEY_1 -K KEY_1 -K KEY_1 -k /etc/rc_keymaps/pulse_length.toml
/dev/lirc0: failed to send: Invalid argument
[root@pikvm ~]# ir-ctl -d /dev/lirc0 -K KEY_1 -K KEY_1 -K KEY_1 -K KEY_1 -K KEY_1 -k /etc/rc_keymaps/nec.toml

nec keymap sends, but doesn't actually do anything to the KVM. i have a sneaking suspicion that there is something wrong with the codes that are being captured with ir-keytable, but i don't know how to confirm this beyond a reasonable doubt. I can confirm that the LED is flashing, but not causing any effect to the KVM.

So actually I missed this earlier, but this lircd.conf file sends two codes for each key: there is a trailing 0 code. So, if you want to this with ir-ctl it should be something like:
ir-ctl --device=/dev/lirc0 -K KEY_1 -k /etc/rc_keymaps/EKL-81UA.toml -S nec:0

i tried this as well. LED flashes, affects no change. this almost further reinforces that the codes captured by ir-keytable are potentially inaccurate.

for the record, my versions are:

[root@pikvm ~]# ir-keytable --version
IR keytable control version 1.22.1

[root@pikvm ~]# ir-ctl --version
IR ctl version 1.22.1

if i swap in a keymap that i captured via LIRC to an ir-ctl toml, again the LED flashes, but doesn't result in any changes.

@aflyingcougar and i are digging into this more.

just for the record: lircd.service has been disabled this whole time so i'm not getting any conflicts from the LIRC daemon.

@crutonjohn
Copy link
Owner Author

Struggling to get cir installed as mentioned before. cargo build and cargo install cir are both throwing errors mostly surrounding libc.

@seanyoung
Copy link

Struggling to get cir installed as mentioned before. cargo build and cargo install cir are both throwing errors mostly surrounding libc.

That's weird. Is this a non-glibc, musl system or so? What are the errors?

@seanyoung
Copy link

Struggling to get cir installed as mentioned before. cargo build and cargo install cir are both throwing errors mostly surrounding libc.

That's weird. Is this a non-glibc, musl system or so? What are the errors?

I've just tried cargo install cir on an archlinux latest and it works fine. Not sure what is going on, but would be interesting to know. What version of cargo and archlinux do you have?

@crutonjohn
Copy link
Owner Author

in the middle of switching laptops (moving from Mac to Linux full time here shortly). give me some time to come back to this.

i'm sure it'll run no problem on linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants