aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/hciops.c81
-rw-r--r--plugins/mgmtops.c77
2 files changed, 81 insertions, 77 deletions
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)