Two issues which are now fixed:
On 04/18/2014 04:09 PM, Jakub Tyszkowski wrote:
@@ -861,45 +861,37 @@ static gboolean disconnected_cb(GIOChannel *io, GIOCondition cond,
int sock, err = 0;
socklen_t len;
- queue_remove(conn_list, dev);
-
sock = g_io_channel_unix_get_fd(io);
len = sizeof(err);
if (!getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len))
DBG("%s (%d)", strerror(err), err);
+ device_disconnect_clients(dev);
connection_cleanup(dev);
Connection cleanup unrefs attrib, triggering notification cleanup, which
still needs client's connection map to remove itself from notification
queue, thus the proper order is:
connection_cleanup(dev);
+ device_disconnect_clients(dev);
@@ -1099,96 +1061,204 @@ static struct gatt_device *create_device(bdaddr_t *addr)
bacpy(&dev->bdaddr, addr);
- dev->clients = queue_new();
dev->services = queue_new();
-
- if (!dev->clients || !dev->services) {
+ if (!dev->services) {
error("gatt: Failed to allocate memory for client");
+
destroy_device(dev);
return NULL;
}
+ if (!queue_push_head(gatt_devices, dev)) {
+ error("gatt: Cannot push device to queue");
+
+ return NULL;
+ }
+
return dev;
}
-static void handle_client_connect(const void *buf, uint16_t len)
+static struct connection_record *create_conn_record(struct gatt_device *device,
+ struct gatt_client *client)
{
- const struct hal_cmd_gatt_client_connect *cmd = buf;
- struct gatt_device *dev = NULL;
- void *l;
- bdaddr_t addr;
+ struct connection_record *new_conn;
+ struct connection_record *last;
+
+ /* Check if already connected */
+ new_conn = new0(struct connection_record, 1);
+ if (!new_conn)
+ return NULL;
+
+ new_conn->client = client;
+ new_conn->device = device;
+
+ /* Make connection id unique to connection record
+ * (client, device) pair.
+ */
+ last = queue_peek_head(client_connections);
+ if (last)
+ new_conn->id = last->id + 1;
+ else
+ new_conn->id = 1;
+
+ if (!queue_push_head(client_connections, new_conn)) {
+ error("gatt: Cannot push client on the client queue!?");
+
+ free(new_conn);
+ return NULL;
+ }
+
+ new_conn->device->client_count++;
+
+ return new_conn;
+}
+
+static void trigger_disconnection(struct connection_record *conn)
+{
+ if (conn->device->state == DEVICE_STATE_DISCONNECTED)
+ return;
+
+ if (queue_remove(client_connections, conn)) {
+ send_client_disconnect_notify(conn, GATT_SUCCESS);
+ conn->device->client_count--;
+ }
+
+ if (conn->device->client_count <= 0) {
+ connection_cleanup(conn->device);
+ device_set_state(conn->device, DEVICE_STATE_DISCONNECTED);
+ }
+
+ free(conn);
+}
+
+static void client_disconnect_devices(struct gatt_client *client)
+{
+ struct connection_record *conn;
+
+ /* find every connection for client record and trigger disconnect */
+ while ((conn = queue_find(client_connections,
It should obviously be:
while ((conn = queue_remove_if(client_connections,
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html