2009-11-04 08:14:02

by Russ Dill

[permalink] [raw]
Subject: Bluetooth audio via pulse doesn't function unless I chant the magic incantations

I have ubuntu lucid (its just karmic+2.6.32-rc5) and I can only get
pulseaudio to detect my Sony DR-BT50 headset if I send some dbus
commands:

addr=00:1a:80:67:63:2c
hci=$(dbus-send --print-reply --system --dest=org.bluez /
org.bluez.Manager.DefaultAdapter | tail -n 1 | cut -f 2 -d '"')
dev=$(dbus-send --print-reply --system --dest=org.bluez $hci
org.bluez.Adapter.FindDevice string:$addr | tail -n 1 | cut -f 2 -d
'"')
dbus-send --print-reply --system --dest=org.bluez $dev org.bluez.Audio.Connect

Additionally, the device shows up under the gnome bluetooth-properties
applet under "Known devices" with the gold star and the keys. The
connected plug doesn't appear until I exec the above commands.
Clicking the plug without the above commands does nothing.

bluez 4.51-0ubuntu2
libbluetooth3 4.51-0ubuntu2
pulseaudio 1:0.9.19-0ubuntu4
pulseaudio-module-bluetooth 1:0.9.19-0ubuntu4

hci0: Type: USB
BD Address: 00:16:CF:F7:04:20 ACL MTU: 1017:8 SCO MTU: 64:8
UP RUNNING PSCAN ISCAN
RX bytes:142026 acl:16520 sco:0 events:10116 errors:0
TX bytes:33958806 acl:39854 sco:0 commands:73 errors:0

(after above commands)

Connections:
< ACL 00:1A:80:67:63:2C handle 11 state 1 lm MASTER

How can I get my machine to automatically pair with this headset?


2009-11-11 08:33:24

by Russ Dill

[permalink] [raw]
Subject: Re: Bluetooth audio via pulse doesn't function unless I chant the magic incantations

On Thu, 2009-11-05 at 02:49 +0000, Bastien Nocera wrote:
> On Wed, 2009-11-04 at 19:13 -0700, Russ Dill wrote:
> > On Wed, Nov 4, 2009 at 6:29 AM, Bastien Nocera <[email protected]> wrote:
> > > On Wed, 2009-11-04 at 01:14 -0700, Russ Dill wrote:
> > >> I have ubuntu lucid (its just karmic+2.6.32-rc5) and I can only get
> > >> pulseaudio to detect my Sony DR-BT50 headset if I send some dbus
> > >> commands:
> > >>
> > >> addr=00:1a:80:67:63:2c
> > >> hci=$(dbus-send --print-reply --system --dest=org.bluez /
> > >> org.bluez.Manager.DefaultAdapter | tail -n 1 | cut -f 2 -d '"')
> > >> dev=$(dbus-send --print-reply --system --dest=org.bluez $hci
> > >> org.bluez.Adapter.FindDevice string:$addr | tail -n 1 | cut -f 2 -d
> > >> '"')
> > >> dbus-send --print-reply --system --dest=org.bluez $dev org.bluez.Audio.Connect
> > >>
> > >> Additionally, the device shows up under the gnome bluetooth-properties
> > >> applet under "Known devices" with the gold star and the keys. The
> > >> connected plug doesn't appear until I exec the above commands.
> > >> Clicking the plug without the above commands does nothing.
> > >
> > > You're using bluez-gnome (or possibly an old version of
> > > gnome-bluetooth). Make sure you use the latest version (2.28.3).
> > >
> > > Cheers
> > >
> >
> > Thank you for the awesomeness.
> >
> > Next question, I get events from keypresses on the headset via a
> > /dev/input/eventX file, but how do I do things with those events?
>
> If you use GNOME, the buttons should be forwarded to X11, and to the
> desktop. So the volume buttons should already work. Check the Sound and
> Keyboard shortcuts preferences.
>
> If you're using something else, I'm afraid I wouldn't know...
>
> Cheers
>

Looking at the spec, yes 0x7e is VENDOR_UNIQUE. It gives a operation
data field length of 5 as spelled out in the spec, it then gives a
company ID of 0x08 0x00 0x46 and then a vendor unique id of 0x00 0x01
for folder+ and 0x00 0x02 for folder -.

Ok, here is my quick and dirty patch for supporting VENDOR_UNIQUE.
audio/control.c doesn't seem to be the right place to store these
quirks. Can we somehow pass it as a uinput message and let some other
software stack layer that has policy files figure it out?

I also don't think KEY_PROG1 and KEY_PROG2 are the right choice, but I'm
not sure what is.

I also noticed that the spec includes info on how to tell the device
that audio is playing or audio is paused. I imagine if this was
implemented, my device would send the correct play/pause keycode.

The patch is mainly a request for comments. It is against bluez-4.51.

--- a/audio/control.c 2009-11-11 00:11:32.000000000 -0700
+++ b/audio/control.c 2009-11-11 01:29:22.000000000 -0700
@@ -193,6 +193,28 @@ static struct {
{ NULL }
};

+struct vendor_keys {
+ const char *name;
+ uint16_t vendorid;
+ uint16_t uinput;
+};
+
+#define COMPANYID_SONY 0x080046
+static struct vendor_keys sony_vendor_keys[] = {
+ { "FOLDER_NEXT", 0x0001, KEY_PROG1 },
+ { "FOLDER_PREV", 0x0002, KEY_PROG2 },
+ { NULL }
+};
+
+static struct {
+ const char *name;
+ uint32_t companyid;
+ struct vendor_keys *keys;
+} vendor_key_map[] = {
+ { "Sony Corporation", COMPANYID_SONY, sony_vendor_keys },
+ { NULL }
+};
+
static GSList *avctp_callbacks = NULL;

static sdp_record_t *avrcp_ct_record()
@@ -348,6 +370,8 @@ static void handle_panel_passthrough(str
{
const char *status;
int pressed, i;
+ const char *name = NULL;
+ uint16_t uinput = 0;

if (operand_count == 0)
return;
@@ -360,17 +384,61 @@ static void handle_panel_passthrough(str
pressed = 1;
}

- for (i = 0; key_map[i].name != NULL; i++) {
- if ((operands[0] & 0x7F) == key_map[i].avrcp) {
- debug("AVRCP: %s %s", key_map[i].name, status);
- send_key(control->uinput, key_map[i].uinput, pressed);
- break;
+ if ((operands[0] & 0x7f) == 0x7e) {
+ const struct vendor_keys *map = NULL;
+ const char *vendor_name = NULL;
+ uint32_t companyid = 0;
+ uint16_t vendorid = 0;
+
+ if (operand_count != 7) {
+ debug("AVRCP: Incorrect operand_count for "
+ "VENDOR_UNIQUE (%d) %s", operand_count, status);
+ return;
}
- }
+ companyid = (operands[2] << 16) | (operands[3] << 8) |
+ operands[4];
+ vendorid = (operands[5] << 8) | operands[6];
+ for (i = 0; vendor_key_map[i].name != NULL; i++) {
+ if (companyid == vendor_key_map[i].companyid) {
+ map = vendor_key_map[i].keys;
+ vendor_name = vendor_key_map[i].name;
+ break;
+ }
+ }
+ if (map == NULL) {
+ debug("AVRCP: Unknown companyid (0x%06x) for "
+ "VENDOR_UNIQUE (%d) %s", companyid,
+ operand_count, status);
+ return;
+ }
+ for (i = 0; map[i].name != NULL; i++) {
+ if (vendorid == map[i].vendorid) {
+ name = map[i].name;
+ uinput = map[i].uinput;
+ break;
+ }
+ }
+ if (name == NULL)
+ debug("AVRCP: unknown vendor button %s 0x%04X %s",
+ vendor_name, vendorid, status);

- if (key_map[i].name == NULL)
- debug("AVRCP: unknown button 0x%02X %s",
+ } else {
+ for (i = 0; key_map[i].name != NULL; i++) {
+ if ((operands[0] & 0x7F) == key_map[i].avrcp) {
+ name = key_map[i].name;
+ uinput = key_map[i].uinput;
+ break;
+ }
+ }
+ if (name == NULL)
+ debug("AVRCP: unknown button 0x%02X %s",
operands[0] & 0x7F, status);
+ }
+
+ if (name) {
+ debug("AVRCP: %s %s", name, status);
+ send_key(control->uinput, uinput, pressed);
+ }
}

static void avctp_disconnected(struct audio_device *dev)
@@ -585,6 +653,12 @@ static int uinput_create(char *name)

for (i = 0; key_map[i].name != NULL; i++)
ioctl(fd, UI_SET_KEYBIT, key_map[i].uinput);
+ for (i = 0; vendor_key_map[i].name != NULL; i++) {
+ const struct vendor_keys *map = vendor_key_map[i].keys;
+ int j;
+ for (j = 0; map[j].name != NULL; j++)
+ ioctl(fd, UI_SET_KEYBIT, map[j].uinput);
+ }

if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) {
err = errno;


Attachments:
signature.asc (197.00 B)
This is a digitally signed message part

2009-11-11 06:58:16

by Russ Dill

[permalink] [raw]
Subject: Re: Bluetooth audio via pulse doesn't function unless I chant the magic incantations


> The headset also has track select buttons, but those aren't making into
> uinput. I can see bluetoothd reading the event, but it never writes it out
> to uinput.
>

Sorry, I meant folder select buttons here. The track forward/back buttons already work


Attachments:
signature.asc (271.00 B)
OpenPGP digital signature

2009-11-11 06:51:43

by Russ Dill

[permalink] [raw]
Subject: Re: Bluetooth audio via pulse doesn't function unless I chant the magic incantations



On Wed, Nov 4, 2009 at 7:49 PM, Bastien Nocera <[email protected]> wrote:
> On Wed, 2009-11-04 at 19:13 -0700, Russ Dill wrote:
>> On Wed, Nov 4, 2009 at 6:29 AM, Bastien Nocera <[email protected]> wrote:
>> > On Wed, 2009-11-04 at 01:14 -0700, Russ Dill wrote:
>> >> I have ubuntu lucid (its just karmic+2.6.32-rc5) and I can only get
>> >> pulseaudio to detect my Sony DR-BT50 headset if I send some dbus
>> >> commands:
>> >>
>> >> addr=00:1a:80:67:63:2c
>> >> hci=$(dbus-send --print-reply --system --dest=org.bluez /
>> >> org.bluez.Manager.DefaultAdapter | tail -n 1 | cut -f 2 -d '"')
>> >> dev=$(dbus-send --print-reply --system --dest=org.bluez $hci
>> >> org.bluez.Adapter.FindDevice string:$addr | tail -n 1 | cut -f 2 -d
>> >> '"')
>> >> dbus-send --print-reply --system --dest=org.bluez $dev org.bluez.Audio.Connect
>> >>
>> >> Additionally, the device shows up under the gnome bluetooth-properties
>> >> applet under "Known devices" with the gold star and the keys. The
>> >> connected plug doesn't appear until I exec the above commands.
>> >> Clicking the plug without the above commands does nothing.
>> >
>> > You're using bluez-gnome (or possibly an old version of
>> > gnome-bluetooth). Make sure you use the latest version (2.28.3).
>> >
>> > Cheers
>> >
>>
>> Thank you for the awesomeness.
>>
>> Next question, I get events from keypresses on the headset via a
>> /dev/input/eventX file, but how do I do things with those events?
>
> If you use GNOME, the buttons should be forwarded to X11, and to the
> desktop. So the volume buttons should already work. Check the Sound and
> Keyboard shortcuts preferences.
>

I'm not sure why it wasn't working before, but it is working now. A couple of things though. It seems my headset tries to be too smart, it has a play/pause button and it alternates between play and pause. So if audio is playing, and I hit pause on the music player, the music pauses. Then I hit pause/play on my headphones and nothing happens because it sent a pause. So I need to press it again so that it will send play.

I'd assign them both to the gnome play functionality since it does both play and pause, but It doesn't seem possible to assign two keys for the same shortcut. Maybe its somehow possible to make a udev rules or somesuch file that does the reassignment of the actual keycode?

The headset also has track select buttons, but those aren't making into uinput. I can see bluetoothd reading the event, but it never writes it out to uinput.

track +
read(25, "0\21\16\0H|~\5\10\0F\0\1", 1024) = 13
write(25, "2\21\16\tH|~\5\10\0F\0\1", 13) = 13
poll([...])
read(25, "@\21\16\0H|\376\5\10\0F\0\1", 1024) = 13
write(25, "B\21\16\tH|\376\5\10\0F\0\1", 13) = 13

track -
read(25, "\240\21\16\0H|~\5\10\0F\0\2", 1024) = 13
write(25, "\242\21\16\tH|~\5\10\0F\0\2", 13) = 13
poll([...])
read(25, "\260\21\16\0H|\376\5\10\0F\0\2", 1024) = 13
write(25, "\262\21\16\tH|\376\5\10\0F\0\2", 13) = 13

where 25 is a socket

From looking at the source, it looks like the key (operand[0]) for both is 0x7e. The last byte changes between a 1 and a 2. Does 0x7e indicate some kind of vendor specific messsaging?

For comparison, here is a key that does make it:

read(25, "\340\21\16\0H|K\0", 1024) = 8
write(26, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\243\0\1\0\0\0", 24) = 24
write(26, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 24) = 24
write(25, "\342\21\16\tH|K\0", 8) = 8
poll([...])
read(25, "\360\21\16\0H|\313\0", 1024) = 8
write(26, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\243\0\0\0\0\0", 24) = 24
write(26, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 24) = 24
write(25, "\362\21\16\tH|\313\0", 8) = 8

26 is /dev/uinput


Attachments:
signature.asc (271.00 B)
OpenPGP digital signature

2009-11-05 02:49:30

by Bastien Nocera

[permalink] [raw]
Subject: Re: Bluetooth audio via pulse doesn't function unless I chant the magic incantations

On Wed, 2009-11-04 at 19:13 -0700, Russ Dill wrote:
> On Wed, Nov 4, 2009 at 6:29 AM, Bastien Nocera <[email protected]> wrote:
> > On Wed, 2009-11-04 at 01:14 -0700, Russ Dill wrote:
> >> I have ubuntu lucid (its just karmic+2.6.32-rc5) and I can only get
> >> pulseaudio to detect my Sony DR-BT50 headset if I send some dbus
> >> commands:
> >>
> >> addr=00:1a:80:67:63:2c
> >> hci=$(dbus-send --print-reply --system --dest=org.bluez /
> >> org.bluez.Manager.DefaultAdapter | tail -n 1 | cut -f 2 -d '"')
> >> dev=$(dbus-send --print-reply --system --dest=org.bluez $hci
> >> org.bluez.Adapter.FindDevice string:$addr | tail -n 1 | cut -f 2 -d
> >> '"')
> >> dbus-send --print-reply --system --dest=org.bluez $dev org.bluez.Audio.Connect
> >>
> >> Additionally, the device shows up under the gnome bluetooth-properties
> >> applet under "Known devices" with the gold star and the keys. The
> >> connected plug doesn't appear until I exec the above commands.
> >> Clicking the plug without the above commands does nothing.
> >
> > You're using bluez-gnome (or possibly an old version of
> > gnome-bluetooth). Make sure you use the latest version (2.28.3).
> >
> > Cheers
> >
>
> Thank you for the awesomeness.
>
> Next question, I get events from keypresses on the headset via a
> /dev/input/eventX file, but how do I do things with those events?

If you use GNOME, the buttons should be forwarded to X11, and to the
desktop. So the volume buttons should already work. Check the Sound and
Keyboard shortcuts preferences.

If you're using something else, I'm afraid I wouldn't know...

Cheers


2009-11-05 02:13:57

by Russ Dill

[permalink] [raw]
Subject: Re: Bluetooth audio via pulse doesn't function unless I chant the magic incantations

On Wed, Nov 4, 2009 at 6:29 AM, Bastien Nocera <[email protected]> wrote:
> On Wed, 2009-11-04 at 01:14 -0700, Russ Dill wrote:
>> I have ubuntu lucid (its just karmic+2.6.32-rc5) and I can only get
>> pulseaudio to detect my Sony DR-BT50 headset if I send some dbus
>> commands:
>>
>> addr=00:1a:80:67:63:2c
>> hci=$(dbus-send --print-reply --system --dest=org.bluez /
>> org.bluez.Manager.DefaultAdapter | tail -n 1 | cut -f 2 -d '"')
>> dev=$(dbus-send --print-reply --system --dest=org.bluez $hci
>> org.bluez.Adapter.FindDevice string:$addr | tail -n 1 | cut -f 2 -d
>> '"')
>> dbus-send --print-reply --system --dest=org.bluez $dev org.bluez.Audio.Connect
>>
>> Additionally, the device shows up under the gnome bluetooth-properties
>> applet under "Known devices" with the gold star and the keys. The
>> connected plug doesn't appear until I exec the above commands.
>> Clicking the plug without the above commands does nothing.
>
> You're using bluez-gnome (or possibly an old version of
> gnome-bluetooth). Make sure you use the latest version (2.28.3).
>
> Cheers
>

Thank you for the awesomeness.

Next question, I get events from keypresses on the headset via a
/dev/input/eventX file, but how do I do things with those events?

2009-11-04 13:29:29

by Bastien Nocera

[permalink] [raw]
Subject: Re: Bluetooth audio via pulse doesn't function unless I chant the magic incantations

On Wed, 2009-11-04 at 01:14 -0700, Russ Dill wrote:
> I have ubuntu lucid (its just karmic+2.6.32-rc5) and I can only get
> pulseaudio to detect my Sony DR-BT50 headset if I send some dbus
> commands:
>
> addr=00:1a:80:67:63:2c
> hci=$(dbus-send --print-reply --system --dest=org.bluez /
> org.bluez.Manager.DefaultAdapter | tail -n 1 | cut -f 2 -d '"')
> dev=$(dbus-send --print-reply --system --dest=org.bluez $hci
> org.bluez.Adapter.FindDevice string:$addr | tail -n 1 | cut -f 2 -d
> '"')
> dbus-send --print-reply --system --dest=org.bluez $dev org.bluez.Audio.Connect
>
> Additionally, the device shows up under the gnome bluetooth-properties
> applet under "Known devices" with the gold star and the keys. The
> connected plug doesn't appear until I exec the above commands.
> Clicking the plug without the above commands does nothing.

You're using bluez-gnome (or possibly an old version of
gnome-bluetooth). Make sure you use the latest version (2.28.3).

Cheers