Skip to Content

Selfie Button as a Presentation Clicker

How to configure a "Selfie Stick" bluetooth remote control as a remote control for a presentation.

Selfie Stick Button

A while ago I had the idea of using a “Selfie Stick” remote control for presentations. It is a Bluetooth device with two buttons. That’s plenty to step forward and back through your slides.

Selfie Stick Button
Remote control for operating iOS/Android camera

The problem that needs to be solved is to remap the buttons so the keys generated control the presentation.

It was actually 7 years ago that I spent £2 on the purchase of this device, but I only recently performed the R&D to get this working. This article describes how it was achieved, and should be generalisable to other similar bluetooth devices.

The following instructions used Debian 11 (Bullseye), but should also work with any distribution using SystemD’s Hardware Database and X.org server.

For the avoidance of doubt, I have never owned a selfie stick.

Pairing as input device

The first step is to pair the device with your computer. I used bluetoothctl (from the bluez package) to achieve this, but you could also use the GUI.

  1. Use the scan command to identify the MAC address of the device
  2. Use the pair command to pair with the device
  3. Use the trust command so it will connect automatically
$ bluetoothctl 
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller D0:DF:9A:B6:F0:30 Discovering: yes
[NEW] Device 12:30:00:20:76:42 AB Shutter 3
[bluetooth]# pair 12:30:00:20:76:42
Attempting to pair with 12:30:00:20:76:42
[CHG] Device 12:30:00:20:76:42 Connected: yes
[CHG] Device 12:30:00:20:76:42 Modalias: usb:v04E8p7021d011B
[CHG] Device 12:30:00:20:76:42 UUIDs: 00001124-0000-1000-8000-00805f9b34fb
[CHG] Device 12:30:00:20:76:42 UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device 12:30:00:20:76:42 ServicesResolved: yes
[CHG] Device 12:30:00:20:76:42 Paired: yes
Pairing successful
[CHG] Device 12:30:00:20:76:42 WakeAllowed: yes
[CHG] Device 12:30:00:20:76:42 ServicesResolved: no
[CHG] Device 12:30:00:20:76:42 Connected: no
[bluetooth]# trust 12:30:00:20:76:42
[CHG] Device 12:30:00:20:76:42 Trusted: yes
Changing 12:30:00:20:76:42 trust succeeded
[CHG] Device 12:30:00:20:76:42 RSSI: -55
[bluetooth]# 

Events

The device should now be connected, and will send events when the buttons are pressed. I found that the iOS button generated a “Volume Up” keypress, and the Android button generated an “Enter” keypress.

The next step is to identify the input devices, and the events that they send. For this you will need the xinput and evtest packages installed.

The command xinput list will show all input devices. You should see the inputs corresponding to the bluetooth device.

$ xinput list
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ AlpsPS/2 ALPS DualPoint TouchPad          id=13   [slave  pointer  (2)]
⎜   ↳ AlpsPS/2 ALPS DualPoint Stick             id=14   [slave  pointer  (2)]
⎜   ↳ AB Shutter 3 Mouse                        id=19   [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Power Button                              id=8    [slave  keyboard (3)]
    ↳ Sleep Button                              id=9    [slave  keyboard (3)]
    ↳ Laptop_Integrated_Webcam_FHD: I           id=10   [slave  keyboard (3)]
    ↳ Dell WMI hotkeys                          id=11   [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=12   [slave  keyboard (3)]
    ↳ ACPI Virtual Keyboard Device              id=15   [slave  keyboard (3)]
    ↳ AB Shutter 3 System Control               id=16   [slave  keyboard (3)]
    ↳ AB Shutter 3 Consumer Control             id=17   [slave  keyboard (3)]
    ↳ AB Shutter 3 Keyboard                     id=18   [slave  keyboard (3)]

I was surprised to see the device registered as 1 pointer device and 3 keyboard devices. More than is required for just 2 buttons!

The next step is to identify the scan codes sent by the buttons. The evtest command will first prompt for input to display events for.

$ sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:      AT Translated Set 2 keyboard
/dev/input/event1:      Lid Switch
/dev/input/event2:      Power Button
/dev/input/event3:      Sleep Button
/dev/input/event4:      Power Button
/dev/input/event5:      Video Bus
/dev/input/event6:      AlpsPS/2 ALPS DualPoint Stick
/dev/input/event7:      AlpsPS/2 ALPS DualPoint TouchPad
/dev/input/event8:      PC Speaker
/dev/input/event9:      Dell WMI hotkeys
/dev/input/event10:     Laptop_Integrated_Webcam_FHD: I
/dev/input/event11:     HDA Digital PCBeep
/dev/input/event12:     HDA Intel PCH Dock Mic
/dev/input/event13:     HDA Intel PCH Mic
/dev/input/event14:     HDA Intel PCH Dock Line Out
/dev/input/event15:     HDA Intel PCH Headphone
/dev/input/event16:     HDA Intel PCH HDMI/DP,pcm=3
/dev/input/event17:     HDA Intel PCH HDMI/DP,pcm=7
/dev/input/event18:     HDA Intel PCH HDMI/DP,pcm=8
/dev/input/event19:     ACPI Virtual Keyboard Device
/dev/input/event20:     AB Shutter 3 Mouse
/dev/input/event21:     AB Shutter 3 Keyboard
/dev/input/event22:     AB Shutter 3 Consumer Control
/dev/input/event23:     AB Shutter 3 System Control
Select the device event number [0-23]:

When you have selected the input device, evtest will display the events the device can generate, and enter a testing phase where it displays the events when they are generated If you know the device, then you can specify that as an argument instead of selecing from ths list).

Here is the output from the “AB Shutter 3 Consumer Control” when the iOS button is pressed

# evtest /dev/input/event22
Input driver version is 1.0.1
Input device ID: bus 0x5 vendor 0x4e8 product 0x7021 version 0x11b
Input device name: "AB Shutter 3 Consumer 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 116 (KEY_POWER)
    Event code 150 (KEY_WWW)
    Event code 152 (KEY_SCREENLOCK)
    Event code 161 (KEY_EJECTCD)
    Event code 163 (KEY_NEXTSONG)
    Event code 164 (KEY_PLAYPAUSE)
    Event code 165 (KEY_PREVIOUSSONG)
    Event code 172 (KEY_HOMEPAGE)
    Event code 217 (KEY_SEARCH)
    Event code 240 (KEY_UNKNOWN)
    Event code 581 (KEY_SCREENSAVER)
  Event type 3 (EV_ABS)
    Event code 40 (ABS_MISC)
      Value      0
      Min        0
      Max        1
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit)
Event: time 1638474453.119478, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1638474453.119478, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
Event: time 1638474453.119478, -------------- SYN_REPORT ------------
Event: time 1638474453.119547, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1638474453.119547, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0
Event: time 1638474453.119547, -------------- SYN_REPORT ------------

I found the Android button associated with the “Keyboard” input.

# evtest /dev/input/event21
Input driver version is 1.0.1
Input device ID: bus 0x5 vendor 0x4e8 product 0x7021 version 0x11b
Input device name: "AB Shutter 3 Keyboard"
[Supported events detail removed]
Testing ... (interrupt to exit)
Event: time 1638474488.591502, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1638474488.591502, type 1 (EV_KEY), code 28 (KEY_ENTER), value 1
Event: time 1638474488.591502, -------------- SYN_REPORT ------------
Event: time 1638474488.620523, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1638474488.620523, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1638474488.620523, -------------- SYN_REPORT ------------

There were no events generated by the “AB Shutter 3 Mouse” or “AB Shutter 3 System Control” inputs.

Change Mapping of Buttons

The details needed are the name of the input device, the scan code generated by the button (see MSC_SCAN above), and the name of the key event you would like instead. One way to identify the valid key names is to look for the KEY_* definitions in input-event-codes.h header file.

For my use I mapped c00e9 on “AB Shutter 3 Consumer Control” to be the right arrow (“next slide please”), and mapped 70028 on the “AB Shutter 3 Keyboard” to be the left arrow.

I created a hwdb file with the desired mapping.

# cat /etc/udev/hwdb.d/70-keyboard.hwdb
evdev:name:AB Shutter 3 Consumer Control:dmi:*
 KEYBOARD_KEY_c00e9=right

evdev:name:AB Shutter 3 Keyboard:dmi:dmi:*
 KEYBOARD_KEY_70028=left

To reload the configuration change to test

$ sudo systemd-hwdb update
$ sudo udevadm trigger -s input

Key Press Repeating

I had one problem after mapping the buttons. The buttons would tend to stick and then autorepeat. This could lead to presentations leaping ahead uncontrollably. I think this is a reflection on the price I paid for the device.

I’ve not found a way to disable the autorepeat for just this device, but I can use xset to disable it for just these two keys. This command has to be run after the device is paired.

I need to know the X keycode for the buttons. Use xinput with the ID of the input device (see previous output of xinput list) to show the keycode when the button is pressed.

$ xinput --test 17
key press   113
key release 113
^C
$ xinput --test 15
key press   114
key release 114
^C

To get the xset command run when the device is connected, I selected one of the input names, and the MAC address (in lower case) to trigger when it was added.

$ cat /etc/udev/rules.d/99-clicker.rules 
ACTION=="add" SUBSYSTEM=="input", \
    ATTRS{name}=="AB Shutter 3 System Control", \
    ATTRS{phys}=="d0:df:9a:b6:f0:30", \
    PROGRAM="/usr/bin/env XAUTHORITY=/var/run/lightdm/root/:0 DISPLAY=:0 /usr/bin/xset -r 113 -r 114"

Ubuntu with Wayland

I briefly looked into how this would work with Wayland on Ubuntu.

It looks like there are tools that will permit the querying of the events generated, but as one of the input devices was not detected, I didn’t proceed any further.

I did verify that using the hwdb configuration file created using this process did work (for the one button that was working).