diff options
-rw-r--r-- | plugins/hciops.c | 205 | ||||
-rw-r--r-- | plugins/mgmtops.c | 117 | ||||
-rw-r--r-- | src/adapter.c | 38 | ||||
-rw-r--r-- | src/adapter.h | 3 |
4 files changed, 198 insertions, 165 deletions
diff --git a/plugins/hciops.c b/plugins/hciops.c index 00b90061..3d68796f 100644 --- a/plugins/hciops.c +++ b/plugins/hciops.c @@ -647,13 +647,111 @@ static int hciops_stop_inquiry(int index) return 0; } +static void update_ext_inquiry_response(int index) +{ + struct dev_info *dev = &devs[index]; + write_ext_inquiry_response_cp cp; + + DBG("hci%d", index); + + if (!(dev->features[6] & LMP_EXT_INQ)) + return; + + if (dev->ssp_mode == 0) + return; + + if (dev->cache_enable) + return; + + memset(&cp, 0, sizeof(cp)); + + eir_create(dev->name, dev->tx_power, dev->did_vendor, dev->did_product, + dev->did_version, dev->uuids, cp.data); + + if (memcmp(cp.data, dev->eir, sizeof(cp.data)) == 0) + return; + + memcpy(dev->eir, cp.data, sizeof(cp.data)); + + if (hci_send_cmd(dev->sk, OGF_HOST_CTL, + OCF_WRITE_EXT_INQUIRY_RESPONSE, + WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0) + error("Unable to write EIR data: %s (%d)", + strerror(errno), errno); +} + +static int hciops_set_name(int index, const char *name) +{ + struct dev_info *dev = &devs[index]; + change_local_name_cp cp; + + DBG("hci%d, name %s", index, name); + + memset(&cp, 0, sizeof(cp)); + strncpy((char *) cp.name, name, sizeof(cp.name)); + + if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, + CHANGE_LOCAL_NAME_CP_SIZE, &cp) < 0) + return -errno; + + memcpy(dev->name, cp.name, 248); + update_ext_inquiry_response(index); + + return 0; +} + +static int write_class(int index, uint32_t class) +{ + struct dev_info *dev = &devs[index]; + write_class_of_dev_cp cp; + + DBG("hci%d class 0x%06x", index, class); + + memcpy(cp.dev_class, &class, 3); + + if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, + WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0) + return -errno; + + dev->pending_cod = class; + + return 0; +} + +static int hciops_set_dev_class(int index, uint8_t major, uint8_t minor) +{ + struct dev_info *dev = &devs[index]; + int err; + + DBG("hci%d major %u minor %u", index, major, minor); + + /* Update only the major and minor class bits keeping remaining bits + * intact*/ + dev->wanted_cod &= 0xffe000; + dev->wanted_cod |= ((major & 0x1f) << 8) | minor; + + if (dev->wanted_cod == dev->current_cod || + dev->cache_enable || dev->pending_cod) + return 0; + + DBG("Changing Major/Minor class to 0x%06x", dev->wanted_cod); + + err = write_class(index, dev->wanted_cod); + if (err < 0) + error("Adapter class update failed: %s (%d)", + strerror(-err), -err); + + return err; +} + static gboolean init_adapter(int index) { struct dev_info *dev = &devs[index]; struct btd_adapter *adapter = NULL; gboolean existing_adapter = dev->registered; - uint8_t mode, on_mode; + uint8_t mode, on_mode, major, minor; gboolean pairable, discoverable; + const char *name; if (!dev->registered) { adapter = btd_manager_register_adapter(index, TRUE); @@ -679,6 +777,14 @@ static gboolean init_adapter(int index) } start_adapter(index); + + name = btd_adapter_get_name(adapter); + if (name) + hciops_set_name(index, name); + + btd_adapter_get_class(adapter, &major, &minor); + hciops_set_dev_class(index, major, minor); + btd_adapter_start(adapter); discoverable = (mode == MODE_DISCOVERABLE); @@ -1495,39 +1601,6 @@ static void read_local_features_complete(int index, init_adapter(index); } -static void update_ext_inquiry_response(int index) -{ - struct dev_info *dev = &devs[index]; - write_ext_inquiry_response_cp cp; - - DBG("hci%d", index); - - if (!(dev->features[6] & LMP_EXT_INQ)) - return; - - if (dev->ssp_mode == 0) - return; - - if (dev->cache_enable) - return; - - memset(&cp, 0, sizeof(cp)); - - eir_create(dev->name, dev->tx_power, dev->did_vendor, dev->did_product, - dev->did_version, dev->uuids, cp.data); - - if (memcmp(cp.data, dev->eir, sizeof(cp.data)) == 0) - return; - - memcpy(dev->eir, cp.data, sizeof(cp.data)); - - if (hci_send_cmd(dev->sk, OGF_HOST_CTL, - OCF_WRITE_EXT_INQUIRY_RESPONSE, - WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0) - error("Unable to write EIR data: %s (%d)", - strerror(errno), errno); -} - static void update_name(int index, const char *name) { struct btd_adapter *adapter; @@ -1666,24 +1739,6 @@ static void read_scan_complete(int index, uint8_t status, void *ptr) adapter_mode_changed(adapter, rp->enable); } -static int write_class(int index, uint32_t class) -{ - struct dev_info *dev = &devs[index]; - write_class_of_dev_cp cp; - - DBG("hci%d class 0x%06x", index, class); - - memcpy(cp.dev_class, &class, 3); - - if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV, - WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0) - return -errno; - - dev->pending_cod = class; - - return 0; -} - /* Limited Discoverable bit mask in CoD */ #define LIMITED_BIT 0x002000 @@ -3034,32 +3089,6 @@ static int hciops_set_powered(int index, gboolean powered) return err; } -static int hciops_set_dev_class(int index, uint8_t major, uint8_t minor) -{ - struct dev_info *dev = &devs[index]; - int err; - - DBG("hci%d major %u minor %u", index, major, minor); - - /* Update only the major and minor class bits keeping remaining bits - * intact*/ - dev->wanted_cod &= 0xffe000; - dev->wanted_cod |= ((major & 0x1f) << 8) | minor; - - if (dev->wanted_cod == dev->current_cod || - dev->cache_enable || dev->pending_cod) - return 0; - - DBG("Changing Major/Minor class to 0x%06x", dev->wanted_cod); - - err = write_class(index, dev->wanted_cod); - if (err < 0) - error("Adapter class update failed: %s (%d)", - strerror(-err), -err); - - return err; -} - static int start_inquiry(int index, uint8_t length) { struct dev_info *dev = &devs[index]; @@ -3157,26 +3186,6 @@ static int hciops_stop_scanning(int index) return le_set_scan_enable(index, 0); } -static int hciops_set_name(int index, const char *name) -{ - struct dev_info *dev = &devs[index]; - change_local_name_cp cp; - - DBG("hci%d, name %s", index, name); - - memset(&cp, 0, sizeof(cp)); - strncpy((char *) cp.name, name, sizeof(cp.name)); - - if (hci_send_cmd(dev->sk, OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME, - CHANGE_LOCAL_NAME_CP_SIZE, &cp) < 0) - return -errno; - - memcpy(dev->name, cp.name, 248); - update_ext_inquiry_response(index); - - return 0; -} - static int cancel_resolve_name(int index) { struct dev_info *info = &devs[index]; diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c index 0b5a9408..975f17eb 100644 --- a/plugins/mgmtops.c +++ b/plugins/mgmtops.c @@ -971,12 +971,64 @@ static int mgmt_set_powered(int index, gboolean powered) return mgmt_set_mode(index, MGMT_OP_SET_POWERED, powered); } +static int mgmt_set_name(int index, const char *name) +{ + char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_local_name)]; + struct mgmt_hdr *hdr = (void *) buf; + struct mgmt_cp_set_local_name *cp = (void *) &buf[sizeof(*hdr)]; + + DBG("index %d, name %s", index, name); + + memset(buf, 0, sizeof(buf)); + hdr->opcode = htobs(MGMT_OP_SET_LOCAL_NAME); + hdr->len = htobs(sizeof(*cp)); + hdr->index = htobs(index); + + strncpy((char *) cp->name, name, sizeof(cp->name) - 1); + + if (write(mgmt_sock, buf, sizeof(buf)) < 0) + return -errno; + + return 0; +} + +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)]; + struct controller_info *info = &controllers[index]; + + DBG("index %d major %u minor %u", index, major, minor); + + if (info->pending_uuid) { + info->major = major; + info->minor = minor; + info->pending_class = TRUE; + return 0; + } + + memset(buf, 0, sizeof(buf)); + hdr->opcode = htobs(MGMT_OP_SET_DEV_CLASS); + hdr->len = htobs(sizeof(*cp)); + hdr->index = htobs(index); + + cp->major = major; + cp->minor = minor; + + if (write(mgmt_sock, buf, sizeof(buf)) < 0) + return -errno; + + return 0; +} + static void read_info_complete(int sk, uint16_t index, void *buf, size_t len) { struct mgmt_rp_read_info *rp = buf; struct controller_info *info; struct btd_adapter *adapter; - uint8_t mode; + const char *name; + uint8_t mode, major, minor; char addr[18]; if (len < sizeof(*rp)) { @@ -1021,7 +1073,17 @@ static void read_info_complete(int sk, uint16_t index, void *buf, size_t len) update_settings(adapter, info->current_settings); - adapter_name_changed(adapter, (char *) rp->name); + name = btd_adapter_get_name(adapter); + + error("mgmtops setting name %s", name); + + if (name) + mgmt_set_name(index, name); + else + adapter_name_changed(adapter, (char *) rp->name); + + btd_adapter_get_class(adapter, &major, &minor); + mgmt_set_dev_class(index, major, minor); btd_adapter_get_mode(adapter, &mode, NULL, NULL); if (mode == MODE_OFF && mgmt_powered(info->current_settings)) { @@ -1203,36 +1265,6 @@ static void read_local_oob_data_failed(int sk, uint16_t index) oob_read_local_data_complete(adapter, NULL, NULL); } -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)]; - struct controller_info *info = &controllers[index]; - - DBG("index %d major %u minor %u", index, major, minor); - - if (info->pending_uuid) { - info->major = major; - info->minor = minor; - info->pending_class = TRUE; - return 0; - } - - memset(buf, 0, sizeof(buf)); - hdr->opcode = htobs(MGMT_OP_SET_DEV_CLASS); - hdr->len = htobs(sizeof(*cp)); - hdr->index = htobs(index); - - cp->major = major; - cp->minor = minor; - - if (write(mgmt_sock, buf, sizeof(buf)) < 0) - return -errno; - - return 0; -} - static void mgmt_add_uuid_complete(int sk, uint16_t index, void *buf, size_t len) { @@ -1902,27 +1934,6 @@ static int mgmt_stop_discovery(int index) return 0; } -static int mgmt_set_name(int index, const char *name) -{ - char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_local_name)]; - struct mgmt_hdr *hdr = (void *) buf; - struct mgmt_cp_set_local_name *cp = (void *) &buf[sizeof(*hdr)]; - - DBG("index %d, name %s", index, name); - - memset(buf, 0, sizeof(buf)); - hdr->opcode = htobs(MGMT_OP_SET_LOCAL_NAME); - hdr->len = htobs(sizeof(*cp)); - hdr->index = htobs(index); - - strncpy((char *) cp->name, name, sizeof(cp->name) - 1); - - if (write(mgmt_sock, buf, sizeof(buf)) < 0) - return -errno; - - return 0; -} - static int mgmt_set_fast_connectable(int index, gboolean enable) { char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_mode)]; diff --git a/src/adapter.c b/src/adapter.c index 6cbf27ac..d9ab4fda 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -168,9 +168,9 @@ static void dev_info_free(void *data) } int btd_adapter_set_class(struct btd_adapter *adapter, uint8_t major, - uint8_t minor) + uint8_t minor) { - return adapter_ops->set_dev_class(adapter->dev_id, major, minor); + return adapter_ops->set_dev_class(adapter->dev_id, major, minor); } static const char *mode2str(uint8_t mode) @@ -811,6 +811,9 @@ int adapter_set_name(struct btd_adapter *adapter, const char *name) int err = adapter_ops->set_name(adapter->dev_id, maxname); if (err < 0) return err; + } else { + g_free(adapter->name); + adapter->name = g_strdup(maxname); } write_local_name(&adapter->bdaddr, maxname); @@ -2213,10 +2216,28 @@ void btd_adapter_get_mode(struct btd_adapter *adapter, uint8_t *mode, *pairable = adapter->pairable; } +void btd_adapter_get_class(struct btd_adapter *adapter, uint8_t *major, + uint8_t *minor) +{ + uint8_t cls[3]; + + if (read_local_class(&adapter->bdaddr, cls) < 0) { + uint32_t class = htobl(main_opts.class); + memcpy(cls, &class, 3); + } + + *major = cls[1]; + *minor = cls[0]; +} + +const char *btd_adapter_get_name(struct btd_adapter *adapter) +{ + return adapter->name; +} + void btd_adapter_start(struct btd_adapter *adapter) { char address[18]; - uint8_t cls[3]; gboolean powered; ba2str(&adapter->bdaddr, address); @@ -2229,17 +2250,6 @@ void btd_adapter_start(struct btd_adapter *adapter) adapter->mode = MODE_CONNECTABLE; adapter->off_timer = 0; - /* Forcing: Name is lost when adapter is powered off */ - if (adapter->name) - adapter_ops->set_name(adapter->dev_id, adapter->name); - - if (read_local_class(&adapter->bdaddr, cls) < 0) { - uint32_t class = htobl(main_opts.class); - memcpy(cls, &class, 3); - } - - btd_adapter_set_class(adapter, cls[1], cls[0]); - powered = TRUE; emit_property_changed(connection, adapter->path, ADAPTER_INTERFACE, "Powered", diff --git a/src/adapter.h b/src/adapter.h index 22bb0bba..e6ee2da8 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -89,6 +89,9 @@ int btd_adapter_stop(struct btd_adapter *adapter); void btd_adapter_get_mode(struct btd_adapter *adapter, uint8_t *mode, uint8_t *on_mode, gboolean *pairable); +void btd_adapter_get_class(struct btd_adapter *adapter, uint8_t *major, + uint8_t *minor); +const char *btd_adapter_get_name(struct btd_adapter *adapter); struct btd_device *adapter_get_device(DBusConnection *conn, struct btd_adapter *adapter, const char *address); |