Programing with a PICkit 2 on Linux

January 8, 2020

I recently bought a PICkit 2 clone (the ICA03) from PICCircuit.com. Programming it has been something of a challenge, mostly because Microchip no longer really supports Linux programming of PIC chips.

First, I needed to get pk2cmd. There are lots of pointers to Microchip’s website, but all of them go to 404s. What I ended up using is a github repo: https://github.com/psmay/pk2cmd. After reading the threatening license agreement, I cloned the repo and built it with make then sudo make install.

git clone https://github.com/psmay/pk2cmd
cd pk2cmd/pk2cmd
make linux
sudo make install

Even after installing PK2DeviceFile.dat in /usr/share and including /usr/share/pk2 on the path (ugh) per the instructions, I still wasn’t able to use it from anywhere except the directory I built it from. At some point I’ll need to look into that.

I plugged the PIC into the ZIF socket with the marking near the top, and made sure the selection switch was on 28-40.

Next, I took my .hex file and stuffed it in ~/pk2cmd/pk2cmd/. Then:

~/pk2cmd/pk2cmd$ sudo pk2cmd -P
Auto-Detect: Found part PIC16F886.

Yay! Let’s try writing the file:

~/pk2cmd/pk2cmd$ sudo ./pk2cmd -PPIC16F886 \
 -f my_hex_file.hex -MPC -Y

(I didn’t include IE on the -M switch because I think my hex file has ID and EEPROM memory in it. -Y does the verification.)

PICkit 2 Program Report
8-1-2020, 23:12:12
Device Type: PIC16F886

Program Succeeded.
PICkit 2 Verify Report
8-1-2020, 23:12:12
Device Type: PIC16F886

Verify Succeeded.

Operation Succeeded

Yay!


Mapping a USB volume knob into a keyboard on Linux for SDR

December 16, 2019

I recently discovered the existence of USB volume knobs. A Reddit user posted an article about reflashing the firmware on one to convert it to a keyboard.

 

IMG_20191216_010138

Inspired, I picked one up for $18 on eBay (“USB Volume Controller Knob Adjuster Switcher for Tablet PC Speaker Audio“) and thought that I might be able to do something similar.

It turns out, under Linux, this is pretty easy.

First, I plugged in the volume knob and saw that Linux detected it correctly and used it to adjust the volume. That was a promising start. I could see it show the “HDMI / DisplayPort” volume – and it went up when I turned the knob to the right, down when I turned the knob to the left, and muted when I pressed the knob.

Next, I wanted to see what events were being generated. I found some very useful instructions at https://yulistic.gitlab.io/2017/12/linux-keymapping-with-udev-hwdb/ and did them:

$ cat /proc/bus/input/devices
...
I: Bus=0003 Vendor=0483 Product=572d Version=0111
N: Name="STMicroelectronics USB Volume Control"
P: Phys=usb-0000:00:1d.0-1.7.2.4.3.1/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.7/2-1.7.2/2-1.7.2.4/2-1.7.2.4.3/2-1.7.2.4.3.1/2-1.7.2.4.3.1:1.0/0003:0483:572D.0008/input/input14
U: Uniq=2070363C4250
H: Handlers=kbd event8 
B: PROP=0
B: EV=13
B: KEY=3800000000 e000000000000 0
B: MSC=10
...

This showed me a few useful things:

  • The device vendor for my device is 0483 (the “I:” line)
  • The product ID for my device is 572d (also on the “I:” line)
  • The device is attached on /dev/input/event8 (on the “H:” line)

So now I could scan the events that came across when I moved the knob:

$ sudo evtest /dev/input/event8
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x483 product 0x572d version 0x111
Input device name: "STMicroelectronics USB Volume Control"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 113 (KEY_MUTE)
    Event code 114 (KEY_VOLUMEDOWN)
    Event code 115 (KEY_VOLUMEUP)
    Event code 163 (KEY_NEXTSONG)
    Event code 164 (KEY_PLAYPAUSE)
    Event code 165 (KEY_PREVIOUSSONG)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit)
Event: time 1576479720.245227, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1576479720.245227, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
Event: time 1576479720.245227, -------------- SYN_REPORT ------------
Event: time 1576479720.253248, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1576479720.253248, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0
Event: time 1576479720.253248, -------------- SYN_REPORT ------------
Event: time 1576479722.325231, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1576479722.325231, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1
Event: time 1576479722.325231, -------------- SYN_REPORT ------------
Event: time 1576479722.333224, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1576479722.333224, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 0
Event: time 1576479722.333224, -------------- SYN_REPORT ------------
Event: time 1576479724.381251, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e2
Event: time 1576479724.381251, type 1 (EV_KEY), code 113 (KEY_MUTE), value 1
Event: time 1576479724.381251, -------------- SYN_REPORT ------------
Event: time 1576479724.389251, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e2
Event: time 1576479724.389251, type 1 (EV_KEY), code 113 (KEY_MUTE), value 0
Event: time 1576479724.389251, -------------- SYN_REPORT ------------

Neat, even more useful things. In particular:

  • When I turn the knob to the right, I get an MSC_SCAN event of type c00e9 (along with a KEY_VOLUMEUP event)
  • When I turn the knob to the left, I get an MSC_SCAN event of type c00ea (along with a KEY_VOLUMEDOWN event)
  • When I push on the knob, I get an MSC_SCAN event of type c00e2 (along with a KEY_MUTE event)
  • Apparently the firmware supports KEY_NEXTSONG, KEY_PREVIOUSSONG and KEY_PLAYPAUSE as well. Huh.

I want to map those MSC_SCAN events to different key codes. In particular, I want a cursor-left key when I turn the knob to the left, a cursor-right key when I turn the knob to the right, and something useful (say, pressing the “m” key) when I press the knob. So I created a hwdb file for my device:

$ cat /etc/udev/hwdb.d/99-usb-knob.hwdb
evdev:input:b*v0483p572D*
 KEYBOARD_KEY_c00ea=left
 KEYBOARD_KEY_c00e9=right
 KEYBOARD_KEY_c00e2=m

You’ll recognize the vendor (0483) and the device (572d) that I found earlier. It’s important to use uppercase hex codes for vendor and product in the hwdb file – but not for the scan codes, which should be lowercase. The values on the right have to be lowercase, and correspond to the KEY_LEFT, KEY_RIGHT and KEY_M values from /usr/include/linux/input-event-codes.h. (You can pick any of the KEY_ values from there.) Then a quick bit of Linux magic to update the hardware database:

$ sudo systemd-hwdb update
$ sudo udevadm trigger

…and… exactly the same as before. I got the volume control displayed when I turned the knob.

After scratching my head and doing some searching, I happened on https://catswhisker.xyz/log/2018/8/27/use_vecinfinity_usb_foot_pedal_as_a_keyboard_under_linux/ which gave me the clue I needed. My knob was being detected, but not as a keyboard – so it wasn’t being used as a keyboard input device.

So I created this file:

$ cat /etc/udev/rules.d/99-usb-knob.rules
ACTION=="add|change", KERNEL=="event[0-9]*", 
 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="572d",
 ENV{ID_INPUT_KEYBOARD}="1"

(That’s all on one line on my machine.) You’ll recognize the vendor and product ID from earlier, using lowercase for the hex this time. I added ID_INPUT_KEYBOARD to the list of attributes for this device.
Unplug the device, plug it back in, and hooray! I’m doing what I wanted to! When I turn the knob left, I go left. When I turn the knob right, I go right. When I press the knob, “m” shows up on the screen.

Now I just need to install an SDR program… and an SDR….


Finding out which disk is which on Ubuntu

June 9, 2019

My file server often has various disks swapped in and out. It can get confusing which /dev/sd? corresponds to which drive. While reading the man page of findfs, I stumbled on this:

The complete overview about filesystems and partitions you can get for example by:
  lsblk –fs
  partx –show
  blkid

These three things (along with judicious use of e2label and the other *label commands) is going to make my life a lot easier!


Fixing Brother printing on Ubuntu

March 15, 2019

Since moving to Ubuntu 16.04.3, printing to my Brother MFC-J650DW printer has been broken. I can print fine, but it’s always offset by a bit, never where it should be on the page.

Turns out this is a bug and there’s a workaround. So I don’t forget next time I set up printers:

lpadmin -p "Brother_MFC_J650DW" -o pdftops-renderer-default=pdftops


Let me know (mail me) when there’s an error

September 5, 2018

I’ve got a shell script where I’d like to know when an error happens. Typically when that happens, something gets written to stdout or stderr – and I’d like to see that. But when things are just peachy, I don’t want to be bothered.

Here’s an easy way to achieve that. At the beginning of my script, I have:

WEATHEROUT=`/bin/mktemp`
WEATHERERR=`/bin/mktemp`

(Did I mention this is a script for a weather station? Yep.)

Then in the body of the script, I have:

/usr/local/bin/do-the-thing > ${WEATHEROUT} 2> ${WEATHERERR}
/usr/local/bin/do-the-other-thing >> ${WEATHEROUT} 2>> ${WEATHERERR}

Finally, at the end of the script, there’s:

if [ -s ${WEATHERERR} -o -s ${WEATHEROUT} ]; then
   cat ${WEATHEROUT} ${WEATHERERR} | /usr/bin/mail -s "Weather command error" me@myaddr
fi

That’s all!


What’s up with mod_security and User-Agent? (406 Not Acceptable)

May 1, 2018

So… what’s the deal with mod_security and User-Agent? I tried to browse to HandheldRadio.net using Lynx, and was greeted with this 406 error:

                            Not Acceptable

   An appropriate representation of the requested resource / could not be
   found on this server.

   Additionally, a 406 Not Acceptable error was encountered while trying
   to use an ErrorDocument to handle the request.

A few searches and I discovered this was due to Apache mod_security.

I don’t get it. Why would you exclude based on User-Agent? That’s something that can be changed at will by any program that decides to be nefarious. This seems like security theatre rather than real security.

Even in the best case, this kind of “security” just turns into a red queen’s race to the bottom where everything will now lie about what it is because someone screwed up a config file somewhere.

And so I’ve started lying (in my .bashrc):

alias lynx='lynx -useragent="Mozilla/5.0 (X11; Ubuntu Lynx; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0"'

Damn, that’s stupid.


Setting a user and group for Samba drives

April 14, 2018

The last time I tried to set a user and password on my Samba drive, I ran into a strange problem: even though my credentials were correct, I was still using the user and group I was logged in as, rather than the one I’d stored with the Samba config.

Luckily, these days there’s an easy way around it in /etc/fstab:

//mysvr/music /music cifs uid=1000,gid=1000,credentials=/etc/samba/credentials/mysvr

 

Simply adding the uid= and gid= lines fixed up the problem for me.