1*6a98e383SMarcel Holtmann // SPDX-License-Identifier: GPL-2.0 2*6a98e383SMarcel Holtmann /* 3*6a98e383SMarcel Holtmann * BlueZ - Bluetooth protocol stack for Linux 4*6a98e383SMarcel Holtmann * 5*6a98e383SMarcel Holtmann * Copyright (C) 2021 Intel Corporation 6*6a98e383SMarcel Holtmann */ 7*6a98e383SMarcel Holtmann 8*6a98e383SMarcel Holtmann #include <net/bluetooth/bluetooth.h> 9*6a98e383SMarcel Holtmann #include <net/bluetooth/hci_core.h> 10*6a98e383SMarcel Holtmann #include <net/bluetooth/mgmt.h> 11*6a98e383SMarcel Holtmann 12*6a98e383SMarcel Holtmann #include "hci_request.h" 13*6a98e383SMarcel Holtmann #include "smp.h" 14*6a98e383SMarcel Holtmann 15*6a98e383SMarcel Holtmann static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, 16*6a98e383SMarcel Holtmann struct sk_buff *skb) 17*6a98e383SMarcel Holtmann { 18*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, "result 0x%2.2x", result); 19*6a98e383SMarcel Holtmann 20*6a98e383SMarcel Holtmann if (hdev->req_status != HCI_REQ_PEND) 21*6a98e383SMarcel Holtmann return; 22*6a98e383SMarcel Holtmann 23*6a98e383SMarcel Holtmann hdev->req_result = result; 24*6a98e383SMarcel Holtmann hdev->req_status = HCI_REQ_DONE; 25*6a98e383SMarcel Holtmann 26*6a98e383SMarcel Holtmann wake_up_interruptible(&hdev->req_wait_q); 27*6a98e383SMarcel Holtmann } 28*6a98e383SMarcel Holtmann 29*6a98e383SMarcel Holtmann static struct sk_buff *hci_cmd_sync_alloc(struct hci_dev *hdev, u16 opcode, 30*6a98e383SMarcel Holtmann u32 plen, const void *param, 31*6a98e383SMarcel Holtmann struct sock *sk) 32*6a98e383SMarcel Holtmann { 33*6a98e383SMarcel Holtmann int len = HCI_COMMAND_HDR_SIZE + plen; 34*6a98e383SMarcel Holtmann struct hci_command_hdr *hdr; 35*6a98e383SMarcel Holtmann struct sk_buff *skb; 36*6a98e383SMarcel Holtmann 37*6a98e383SMarcel Holtmann skb = bt_skb_alloc(len, GFP_ATOMIC); 38*6a98e383SMarcel Holtmann if (!skb) 39*6a98e383SMarcel Holtmann return NULL; 40*6a98e383SMarcel Holtmann 41*6a98e383SMarcel Holtmann hdr = skb_put(skb, HCI_COMMAND_HDR_SIZE); 42*6a98e383SMarcel Holtmann hdr->opcode = cpu_to_le16(opcode); 43*6a98e383SMarcel Holtmann hdr->plen = plen; 44*6a98e383SMarcel Holtmann 45*6a98e383SMarcel Holtmann if (plen) 46*6a98e383SMarcel Holtmann skb_put_data(skb, param, plen); 47*6a98e383SMarcel Holtmann 48*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, "skb len %d", skb->len); 49*6a98e383SMarcel Holtmann 50*6a98e383SMarcel Holtmann hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; 51*6a98e383SMarcel Holtmann hci_skb_opcode(skb) = opcode; 52*6a98e383SMarcel Holtmann 53*6a98e383SMarcel Holtmann return skb; 54*6a98e383SMarcel Holtmann } 55*6a98e383SMarcel Holtmann 56*6a98e383SMarcel Holtmann static void hci_cmd_sync_add(struct hci_request *req, u16 opcode, u32 plen, 57*6a98e383SMarcel Holtmann const void *param, u8 event, struct sock *sk) 58*6a98e383SMarcel Holtmann { 59*6a98e383SMarcel Holtmann struct hci_dev *hdev = req->hdev; 60*6a98e383SMarcel Holtmann struct sk_buff *skb; 61*6a98e383SMarcel Holtmann 62*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, "opcode 0x%4.4x plen %d", opcode, plen); 63*6a98e383SMarcel Holtmann 64*6a98e383SMarcel Holtmann /* If an error occurred during request building, there is no point in 65*6a98e383SMarcel Holtmann * queueing the HCI command. We can simply return. 66*6a98e383SMarcel Holtmann */ 67*6a98e383SMarcel Holtmann if (req->err) 68*6a98e383SMarcel Holtmann return; 69*6a98e383SMarcel Holtmann 70*6a98e383SMarcel Holtmann skb = hci_cmd_sync_alloc(hdev, opcode, plen, param, sk); 71*6a98e383SMarcel Holtmann if (!skb) { 72*6a98e383SMarcel Holtmann bt_dev_err(hdev, "no memory for command (opcode 0x%4.4x)", 73*6a98e383SMarcel Holtmann opcode); 74*6a98e383SMarcel Holtmann req->err = -ENOMEM; 75*6a98e383SMarcel Holtmann return; 76*6a98e383SMarcel Holtmann } 77*6a98e383SMarcel Holtmann 78*6a98e383SMarcel Holtmann if (skb_queue_empty(&req->cmd_q)) 79*6a98e383SMarcel Holtmann bt_cb(skb)->hci.req_flags |= HCI_REQ_START; 80*6a98e383SMarcel Holtmann 81*6a98e383SMarcel Holtmann bt_cb(skb)->hci.req_event = event; 82*6a98e383SMarcel Holtmann 83*6a98e383SMarcel Holtmann skb_queue_tail(&req->cmd_q, skb); 84*6a98e383SMarcel Holtmann } 85*6a98e383SMarcel Holtmann 86*6a98e383SMarcel Holtmann static int hci_cmd_sync_run(struct hci_request *req) 87*6a98e383SMarcel Holtmann { 88*6a98e383SMarcel Holtmann struct hci_dev *hdev = req->hdev; 89*6a98e383SMarcel Holtmann struct sk_buff *skb; 90*6a98e383SMarcel Holtmann unsigned long flags; 91*6a98e383SMarcel Holtmann 92*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, "length %u", skb_queue_len(&req->cmd_q)); 93*6a98e383SMarcel Holtmann 94*6a98e383SMarcel Holtmann /* If an error occurred during request building, remove all HCI 95*6a98e383SMarcel Holtmann * commands queued on the HCI request queue. 96*6a98e383SMarcel Holtmann */ 97*6a98e383SMarcel Holtmann if (req->err) { 98*6a98e383SMarcel Holtmann skb_queue_purge(&req->cmd_q); 99*6a98e383SMarcel Holtmann return req->err; 100*6a98e383SMarcel Holtmann } 101*6a98e383SMarcel Holtmann 102*6a98e383SMarcel Holtmann /* Do not allow empty requests */ 103*6a98e383SMarcel Holtmann if (skb_queue_empty(&req->cmd_q)) 104*6a98e383SMarcel Holtmann return -ENODATA; 105*6a98e383SMarcel Holtmann 106*6a98e383SMarcel Holtmann skb = skb_peek_tail(&req->cmd_q); 107*6a98e383SMarcel Holtmann bt_cb(skb)->hci.req_complete_skb = hci_cmd_sync_complete; 108*6a98e383SMarcel Holtmann bt_cb(skb)->hci.req_flags |= HCI_REQ_SKB; 109*6a98e383SMarcel Holtmann 110*6a98e383SMarcel Holtmann spin_lock_irqsave(&hdev->cmd_q.lock, flags); 111*6a98e383SMarcel Holtmann skb_queue_splice_tail(&req->cmd_q, &hdev->cmd_q); 112*6a98e383SMarcel Holtmann spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); 113*6a98e383SMarcel Holtmann 114*6a98e383SMarcel Holtmann queue_work(hdev->workqueue, &hdev->cmd_work); 115*6a98e383SMarcel Holtmann 116*6a98e383SMarcel Holtmann return 0; 117*6a98e383SMarcel Holtmann } 118*6a98e383SMarcel Holtmann 119*6a98e383SMarcel Holtmann /* This function requires the caller holds hdev->req_lock. */ 120*6a98e383SMarcel Holtmann struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, 121*6a98e383SMarcel Holtmann const void *param, u8 event, u32 timeout, 122*6a98e383SMarcel Holtmann struct sock *sk) 123*6a98e383SMarcel Holtmann { 124*6a98e383SMarcel Holtmann struct hci_request req; 125*6a98e383SMarcel Holtmann struct sk_buff *skb; 126*6a98e383SMarcel Holtmann int err = 0; 127*6a98e383SMarcel Holtmann 128*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, ""); 129*6a98e383SMarcel Holtmann 130*6a98e383SMarcel Holtmann hci_req_init(&req, hdev); 131*6a98e383SMarcel Holtmann 132*6a98e383SMarcel Holtmann hci_cmd_sync_add(&req, opcode, plen, param, event, sk); 133*6a98e383SMarcel Holtmann 134*6a98e383SMarcel Holtmann hdev->req_status = HCI_REQ_PEND; 135*6a98e383SMarcel Holtmann 136*6a98e383SMarcel Holtmann err = hci_cmd_sync_run(&req); 137*6a98e383SMarcel Holtmann if (err < 0) 138*6a98e383SMarcel Holtmann return ERR_PTR(err); 139*6a98e383SMarcel Holtmann 140*6a98e383SMarcel Holtmann err = wait_event_interruptible_timeout(hdev->req_wait_q, 141*6a98e383SMarcel Holtmann hdev->req_status != HCI_REQ_PEND, 142*6a98e383SMarcel Holtmann timeout); 143*6a98e383SMarcel Holtmann 144*6a98e383SMarcel Holtmann if (err == -ERESTARTSYS) 145*6a98e383SMarcel Holtmann return ERR_PTR(-EINTR); 146*6a98e383SMarcel Holtmann 147*6a98e383SMarcel Holtmann switch (hdev->req_status) { 148*6a98e383SMarcel Holtmann case HCI_REQ_DONE: 149*6a98e383SMarcel Holtmann err = -bt_to_errno(hdev->req_result); 150*6a98e383SMarcel Holtmann break; 151*6a98e383SMarcel Holtmann 152*6a98e383SMarcel Holtmann case HCI_REQ_CANCELED: 153*6a98e383SMarcel Holtmann err = -hdev->req_result; 154*6a98e383SMarcel Holtmann break; 155*6a98e383SMarcel Holtmann 156*6a98e383SMarcel Holtmann default: 157*6a98e383SMarcel Holtmann err = -ETIMEDOUT; 158*6a98e383SMarcel Holtmann break; 159*6a98e383SMarcel Holtmann } 160*6a98e383SMarcel Holtmann 161*6a98e383SMarcel Holtmann hdev->req_status = 0; 162*6a98e383SMarcel Holtmann hdev->req_result = 0; 163*6a98e383SMarcel Holtmann skb = hdev->req_skb; 164*6a98e383SMarcel Holtmann hdev->req_skb = NULL; 165*6a98e383SMarcel Holtmann 166*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, "end: err %d", err); 167*6a98e383SMarcel Holtmann 168*6a98e383SMarcel Holtmann if (err < 0) { 169*6a98e383SMarcel Holtmann kfree_skb(skb); 170*6a98e383SMarcel Holtmann return ERR_PTR(err); 171*6a98e383SMarcel Holtmann } 172*6a98e383SMarcel Holtmann 173*6a98e383SMarcel Holtmann if (!skb) 174*6a98e383SMarcel Holtmann return ERR_PTR(-ENODATA); 175*6a98e383SMarcel Holtmann 176*6a98e383SMarcel Holtmann return skb; 177*6a98e383SMarcel Holtmann } 178*6a98e383SMarcel Holtmann EXPORT_SYMBOL(__hci_cmd_sync_sk); 179*6a98e383SMarcel Holtmann 180*6a98e383SMarcel Holtmann /* This function requires the caller holds hdev->req_lock. */ 181*6a98e383SMarcel Holtmann struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, 182*6a98e383SMarcel Holtmann const void *param, u32 timeout) 183*6a98e383SMarcel Holtmann { 184*6a98e383SMarcel Holtmann return __hci_cmd_sync_sk(hdev, opcode, plen, param, 0, timeout, NULL); 185*6a98e383SMarcel Holtmann } 186*6a98e383SMarcel Holtmann EXPORT_SYMBOL(__hci_cmd_sync); 187*6a98e383SMarcel Holtmann 188*6a98e383SMarcel Holtmann /* Send HCI command and wait for command complete event */ 189*6a98e383SMarcel Holtmann struct sk_buff *hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, 190*6a98e383SMarcel Holtmann const void *param, u32 timeout) 191*6a98e383SMarcel Holtmann { 192*6a98e383SMarcel Holtmann struct sk_buff *skb; 193*6a98e383SMarcel Holtmann 194*6a98e383SMarcel Holtmann if (!test_bit(HCI_UP, &hdev->flags)) 195*6a98e383SMarcel Holtmann return ERR_PTR(-ENETDOWN); 196*6a98e383SMarcel Holtmann 197*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, "opcode 0x%4.4x plen %d", opcode, plen); 198*6a98e383SMarcel Holtmann 199*6a98e383SMarcel Holtmann hci_req_sync_lock(hdev); 200*6a98e383SMarcel Holtmann skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout); 201*6a98e383SMarcel Holtmann hci_req_sync_unlock(hdev); 202*6a98e383SMarcel Holtmann 203*6a98e383SMarcel Holtmann return skb; 204*6a98e383SMarcel Holtmann } 205*6a98e383SMarcel Holtmann EXPORT_SYMBOL(hci_cmd_sync); 206*6a98e383SMarcel Holtmann 207*6a98e383SMarcel Holtmann /* This function requires the caller holds hdev->req_lock. */ 208*6a98e383SMarcel Holtmann struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, 209*6a98e383SMarcel Holtmann const void *param, u8 event, u32 timeout) 210*6a98e383SMarcel Holtmann { 211*6a98e383SMarcel Holtmann return __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, 212*6a98e383SMarcel Holtmann NULL); 213*6a98e383SMarcel Holtmann } 214*6a98e383SMarcel Holtmann EXPORT_SYMBOL(__hci_cmd_sync_ev); 215*6a98e383SMarcel Holtmann 216*6a98e383SMarcel Holtmann /* This function requires the caller holds hdev->req_lock. */ 217*6a98e383SMarcel Holtmann int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen, 218*6a98e383SMarcel Holtmann const void *param, u8 event, u32 timeout, 219*6a98e383SMarcel Holtmann struct sock *sk) 220*6a98e383SMarcel Holtmann { 221*6a98e383SMarcel Holtmann struct sk_buff *skb; 222*6a98e383SMarcel Holtmann u8 status; 223*6a98e383SMarcel Holtmann 224*6a98e383SMarcel Holtmann skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk); 225*6a98e383SMarcel Holtmann if (IS_ERR_OR_NULL(skb)) { 226*6a98e383SMarcel Holtmann bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode, 227*6a98e383SMarcel Holtmann PTR_ERR(skb)); 228*6a98e383SMarcel Holtmann return PTR_ERR(skb); 229*6a98e383SMarcel Holtmann } 230*6a98e383SMarcel Holtmann 231*6a98e383SMarcel Holtmann status = skb->data[0]; 232*6a98e383SMarcel Holtmann 233*6a98e383SMarcel Holtmann kfree_skb(skb); 234*6a98e383SMarcel Holtmann 235*6a98e383SMarcel Holtmann return status; 236*6a98e383SMarcel Holtmann } 237*6a98e383SMarcel Holtmann EXPORT_SYMBOL(__hci_cmd_sync_status_sk); 238*6a98e383SMarcel Holtmann 239*6a98e383SMarcel Holtmann int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen, 240*6a98e383SMarcel Holtmann const void *param, u32 timeout) 241*6a98e383SMarcel Holtmann { 242*6a98e383SMarcel Holtmann return __hci_cmd_sync_status_sk(hdev, opcode, plen, param, 0, timeout, 243*6a98e383SMarcel Holtmann NULL); 244*6a98e383SMarcel Holtmann } 245*6a98e383SMarcel Holtmann EXPORT_SYMBOL(__hci_cmd_sync_status); 246*6a98e383SMarcel Holtmann 247*6a98e383SMarcel Holtmann static void hci_cmd_sync_work(struct work_struct *work) 248*6a98e383SMarcel Holtmann { 249*6a98e383SMarcel Holtmann struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_sync_work); 250*6a98e383SMarcel Holtmann struct hci_cmd_sync_work_entry *entry; 251*6a98e383SMarcel Holtmann hci_cmd_sync_work_func_t func; 252*6a98e383SMarcel Holtmann hci_cmd_sync_work_destroy_t destroy; 253*6a98e383SMarcel Holtmann void *data; 254*6a98e383SMarcel Holtmann 255*6a98e383SMarcel Holtmann bt_dev_dbg(hdev, ""); 256*6a98e383SMarcel Holtmann 257*6a98e383SMarcel Holtmann mutex_lock(&hdev->cmd_sync_work_lock); 258*6a98e383SMarcel Holtmann entry = list_first_entry(&hdev->cmd_sync_work_list, 259*6a98e383SMarcel Holtmann struct hci_cmd_sync_work_entry, list); 260*6a98e383SMarcel Holtmann if (entry) { 261*6a98e383SMarcel Holtmann list_del(&entry->list); 262*6a98e383SMarcel Holtmann func = entry->func; 263*6a98e383SMarcel Holtmann data = entry->data; 264*6a98e383SMarcel Holtmann destroy = entry->destroy; 265*6a98e383SMarcel Holtmann kfree(entry); 266*6a98e383SMarcel Holtmann } else { 267*6a98e383SMarcel Holtmann func = NULL; 268*6a98e383SMarcel Holtmann data = NULL; 269*6a98e383SMarcel Holtmann destroy = NULL; 270*6a98e383SMarcel Holtmann } 271*6a98e383SMarcel Holtmann mutex_unlock(&hdev->cmd_sync_work_lock); 272*6a98e383SMarcel Holtmann 273*6a98e383SMarcel Holtmann if (func) { 274*6a98e383SMarcel Holtmann int err; 275*6a98e383SMarcel Holtmann 276*6a98e383SMarcel Holtmann hci_req_sync_lock(hdev); 277*6a98e383SMarcel Holtmann 278*6a98e383SMarcel Holtmann err = func(hdev, data); 279*6a98e383SMarcel Holtmann 280*6a98e383SMarcel Holtmann if (destroy) 281*6a98e383SMarcel Holtmann destroy(hdev, data, err); 282*6a98e383SMarcel Holtmann 283*6a98e383SMarcel Holtmann hci_req_sync_unlock(hdev); 284*6a98e383SMarcel Holtmann } 285*6a98e383SMarcel Holtmann } 286*6a98e383SMarcel Holtmann 287*6a98e383SMarcel Holtmann void hci_cmd_sync_init(struct hci_dev *hdev) 288*6a98e383SMarcel Holtmann { 289*6a98e383SMarcel Holtmann INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work); 290*6a98e383SMarcel Holtmann INIT_LIST_HEAD(&hdev->cmd_sync_work_list); 291*6a98e383SMarcel Holtmann mutex_init(&hdev->cmd_sync_work_lock); 292*6a98e383SMarcel Holtmann } 293*6a98e383SMarcel Holtmann 294*6a98e383SMarcel Holtmann void hci_cmd_sync_clear(struct hci_dev *hdev) 295*6a98e383SMarcel Holtmann { 296*6a98e383SMarcel Holtmann struct hci_cmd_sync_work_entry *entry, *tmp; 297*6a98e383SMarcel Holtmann 298*6a98e383SMarcel Holtmann cancel_work_sync(&hdev->cmd_sync_work); 299*6a98e383SMarcel Holtmann 300*6a98e383SMarcel Holtmann list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) { 301*6a98e383SMarcel Holtmann if (entry->destroy) 302*6a98e383SMarcel Holtmann entry->destroy(hdev, entry->data, -ECANCELED); 303*6a98e383SMarcel Holtmann 304*6a98e383SMarcel Holtmann list_del(&entry->list); 305*6a98e383SMarcel Holtmann kfree(entry); 306*6a98e383SMarcel Holtmann } 307*6a98e383SMarcel Holtmann } 308*6a98e383SMarcel Holtmann 309*6a98e383SMarcel Holtmann int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func, 310*6a98e383SMarcel Holtmann void *data, hci_cmd_sync_work_destroy_t destroy) 311*6a98e383SMarcel Holtmann { 312*6a98e383SMarcel Holtmann struct hci_cmd_sync_work_entry *entry; 313*6a98e383SMarcel Holtmann 314*6a98e383SMarcel Holtmann entry = kmalloc(sizeof(*entry), GFP_KERNEL); 315*6a98e383SMarcel Holtmann if (!entry) 316*6a98e383SMarcel Holtmann return -ENOMEM; 317*6a98e383SMarcel Holtmann 318*6a98e383SMarcel Holtmann entry->func = func; 319*6a98e383SMarcel Holtmann entry->data = data; 320*6a98e383SMarcel Holtmann entry->destroy = destroy; 321*6a98e383SMarcel Holtmann 322*6a98e383SMarcel Holtmann mutex_lock(&hdev->cmd_sync_work_lock); 323*6a98e383SMarcel Holtmann list_add_tail(&entry->list, &hdev->cmd_sync_work_list); 324*6a98e383SMarcel Holtmann mutex_unlock(&hdev->cmd_sync_work_lock); 325*6a98e383SMarcel Holtmann 326*6a98e383SMarcel Holtmann queue_work(hdev->req_workqueue, &hdev->cmd_sync_work); 327*6a98e383SMarcel Holtmann 328*6a98e383SMarcel Holtmann return 0; 329*6a98e383SMarcel Holtmann } 330*6a98e383SMarcel Holtmann EXPORT_SYMBOL(hci_cmd_sync_queue); 331