A (formerly Belkin, now Razer, which is evidently unrelated to Mazer Rackham) Nostromo N52 SpeedPad might not be a perfect CNC pendant, but it does have plenty of buttons and an (oddly oriented) XY joypad that might be useful for, say, a 3D printer controller running LinuxCNC.

Following the same path as with the Logitech Dual Action Gamepad that became the Joggy Thing, we find that the N52 reports itself as a keyboard and a mouse:
less /proc/bus/input/devices ... snippage ... I: Bus=0003 Vendor=050d Product=0815 Version=0110 N: Name="Honey Bee Nostromo SpeedPad2 " P: Phys=usb-0000:00:02.0-10/input0 S: Sysfs=/devices/pci0000:00/0000:00:02.0/usb2/2-10/2-10:1.0/input/input3 U: Uniq= H: Handlers=kbd event3 B: EV=100013 B: KEY=e080ffdf 1cfffff ffffffff fffffffe B: MSC=10 I: Bus=0003 Vendor=050d Product=0815 Version=0110 N: Name="Honey Bee Nostromo SpeedPad2 " P: Phys=usb-0000:00:02.0-10/input1 S: Sysfs=/devices/pci0000:00/0000:00:02.0/usb2/2-10/2-10:1.1/input/input4 U: Uniq= H: Handlers=mouse1 event4 B: EV=20017 B: KEY=70000 0 0 0 0 0 0 0 0 B: REL=103 B: MSC=10 B: LED=7
The corresponding device files belong to the root user:
ll /dev/input ... snippage ... crw-r----- 1 root root 13, 67 2013-02-08 11:06 event3 crw-r----- 1 root root 13, 68 2013-02-08 11:06 event4 ... snippage ... crw-r----- 1 root root 13, 33 2013-02-08 11:06 mouse1
Which calls for some udev trickery to change the owner & permissions during boot / hotplugging so that it becomes available to mere mortals such as I.
First, get the bus connection information:
lsusb ... snippage ... Bus 002 Device 004: ID 050d:0815 Belkin Components Nostromo n52 HID SpeedPad Mouse Wheel ... snippage ...
Then dump the attributes:
udevadm info --query=all --attribute-walk --name=/dev/bus/usb/002/004 Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device. looking at device '/devices/pci0000:00/0000:00:02.0/usb2/2-10': KERNEL=="2-10" SUBSYSTEM=="usb" DRIVER=="usb" ATTR{configuration}=="" ATTR{bNumInterfaces}==" 2" ATTR{bConfigurationValue}=="1" ATTR{bmAttributes}=="80" ATTR{bMaxPower}==" 90mA" ATTR{urbnum}=="1354" ATTR{idVendor}=="050d" ATTR{idProduct}=="0815" ATTR{bcdDevice}=="0210" ATTR{bDeviceClass}=="00" ATTR{bDeviceSubClass}=="00" ATTR{bDeviceProtocol}=="00" ATTR{bNumConfigurations}=="1" ATTR{bMaxPacketSize0}=="8" ATTR{speed}=="1.5" ATTR{busnum}=="2" ATTR{devnum}=="4" ATTR{version}==" 1.10" ATTR{maxchild}=="0" ATTR{quirks}=="0x0" ATTR{authorized}=="1" ATTR{manufacturer}=="Honey Bee " ATTR{product}=="Nostromo SpeedPad2 " ... snippage ...
Note the trailing blank in the manufacturer
and product
values.
Create a new rules file /etc/udev/rule/90-Nostromo.rules
to change the group and permissions:
# Belkin Nostromo N52 SpeedPad controller for LinuxCNC # Ed Nisley - KE4ZNU - February 2013 ATTRS{product}=="Nostromo SpeedPad2",GROUP="plugdev",MODE="0660"
Note that the file name must start with a number around 90-
to avoid being clobbered by a rule in /lib/udev/rules.d/50-udev-default.rules
that (re)sets the permissions to 0640
; the doc suggests that rules without numbers happen after all the number rules, so perhaps you could just use meaningful names. That took an embarrassingly long time to figure out…
There’s no need for the trailing blank in that rule, as the match proceeds left-to-right and stops at the end of the test string.
You must, perforce, be in the plugdev
group. If not, add yourself.
You need not unplug the N52 to test the rule. Just use:
sudo udevadm trigger
Which produces the desired result:
crw-rw---- 1 root plugdev 13, 67 2013-02-08 15:09 event3 crw-rw---- 1 root plugdev 13, 68 2013-02-08 15:09 event4 ... snippage ... crw-rw---- 1 root plugdev 13, 33 2013-02-08 15:09 mouse1
Poking around using, among other things, xev
reveals:
- Main keypad is the left half of a standard QWERTY keyboard
- Joypad returns cursor keys, center push = nothing
- Orange button is, weirdly, the Left-Alt key
- Wheel is a mouse scroll wheel
- Push wheel = middle mouse button
- Thumb pad = space
- RGB LEDs are, respectively, num-, caps-, and scroll-lock
Then load HAL:
halrun loadusr -W hal_input -K +Nostromo:0 -KRL +Nostromo:1 show pin input.* loadusr halmeter
The + prefix tells HAL to capture the named device and prevent its events from reaching X. The KRL
codes suggest which functions you’re interested in for that particular device. The suffix digit selects successive devices for multiple gadgets matching the same name string.
Apparently, the N52 reports it can produce all the usual keyboard and mouse values & buttons, even if they’re not connected to physical hardware. I suspect it has generic keyboard / mouse controllers inside, with just a few of the usual matrix crosspoints connected to switches.
The basic key mapping, sorted by the Nostromo functions:
Type | Dir | Name | Nostromo key |
bit | OUT | input.0.key-tab | F1 |
bit | OUT | input.0.key-q | F2 |
bit | OUT | input.0.key-w | F3 |
bit | OUT | input.0.key-e | F4 |
bit | OUT | input.0.key-r | F5 |
bit | OUT | input.0.key-capslock | F6 |
bit | OUT | input.0.key-a | F7 |
bit | OUT | input.0.key-s | F8 |
bit | OUT | input.0.key-d | F9 |
bit | OUT | input.0.key-f | F10 |
bit | OUT | input.0.key-leftshift | F11 |
bit | OUT | input.0.key-z | F12 |
bit | OUT | input.0.key-x | F13 |
bit | OUT | input.0.key-c | F14 |
bit | OUT | input.0.key-space | F15 |
bit | OUT | input.0.key-leftalt | Orange button |
bit | OUT | input.0.key-right | Pad bottom |
bit | OUT | input.0.key-down | Pad front |
bit | OUT | input.0.key-up | Pad rear |
bit | OUT | input.0.key-left | Pad top |
bit | OUT | input.1.btn-middle | Wheel press |
s32 | OUT | input.1.rel-wheel-counts | Scroll wheel |
bit | IN | input.1.led-numl | Red LED |
bit | IN | input.1.led-capsl | Green LED |
bit | IN | input.1.led-scrolll | Blue LED |
The bit
pins also have inverted values available on the corresponding -not
pins. The LEDs have an -invert
that flips the sense of the input pin. The rel-wheel
pin has other useful tidbits as suffixes; the count
changes by ±1 for each wheel detent.
The Tab
key and all the letters auto-repeat, the various Shift
and Alt
keys do not. That seems to make no difference to the bit values reported by HAL.
The complete table, sorted by HAL pin name:
Type | Dir | Name | Nostromo key |
bit | OUT | input.0.key-0 | |
bit | OUT | input.0.key-0-not | |
bit | OUT | input.0.key-1 | |
bit | OUT | input.0.key-1-not | |
bit | OUT | input.0.key-102nd | |
bit | OUT | input.0.key-102nd-not | |
bit | OUT | input.0.key-2 | |
bit | OUT | input.0.key-2-not | |
bit | OUT | input.0.key-3 | |
bit | OUT | input.0.key-3-not | |
bit | OUT | input.0.key-4 | |
bit | OUT | input.0.key-4-not | |
bit | OUT | input.0.key-5 | |
bit | OUT | input.0.key-5-not | |
bit | OUT | input.0.key-6 | |
bit | OUT | input.0.key-6-not | |
bit | OUT | input.0.key-7 | |
bit | OUT | input.0.key-7-not | |
bit | OUT | input.0.key-8 | |
bit | OUT | input.0.key-8-not | |
bit | OUT | input.0.key-9 | |
bit | OUT | input.0.key-9-not | |
bit | OUT | input.0.key-a | F7 |
bit | OUT | input.0.key-a-not | |
bit | OUT | input.0.key-apostrophe | |
bit | OUT | input.0.key-apostrophe-not | |
bit | OUT | input.0.key-b | |
bit | OUT | input.0.key-b-not | |
bit | OUT | input.0.key-backslash | |
bit | OUT | input.0.key-backslash-not | |
bit | OUT | input.0.key-backspace | |
bit | OUT | input.0.key-backspace-not | |
bit | OUT | input.0.key-c | F14 |
bit | OUT | input.0.key-c-not | |
bit | OUT | input.0.key-capslock | F6 |
bit | OUT | input.0.key-capslock-not | |
bit | OUT | input.0.key-comma | |
bit | OUT | input.0.key-comma-not | |
bit | OUT | input.0.key-compose | |
bit | OUT | input.0.key-compose-not | |
bit | OUT | input.0.key-d | F9 |
bit | OUT | input.0.key-d-not | |
bit | OUT | input.0.key-delete | |
bit | OUT | input.0.key-delete-not | |
bit | OUT | input.0.key-dot | |
bit | OUT | input.0.key-dot-not | |
bit | OUT | input.0.key-down | Pad left |
bit | OUT | input.0.key-down-not | |
bit | OUT | input.0.key-e | F4 |
bit | OUT | input.0.key-e-not | |
bit | OUT | input.0.key-end | |
bit | OUT | input.0.key-end-not | |
bit | OUT | input.0.key-enter | |
bit | OUT | input.0.key-enter-not | |
bit | OUT | input.0.key-equal | |
bit | OUT | input.0.key-equal-not | |
bit | OUT | input.0.key-esc | |
bit | OUT | input.0.key-esc-not | |
bit | OUT | input.0.key-f | F10 |
bit | OUT | input.0.key-f-not | |
bit | OUT | input.0.key-f1 | |
bit | OUT | input.0.key-f1-not | |
bit | OUT | input.0.key-f10 | |
bit | OUT | input.0.key-f10-not | |
bit | OUT | input.0.key-f11 | |
bit | OUT | input.0.key-f11-not | |
bit | OUT | input.0.key-f12 | |
bit | OUT | input.0.key-f12-not | |
bit | OUT | input.0.key-f2 | |
bit | OUT | input.0.key-f2-not | |
bit | OUT | input.0.key-f3 | |
bit | OUT | input.0.key-f3-not | |
bit | OUT | input.0.key-f4 | |
bit | OUT | input.0.key-f4-not | |
bit | OUT | input.0.key-f5 | |
bit | OUT | input.0.key-f5-not | |
bit | OUT | input.0.key-f6 | |
bit | OUT | input.0.key-f6-not | |
bit | OUT | input.0.key-f7 | |
bit | OUT | input.0.key-f7-not | |
bit | OUT | input.0.key-f8 | |
bit | OUT | input.0.key-f8-not | |
bit | OUT | input.0.key-f9 | |
bit | OUT | input.0.key-f9-not | |
bit | OUT | input.0.key-g | |
bit | OUT | input.0.key-g-not | |
bit | OUT | input.0.key-grave | |
bit | OUT | input.0.key-grave-not | |
bit | OUT | input.0.key-h | |
bit | OUT | input.0.key-h-not | |
bit | OUT | input.0.key-home | |
bit | OUT | input.0.key-home-not | |
bit | OUT | input.0.key-i | |
bit | OUT | input.0.key-i-not | |
bit | OUT | input.0.key-insert | |
bit | OUT | input.0.key-insert-not | |
bit | OUT | input.0.key-j | |
bit | OUT | input.0.key-j-not | |
bit | OUT | input.0.key-k | |
bit | OUT | input.0.key-k-not | |
bit | OUT | input.0.key-kp0 | |
bit | OUT | input.0.key-kp0-not | |
bit | OUT | input.0.key-kp1 | |
bit | OUT | input.0.key-kp1-not | |
bit | OUT | input.0.key-kp2 | |
bit | OUT | input.0.key-kp2-not | |
bit | OUT | input.0.key-kp3 | |
bit | OUT | input.0.key-kp3-not | |
bit | OUT | input.0.key-kp4 | |
bit | OUT | input.0.key-kp4-not | |
bit | OUT | input.0.key-kp5 | |
bit | OUT | input.0.key-kp5-not | |
bit | OUT | input.0.key-kp6 | |
bit | OUT | input.0.key-kp6-not | |
bit | OUT | input.0.key-kp7 | |
bit | OUT | input.0.key-kp7-not | |
bit | OUT | input.0.key-kp8 | |
bit | OUT | input.0.key-kp8-not | |
bit | OUT | input.0.key-kp9 | |
bit | OUT | input.0.key-kp9-not | |
bit | OUT | input.0.key-kpasterisk | |
bit | OUT | input.0.key-kpasterisk-not | |
bit | OUT | input.0.key-kpdot | |
bit | OUT | input.0.key-kpdot-not | |
bit | OUT | input.0.key-kpenter | |
bit | OUT | input.0.key-kpenter-not | |
bit | OUT | input.0.key-kpminus | |
bit | OUT | input.0.key-kpminus-not | |
bit | OUT | input.0.key-kpplus | |
bit | OUT | input.0.key-kpplus-not | |
bit | OUT | input.0.key-kpslash | |
bit | OUT | input.0.key-kpslash-not | |
bit | OUT | input.0.key-l | |
bit | OUT | input.0.key-l-not | |
bit | OUT | input.0.key-left | Pad top |
bit | OUT | input.0.key-left-not | |
bit | OUT | input.0.key-leftalt | Orange button |
bit | OUT | input.0.key-leftalt-not | |
bit | OUT | input.0.key-leftbrace | |
bit | OUT | input.0.key-leftbrace-not | |
bit | OUT | input.0.key-leftctrl | |
bit | OUT | input.0.key-leftctrl-not | |
bit | OUT | input.0.key-leftmeta | |
bit | OUT | input.0.key-leftmeta-not | |
bit | OUT | input.0.key-leftshift | F11 |
bit | OUT | input.0.key-leftshift-not | |
bit | OUT | input.0.key-m | |
bit | OUT | input.0.key-m-not | |
bit | OUT | input.0.key-minus | |
bit | OUT | input.0.key-minus-not | |
bit | OUT | input.0.key-n | |
bit | OUT | input.0.key-n-not | |
bit | OUT | input.0.key-numlock | |
bit | OUT | input.0.key-numlock-not | |
bit | OUT | input.0.key-o | |
bit | OUT | input.0.key-o-not | |
bit | OUT | input.0.key-p | |
bit | OUT | input.0.key-p-not | |
bit | OUT | input.0.key-pagedown | |
bit | OUT | input.0.key-pagedown-not | |
bit | OUT | input.0.key-pageup | |
bit | OUT | input.0.key-pageup-not | |
bit | OUT | input.0.key-pause | |
bit | OUT | input.0.key-pause-not | |
bit | OUT | input.0.key-q | F2 |
bit | OUT | input.0.key-q-not | |
bit | OUT | input.0.key-r | F5 |
bit | OUT | input.0.key-r-not | |
bit | OUT | input.0.key-right | Pad bottom |
bit | OUT | input.0.key-right-not | |
bit | OUT | input.0.key-rightalt | |
bit | OUT | input.0.key-rightalt-not | |
bit | OUT | input.0.key-rightbrace | |
bit | OUT | input.0.key-rightbrace-not | |
bit | OUT | input.0.key-rightctrl | |
bit | OUT | input.0.key-rightctrl-not | |
bit | OUT | input.0.key-rightmeta | |
bit | OUT | input.0.key-rightmeta-not | |
bit | OUT | input.0.key-rightshift | |
bit | OUT | input.0.key-rightshift-not | |
bit | OUT | input.0.key-s | F8 |
bit | OUT | input.0.key-s-not | |
bit | OUT | input.0.key-scrolllock | |
bit | OUT | input.0.key-scrolllock-not | |
bit | OUT | input.0.key-semicolon | |
bit | OUT | input.0.key-semicolon-not | |
bit | OUT | input.0.key-slash | |
bit | OUT | input.0.key-slash-not | |
bit | OUT | input.0.key-space | F15 |
bit | OUT | input.0.key-space-not | |
bit | OUT | input.0.key-sysrq | |
bit | OUT | input.0.key-sysrq-not | |
bit | OUT | input.0.key-t | |
bit | OUT | input.0.key-t-not | |
bit | OUT | input.0.key-tab | F1 |
bit | OUT | input.0.key-tab-not | |
bit | OUT | input.0.key-u | |
bit | OUT | input.0.key-u-not | |
bit | OUT | input.0.key-up | Pad right |
bit | OUT | input.0.key-up-not | |
bit | OUT | input.0.key-v | |
bit | OUT | input.0.key-v-not | |
bit | OUT | input.0.key-w | F3 |
bit | OUT | input.0.key-w-not | |
bit | OUT | input.0.key-x | F13 |
bit | OUT | input.0.key-x-not | |
bit | OUT | input.0.key-y | |
bit | OUT | input.0.key-y-not | |
bit | OUT | input.0.key-z | F12 |
bit | OUT | input.0.key-z-not | |
bit | OUT | input.1.btn-middle | Wheel press |
bit | OUT | input.1.btn-middle-not | … inverted |
bit | OUT | input.1.btn-mouse | |
bit | OUT | input.1.btn-mouse-not | |
bit | OUT | input.1.btn-right | |
bit | OUT | input.1.btn-right-not | |
bit | IN | input.1.led-capsl | Green LED |
bit | IN | input.1.led-capsl-invert | |
bit | IN | input.1.led-numl | Red LED |
bit | IN | input.1.led-numl-invert | |
bit | IN | input.1.led-scrolll | Blue LED |
bit | IN | input.1.led-scrolll-invert | |
s32 | OUT | input.1.rel-wheel-counts | Scroll wheel |
float | OUT | input.1.rel-wheel-position | =count/scale |
bit | IN | input.1.rel-wheel-reset | Clear pos’n |
float | IN | input.1.rel-wheel-scale | count→pos’n |
s32 | OUT | input.1.rel-x-counts | |
float | OUT | input.1.rel-x-position | |
bit | IN | input.1.rel-x-reset | |
float | IN | input.1.rel-x-scale | |
s32 | OUT | input.1.rel-y-counts | |
float | OUT | input.1.rel-y-position | |
bit | IN | input.1.rel-y-reset | |
float | IN | input.1.rel-y-scale |
3 thoughts on “LinuxCNC HAL Pin Names: Belkin Nostromo N52 SpeedPad”
Comments are closed.