Pairing a bluetooth Intsun/Terios T3 gamepad on Linux

These instructions are mostly for my later convenience but if you have an Intsun or Terios T3 bluetooth gamepad that you want to pair with Linux via the command line they might help you out.

These instructions assume you have a bluetooth dongle that is recognised by your kernel. I’ve had success with this one. These steps worked for me on Ubuntu 16.04 LTS.

  1. Install the following packages:
    $ sudo apt-get install bluez joystick
  2. Put the gamepad in bluetooth pairing mode by holding down the X and Home buttons simultaneously. The LED ring around the home button should now start blinking rapidly.
  3. Start the interactive command-line interface to the bluetooth stack bluetoothctl
    $ sudo bluetoothctl
    [NEW] Controller XX:XX:XX:XX:XX:XX live-0 [default]

    For readability I’ll put the typed commands in blue from here on.
  4. Next power on your bluetooth interface and make it discoverable (maybe not strictly necessary):
    [bluetooth]# power on
    Changing power on succeeded
    [bluetooth]# discoverable on
    Changing discoverable on succeeded
    [CHG] Controller XX:XX:XX:XX:XX:XX Discoverable: yes
  5. Register as the default agent:
    [bluetooth]# agent on
    Agent registered
    [bluetooth]# default-agent
    Default agent request successful
  6. Start scanning to look for discoverable devices:
    [bluetooth]# scan on
    Discovery started
    [CHG] Controller XX:XX:XX:XX:XX:XX Discovering: yes
  7. After a few seconds the devices command should list your gamepad:
    [bluetooth]# devices
    [NEW] Device YY:YY:YY:YY:YY:YY Bluetooth Gamepad
  8. It seems that PIN-less pairing requires that the device be trusted first:
    [bluetooth]# trust YY:YY:YY:YY:YY:YY
    [CHG] Device YY:YY:YY:YY:YY:YY Trusted: yes
    Changing YY:YY:YY:YY:YY:YY trust succeeded
  9. Try to pair with the gamepad:
    [bluetooth]# pair YY:YY:YY:YY:YY:YY
    Attempting to pair with YY:YY:YY:YY:YY:YY
    [CHG] Device YY:YY:YY:YY:YY:YY Connected: yes
    [CHG] Device YY:YY:YY:YY:YY:YY Modalias: usb:v1949p0402d011B
    [CHG] Device YY:YY:YY:YY:YY:YY UUIDs: 00001124-0000-1000-8000-00805f9b34fb
    [CHG] Device YY:YY:YY:YY:YY:YY UUIDs: 00001200-0000-1000-8000-00805f9b34fb
    [CHG] Device YY:YY:YY:YY:YY:YY Paired: yes
    Pairing successful
  10. Connect to the gamepad:
    [bluetooth]# connect YY:YY:YY:YY:YY:YY
    Attempting to connect to YY:YY:YY:YY:YY:YY
  11. Quit bluetoolctl:
    [bluetooth]# quit
    Agent unregistered
    [DEL] Controller XX:XX:XX:XX:XX:XX live-0 [default]

All being well the gamepad LEDs will now stop flashing and a single one will be illuminated.

You can test the gamepad using the jstest command:
jstest /dev/input/js0
(your device name may vary)

Virgin Media WiFi Android app on a rooted device

Virgin Media have a handy Android app which lets Virgin Media subscribers connect to their Virgin Media WiFi service. However they have, in their infinite wisdom, decided that they will not support running this app on rooted Android devices – which is entirely their prerogative.

As a longtime fan of rooted Android (I currently run LineageOS 14.1 on my HTC 10) I was disappointed by Virgin’s decision but decided to treat it as a learning opportunity. So, purely for academic / research purposes, is it possible to modify the Android APK such that it will run on a rooted handset? Yes, yes it is and it’s quite easy if you know what you’re doing.

Here’s how I went about my proof-of-concept:

  1. Install the Virgin Media WiFi app on your phone from the Play Store.
  2. Use ADB to pull the APK file from your device. For me this worked like this:
    adb pull /data/app/com.virginmedia.simplewifi-1
    pull: building file list...
    pull: /data/app/com.virginmedia.simplewifi-1/lib/arm64/libdevicescape-jni.so -> ./lib/arm64/libdevicescape-jni.so
    pull: /data/app/com.virginmedia.simplewifi-1/base.apk -> ./base.apk
    
  3. Use the fantastic apktool to decompile the base.apk:
    apktool d base.apk
    I: Using Apktool 2.2.2 on base.apk
    I: Loading resource table...
    I: Decoding AndroidManifest.xml with resources...
    I: Loading resource table from file: /home/simon/.local/share/apktool/framework/1.apk
    I: Regular manifest package...
    I: Decoding file-resources...
    I: Decoding values */* XMLs...
    I: Baksmaling classes.dex...
    I: Copying assets and libs...
    I: Copying unknown files...
    I: Copying original files...
  4. Now let’s start looking for the text in the toast notification it pops up to tell you it’s not going to run on a rooted device:
    grep -R "rooted" *
    res/values/public.xml:    <public type="string" name="alert_rooted_device" id="0x7f0800d1" />
    res/values/strings.xml:    <string name="alert_rooted_device">For security reasons you are not able to run this app on a rooted device</string>

    I’d take a reasonable guess that “alert_rooted_device” is the one we’re after. Let’s see if that id “0x7f0800d1” is referenced anywhere in the decompiled code:

    grep -Ri "7f0800d1" *
    res/values/public.xml:    <public type="string" name="alert_rooted_device" id="0x7f0800d1" />
    smali/com/studios/ocasta/prototype/vmwfsclient/ui/activities/StartActivity.smali:    const v0, 0x7f0800d1

    Aha! It looks like StartActivity.smali might be worth a closer look.

  5. So let’s take a look at the decompiled StartActivity.smali:
    StartActivity.smali
    Seems like it’s invoking com/studios/ocasta/prototype/vmwfsclient/g/i;->a() (line 283), putting the result into v0 (line 285) and then jumping to :cond_0 if v0 is equal to 0 (line 287). If v0 isn’t zero then it raises a Toast notification with the id of the “alert_rooted_device” string (0x7f0800d) (lines 289-297) and calls the “finish()” method (line 299).
    I think it’s a reasonable guess that lines 283-299 are responsible to detecting whether the device is rooted, displaying a toast notification to that effect and exiting.
    So what, if we were so inclined, could we do about it?
  6. Looks likely that if the device isn’t rooted then line 287:
    if-eqz v0, :cond_0

    will skip over the toast + exit stuff. So what if line 287 read simply:

    goto :cond_0

    instead? Skipping over the toast and exit regardless of the result of the method invoked at line 283.
    Let’s give it a go!

  7. Make whatever modifications you decide to and use apktool to rebuild the apk
    apktool b base -o com.virginmedia.simplewifi-rooted.apk
    I: Using Apktool 2.2.2
    I: Checking whether sources has changed...
    I: Smaling smali folder into classes.dex...
    I: Checking whether resources has changed...
    I: Building apk file...
    I: Copying unknown files/dir...

    This should produce an apk which you’ll need to zipalign and sign before you try installing it on a rooted Android device for educational purposes only.

So what did we learn here?

  1. It is often trivial to work around root detection on Android apps.
  2. The root detection in this case isn’t even necessary since the app will set-up WiFi auto sign-on for you, so you could:
    Remove root (temporary)
    Install the app & set-up auto sign-on
    Reinstate root and just don’t launch the app

Virtually unplug USB devices under Linux

A USB cable lies unplugged next to a laptop

My laptop has a built-in webcam which I don’t normally want enabled. The immediately obvious solution to this would be to blacklist the usb webcam kernel module (uvcvideo). However, I sometimes want to plug in an external USB webcam and use that. So how do you unplug/disable a built-in USB device under Linux?

After a bit of poking about it turns out to be possible to do via sysfs, but it’s a bit fiddly. So I wrote a script that I can run from rc.local to disable (or enable) a device with a specific vendor and product id.

Example usage:

$ lsusb
[...]
Bus 003 Device 005: ID 04ca:7034 Lite-On Technology Corp. 
[...]
usbEnableDisable.sh 04ca 7034 disable

Reject DOS line-endings at Git pre-commit

All *nix devs seethe with rage when DOS line-endings (CRLF) end up in your beautiful source code, right? If you use Git for your version control you’re in luck, use this local pre-commit hook to kick those CRLFs to the kerb before they can even make it into your local commit.

Install by copying the pre-commit file to the .git/hooks directory of your checkout. Ask your Windows using colleagues nicely to do the same.

GDB attach to a running process in batch mode

Ever needed to attach to a running process in a gdb batch mode script but didn’t know the process’ PID in advance? You can use GDB’s built-in Python interpreter to do the heavy lifting for you. Put the following in your batch-mode script:
python gdb.execute("attach " + os.popen('pgrep <process name>').read().rstrip())
<gdb commands go here>
detach
quit

Then run as follows:
gdb --batch -x <script>

Magic!

Removing a disk from a RAID 1 array

I’m in the process of building a new NAS server to replace our existing one which is getting a bit long in the tooth. As usual I’ve opted to install Ubuntu Server LTS as the OS. In my current NAS I’ve got the system partition RAID 1’d across all the drives, this means that should one fail I’ve still got 4 copies.

Setting up the new NAS I’ve put the system partition on a separate SSD from the main data drives. I’ve currently only got the one SSD but I wanted the option of RAID 1’ing the system drive for redundancy should I decide to get another SSD in future.

The Ubuntu installer will quite happily let you create a RAID 1 MD device with 2 disks but only select a single drive to belong to it. This would be the equivalent of the following mdadm command:

mdadm --create /dev/md2 --level=1 --raid-devices=2 /dev/loop1 missing

However, when you boot the OS will consider that array degraded:

mdadm -D /dev/md2
/dev/md2:
Version : 1.2
Creation Time : Fri Jan 16 21:24:44 2015
Raid Level : raid1
Array Size : 32704 (31.94 MiB 33.49 MB)
Used Dev Size : 32704 (31.94 MiB 33.49 MB)
Raid Devices : 2
Total Devices : 1
Persistence : Superblock is persistent

Update Time : Fri Jan 16 21:26:58 2015
State : clean, degraded
Active Devices : 1
Working Devices : 1
Failed Devices : 0
Spare Devices : 0

Name : lupin:2 (local to host lupin)
UUID : eccabf13:879f4196:1c47de11:3059e0b8
Events : 6

Number Major Minor RaidDevice State
0 7 1 0 active sync /dev/loop1
1 0 0 1 removed

It seems that you can’t remove the “missing” disk from the array even with

mdadm /dev/md2 -r detached

I eventually found the solution to this problem. It seems (counter-intuitively) that to remove a device from the array you have to “grow” that array as follows:

mdadm /dev/md2 --grow --force --raid-devices=1

This resulted in the missing / removed / non-existent device being removed from the array and it being considered clean:

mdadm -D /dev/md2
/dev/md2:
Version : 1.2
Creation Time : Fri Jan 16 21:24:44 2015
Raid Level : raid1
Array Size : 32704 (31.94 MiB 33.49 MB)
Used Dev Size : 32704 (31.94 MiB 33.49 MB)
Raid Devices : 1
Total Devices : 1
Persistence : Superblock is persistent

Update Time : Fri Jan 16 21:32:17 2015
State : clean
Active Devices : 1
Working Devices : 1
Failed Devices : 0
Spare Devices : 0

Name : lupin:2 (local to host lupin)
UUID : eccabf13:879f4196:1c47de11:3059e0b8
Events : 11

Number Major Minor RaidDevice State
0 7 1 0 active sync /dev/loop1

This took me a while to figure out so I hope this might help someone else out there who’s trying to achieve the same thing.

Dropbox on Ubuntu Server

I’ve been using the Dropbox Linux client on my server for a while now, it’s very handy for sync’ing files to & from my various systems.

I recently installed a new server and hit the problem that following the usual instructions:


cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -
~/.dropbox-dist/dropboxd

resulted in Dropbox not starting.

The problem (according to its crash log) was that it was trying to link against libgtk which I didn’t have installed on my (headless) Ubuntu Server 14.04 installation.

After a bit of messing around I realized that the problem was that I had enabled ForwardX11 on my PuTTY sessions and so dropboxd thought that I had an X11 session available. When I disabled X11 forwarding the problem went away & dropboxd ran as normal.

Unrar – Delete archive(s) after extraction

Due to lack of disk space on a server I needed a mechanism for automatically deleting RAR archives after their contents had been extracted. I couldn’t find any particularly neat way to do this with a shell script so I knocked up the following quick & dirty patch for unrar.

The patch applies cleanly to version 5.1.6 of the unrar source as follows:

wget 'http://www.rarlab.com/rar/unrarsrc-5.1.6.tar.gz'
tar -xvzf unrarsrc-5.1.6.tar.gz
cd unrar
wget 'http://simon.aldrich.eu/download/unrar/unrar-deleteOnExtract.patch'
patch -p1 < unrar-deleteOnExtract.patch
make

The compiled unrar binary will have the following extra option:

de  Delete archive(s) after extracting

Which you can use with the -e or -x commands e.g.:

unrar x -de test.part01.rar

Hopefully this might be useful to someone other than just me. Although, obviously, if extraction fails for any reason you will have deleted all the earlier volumes in the archive set. My suggestion would be to use the -t command to test your archive(s) first. I take no responsibility for any screw-ups you may cause yourself if you use this patch – caveat emptor!