Return-Path: MIME-Version: 1.0 In-Reply-To: <1367006741-28907-7-git-send-email-deymo@chromium.org> References: <1367006741-28907-1-git-send-email-deymo@chromium.org> <1367006741-28907-7-git-send-email-deymo@chromium.org> Date: Sat, 27 Apr 2013 11:31:08 +0200 Message-ID: Subject: Re: [PATCH v4 6/8] autopair: Add the autopair plugin. From: David Herrmann To: Alex Deymo Cc: "linux-bluetooth@vger.kernel.org" , Marcel Holtmann , Scott James Remnant Content-Type: text/plain; charset=ISO-8859-1 List-ID: Hi Alex On Fri, Apr 26, 2013 at 10:05 PM, Alex Deymo wrote: > The autopair plugin tries standard pincodes for different devices with dumb > pincodes. It also generates a random 6 digit pincode for keyboards that > support any pincode but fallbacks to the agent call in case the random > generated pincode didn't work. > --- > Makefile.plugins | 3 ++ > plugins/autopair.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 153 insertions(+) > create mode 100644 plugins/autopair.c > > diff --git a/Makefile.plugins b/Makefile.plugins > index 44e6eca..3efe849 100644 > --- a/Makefile.plugins > +++ b/Makefile.plugins > @@ -5,6 +5,9 @@ builtin_sources += plugins/hostname.c > builtin_modules += wiimote > builtin_sources += plugins/wiimote.c > > +builtin_modules += autopair > +builtin_sources += plugins/autopair.c > + > if MAINTAINER_MODE > builtin_modules += gatt_example > builtin_sources += plugins/gatt-example.c > diff --git a/plugins/autopair.c b/plugins/autopair.c > new file mode 100644 > index 0000000..2b7a5ee > --- /dev/null > +++ b/plugins/autopair.c > @@ -0,0 +1,150 @@ > +/* > + * > + * BlueZ - Bluetooth protocol stack for Linux > + * > + * Copyright (C) 2012 Google Inc. > + * > + * > + * 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 > +#endif > + > +#include > +#include > + > +#include > +#include > + > +#include "plugin.h" > +#include "adapter.h" > +#include "device.h" > +#include "log.h" > +#include "storage.h" > + > +/* > + * Plugin to handle automatic pairing of devices with reduced user > + * interaction, including implementing the recommendation of the HID spec > + * for keyboard devices. > + * > + * The plugin works by intercepting the PIN request for devices; if the > + * device is a keyboard a random six-digit numeric PIN is generated and > + * returned, flagged for displaying using DisplayPinCode. > + * > + */ > + > +static ssize_t autopair_pincb(struct btd_adapter *adapter, > + struct btd_device *device, > + char *pinbuf, gboolean *display, > + uint32_t attempt) > +{ > + char addr[18]; > + char pinstr[7]; > + uint32_t class; > + > + ba2str(device_get_address(device), addr); > + > + class = btd_device_get_class(device); > + > + DBG("device %s 0x%x", addr, class); > + > + /* This is a class-based pincode guesser. Ignore devices with an unknown > + * class. */ > + if (class == 0) > + return 0; > + > + switch ((class & 0x1f00) >> 8) { > + case 0x04: /* Audio/Video */ > + switch ((class & 0xfc) >> 2) { > + case 0x01: /* Wearable Headset Device */ > + case 0x02: /* Hands-free Device */ > + case 0x06: /* Headphones */ > + case 0x07: /* Portable Audio */ > + case 0x0a: /* HiFi Audio Device */ > + if (attempt > 1) > + return 0; > + memcpy(pinbuf, "0000", 4); > + return 4; > + break; > + } > + break; > + case 0x05: /* Peripheral */ > + switch ((class & 0xc0) >> 6) { > + case 0x01: /* Keyboard */ > + case 0x03: /* Combo keyboard/pointing device */ > + if (attempt > 1) > + return 0; > + snprintf(pinstr, sizeof(pinstr), "%06d", > + rand() % 1000000); > + *display = TRUE; > + memcpy(pinbuf, pinstr, 6); > + return 6; > + break; > + case 0x02: /* Pointing device */ > + if (attempt > 1) > + return 0; > + memcpy(pinbuf, "0000", 4); > + return 4; > + break; > + } > + break; > + } > + > + return 0; > +} > + > + > +static int autopair_probe(struct btd_adapter *adapter) > +{ > + btd_adapter_register_pin_cb(adapter, autopair_pincb); > + > + return 0; > +} > + > +static void autopair_remove(struct btd_adapter *adapter) > +{ > + btd_adapter_unregister_pin_cb(adapter, autopair_pincb); > +} > + > +static struct btd_adapter_driver autopair_driver = { > + .name = "autopair", > + .probe = autopair_probe, > + .remove = autopair_remove, > +}; > + > +static int autopair_init(void) > +{ > + /* Initialize the random seed from /dev/urandom */ > + unsigned int seed = time(NULL); > + FILE *f = fopen("/dev/urandom", "rb"); > + if (f != NULL) { > + fread(&seed, sizeof(seed), 1, f); > + fclose(f); > + } > + srand(seed); > + > + return btd_register_adapter_driver(&autopair_driver); > +} > + > +static void autopair_exit(void) > +{ > + btd_unregister_adapter_driver(&autopair_driver); > +} > + > +BLUETOOTH_PLUGIN_DEFINE(autopair, VERSION, > + BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, autopair_init, autopair_exit) Would you mind choosing a lower priority than default? Or how do you intend other plugins like plugins/wiimote.c to work in combination with this? I have seen a lot of 3rd party Wii-Remote based devices which report nearly random "class" entries. So if the autopair callback is called _before_ the wiimote callback, pairing will fail. I have two solutions for this: Integrate wiimote pairing into this plugin or changing the plugin priorities so the autopair callback is registered _after_ other pin-callbacks (or reversed, I forgot the order in which pincbs are called). I'm ok with both. Regards David