This sort of thing happens with Free Software, too, but I prefer Microsoft’s phrasing…

Let’s see… that’s various forms of “update” used as nouns, proper nouns, adjectives, and a gerund…
The Smell of Molten Projects in the Morning
Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
General-purpose computers doing something specific
That comment suggested a different solution to the problem of having the display manager start before the NFS mounts complete. When that happens, you can sign in and start programs that won’t have access to their data, producing all manner of heartache and confusion.
One complication: it seems /etc/rc.local starts and runs before the network (among other tidbits) gets connected and becomes ready, which means you can’t just plunk your code in that file like you used to, at least not in Ubuntu. Fixing that requires an upstart script triggered when the network interface finally hauls itself to its feet.
There’s no actual link between the NFS mount commands and the display manager startup, but it seems that if you don’t attempt to mount the NFS shares before the network becomes active (which is what happen with shares automounted through /etc/fstab), but wait for the network to come up and then issue the mounts, the shares mount almost instantly and become ready by the time the display manager presents the login screen. That’s better than the kludge I had figured out and works fine, so I’ll run with it until something else breaks.
The not-quite-deterministic fix has three parts:
noauto in the fstab entries for the NFS sharesupstart script to mount those shares after eth0 lights uplightdm to start up normally (i.e., remove my hackish attempts)A sample line from fstab, with the vital noauto option:
oyster:/mnt/bulkdata /mnt/bulkdata nfs noauto,noatime 0 0
The /etc/init/local.conf script assumes the network interface will be eth0, which does not generalize to wireless networks on laptops and suchlike. You could add some Boolean logic to wait for the first of several interfaces, I suppose:
description "Stuff that should be in /etc/rc.local" author "Ed Nisley - KE4ZNU" start on (local-filesystems and net-device-up IFACE=eth0) stop on shutdown script logger Starting local init... logger Mounting NFS filesystems mount /mnt/bulkdata mount /mnt/userfiles mount /mnt/diskimages mount /mnt/music logger Ending local init end script
The lightdm.conf file reverts to the distribution version, with this starting trigger:
start on ((filesystem
and runlevel [!06]
and started dbus
and (drm-device-added card0 PRIMARY_DEVICE_FOR_DISPLAY=1
or stopped udev-fallback-graphics))
or runlevel PREVLEVEL=S)
It’s worth noting that the upstart interpreter hates comment lines embedded within statements: it does not regard them as whitespace and does not ignore them. Just don’t do it. That explains some of the problems I encountered before, but fixing those problems did not eliminate the overall issue.
The end result of all that hocus-pocus makes the box boot the way it used to: the display manager comes up promptly, presents the GUI login screen, and the NFS mounts are ready when you are.
Here’s a combined and sorted list of all the G-Code and M-Code commands for (as many of) the Free Software G-Code interpreters (that I could find) relevant to DIY 3D printing. With any luck, I now know:
The short descriptions come from tables on the original source pages, perhaps with a bit of massaging to make things more uniform; I did as little rearranging and editing as possible.
If you see anything wrong or have another G-Code interpreter I should include, let me know…
3D Printer G-Code and M-Code Commands 27 Feb 2013 Ed Nisley - KE4ZNU V3 - NIST RS274NGC V3- http://www.nist.gov/manuscript-publication-search.cfm?pub_id=823374 LC - LinuxCNC - http://www.linuxcnc.org/docs/ RG - ReplicatorG - http://replicat.org/gcodes and /mcodes JF - Jetty Firmware - http://replicat.org/mcodes at bottom RR - RepRap - http://reprap.org/wiki/G_codes (cross-linked from many G-Code pages) MF - Marlin Firmware dialect of RR (via Dan Newman) G0 LC Coordinated Straight Motion Rapid G0 MF same as G1 G0 RG Rapid Motion G0 RR Rapid move G0 V3 rapid positioning G1 LC Coordinated Straight Motion Feed Rate G1 MF Coordinated Movement X Y Z E G1 RG Coordinated Motion G1 RR Controlled move G1 V3 linear interpolation G2 LC Coordinated Helical Motion Feed Rate G2 MF CW ARC G2 RG Arc - Clockwise G2 V3 circular/helical interpolation (clockwise) G3 LC Coordinated Helical Motion Feed Rate G3 MF CCW ARC G3 RG Arc - Counter Clockwise G3 V3 circular/helical interpolation (counterclockwise) G4 LC Dwell G4 MF Dwell S<seconds> or P<milliseconds> G4 RG Dwell G4 RR Dwell G4 V3 dwell G5.1 LC Quadratic B-Spline G5.2 LC NURBs Block Open G5.3 LC NURBs Block Close G7 LC Diameter Mode (lathe) G8 LC Radius Mode (lathe) G10 LC L10 Set Tool Table, Calculated, Workpiece G10 LC L11 Set Tool Table, Calculated, Fixture G10 LC L1 Set Tool Table Entry G10 LC L20 Coordinate System Origin Setting Calculated G10 LC L2 Coordinate System Origin Setting G10 RG Create Coordinate System Offset from the Absolute one G10 RR Head Offset G10 V3 coordinate system origin setting G17 LC Arc plane XY G17 RG Select XY plane (default) G17 V3 XY-plane selection G17.1 LC Arc plane UV G18 LC Arc plane ZX G18 RG Select XZ plane (not implemented) G18 V3 XZ-plane selection G18.1 LC Arc plane WU G19 LC Arc plane YZ G19 RG Select YX plane (not implemented) G19 V3 YZ-plane selection G19.1 LC Arc plane VW G20 LC Unit of Measure - inch G20 RG Inches as units G20 RR Set Units to Inches G20 V3 inch system selection G21 LC Unit of Measure - millimeter G21 RG Millimeters as units G21 RR Set Units to Millimeters G21 V3 millimeter system selection G28 LC Go to Predefined Position G28 MF Home all Axis G28 RG Home given Axes to maximum G28 RR Move to Origin G28 V3 return to home G28.1 LC Store Predefined Position G29-G32 RR Bed probing G30 LC Go to Predefined Position G30 RG Go Home via Intermediate Point (not implemented) G30 V3 return to secondary home G30.1 LC Store Predefined Position G31 RG Single probe (not implemented) G32 RG Probe area (not implemented) G33 LC Spindle Synchronized Motion G33.1 LC Rigid Tapping G38.2 LC Probe toward, stop on contact, error G38.2 V3 straight probe G38.3 LC Probe toward, stop on contact G38.4 LC Probe away, stop on release, error G38.5 LC Probe away, stop on release G40 LC Cancel Cutter Compensation G40 V3 cancel cutter radius compensation G41 LC Cutter Compensation - left G41 V3 start cutter radius compensation left G41.1 LC Dynamic Cutter Compensation - left G42 LC Cutter Compensation - right G42 V3 start cutter radius compensation right G42.1 LC Dynamic Cutter Compensation - right G43 LC Use Tool Length Offset from Tool Table G43 V3 tool length offset (plus) G43.1 LC Dynamic Tool Length Offset G49 LC Cancel Tool Length Offset G49 V3 cancel tool length offset G53 LC Motion in Machine Coordinate System G53 RG Set absolute coordinate system G53 V3 motion in machine coordinate system G54-G59 RG Use coordinate system from G10 P0-5 G54 LC Select Coordinate System 1 G54 V3 use preset work coordinate system 1 G55 LC Select Coordinate System 2 G55 V3 use preset work coordinate system 2 G56 LC Select Coordinate System 3 G56 V3 use preset work coordinate system 3 G57 LC Select Coordinate System 4 G57 V3 use preset work coordinate system 4 G58 LC Select Coordinate System 5 G58 V3 use preset work coordinate system 5 G59 LC Select Coordinate System 6 G59 V3 use preset work coordinate system 6 G59.1 LC Select Coordinate System 7 G59.1 V3 use preset work coordinate system 7 G59.2 LC Select Coordinate System 8 G59.2 V3 use preset work coordinate system 8 G59.3 LC Select Coordinate System 9 G59.3 V3 use preset work coordinate system 9 G61 LC Path Control Mode - exact path G61 V3 set path control mode: exact path G61.1 LC Path Control Mode - exact stop (same as G61) G61.1 V3 set path control mode: exact stop G64 LC Path Control Mode - Optional Tolerance G64 V3 set path control mode: continuous G73 LC Drilling Cycle with Chip Breaking G76 LC Multi-pass Threading Cycle (Lathe) G80 LC Cancel Motion Modes G80 V3 cancel motion mode (including any canned cycle) G81 LC Drilling Cycle G81 V3 canned cycle: drilling G82 LC Drilling Cycle with Dwell G82 V3 canned cycle: drilling with dwell G83 LC Drilling Cycle with Peck G83 V3 canned cycle: peck drilling G84 V3 canned cycle: right hand tapping G85 LC Boring Cycle, No Dwell, Feed Out G85 V3 canned cycle: boring, no dwell, feed out G86 LC Boring Cycle, Stop, Rapid Out G86 V3 canned cycle: boring, spindle stop, rapid out G87 V3 canned cycle: back boring G88 V3 canned cycle: boring, spindle stop, manual out G89 LC Boring Cycle, Dwell, Feed Out G89 V3 canned cycle: boring, dwell, feed out G90 LC G91 Distance Mode G90 MF Use Absolute Coordinates G90 RG Absolute Positioning G90 RR Set to Absolute Positioning G90 V3 absolute distance mode G90.1 LC Arc Distance Mode - absolute IJK G91 MF Use Relative Coordinates G91 RG Relative Positioning G91 RR Set to Relative Positioning G91 V3 incremental distance mode G91.1 LC Arc Distance Mode - incremental IJK G92.1 V3 cancel offset coordinate systems and set parameters to zero G92 LC Coordinate System Offset G92 MF Set current position to cordinates given G92 RG Define current position on axes G92 RR Set Position G92 V3 offset coordinate systems and set parameters G92.1 LC Cancel Coordinate System Offsets G92.2 LC Cancel Coordinate System Offsets G92.2 V3 cancel offset coordinate systems but do not reset parameters G92.3 LC Restore Axis Offsets G92.3 V3 apply parameters to offset coordinate systems G93 LC Feed Mode - Inverse time G93 V3 inverse time feed rate mode G94 LC Feed Mode - Units per minute G94 RG Feed rate mode (not implemented) G94 V3 units per minute feed rate mode G95 LC Feed Mode - Units per revolution G96 LC Constant Surface Speed G97 LC RPM Mode G97 RG Spindle speed rate G98 LC Canned Cycle Z Retract Mode G98 V3 initial level return in canned cycles G99 LC Canned Cycle Z Retract Mode G99 V3 R-point level return in canned cycles G161 RG Home negative G162 RG Home positive M0 LC Program Pause M0 RG Unconditional Halt (not supported on SD) M0 RR Stop M0 V3 program stop M1 LC Program Pause - optional M1 RG Optional Halt (not supported on SD) M1 RR Sleep M1 V3 optional program stop M2 LC Program End M2 RG End program M2 V3 program end M3 LC Spindle Control - clockwise ON M3 RG spindle on, CW M3 RR Spindle On, Clockwise (CNC specific) M3 V3 turn spindle clockwise M4 LC Spindle Control - counterclockwise ON M4 RG spindle on, CCW M4 RR Spindle On, Counter-Clockwise (CNC specific) M4 V3 turn spindle counterclockwise M5 LC Spindle Control - OFF M5 RG spindle off M5 RR Spindle Off (CNC specific) M5 V3 stop spindle turning M6 LC Tool Change M6 RG Tool change. This code waits until the toolhead is ready before proceeding. This is often used to wait for a toolhead to reach the its set temperature before beginning a print. ReplicatorG also supports giving a timeout with M6 P<secs>. M6 V3 tool change M7 LC Coolant Control - mist ON M7 RG coolant A on (flood coolant) M7 RR Mist Coolant On (CNC specific) M7 V3 mist coolant on M8 LC Coolant Control - flood ON M8 RG cooland B on (mist coolant) M8 RR Flood Coolant On (CNC specific) M8 V3 flood coolant on M9 LC Coolant Control - OFF M9 RG all coolants off M9 RR Coolant Off (CNC specific) M9 V3 mist and flood coolant off M10 RG close clamp M10 RR Vacuum On (CNC specific) M11 RG open clamp M11 RR Vacuum Off (CNC specific) M13 RG spindle CW and coolant A on M14 RG spindle CCW and coolant A on M17 MF Enable/Power all stepper motors M17 RG enable motor(s) M17 RR Enable/Power all stepper motors M18 MF Disable all stepper motors; same as M84 M18 RG disable motor(s) M18 RR Disable all stepper motors M20 MF List SD card M20 RR List SD card M21 MF Init SD card M21 RG open collet M21 RR Initialize SD card M22 MF Release SD card M22 RG close collet M22 RR Release SD card M23 MF Select SD file (M23 filename.g) M23 RR Select SD file M24 MF Start/resume SD print M24 RR Start/resume SD print M25 MF Pause SD print M25 RR Pause SD print M26 MF Set SD position in bytes (M26 S12345) M26 RR Set SD position M27 MF Report SD print status M27 RR Report SD print status M28 MF Start SD write (M28 filename.g) M28 RR Begin write to SD card M29 MF Stop SD write M29 RR Stop writing to SD card M30 LC Program End - exchange pallet shuttles M30 MF Delete file from SD (M30 filename.g) M30 RG program rewind M30 RR Delete a file on the SD card M30 V3 program end, pallet shuttle, and reset M31 MF Output time since last M109 or SD card start to serial M40-M46 RG change gear ratio (0 - 6) M40 RR Eject M41 RR Loop M42 MF Change pin status via gcode M42 RR Stop on material exhausted / Switch I/O pin M43 RR Stand by on material exhausted M48 LC Feed & Spindle Overrides - Enable M48 V3 enable speed and feed overrides M49 LC Feed & Spindle Overrides - Disable M49 V3 disable speed and feed overrides M50 LC Feed Override Control M50 RG read spindle speed M51 LC Spindle Override Control M52 LC Adaptive Feed Control M53 LC Feed Stop Control M60 LC Pallet Change Pause M60 V3 pallet shuttle and program stop M61 LC Set Current Tool Number M62 LC Output Control - synchronized ON M63 LC Output Control - synchronized OFF M64 LC Output Control - immediate ON M65 LC Output Control - immediate OFF M66 LC Input Control - wait M67 LC Analog Output Control - synchronized M68 LC Analog Output Control - immediate M70 RG Display message on machine, with optional timeout specified by P-code in seconds M71 RG Pause activity and display message, resuming build on button push. Optional timeout specified by P-code in seconds. If timeout is specified and no button is pushed, machine should shut down or reset. M72 RG Play a song or tone defined by the machine, by a P-code specifying a song type. Default songs are Error Sound (P0), a Ta-da sound (P1), and a warning sound (P2). all other sounds are user or machine specific, with P2 the default for unknown sounds. M73 RG Manually set build percentage. Valid P values are 0 to 100, values over 100 are rounded down to 100 M80 MF Turn on Power Supply M80 RR ATX Power On M81 MF Turn off Power Supply M81 RR ATX Power Off M82 MF Set E codes absolute (default) M82 RR set extruder to absolute mode M83 MF Set E codes relative while in Absolute Coordinates (G90) mode M83 RR set extruder to relative mode M84 MF Disable steppers until next move, or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. M84 RR Stop idle hold M85 MF Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default) M92 MF Set axis_steps_per_unit - same syntax as G92 M92 RR Set axis_steps_per_unit M98 RR Get axis_hysteresis_mm M99 RR Set axis_hysteresis_mm M100 LC through M199 User Defined M codes M101 RR Extruder on, fwd M101 RR Turn extruder 1 on Forward / Undo Extruder Retraction M102 RR Extruder on, reverse M102 RR Turn extruder 1 on Reverse M103 RR Extruder off M103 RR Turn all extruders off / Extruder Retraction M104 MF Set extruder target temp M104 RR Set Extruder Temperature M104 RR Snn set temperature in degrees Celsius M105 MF Read current temp M105 RR get extruder temperature M105 RR Get Extruder Temperature M106 MF Fan on M106 RR Fan On M106 RR turn fan on M107 MF Fan off M107 RR Fan Off M107 RR turn fan off M108 RR Set Extruder's Max Speed (Rnnn = RPM, Pnnn = PWM) M108 RR Set Extruder Speed M109 MF Wait for extruder current temp to reach target temp. M109 RR Set Extruder Temperature and Wait M109 RR Snnn set build platform temperature in degrees Celsuis M110 RR Set Current Line Number M110 RR Snnn set chamber temperature in degrees Celsius M111 RR Set Debug Level M112 RR Emergency Stop M113 RR Set Extruder PWM M114 MF Display current position M114 MF Output current position to serial port M114 RR Get Current Position M115 MF Capabilities string M115 RR Get Firmware Version and Capabilities M116 RR Wait M117 MF display message M117 RR Get Zero Position M118 RR Negotiate Features M119 MF Output Endstop status to serial port M119 RR Get Endstop Status M120 RR M121, M122 Snnn set the PID gain for the temperature regulator (not currently supported by ReplicatorG) M123 RR M124 Snnn set iMax and iMin windup guard for the PID controller (not currently supported by ReplicatorG) M126 JF use acceleration for subsequent instructions M126 RG valve open (acceleration on for subsequent instructions in the Jetty Firmware) M126 RR Open Valve M127 JF disable acceleration for subsequent instructions M127 RG valve close (acceleration off for subsequent instructions in the Jetty Firmware) M127 RR Close Valve M128 RR Extruder Pressure PWM M128 RR get position M129 RR Extruder pressure off M129 RR get range (not currently supported by ReplicatorG) M130 RR Set PID P value M130 RR set range (not currently supported by ReplicatorG) M131 RR Set PID I value M132 RR Set PID D value M133 RR Set PID I limit value M134 RR Write PID values to EEPROM M136 RR Print PID settings to host M140 MF Set bed target temp M140 RR Bed Temperature (Fast) M141 RR Chamber Temperature (Fast) M142 RR Holding Pressure M143 RR Maximum hot-end temperature M160 RR Number of mixed materials M190 MF Wait for bed current temp to reach target temp. M190 RR Wait for bed temperature to reach target temp M200 JF reset (to pick up changes) M200 MF Set filament diameter M200 RR reset driver M200 RR Set filament diameter / Get Endstop Status M201 JF set maximum rates of acceleration/deceleration M201 MF Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) M201 RR Set max printing acceleration M202 MF Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!! M202 RR clear buffer (not currently supported by ReplicatorG) M202 RR Set max travel acceleration M203 JF set maximum feed rates M203 MF Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec M203 RR Set maximum feedrate M204 JF set default rates of acceleration M204 MF Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate M204 RR Set default acceleration M205 JF set minimum feed rates and planner speed M205 MF advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk, E=maximum E jerk M205 RR advanced settings M206 JF set extruded noodle diameter, extruder maximum reverse feed rate, extruder deprime, slowdown limit, and direction of extruder feed M206 MF set additional homeing offset M206 RR set home offset M207 JF set JKN Advance parameters K and K2 M207 RR calibrate z axis by detecting z max length M208 JF set extruder steps per millimeter M208 RR set axis max travel M209 JF turn acceleration planner on or off; enable or disable override of gcode temperature settings M209 RR enable automatic retract M215 JF set steps per millimeter for each axis M216 JF set maximum speed changes for each axis M220 MF S<factor in percent> set speed factor override percentage M220 RR Set speed factor override percentage M221 MF S<factor in percent> set extrude factor override percentage M221 RR set extrude factor override percentage M226 RR Gcode Initiated Pause M227 RR Enable Automatic Reverse and Prime M228 RR Disable Automatic Reverse and Prime M229 RR Enable Automatic Reverse and Prime M230 RR Disable / Enable Wait for Temperature Change M240 MF Trigger a camera to take a photograph M240 RR Start conveyor belt motor / Echo off M241 RR Stop conveyor belt motor / echo on M245 RR Start cooler M246 RR Stop cooler M300 RR Play beep sound M300 RR Snnn set servo 1 position M301 MF Set PID parameters P I and D M301 RR Set PID parameters - Hot End M301 RR Snnn set servo 2 position M302 MF Allow cold extrudes M303 MF PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C) M304 RR Set PID parameters - Bed M310 RG (filepath) logging M311 RG stop logging M312 RG (message) log message M320 RG acceleration on for subsequent instructions M321 RG acceleration off for subsequent instructions M400 MF Finish all moves M420 RR Set RGB Colors as PWM M500 MF stores paramters in EEPROM M500 RR stores paramters in EEPROM M501 MF reads parameters from EEPROM (if you need reset them after you changed them temporarily). M501 RR reads parameters from EEPROM M502 MF reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. M502 RR reverts to the default "factory settings". M503 MF print the current settings (from memory not from eeprom) M503 RR Print settings M999 MF Restart after being stopped by error
Going through the usual dance to reveal the HAL pin names for an Arduino Leonardo knockoff shows that it is, indeed, both a mouse and a keyboard.

Pawing through less /proc/bus/input/devices reveals:
I: Bus=0003 Vendor=2341 Product=8036 Version=0101 N: Name="Arduino LLC Arduino Leonardo" P: Phys=usb-0000:00:1d.0-1/input2 S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.2/input/input3 U: Uniq= H: Handlers=kbd mouse1 event3 B: EV=100017 B: KEY=70000 0 0 0 0 e080ffdf 1cfffff ffffffff fffffffe B: REL=103 B: MSC=10
Tweaking the permissions:
sudo chgrp users /dev/input/event3 sudo chgrp users /dev/input/mouse1 sudo chmod g+w /dev/input/event3 sudo chmod g+w /dev/input/mouse1
The output of lsusb shows something interesting:
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 006: ID 06f2:0011 Emine Technology Co. KVM Switch Keyboard Bus 004 Device 005: ID 046d:c401 Logitech, Inc. TrackMan Marble Wheel Bus 004 Device 004: ID 04d9:1203 Holtek Semiconductor, Inc. MC Industries Keyboard Bus 004 Device 003: ID 046d:c216 Logitech, Inc. Dual Action Gamepad Bus 004 Device 002: ID 0451:2046 Texas Instruments, Inc. TUSB2046 Hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 002 Device 002: ID 2341:8036 Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
For whatever reason, this board doesn’t report a device name. It’s plugged into the same USB port as that mouse, so it gets the same Bus and Device numbers, which helps confirm that’s the board.
Querying the attributes with udevadm produces the all-important product string:
udevadm info --query=all --attribute-walk --name=/dev/bus/usb/002/002
... snippage ...
looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1':
KERNEL=="2-1"
SUBSYSTEM=="usb"
DRIVER=="usb"
ATTR{configuration}==""
ATTR{bNumInterfaces}==" 3"
ATTR{bConfigurationValue}=="1"
ATTR{bmAttributes}=="80"
ATTR{bMaxPower}=="500mA"
ATTR{urbnum}=="17"
ATTR{idVendor}=="2341"
ATTR{idProduct}=="8036"
ATTR{bcdDevice}=="0100"
ATTR{bDeviceClass}=="02"
ATTR{bDeviceSubClass}=="00"
ATTR{bDeviceProtocol}=="00"
ATTR{bNumConfigurations}=="1"
ATTR{bMaxPacketSize0}=="64"
ATTR{speed}=="12"
ATTR{busnum}=="2"
ATTR{devnum}=="2"
ATTR{version}==" 2.00"
ATTR{maxchild}=="0"
ATTR{quirks}=="0x0"
ATTR{authorized}=="1"
ATTR{manufacturer}=="Arduino LLC"
ATTR{product}=="Arduino Leonardo"
Then we know enough to discover what it can do:
halrun
halcmd: loadusr -W hal_input -KRAL Leo
halcmd: show all
Loaded HAL Components:
ID Type Name PID State
5 User hal_input 11265 ready
3 User halcmd11264 11264 ready
Component Pins:
Owner Type Dir Value Name
5 bit OUT FALSE input.0.btn-middle
5 bit OUT TRUE input.0.btn-middle-not
5 bit OUT FALSE input.0.btn-mouse
5 bit OUT TRUE input.0.btn-mouse-not
5 bit OUT FALSE input.0.btn-right
5 bit OUT TRUE input.0.btn-right-not
5 bit OUT FALSE input.0.key-0
5 bit OUT TRUE input.0.key-0-not
5 bit OUT FALSE input.0.key-1
5 bit OUT TRUE input.0.key-1-not
5 bit OUT FALSE input.0.key-102nd
5 bit OUT TRUE input.0.key-102nd-not
5 bit OUT FALSE input.0.key-2
5 bit OUT TRUE input.0.key-2-not
5 bit OUT FALSE input.0.key-3
5 bit OUT TRUE input.0.key-3-not
5 bit OUT FALSE input.0.key-4
5 bit OUT TRUE input.0.key-4-not
5 bit OUT FALSE input.0.key-5
5 bit OUT TRUE input.0.key-5-not
5 bit OUT FALSE input.0.key-6
5 bit OUT TRUE input.0.key-6-not
5 bit OUT FALSE input.0.key-7
5 bit OUT TRUE input.0.key-7-not
5 bit OUT FALSE input.0.key-8
5 bit OUT TRUE input.0.key-8-not
5 bit OUT FALSE input.0.key-9
5 bit OUT TRUE input.0.key-9-not
5 bit OUT FALSE input.0.key-a
5 bit OUT TRUE input.0.key-a-not
5 bit OUT FALSE input.0.key-apostrophe
5 bit OUT TRUE input.0.key-apostrophe-not
5 bit OUT FALSE input.0.key-b
5 bit OUT TRUE input.0.key-b-not
5 bit OUT FALSE input.0.key-backslash
5 bit OUT TRUE input.0.key-backslash-not
5 bit OUT FALSE input.0.key-backspace
5 bit OUT TRUE input.0.key-backspace-not
5 bit OUT FALSE input.0.key-c
5 bit OUT TRUE input.0.key-c-not
5 bit OUT FALSE input.0.key-capslock
5 bit OUT TRUE input.0.key-capslock-not
5 bit OUT FALSE input.0.key-comma
5 bit OUT TRUE input.0.key-comma-not
5 bit OUT FALSE input.0.key-compose
5 bit OUT TRUE input.0.key-compose-not
5 bit OUT FALSE input.0.key-d
5 bit OUT TRUE input.0.key-d-not
5 bit OUT FALSE input.0.key-delete
5 bit OUT TRUE input.0.key-delete-not
5 bit OUT FALSE input.0.key-dot
5 bit OUT TRUE input.0.key-dot-not
5 bit OUT FALSE input.0.key-down
5 bit OUT TRUE input.0.key-down-not
5 bit OUT FALSE input.0.key-e
5 bit OUT TRUE input.0.key-e-not
5 bit OUT FALSE input.0.key-end
5 bit OUT TRUE input.0.key-end-not
5 bit OUT FALSE input.0.key-enter
5 bit OUT TRUE input.0.key-enter-not
5 bit OUT FALSE input.0.key-equal
5 bit OUT TRUE input.0.key-equal-not
5 bit OUT FALSE input.0.key-esc
5 bit OUT TRUE input.0.key-esc-not
5 bit OUT FALSE input.0.key-f
5 bit OUT TRUE input.0.key-f-not
5 bit OUT FALSE input.0.key-f1
5 bit OUT TRUE input.0.key-f1-not
5 bit OUT FALSE input.0.key-f10
5 bit OUT TRUE input.0.key-f10-not
5 bit OUT FALSE input.0.key-f11
5 bit OUT TRUE input.0.key-f11-not
5 bit OUT FALSE input.0.key-f12
5 bit OUT TRUE input.0.key-f12-not
5 bit OUT FALSE input.0.key-f2
5 bit OUT TRUE input.0.key-f2-not
5 bit OUT FALSE input.0.key-f3
5 bit OUT TRUE input.0.key-f3-not
5 bit OUT FALSE input.0.key-f4
5 bit OUT TRUE input.0.key-f4-not
5 bit OUT FALSE input.0.key-f5
5 bit OUT TRUE input.0.key-f5-not
5 bit OUT FALSE input.0.key-f6
5 bit OUT TRUE input.0.key-f6-not
5 bit OUT FALSE input.0.key-f7
5 bit OUT TRUE input.0.key-f7-not
5 bit OUT FALSE input.0.key-f8
5 bit OUT TRUE input.0.key-f8-not
5 bit OUT FALSE input.0.key-f9
5 bit OUT TRUE input.0.key-f9-not
5 bit OUT FALSE input.0.key-g
5 bit OUT TRUE input.0.key-g-not
5 bit OUT FALSE input.0.key-grave
5 bit OUT TRUE input.0.key-grave-not
5 bit OUT FALSE input.0.key-h
5 bit OUT TRUE input.0.key-h-not
5 bit OUT FALSE input.0.key-home
5 bit OUT TRUE input.0.key-home-not
5 bit OUT FALSE input.0.key-i
5 bit OUT TRUE input.0.key-i-not
5 bit OUT FALSE input.0.key-insert
5 bit OUT TRUE input.0.key-insert-not
5 bit OUT FALSE input.0.key-j
5 bit OUT TRUE input.0.key-j-not
5 bit OUT FALSE input.0.key-k
5 bit OUT TRUE input.0.key-k-not
5 bit OUT FALSE input.0.key-kp0
5 bit OUT TRUE input.0.key-kp0-not
5 bit OUT FALSE input.0.key-kp1
5 bit OUT TRUE input.0.key-kp1-not
5 bit OUT FALSE input.0.key-kp2
5 bit OUT TRUE input.0.key-kp2-not
5 bit OUT FALSE input.0.key-kp3
5 bit OUT TRUE input.0.key-kp3-not
5 bit OUT FALSE input.0.key-kp4
5 bit OUT TRUE input.0.key-kp4-not
5 bit OUT FALSE input.0.key-kp5
5 bit OUT TRUE input.0.key-kp5-not
5 bit OUT FALSE input.0.key-kp6
5 bit OUT TRUE input.0.key-kp6-not
5 bit OUT FALSE input.0.key-kp7
5 bit OUT TRUE input.0.key-kp7-not
5 bit OUT FALSE input.0.key-kp8
5 bit OUT TRUE input.0.key-kp8-not
5 bit OUT FALSE input.0.key-kp9
5 bit OUT TRUE input.0.key-kp9-not
5 bit OUT FALSE input.0.key-kpasterisk
5 bit OUT TRUE input.0.key-kpasterisk-not
5 bit OUT FALSE input.0.key-kpdot
5 bit OUT TRUE input.0.key-kpdot-not
5 bit OUT FALSE input.0.key-kpenter
5 bit OUT TRUE input.0.key-kpenter-not
5 bit OUT FALSE input.0.key-kpminus
5 bit OUT TRUE input.0.key-kpminus-not
5 bit OUT FALSE input.0.key-kpplus
5 bit OUT TRUE input.0.key-kpplus-not
5 bit OUT FALSE input.0.key-kpslash
5 bit OUT TRUE input.0.key-kpslash-not
5 bit OUT FALSE input.0.key-l
5 bit OUT TRUE input.0.key-l-not
5 bit OUT FALSE input.0.key-left
5 bit OUT TRUE input.0.key-left-not
5 bit OUT FALSE input.0.key-leftalt
5 bit OUT TRUE input.0.key-leftalt-not
5 bit OUT FALSE input.0.key-leftbrace
5 bit OUT TRUE input.0.key-leftbrace-not
5 bit OUT FALSE input.0.key-leftctrl
5 bit OUT TRUE input.0.key-leftctrl-not
5 bit OUT FALSE input.0.key-leftmeta
5 bit OUT TRUE input.0.key-leftmeta-not
5 bit OUT FALSE input.0.key-leftshift
5 bit OUT TRUE input.0.key-leftshift-not
5 bit OUT FALSE input.0.key-m
5 bit OUT TRUE input.0.key-m-not
5 bit OUT FALSE input.0.key-minus
5 bit OUT TRUE input.0.key-minus-not
5 bit OUT FALSE input.0.key-n
5 bit OUT TRUE input.0.key-n-not
5 bit OUT FALSE input.0.key-numlock
5 bit OUT TRUE input.0.key-numlock-not
5 bit OUT FALSE input.0.key-o
5 bit OUT TRUE input.0.key-o-not
5 bit OUT FALSE input.0.key-p
5 bit OUT TRUE input.0.key-p-not
5 bit OUT FALSE input.0.key-pagedown
5 bit OUT TRUE input.0.key-pagedown-not
5 bit OUT FALSE input.0.key-pageup
5 bit OUT TRUE input.0.key-pageup-not
5 bit OUT FALSE input.0.key-pause
5 bit OUT TRUE input.0.key-pause-not
5 bit OUT FALSE input.0.key-q
5 bit OUT TRUE input.0.key-q-not
5 bit OUT FALSE input.0.key-r
5 bit OUT TRUE input.0.key-r-not
5 bit OUT FALSE input.0.key-right
5 bit OUT TRUE input.0.key-right-not
5 bit OUT FALSE input.0.key-rightalt
5 bit OUT TRUE input.0.key-rightalt-not
5 bit OUT FALSE input.0.key-rightbrace
5 bit OUT TRUE input.0.key-rightbrace-not
5 bit OUT FALSE input.0.key-rightctrl
5 bit OUT TRUE input.0.key-rightctrl-not
5 bit OUT FALSE input.0.key-rightmeta
5 bit OUT TRUE input.0.key-rightmeta-not
5 bit OUT FALSE input.0.key-rightshift
5 bit OUT TRUE input.0.key-rightshift-not
5 bit OUT FALSE input.0.key-s
5 bit OUT TRUE input.0.key-s-not
5 bit OUT FALSE input.0.key-scrolllock
5 bit OUT TRUE input.0.key-scrolllock-not
5 bit OUT FALSE input.0.key-semicolon
5 bit OUT TRUE input.0.key-semicolon-not
5 bit OUT FALSE input.0.key-slash
5 bit OUT TRUE input.0.key-slash-not
5 bit OUT FALSE input.0.key-space
5 bit OUT TRUE input.0.key-space-not
5 bit OUT FALSE input.0.key-sysrq
5 bit OUT TRUE input.0.key-sysrq-not
5 bit OUT FALSE input.0.key-t
5 bit OUT TRUE input.0.key-t-not
5 bit OUT FALSE input.0.key-tab
5 bit OUT TRUE input.0.key-tab-not
5 bit OUT FALSE input.0.key-u
5 bit OUT TRUE input.0.key-u-not
5 bit OUT FALSE input.0.key-up
5 bit OUT TRUE input.0.key-up-not
5 bit OUT FALSE input.0.key-v
5 bit OUT TRUE input.0.key-v-not
5 bit OUT FALSE input.0.key-w
5 bit OUT TRUE input.0.key-w-not
5 bit OUT FALSE input.0.key-x
5 bit OUT TRUE input.0.key-x-not
5 bit OUT FALSE input.0.key-y
5 bit OUT TRUE input.0.key-y-not
5 bit OUT FALSE input.0.key-z
5 bit OUT TRUE input.0.key-z-not
5 s32 OUT 0 input.0.rel-wheel-counts
5 float OUT 0 input.0.rel-wheel-position
5 bit IN FALSE input.0.rel-wheel-reset
5 float IN 1 input.0.rel-wheel-scale
5 s32 OUT 0 input.0.rel-x-counts
5 float OUT 0 input.0.rel-x-position
5 bit IN FALSE input.0.rel-x-reset
5 float IN 1 input.0.rel-x-scale
5 s32 OUT 0 input.0.rel-y-counts
5 float OUT 0 input.0.rel-y-position
5 bit IN FALSE input.0.rel-y-reset
5 float IN 1 input.0.rel-y-scale
That’s a pretty decent assortment of directly usable names and features, even without keyboard LEDs. The mouse pins could be repurposed for general sensor values:
I think you could use count to transfer a bare ADC reading from the Leonardo, then use scale to get the actual voltage in “position”. In that situation, reset wouldn’t be at all useful.
The keyboard pins could transfer Boolean sensors.
You’d want to give HAL exclusive control of the Leonardo-is-not-a-mouse, because the incoming data would make hash of the, ah, LinuxCNC UI experience in short order. I’m not sure how to control that; the Leonardo advice boils down to “be careful” and “use a physical switch”.
I have *no* idea where the names come from, but apparently the OS / kernel / something has a HID layer that translates bare USB capability bits into strings. How that relates to a particular device, what the choices might be, how one could add / replace the names for a given device, and all that, I don’t know yet.
I’ve always wondered what the LinuxCNC HAL pin names would be for an ordinary mouse, particularly nowadays when an Arduino Leonardo can become a USB HID gadget without much effort at all. If one had a Leonardo and l337 programming skillz, one might receive far more interesting data than just fast-twitch muscle movement…

So. We begin…
From less /proc/bus/input/devices:
... snippage ... I: Bus=0003 Vendor=046d Product=c077 Version=0111 N: Name="Logitech USB Optical Mouse" P: Phys=usb-0000:00:1d.0-1/input0 S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/input/input10 U: Uniq= H: Handlers=mouse3 event10 B: EV=17 B: KEY=ff0000 0 0 0 0 0 0 0 0 B: REL=143 B: MSC=10
From ll /dev/input:
... snippage ... crw-r----- 1 root root 13, 74 2013-02-23 07:46 event10 ... snippage ... crw-r----- 1 root root 13, 35 2013-02-23 07:46 mouse3
Manually beat the permissions into shape, because this is a one-off affair:
sudo chgrp users /dev/input/event10 sudo chgrp users /dev/input/mouse3 sudo chmod g+w /dev/input/event10 sudo chmod g+w /dev/input/mouse3
Find the USB address from lsusb:
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 006: ID 06f2:0011 Emine Technology Co. KVM Switch Keyboard Bus 004 Device 005: ID 046d:c401 Logitech, Inc. TrackMan Marble Wheel Bus 004 Device 004: ID 04d9:1203 Holtek Semiconductor, Inc. MC Industries Keyboard Bus 004 Device 003: ID 046d:c216 Logitech, Inc. Dual Action Gamepad Bus 004 Device 002: ID 0451:2046 Texas Instruments, Inc. TUSB2046 Hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 002 Device 002: ID 046d:c077 Logitech, Inc. Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Query the attributes with udevadm:
udevadm info --query=all --attribute-walk --name=/dev/bus/usb/002/002
... snippage ...
looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1':
KERNEL=="2-1"
SUBSYSTEM=="usb"
DRIVER=="usb"
ATTR{configuration}==""
ATTR{bNumInterfaces}==" 1"
ATTR{bConfigurationValue}=="1"
ATTR{bmAttributes}=="a0"
ATTR{bMaxPower}==" 98mA"
ATTR{urbnum}=="13"
ATTR{idVendor}=="046d"
ATTR{idProduct}=="c077"
ATTR{bcdDevice}=="6700"
ATTR{bDeviceClass}=="00"
ATTR{bDeviceSubClass}=="00"
ATTR{bDeviceProtocol}=="00"
ATTR{bNumConfigurations}=="1"
ATTR{bMaxPacketSize0}=="8"
ATTR{speed}=="1.5"
ATTR{busnum}=="2"
ATTR{devnum}=="2"
ATTR{version}==" 2.00"
ATTR{maxchild}=="0"
ATTR{quirks}=="0x0"
ATTR{authorized}=="1"
ATTR{manufacturer}=="Logitech"
ATTR{product}=="USB Optical Mouse"
Fire up halrun, load hal_input, and dump the pins:
halrun
halcmd: loadusr -W hal_input -KRAL Optical
halcmd: show all
Loaded HAL Components:
ID Type Name PID State
5 User hal_input 1693 ready
3 User halcmd1692 1692 ready
Component Pins:
Owner Type Dir Value Name
5 bit OUT FALSE input.0.btn-back
5 bit OUT TRUE input.0.btn-back-not
5 bit OUT FALSE input.0.btn-extra
5 bit OUT TRUE input.0.btn-extra-not
5 bit OUT FALSE input.0.btn-forward
5 bit OUT TRUE input.0.btn-forward-not
5 bit OUT FALSE input.0.btn-middle
5 bit OUT TRUE input.0.btn-middle-not
5 bit OUT FALSE input.0.btn-mouse
5 bit OUT TRUE input.0.btn-mouse-not
5 bit OUT FALSE input.0.btn-right
5 bit OUT TRUE input.0.btn-right-not
5 bit OUT FALSE input.0.btn-side
5 bit OUT TRUE input.0.btn-side-not
5 bit OUT FALSE input.0.btn-task
5 bit OUT TRUE input.0.btn-task-not
5 s32 OUT 0 input.0.rel-hwheel-counts
5 float OUT 0 input.0.rel-hwheel-position
5 bit IN FALSE input.0.rel-hwheel-reset
5 float IN 1 input.0.rel-hwheel-scale
5 s32 OUT 0 input.0.rel-wheel-counts
5 float OUT 0 input.0.rel-wheel-position
5 bit IN FALSE input.0.rel-wheel-reset
5 float IN 1 input.0.rel-wheel-scale
5 s32 OUT 0 input.0.rel-x-counts
5 float OUT 0 input.0.rel-x-position
5 bit IN FALSE input.0.rel-x-reset
5 float IN 1 input.0.rel-x-scale
5 s32 OUT 0 input.0.rel-y-counts
5 float OUT 0 input.0.rel-y-position
5 bit IN FALSE input.0.rel-y-reset
5 float IN 1 input.0.rel-y-scale
... snippage ...
Hmmm, that was interesting…
A wannabe spammer inadvertently sent me a nice comment-spam template:
{{You must|You need to|You have to|You should} {take advantage of|make the most of|benefit from|take full advantage of} {all the|all of the|each of the|every one of the} software advancements that {happen to be|are actually|are|are generally} {a successful|an effective|an excellent|a prosperous} {Internet marketer|Online marketer|Internet entrepreneur|Affiliate marketer}. {If your|In case your|Should your|When your} work {begins to|starts to|actually starts to} suffer, {the competition|your competition|competition|your competitors} could {leave you|make you|create} {in the|within the|inside the|from the} dust. Show {that you are|that you will be|that you are currently|you are} always {on the|around the|in the|about the} {cutting edge|innovative|leading edge|really advanced}, {and they will|and they can} {learn to|learn how to|figure out how to|discover how to} trust {you and your|both you and your|you and the|your} products.
Multiplying the number of choices together gives a tidy 4.8×109 different comments, each one heartbreakingly close to making sense.
It’s now in my spam collection, along with some other nuggets snatched from the Internet’s outfall pipe…
The hack I added to the lightdm startup script occasionally causes it to hang, which suggests a timing problem. The result leaves the default text-mode login screen active on VT1, after which I can log in and issue sudo lightdm start to produce the usual GUI screen. Using startx doesn’t (seem to) start the display manager, resulting in all manner of weird behavior.
The definitive Upstart info seems to be in the Upstart Intro, Cookbook, and Best Practises document.
The stanza I modified looks like this:
start on ((filesystem
and runlevel [!06]
and started dbus
and (drm-device-added card0 PRIMARY_DEVICE_FOR_DISPLAY=1
or stopped udev-fallback-graphics)
and mounted MOUNTPOINT=/mnt/bulkdata)
or runlevel PREVLEVEL=S)
According to the timing diagram in section 10.1.8, the filesystem event should happen after all the remote filesystems have been mounted, which seems like that stanza might produce a race condition. So just waiting for the filesystem event should suffice, but it doesn’t; that’s why I had to add the mounted event.
According to the example in section 11.14, that stanza should probably look like:
start on ((filesystem
and (runlevel [!06]
and (started dbus
and (drm-device-added card0 PRIMARY_DEVICE_FOR_DISPLAY=1
or stopped udev-fallback-graphics))))
or runlevel PREVLEVEL=S)
The additional parentheses around successive conditions seem to serialize them, so that they need not all occur at the same time.
At least I think that’s how it should work…
Unfortunately, it doesn’t. The good news is that it’s converted the intermittent failure into a hard fault, which is generally a step in the right direction.
Changing the stanza to:
#start on ((filesystem
start on ((mounted MOUNTPOINT=/mnt/bulkdata
and runlevel [!06]
and started dbus
and (drm-device-added card0 PRIMARY_DEVICE_FOR_DISPLAY=1
or stopped udev-fallback-graphics))
# and mounted MOUNTPOINT=/mnt/bulkdata))
or runlevel PREVLEVEL=S)
… also fails hard.
At this point, I have no idea what to do, so I’ve restored the original stanza.