diff options
author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-20 19:59:38 +0000 |
---|---|---|
committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-20 19:59:38 +0000 |
commit | 43f70678ca8847c32c122be4deb19f5c0285af2c (patch) | |
tree | 2ec68d4738655b7843f3fe4b234723ba9d561267 /hcid/dbus.c | |
parent | 76435ed8bf033567c510e7ba9a18e39c1729534a (diff) |
Added D-Bus signals: RemoteDeviceConnected and RemoteDeviceDisconnected
Diffstat (limited to 'hcid/dbus.c')
-rw-r--r-- | hcid/dbus.c | 201 |
1 files changed, 183 insertions, 18 deletions
diff --git a/hcid/dbus.c b/hcid/dbus.c index ac00e8d1..02d7f739 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -98,7 +98,7 @@ static const char *phone_minor_cls[] = { }; -void discovered_device_free(void *data, void *user_data) +void discovered_device_info_free(void *data, void *user_data) { struct discovered_dev_info *dev = data; @@ -108,6 +108,27 @@ void discovered_device_free(void *data, void *user_data) } } +static void bonding_request_info_free(void *data, void *user_data) +{ + struct bonding_request_info *dev = data; + + if (dev) { + free(dev->bdaddr); + dbus_message_unref(dev->msg); + free(dev); + } +} + +static void active_conn_info_free(void *data, void *user_data) +{ + struct active_conn_info *dev = data; + + if (dev) { + free(dev->bdaddr); + free(dev); + } +} + int bonding_requests_find(const void *data, const void *user_data) { const struct bonding_request_info *dev = data; @@ -187,6 +208,52 @@ static int remote_name_remove(struct slist **list, bdaddr_t *bdaddr) return ret_val; } +static int active_conn_find_by_handle(const void *data, const void *user_data) +{ + const struct active_conn_info *dev = data; + const uint16_t *handle = user_data; + + if (dev->handle == *handle) + return 0; + + return -1; +} + +static int active_conn_append(struct slist **list, bdaddr_t *bdaddr, uint16_t handle) +{ + struct active_conn_info *dev = NULL; + + dev = malloc(sizeof(*dev)); + if (!dev) + return -1; + + dev->bdaddr = malloc(sizeof(*dev->bdaddr)); + bacpy(dev->bdaddr, bdaddr); + dev->handle = handle; + + *list = slist_append(*list, dev); + return 0; +} + +static int active_conn_remove(struct slist **list, uint16_t *handle) +{ + struct active_conn_info *dev; + struct slist *l; + int ret_val = -1; + + l = slist_find(*list, handle, active_conn_find_by_handle); + + if (l) { + dev = l->data; + *list = slist_remove(*list, dev); + free(dev->bdaddr); + free(dev); + ret_val = 0; + } + + return ret_val; +} + static DBusMessage *dbus_msg_new_authentication_return(DBusMessage *msg, uint8_t status) { @@ -356,14 +423,31 @@ failed: static gboolean unregister_dbus_path(const char *path) { - struct hci_dbus_data *data; + struct hci_dbus_data *pdata; info("Unregister path:%s", path); - if (dbus_connection_get_object_path_data(connection, path, (void *) &data) && data) { - if (data->requestor_name) - free(data->requestor_name); - free(data); + if (dbus_connection_get_object_path_data(connection, path, (void *) &pdata) && pdata) { + if (pdata->requestor_name) + free(pdata->requestor_name); + + if (pdata->discovered_devices) { + slist_foreach(pdata->discovered_devices, discovered_device_info_free, NULL); + slist_free(pdata->discovered_devices); + pdata->discovered_devices = NULL; + } + + if (pdata->bonding_requests) { + slist_foreach(pdata->bonding_requests, bonding_request_info_free, NULL); + slist_free(pdata->bonding_requests); + pdata->bonding_requests = NULL; + } + + if (pdata->active_conn) { + slist_foreach(pdata->active_conn, active_conn_info_free, NULL); + slist_free(pdata->active_conn); + pdata->active_conn = NULL; + } } if (!dbus_connection_unregister_object_path (connection, path)) { @@ -387,10 +471,12 @@ gboolean hcid_dbus_register_device(uint16_t id) char *pptr = path; gboolean ret; DBusMessage *message = NULL; - int dd = -1; + int i, dd = -1; read_scan_enable_rp rp; struct hci_request rq; struct hci_dbus_data* pdata; + struct hci_conn_list_req *cl = NULL; + struct hci_conn_info *ci = NULL; snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); ret = register_dbus_path(path, ADAPTER_PATH_ID, id, &obj_dev_vtable, FALSE); @@ -447,6 +533,27 @@ gboolean hcid_dbus_register_device(uint16_t id) } dbus_connection_flush(connection); + + /* + * retrieve the active connections: address the scenario where + * the are active connections before the daemon've started + */ + + cl = malloc(10 * sizeof(*ci) + sizeof(*cl)); + if (!cl) + goto failed; + + cl->dev_id = id; + cl->conn_num = 10; + ci = cl->conn_info; + + if (ioctl(dd, HCIGETCONNLIST, (void *) cl) < 0) { + free(cl); + goto failed; + } + + for (i = 0; i < cl->conn_num; i++, ci++) + active_conn_append(&pdata->active_conn, &ci->bdaddr, ci->handle); failed: if (message) @@ -458,6 +565,9 @@ failed: if (dd >= 0) close(dd); + if (cl) + free(cl); + return ret; } @@ -752,7 +862,7 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local) pdata->discover_state = DISCOVER_OFF; /* free discovered devices list */ - slist_foreach(pdata->discovered_devices, discovered_device_free, NULL); + slist_foreach(pdata->discovered_devices, discovered_device_info_free, NULL); slist_free(pdata->discovered_devices); pdata->discovered_devices = NULL; @@ -945,7 +1055,7 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char goto failed; /* skip if a new request has been sent */ /* free discovered devices list */ - slist_foreach(pdata->discovered_devices, discovered_device_free, NULL); + slist_foreach(pdata->discovered_devices, discovered_device_info_free, NULL); slist_free(pdata->discovered_devices); pdata->discovered_devices = NULL; @@ -971,6 +1081,7 @@ failed: void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer) { char path[MAX_PATH_LENGTH]; + DBusMessage *message = NULL; struct hci_request rq; evt_cmd_status rp; auth_requested_cp cp; @@ -992,28 +1103,37 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); + if (!status) { + /* Sent the remote device connected signal */ + message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceConnected"); + + dbus_message_append_args(message, + DBUS_TYPE_STRING, &peer_addr, + DBUS_TYPE_INVALID); + + send_reply_and_unref(connection, message); + } + if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) goto failed; - l = slist_find(pdata->bonding_requests, peer, bonding_requests_find); + /* add in the active connetions list */ + active_conn_append(&pdata->active_conn, peer, handle); - /* - * Connections can be requested by other applications, profiles and bonding - * For now it's necessary check only if there a pending bonding request - */ + /* check if this connection request was requested by a bonding procedure */ + l = slist_find(pdata->bonding_requests, peer, bonding_requests_find); if (!l) goto failed; dev = l->data; - /* connection failed */ if (status) { error_connection_attempt_failed(connection, dev->msg, status); goto failed; } if (dev->bonding_state != CONNECTING) - goto failed; /* FIXME: is it possible? */ + goto failed; dd = hci_open_dev(pdata->dev_id); if (dd < 0) { @@ -1032,7 +1152,6 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b rq.event = EVT_CMD_STATUS; rq.rparam = &rp; rq.rlen = EVT_CMD_STATUS_SIZE; - rq.ocf = OCF_AUTH_REQUESTED; rq.cparam = &cp; rq.clen = AUTH_REQUESTED_CP_SIZE; @@ -1069,8 +1188,54 @@ failed: bt_free(peer_addr); } -void hcid_dbus_disconn_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t reason) +void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, uint8_t reason) { + char path[MAX_PATH_LENGTH]; + struct hci_dbus_data *pdata = NULL; + struct active_conn_info *dev; + DBusMessage *message; + struct slist *l; + char *local_addr, *peer_addr = NULL; + bdaddr_t tmp; + int id; + + baswap(&tmp, local); local_addr = batostr(&tmp); + + id = hci_devid(local_addr); + if (id < 0) { + error("No matching device id for %s", local_addr); + goto failed; + } + + snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); + + if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) + goto failed; + + l = slist_find(pdata->active_conn, &handle, active_conn_find_by_handle); + + if (!l) + goto failed; + + dev = l->data; + /* add in the active connetions list */ + baswap(&tmp, dev->bdaddr); peer_addr = batostr(&tmp); + + /* Sent the remote device disconnected signal */ + message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceDisconnected"); + + dbus_message_append_args(message, + DBUS_TYPE_STRING, &peer_addr, + DBUS_TYPE_INVALID); + + send_reply_and_unref(connection, message); + active_conn_remove(&pdata->active_conn, &handle); + +failed: + if (peer_addr) + free(peer_addr); + + free(local_addr); } /***************************************************************** |