summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2010-12-30 15:03:57 +0200
committerJohan Hedberg <johan.hedberg@nokia.com>2010-12-30 15:06:16 +0200
commit6964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9 (patch)
tree9010b09c62a4ff8a9793d646ea5beba76a621ba5
parent3e1b64c81d0ef4ae92b601114aa06d85c735d646 (diff)
downloadbluez-6964bd2dd54d5cce7ce2588b0dcd0a3530e6fba9.tar.gz
mgmt: Implement set_pairable
This patch implements support for the set_pairable managment command. Due to the async nature of it a new btd_adapter_pairable_changed function is added to the core daemon.
-rw-r--r--doc/mgmt-api.txt16
-rw-r--r--lib/mgmt.h4
-rw-r--r--plugins/hciops.c9
-rw-r--r--plugins/mgmtops.c75
-rw-r--r--src/adapter.c28
-rw-r--r--src/adapter.h2
6 files changed, 119 insertions, 15 deletions
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index ba429501e..e785a5e17 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -107,6 +107,15 @@ Set Connectable Command
Connectable (1 Octet)
+Set Pairable Command
+====================
+
+ Command Code: 0x0008
+ Command Parameters: Controller_Index (2 Octets)
+ Pairable (1 Octet)
+ Return Paramters: Controller_Index (2 Octets)
+ Pairable (1 Octet)
+
Read Tracing Buffer Size Command
================================
@@ -216,3 +225,10 @@ Controller Connectable Event
Event Code 0x0008
Event Parameters Controller_Index (2 Octets)
Connectable (1 Octet)
+
+Controller Pairable Event
+=========================
+
+Event Code 0x0009
+Event Parameters Controller_Index (2 Octets)
+ Pairable (1 Octet)
diff --git a/lib/mgmt.h b/lib/mgmt.h
index 3657f71d6..1c3094986 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -79,6 +79,8 @@ struct mgmt_mode {
#define MGMT_OP_SET_CONNECTABLE 0x0007
+#define MGMT_OP_SET_PAIRABLE 0x0008
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
uint16_t opcode;
@@ -112,3 +114,5 @@ struct mgmt_ev_index_removed {
#define MGMT_EV_DISCOVERABLE 0x0007
#define MGMT_EV_CONNECTABLE 0x0008
+
+#define MGMT_EV_PAIRABLE 0x0009
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 9861d6025..ad83eb24a 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -310,8 +310,15 @@ static int hciops_set_discoverable(int index, gboolean discoverable)
static int hciops_set_pairable(int index, gboolean pairable)
{
+ struct btd_adapter *adapter;
+
DBG("hci%d pairable %d", index, pairable);
- return -ENOSYS;
+
+ adapter = manager_find_adapter(&devs[index].bdaddr);
+ if (adapter)
+ btd_adapter_pairable_changed(adapter, pairable);
+
+ return 0;
}
static int hciops_power_off(int index)
diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index 32d88d33d..d4378d872 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -206,7 +206,7 @@ static int mgmt_set_discoverable(int index, gboolean discoverable)
static int mgmt_set_pairable(int index, gboolean pairable)
{
DBG("index %d pairable %d", index, pairable);
- return -ENOSYS;
+ return mgmt_set_mode(index, MGMT_OP_SET_PAIRABLE, pairable);
}
static int mgmt_update_powered(int index, uint8_t powered)
@@ -261,7 +261,8 @@ static int mgmt_update_powered(int index, uint8_t powered)
adapter_mode_changed(adapter, mode);
}
- mgmt_set_pairable(index, pairable);
+ if (info->pairable != pairable)
+ mgmt_set_pairable(index, pairable);
return 0;
}
@@ -365,6 +366,38 @@ static void mgmt_connectable(int sk, void *buf, size_t len)
adapter_mode_changed(adapter, mode);
}
+static void mgmt_pairable(int sk, void *buf, size_t len)
+{
+ struct mgmt_mode *ev = buf;
+ struct controller_info *info;
+ struct btd_adapter *adapter;
+ uint16_t index;
+
+ if (len < sizeof(*ev)) {
+ error("Too small pairable event");
+ return;
+ }
+
+ index = btohs(bt_get_unaligned(&ev->index));
+
+ DBG("Controller %u pairable %u", index, ev->val);
+
+ if (index > max_index) {
+ error("Unexpected index %u in pairable event", index);
+ return;
+ }
+
+ info = &controllers[index];
+
+ info->pairable = ev->val ? TRUE : FALSE;
+
+ adapter = manager_find_adapter(&info->bdaddr);
+ if (!adapter)
+ return;
+
+ btd_adapter_pairable_changed(adapter, info->pairable);
+}
+
static void read_index_list_complete(int sk, void *buf, size_t len)
{
struct mgmt_rp_read_index_list *rp = buf;
@@ -549,6 +582,38 @@ static void set_connectable_complete(int sk, void *buf, size_t len)
adapter_mode_changed(adapter, rp->val ? SCAN_PAGE : 0);
}
+static void set_pairable_complete(int sk, void *buf, size_t len)
+{
+ struct mgmt_mode *rp = buf;
+ struct controller_info *info;
+ struct btd_adapter *adapter;
+ uint16_t index;
+
+ if (len < sizeof(*rp)) {
+ error("Too small set pairable complete event");
+ return;
+ }
+
+ index = btohs(bt_get_unaligned(&rp->index));
+
+ DBG("hci%d pairable %u", index, rp->val);
+
+ if (index > max_index) {
+ error("Unexpected index %u in pairable complete", index);
+ return;
+ }
+
+ info = &controllers[index];
+
+ info->pairable = rp->val ? TRUE : FALSE;
+
+ adapter = manager_find_adapter(&info->bdaddr);
+ if (!adapter)
+ return;
+
+ btd_adapter_pairable_changed(adapter, info->pairable);
+}
+
static void mgmt_cmd_complete(int sk, void *buf, size_t len)
{
struct mgmt_ev_cmd_complete *ev = buf;
@@ -582,6 +647,9 @@ static void mgmt_cmd_complete(int sk, void *buf, size_t len)
case MGMT_OP_SET_CONNECTABLE:
set_connectable_complete(sk, ev->data, len - sizeof(*ev));
break;
+ case MGMT_OP_SET_PAIRABLE:
+ set_pairable_complete(sk, ev->data, len - sizeof(*ev));
+ break;
default:
error("Unknown command complete for opcode %u", opcode);
break;
@@ -685,6 +753,9 @@ static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data
case MGMT_EV_CONNECTABLE:
mgmt_connectable(sk, buf + MGMT_HDR_SIZE, len);
break;
+ case MGMT_EV_PAIRABLE:
+ mgmt_pairable(sk, buf + MGMT_HDR_SIZE, len);
+ break;
default:
error("Unknown Management opcode %u", opcode);
break;
diff --git a/src/adapter.c b/src/adapter.c
index e6a2081fa..87a8bebc2 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -546,6 +546,22 @@ static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg,
return NULL;
}
+void btd_adapter_pairable_changed(struct btd_adapter *adapter,
+ gboolean pairable)
+{
+ adapter->pairable = pairable;
+
+ write_device_pairable(&adapter->bdaddr, pairable);
+
+ emit_property_changed(connection, adapter->path,
+ ADAPTER_INTERFACE, "Pairable",
+ DBUS_TYPE_BOOLEAN, &pairable);
+
+ if (pairable && adapter->pairable_timeout)
+ adapter_set_pairable_timeout(adapter,
+ adapter->pairable_timeout);
+}
+
static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg,
gboolean pairable, void *data)
{
@@ -566,20 +582,8 @@ static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg,
return btd_error_failed(msg, strerror(-err));
store:
- adapter->pairable = pairable;
-
adapter_ops->set_pairable(adapter->dev_id, pairable);
- write_device_pairable(&adapter->bdaddr, pairable);
-
- emit_property_changed(connection, adapter->path,
- ADAPTER_INTERFACE, "Pairable",
- DBUS_TYPE_BOOLEAN, &pairable);
-
- if (pairable && adapter->pairable_timeout)
- adapter_set_pairable_timeout(adapter,
- adapter->pairable_timeout);
-
done:
return msg ? dbus_message_new_method_return(msg) : NULL;
}
diff --git a/src/adapter.h b/src/adapter.h
index 4599ea7d1..250c65e55 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -151,6 +151,8 @@ void adapter_service_insert(struct btd_adapter *adapter, void *rec);
void adapter_service_remove(struct btd_adapter *adapter, void *rec);
void btd_adapter_class_changed(struct btd_adapter *adapter,
uint32_t new_class);
+void btd_adapter_pairable_changed(struct btd_adapter *adapter,
+ gboolean pairable);
struct agent *adapter_get_agent(struct btd_adapter *adapter);
void adapter_add_connection(struct btd_adapter *adapter,