···490490}491491EXPORT_SYMBOL(bt_sock_ioctl);492492493493+/* This function expects the sk lock to be held when called */493494int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)494495{495496 DECLARE_WAITQUEUE(wait, current);···525524 return err;526525}527526EXPORT_SYMBOL(bt_sock_wait_state);527527+528528+/* This function expects the sk lock to be held when called */529529+int bt_sock_wait_ready(struct sock *sk, unsigned long flags)530530+{531531+ DECLARE_WAITQUEUE(wait, current);532532+ unsigned long timeo;533533+ int err = 0;534534+535535+ BT_DBG("sk %p", sk);536536+537537+ timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);538538+539539+ add_wait_queue(sk_sleep(sk), &wait);540540+ set_current_state(TASK_INTERRUPTIBLE);541541+ while (test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags)) {542542+ if (!timeo) {543543+ err = -EAGAIN;544544+ break;545545+ }546546+547547+ if (signal_pending(current)) {548548+ err = sock_intr_errno(timeo);549549+ break;550550+ }551551+552552+ release_sock(sk);553553+ timeo = schedule_timeout(timeo);554554+ lock_sock(sk);555555+ set_current_state(TASK_INTERRUPTIBLE);556556+557557+ err = sock_error(sk);558558+ if (err)559559+ break;560560+ }561561+ __set_current_state(TASK_RUNNING);562562+ remove_wait_queue(sk_sleep(sk), &wait);563563+564564+ return err;565565+}566566+EXPORT_SYMBOL(bt_sock_wait_ready);528567529568#ifdef CONFIG_PROC_FS530569struct bt_seq_state {
···3232#include <net/bluetooth/mgmt.h>3333#include <net/bluetooth/smp.h>34343535-bool enable_hs;3636-3735#define MGMT_VERSION 13838-#define MGMT_REVISION 33636+#define MGMT_REVISION 439374038static const u16 mgmt_commands[] = {4139 MGMT_OP_READ_INDEX_LIST,···7476 MGMT_OP_BLOCK_DEVICE,7577 MGMT_OP_UNBLOCK_DEVICE,7678 MGMT_OP_SET_DEVICE_ID,7979+ MGMT_OP_SET_ADVERTISING,8080+ MGMT_OP_SET_BREDR,8181+ MGMT_OP_SET_STATIC_ADDRESS,7782};78837984static const u16 mgmt_events[] = {···340339 if (test_bit(HCI_SETUP, &d->dev_flags))341340 continue;342341342342+ if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))343343+ continue;344344+343345 if (!mgmt_valid_hdev(d))344346 continue;345347···380376 settings |= MGMT_SETTING_DISCOVERABLE;381377 settings |= MGMT_SETTING_BREDR;382378 settings |= MGMT_SETTING_LINK_SECURITY;379379+ settings |= MGMT_SETTING_HS;383380 }384381385385- if (enable_hs)386386- settings |= MGMT_SETTING_HS;387387-388388- if (lmp_le_capable(hdev))382382+ if (lmp_le_capable(hdev)) {389383 settings |= MGMT_SETTING_LE;384384+ settings |= MGMT_SETTING_ADVERTISING;385385+ }390386391387 return settings;392388}···410406 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))411407 settings |= MGMT_SETTING_PAIRABLE;412408413413- if (lmp_bredr_capable(hdev))409409+ if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))414410 settings |= MGMT_SETTING_BREDR;415411416412 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))···424420425421 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))426422 settings |= MGMT_SETTING_HS;423423+424424+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))425425+ settings |= MGMT_SETTING_ADVERTISING;427426428427 return settings;429428}···811804812805 hci_dev_lock(hdev);813806807807+ if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {808808+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,809809+ MGMT_STATUS_BUSY);810810+ goto failed;811811+ }812812+814813 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {815814 cancel_delayed_work(&hdev->power_off);816815···830817831818 if (!!cp->val == hdev_is_powered(hdev)) {832819 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);833833- goto failed;834834- }835835-836836- if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {837837- err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,838838- MGMT_STATUS_BUSY);839820 goto failed;840821 }841822···890883 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);891884}892885886886+struct cmd_lookup {887887+ struct sock *sk;888888+ struct hci_dev *hdev;889889+ u8 mgmt_status;890890+};891891+892892+static void settings_rsp(struct pending_cmd *cmd, void *data)893893+{894894+ struct cmd_lookup *match = data;895895+896896+ send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);897897+898898+ list_del(&cmd->list);899899+900900+ if (match->sk == NULL) {901901+ match->sk = cmd->sk;902902+ sock_hold(match->sk);903903+ }904904+905905+ mgmt_pending_free(cmd);906906+}907907+908908+static void cmd_status_rsp(struct pending_cmd *cmd, void *data)909909+{910910+ u8 *status = data;911911+912912+ cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);913913+ mgmt_pending_remove(cmd);914914+}915915+916916+static u8 mgmt_bredr_support(struct hci_dev *hdev)917917+{918918+ if (!lmp_bredr_capable(hdev))919919+ return MGMT_STATUS_NOT_SUPPORTED;920920+ else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))921921+ return MGMT_STATUS_REJECTED;922922+ else923923+ return MGMT_STATUS_SUCCESS;924924+}925925+926926+static u8 mgmt_le_support(struct hci_dev *hdev)927927+{928928+ if (!lmp_le_capable(hdev))929929+ return MGMT_STATUS_NOT_SUPPORTED;930930+ else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))931931+ return MGMT_STATUS_REJECTED;932932+ else933933+ return MGMT_STATUS_SUCCESS;934934+}935935+893936static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,894937 u16 len)895938{896939 struct mgmt_cp_set_discoverable *cp = data;897940 struct pending_cmd *cmd;898941 u16 timeout;899899- u8 scan;942942+ u8 scan, status;900943 int err;901944902945 BT_DBG("request for %s", hdev->name);903946904904- if (!lmp_bredr_capable(hdev))947947+ status = mgmt_bredr_support(hdev);948948+ if (status)905949 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,906906- MGMT_STATUS_NOT_SUPPORTED);950950+ status);907951908952 if (cp->val != 0x00 && cp->val != 0x01)909953 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,···11031045 struct mgmt_mode *cp = data;11041046 struct pending_cmd *cmd;11051047 struct hci_request req;11061106- u8 scan;10481048+ u8 scan, status;11071049 int err;1108105011091051 BT_DBG("request for %s", hdev->name);1110105211111111- if (!lmp_bredr_capable(hdev))10531053+ status = mgmt_bredr_support(hdev);10541054+ if (status)11121055 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,11131113- MGMT_STATUS_NOT_SUPPORTED);10561056+ status);1114105711151058 if (cp->val != 0x00 && cp->val != 0x01)11161059 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,···12271168{12281169 struct mgmt_mode *cp = data;12291170 struct pending_cmd *cmd;12301230- u8 val;11711171+ u8 val, status;12311172 int err;1232117312331174 BT_DBG("request for %s", hdev->name);1234117512351235- if (!lmp_bredr_capable(hdev))11761176+ status = mgmt_bredr_support(hdev);11771177+ if (status)12361178 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,12371237- MGMT_STATUS_NOT_SUPPORTED);11791179+ status);1238118012391181 if (cp->val != 0x00 && cp->val != 0x01)12401182 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,···12961236{12971237 struct mgmt_mode *cp = data;12981238 struct pending_cmd *cmd;12991299- u8 val;12391239+ u8 val, status;13001240 int err;1301124113021242 BT_DBG("request for %s", hdev->name);12431243+12441244+ status = mgmt_bredr_support(hdev);12451245+ if (status)12461246+ return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);1303124713041248 if (!lmp_ssp_capable(hdev))13051249 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,···13661302static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)13671303{13681304 struct mgmt_mode *cp = data;13051305+ bool changed;13061306+ u8 status;13071307+ int err;1369130813701309 BT_DBG("request for %s", hdev->name);1371131013721372- if (!enable_hs)13731373- return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,13741374- MGMT_STATUS_NOT_SUPPORTED);13111311+ status = mgmt_bredr_support(hdev);13121312+ if (status)13131313+ return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);1375131413761315 if (cp->val != 0x00 && cp->val != 0x01)13771316 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,13781317 MGMT_STATUS_INVALID_PARAMS);1379131813801380- if (cp->val)13811381- set_bit(HCI_HS_ENABLED, &hdev->dev_flags);13821382- else13831383- clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);13191319+ hci_dev_lock(hdev);1384132013851385- return send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);13211321+ if (cp->val) {13221322+ changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);13231323+ } else {13241324+ if (hdev_is_powered(hdev)) {13251325+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,13261326+ MGMT_STATUS_REJECTED);13271327+ goto unlock;13281328+ }13291329+13301330+ changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);13311331+ }13321332+13331333+ err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);13341334+ if (err < 0)13351335+ goto unlock;13361336+13371337+ if (changed)13381338+ err = new_settings(hdev, sk);13391339+13401340+unlock:13411341+ hci_dev_unlock(hdev);13421342+ return err;13431343+}13441344+13451345+static void le_enable_complete(struct hci_dev *hdev, u8 status)13461346+{13471347+ struct cmd_lookup match = { NULL, hdev };13481348+13491349+ if (status) {13501350+ u8 mgmt_err = mgmt_status(status);13511351+13521352+ mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,13531353+ &mgmt_err);13541354+ return;13551355+ }13561356+13571357+ mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);13581358+13591359+ new_settings(hdev, match.sk);13601360+13611361+ if (match.sk)13621362+ sock_put(match.sk);13861363}1387136413881365static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)···14311326 struct mgmt_mode *cp = data;14321327 struct hci_cp_write_le_host_supported hci_cp;14331328 struct pending_cmd *cmd;13291329+ struct hci_request req;14341330 int err;14351331 u8 val, enabled;14361332···14461340 MGMT_STATUS_INVALID_PARAMS);1447134114481342 /* LE-only devices do not allow toggling LE on/off */14491449- if (!lmp_bredr_capable(hdev))13431343+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))14501344 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,14511345 MGMT_STATUS_REJECTED);14521346···14631357 changed = true;14641358 }1465135913601360+ if (!val && test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {13611361+ clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);13621362+ changed = true;13631363+ }13641364+14661365 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);14671366 if (err < 0)14681367 goto unlock;···14781367 goto unlock;14791368 }1480136914811481- if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {13701370+ if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||13711371+ mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {14821372 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,14831373 MGMT_STATUS_BUSY);14841374 goto unlock;···14981386 hci_cp.simul = lmp_le_br_capable(hdev);14991387 }1500138815011501- err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),15021502- &hci_cp);13891389+ hci_req_init(&req, hdev);13901390+13911391+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags) && !val)13921392+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val);13931393+13941394+ hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),13951395+ &hci_cp);13961396+13971397+ err = hci_req_run(&req, le_enable_complete);15031398 if (err < 0)15041399 mgmt_pending_remove(cmd);15051400···18241705 struct mgmt_cp_load_link_keys *cp = data;18251706 u16 key_count, expected_len;18261707 int i;17081708+17091709+ BT_DBG("request for %s", hdev->name);17101710+17111711+ if (!lmp_bredr_capable(hdev))17121712+ return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,17131713+ MGMT_STATUS_NOT_SUPPORTED);1827171418281715 key_count = __le16_to_cpu(cp->key_count);18291716···28102685 struct hci_request req;28112686 /* General inquiry access code (GIAC) */28122687 u8 lap[3] = { 0x33, 0x8b, 0x9e };26882688+ u8 status;28132689 int err;2814269028152691 BT_DBG("%s", hdev->name);···2847272128482722 switch (hdev->discovery.type) {28492723 case DISCOV_TYPE_BREDR:28502850- if (!lmp_bredr_capable(hdev)) {27242724+ status = mgmt_bredr_support(hdev);27252725+ if (status) {28512726 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,28522852- MGMT_STATUS_NOT_SUPPORTED);27272727+ status);28532728 mgmt_pending_remove(cmd);28542729 goto failed;28552730 }···2872274528732746 case DISCOV_TYPE_LE:28742747 case DISCOV_TYPE_INTERLEAVED:28752875- if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {27482748+ status = mgmt_le_support(hdev);27492749+ if (status) {28762750 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,28772877- MGMT_STATUS_NOT_SUPPORTED);27512751+ status);28782752 mgmt_pending_remove(cmd);28792753 goto failed;28802754 }2881275528822756 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&28832883- !lmp_bredr_capable(hdev)) {27572757+ !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {28842758 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,28852759 MGMT_STATUS_NOT_SUPPORTED);28862760 mgmt_pending_remove(cmd);···31933065 return err;31943066}3195306730683068+static void set_advertising_complete(struct hci_dev *hdev, u8 status)30693069+{30703070+ struct cmd_lookup match = { NULL, hdev };30713071+30723072+ if (status) {30733073+ u8 mgmt_err = mgmt_status(status);30743074+30753075+ mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,30763076+ cmd_status_rsp, &mgmt_err);30773077+ return;30783078+ }30793079+30803080+ mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,30813081+ &match);30823082+30833083+ new_settings(hdev, match.sk);30843084+30853085+ if (match.sk)30863086+ sock_put(match.sk);30873087+}30883088+30893089+static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)30903090+{30913091+ struct mgmt_mode *cp = data;30923092+ struct pending_cmd *cmd;30933093+ struct hci_request req;30943094+ u8 val, enabled, status;30953095+ int err;30963096+30973097+ BT_DBG("request for %s", hdev->name);30983098+30993099+ status = mgmt_le_support(hdev);31003100+ if (status)31013101+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,31023102+ status);31033103+31043104+ if (cp->val != 0x00 && cp->val != 0x01)31053105+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,31063106+ MGMT_STATUS_INVALID_PARAMS);31073107+31083108+ hci_dev_lock(hdev);31093109+31103110+ val = !!cp->val;31113111+ enabled = test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);31123112+31133113+ if (!hdev_is_powered(hdev) || val == enabled) {31143114+ bool changed = false;31153115+31163116+ if (val != test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {31173117+ change_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);31183118+ changed = true;31193119+ }31203120+31213121+ err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);31223122+ if (err < 0)31233123+ goto unlock;31243124+31253125+ if (changed)31263126+ err = new_settings(hdev, sk);31273127+31283128+ goto unlock;31293129+ }31303130+31313131+ if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||31323132+ mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {31333133+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,31343134+ MGMT_STATUS_BUSY);31353135+ goto unlock;31363136+ }31373137+31383138+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);31393139+ if (!cmd) {31403140+ err = -ENOMEM;31413141+ goto unlock;31423142+ }31433143+31443144+ hci_req_init(&req, hdev);31453145+31463146+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val);31473147+31483148+ err = hci_req_run(&req, set_advertising_complete);31493149+ if (err < 0)31503150+ mgmt_pending_remove(cmd);31513151+31523152+unlock:31533153+ hci_dev_unlock(hdev);31543154+ return err;31553155+}31563156+31573157+static int set_static_address(struct sock *sk, struct hci_dev *hdev,31583158+ void *data, u16 len)31593159+{31603160+ struct mgmt_cp_set_static_address *cp = data;31613161+ int err;31623162+31633163+ BT_DBG("%s", hdev->name);31643164+31653165+ if (!lmp_le_capable(hdev))31663166+ return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,31673167+ MGMT_STATUS_NOT_SUPPORTED);31683168+31693169+ if (hdev_is_powered(hdev))31703170+ return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,31713171+ MGMT_STATUS_REJECTED);31723172+31733173+ if (bacmp(&cp->bdaddr, BDADDR_ANY)) {31743174+ if (!bacmp(&cp->bdaddr, BDADDR_NONE))31753175+ return cmd_status(sk, hdev->id,31763176+ MGMT_OP_SET_STATIC_ADDRESS,31773177+ MGMT_STATUS_INVALID_PARAMS);31783178+31793179+ /* Two most significant bits shall be set */31803180+ if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)31813181+ return cmd_status(sk, hdev->id,31823182+ MGMT_OP_SET_STATIC_ADDRESS,31833183+ MGMT_STATUS_INVALID_PARAMS);31843184+ }31853185+31863186+ hci_dev_lock(hdev);31873187+31883188+ bacpy(&hdev->static_addr, &cp->bdaddr);31893189+31903190+ err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);31913191+31923192+ hci_dev_unlock(hdev);31933193+31943194+ return err;31953195+}31963196+31963197static void fast_connectable_complete(struct hci_dev *hdev, u8 status)31973198{31983199 struct pending_cmd *cmd;···3365310833663109 BT_DBG("%s", hdev->name);3367311033683368- if (!lmp_bredr_capable(hdev) || hdev->hci_ver < BLUETOOTH_VER_1_2)31113111+ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||31123112+ hdev->hci_ver < BLUETOOTH_VER_1_2)33693113 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,33703114 MGMT_STATUS_NOT_SUPPORTED);33713115···34203162 return err;34213163}3422316431653165+static void set_bredr_complete(struct hci_dev *hdev, u8 status)31663166+{31673167+ struct pending_cmd *cmd;31683168+31693169+ BT_DBG("status 0x%02x", status);31703170+31713171+ hci_dev_lock(hdev);31723172+31733173+ cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);31743174+ if (!cmd)31753175+ goto unlock;31763176+31773177+ if (status) {31783178+ u8 mgmt_err = mgmt_status(status);31793179+31803180+ /* We need to restore the flag if related HCI commands31813181+ * failed.31823182+ */31833183+ clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);31843184+31853185+ cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);31863186+ } else {31873187+ send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);31883188+ new_settings(hdev, cmd->sk);31893189+ }31903190+31913191+ mgmt_pending_remove(cmd);31923192+31933193+unlock:31943194+ hci_dev_unlock(hdev);31953195+}31963196+31973197+static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)31983198+{31993199+ struct mgmt_mode *cp = data;32003200+ struct pending_cmd *cmd;32013201+ struct hci_request req;32023202+ int err;32033203+32043204+ BT_DBG("request for %s", hdev->name);32053205+32063206+ if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))32073207+ return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,32083208+ MGMT_STATUS_NOT_SUPPORTED);32093209+32103210+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))32113211+ return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,32123212+ MGMT_STATUS_REJECTED);32133213+32143214+ if (cp->val != 0x00 && cp->val != 0x01)32153215+ return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,32163216+ MGMT_STATUS_INVALID_PARAMS);32173217+32183218+ hci_dev_lock(hdev);32193219+32203220+ if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {32213221+ err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);32223222+ goto unlock;32233223+ }32243224+32253225+ if (!hdev_is_powered(hdev)) {32263226+ if (!cp->val) {32273227+ clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);32283228+ clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);32293229+ clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);32303230+ clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);32313231+ clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);32323232+ clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);32333233+ }32343234+32353235+ change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);32363236+32373237+ err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);32383238+ if (err < 0)32393239+ goto unlock;32403240+32413241+ err = new_settings(hdev, sk);32423242+ goto unlock;32433243+ }32443244+32453245+ /* Reject disabling when powered on */32463246+ if (!cp->val) {32473247+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,32483248+ MGMT_STATUS_REJECTED);32493249+ goto unlock;32503250+ }32513251+32523252+ if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {32533253+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,32543254+ MGMT_STATUS_BUSY);32553255+ goto unlock;32563256+ }32573257+32583258+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);32593259+ if (!cmd) {32603260+ err = -ENOMEM;32613261+ goto unlock;32623262+ }32633263+32643264+ /* We need to flip the bit already here so that hci_update_ad32653265+ * generates the correct flags.32663266+ */32673267+ set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);32683268+32693269+ hci_req_init(&req, hdev);32703270+ hci_update_ad(&req);32713271+ err = hci_req_run(&req, set_bredr_complete);32723272+ if (err < 0)32733273+ mgmt_pending_remove(cmd);32743274+32753275+unlock:32763276+ hci_dev_unlock(hdev);32773277+ return err;32783278+}32793279+34233280static bool ltk_is_valid(struct mgmt_ltk_info *key)34243281{34253282 if (key->authenticated != 0x00 && key->authenticated != 0x01)···35523179 struct mgmt_cp_load_long_term_keys *cp = cp_data;35533180 u16 key_count, expected_len;35543181 int i, err;31823182+31833183+ BT_DBG("request for %s", hdev->name);31843184+31853185+ if (!lmp_le_capable(hdev))31863186+ return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,31873187+ MGMT_STATUS_NOT_SUPPORTED);3555318835563189 key_count = __le16_to_cpu(cp->key_count);35573190···36553276 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },36563277 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },36573278 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },32793279+ { set_advertising, false, MGMT_SETTING_SIZE },32803280+ { set_bredr, false, MGMT_SETTING_SIZE },32813281+ { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },36583282};3659328336603284···36983316 if (index != MGMT_INDEX_NONE) {36993317 hdev = hci_dev_get(index);37003318 if (!hdev) {33193319+ err = cmd_status(sk, index, opcode,33203320+ MGMT_STATUS_INVALID_INDEX);33213321+ goto done;33223322+ }33233323+33243324+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {37013325 err = cmd_status(sk, index, opcode,37023326 MGMT_STATUS_INVALID_INDEX);37033327 goto done;···37533365 return err;37543366}3755336737563756-static void cmd_status_rsp(struct pending_cmd *cmd, void *data)37573757-{37583758- u8 *status = data;37593759-37603760- cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);37613761- mgmt_pending_remove(cmd);37623762-}37633763-37643368int mgmt_index_added(struct hci_dev *hdev)37653369{37663370 if (!mgmt_valid_hdev(hdev))···37713391 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);3772339237733393 return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);37743774-}37753775-37763776-struct cmd_lookup {37773777- struct sock *sk;37783778- struct hci_dev *hdev;37793779- u8 mgmt_status;37803780-};37813781-37823782-static void settings_rsp(struct pending_cmd *cmd, void *data)37833783-{37843784- struct cmd_lookup *match = data;37853785-37863786- send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);37873787-37883788- list_del(&cmd->list);37893789-37903790- if (match->sk == NULL) {37913791- match->sk = cmd->sk;37923792- sock_hold(match->sk);37933793- }37943794-37953795- mgmt_pending_free(cmd);37963394}3797339537983396static void set_bredr_scan(struct hci_request *req)···38393481 cp.simul != lmp_host_le_br_capable(hdev))38403482 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,38413483 sizeof(cp), &cp);34843484+34853485+ /* In case BR/EDR was toggled during the AUTO_OFF phase */34863486+ hci_update_ad(&req);34873487+ }34883488+34893489+ if (lmp_le_capable(hdev)) {34903490+ /* Set random address to static address if configured */34913491+ if (bacmp(&hdev->static_addr, BDADDR_ANY))34923492+ hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6,34933493+ &hdev->static_addr);34943494+ }34953495+34963496+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {34973497+ u8 adv = 0x01;34983498+34993499+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv);38423500 }3843350138443502 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);···38633489 sizeof(link_sec), &link_sec);3864349038653491 if (lmp_bredr_capable(hdev)) {38663866- set_bredr_scan(&req);34923492+ if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))34933493+ set_bredr_scan(&req);38673494 update_class(&req);38683495 update_name(&req);38693496 update_eir(&req);···45074132 return err;45084133}4509413445104510-int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)45114511-{45124512- struct cmd_lookup match = { NULL, hdev };45134513- bool changed = false;45144514- int err = 0;45154515-45164516- if (status) {45174517- u8 mgmt_err = mgmt_status(status);45184518-45194519- if (enable && test_and_clear_bit(HCI_LE_ENABLED,45204520- &hdev->dev_flags))45214521- err = new_settings(hdev, NULL);45224522-45234523- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,45244524- &mgmt_err);45254525-45264526- return err;45274527- }45284528-45294529- if (enable) {45304530- if (!test_and_set_bit(HCI_LE_ENABLED, &hdev->dev_flags))45314531- changed = true;45324532- } else {45334533- if (test_and_clear_bit(HCI_LE_ENABLED, &hdev->dev_flags))45344534- changed = true;45354535- }45364536-45374537- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);45384538-45394539- if (changed)45404540- err = new_settings(hdev, match.sk);45414541-45424542- if (match.sk)45434543- sock_put(match.sk);45444544-45454545- return err;45464546-}45474547-45484135int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,45494136 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u845504137 ssp, u8 *eir, u16 eir_len)···46234286 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),46244287 cmd ? cmd->sk : NULL);46254288}46264626-46274627-module_param(enable_hs, bool, 0644);46284628-MODULE_PARM_DESC(enable_hs, "Enable High Speed support");
+6-1
net/bluetooth/rfcomm/sock.c
···544544 struct sock *sk = sock->sk;545545 struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;546546 struct sk_buff *skb;547547- int sent = 0;547547+ int sent;548548549549 if (test_bit(RFCOMM_DEFER_SETUP, &d->flags))550550 return -ENOTCONN;···558558 BT_DBG("sock %p, sk %p", sock, sk);559559560560 lock_sock(sk);561561+562562+ sent = bt_sock_wait_ready(sk, msg->msg_flags);563563+ if (sent)564564+ goto done;561565562566 while (len) {563567 size_t size = min_t(size_t, len, d->mtu);···598594 len -= size;599595 }600596597597+done:601598 release_sock(sk);602599603600 return sent;
+2-33
net/bluetooth/rfcomm/tty.c
···569569static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)570570{571571 struct rfcomm_dev *dev = dlc->owner;572572- struct tty_struct *tty;573572 if (!dev)574573 return;575574···580581 DPM_ORDER_DEV_AFTER_PARENT);581582582583 wake_up_interruptible(&dev->port.open_wait);583583- } else if (dlc->state == BT_CLOSED) {584584- tty = tty_port_tty_get(&dev->port);585585- if (!tty) {586586- if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {587587- /* Drop DLC lock here to avoid deadlock588588- * 1. rfcomm_dev_get will take rfcomm_dev_lock589589- * but in rfcomm_dev_add there's lock order:590590- * rfcomm_dev_lock -> dlc lock591591- * 2. tty_port_put will deadlock if it's592592- * the last reference593593- *594594- * FIXME: when we release the lock anything595595- * could happen to dev, even its destruction596596- */597597- rfcomm_dlc_unlock(dlc);598598- if (rfcomm_dev_get(dev->id) == NULL) {599599- rfcomm_dlc_lock(dlc);600600- return;601601- }602602-603603- if (!test_and_set_bit(RFCOMM_TTY_RELEASED,604604- &dev->flags))605605- tty_port_put(&dev->port);606606-607607- tty_port_put(&dev->port);608608- rfcomm_dlc_lock(dlc);609609- }610610- } else {611611- tty_hangup(tty);612612- tty_kref_put(tty);613613- }614614- }584584+ } else if (dlc->state == BT_CLOSED)585585+ tty_port_tty_hangup(&dev->port, false);615586}616587617588static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)