OSDN Git Service

Update Class of Device handling to the latest management interface
authorJohan Hedberg <johan.hedberg@nokia.com>
Fri, 14 Jan 2011 21:14:13 +0000 (23:14 +0200)
committerJohan Hedberg <johan.hedberg@nokia.com>
Sun, 16 Jan 2011 21:09:40 +0000 (23:09 +0200)
This patch updates the class of device handling code to match the latest
management interface. A notable feature is that UUID to service class
mapping policy remains in user space with the help of the svc_hint
parameter of the add_uuid command. This is to make it easy to update the
mapping table when new profiles come along.

doc/mgmt-api.txt
lib/mgmt.h
plugins/hciops.c
plugins/mgmtops.c
src/adapter.c
src/adapter.h

index 24c7070..d964a70 100644 (file)
@@ -122,6 +122,7 @@ Add UUID Command
        Command Code:           0x0009
        Command Parameters:     Controller_Index (2 Octets)
                                UUID (16 Octets)
+                               SVC_Hint (1 octet)
        Return Paramters:       Controller_Index (2 Octets)
 
 
@@ -134,6 +135,25 @@ Remove UUID Command
        Return Paramters:       Controller_Index (2 Octets)
 
 
+Set Device Class
+================
+
+       Command Code:           0x000B
+       Command Parameters:     Controller_Index (2 Octets)
+                               Major_Class (1 octet)
+                               Minor_Class (1 octed)
+       Return Paramters:       Controller_Index (2 Octets)
+
+
+Set Service Cache Command
+=========================
+
+       Command Code:           0x000C
+       Command Parameters:     Controller_Index (2 Octets)
+                               Enable (1 octet)
+       Return Paramters:       Controller_Index (2 Octets)
+
+
 Read Tracing Buffer Size Command
 ================================
 
index a382c53..6bdefab 100644 (file)
@@ -81,14 +81,31 @@ struct mgmt_mode {
 
 #define MGMT_OP_SET_PAIRABLE           0x0008
 
-struct mgmt_cp_uuid {
+#define MGMT_OP_ADD_UUID               0x0009
+struct mgmt_cp_add_uuid {
        uint16_t index;
        uint8_t uuid[16];
+       uint8_t svc_hint;
 } __packed;
 
-#define MGMT_OP_ADD_UUID               0x0009
-
 #define MGMT_OP_REMOVE_UUID            0x000A
+struct mgmt_cp_remove_uuid {
+       uint16_t index;
+       uint8_t uuid[16];
+} __packed;
+
+#define MGMT_OP_SET_DEV_CLASS          0x000B
+struct mgmt_cp_set_dev_class {
+       uint16_t index;
+       uint8_t major;
+       uint8_t minor;
+} __packed;
+
+#define MGMT_OP_SET_SERVICE_CACHE      0x000C
+struct mgmt_cp_set_service_cache {
+       uint16_t index;
+       uint8_t enable;
+} __packed;
 
 #define MGMT_EV_CMD_COMPLETE           0x0001
 struct mgmt_ev_cmd_complete {
index 4d8850f..fec7e16 100644 (file)
@@ -63,6 +63,11 @@ enum {
        PENDING_NAME,
 };
 
+struct uuid_info {
+       uuid_t uuid;
+       uint8_t svc_hint;
+};
+
 static int max_dev = -1;
 static struct dev_info {
        int sk;
@@ -1037,10 +1042,10 @@ static void eir_generate_uuid128(GSList *list, uint8_t *ptr, uint16_t *eir_len)
        uuid128 = ptr + 2;
 
        for (; list; list = list->next) {
-               uuid_t *uuid = list->data;
-               uint8_t *uuid128_data = uuid->value.uuid128.data;
+               struct uuid_info *uuid = list->data;
+               uint8_t *uuid128_data = uuid->uuid.value.uuid128.data;
 
-               if (uuid->type != SDP_UUID128)
+               if (uuid->uuid.type != SDP_UUID128)
                        continue;
 
                /* Stop if not enough space to put next UUID128 */
@@ -1136,15 +1141,15 @@ static void create_ext_inquiry_response(int index, uint8_t *data)
 
        /* Group all UUID16 types */
        for (l = dev->uuids; l != NULL; l = g_slist_next(l)) {
-               uuid_t *uuid = l->data;
+               struct uuid_info *uuid = l->data;
 
-               if (uuid->type != SDP_UUID16)
+               if (uuid->uuid.type != SDP_UUID16)
                        continue;
 
-               if (uuid->value.uuid16 < 0x1100)
+               if (uuid->uuid.value.uuid16 < 0x1100)
                        continue;
 
-               if (uuid->value.uuid16 == PNP_INFO_SVCLASS_ID)
+               if (uuid->uuid.value.uuid16 == PNP_INFO_SVCLASS_ID)
                        continue;
 
                /* Stop if not enough space to put next UUID16 */
@@ -1155,13 +1160,13 @@ static void create_ext_inquiry_response(int index, uint8_t *data)
 
                /* Check for duplicates */
                for (i = 0; i < uuid_count; i++)
-                       if (uuid16[i] == uuid->value.uuid16)
+                       if (uuid16[i] == uuid->uuid.value.uuid16)
                                break;
 
                if (i < uuid_count)
                        continue;
 
-               uuid16[uuid_count++] = uuid->value.uuid16;
+               uuid16[uuid_count++] = uuid->uuid.value.uuid16;
                eir_len += sizeof(uint16_t);
        }
 
@@ -3021,48 +3026,6 @@ static int hciops_enable_le(int index)
        return 0;
 }
 
-static uint8_t get_uuid_mask(uint16_t uuid16)
-{
-       switch (uuid16) {
-       case DIALUP_NET_SVCLASS_ID:
-       case CIP_SVCLASS_ID:
-               return 0x42;    /* Telephony & Networking */
-       case IRMC_SYNC_SVCLASS_ID:
-       case OBEX_OBJPUSH_SVCLASS_ID:
-       case OBEX_FILETRANS_SVCLASS_ID:
-       case IRMC_SYNC_CMD_SVCLASS_ID:
-       case PBAP_PSE_SVCLASS_ID:
-               return 0x10;    /* Object Transfer */
-       case HEADSET_SVCLASS_ID:
-       case HANDSFREE_SVCLASS_ID:
-               return 0x20;    /* Audio */
-       case CORDLESS_TELEPHONY_SVCLASS_ID:
-       case INTERCOM_SVCLASS_ID:
-       case FAX_SVCLASS_ID:
-       case SAP_SVCLASS_ID:
-       /*
-        * Setting the telephony bit for the handsfree audio gateway
-        * role is not required by the HFP specification, but the
-        * Nokia 616 carkit is just plain broken! It will refuse
-        * pairing without this bit set.
-        */
-       case HANDSFREE_AGW_SVCLASS_ID:
-               return 0x40;    /* Telephony */
-       case AUDIO_SOURCE_SVCLASS_ID:
-       case VIDEO_SOURCE_SVCLASS_ID:
-               return 0x08;    /* Capturing */
-       case AUDIO_SINK_SVCLASS_ID:
-       case VIDEO_SINK_SVCLASS_ID:
-               return 0x04;    /* Rendering */
-       case PANU_SVCLASS_ID:
-       case NAP_SVCLASS_ID:
-       case GN_SVCLASS_ID:
-               return 0x02;    /* Networking */
-       default:
-               return 0;
-       }
-}
-
 static uint8_t generate_service_class(int index)
 {
        struct dev_info *dev = &devs[index];
@@ -3070,12 +3033,9 @@ static uint8_t generate_service_class(int index)
        uint8_t val = 0;
 
        for (l = dev->uuids; l != NULL; l = g_slist_next(l)) {
-               uuid_t *uuid = l->data;
+               struct uuid_info *uuid = l->data;
 
-               if (uuid->type != SDP_UUID16)
-                       continue;
-
-               val |= get_uuid_mask(uuid->value.uuid16);
+               val |= uuid->svc_hint;
        }
 
        return val;
@@ -3117,13 +3077,18 @@ static int update_service_classes(int index)
        return err;
 }
 
-static int hciops_add_uuid(int index, uuid_t *uuid)
+static int hciops_add_uuid(int index, uuid_t *uuid, uint8_t svc_hint)
 {
        struct dev_info *dev = &devs[index];
+       struct uuid_info *info;
 
        DBG("hci%d", index);
 
-       dev->uuids = g_slist_append(dev->uuids, g_memdup(uuid, sizeof(*uuid)));
+       info = g_new0(struct uuid_info, 1);
+       memcpy(&info->uuid, uuid, sizeof(*uuid));
+       info->svc_hint = svc_hint;
+
+       dev->uuids = g_slist_append(dev->uuids, info);
 
        return update_service_classes(index);
 }
index 28b42bb..e33c049 100644 (file)
@@ -410,17 +410,44 @@ static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
                memcpy(uuid128, uuid, sizeof(*uuid));
 }
 
-static int mgmt_uuid_op(int index, uint16_t op, uuid_t *uuid)
+static int mgmt_add_uuid(int index, uuid_t *uuid, uint8_t svc_hint)
 {
-       char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_uuid)];
+       char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_add_uuid)];
        struct mgmt_hdr *hdr = (void *) buf;
-       struct mgmt_cp_uuid *cp = (void *) &buf[sizeof(*hdr)];
+       struct mgmt_cp_add_uuid *cp = (void *) &buf[sizeof(*hdr)];
        uuid_t uuid128;
 
+       DBG("index %d", index);
+
        uuid_to_uuid128(&uuid128, uuid);
 
        memset(buf, 0, sizeof(buf));
-       hdr->opcode = htobs(op);
+       hdr->opcode = htobs(MGMT_OP_ADD_UUID);
+       hdr->len = htobs(sizeof(*cp));
+
+       cp->index = htobs(index);
+       memcpy(cp->uuid, uuid128.value.uuid128.data, 16);
+       cp->svc_hint = svc_hint;
+
+       if (write(mgmt_sock, buf, sizeof(buf)) < 0)
+               return -errno;
+
+       return 0;
+}
+
+static int mgmt_remove_uuid(int index, uuid_t *uuid)
+{
+       char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_remove_uuid)];
+       struct mgmt_hdr *hdr = (void *) buf;
+       struct mgmt_cp_remove_uuid *cp = (void *) &buf[sizeof(*hdr)];
+       uuid_t uuid128;
+
+       DBG("index %d", index);
+
+       uuid_to_uuid128(&uuid128, uuid);
+
+       memset(buf, 0, sizeof(buf));
+       hdr->opcode = htobs(MGMT_OP_REMOVE_UUID);
        hdr->len = htobs(sizeof(*cp));
 
        cp->index = htobs(index);
@@ -439,7 +466,7 @@ static int clear_uuids(int index)
        memset(&uuid_any, 0, sizeof(uuid_any));
        uuid_any.type = SDP_UUID128;
 
-       return mgmt_uuid_op(index, MGMT_OP_REMOVE_UUID, &uuid_any);
+       return mgmt_remove_uuid(index, &uuid_any);
 }
 
 static void read_index_list_complete(int sk, void *buf, size_t len)
@@ -497,6 +524,8 @@ static void read_info_complete(int sk, void *buf, size_t len)
                return;
        }
 
+       mgmt_set_mode(index, MGMT_OP_SET_SERVICE_CACHE, 1);
+
        info = &controllers[index];
        info->type = rp->type;
        info->enabled = rp->powered;
@@ -701,6 +730,12 @@ static void mgmt_cmd_complete(int sk, void *buf, size_t len)
        case MGMT_OP_REMOVE_UUID:
                DBG("remove_uuid complete");
                break;
+       case MGMT_OP_SET_DEV_CLASS:
+               DBG("set_dev_class complete");
+               break;
+       case MGMT_OP_SET_SERVICE_CACHE:
+               DBG("set_service_cache complete");
+               break;
        default:
                error("Unknown command complete for opcode %u", opcode);
                break;
@@ -879,8 +914,24 @@ static void mgmt_cleanup(void)
 
 static int mgmt_set_dev_class(int index, uint8_t major, uint8_t minor)
 {
+       char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_dev_class)];
+       struct mgmt_hdr *hdr = (void *) buf;
+       struct mgmt_cp_set_dev_class *cp = (void *) &buf[sizeof(*hdr)];
+
        DBG("index %d major %u minor %u", index, major, minor);
-       return -ENOSYS;
+
+       memset(buf, 0, sizeof(buf));
+       hdr->opcode = htobs(MGMT_OP_SET_DEV_CLASS);
+       hdr->len = htobs(sizeof(*cp));
+
+       cp->index = htobs(index);
+       cp->major = major;
+       cp->minor = minor;
+
+       if (write(mgmt_sock, buf, sizeof(buf)) < 0)
+               return -errno;
+
+       return 0;
 }
 
 static int mgmt_set_limited_discoverable(int index, gboolean limited)
@@ -1123,22 +1174,10 @@ static int mgmt_set_did(int index, uint16_t vendor, uint16_t product,
        return -ENOSYS;
 }
 
-static int mgmt_add_uuid(int index, uuid_t *uuid)
-{
-       DBG("index %d", index);
-       return mgmt_uuid_op(index, MGMT_OP_ADD_UUID, uuid);
-}
-
-static int mgmt_remove_uuid(int index, uuid_t *uuid)
-{
-       DBG("index %d", index);
-       return mgmt_uuid_op(index, MGMT_OP_REMOVE_UUID, uuid);
-}
-
 static int mgmt_disable_cod_cache(int index)
 {
        DBG("index %d", index);
-       return -ENOSYS;
+       return mgmt_set_mode(index, MGMT_OP_SET_SERVICE_CACHE, 0);
 }
 
 static int mgmt_restore_powered(int index)
index 87a8beb..ab4791c 100644 (file)
@@ -1004,6 +1004,51 @@ static void adapter_emit_uuids_updated(struct btd_adapter *adapter)
        g_strfreev(uuids);
 }
 
+static uint8_t get_uuid_mask(uuid_t *uuid)
+{
+       if (uuid->type != SDP_UUID16)
+               return 0;
+
+       switch (uuid->value.uuid16) {
+       case DIALUP_NET_SVCLASS_ID:
+       case CIP_SVCLASS_ID:
+               return 0x42;    /* Telephony & Networking */
+       case IRMC_SYNC_SVCLASS_ID:
+       case OBEX_OBJPUSH_SVCLASS_ID:
+       case OBEX_FILETRANS_SVCLASS_ID:
+       case IRMC_SYNC_CMD_SVCLASS_ID:
+       case PBAP_PSE_SVCLASS_ID:
+               return 0x10;    /* Object Transfer */
+       case HEADSET_SVCLASS_ID:
+       case HANDSFREE_SVCLASS_ID:
+               return 0x20;    /* Audio */
+       case CORDLESS_TELEPHONY_SVCLASS_ID:
+       case INTERCOM_SVCLASS_ID:
+       case FAX_SVCLASS_ID:
+       case SAP_SVCLASS_ID:
+       /*
+        * Setting the telephony bit for the handsfree audio gateway
+        * role is not required by the HFP specification, but the
+        * Nokia 616 carkit is just plain broken! It will refuse
+        * pairing without this bit set.
+        */
+       case HANDSFREE_AGW_SVCLASS_ID:
+               return 0x40;    /* Telephony */
+       case AUDIO_SOURCE_SVCLASS_ID:
+       case VIDEO_SOURCE_SVCLASS_ID:
+               return 0x08;    /* Capturing */
+       case AUDIO_SINK_SVCLASS_ID:
+       case VIDEO_SINK_SVCLASS_ID:
+               return 0x04;    /* Rendering */
+       case PANU_SVCLASS_ID:
+       case NAP_SVCLASS_ID:
+       case GN_SVCLASS_ID:
+               return 0x02;    /* Networking */
+       default:
+               return 0;
+       }
+}
+
 static int uuid_cmp(const void *a, const void *b)
 {
        const sdp_record_t *rec = a;
@@ -1025,8 +1070,10 @@ void adapter_service_insert(struct btd_adapter *adapter, void *r)
        adapter->services = sdp_list_insert_sorted(adapter->services, rec,
                                                                record_sort);
 
-       if (new_uuid)
-               adapter_ops->add_uuid(adapter->dev_id, &rec->svclass);
+       if (new_uuid) {
+               uint8_t svc_hint = get_uuid_mask(&rec->svclass);
+               adapter_ops->add_uuid(adapter->dev_id, &rec->svclass, svc_hint);
+       }
 
        adapter_emit_uuids_updated(adapter);
 }
index 250c65e..b66be9a 100644 (file)
@@ -234,7 +234,7 @@ struct btd_adapter_ops {
                                                        gpointer user_data);
        int (*set_did) (int index, uint16_t vendor, uint16_t product,
                                                        uint16_t version);
-       int (*add_uuid) (int index, uuid_t *uuid);
+       int (*add_uuid) (int index, uuid_t *uuid, uint8_t svc_hint);
        int (*remove_uuid) (int index, uuid_t *uuid);
        int (*disable_cod_cache) (int index);
        int (*restore_powered) (int index);