From 89ae2d2c0f78019882b35c85bde0103a0ba12773 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 13 Dec 2011 11:20:06 +0200 Subject: [PATCH] mgmt: Update read_info & related messages to match the API spec --- lib/mgmt.h | 29 ++-- mgmt/main.c | 87 ++++++++--- plugins/mgmtops.c | 383 +++++++++++++--------------------------------- 3 files changed, 192 insertions(+), 307 deletions(-) diff --git a/lib/mgmt.h b/lib/mgmt.h index 396081516..ca082140b 100644 --- a/lib/mgmt.h +++ b/lib/mgmt.h @@ -54,22 +54,29 @@ struct mgmt_rp_read_index_list { /* Reserve one extra byte for names in management messages so that they * are always guaranteed to be nul-terminated */ #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) +#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) + +#define MGMT_SETTING_POWERED 0x00000001 +#define MGMT_SETTING_CONNECTABLE 0x00000002 +#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004 +#define MGMT_SETTING_DISCOVERABLE 0x00000008 +#define MGMT_SETTING_PAIRABLE 0x00000010 +#define MGMT_SETTING_LINK_SECURITY 0x00000020 +#define MGMT_SETTING_SSP 0x00000040 +#define MGMT_SETTING_BREDR 0x00000080 +#define MGMT_SETTING_HS 0x00000100 +#define MGMT_SETTING_LE 0x00000200 #define MGMT_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { - uint8_t type; - uint8_t powered; - uint8_t connectable; - uint8_t discoverable; - uint8_t pairable; - uint8_t sec_mode; bdaddr_t bdaddr; - uint8_t dev_class[3]; - uint8_t features[8]; + uint8_t version; uint16_t manufacturer; - uint8_t hci_ver; - uint16_t hci_rev; + uint32_t supported_settings; + uint32_t current_settings; + uint8_t dev_class[3]; uint8_t name[MGMT_MAX_NAME_LENGTH]; + uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH]; } __packed; struct mgmt_mode { @@ -263,7 +270,7 @@ struct mgmt_ev_controller_error { #define MGMT_EV_INDEX_REMOVED 0x0005 -#define MGMT_EV_POWERED 0x0006 +#define MGMT_EV_NEW_SETTINGS 0x0006 #define MGMT_EV_DISCOVERABLE 0x0007 diff --git a/mgmt/main.c b/mgmt/main.c index 91ce10279..225ed7413 100644 --- a/mgmt/main.c +++ b/mgmt/main.c @@ -320,20 +320,60 @@ static int mgmt_index_removed(int mgmt_sk, uint16_t index) return 0; } -static int mgmt_setting(int mgmt_sk, uint16_t index, uint16_t op, +static const char *settings_str[] = { + "powered", + "connectable", + "fast-connectable", + "discoverable", + "pairable", + "link-security", + "ssp", + "br/edr", + "hs", + "le" , +}; + +static void print_settings(uint32_t settings) +{ + unsigned i; + + for (i = 0; i < NELEM(settings_str); i++) { + if ((settings & (1 << i)) != 0) + printf("%s ", settings_str[i]); + } +} + +static int mgmt_new_settings(int mgmt_sk, uint16_t index, + uint32_t *ev, uint16_t len) +{ + if (len < sizeof(*ev)) { + fprintf(stderr, "Too short new_settings event (%u)\n", len); + return -EINVAL; + } + + if (monitor) { + printf("hci%u new_settings: ", index); + print_settings(bt_get_le32(ev)); + printf("\n"); + } + + return 0; +} + +static int mgmt_discovering(int mgmt_sk, uint16_t index, struct mgmt_mode *ev, uint16_t len) { if (len < sizeof(*ev)) { - fprintf(stderr, "Too short (%u bytes) %s event\n", - len, mgmt_evstr(op)); + fprintf(stderr, "Too short (%u bytes) discovering event\n", + len); return -EINVAL; } - if (op == MGMT_EV_DISCOVERING && ev->val == 0 && discovery) + if (ev->val == 0 && discovery) exit(EXIT_SUCCESS); if (monitor) - printf("hci%u %s %s\n", index, mgmt_evstr(op), + printf("hci%u discovering %s\n", index, ev->val ? "on" : "off"); return 0; @@ -689,12 +729,10 @@ static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index, return mgmt_index_added(mgmt_sk, index); case MGMT_EV_INDEX_REMOVED: return mgmt_index_removed(mgmt_sk, index); - case MGMT_EV_POWERED: - case MGMT_EV_DISCOVERABLE: - case MGMT_EV_CONNECTABLE: - case MGMT_EV_PAIRABLE: + case MGMT_EV_NEW_SETTINGS: + return mgmt_new_settings(mgmt_sk, index, data, len); case MGMT_EV_DISCOVERING: - return mgmt_setting(mgmt_sk, index, ev, data, len); + return mgmt_discovering(mgmt_sk, index, data, len); case MGMT_EV_NEW_LINK_KEY: return mgmt_new_link_key(mgmt_sk, index, data, len); case MGMT_EV_DEVICE_CONNECTED: @@ -783,16 +821,19 @@ static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status, } ba2str(&rp->bdaddr, addr); - printf("hci%u:\ttype %u addr %s class 0x%02x%02x%02x\n", - id, rp->type, addr, - rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]); - printf("\tmanufacturer %d HCI ver %d:%d\n", - bt_get_le16(&rp->manufacturer), - rp->hci_ver, bt_get_le16(&rp->hci_rev)); - printf("\tpowered %u connectable %u discoverable %u\n", - rp->powered, rp->connectable, rp->discoverable); - printf("\tpairable %u sec_mode %u\n", rp->pairable, rp->sec_mode); - printf("\tname %s\n\n", (char *) rp->name); + printf("hci%u:\taddr %s version %u manufacturer %u" + " class 0x%02x%02x%02x\n", + id, addr, rp->version, bt_get_le16(&rp->manufacturer), + rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]); + + printf("\tsupported settings: "); + print_settings(bt_get_le32(&rp->supported_settings)); + + printf("\n\tcurrent settings: "); + print_settings(bt_get_le32(&rp->current_settings)); + + printf("\n\tname %s\n", rp->name); + printf("\tshort name %s\n", rp->short_name); if (pending == NULL) exit(EXIT_SUCCESS); @@ -879,7 +920,7 @@ static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv) static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status, void *rsp, uint16_t len, void *user_data) { - struct mgmt_mode *rp = rsp; + uint32_t *rp = rsp; if (status != 0) { fprintf(stderr, @@ -894,7 +935,9 @@ static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status, exit(EXIT_FAILURE); } - printf("hci%u %s %s\n", id, mgmt_opstr(op), rp->val ? "on" : "off"); + printf("hci%u %s complete, settings: ", id, mgmt_opstr(op)); + print_settings(bt_get_le32(rp)); + printf("\n"); exit(EXIT_SUCCESS); } diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c index b9e9ad634..ff208223d 100644 --- a/plugins/mgmtops.c +++ b/plugins/mgmtops.c @@ -55,18 +55,12 @@ static int max_index = -1; static struct controller_info { gboolean valid; gboolean notified; - uint8_t type; bdaddr_t bdaddr; - uint8_t features[8]; - uint8_t dev_class[3]; + uint8_t version; uint16_t manufacturer; - uint8_t hci_ver; - uint16_t hci_rev; - gboolean enabled; - gboolean connectable; - gboolean discoverable; - gboolean pairable; - uint8_t sec_mode; + uint32_t supported_settings; + uint32_t current_settings; + uint8_t dev_class[3]; GSList *connections; } *controllers = NULL; @@ -218,179 +212,142 @@ static int mgmt_set_pairable(int index, gboolean pairable) return mgmt_set_mode(index, MGMT_OP_SET_PAIRABLE, pairable); } -static int mgmt_update_powered(int index, uint8_t powered) +static inline int mgmt_powered(uint32_t settings) { - struct controller_info *info; - struct btd_adapter *adapter; - gboolean pairable; - uint8_t on_mode; - - if (index > max_index) { - error("Unexpected index %u", index); - return -ENODEV; - } - - info = &controllers[index]; - - info->enabled = powered; - - adapter = manager_find_adapter(&info->bdaddr); - if (adapter == NULL) { - DBG("Adapter not found"); - return -ENODEV; - } - - if (!powered) { - info->connectable = FALSE; - info->pairable = FALSE; - info->discoverable = FALSE; + return (settings & MGMT_SETTING_POWERED) != 0; +} - btd_adapter_stop(adapter); - return 0; - } +static inline int mgmt_connectable(uint32_t settings) +{ + return (settings & MGMT_SETTING_CONNECTABLE) != 0; +} - btd_adapter_start(adapter); +static inline int mgmt_fast_connectable(uint32_t settings) +{ + return (settings & MGMT_SETTING_FAST_CONNECTABLE) != 0; +} - btd_adapter_get_mode(adapter, NULL, &on_mode, &pairable); +static inline int mgmt_discoverable(uint32_t settings) +{ + return (settings & MGMT_SETTING_DISCOVERABLE) != 0; +} - if (on_mode == MODE_DISCOVERABLE && !info->discoverable) - mgmt_set_discoverable(index, TRUE); - else if (on_mode == MODE_CONNECTABLE && !info->connectable) - mgmt_set_connectable(index, TRUE); - else { - uint8_t mode = 0; +static inline int mgmt_pairable(uint32_t settings) +{ + return (settings & MGMT_SETTING_PAIRABLE) != 0; +} - if (info->connectable) - mode |= SCAN_PAGE; - if (info->discoverable) - mode |= SCAN_INQUIRY; +static inline int mgmt_ssp(uint32_t settings) +{ + return (settings & MGMT_SETTING_SSP) != 0; +} - adapter_mode_changed(adapter, mode); - } +static inline int mgmt_bredr(uint32_t settings) +{ + return (settings & MGMT_SETTING_BREDR) != 0; +} - if (info->pairable != pairable) - mgmt_set_pairable(index, pairable); +static inline int mgmt_high_speed(uint32_t settings) +{ + return (settings & MGMT_SETTING_HS) != 0; +} - return 0; +static inline int mgmt_low_energy(uint32_t settings) +{ + return (settings & MGMT_SETTING_LE) != 0; } -static void mgmt_powered(int sk, uint16_t index, void *buf, size_t len) +static uint8_t create_mode(uint32_t settings) { - struct mgmt_mode *ev = buf; + uint8_t mode = 0; - if (len < sizeof(*ev)) { - error("Too small powered event"); - return; - } + if (mgmt_connectable(settings)) + mode |= SCAN_PAGE; - DBG("Controller %u powered %u", index, ev->val); + if (mgmt_discoverable(settings)) + mode |= SCAN_INQUIRY; - mgmt_update_powered(index, ev->val); + return mode; } -static void mgmt_discoverable(int sk, uint16_t index, void *buf, size_t len) +static int mgmt_update_powered(struct btd_adapter *adapter, uint32_t settings) { - struct mgmt_mode *ev = buf; - struct controller_info *info; - struct btd_adapter *adapter; - uint8_t mode; - - if (len < sizeof(*ev)) { - error("Too small discoverable event"); - return; - } - - DBG("Controller %u discoverable %u", index, ev->val); + gboolean pairable; + uint8_t on_mode; + uint16_t index; - if (index > max_index) { - error("Unexpected index %u in discoverable event", index); - return; + if (!mgmt_powered(settings)) { + btd_adapter_stop(adapter); + return 0; } - info = &controllers[index]; + btd_adapter_start(adapter); - info->discoverable = ev->val ? TRUE : FALSE; + btd_adapter_get_mode(adapter, NULL, &on_mode, &pairable); - adapter = manager_find_adapter(&info->bdaddr); - if (!adapter) - return; + index = adapter_get_dev_id(adapter); - if (info->connectable) - mode = SCAN_PAGE; + if (on_mode == MODE_DISCOVERABLE && !mgmt_discoverable(settings)) + mgmt_set_discoverable(index, TRUE); + else if (on_mode == MODE_CONNECTABLE && !mgmt_connectable(settings)) + mgmt_set_connectable(index, TRUE); else - mode = 0; + adapter_mode_changed(adapter, create_mode(settings)); - if (info->discoverable) - mode |= SCAN_INQUIRY; + if (mgmt_pairable(settings) != pairable) + mgmt_set_pairable(index, pairable); - adapter_mode_changed(adapter, mode); + return 0; } -static void mgmt_connectable(int sk, uint16_t index, void *buf, size_t len) +static int mode_changed(uint32_t s1, uint32_t s2) { - struct mgmt_mode *ev = buf; - struct controller_info *info; - struct btd_adapter *adapter; - uint8_t mode; - - if (len < sizeof(*ev)) { - error("Too small connectable event"); - return; - } - - DBG("Controller %u connectable %u", index, ev->val); - - if (index > max_index) { - error("Unexpected index %u in connectable event", index); - return; - } - - info = &controllers[index]; - - info->connectable = ev->val ? TRUE : FALSE; - - adapter = manager_find_adapter(&info->bdaddr); - if (!adapter) - return; + if (mgmt_connectable(s1) != mgmt_connectable(s2)) + return 1; - if (info->discoverable) - mode = SCAN_INQUIRY; - else - mode = 0; - - if (info->connectable) - mode |= SCAN_PAGE; + if (mgmt_discoverable(s1) != mgmt_discoverable(s2)) + return 1; - adapter_mode_changed(adapter, mode); + return 0; } -static void mgmt_pairable(int sk, uint16_t index, void *buf, size_t len) +static void mgmt_new_settings(int sk, uint16_t index, void *buf, size_t len) { - struct mgmt_mode *ev = buf; + uint32_t settings, *ev = buf; struct controller_info *info; struct btd_adapter *adapter; if (len < sizeof(*ev)) { - error("Too small pairable event"); + error("Too small new settings event"); return; } - DBG("Controller %u pairable %u", index, ev->val); + DBG("hci%u new settings", index); if (index > max_index) { - error("Unexpected index %u in pairable event", index); + error("Unexpected index %u in new_settings event", index); return; } info = &controllers[index]; - info->pairable = ev->val ? TRUE : FALSE; - adapter = manager_find_adapter(&info->bdaddr); - if (!adapter) + if (adapter == NULL) { + DBG("Adapter not found"); return; + } + + settings = bt_get_le32(ev); + + if (mgmt_powered(settings) != mgmt_powered(info->current_settings)) + mgmt_update_powered(adapter, settings); + else if (mode_changed(settings, info->current_settings)) + adapter_mode_changed(adapter, create_mode(settings)); + + if (mgmt_pairable(settings) != mgmt_pairable(info->current_settings)) + btd_adapter_pairable_changed(adapter, mgmt_pairable(settings)); - btd_adapter_pairable_changed(adapter, info->pairable); + info->current_settings = settings; } static void mgmt_new_link_key(int sk, uint16_t index, void *buf, size_t len) @@ -810,29 +767,25 @@ static void read_info_complete(int sk, uint16_t index, void *buf, size_t len) mgmt_set_mode(index, MGMT_OP_SET_SERVICE_CACHE, 1); info = &controllers[index]; - info->type = rp->type; - info->enabled = rp->powered; - info->connectable = rp->connectable; - info->discoverable = rp->discoverable; - info->pairable = rp->pairable; - info->sec_mode = rp->sec_mode; + bacpy(&info->bdaddr, &rp->bdaddr); - memcpy(info->dev_class, rp->dev_class, 3); - memcpy(info->features, rp->features, 8); + info->version = rp->version; info->manufacturer = btohs(bt_get_unaligned(&rp->manufacturer)); - info->hci_ver = rp->hci_ver; - info->hci_rev = btohs(bt_get_unaligned(&rp->hci_rev)); + + memcpy(&info->supported_settings, &rp->supported_settings, + sizeof(info->supported_settings)); + memcpy(&info->current_settings, &rp->current_settings, + sizeof(info->current_settings)); + + memcpy(info->dev_class, rp->dev_class, sizeof(info->dev_class)); ba2str(&info->bdaddr, addr); - DBG("hci%u type %u addr %s", index, info->type, addr); - DBG("hci%u class 0x%02x%02x%02x", index, + DBG("hci%u addr %s version %u manufacturer %u class 0x%02x%02x%02x\n", + index, addr, info->version, info->manufacturer, info->dev_class[2], info->dev_class[1], info->dev_class[0]); - DBG("hci%u manufacturer %d HCI ver %d:%d", index, info->manufacturer, - info->hci_ver, info->hci_rev); - DBG("hci%u enabled %u discoverable %u pairable %u sec_mode %u", index, - info->enabled, info->discoverable, - info->pairable, info->sec_mode); + DBG("hci%u settings", index); DBG("hci%u name %s", index, (char *) rp->name); + DBG("hci%u short name %s", index, (char *) rp->short_name); adapter = btd_manager_register_adapter(index); if (adapter == NULL) { @@ -846,8 +799,8 @@ static void read_info_complete(int sk, uint16_t index, void *buf, size_t len) return; } - if (info->enabled) - mgmt_update_powered(index, TRUE); + if (mgmt_powered(info->current_settings)) + mgmt_update_powered(adapter, info->current_settings); else mgmt_set_powered(index, TRUE); @@ -856,115 +809,6 @@ static void read_info_complete(int sk, uint16_t index, void *buf, size_t len) btd_adapter_unref(adapter); } -static void set_powered_complete(int sk, uint16_t index, void *buf, size_t len) -{ - struct mgmt_mode *rp = buf; - - if (len < sizeof(*rp)) { - error("Too small set powered complete event"); - return; - } - - DBG("hci%d powered %u", index, rp->val); - - mgmt_update_powered(index, rp->val); -} - -static void set_discoverable_complete(int sk, uint16_t index, void *buf, - size_t len) -{ - struct mgmt_mode *rp = buf; - struct controller_info *info; - struct btd_adapter *adapter; - uint8_t mode; - - if (len < sizeof(*rp)) { - error("Too small set discoverable complete event"); - return; - } - - DBG("hci%d discoverable %u", index, rp->val); - - if (index > max_index) { - error("Unexpected index %u in discoverable complete", index); - return; - } - - info = &controllers[index]; - - info->discoverable = rp->val ? TRUE : FALSE; - - adapter = manager_find_adapter(&info->bdaddr); - if (!adapter) - return; - - /* set_discoverable will always also change page scanning */ - mode = SCAN_PAGE; - - if (info->discoverable) - mode |= SCAN_INQUIRY; - - adapter_mode_changed(adapter, mode); -} - -static void set_connectable_complete(int sk, uint16_t index, void *buf, - size_t len) -{ - struct mgmt_mode *rp = buf; - struct controller_info *info; - struct btd_adapter *adapter; - - if (len < sizeof(*rp)) { - error("Too small set connectable complete event"); - return; - } - - DBG("hci%d connectable %u", index, rp->val); - - if (index > max_index) { - error("Unexpected index %u in connectable complete", index); - return; - } - - info = &controllers[index]; - - info->connectable = rp->val ? TRUE : FALSE; - - adapter = manager_find_adapter(&info->bdaddr); - if (adapter) - adapter_mode_changed(adapter, rp->val ? SCAN_PAGE : 0); -} - -static void set_pairable_complete(int sk, uint16_t index, void *buf, - size_t len) -{ - struct mgmt_mode *rp = buf; - struct controller_info *info; - struct btd_adapter *adapter; - - if (len < sizeof(*rp)) { - error("Too small set pairable complete event"); - return; - } - - DBG("hci%d pairable %u", index, rp->val); - - if (index > max_index) { - error("Unexpected index %u in pairable complete", index); - return; - } - - info = &controllers[index]; - - info->pairable = rp->val ? TRUE : FALSE; - - adapter = manager_find_adapter(&info->bdaddr); - if (!adapter) - return; - - btd_adapter_pairable_changed(adapter, info->pairable); -} - static void disconnect_complete(int sk, uint16_t index, void *buf, size_t len) { struct mgmt_rp_disconnect *rp = buf; @@ -1158,16 +1002,16 @@ static void mgmt_cmd_complete(int sk, uint16_t index, void *buf, size_t len) read_info_complete(sk, index, ev->data, len); break; case MGMT_OP_SET_POWERED: - set_powered_complete(sk, index, ev->data, len); + mgmt_new_settings(sk, index, ev->data, len); break; case MGMT_OP_SET_DISCOVERABLE: - set_discoverable_complete(sk, index, ev->data, len); + mgmt_new_settings(sk, index, ev->data, len); break; case MGMT_OP_SET_CONNECTABLE: - set_connectable_complete(sk, index, ev->data, len); + mgmt_new_settings(sk, index, ev->data, len); break; case MGMT_OP_SET_PAIRABLE: - set_pairable_complete(sk, index, ev->data, len); + mgmt_new_settings(sk, index, ev->data, len); break; case MGMT_OP_ADD_UUID: DBG("add_uuid complete"); @@ -1525,17 +1369,8 @@ static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data case MGMT_EV_INDEX_REMOVED: mgmt_index_removed(sk, index); break; - case MGMT_EV_POWERED: - mgmt_powered(sk, index, buf + MGMT_HDR_SIZE, len); - break; - case MGMT_EV_DISCOVERABLE: - mgmt_discoverable(sk, index, buf + MGMT_HDR_SIZE, len); - break; - case MGMT_EV_CONNECTABLE: - mgmt_connectable(sk, index, buf + MGMT_HDR_SIZE, len); - break; - case MGMT_EV_PAIRABLE: - mgmt_pairable(sk, index, buf + MGMT_HDR_SIZE, len); + case MGMT_EV_NEW_SETTINGS: + mgmt_new_settings(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_NEW_LINK_KEY: mgmt_new_link_key(sk, index, buf + MGMT_HDR_SIZE, len); -- 2.47.3