diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2011-01-14 23:14:13 +0200 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2011-01-16 23:09:40 +0200 |
commit | 006301ab40fc71da92f593ddfb2dba70202bd061 (patch) | |
tree | 7e2a2c773d46f20e04641a4caf4049af2e662120 | |
parent | 24dbc52388f1ef2e759d24d74cd32f93531c8857 (diff) | |
download | bluez-006301ab40fc71da92f593ddfb2dba70202bd061.tar.gz |
Update Class of Device handling to the latest management interface
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.
-rw-r--r-- | doc/mgmt-api.txt | 20 | ||||
-rw-r--r-- | lib/mgmt.h | 23 | ||||
-rw-r--r-- | plugins/hciops.c | 81 | ||||
-rw-r--r-- | plugins/mgmtops.c | 77 | ||||
-rw-r--r-- | src/adapter.c | 51 | ||||
-rw-r--r-- | src/adapter.h | 2 |
6 files changed, 171 insertions, 83 deletions
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt index 24c7070a..d964a702 100644 --- a/doc/mgmt-api.txt +++ b/doc/mgmt-api.txt @@ -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 ================================ @@ -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 { diff --git a/plugins/hciops.c b/plugins/hciops.c index 4d8850fa..fec7e166 100644 --- a/plugins/hciops.c +++ b/plugins/hciops.c @@ -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); } diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c index 28b42bbe..e33c0496 100644 --- a/plugins/mgmtops.c +++ b/plugins/mgmtops.c @@ -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) diff --git a/src/adapter.c b/src/adapter.c index 87a8bebc..ab4791c6 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -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); } diff --git a/src/adapter.h b/src/adapter.h index 250c65e5..b66be9a8 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -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); |