Go Down

Topic: Using USB Keyboard (Read 20297 times) previous topic - next topic

snooops

here is a reported issue ...
https://github.com/arduino/linino/issues/22

Tunell

#16
Feb 28, 2014, 12:11 am Last Edit: Feb 28, 2014, 12:14 am by Tunell Reason: 1
For anybody who's a noob like me, I've outlined the exact steps of what to do to get the keystrokes to echo properly

1) Download sonnyyu's custom .ipk files on SD card in \arduino\www
https://drive.google.com/file/d/0B49lSur2AThlQ1NnX1hzWFV6UEE/edit?usp=sharing
https://drive.google.com/file/d/0B49lSur2AThleW04WHNqRDc2S0E/edit?usp=sharing

2) Do general package updates
Code: [Select]

  opkg update
  opkg install kmod-input-core
  opkg install kmod-input-evdev


3) Install USB updates kmod-hid***.ipk from your sd card
Code: [Select]

  opkg install /mnt/sda1/arduino/www/kmod-hid_3.8.3-1_ar71xx.ipk
  opkg install /mnt/sda1/arduino/www/kmod-hid-generic_3.8.3-1_ar71xx.ipk


4) Install necessary HID driver  
Code: [Select]

  opkg update
  opkg install kmod-usb-hid


5) Put hid in kernel
Code: [Select]

  insmod  hid-generic
  echo "hid-generic" >>/etc/modules.d/62-hid-generic


6) See the data on the terminal
Code: [Select]

  cat /dev/input/event1  | hexdump     #continuous dumping of raw (useless) hex data
 

OR
Code: [Select]

  hexdump -n 96 /dev/input/event1 | head -n 2 | cut -d' ' -f9  #single keystroke's code and value


7) write a script to continuously monitor and decode /dev/input/event1 stream and echo the characters to the bridge
(still in the works. I'm still very new at this)

here's a link for the USB keycode to ascii lookup:
https://chromium.googlesource.com/chromium/chromium/+/master/ui/base/keycodes/usb_keycode_map.h

sonnyyu


Tunell

#18
Mar 18, 2014, 09:40 pm Last Edit: Mar 18, 2014, 10:25 pm by Tunell Reason: 1

Nice!


Sonnyyu, do you know the best way to have the actual characters dump into the console rather than the keycodes? I've written a script that listens to the events, parses them, and translates them, but it is not looping fast enough to keep up with user input. Keys are being dropped and I'm having to manage the shift and control keys manually. This can't be right...

It seems like there should be a simple solution to this. I'm not super-familiar with linux, but I have a feeling that it is a simple answer that I am just not aware of.

sonnyyu

Plan A: C's evtest
At evtest is include evtest-capture,

Code: [Select]
evtest-capture "/dev/input/eventX" [evtest-capture.xml]

evtest-capture captures the information and events from the input device specified on the command line and writes it to the xml file given. If no filename is given for the output file, evtest-capture.xml is chosen as default.

Cross compile is needed.


Plan B: Python evdev (c-api)

http://packages.python.org/evdev/
Even name is python but it is c-api python, Cross compile is needed.

sonnyyu

Plan C: Python evdev (ctypes)

Micah Dowty wrote very nice pure python evdev.

Install hid driver:

Code: [Select]
opkg update
opkg install kmod-input-core
opkg install     kmod-input-evdev
opkg install wget
cd /tmp
wget https://www.dropbox.com/s/whnf5huyk39krqx/kmod-hid_3.8.3-1_ar71xx.ipk --no-check-certificate
rm /tmp/opkg-lists/*; opkg install kmod-hid_3.8.3-1_ar71xx.ipk
wget https://www.dropbox.com/s/2yegmen4rdy6uwm/kmod-hid-generic_3.8.3-1_ar71xx.ipk --no-check-certificate
opkg install kmod-hid-generic_3.8.3-1_ar71xx.ipk
opkg update
opkg install kmod-usb-hid


Code: [Select]
insmod  hid-generic
echo "hid-generic" >>/etc/modules.d/62-hid-generic


test keyboard driver:  

Code: [Select]
cat /dev/input/event1  | hexdump

download Micah's code ( I clean a little):

Code: [Select]
cd /mnt/sda1
wget https://www.dropbox.com/s/uwy1d0lgawljf3b/evdev.py --no-check-certificate
chmod 755 evdev.py


Test code:

Code: [Select]
./evdev.py '/dev/input/event1'
<Event timestamp=1395255517.851952 type='EV_MSC' code=4 value=458756>
<Event timestamp=1395255517.851952 type='EV_KEY' code='KEY_A' value=1>
30

sonnyyu

Make USB Keyboard works with Arduino, by combine both code.

Code: [Select]
def demo():
...
    dev = DeviceGroup(sys.argv[1:])
    while 1:
        event = dev.next_event()
        if event is not None:
            print repr(event)
            if event.type == "EV_KEY" and event.value == 1:
                if event.code.startswith("KEY"):
                    print event.scanCode
                elif event.code.startswith("BTN"):
                    print event.code


Code: [Select]
#!/usr/bin/python
import sys 
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
from bridgeclient import BridgeClient as bridgeclient
bc = bridgeclient()                         
bc.put('to_arduino',keyboard_code)

Tunell

nice, I'll have to see what I can do with this!

tdicola

#23
Mar 23, 2014, 02:56 am Last Edit: Mar 23, 2014, 03:29 am by tdicola Reason: 1

Make USB Keyboard works with Arduino, by combine both code.

Code: [Select]
def demo():
...
    dev = DeviceGroup(sys.argv[1:])
    while 1:
        event = dev.next_event()
        if event is not None:
            print repr(event)
            if event.type == "EV_KEY" and event.value == 1:
                if event.code.startswith("KEY"):
                    print event.scanCode
                elif event.code.startswith("BTN"):
                    print event.code


Code: [Select]
#!/usr/bin/python
import sys 
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
from bridgeclient import BridgeClient as bridgeclient
bc = bridgeclient()                         
bc.put('to_arduino',keyboard_code)



Thanks for these steps--unfortunately I'm hitting this error when attempting to install the custom kmod-hid:

Code: [Select]

root@Arduino:/tmp# opkg install kmod-hid_3.8.3-1_ar71xx.ipk
Installing kmod-hid (3.8.3-1) to root...
Collected errors:
* satisfy_dependencies_for: Cannot satisfy the following dependencies for kmod-hid:
* kernel (= 3.8.3-1-cf85e4dc55fb28677fb803cf0f9ad60a) *
* opkg_install_cmd: Cannot install package kmod-hid.
root@Arduino:/tmp#


Any idea what might be wrong?  I had just updated my linino OS before finding this thread in the hope that it would fix access to keyboards / mice (it didn't).  Could I have a newer kernel that isn't compatible?

edit: Actually, running uname -r it looks like my kernel is version 3.3.8--that seems kind of weird for it to be lower.  I installed the latest linino image using the steps here: http://linino.org/doku.php?id=wiki:upgradeimage  Are those wrong and did I actually downgrade?  Any pointer on how to get version 3.8.3 ?

edit2: Just reverted to the 1.0 image from http://arduino.cc/en/Tutorial/YunSysupgrade#.Uy5FdnWx2OW and now uname -r returns 3.8.3, phew.  I have no idea what that linino.org page is pointing to but strongly suggest everyone just forget it exists because it seems quite out of date.

tdicola

Got everything working with sunnyyu's instructions.  Can access the events generated from a mouse attached to the Yun.  Thanks again for posting those steps!

What needs to be done to get this fix into the next version of Linino?  This would really be great to resolve as it's quite an interesting scenario to attach USB HID devices to the Yun and use them in sketches through some bridge communication.

sonnyyu


...
edit: Actually, running uname -r it looks like my kernel is version 3.3.8--that seems kind of weird for it to be lower.  I installed the latest linino image using the steps here: http://linino.org/doku.php?id=wiki:upgradeimage  Are those wrong and did I actually downgrade?  Any pointer on how to get version 3.8.3 ?

edit2: Just reverted to the 1.0 image from http://arduino.cc/en/Tutorial/YunSysupgrade#.Uy5FdnWx2OW and now uname -r returns 3.8.3, phew.  I have no idea what that linino.org page is pointing to but strongly suggest everyone just forget it exists because it seems quite out of date.


Thanks a lot for sharing.  ( sunnyyu is typo, it is sonnyyu)

federicofissore

USB keyboard support should be fixed in the latest image we just published. See http://forum.arduino.cc/index.php?topic=235360.0

petros00

Sorry to resurrect such an old thread, but I'm struggling to send keyboard strokes from the linen side to my sketch and can't figure out what to do. I'm running the python script that sonnyyu posted, but then what should I run on the arduino side in order to read the keystrokes?

Thanks

ShapeShifter

I've not specifically tried to talk to a USB keyboard, but I have used a USB scanner that acts like a keyboard. The code should be the same.

My approach was to write a Python script (with a lot of input from sonnyyu) that I could run on the Linux side. This script reads the keyboard keycodes, translates them into ASCII characters, and prints out those characters as they were typed. I'd test it by running that script in a Linux SSH shell, and verify that it displayed the data as expected. The output from the script should be the minimum amount of data to represent what's going on, for example it should just output the letter typed and not a full debug string like "The letter typed is X"

With that working on the Linux side, I then moved on to the sketch. In there, I use a Process object to start the Python script on the Linux side. That automatically starts the Python code, and any output it generates can be read from the Process object.

When setting up the Process object, you want it to be defined up at the file level so it never gets destroyed (don't define it inside loop().) In setup(), start the Process to run asynchronously. Make sure to include "-u" in the Python command line that starts the script, or the output will be buffered and you won't see anything until a large amount of data has been typed, and then you will see it all at once. With the Process started in setup(), you can then look for output from the Process in loop() using Process.available() to see if there is data to read.

I usually take it one step further, and inside of loop I use Process.running() to see if the script is still running. If that returns false, the Python script has crashed, so I restart it with another runAsynchronously() call.

petros00

#29
May 25, 2017, 02:05 pm Last Edit: May 25, 2017, 02:17 pm by petros00
I'm using sonnyyu's version of Micah's code(found further up in this thread) which when run in ssh produces this type of results if keys are pressed:

<Event timestamp=1495713324.5426631 type='EV_RST' code=0 value=0>
<Event timestamp=1495713324.662632 type='EV_MSC' code=4 value=458850>
<Event timestamp=1495713324.6626431 type='EV_KEY' code='KEY_KP0' value=0>
<Event timestamp=1495713324.6626478 type='EV_RST' code=0 value=0>
<Event timestamp=1495713324.6866268 type='EV_MSC' code=4 value=458835>
<Event timestamp=1495713324.6866381 type='EV_KEY' code='KEY_NUMLOCK' value=1>

I'm very curious to see if only the values get passed to arduino or the whole lines.

In order to get the script going, I do this: python /mnt/sda1/evdev.py '/dev/input/event1'

On the arduino side, should it be the same, e.g., this?

p.begin("/mnt/sda1/evdev.py '/dev/input/event1'");
p.runAsynchronously();

In this case, where do I put the -u? I tried putting it after event1' but I still see nothing in serial monitor. The code I use on 32u4 side is this:

Code: [Select]
#include "Bridge.h"
#include "Process.h"

Process p;

void setup() {
  Serial.begin(19200);
  Bridge.begin();
  
  p.begin("/mnt/sda1/evdev.py '/dev/input/event1' -u");
  p.runAsynchronously();
}

void loop() {
  while (p.available() )
    Serial.print((char)p.read());
}




Also, sonny suggests using this code to get the data over to 32u4, where does it need to go?

Code: [Select]
#!/usr/bin/python
import sys 
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
from bridgeclient import BridgeClient as bridgeclient
bc = bridgeclient()                         
bc.put('to_arduino',keyboard_code)


Sorry for the many questions, I have zero knowledge on programming, learning a bit as I go...

Go Up