2012-01-24 00:27:44

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 0/8] Generate PIN for keyboards inside bluetoothd

Thanks for the comments on my RFC patch set, I've addressed those in
this new version which I'm now submitting formally.

The main changes are:
- bt_ids.h moved to src/
- a D-Bus error from calling DisplayPinCode results in a fallback to
calling RequestPinCode instead
- PIN isn't sent to the adapter until a successful reply from either
DisplayPinCode or RequestPinCode

This grew the patch a bit unsurprisingly, so I've split it up a fair
amount more - including separating out the documentating and tests
as requested.

Scott James Remnant (8):
bt_ids: add header of device class constants
Rename AUTH_TYPE_NOTIFY to AUTH_TYPE_NOTIFY_PASSKEY
Pass passkey by pointer rather than by value
agent: add DisplayPinCode method
Add AUTH_TYPE_NOTIFY_PASSKEY to device_request_authentication
Generate PIN for keyboard devices
doc: document DisplayPinCode
simple-agent: add DisplayPinCode

doc/agent-api.txt | 24 ++++++++++
src/agent.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++-
src/agent.h | 4 ++
src/bt_ids.h | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/device.c | 72 +++++++++++++++++++++++++++---
src/device.h | 5 +-
src/event.c | 29 ++++++++++--
test/simple-agent | 5 ++
8 files changed, 360 insertions(+), 16 deletions(-)
create mode 100644 src/bt_ids.h

--
1.7.7.3



2012-01-24 00:27:52

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 8/8] simple-agent: add DisplayPinCode

---
test/simple-agent | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/test/simple-agent b/test/simple-agent
index 8d65860..4416adb 100755
--- a/test/simple-agent
+++ b/test/simple-agent
@@ -52,6 +52,11 @@ class Agent(dbus.service.Object):
print "DisplayPasskey (%s, %d)" % (device, passkey)

@dbus.service.method("org.bluez.Agent",
+ in_signature="os", out_signature="")
+ def DisplayPinCode(self, device, pincode):
+ print "DisplayPinCode (%s, %s)" % (device, pincode)
+
+ @dbus.service.method("org.bluez.Agent",
in_signature="ou", out_signature="")
def RequestConfirmation(self, device, passkey):
print "RequestConfirmation (%s, %d)" % (device, passkey)
--
1.7.7.3


2012-01-24 00:27:51

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 7/8] doc: document DisplayPinCode

---
doc/agent-api.txt | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/doc/agent-api.txt b/doc/agent-api.txt
index 9ab2063..5c8d4d2 100644
--- a/doc/agent-api.txt
+++ b/doc/agent-api.txt
@@ -61,6 +61,30 @@ Methods void Release()
so the display should be zero-padded at the start if
the value contains less than 6 digits.

+ void DisplayPinCode(object device, string pincode)
+
+ This method gets called when the service daemon
+ needs to display a pincode for an authentication.
+
+ An empty reply should be returned. When the pincode
+ needs no longer to be displayed, the Cancel method
+ of the agent will be called.
+
+ If this method is not implemented the RequestPinCode
+ method will be used instead.
+
+ This is used during the pairing process of keyboards
+ that don't support Bluetooth 2.1 Secure Simple Pairing,
+ in contrast to DisplayPasskey which is used for those
+ that do.
+
+ This method will only ever be called once since
+ older keyboards do not support typing notification.
+
+ Note that the PIN will always be a 6-digit number,
+ zero-padded to 6 digits. This is for harmony with
+ the later specification.
+
void RequestConfirmation(object device, uint32 passkey)

This method gets called when the service daemon
--
1.7.7.3


2012-01-24 00:27:50

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 6/8] Generate PIN for keyboard devices

As recommended by the HID profile, generate a PIN for keyboard devices
and display on the host so that the user may enter it into the keyboard.

The new DisplayPinCode agent method is used, including its fallback to
RequestPinCode.

Generated PINs are numeric so that they may entered into Bluetooth
numeric keypads, and are zero-padded to six digits for compatibility
with Bluetooth 2.1 Secure Simple Pairing passkeys.
---
src/event.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/src/event.c b/src/event.c
index 5aa5ef9..12c569f 100644
--- a/src/event.c
+++ b/src/event.c
@@ -27,6 +27,7 @@
#endif

#define _GNU_SOURCE
+#include <time.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
@@ -49,6 +50,7 @@
#include "agent.h"
#include "storage.h"
#include "event.h"
+#include "bt_ids.h"

static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
struct btd_adapter **adapter,
@@ -119,6 +121,7 @@ int btd_event_request_pin(bdaddr_t *sba, bdaddr_t *dba, gboolean secure)
struct btd_device *device;
char pin[17];
ssize_t pinlen;
+ uint32_t class;

if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
return -ENODEV;
@@ -130,6 +133,22 @@ int btd_event_request_pin(bdaddr_t *sba, bdaddr_t *dba, gboolean secure)
return 0;
}

+ if (device_is_bonding(device, NULL) &&
+ read_remote_class(sba, dba, &class) == 0) {
+ switch (BT_CLASS(class)) {
+ case BT_CLASS_PERIPHERAL_KEYBOARD:
+ case BT_CLASS_PERIPHERAL_KEYBOARD_POINTING:
+ /* Generate a PIN in the range 000000-999999 */
+ DBG("Generating pincode for keyboard");
+ srand(time(NULL));
+ snprintf(pin, sizeof pin, "%06d", rand() % 1000000);
+
+ return device_request_authentication(device,
+ AUTH_TYPE_NOTIFY_PINCODE, pin,
+ secure, pincode_cb);
+ }
+ }
+
return device_request_authentication(device, AUTH_TYPE_PINCODE, NULL,
secure, pincode_cb);
}
--
1.7.7.3


2012-01-24 00:27:49

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 5/8] Add AUTH_TYPE_NOTIFY_PASSKEY to device_request_authentication

This new authentication type accepts a pincode and calls the
DisplayPinCode agent method, a fallback is provided so that if the
method is not implemented the older RequestPinCode method is used
instead.

Due to this fallback, the agent_pincode_cb is used and calling
functions should send the pincode passed to the callback to the
adapter, which may differ from that generated.
---
src/device.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/device.h | 1 +
2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/src/device.c b/src/device.c
index 82afbbe..89d961c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -94,6 +94,7 @@ struct authentication_req {
struct agent *agent;
struct btd_device *device;
uint32_t passkey;
+ char *pincode;
gboolean secure;
};

@@ -249,6 +250,8 @@ static void device_free(gpointer user_data)

DBG("%p", device);

+ if (device->authr)
+ g_free(device->authr->pincode);
g_free(device->authr);
g_free(device->path);
g_free(device->alias);
@@ -2320,12 +2323,15 @@ void device_simple_pairing_complete(struct btd_device *device, uint8_t status)
{
struct authentication_req *auth = device->authr;

- if (auth && auth->type == AUTH_TYPE_NOTIFY_PASSKEY && auth->agent)
+ if (auth && (auth->type == AUTH_TYPE_NOTIFY_PASSKEY
+ || auth->type == AUTH_TYPE_NOTIFY_PINCODE) && auth->agent)
agent_cancel(auth->agent);
}

static void device_auth_req_free(struct btd_device *device)
{
+ if (device->authr)
+ g_free(device->authr->pincode);
g_free(device->authr);
device->authr = NULL;
}
@@ -2337,7 +2343,8 @@ void device_bonding_complete(struct btd_device *device, uint8_t status)

DBG("bonding %p status 0x%02x", bonding, status);

- if (auth && auth->type == AUTH_TYPE_NOTIFY_PASSKEY && auth->agent)
+ if (auth && (auth->type == AUTH_TYPE_NOTIFY_PASSKEY
+ || auth->type == AUTH_TYPE_NOTIFY_PINCODE) && auth->agent)
agent_cancel(auth->agent);

if (status) {
@@ -2543,6 +2550,46 @@ done:
device->authr->agent = NULL;
}

+static void display_pincode_cb(struct agent *agent, DBusError *err, void *data)
+{
+ struct authentication_req *auth = data;
+ struct btd_device *device = auth->device;
+ struct btd_adapter *adapter = device_get_adapter(device);
+ struct agent *adapter_agent = adapter_get_agent(adapter);
+
+ if (err && (g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err->name) ||
+ g_str_equal(DBUS_ERROR_NO_REPLY, err->name))) {
+
+ /* Request a pincode if we fail to display one */
+ if (auth->agent == adapter_agent || adapter_agent == NULL) {
+ if (agent_request_pincode(agent, device, pincode_cb,
+ auth->secure, auth, NULL) < 0)
+ goto done;
+ return;
+ }
+
+ if (agent_display_pincode(adapter_agent, device, auth->pincode,
+ display_pincode_cb, auth, NULL) < 0)
+ goto done;
+
+ auth->agent = adapter_agent;
+ return;
+ }
+
+done:
+ /* No need to reply anything if the authentication already failed */
+ if (auth->cb == NULL)
+ return;
+
+ ((agent_pincode_cb) auth->cb)(agent, err, auth->pincode, device);
+
+ g_free(device->authr->pincode);
+ device->authr->pincode = NULL;
+ device->authr->cb = NULL;
+ device->authr->agent = NULL;
+}
+
+
int device_request_authentication(struct btd_device *device, auth_type_t type,
void *data, gboolean secure, void *cb)
{
@@ -2591,6 +2638,11 @@ int device_request_authentication(struct btd_device *device, auth_type_t type,
auth->passkey = *(uint32_t *)data;
err = agent_display_passkey(agent, device, auth->passkey);
break;
+ case AUTH_TYPE_NOTIFY_PINCODE:
+ auth->pincode = g_strdup((const char *)data);
+ err = agent_display_pincode(agent, device, auth->pincode,
+ display_pincode_cb, auth, NULL);
+ break;
default:
err = -EINVAL;
}
@@ -2631,6 +2683,9 @@ static void cancel_authentication(struct authentication_req *auth)
case AUTH_TYPE_NOTIFY_PASSKEY:
/* User Notify doesn't require any reply */
break;
+ case AUTH_TYPE_NOTIFY_PINCODE:
+ ((agent_pincode_cb) auth->cb)(agent, &err, NULL, device);
+ break;
}

dbus_error_free(&err);
diff --git a/src/device.h b/src/device.h
index 925155c..1be2aca 100644
--- a/src/device.h
+++ b/src/device.h
@@ -31,6 +31,7 @@ typedef enum {
AUTH_TYPE_PASSKEY,
AUTH_TYPE_CONFIRM,
AUTH_TYPE_NOTIFY_PASSKEY,
+ AUTH_TYPE_NOTIFY_PINCODE,
} auth_type_t;

struct btd_device *device_create(DBusConnection *conn,
--
1.7.7.3


2012-01-24 00:27:48

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 4/8] agent: add DisplayPinCode method

In constrast to DisplayPasskey, this sends a UTF-8 string PIN code
to the agent; also we support a callback for the case where the
Agent doesn't implement this new method so we can fallback.
---
src/agent.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/agent.h | 4 ++
2 files changed, 115 insertions(+), 1 deletions(-)

diff --git a/src/agent.c b/src/agent.c
index 9b942e8..23e3b43 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -52,7 +52,8 @@ typedef enum {
AGENT_REQUEST_CONFIRMATION,
AGENT_REQUEST_PINCODE,
AGENT_REQUEST_AUTHORIZE,
- AGENT_REQUEST_CONFIRM_MODE
+ AGENT_REQUEST_CONFIRM_MODE,
+ AGENT_REQUEST_DISPLAY_PINCODE,
} agent_request_type_t;

struct agent {
@@ -699,6 +700,115 @@ int agent_display_passkey(struct agent *agent, struct btd_device *device,
return 0;
}

+static void display_pincode_reply(DBusPendingCall *call, void *user_data)
+{
+ struct agent_request *req = user_data;
+ struct agent *agent = req->agent;
+ DBusMessage *message;
+ DBusError err;
+ agent_cb cb = req->cb;
+
+ /* clear agent->request early; our callback will likely try
+ * another request */
+ agent->request = NULL;
+
+ /* steal_reply will always return non-NULL since the callback
+ * is only called after a reply has been received */
+ message = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&err);
+ if (dbus_set_error_from_message(&err, message)) {
+ error("Agent replied with an error: %s, %s",
+ err.name, err.message);
+
+ cb(agent, &err, req->user_data);
+
+ if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
+ agent_cancel(agent);
+ dbus_message_unref(message);
+ dbus_error_free(&err);
+ return;
+ }
+
+ dbus_error_free(&err);
+ goto done;
+ }
+
+ dbus_error_init(&err);
+ if (!dbus_message_get_args(message, &err, DBUS_TYPE_INVALID)) {
+ error("Wrong reply signature: %s", err.message);
+ cb(agent, &err, req->user_data);
+ dbus_error_free(&err);
+ goto done;
+ }
+
+ cb(agent, NULL, req->user_data);
+done:
+ dbus_message_unref(message);
+
+ agent_request_free(req, TRUE);
+}
+
+static int display_pincode_request_new(struct agent_request *req,
+ const char *device_path,
+ const char *pincode)
+{
+ struct agent *agent = req->agent;
+
+ req->msg = dbus_message_new_method_call(agent->name, agent->path,
+ "org.bluez.Agent", "DisplayPinCode");
+ if (req->msg == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return -ENOMEM;
+ }
+
+ dbus_message_append_args(req->msg,
+ DBUS_TYPE_OBJECT_PATH, &device_path,
+ DBUS_TYPE_STRING, &pincode,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(connection, req->msg,
+ &req->call, REQUEST_TIMEOUT) == FALSE) {
+ error("D-Bus send failed");
+ return -EIO;
+ }
+
+ dbus_pending_call_set_notify(req->call, display_pincode_reply,
+ req, NULL);
+
+ return 0;
+}
+
+int agent_display_pincode(struct agent *agent, struct btd_device *device,
+ const char *pincode, agent_cb cb,
+ void *user_data, GDestroyNotify destroy)
+{
+ struct agent_request *req;
+ const gchar *dev_path = device_get_path(device);
+ int err;
+
+ if (agent->request)
+ return -EBUSY;
+
+ DBG("Calling Agent.DisplayPinCode: name=%s, path=%s, pincode=%s",
+ agent->name, agent->path, pincode);
+
+ req = agent_request_new(agent, AGENT_REQUEST_DISPLAY_PINCODE, cb,
+ user_data, destroy);
+
+ err = display_pincode_request_new(req, dev_path, pincode);
+ if (err < 0)
+ goto failed;
+
+ agent->request = req;
+
+ return 0;
+
+failed:
+ agent_request_free(req, FALSE);
+ return err;
+}
+
uint8_t agent_get_io_capability(struct agent *agent)
{
return agent->capability;
diff --git a/src/agent.h b/src/agent.h
index f62bf3b..69ad42b 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -64,6 +64,10 @@ int agent_request_confirmation(struct agent *agent, struct btd_device *device,
int agent_display_passkey(struct agent *agent, struct btd_device *device,
uint32_t passkey);

+int agent_display_pincode(struct agent *agent, struct btd_device *device,
+ const char *pincode, agent_cb cb,
+ void *user_data, GDestroyNotify destroy);
+
int agent_cancel(struct agent *agent);

gboolean agent_is_busy(struct agent *agent, void *user_data);
--
1.7.7.3


2012-01-24 00:27:47

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 3/8] Pass passkey by pointer rather than by value

This allows alternate data of a different type to be passed to
device_request_authentication() for other notification types such
as those that require a PIN.
---
src/device.c | 9 +++++----
src/device.h | 2 +-
src/event.c | 8 ++++----
3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/device.c b/src/device.c
index 670bfc4..82afbbe 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2544,7 +2544,7 @@ done:
}

int device_request_authentication(struct btd_device *device, auth_type_t type,
- uint32_t passkey, gboolean secure, void *cb)
+ void *data, gboolean secure, void *cb)
{
struct authentication_req *auth;
struct agent *agent;
@@ -2570,7 +2570,6 @@ int device_request_authentication(struct btd_device *device, auth_type_t type,
auth->device = device;
auth->cb = cb;
auth->type = type;
- auth->passkey = passkey;
auth->secure = secure;
device->authr = auth;

@@ -2584,11 +2583,13 @@ int device_request_authentication(struct btd_device *device, auth_type_t type,
auth, NULL);
break;
case AUTH_TYPE_CONFIRM:
- err = agent_request_confirmation(agent, device, passkey,
+ auth->passkey = *(uint32_t *)data;
+ err = agent_request_confirmation(agent, device, auth->passkey,
confirm_cb, auth, NULL);
break;
case AUTH_TYPE_NOTIFY_PASSKEY:
- err = agent_display_passkey(agent, device, passkey);
+ auth->passkey = *(uint32_t *)data;
+ err = agent_display_passkey(agent, device, auth->passkey);
break;
default:
err = -EINVAL;
diff --git a/src/device.h b/src/device.h
index 2558e4a..925155c 100644
--- a/src/device.h
+++ b/src/device.h
@@ -82,7 +82,7 @@ gboolean device_is_creating(struct btd_device *device, const char *sender);
gboolean device_is_bonding(struct btd_device *device, const char *sender);
void device_cancel_bonding(struct btd_device *device, uint8_t status);
int device_request_authentication(struct btd_device *device, auth_type_t type,
- uint32_t passkey, gboolean secure, void *cb);
+ void *data, gboolean secure, void *cb);
void device_cancel_authentication(struct btd_device *device, gboolean aborted);
gboolean device_is_authenticating(struct btd_device *device);
gboolean device_is_authorizing(struct btd_device *device);
diff --git a/src/event.c b/src/event.c
index d3de936..5aa5ef9 100644
--- a/src/event.c
+++ b/src/event.c
@@ -130,7 +130,7 @@ int btd_event_request_pin(bdaddr_t *sba, bdaddr_t *dba, gboolean secure)
return 0;
}

- return device_request_authentication(device, AUTH_TYPE_PINCODE, 0,
+ return device_request_authentication(device, AUTH_TYPE_PINCODE, NULL,
secure, pincode_cb);
}

@@ -177,7 +177,7 @@ int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
return -ENODEV;

return device_request_authentication(device, AUTH_TYPE_CONFIRM,
- passkey, FALSE, confirm_cb);
+ &passkey, FALSE, confirm_cb);
}

int btd_event_user_passkey(bdaddr_t *sba, bdaddr_t *dba)
@@ -188,7 +188,7 @@ int btd_event_user_passkey(bdaddr_t *sba, bdaddr_t *dba)
if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
return -ENODEV;

- return device_request_authentication(device, AUTH_TYPE_PASSKEY, 0,
+ return device_request_authentication(device, AUTH_TYPE_PASSKEY, NULL,
FALSE, passkey_cb);
}

@@ -201,7 +201,7 @@ int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
return -ENODEV;

return device_request_authentication(device, AUTH_TYPE_NOTIFY_PASSKEY,
- passkey, FALSE, NULL);
+ &passkey, FALSE, NULL);
}

void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
--
1.7.7.3


2012-01-24 00:27:46

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 2/8] Rename AUTH_TYPE_NOTIFY to AUTH_TYPE_NOTIFY_PASSKEY

This makes room for additional notification types to be added.
---
src/device.c | 8 ++++----
src/device.h | 2 +-
src/event.c | 4 ++--
3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/device.c b/src/device.c
index c19acd4..670bfc4 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2320,7 +2320,7 @@ void device_simple_pairing_complete(struct btd_device *device, uint8_t status)
{
struct authentication_req *auth = device->authr;

- if (auth && auth->type == AUTH_TYPE_NOTIFY && auth->agent)
+ if (auth && auth->type == AUTH_TYPE_NOTIFY_PASSKEY && auth->agent)
agent_cancel(auth->agent);
}

@@ -2337,7 +2337,7 @@ void device_bonding_complete(struct btd_device *device, uint8_t status)

DBG("bonding %p status 0x%02x", bonding, status);

- if (auth && auth->type == AUTH_TYPE_NOTIFY && auth->agent)
+ if (auth && auth->type == AUTH_TYPE_NOTIFY_PASSKEY && auth->agent)
agent_cancel(auth->agent);

if (status) {
@@ -2587,7 +2587,7 @@ int device_request_authentication(struct btd_device *device, auth_type_t type,
err = agent_request_confirmation(agent, device, passkey,
confirm_cb, auth, NULL);
break;
- case AUTH_TYPE_NOTIFY:
+ case AUTH_TYPE_NOTIFY_PASSKEY:
err = agent_display_passkey(agent, device, passkey);
break;
default:
@@ -2627,7 +2627,7 @@ static void cancel_authentication(struct authentication_req *auth)
case AUTH_TYPE_PASSKEY:
((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
break;
- case AUTH_TYPE_NOTIFY:
+ case AUTH_TYPE_NOTIFY_PASSKEY:
/* User Notify doesn't require any reply */
break;
}
diff --git a/src/device.h b/src/device.h
index 13005ae..2558e4a 100644
--- a/src/device.h
+++ b/src/device.h
@@ -30,7 +30,7 @@ typedef enum {
AUTH_TYPE_PINCODE,
AUTH_TYPE_PASSKEY,
AUTH_TYPE_CONFIRM,
- AUTH_TYPE_NOTIFY,
+ AUTH_TYPE_NOTIFY_PASSKEY,
} auth_type_t;

struct btd_device *device_create(DBusConnection *conn,
diff --git a/src/event.c b/src/event.c
index 0783b47..d3de936 100644
--- a/src/event.c
+++ b/src/event.c
@@ -200,8 +200,8 @@ int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
return -ENODEV;

- return device_request_authentication(device, AUTH_TYPE_NOTIFY, passkey,
- FALSE, NULL);
+ return device_request_authentication(device, AUTH_TYPE_NOTIFY_PASSKEY,
+ passkey, FALSE, NULL);
}

void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
--
1.7.7.3


2012-01-24 00:27:45

by Scott James Remnant

[permalink] [raw]
Subject: [PATCHv2 1/8] bt_ids: add header of device class constants

---
src/bt_ids.h | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 125 insertions(+), 0 deletions(-)
create mode 100644 src/bt_ids.h

diff --git a/src/bt_ids.h b/src/bt_ids.h
new file mode 100644
index 0000000..da89cf6
--- /dev/null
+++ b/src/bt_ids.h
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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
+ *
+ */
+
+/* Service classes */
+#define BT_SVC_BITMASK 0xFFE000
+#define BT_SVC_LIMITED_DISCOVERABILITY 0x002000
+#define BT_SVC_POSITIONING 0x010000
+#define BT_SVC_NETWORKING 0x020000
+#define BT_SVC_RENDER 0x040000
+#define BT_SVC_CAPTURE 0x080000
+#define BT_SVC_OBJECT_TRANSFER 0x100000
+#define BT_SVC_AUDIO 0x200000
+#define BT_SVC_TELEPHONE 0x400000
+#define BT_SVC_INFORMATION 0x800000
+
+#define BT_SVC(_class) ((_class) & BT_SVC_BITMASK)
+
+/* Major device classes */
+#define BT_MAJOR_CLASS_BITMASK 0x1F00
+#define BT_MAJOR_CLASS_MISC 0x0000
+#define BT_MAJOR_CLASS_COMPUTER 0x0100
+#define BT_MAJOR_CLASS_PHONE 0x0200
+#define BT_MAJOR_CLASS_NETWORKING 0x0300
+#define BT_MAJOR_CLASS_AUDIO_VIDEO 0x0400
+#define BT_MAJOR_CLASS_PERIPHERAL 0x0500
+#define BT_MAJOR_CLASS_IMAGING 0x0600
+#define BT_MAJOR_CLASS_WEARABLE 0x0700
+#define BT_MAJOR_CLASS_TOY 0x0800
+#define BT_MAJOR_CLASS_HEATLH 0x0900
+#define BT_MAJOR_CLASS_UNCATEGORIZED 0x1F00
+
+#define BT_MAJOR_CLASS(_class) ((_class) & BT_MAJOR_CLASS_BITMASK)
+
+/* Minor device classes (includes major class) */
+#define BT_CLASS_BITMASK 0x1FFC
+
+#define BT_CLASS(_class) ((_class) & BT_CLASS_BITMASK)
+
+/* Devices in the COMPUTER major class */
+#define BT_CLASS_COMPUTER_UNCATEGORIZED 0x0100
+#define BT_CLASS_COMPUTER_DESKTOP 0x0104
+#define BT_CLASS_COMPUTER_SERVER 0x0108
+#define BT_CLASS_COMPUTER_LAPTOP 0x010C
+#define BT_CLASS_COMPUTER_HANDHELD_PC_PDA 0x0110
+#define BT_CLASS_COMPUTER_PALM_SIZE_PC_PDA 0x0114
+#define BT_CLASS_COMPUTER_WEARABLE 0x0118
+
+/* Devices in the PHONE major class */
+#define BT_CLASS_PHONE_UNCATEGORIZED 0x0200
+#define BT_CLASS_PHONE_CELLULAR 0x0204
+#define BT_CLASS_PHONE_CORDLESS 0x0208
+#define BT_CLASS_PHONE_SMART 0x020C
+#define BT_CLASS_PHONE_MODEM_OR_GATEWAY 0x0210
+#define BT_CLASS_PHONE_ISDN 0x0214
+
+/* Devices in the AUDIO_VIDEO major class */
+#define BT_CLASS_AUDIO_VIDEO_UNCATEGORIZED 0x0400
+#define BT_CLASS_AUDIO_VIDEO_WEARABLE_HEADSET 0x0404
+#define BT_CLASS_AUDIO_VIDEO_HANDSFREE 0x0408
+#define BT_CLASS_AUDIO_VIDEO_MICROPHONE 0x0410
+#define BT_CLASS_AUDIO_VIDEO_LOUDSPEAKER 0x0414
+#define BT_CLASS_AUDIO_VIDEO_HEADPHONES 0x0418
+#define BT_CLASS_AUDIO_VIDEO_PORTABLE_AUDIO 0x041C
+#define BT_CLASS_AUDIO_VIDEO_CAR_AUDIO 0x0420
+#define BT_CLASS_AUDIO_VIDEO_SET_TOP_BOX 0x0424
+#define BT_CLASS_AUDIO_VIDEO_HIFI_AUDIO 0x0428
+#define BT_CLASS_AUDIO_VIDEO_VCR 0x042C
+#define BT_CLASS_AUDIO_VIDEO_VIDEO_CAMERA 0x0430
+#define BT_CLASS_AUDIO_VIDEO_CAMCORDER 0x0434
+#define BT_CLASS_AUDIO_VIDEO_VIDEO_MONITOR 0x0438
+#define BT_CLASS_AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER 0x043C
+#define BT_CLASS_AUDIO_VIDEO_VIDEO_CONFERENCING 0x0440
+#define BT_CLASS_AUDIO_VIDEO_VIDEO_GAMING_TOY 0x0448
+
+/* Devices in the WEARABLE major class */
+#define BT_CLASS_WEARABLE_UNCATEGORIZED 0x0700
+#define BT_CLASS_WEARABLE_WRIST_WATCH 0x0704
+#define BT_CLASS_WEARABLE_PAGER 0x0708
+#define BT_CLASS_WEARABLE_JACKET 0x070C
+#define BT_CLASS_WEARABLE_HELMET 0x0710
+#define BT_CLASS_WEARABLE_GLASSES 0x0714
+
+/* Devices in the TOY major class */
+#define BT_CLASS_TOY_UNCATEGORIZED 0x0800
+#define BT_CLASS_TOY_ROBOT 0x0804
+#define BT_CLASS_TOY_VEHICLE 0x0808
+#define BT_CLASS_TOY_DOLL_ACTION_FIGURE 0x080C
+#define BT_CLASS_TOY_CONTROLLER 0x0810
+#define BT_CLASS_TOY_GAME 0x0814
+
+/* Devices in the HEALTH major class */
+#define BT_CLASS_HEALTH_UNCATEGORIZED 0x0900
+#define BT_CLASS_HEALTH_BLOOD_PRESSURE 0x0904
+#define BT_CLASS_HEALTH_THERMOMETER 0x0908
+#define BT_CLASS_HEALTH_WEIGHING 0x090C
+#define BT_CLASS_HEALTH_GLUCOSE 0x0910
+#define BT_CLASS_HEALTH_PULSE_OXIMETER 0x0914
+#define BT_CLASS_HEALTH_PULSE_RATE 0x0918
+#define BT_CLASS_HEALTH_DATA_DISPLAY 0x091C
+
+/* Devices in the PERIPHERAL major class */
+#define BT_CLASS_PERIPHERAL_NON_KEYBOARD_NON_POINTING 0x0500
+#define BT_CLASS_PERIPHERAL_KEYBOARD 0x0540
+#define BT_CLASS_PERIPHERAL_POINTING 0x0580
+#define BT_CLASS_PERIPHERAL_KEYBOARD_POINTING 0x05C0
--
1.7.7.3