diff --git a/src/adapter.c b/src/adapter.c
index 536edb1..d596e48 100644
--- a/src/adapter.c
+++ b/src/adapter.c
adapter->profiles = NULL;
}
-static void adapter_stop(struct btd_adapter *adapter)
-{
- bool emit_discovering = false;
-
- /* check pending requests */
- reply_pending_requests(adapter);
-
- if (adapter->discovery) {
- emit_discovering = true;
- stop_discovery(adapter);
- }
-
- if (adapter->disc_sessions) {
- g_slist_free_full(adapter->disc_sessions, session_free);
- adapter->disc_sessions = NULL;
- }
-
- while (adapter->connections) {
- struct btd_device *device = adapter->connections->data;
- adapter_remove_connection(adapter, device);
- }
-
- if (emit_discovering)
- g_dbus_emit_property_changed(dbus_conn, adapter->path,
- ADAPTER_INTERFACE, "Discovering");
-
- if (adapter->dev_class) {
- /* the kernel should reset the class of device when powering
- * down, but it does not. So force it here ... */
- adapter->dev_class = 0;
- g_dbus_emit_property_changed(dbus_conn, adapter->path,
- ADAPTER_INTERFACE, "Class");
- }
-
- g_dbus_emit_property_changed(dbus_conn, adapter->path,
- ADAPTER_INTERFACE, "Powered");
-
- DBG("adapter %s has been disabled", adapter->path);
-}
-
static void free_service_auth(gpointer data, gpointer user_data)
{
struct service_auth *auth = data;
adapter->connections = g_slist_append(adapter->connections, device);
}
-void adapter_remove_connection(struct btd_adapter *adapter,
+static void adapter_remove_connection(struct btd_adapter *adapter,
struct btd_device *device)
{
DBG("");
}
}
+static void adapter_stop(struct btd_adapter *adapter)
+{
+ bool emit_discovering = false;
+
+ /* check pending requests */
+ reply_pending_requests(adapter);
+
+ if (adapter->discovery) {
+ emit_discovering = true;
+ stop_discovery(adapter);
+ }
+
+ if (adapter->disc_sessions) {
+ g_slist_free_full(adapter->disc_sessions, session_free);
+ adapter->disc_sessions = NULL;
+ }
+
+ while (adapter->connections) {
+ struct btd_device *device = adapter->connections->data;
+ adapter_remove_connection(adapter, device);
+ }
+
+ if (emit_discovering)
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
+ ADAPTER_INTERFACE, "Discovering");
+
+ if (adapter->dev_class) {
+ /* the kernel should reset the class of device when powering
+ * down, but it does not. So force it here ... */
+ adapter->dev_class = 0;
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
+ ADAPTER_INTERFACE, "Class");
+ }
+
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
+ ADAPTER_INTERFACE, "Powered");
+
+ DBG("adapter %s has been disabled", adapter->path);
+}
+
int btd_register_adapter_driver(struct btd_adapter_driver *driver)
{
adapter_drivers = g_slist_append(adapter_drivers, driver);
return -ENOSYS;
}
+static void dev_disconnected(struct btd_adapter *adapter,
+ const struct mgmt_addr_info *addr,
+ uint8_t reason)
+{
+ struct btd_device *device;
+ char dst[18];
+
+ ba2str(&addr->bdaddr, dst);
+
+ DBG("Device %s disconnected, reason %u", dst, reason);
+
+ device = adapter_find_device(adapter, dst);
+ if (device)
+ adapter_remove_connection(adapter, device);
+
+ adapter_bonding_complete(adapter, &addr->bdaddr, addr->type,
+ MGMT_STATUS_DISCONNECTED);
+}
+
+static void disconnect_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_disconnect *rp = param;
+ struct btd_adapter *adapter = user_data;
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Failed to disconnect device: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ return;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("Too small device disconnect response");
+ return;
+ }
+
+ dev_disconnected(adapter, &rp->addr, MGMT_DEV_DISCONN_LOCAL_HOST);
+}
+
int btd_adapter_disconnect_device(struct btd_adapter *adapter,
const bdaddr_t *bdaddr,
uint8_t bdaddr_type)
{
- return mgmt_disconnect(adapter->dev_id, bdaddr, bdaddr_type);
+ struct mgmt_cp_disconnect cp;
+
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.addr.bdaddr, bdaddr);
+ cp.addr.type = bdaddr_type;
+
+ if (mgmt_send(adapter->mgmt, MGMT_OP_DISCONNECT,
+ adapter->dev_id, sizeof(cp), &cp,
+ disconnect_complete, adapter, NULL) > 0)
+ return 0;
+
+ return -EIO;
}
int btd_adapter_remove_bonding(struct btd_adapter *adapter,
return 0;
}
+static void disconnected_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_ev_device_disconnected *ev = param;
+ struct btd_adapter *adapter = user_data;
+ uint8_t reason;
+
+ if (length < sizeof(struct mgmt_addr_info)) {
+ error("Too small device disconnected event");
+ return;
+ }
+
+ if (length < sizeof(*ev))
+ reason = MGMT_DEV_DISCONN_UNKNOWN;
+ else
+ reason = ev->reason;
+
+ dev_disconnected(adapter, &ev->addr, reason);
+}
+
static void read_info_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
discovering_callback,
adapter, NULL);
+ mgmt_register(adapter->mgmt, MGMT_EV_DEVICE_DISCONNECTED,
+ adapter->dev_id,
+ disconnected_callback,
+ adapter, NULL);
+
set_dev_class(adapter, adapter->major_class, adapter->minor_class);
set_name(adapter, btd_adapter_get_name(adapter));
diff --git a/src/adapter.h b/src/adapter.h
index 8f0276b..944364b 100644
--- a/src/adapter.h
+++ b/src/adapter.h
struct agent *adapter_get_agent(struct btd_adapter *adapter);
void adapter_add_connection(struct btd_adapter *adapter,
struct btd_device *device);
-void adapter_remove_connection(struct btd_adapter *adapter,
- struct btd_device *device);
struct btd_adapter *btd_adapter_ref(struct btd_adapter *adapter);
void btd_adapter_unref(struct btd_adapter *adapter);
diff --git a/src/mgmt.c b/src/mgmt.c
index d5088b2..10f21d1 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
eir_data_free(&eir_data);
}
-static void mgmt_device_disconnected(uint16_t index, void *buf, size_t len)
-{
- struct mgmt_ev_device_disconnected *ev = buf;
- struct btd_adapter *adapter;
- struct btd_device *device;
- char addr[18];
- uint8_t reason;
-
- if (len < sizeof(struct mgmt_addr_info)) {
- error("Too small device_disconnected event");
- return;
- }
-
- if (len < sizeof(*ev))
- reason = MGMT_DEV_DISCONN_UNKNOWN;
- else
- reason = ev->reason;
-
- ba2str(&ev->addr.bdaddr, addr);
-
- DBG("hci%u device %s disconnected reason %u", index, addr, reason);
-
- if (!get_adapter_and_device(index, &ev->addr, &adapter, &device, false))
- return;
-
- if (device)
- adapter_remove_connection(adapter, device);
-}
-
static void mgmt_connect_failed(uint16_t index, void *buf, size_t len)
{
struct mgmt_ev_connect_failed *ev = buf;
}
}
-static void disconnect_complete(uint16_t index, uint8_t status,
- void *buf, size_t len)
-{
- struct mgmt_rp_disconnect *rp = buf;
- struct btd_adapter *adapter;
- struct btd_device *device;
- char addr[18];
-
- if (len < sizeof(*rp)) {
- error("Too small disconnect complete event");
- return;
- }
-
- ba2str(&rp->addr.bdaddr, addr);
-
- if (status != 0) {
- error("Disconnecting %s failed with status %u", addr, status);
- return;
- }
-
- DBG("hci%d %s disconnected", index, addr);
-
- if (!get_adapter_and_device(index, &rp->addr, &adapter, &device, false))
- return;
-
- if (device)
- adapter_remove_connection(adapter, device);
-
- adapter_bonding_complete(adapter, &rp->addr.bdaddr, rp->addr.type,
- MGMT_STATUS_DISCONNECTED);
-}
-
static void pair_device_complete(uint16_t index, uint8_t status,
void *buf, size_t len)
{
DBG("unpair_device complete");
break;
case MGMT_OP_DISCONNECT:
- disconnect_complete(index, ev->status, ev->data, len);
+ DBG("disconnect complete event");
break;
case MGMT_OP_GET_CONNECTIONS:
DBG("get_connections complete");
mgmt_device_connected(index, buf + MGMT_HDR_SIZE, len);
break;
case MGMT_EV_DEVICE_DISCONNECTED:
- mgmt_device_disconnected(index, buf + MGMT_HDR_SIZE, len);
+ DBG("device_disconnected event");
break;
case MGMT_EV_CONNECT_FAILED:
mgmt_connect_failed(index, buf + MGMT_HDR_SIZE, len);