2009-06-04 09:28:42

by Bastien Nocera

[permalink] [raw]
Subject: [PATCH] Add sixaxis cable-pairing plugin

Works for me, comments welcome.

It uses gudev. See http://blog.fubar.dk/?p=106

Cheers


Attachments:
0001-Add-sixaxis-cable-pairing-plugin.patch (14.27 kB)

2009-06-06 17:51:08

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

Hi Luiz,

> First I would like to know if splitting the current code of gudev into
> udev-glib and udev-gobject would be a good idea to begin with. By
> looking at connmand code it seems quite simple to integrate glib
> mainloop with udev so if we were not adding any API to udev-glib it
> seems like an unnecessary step, I heard that udev has some race
> conditions so perhaps we could add some very basic watch registration
> like we have done to libgdus. That way udev-object API doesn't have to
> change much just depend on udev-glib.
>
> On bluetoothd side, I would like to make udev code generic enough to
> detect any bluetooth device not only sixaxis so we can do different
> plugins to handle any device doing this cable association/cable
> pairing thing.

don't bother with udev-glib here. The native libudev integration with
mainloop is simple enough. If you need an example, look at ConnMan.

Regards

Marcel



2009-06-06 17:41:02

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

Hi,

First I would like to know if splitting the current code of gudev into
udev-glib and udev-gobject would be a good idea to begin with. By
looking at connmand code it seems quite simple to integrate glib
mainloop with udev so if we were not adding any API to udev-glib it
seems like an unnecessary step, I heard that udev has some race
conditions so perhaps we could add some very basic watch registration
like we have done to libgdus. That way udev-object API doesn't have to
change much just depend on udev-glib.

On bluetoothd side, I would like to make udev code generic enough to
detect any bluetooth device not only sixaxis so we can do different
plugins to handle any device doing this cable association/cable
pairing thing.

--=20
Luiz Augusto von Dentz
Engenheiro de Computa=E7=E3o

2009-06-05 15:06:17

by Bastien Nocera

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

On Fri, 2009-06-05 at 16:56 +0200, Marcel Holtmann wrote:
>
> > > On that point, you haven't merged the Socket fix upstream
> >
> > It's not upstreamable, see the RH bugzilla. It depends on a kernel
> patch
> > that can't go upstream.
>
> Which bug is it.

It's listed in the spec file, in the same directory you found that
patch:
https://bugzilla.redhat.com/show_bug.cgi?id=498756

> What is missing and why haven't I seen that kernel
> patch at least send to the mailing list for review.

It's a patch to serial core, not Bluetooth, and there's a 3-year old
discussion on LKML, amongst other things.

2009-06-05 14:56:15

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

Hi Bastien,

> > > You can keep personal attacks out of that. I think I've shown enough
> > > patience trying to get this functionality into bluez proper.
> >
> > This is not personal. I am keeping a watch on the dependencies of
> > BlueZ
> > and I don't see any need for adding GObject to the mix for the SixAxis
> > support. Feel free to convince me that GObject based gudev is really
> > necessary for this. Until then I declare this bloat.
>
> No, it's not absolutely necessary, but somebody has to reinvent the
> wheel, and I'm not happy spending time doing that.
>
> > Please remember that BlueZ will run on embedded devices with limited
> > memory and space requirements. You might argue that these devices
> > don't
> > need SixAxis support, but I prefer to keep that option.
>
> Yes. And if such uses exist, I'm sure they'd be happy putting some
> effort into bluez and do the port from gudev to libudev themselves.
>
> > > I won't be updating this patch, but Luiz showed interested. My patch
> > > will show up in the Fedora packages shortly.
> >
> > That is your choice. Personally I really dislike if distros just go
> > against upstream and start merging stuff, because it takes more effort
> > to get it into upstream first.
>
> All my patches are sent upstream before they go into the packages, and I
> think I put quite a bit of work into this. But at the end of the day, I
> only have so much time, and rewriting bits of code because the upstream
> doesn't like GObject isn't what I call a good use of my time. So I'm
> leaving it to somebody else to go the last mile because I can't be
> bothered.

fair enough and if Luiz takes care of this I am more than happy either
way.

> > On that point, you haven't merged the Socket fix upstream
>
> It's not upstreamable, see the RH bugzilla. It depends on a kernel patch
> that can't go upstream.

Which bug is it. What is missing and why haven't I seen that kernel
patch at least send to the mailing list for review.

> > and also the
> > Wacom and UTF-8 fix could be send upstream.
>
> They already have, and you commented on them. I still believe the UTF-8
> one could be merged as-is, but I don't have a good answer for the Wacom
> one, which would need more investigation.

The UTF-8 might go in as is. As I said, Johan could review these and
merge them as good as I can. So feel free to bug him about it.

Regards

Marcel



2009-06-05 14:48:20

by Bastien Nocera

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

On Fri, 2009-06-05 at 16:15 +0200, Marcel Holtmann wrote:
>
> > You can keep personal attacks out of that. I think I've shown enough
> > patience trying to get this functionality into bluez proper.
>
> This is not personal. I am keeping a watch on the dependencies of
> BlueZ
> and I don't see any need for adding GObject to the mix for the SixAxis
> support. Feel free to convince me that GObject based gudev is really
> necessary for this. Until then I declare this bloat.

No, it's not absolutely necessary, but somebody has to reinvent the
wheel, and I'm not happy spending time doing that.

> Please remember that BlueZ will run on embedded devices with limited
> memory and space requirements. You might argue that these devices
> don't
> need SixAxis support, but I prefer to keep that option.

Yes. And if such uses exist, I'm sure they'd be happy putting some
effort into bluez and do the port from gudev to libudev themselves.

> > I won't be updating this patch, but Luiz showed interested. My patch
> > will show up in the Fedora packages shortly.
>
> That is your choice. Personally I really dislike if distros just go
> against upstream and start merging stuff, because it takes more effort
> to get it into upstream first.

All my patches are sent upstream before they go into the packages, and I
think I put quite a bit of work into this. But at the end of the day, I
only have so much time, and rewriting bits of code because the upstream
doesn't like GObject isn't what I call a good use of my time. So I'm
leaving it to somebody else to go the last mile because I can't be
bothered.

> On that point, you haven't merged the Socket fix upstream

It's not upstreamable, see the RH bugzilla. It depends on a kernel patch
that can't go upstream.

> and also the
> Wacom and UTF-8 fix could be send upstream.

They already have, and you commented on them. I still believe the UTF-8
one could be merged as-is, but I don't have a good answer for the Wacom
one, which would need more investigation.

> I know you send some version
> of these at least once or twice, but besides me also Johan could merge
> these patches.

Cheers

2009-06-05 14:15:33

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

Hi Bastien,

> > > > > Works for me, comments welcome.
> > > > >
> > > > > It uses gudev. See http://blog.fubar.dk/?p=106
> > > >
> > > > no way. Please use just plain libudev and spare use the GObject
> > > > overhead. I have used libudev before and it is just fine. Not that I
> > > > have actually looked at your patch at all.
> > >
> > > GObject overhead? Did you intend on building sixaxis support into a 5
> > > year old phone that it would actually matter?
> >
> > as I said, I am not adding a dependency on a GObject based library to
> > it. We wanna be able to replace GLib with eglib or similar if we have
> > to. Doing this for GObject based libraries is a pain in the ass. It is
> > just bloat.
>
> Which is exactly why the cable pairing stuff is implemented as a plugin.
> You don't have to care about what's in it, or what its dependencies are
> if you don't ship the plugin.

then make it an external plugin in its own repository, but I am not
merging code that depends on anything GObject if it is just pointless
dependency and bloat.

> > > Anyway, that'll go way down my list of things to do, along with porting
> > > the rest of the apps to libusb1, which I guess will be a problem as
> > > well.
> >
> > My biggest problem with libusb1 is that not all distros have it right
> > now. However that might change in 2 or 3 month. So it should become
> > easier.
>
> That's not what the mail archives or IRC will tell me. Your problem was
> that this would make bluez depend on 2 different libusb versions, which
> you didn't want. That hasn't changed.

My answer might be misleading here. My view on this one hasn't changed.
I want either libusb0 or libusb1. However libusb1 becomes only an option
when all major distros did a refresh and have it available. So meaning
BlueZ will be ported over to libusb1 completely at some point. The point
is closer now than 6 month ago.

> > > gudev lives in udev-extras, and udev-extras will most likely be merged
> > > into udev itself. And it saves me from reinventing the wheel, and doing
> > > my own mainloop integration (etc.).
> >
> > The whole point of udev and udev-extras is to keep the dependency chain
> > small. So I don't think it gets merged.
> >
> > The GLib mainloop integration for libudev is really simple. So that is
> > not an excuse for being lazy and dragging GObject into the mix.
>
> You can keep personal attacks out of that. I think I've shown enough
> patience trying to get this functionality into bluez proper.

This is not personal. I am keeping a watch on the dependencies of BlueZ
and I don't see any need for adding GObject to the mix for the SixAxis
support. Feel free to convince me that GObject based gudev is really
necessary for this. Until then I declare this bloat.

Please remember that BlueZ will run on embedded devices with limited
memory and space requirements. You might argue that these devices don't
need SixAxis support, but I prefer to keep that option.

> I won't be updating this patch, but Luiz showed interested. My patch
> will show up in the Fedora packages shortly.

That is your choice. Personally I really dislike if distros just go
against upstream and start merging stuff, because it takes more effort
to get it into upstream first.

On that point, you haven't merged the Socket fix upstream and also the
Wacom and UTF-8 fix could be send upstream. I know you send some version
of these at least once or twice, but besides me also Johan could merge
these patches.

Regards

Marcel



2009-06-05 13:52:54

by Bastien Nocera

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

On Fri, 2009-06-05 at 15:06 +0200, Marcel Holtmann wrote:
> Hi Bastien,
>
> > > > Works for me, comments welcome.
> > > >
> > > > It uses gudev. See http://blog.fubar.dk/?p=106
> > >
> > > no way. Please use just plain libudev and spare use the GObject
> > > overhead. I have used libudev before and it is just fine. Not that I
> > > have actually looked at your patch at all.
> >
> > GObject overhead? Did you intend on building sixaxis support into a 5
> > year old phone that it would actually matter?
>
> as I said, I am not adding a dependency on a GObject based library to
> it. We wanna be able to replace GLib with eglib or similar if we have
> to. Doing this for GObject based libraries is a pain in the ass. It is
> just bloat.

Which is exactly why the cable pairing stuff is implemented as a plugin.
You don't have to care about what's in it, or what its dependencies are
if you don't ship the plugin.

> > Anyway, that'll go way down my list of things to do, along with porting
> > the rest of the apps to libusb1, which I guess will be a problem as
> > well.
>
> My biggest problem with libusb1 is that not all distros have it right
> now. However that might change in 2 or 3 month. So it should become
> easier.

That's not what the mail archives or IRC will tell me. Your problem was
that this would make bluez depend on 2 different libusb versions, which
you didn't want. That hasn't changed.

> > gudev lives in udev-extras, and udev-extras will most likely be merged
> > into udev itself. And it saves me from reinventing the wheel, and doing
> > my own mainloop integration (etc.).
>
> The whole point of udev and udev-extras is to keep the dependency chain
> small. So I don't think it gets merged.
>
> The GLib mainloop integration for libudev is really simple. So that is
> not an excuse for being lazy and dragging GObject into the mix.

You can keep personal attacks out of that. I think I've shown enough
patience trying to get this functionality into bluez proper.

I won't be updating this patch, but Luiz showed interested. My patch
will show up in the Fedora packages shortly.

Cheers

2009-06-05 13:06:31

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

Hi Bastien,

> > > Works for me, comments welcome.
> > >
> > > It uses gudev. See http://blog.fubar.dk/?p=106
> >
> > no way. Please use just plain libudev and spare use the GObject
> > overhead. I have used libudev before and it is just fine. Not that I
> > have actually looked at your patch at all.
>
> GObject overhead? Did you intend on building sixaxis support into a 5
> year old phone that it would actually matter?

as I said, I am not adding a dependency on a GObject based library to
it. We wanna be able to replace GLib with eglib or similar if we have
to. Doing this for GObject based libraries is a pain in the ass. It is
just bloat.

> Anyway, that'll go way down my list of things to do, along with porting
> the rest of the apps to libusb1, which I guess will be a problem as
> well.

My biggest problem with libusb1 is that not all distros have it right
now. However that might change in 2 or 3 month. So it should become
easier.

> gudev lives in udev-extras, and udev-extras will most likely be merged
> into udev itself. And it saves me from reinventing the wheel, and doing
> my own mainloop integration (etc.).

The whole point of udev and udev-extras is to keep the dependency chain
small. So I don't think it gets merged.

The GLib mainloop integration for libudev is really simple. So that is
not an excuse for being lazy and dragging GObject into the mix.

Regards

Marcel



2009-06-05 10:42:40

by Bastien Nocera

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

On Thu, 2009-06-04 at 20:13 +0200, Marcel Holtmann wrote:
> Hi Bastien,
>
> > Works for me, comments welcome.
> >
> > It uses gudev. See http://blog.fubar.dk/?p=106
>
> no way. Please use just plain libudev and spare use the GObject
> overhead. I have used libudev before and it is just fine. Not that I
> have actually looked at your patch at all.

GObject overhead? Did you intend on building sixaxis support into a 5
year old phone that it would actually matter?

Anyway, that'll go way down my list of things to do, along with porting
the rest of the apps to libusb1, which I guess will be a problem as
well.

gudev lives in udev-extras, and udev-extras will most likely be merged
into udev itself. And it saves me from reinventing the wheel, and doing
my own mainloop integration (etc.).

2009-06-04 18:13:59

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

Hi Bastien,

> Works for me, comments welcome.
>
> It uses gudev. See http://blog.fubar.dk/?p=106

no way. Please use just plain libudev and spare use the GObject
overhead. I have used libudev before and it is just fine. Not that I
have actually looked at your patch at all.

Regards

Marcel



2009-10-11 09:40:54

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Add sixaxis cable-pairing plugin

Hi Bastien,

> Implement the old "sixpair" using libudev and libusb-1.0.
>
> When a Sixaxis device is plugged in, events are filtered, and
> the device is selected, poked around to set the default Bluetooth
> address, and added to the database of the current default adapter.
> ---
> Makefile.am | 9 +-
> acinclude.m4 | 16 +++
> configure.ac | 1 +
> plugins/cable.c | 384
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 408 insertions(+), 2 deletions(-)
> create mode 100644 plugins/cable.c
>
> diff --git a/Makefile.am b/Makefile.am
> index c8337d6..e5eccdf 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -162,6 +162,11 @@ builtin_modules += service
> builtin_sources += plugins/service.c
> endif
>
> +if CABLE
> +builtin_modules += cable
> +builtin_sources += plugins/cable.c
> +endif
> +

since it is not really a generic cable pairing. I prefer that we just
call this SIXPAIR and sixpair.c

> builtin_modules += hciops
> builtin_sources += plugins/hciops.c
>
> @@ -192,7 +197,7 @@ src_bluetoothd_SOURCES = $(gdbus_sources)
> $(builtin_sources) \
> src/dbus-common.c src/dbus-common.h \
> src/dbus-hci.h src/dbus-hci.c
> src_bluetoothd_LDADD = lib/libbluetooth.la @GLIB_LIBS@ @DBUS_LIBS@ \
> - @CAPNG_LIBS@
> -ldl
> + @CAPNG_LIBS@
> @CABLE_LIBS@ -ldl
> src_bluetoothd_LDFLAGS = -Wl,--export-dynamic \
> -Wl,--version-script=src/bluetooth.ver
> src_bluetoothd_DEPENDENCIES = src/bluetooth.ver lib/libbluetooth.la
> @@ -305,7 +310,7 @@ EXTRA_DIST += doc/manager-api.txt \
>
> AM_YFLAGS = -d
>
> -AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ \
> +AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ @CABLE_CFLAGS@
> \
> -DBLUETOOTH_PLUGIN_BUILTIN -DPLUGINDIR=
> \""$(plugindir)"\"

This needs changing. I wanna have a separate udev and libusb1 check.
However I can do that for you in case there are problems.

> INCLUDES = -I$(builddir)/lib -I$(builddir)/src -I$(srcdir)/src \
> diff --git a/acinclude.m4 b/acinclude.m4
> index e7d1c32..10e5241 100644
> --- a/acinclude.m4
> +++ b/acinclude.m4
> @@ -142,6 +142,12 @@ AC_DEFUN([AC_PATH_USB], [
> [Define to 1 if you need the
> usb_interrupt_read() function.]))
> ])
>
> +AC_DEFUN([AC_PATH_CABLE], [
> + PKG_CHECK_MODULES(CABLE, libudev libusb-1.0, cable_found=yes,
> cable_found=no)
> + AC_SUBST(CABLE_CFLAGS)
> + AC_SUBST(CABLE_LIBS)
> +])
> +
> AC_DEFUN([AC_PATH_NETLINK], [
> PKG_CHECK_MODULES(NETLINK, libnl-1, netlink_found=yes,
> netlink_found=no)
> AC_SUBST(NETLINK_CFLAGS)
> @@ -170,6 +176,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
> netlink_enable=no
> hal_enable=${hal_found}
> usb_enable=${usb_found}
> + cable_enable=${cable_found}
> alsa_enable=${alsa_found}
> gstreamer_enable=${gstreamer_found}
> audio_enable=yes
> @@ -239,6 +246,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
> usb_enable=${enableval}
> ])
>
> + AC_ARG_ENABLE(cable, AC_HELP_STRING([--enable-cable], [enable
> DeviceKit support]), [
> + cable_enable=${enableval}
> + ])
> +
> AC_ARG_ENABLE(netlink, AC_HELP_STRING([--enable-netlink],
> [enable NETLINK support]), [
> netlink_enable=${enableval}
> ])
> @@ -326,6 +337,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
> AC_DEFINE(HAVE_CAPNG, 1, [Define to 1 if you have
> capabilities library.])
> fi
>
> + if (test "${cable_enable}" = "yes" && test "${cable_found}" =
> "yes"); then
> + AC_DEFINE(HAVE_CABLE, 1, [Define to 1 if you have
> libcable.])
> + fi
> +
> AM_CONDITIONAL(SNDFILE, test "${sndfile_enable}" = "yes" &&
> test "${sndfile_found}" = "yes")
> AM_CONDITIONAL(NETLINK, test "${netlink_enable}" = "yes" &&
> test "${netlink_found}" = "yes")
> AM_CONDITIONAL(USB, test "${usb_enable}" = "yes" && test
> "${usb_found}" = "yes")
> @@ -350,4 +365,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [
> AM_CONDITIONAL(DFUTOOL, test "${dfutool_enable}" = "yes" &&
> test "${usb_found}" = "yes")
> AM_CONDITIONAL(UDEVRULES, test "${udevrules_enable}" = "yes")
> AM_CONDITIONAL(CONFIGFILES, test "${configfiles_enable}" =
> "yes")
> + AM_CONDITIONAL(CABLE, test "${cable_enable}" = "yes" && test
> "${cable_found}" = "yes")
> ])
> diff --git a/configure.ac b/configure.ac
> index b93cca0..5df134f 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -40,6 +40,7 @@ AC_PATH_GLIB
> AC_PATH_ALSA
> AC_PATH_GSTREAMER
> AC_PATH_USB
> +AC_PATH_CABLE
> AC_PATH_NETLINK
> AC_PATH_SNDFILE
> AC_PATH_CAPNG
> diff --git a/plugins/cable.c b/plugins/cable.c
> new file mode 100644
> index 0000000..0b7cc7a
> --- /dev/null
> +++ b/plugins/cable.c
> @@ -0,0 +1,384 @@
> +/*
> + *
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2009 Bastien Nocera <[email protected]>
> + *
> + *
> + * This program is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License as published
> by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> 02110-1301 USA
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include <glib.h>
> +#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE 1
> +#include <libudev.h>
> +#include <dbus/dbus.h>
> +#include <bluetooth/bluetooth.h>
> +#include <bluetooth/sdp.h>
> +#include <libusb.h>
> +
> +#include "plugin.h"
> +#include "logging.h"
> +
> +#include "manager.h"
> +#include "adapter.h"
> +#include "device.h"
> +
> +#include "storage.h"
> +#include "sdp_lib.h"
> +
> +/* Vendor and product ID for the Sixaxis PS3 controller */
> +#define VENDOR 0x054c
> +#define PRODUCT 0x0268
> +#define SIXAXIS_PNP_RECORD
> "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800"
> +#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
> +
> +static struct btd_device *create_cable_association(DBusConnection
> *conn,
> + struct btd_adapter
> *adapter,
> + const char *name,
> + const char
> *address,
> + guint32 vendor_id,
> + guint32
> product_id,
> + const char
> *pnp_record)
> +{
> + sdp_record_t *rec;
> + struct btd_device *device;
> + bdaddr_t src, dst;
> + char srcaddr[18];
> +
> + device = adapter_find_device(adapter, address);
> + if (device == NULL)
> + device = adapter_create_device(conn, adapter,
> address);
> + if (device != NULL) {
> + device_set_temporary(device, FALSE);
> + device_set_name(device, name);
> + }
> +
> + str2ba(address, &dst);
> + adapter_get_address(adapter, &src);
> + ba2str(&src, srcaddr);
> +
> + write_device_name(&dst, &src, (char *) name);
> +
> + /* Store the device's SDP record */
> + rec = record_from_string(pnp_record);
> + store_record(srcaddr, address, rec);
> + sdp_record_free(rec);
> + /* Set the device id */
> + store_device_id(srcaddr, address, 0xffff, vendor_id,
> product_id, 0);
> + /* Don't write a profile, it will be updated when the device
> connects */
> +
> + write_trust(srcaddr, address, "[all]", TRUE);
> +
> + return device;
> +}
> +
> +static char *get_bdaddr(libusb_device_handle *devh, int itfnum)
> +{
> + unsigned char msg[17];
> + char *address;
> + int res;
> +
> + res = libusb_control_transfer(devh,
> + LIBUSB_ENDPOINT_IN |
> LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
> + 0x01, 0x03f2, itfnum,
> + (void*) msg, sizeof(msg),
> + 5000);
> +
> + if (res < 0) {
> + debug("Getting the device Bluetooth address failed");
> + return NULL;
> + }
> +
> + address = g_strdup_printf("%02X:%02X:%02X:%02X:%02X:%02X",
> + msg[4], msg[5], msg[6], msg[7],
> msg[8], msg[9]);
> +
> + debug("Device Bluetooth address: %s\n", address);
> +
> + return address;
> +}
> +
> +static gboolean set_master_bdaddr(libusb_device_handle *devh, int
> itfnum, char *host)
> +{
> + unsigned char msg[8];
> + int mac[6];
> + int res;
> +
> + if (sscanf(host, "%X:%X:%X:%X:%X:%X",
> + &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) !=
> 6) {
> + return FALSE;
> + }
> +
> + msg[0] = 0x01;
> + msg[1] = 0x00;
> + msg[2] = mac[0];
> + msg[3] = mac[1];
> + msg[4] = mac[2];
> + msg[5] = mac[3];
> + msg[6] = mac[4];
> + msg[7] = mac[5];
> +
> + res = libusb_control_transfer(devh,
> + LIBUSB_ENDPOINT_OUT |
> LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
> + 0x09, 0x03f5, itfnum,
> + (void*) msg, sizeof(msg),
> + 5000);
> +
> + if (res < 0) {
> + debug("Setting the master Bluetooth address failed");
> + return FALSE;
> + }
> +
> + return TRUE;
> +}

These are all blocking functions. That worries me a little bit in case
we have weird timeouts. I know that libusb1 supports async operation. Is
it possible to use that?

> +static void handle_usb_device(struct btd_adapter *adapter,
> + libusb_device *dev,
> + struct libusb_config_descriptor *cfg,
> + int itfnum,
> + const struct libusb_interface_descriptor
> *alt)
> +{
> + DBusConnection *conn;
> + libusb_device_handle *devh;
> + char *device_bdaddr;
> + char adapter_bdaddr[18];
> + struct btd_device *device;
> + bdaddr_t dst;
> +
> + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
> + if (conn == NULL) {
> + debug("Failed to get on the bus");
> + return;
> + }
> +
> + if (libusb_open(dev, &devh) < 0) {
> + debug("Can't open device");
> + goto bail;
> + }
> + libusb_detach_kernel_driver(devh, itfnum);
> +
> + if (libusb_claim_interface(devh, itfnum) < 0) {
> + debug("Can't claim interface %d", itfnum);
> + goto bail;
> + }
> +
> + device_bdaddr = get_bdaddr(devh, itfnum);
> + if (device_bdaddr == NULL) {
> + debug("Failed to get the Bluetooth address from the
> device");
> + goto bail;
> + }
> +
> + device = create_cable_association(conn,
> + adapter,
> + "PLAYSTATION(R)3
> Controller",
> + device_bdaddr,
> + VENDOR, PRODUCT,
> SIXAXIS_PNP_RECORD);
> + btd_device_add_uuid(device, HID_UUID);
> +
> + adapter_get_address(adapter, &dst);
> + ba2str(&dst, adapter_bdaddr);
> + debug("Adapter bdaddr %s", adapter_bdaddr);
> +
> + if (set_master_bdaddr(devh, itfnum, adapter_bdaddr) == FALSE)
> {
> + debug("Failed to set the master Bluetooth address");
> + goto bail;
> + }
> +
> +bail:
> + dbus_connection_unref(conn);
> + g_free(device_bdaddr);
> + libusb_release_interface(devh, itfnum);
> + /* We ignore errors from the reattach, as there's nothing we
> + * can do about it */
> + libusb_attach_kernel_driver(devh, itfnum);
> + if (devh != NULL)
> + libusb_close(devh);
> +}

It has been a long time I looked through this stuff. So does the
controller user USB control messages or are they just plain HID message.
If HID, then I would prefer if we use hidraw and don't have to detach
the kernel driver.

> +
> +static void handle_device_plug(struct udev_device *udevice)
> +{
> + struct btd_adapter *adapter;
> + int adapter_id;
> + guint i;
> +
> + libusb_device **list, *usbdev;
> + ssize_t num_devices;
> + struct libusb_device_descriptor desc;
> + guint8 j;
> +
> + if (g_strcmp0(udev_device_get_property_value(udevice,
> "ID_SERIAL"),
> + "Sony_PLAYSTATION_R_3_Controller") != 0)
> + return;
> + /* Don't look at events with an associated driver */
> + if (udev_device_get_property_value(udevice, "ID_USB_DRIVER") !
> = NULL)
> + return;
> +
> + debug("Found Sixaxis device");
> +
> + /* Look for the default adapter */
> + adapter_id = manager_get_default_adapter();
> + if (adapter_id == -1) {
> + debug("No adapters, exiting");
> + return;
> + }
> + adapter = manager_find_adapter_by_id(adapter_id);
> + if (adapter == NULL)
> + return;
> +
> + /* Look for the USB device */
> + libusb_init(NULL);
> +
> + num_devices = libusb_get_device_list(NULL, &list);
> + if (num_devices < 0) {
> + debug("libusb_get_device_list failed");
> + return;
> + }
> +
> + usbdev = NULL;
> + for (i = 0; i < num_devices; i++) {
> + char *path;
> +
> + path = g_strdup_printf("%s/%03d/%03d", "/dev/bus/usb",
> + libusb_get_bus_number(list[i]),
> +
> libusb_get_device_address(list[i]));
> + if (g_strcmp0(path, udev_device_get_devnode(udevice))
> == 0) {
> + g_free(path);
> + usbdev = libusb_ref_device(list[i]);
> + break;
> + }
> + g_free(path);
> + }
> +
> + libusb_free_device_list(list, TRUE);
> + if (usbdev == NULL) {
> + debug("Found a Sixaxis, but couldn't find it via
> libusb");
> + goto out;
> + }
> +
> + if (libusb_get_device_descriptor(usbdev, &desc) < 0) {
> + debug("libusb_get_device_descriptor() failed");
> + goto out;
> + }
> +
> + /* Look for the interface number that interests us */
> + for (j = 0; j < desc.bNumConfigurations; j++) {
> + struct libusb_config_descriptor *config;
> + guint8 k;
> +
> + if (libusb_get_config_descriptor(usbdev, j, &config) <
> 0) {
> + debug("Failed to get config descriptor %d",
> j);
> + continue;
> + }
> +
> + for (k = 0; k < config->bNumInterfaces; k++) {
> + const struct libusb_interface *itf =
> &config->interface[k];
> + int l;
> +
> + for (l = 0; l < itf->num_altsetting ; l++) {
> + struct libusb_interface_descriptor
> alt;
> +
> + alt = itf->altsetting[l];
> + if (alt.bInterfaceClass == 3) {
> + handle_usb_device(adapter,
> usbdev, config, l, &alt);
> + }
> + }
> + }
> + }
> +
> +out:
> + if (usbdev != NULL)
> + libusb_unref_device(usbdev);
> + libusb_exit(NULL);
> +}

What we are missing from libusb1 is a function to create the device
handle directly from a udev syspath. The enumeration is actually pretty
bad since it wakes up all USB devices on the all busses.

> +
> +static gboolean device_event_idle(struct udev_device *udevice)
> +{
> + handle_device_plug(udevice);
> + udev_device_unref(udevice);
> + return FALSE;
> +}
> +
> +static struct udev *ctx = NULL;
> +static struct udev_monitor *monitor = NULL;
> +static guint watch_id = 0;
> +
> +static gboolean
> +monitor_event(GIOChannel *source,
> + GIOCondition condition,
> + gpointer data)
> +{
> + struct udev_device *udevice;
> +
> + udevice = udev_monitor_receive_device(monitor);
> + if (udevice == NULL)
> + goto out;
> + if (g_strcmp0(udev_device_get_action(udevice), "add") != 0)
> + goto out;
> +
> + g_timeout_add_seconds(1, (GSourceFunc) device_event_idle,
> udevice);
> +
> +out:
> + return TRUE;
> +}

Why is the timeout thing needed? Or do you actually want idle callback?

Regards

Marcel