Turning your Cubieboard/RaspberryPi into an A2DP capable media receiver

Few months ago I found out that there are a2dp media receivers out there, but the good ones that feature digital audio connectivity (TOSLINK or Electrical S/PDIF) are very expensive, so I decided to build one myself.

First I ordered a Bluetooth 4.0 USB dongle on Ebay – that was actually the longest part since I had to wait more than 2 weeks for it to arrive.

When the hardware is ready – we can move on to its configuration. The whole process is fairly simple if you know what you’re doing (it took me a while to debug why sink device wasn’t identified in PulseAudio 4.0).

Before we begin
We need to install the packages. I won’t get into too many details since this guide is kind of universal for all distros, but here’s what I installed on linaro:
apt-get install bluetooth bluez bluez-audio bluez-alsa:armhf bluez-tools bluez-utils pulseaudio pulseaudio-module-bluetooth pulseaudio-module-hal pulseaudio-module-udev pulseaudio-utils

Step 1: Set up bluetooth daemon
Herare are the contents of my /etc/bluetooth/audio.conf:

[General]
Enable=Source
Disable=Socket

[Headset]
HFP=false

[A2DP]
SBCSources=1
MPEG12Sources=0

We also need to modify adapter name to something reasonable by setting Name = MediCenter in [general] section of /etc/bluetooth/main.conf, and device class to 0x20041C to make it discoverable as an audio sync. After editing my /etc/bluetooth/main.conf looks like this:

[General]
Name = MediaCenter
Class = 0x20041C
DiscoverableTimeout = 0
PairableTimeout = 0
PageTimeout = 8192
AutoConnectTimeout = 60
InitiallyPowered = true
RememberPowered = true
ReverseServiceDiscovery = true
NameResolving = true
DebugKeys = false
EnableGatt = false

If your bluetooth dongle was connected to the system before you modified your bluetooth configuration files, you’ll have to also modify it’s profile in /var/lib/bluetooth/*/config. It should look like this:

name MediaCenter
pairable yes
class 0x20041C

After editing it make sure you restart bluetooth service by issuing a /etc/init.d/bluetooth restart

Step 2: configure bluetooth daemon to accept incoming connections
For this we need to create a custom script that will daemonize bluetooth agent on system startup. Mine looks like this (credits to instructables.com):

### BEGIN INIT INFO
# Provides: bluetooth-agent
# Required-Start: $remote_fs $syslog bluetooth pulseaudio
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Makes Bluetooth discoverable and connectable to 0000
# Description: Start Bluetooth-Agent at boot time.
### END INIT INFO
#! /bin/sh
# /etc/init.d/bluetooth-agent
USER=root
HOME=/root
export USER HOME
case "$1" in
start)
echo "setting bluetooth discoverable"
sudo hciconfig hci0 piscan
start-stop-daemon -c pulse -S -b -x /usr/bin/bluetooth-agent -- 0000
echo "bluetooth-agent startet pw: 0000"
;;
stop)
echo "Stopping bluetooth-agent"
start-stop-daemon -K -x /usr/bin/bluetooth-agent
;;
*)
echo "Usage: /etc/init.d/bluetooth-agent {start|stop}"
exit 1
;;
esac
exit 0

Once the script is installed in /etc/init.d/bluetooth-agent you need to make it executable an make sure it runs on startup:

chmod 775 /etc/init.d/bluetooth-agent
update-rc.d bluetooth-agent defaults
update-rc.d bluetooth-agent enable

Two things marked as bold in the script is the used under which bluetooth agent runs (pulse) and the pin used to connect to it (0000). Feel free to change the second to whatever you want.

Next, we need to add user pulse to bluetooth group to grant it control over your dongle:
usermod -a -G bluetooth pulse

For some of the agent will still fail to start complaining about dbus not allowing method calls. If you experience this problem, you need to change a policy group in /etc/dbus-1/system.d/bluetooth.conf. Find the the section and add the line in bold:

<!-- allow users of bluetooth group to communicate with hcid -->
<policy group="bluetooth">
<allow send_destination="org.bluez"/>
<allow send_type="method_call"/>
</policy>

Step 3: configure pulse audio
I am running a headless system so I had to run pulseaudio as a daemon. My daemon runs under user pulse (default) which after completing step 2 should be a member of bluetooth group. I’m sure you’ll find a guide out there on how to do that, so I will skip instructions to configure it.

On a non-realtime kernel my /etc/pulse/daemon.conf looks like this:

allow-module-loading = yes
high-priority = yes
nice-level = -11
realtime-scheduling = no
load-default-script-file = yes
default-script-file = /etc/pulse/default.pa
log-target = auto
log-level = notice
resample-method = speex-float-1
flat-volumes = no
default-fragments = 8
default-fragment-size-msec = 10
deferred-volume-safety-margin-usec = 1

If you don’t include default script then you’ll have to add the following lines to your system.pa:

### Automatically load driver modules for Bluetooth hardware
.ifexists module-bluetooth-policy.so
load-module module-bluetooth-policy
.endif

.ifexists module-bluetooth-discover.so
load-module module-bluetooth-discover
.endif

Note: depending on your os and pulseaudio version the above may be disabled in defaults.pa by default, so make sure you enable bluetooth-policy and bluetooth-discover modules. I also have the following lines at the en of my system.pa to enable pulseaudio accept incoming tcp and rtp connections and announce the available sinks over zeroconf for streaming over network:

# Make local subsistem available over TCP
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/16
# Also accept RTP traffic
load-module module-rtp-recv
# Publish to zeroconf
load-module module-zeroconf-publish

Final step: configure a loopback between a2dp input and the output of your choice on device connect
For that we’ll need an udev rule that will trigger a script once new input devices are connected. Mine looks like this:
cat /etc/udev/rules.d/99-input.rules

SUBSYSTEM=="input", GROUP="input", MODE="0660"
KERNEL=="input[0-9]*", RUN+="/usr/lib/udev/bluetooth"

It will run /usr/lib/udev/bluetooth every time new device is connected or disconnects.

Later you need to create /usr/lib/udev/bluetooth and make it executable:

chmod 754 /usr/lib/udev/bluetooth

Contents of mine are:

#!/bin/bash
AUDIOSINK="alsa_output.platform-sunxi-sndhdmi.0.analog-stereo"
echo "Executing bluetooth script...|$ACTION|" | logger

ACTION=$(expr “$ACTION” : “([a-zA-Z]+).*”)
if [ “$ACTION” = “add” ]
then
# Turn off BT discover mode before connecting existing BT device to audio
hciconfig hci0 noscan

# Set volume level to 100 percent
amixer set Master 100%

for dev in $(find /sys/devices/virtual/input/* -name input*)
do
if [ -f “$dev/name” ]
then
mac=$(cat “$dev/name” | sed ‘s/:/_/g’)
bluez_dev=bluez_source.$mac

sleep 1
cardid=`sudo -u pulse pactl list cards short | grep bluez_card | cut -f1`
echo “sudo -u pulse pactl set-card-profile $cardid a2dp_source” | logger
sudo -u pulse pactl set-card-profile $cardid a2dp_source 2>&1 | logger

sleep 3
CONFIRM=`sudo -u pulse pactl list short | grep $bluez_dev`
if [ ! -z “$CONFIRM” ]
then
echo “Setting bluez_source to: $bluez_dev” | logger
sudo -u pulse pactl load-module module-loopback source=”$bluez_dev” sink=”$AUDIOSINK” source_dont_move=”true” sink_input_properties=”media.role=music” 2>&1| logger
else
echo “Device $bluez_dev not found” | logger
fi
fi
done
fi

if [ “$ACTION” = “remove” ]
then
# Turn on bluetooth discovery if device disconnects
sudo hciconfig hci0 piscan
fi

The one linke you will have to change is the bold one. In my case I’m redirecting all incoming audio to hdmi stereo sink, your device name most probably be different so you’ll have to get it by running:
sudo -u pulse pactl list sinks short

Here’s my output:

0 alsa_output.platform-sunxi-codec.analog-stereo module-alsa-card.c s16le 2ch 44100Hz RUNNING
1 alsa_output.platform-sunxi-sndhdmi.0.analog-stereo module-alsa-card.c s16le 2ch 44100Hz RUNNING

Second column is what we need.

Troubleshooting:
Depending on your syslog configuration, logs may be written in different places. Most probably it’s /var/log/messages or /var/log/syslog. Try to connect a device and watch the logs as you connect. Make sure bluetoothd, bluetooth-agent and pulseaudio are running.

Feel free to comment here if you have issues.

XBMC on OUYA running debian

I’ve been playing around with debian for ouya recently – seems to be working fine: you need a device to load the kernel from (good use for my cubieboard or rpi?), otherwise it’s good. Hardware acceleration works, HDMI audio as well: so I thought I’d give it a try with XBMC. It works flawlessly on Android, but I want it running an environment I would have more control over. Also the key bindings are killing me.

Anyway, first attempt failed (took ~24 hrs to build) – I screwed up with the rules file a bit and built it with OpenGL support instead of OpenGL ES. Second try is compiling: expect it to be ready by tomorrow evening. If it works – it’s going to be first working XBMC on OUYA running linux.

Stay tuned!

Creative Clock

Google Authenticator PAM module for RHEL6

I thought I would give it a try to google authenticator pam module so I built it for RHEL6. You should theoretically be able to use it on any derivative tree including CentOS, Scientific Linux, and others.

Instructions:

# Configure my repo

wget -O /etc/yum.repos.d/chaos.repo http://yum.vadimgrinco.com/repo/rhel/chaos.repo

# Install google authenticator pam module and its dependencies

yum -y install libpam-google-authenticator

# Run the initial configuration of google authenticator and scan the QR code

google-authenticator

# Edit /etc/pam.d/sshd to enable google authenticator

sed -e "s/auth.*include.*password-auth/authtrequiredtpam_google_authenticator.son/" -i /etc/pam.d/sshd

Now it’s time to configure sshd for challange-response auth:

# disable plain password authentication over encrypted tunnel (default)

sed -e "s/PasswordAuthentication.*/PasswordAuthentication no/" -i /etc/ssh/sshd_config

# enable challenge-response authentication

sed -e "s/ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/" -i /etc/ssh/sshd_config

# enable pam support

sed -e "s/UsePAM.*/UsePAM yes/" -i /etc/ssh/sshd_config

Restart sshd and enjoy the new security feature of your server.

How to sniff the ether for 20$ (50-1100Mhz and 1250-2200Mhz)

1. Buy a Realtek RTL2832U with a Elonics E4000 receiver from ebay

2. Install gnuradio and its development package

3. Build RTL-SDR

4. Build latest SDR# from SVN (pre-built binaries didn’t work for me on Linux)

5. Enjoy

Optionally you can use DSD to decode P25 digital broadcasts

If you’re having troubles using RTL-SDR via USB in SDR# use the RTL-SDR / TCP module:

– launch rtl_tcp server by running ` rtl_tcp -a 0.0.0.0`

– Select RTL-SDR / TCP source in SDR#, click on configure and change the server ip address to the address of the machine rtl_tcp is running on (127.0.0.1 should do it if you’re running both client and server on the same host)

 

Broadcom CrystalHD driver, library and gstreamer plug-in for ubuntu 11.10

I have packaged the newer version of crystalhd kernel dkms, libcrystalhd3 and gstreamer plug-in crystalhd for ubuntu 11.10. Feel free to download it from here:

crystalhd-dkms_0.0~git20110715.fdd2f19-4.2_i386.deb
libcrystalhd3_0.0~git20110715.fdd2f19-4.2_i386.deb
gstreamer0.10-crystalhd_0.0~git20110715.fdd2f19-4.2_i386.deb

Debug package if you need it:

libcrystalhd-dev_0.0~git20110715.fdd2f19-4.2_i386.deb

TIP: there is also XBMC built with crystalhd support available in my repo.