From: Russ Dill <russ.dill@gmail.com>
To: Bastien Nocera <hadess@hadess.net>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: Bluetooth audio via pulse doesn't function unless I chant the magic incantations
Date: Wed, 11 Nov 2009 01:33:24 -0700 [thread overview]
Message-ID: <1257928404.1605.17.camel@russ-laptop> (raw)
In-Reply-To: <1257389371.23167.155.camel@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 6060 bytes --]
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 <hadess@hadess.net> 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;
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
prev parent reply other threads:[~2009-11-11 8:33 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-04 8:14 Bluetooth audio via pulse doesn't function unless I chant the magic incantations Russ Dill
2009-11-04 13:29 ` Bastien Nocera
2009-11-05 2:13 ` Russ Dill
2009-11-05 2:49 ` Bastien Nocera
2009-11-11 6:51 ` russ.dill
2009-11-11 6:58 ` russ.dill
2009-11-11 8:33 ` Russ Dill [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1257928404.1605.17.camel@russ-laptop \
--to=russ.dill@gmail.com \
--cc=hadess@hadess.net \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox