1*afd2daa2SMarcel Holtmann // SPDX-License-Identifier: GPL-2.0-only 2*afd2daa2SMarcel Holtmann 3*afd2daa2SMarcel Holtmann #include <linux/module.h> 4*afd2daa2SMarcel Holtmann #include <linux/virtio.h> 5*afd2daa2SMarcel Holtmann #include <linux/virtio_config.h> 6*afd2daa2SMarcel Holtmann #include <linux/skbuff.h> 7*afd2daa2SMarcel Holtmann 8*afd2daa2SMarcel Holtmann #include <uapi/linux/virtio_ids.h> 9*afd2daa2SMarcel Holtmann #include <uapi/linux/virtio_bt.h> 10*afd2daa2SMarcel Holtmann 11*afd2daa2SMarcel Holtmann #include <net/bluetooth/bluetooth.h> 12*afd2daa2SMarcel Holtmann #include <net/bluetooth/hci_core.h> 13*afd2daa2SMarcel Holtmann 14*afd2daa2SMarcel Holtmann #define VERSION "0.1" 15*afd2daa2SMarcel Holtmann 16*afd2daa2SMarcel Holtmann enum { 17*afd2daa2SMarcel Holtmann VIRTBT_VQ_TX, 18*afd2daa2SMarcel Holtmann VIRTBT_VQ_RX, 19*afd2daa2SMarcel Holtmann VIRTBT_NUM_VQS, 20*afd2daa2SMarcel Holtmann }; 21*afd2daa2SMarcel Holtmann 22*afd2daa2SMarcel Holtmann struct virtio_bluetooth { 23*afd2daa2SMarcel Holtmann struct virtio_device *vdev; 24*afd2daa2SMarcel Holtmann struct virtqueue *vqs[VIRTBT_NUM_VQS]; 25*afd2daa2SMarcel Holtmann struct work_struct rx; 26*afd2daa2SMarcel Holtmann struct hci_dev *hdev; 27*afd2daa2SMarcel Holtmann }; 28*afd2daa2SMarcel Holtmann 29*afd2daa2SMarcel Holtmann static int virtbt_add_inbuf(struct virtio_bluetooth *vbt) 30*afd2daa2SMarcel Holtmann { 31*afd2daa2SMarcel Holtmann struct virtqueue *vq = vbt->vqs[VIRTBT_VQ_RX]; 32*afd2daa2SMarcel Holtmann struct scatterlist sg[1]; 33*afd2daa2SMarcel Holtmann struct sk_buff *skb; 34*afd2daa2SMarcel Holtmann int err; 35*afd2daa2SMarcel Holtmann 36*afd2daa2SMarcel Holtmann skb = alloc_skb(1000, GFP_KERNEL); 37*afd2daa2SMarcel Holtmann sg_init_one(sg, skb->data, 1000); 38*afd2daa2SMarcel Holtmann 39*afd2daa2SMarcel Holtmann err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL); 40*afd2daa2SMarcel Holtmann if (err < 0) { 41*afd2daa2SMarcel Holtmann kfree_skb(skb); 42*afd2daa2SMarcel Holtmann return err; 43*afd2daa2SMarcel Holtmann } 44*afd2daa2SMarcel Holtmann 45*afd2daa2SMarcel Holtmann return 0; 46*afd2daa2SMarcel Holtmann } 47*afd2daa2SMarcel Holtmann 48*afd2daa2SMarcel Holtmann static int virtbt_open(struct hci_dev *hdev) 49*afd2daa2SMarcel Holtmann { 50*afd2daa2SMarcel Holtmann struct virtio_bluetooth *vbt = hci_get_drvdata(hdev); 51*afd2daa2SMarcel Holtmann 52*afd2daa2SMarcel Holtmann if (virtbt_add_inbuf(vbt) < 0) 53*afd2daa2SMarcel Holtmann return -EIO; 54*afd2daa2SMarcel Holtmann 55*afd2daa2SMarcel Holtmann virtqueue_kick(vbt->vqs[VIRTBT_VQ_RX]); 56*afd2daa2SMarcel Holtmann return 0; 57*afd2daa2SMarcel Holtmann } 58*afd2daa2SMarcel Holtmann 59*afd2daa2SMarcel Holtmann static int virtbt_close(struct hci_dev *hdev) 60*afd2daa2SMarcel Holtmann { 61*afd2daa2SMarcel Holtmann struct virtio_bluetooth *vbt = hci_get_drvdata(hdev); 62*afd2daa2SMarcel Holtmann int i; 63*afd2daa2SMarcel Holtmann 64*afd2daa2SMarcel Holtmann cancel_work_sync(&vbt->rx); 65*afd2daa2SMarcel Holtmann 66*afd2daa2SMarcel Holtmann for (i = 0; i < ARRAY_SIZE(vbt->vqs); i++) { 67*afd2daa2SMarcel Holtmann struct virtqueue *vq = vbt->vqs[i]; 68*afd2daa2SMarcel Holtmann struct sk_buff *skb; 69*afd2daa2SMarcel Holtmann 70*afd2daa2SMarcel Holtmann while ((skb = virtqueue_detach_unused_buf(vq))) 71*afd2daa2SMarcel Holtmann kfree_skb(skb); 72*afd2daa2SMarcel Holtmann } 73*afd2daa2SMarcel Holtmann 74*afd2daa2SMarcel Holtmann return 0; 75*afd2daa2SMarcel Holtmann } 76*afd2daa2SMarcel Holtmann 77*afd2daa2SMarcel Holtmann static int virtbt_flush(struct hci_dev *hdev) 78*afd2daa2SMarcel Holtmann { 79*afd2daa2SMarcel Holtmann return 0; 80*afd2daa2SMarcel Holtmann } 81*afd2daa2SMarcel Holtmann 82*afd2daa2SMarcel Holtmann static int virtbt_send_frame(struct hci_dev *hdev, struct sk_buff *skb) 83*afd2daa2SMarcel Holtmann { 84*afd2daa2SMarcel Holtmann struct virtio_bluetooth *vbt = hci_get_drvdata(hdev); 85*afd2daa2SMarcel Holtmann struct scatterlist sg[1]; 86*afd2daa2SMarcel Holtmann int err; 87*afd2daa2SMarcel Holtmann 88*afd2daa2SMarcel Holtmann memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); 89*afd2daa2SMarcel Holtmann 90*afd2daa2SMarcel Holtmann sg_init_one(sg, skb->data, skb->len); 91*afd2daa2SMarcel Holtmann err = virtqueue_add_outbuf(vbt->vqs[VIRTBT_VQ_TX], sg, 1, skb, 92*afd2daa2SMarcel Holtmann GFP_KERNEL); 93*afd2daa2SMarcel Holtmann if (err) { 94*afd2daa2SMarcel Holtmann kfree_skb(skb); 95*afd2daa2SMarcel Holtmann return err; 96*afd2daa2SMarcel Holtmann } 97*afd2daa2SMarcel Holtmann 98*afd2daa2SMarcel Holtmann virtqueue_kick(vbt->vqs[VIRTBT_VQ_TX]); 99*afd2daa2SMarcel Holtmann return 0; 100*afd2daa2SMarcel Holtmann } 101*afd2daa2SMarcel Holtmann 102*afd2daa2SMarcel Holtmann static int virtbt_setup_zephyr(struct hci_dev *hdev) 103*afd2daa2SMarcel Holtmann { 104*afd2daa2SMarcel Holtmann struct sk_buff *skb; 105*afd2daa2SMarcel Holtmann 106*afd2daa2SMarcel Holtmann /* Read Build Information */ 107*afd2daa2SMarcel Holtmann skb = __hci_cmd_sync(hdev, 0xfc08, 0, NULL, HCI_INIT_TIMEOUT); 108*afd2daa2SMarcel Holtmann if (IS_ERR(skb)) 109*afd2daa2SMarcel Holtmann return PTR_ERR(skb); 110*afd2daa2SMarcel Holtmann 111*afd2daa2SMarcel Holtmann bt_dev_info(hdev, "%s", (char *)(skb->data + 1)); 112*afd2daa2SMarcel Holtmann 113*afd2daa2SMarcel Holtmann hci_set_fw_info(hdev, "%s", skb->data + 1); 114*afd2daa2SMarcel Holtmann 115*afd2daa2SMarcel Holtmann kfree_skb(skb); 116*afd2daa2SMarcel Holtmann return 0; 117*afd2daa2SMarcel Holtmann } 118*afd2daa2SMarcel Holtmann 119*afd2daa2SMarcel Holtmann static int virtbt_set_bdaddr_zephyr(struct hci_dev *hdev, 120*afd2daa2SMarcel Holtmann const bdaddr_t *bdaddr) 121*afd2daa2SMarcel Holtmann { 122*afd2daa2SMarcel Holtmann struct sk_buff *skb; 123*afd2daa2SMarcel Holtmann 124*afd2daa2SMarcel Holtmann /* Write BD_ADDR */ 125*afd2daa2SMarcel Holtmann skb = __hci_cmd_sync(hdev, 0xfc06, 6, bdaddr, HCI_INIT_TIMEOUT); 126*afd2daa2SMarcel Holtmann if (IS_ERR(skb)) 127*afd2daa2SMarcel Holtmann return PTR_ERR(skb); 128*afd2daa2SMarcel Holtmann 129*afd2daa2SMarcel Holtmann kfree_skb(skb); 130*afd2daa2SMarcel Holtmann return 0; 131*afd2daa2SMarcel Holtmann } 132*afd2daa2SMarcel Holtmann 133*afd2daa2SMarcel Holtmann static int virtbt_setup_intel(struct hci_dev *hdev) 134*afd2daa2SMarcel Holtmann { 135*afd2daa2SMarcel Holtmann struct sk_buff *skb; 136*afd2daa2SMarcel Holtmann 137*afd2daa2SMarcel Holtmann /* Intel Read Version */ 138*afd2daa2SMarcel Holtmann skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT); 139*afd2daa2SMarcel Holtmann if (IS_ERR(skb)) 140*afd2daa2SMarcel Holtmann return PTR_ERR(skb); 141*afd2daa2SMarcel Holtmann 142*afd2daa2SMarcel Holtmann kfree_skb(skb); 143*afd2daa2SMarcel Holtmann return 0; 144*afd2daa2SMarcel Holtmann } 145*afd2daa2SMarcel Holtmann 146*afd2daa2SMarcel Holtmann static int virtbt_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr) 147*afd2daa2SMarcel Holtmann { 148*afd2daa2SMarcel Holtmann struct sk_buff *skb; 149*afd2daa2SMarcel Holtmann 150*afd2daa2SMarcel Holtmann /* Intel Write BD Address */ 151*afd2daa2SMarcel Holtmann skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT); 152*afd2daa2SMarcel Holtmann if (IS_ERR(skb)) 153*afd2daa2SMarcel Holtmann return PTR_ERR(skb); 154*afd2daa2SMarcel Holtmann 155*afd2daa2SMarcel Holtmann kfree_skb(skb); 156*afd2daa2SMarcel Holtmann return 0; 157*afd2daa2SMarcel Holtmann } 158*afd2daa2SMarcel Holtmann 159*afd2daa2SMarcel Holtmann static int virtbt_setup_realtek(struct hci_dev *hdev) 160*afd2daa2SMarcel Holtmann { 161*afd2daa2SMarcel Holtmann struct sk_buff *skb; 162*afd2daa2SMarcel Holtmann 163*afd2daa2SMarcel Holtmann /* Read ROM Version */ 164*afd2daa2SMarcel Holtmann skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT); 165*afd2daa2SMarcel Holtmann if (IS_ERR(skb)) 166*afd2daa2SMarcel Holtmann return PTR_ERR(skb); 167*afd2daa2SMarcel Holtmann 168*afd2daa2SMarcel Holtmann bt_dev_info(hdev, "ROM version %u", *((__u8 *) (skb->data + 1))); 169*afd2daa2SMarcel Holtmann 170*afd2daa2SMarcel Holtmann kfree_skb(skb); 171*afd2daa2SMarcel Holtmann return 0; 172*afd2daa2SMarcel Holtmann } 173*afd2daa2SMarcel Holtmann 174*afd2daa2SMarcel Holtmann static int virtbt_shutdown_generic(struct hci_dev *hdev) 175*afd2daa2SMarcel Holtmann { 176*afd2daa2SMarcel Holtmann struct sk_buff *skb; 177*afd2daa2SMarcel Holtmann 178*afd2daa2SMarcel Holtmann /* Reset */ 179*afd2daa2SMarcel Holtmann skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); 180*afd2daa2SMarcel Holtmann if (IS_ERR(skb)) 181*afd2daa2SMarcel Holtmann return PTR_ERR(skb); 182*afd2daa2SMarcel Holtmann 183*afd2daa2SMarcel Holtmann kfree_skb(skb); 184*afd2daa2SMarcel Holtmann return 0; 185*afd2daa2SMarcel Holtmann } 186*afd2daa2SMarcel Holtmann 187*afd2daa2SMarcel Holtmann static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb) 188*afd2daa2SMarcel Holtmann { 189*afd2daa2SMarcel Holtmann __u8 pkt_type; 190*afd2daa2SMarcel Holtmann 191*afd2daa2SMarcel Holtmann pkt_type = *((__u8 *) skb->data); 192*afd2daa2SMarcel Holtmann skb_pull(skb, 1); 193*afd2daa2SMarcel Holtmann 194*afd2daa2SMarcel Holtmann switch (pkt_type) { 195*afd2daa2SMarcel Holtmann case HCI_EVENT_PKT: 196*afd2daa2SMarcel Holtmann case HCI_ACLDATA_PKT: 197*afd2daa2SMarcel Holtmann case HCI_SCODATA_PKT: 198*afd2daa2SMarcel Holtmann case HCI_ISODATA_PKT: 199*afd2daa2SMarcel Holtmann hci_skb_pkt_type(skb) = pkt_type; 200*afd2daa2SMarcel Holtmann hci_recv_frame(vbt->hdev, skb); 201*afd2daa2SMarcel Holtmann break; 202*afd2daa2SMarcel Holtmann } 203*afd2daa2SMarcel Holtmann } 204*afd2daa2SMarcel Holtmann 205*afd2daa2SMarcel Holtmann static void virtbt_rx_work(struct work_struct *work) 206*afd2daa2SMarcel Holtmann { 207*afd2daa2SMarcel Holtmann struct virtio_bluetooth *vbt = container_of(work, 208*afd2daa2SMarcel Holtmann struct virtio_bluetooth, rx); 209*afd2daa2SMarcel Holtmann struct sk_buff *skb; 210*afd2daa2SMarcel Holtmann unsigned int len; 211*afd2daa2SMarcel Holtmann 212*afd2daa2SMarcel Holtmann skb = virtqueue_get_buf(vbt->vqs[VIRTBT_VQ_RX], &len); 213*afd2daa2SMarcel Holtmann if (!skb) 214*afd2daa2SMarcel Holtmann return; 215*afd2daa2SMarcel Holtmann 216*afd2daa2SMarcel Holtmann skb->len = len; 217*afd2daa2SMarcel Holtmann virtbt_rx_handle(vbt, skb); 218*afd2daa2SMarcel Holtmann 219*afd2daa2SMarcel Holtmann if (virtbt_add_inbuf(vbt) < 0) 220*afd2daa2SMarcel Holtmann return; 221*afd2daa2SMarcel Holtmann 222*afd2daa2SMarcel Holtmann virtqueue_kick(vbt->vqs[VIRTBT_VQ_RX]); 223*afd2daa2SMarcel Holtmann } 224*afd2daa2SMarcel Holtmann 225*afd2daa2SMarcel Holtmann static void virtbt_tx_done(struct virtqueue *vq) 226*afd2daa2SMarcel Holtmann { 227*afd2daa2SMarcel Holtmann struct sk_buff *skb; 228*afd2daa2SMarcel Holtmann unsigned int len; 229*afd2daa2SMarcel Holtmann 230*afd2daa2SMarcel Holtmann while ((skb = virtqueue_get_buf(vq, &len))) 231*afd2daa2SMarcel Holtmann kfree_skb(skb); 232*afd2daa2SMarcel Holtmann } 233*afd2daa2SMarcel Holtmann 234*afd2daa2SMarcel Holtmann static void virtbt_rx_done(struct virtqueue *vq) 235*afd2daa2SMarcel Holtmann { 236*afd2daa2SMarcel Holtmann struct virtio_bluetooth *vbt = vq->vdev->priv; 237*afd2daa2SMarcel Holtmann 238*afd2daa2SMarcel Holtmann schedule_work(&vbt->rx); 239*afd2daa2SMarcel Holtmann } 240*afd2daa2SMarcel Holtmann 241*afd2daa2SMarcel Holtmann static int virtbt_probe(struct virtio_device *vdev) 242*afd2daa2SMarcel Holtmann { 243*afd2daa2SMarcel Holtmann vq_callback_t *callbacks[VIRTBT_NUM_VQS] = { 244*afd2daa2SMarcel Holtmann [VIRTBT_VQ_TX] = virtbt_tx_done, 245*afd2daa2SMarcel Holtmann [VIRTBT_VQ_RX] = virtbt_rx_done, 246*afd2daa2SMarcel Holtmann }; 247*afd2daa2SMarcel Holtmann const char *names[VIRTBT_NUM_VQS] = { 248*afd2daa2SMarcel Holtmann [VIRTBT_VQ_TX] = "tx", 249*afd2daa2SMarcel Holtmann [VIRTBT_VQ_RX] = "rx", 250*afd2daa2SMarcel Holtmann }; 251*afd2daa2SMarcel Holtmann struct virtio_bluetooth *vbt; 252*afd2daa2SMarcel Holtmann struct hci_dev *hdev; 253*afd2daa2SMarcel Holtmann int err; 254*afd2daa2SMarcel Holtmann __u8 type; 255*afd2daa2SMarcel Holtmann 256*afd2daa2SMarcel Holtmann if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) 257*afd2daa2SMarcel Holtmann return -ENODEV; 258*afd2daa2SMarcel Holtmann 259*afd2daa2SMarcel Holtmann type = virtio_cread8(vdev, offsetof(struct virtio_bt_config, type)); 260*afd2daa2SMarcel Holtmann 261*afd2daa2SMarcel Holtmann switch (type) { 262*afd2daa2SMarcel Holtmann case VIRTIO_BT_CONFIG_TYPE_PRIMARY: 263*afd2daa2SMarcel Holtmann case VIRTIO_BT_CONFIG_TYPE_AMP: 264*afd2daa2SMarcel Holtmann break; 265*afd2daa2SMarcel Holtmann default: 266*afd2daa2SMarcel Holtmann return -EINVAL; 267*afd2daa2SMarcel Holtmann } 268*afd2daa2SMarcel Holtmann 269*afd2daa2SMarcel Holtmann vbt = kzalloc(sizeof(*vbt), GFP_KERNEL); 270*afd2daa2SMarcel Holtmann if (!vbt) 271*afd2daa2SMarcel Holtmann return -ENOMEM; 272*afd2daa2SMarcel Holtmann 273*afd2daa2SMarcel Holtmann vdev->priv = vbt; 274*afd2daa2SMarcel Holtmann vbt->vdev = vdev; 275*afd2daa2SMarcel Holtmann 276*afd2daa2SMarcel Holtmann INIT_WORK(&vbt->rx, virtbt_rx_work); 277*afd2daa2SMarcel Holtmann 278*afd2daa2SMarcel Holtmann err = virtio_find_vqs(vdev, VIRTBT_NUM_VQS, vbt->vqs, callbacks, 279*afd2daa2SMarcel Holtmann names, NULL); 280*afd2daa2SMarcel Holtmann if (err) 281*afd2daa2SMarcel Holtmann return err; 282*afd2daa2SMarcel Holtmann 283*afd2daa2SMarcel Holtmann hdev = hci_alloc_dev(); 284*afd2daa2SMarcel Holtmann if (!hdev) { 285*afd2daa2SMarcel Holtmann err = -ENOMEM; 286*afd2daa2SMarcel Holtmann goto failed; 287*afd2daa2SMarcel Holtmann } 288*afd2daa2SMarcel Holtmann 289*afd2daa2SMarcel Holtmann vbt->hdev = hdev; 290*afd2daa2SMarcel Holtmann 291*afd2daa2SMarcel Holtmann hdev->bus = HCI_VIRTIO; 292*afd2daa2SMarcel Holtmann hdev->dev_type = type; 293*afd2daa2SMarcel Holtmann hci_set_drvdata(hdev, vbt); 294*afd2daa2SMarcel Holtmann 295*afd2daa2SMarcel Holtmann hdev->open = virtbt_open; 296*afd2daa2SMarcel Holtmann hdev->close = virtbt_close; 297*afd2daa2SMarcel Holtmann hdev->flush = virtbt_flush; 298*afd2daa2SMarcel Holtmann hdev->send = virtbt_send_frame; 299*afd2daa2SMarcel Holtmann 300*afd2daa2SMarcel Holtmann if (virtio_has_feature(vdev, VIRTIO_BT_F_VND_HCI)) { 301*afd2daa2SMarcel Holtmann __u16 vendor; 302*afd2daa2SMarcel Holtmann 303*afd2daa2SMarcel Holtmann virtio_cread(vdev, struct virtio_bt_config, vendor, &vendor); 304*afd2daa2SMarcel Holtmann 305*afd2daa2SMarcel Holtmann switch (vendor) { 306*afd2daa2SMarcel Holtmann case VIRTIO_BT_CONFIG_VENDOR_ZEPHYR: 307*afd2daa2SMarcel Holtmann hdev->manufacturer = 1521; 308*afd2daa2SMarcel Holtmann hdev->setup = virtbt_setup_zephyr; 309*afd2daa2SMarcel Holtmann hdev->shutdown = virtbt_shutdown_generic; 310*afd2daa2SMarcel Holtmann hdev->set_bdaddr = virtbt_set_bdaddr_zephyr; 311*afd2daa2SMarcel Holtmann break; 312*afd2daa2SMarcel Holtmann 313*afd2daa2SMarcel Holtmann case VIRTIO_BT_CONFIG_VENDOR_INTEL: 314*afd2daa2SMarcel Holtmann hdev->manufacturer = 2; 315*afd2daa2SMarcel Holtmann hdev->setup = virtbt_setup_intel; 316*afd2daa2SMarcel Holtmann hdev->shutdown = virtbt_shutdown_generic; 317*afd2daa2SMarcel Holtmann hdev->set_bdaddr = virtbt_set_bdaddr_intel; 318*afd2daa2SMarcel Holtmann set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); 319*afd2daa2SMarcel Holtmann set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); 320*afd2daa2SMarcel Holtmann set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); 321*afd2daa2SMarcel Holtmann break; 322*afd2daa2SMarcel Holtmann 323*afd2daa2SMarcel Holtmann case VIRTIO_BT_CONFIG_VENDOR_REALTEK: 324*afd2daa2SMarcel Holtmann hdev->manufacturer = 93; 325*afd2daa2SMarcel Holtmann hdev->setup = virtbt_setup_realtek; 326*afd2daa2SMarcel Holtmann hdev->shutdown = virtbt_shutdown_generic; 327*afd2daa2SMarcel Holtmann set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); 328*afd2daa2SMarcel Holtmann set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); 329*afd2daa2SMarcel Holtmann break; 330*afd2daa2SMarcel Holtmann } 331*afd2daa2SMarcel Holtmann } 332*afd2daa2SMarcel Holtmann 333*afd2daa2SMarcel Holtmann if (virtio_has_feature(vdev, VIRTIO_BT_F_MSFT_EXT)) { 334*afd2daa2SMarcel Holtmann __u16 msft_opcode; 335*afd2daa2SMarcel Holtmann 336*afd2daa2SMarcel Holtmann virtio_cread(vdev, struct virtio_bt_config, 337*afd2daa2SMarcel Holtmann msft_opcode, &msft_opcode); 338*afd2daa2SMarcel Holtmann 339*afd2daa2SMarcel Holtmann hci_set_msft_opcode(hdev, msft_opcode); 340*afd2daa2SMarcel Holtmann } 341*afd2daa2SMarcel Holtmann 342*afd2daa2SMarcel Holtmann if (virtio_has_feature(vdev, VIRTIO_BT_F_AOSP_EXT)) 343*afd2daa2SMarcel Holtmann hci_set_aosp_capable(hdev); 344*afd2daa2SMarcel Holtmann 345*afd2daa2SMarcel Holtmann if (hci_register_dev(hdev) < 0) { 346*afd2daa2SMarcel Holtmann hci_free_dev(hdev); 347*afd2daa2SMarcel Holtmann err = -EBUSY; 348*afd2daa2SMarcel Holtmann goto failed; 349*afd2daa2SMarcel Holtmann } 350*afd2daa2SMarcel Holtmann 351*afd2daa2SMarcel Holtmann return 0; 352*afd2daa2SMarcel Holtmann 353*afd2daa2SMarcel Holtmann failed: 354*afd2daa2SMarcel Holtmann vdev->config->del_vqs(vdev); 355*afd2daa2SMarcel Holtmann return err; 356*afd2daa2SMarcel Holtmann } 357*afd2daa2SMarcel Holtmann 358*afd2daa2SMarcel Holtmann static void virtbt_remove(struct virtio_device *vdev) 359*afd2daa2SMarcel Holtmann { 360*afd2daa2SMarcel Holtmann struct virtio_bluetooth *vbt = vdev->priv; 361*afd2daa2SMarcel Holtmann struct hci_dev *hdev = vbt->hdev; 362*afd2daa2SMarcel Holtmann 363*afd2daa2SMarcel Holtmann hci_unregister_dev(hdev); 364*afd2daa2SMarcel Holtmann vdev->config->reset(vdev); 365*afd2daa2SMarcel Holtmann 366*afd2daa2SMarcel Holtmann hci_free_dev(hdev); 367*afd2daa2SMarcel Holtmann vbt->hdev = NULL; 368*afd2daa2SMarcel Holtmann 369*afd2daa2SMarcel Holtmann vdev->config->del_vqs(vdev); 370*afd2daa2SMarcel Holtmann kfree(vbt); 371*afd2daa2SMarcel Holtmann } 372*afd2daa2SMarcel Holtmann 373*afd2daa2SMarcel Holtmann static struct virtio_device_id virtbt_table[] = { 374*afd2daa2SMarcel Holtmann { VIRTIO_ID_BT, VIRTIO_DEV_ANY_ID }, 375*afd2daa2SMarcel Holtmann { 0 }, 376*afd2daa2SMarcel Holtmann }; 377*afd2daa2SMarcel Holtmann 378*afd2daa2SMarcel Holtmann MODULE_DEVICE_TABLE(virtio, virtbt_table); 379*afd2daa2SMarcel Holtmann 380*afd2daa2SMarcel Holtmann static const unsigned int virtbt_features[] = { 381*afd2daa2SMarcel Holtmann VIRTIO_BT_F_VND_HCI, 382*afd2daa2SMarcel Holtmann VIRTIO_BT_F_MSFT_EXT, 383*afd2daa2SMarcel Holtmann VIRTIO_BT_F_AOSP_EXT, 384*afd2daa2SMarcel Holtmann }; 385*afd2daa2SMarcel Holtmann 386*afd2daa2SMarcel Holtmann static struct virtio_driver virtbt_driver = { 387*afd2daa2SMarcel Holtmann .driver.name = KBUILD_MODNAME, 388*afd2daa2SMarcel Holtmann .driver.owner = THIS_MODULE, 389*afd2daa2SMarcel Holtmann .feature_table = virtbt_features, 390*afd2daa2SMarcel Holtmann .feature_table_size = ARRAY_SIZE(virtbt_features), 391*afd2daa2SMarcel Holtmann .id_table = virtbt_table, 392*afd2daa2SMarcel Holtmann .probe = virtbt_probe, 393*afd2daa2SMarcel Holtmann .remove = virtbt_remove, 394*afd2daa2SMarcel Holtmann }; 395*afd2daa2SMarcel Holtmann 396*afd2daa2SMarcel Holtmann module_virtio_driver(virtbt_driver); 397*afd2daa2SMarcel Holtmann 398*afd2daa2SMarcel Holtmann MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 399*afd2daa2SMarcel Holtmann MODULE_DESCRIPTION("Generic Bluetooth VIRTIO driver ver " VERSION); 400*afd2daa2SMarcel Holtmann MODULE_VERSION(VERSION); 401*afd2daa2SMarcel Holtmann MODULE_LICENSE("GPL"); 402