static void btusb_bulk_complete(struct urb *urb) { struct hci_dev *hdev = urb->context; struct btusb_data *data = hci_get_drvdata(hdev); int err; BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) return; if (urb->status == 0) { hdev->stat.byte_rx += urb->actual_length; if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, urb->transfer_buffer, urb->actual_length) < 0) { BT_ERR("%s corrupted ACL packet", hdev->name); hdev->stat.err_rx++; } } if (!test_bit(BTUSB_BULK_RUNNING, &data->flags)) return; usb_anchor_urb(urb, &data->bulk_anchor); usb_mark_last_busy(data->udev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { /* -EPERM: urb is being killed; * -ENODEV: device got disconnected */ if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p failed to resubmit (%d)", hdev->name, urb, -err); usb_unanchor_urb(urb); } }
static int bluecard_hci_close(struct hci_dev *hdev) { bluecard_info_t *info = hci_get_drvdata(hdev); if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) return 0; bluecard_hci_flush(hdev); if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) unsigned int iobase = info->p_dev->resource[0]->start; #else unsigned int iobase = info->p_dev->io.BasePort1; #endif /* Disable LED */ outb(0x00, iobase + 0x30); } return 0; }
static int bluecard_hci_open(struct hci_dev *hdev) { bluecard_info_t *info = hci_get_drvdata(hdev); if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); if (test_and_set_bit(HCI_RUNNING, &(hdev->flags))) return 0; if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) unsigned int iobase = info->p_dev->resource[0]->start; #else unsigned int iobase = info->p_dev->io.BasePort1; #endif /* Enable LED */ outb(0x08 | 0x20, iobase + 0x30); } return 0; }
/* Send frames from HCI layer */ static int hci_uart_send_frame(struct sk_buff *skb) { struct hci_dev* hdev = (struct hci_dev *) skb->dev; struct hci_uart *hu; if (!hdev) { BT_ERR("Frame for unknown device (hdev=NULL)"); return -ENODEV; } if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; hu = hci_get_drvdata(hdev); BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); hu->proto->enqueue(hu, skb); hci_uart_tx_wakeup(hu); return 0; }
static int nokia_recv_negotiation_packet(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_uart *hu = hci_get_drvdata(hdev); struct nokia_bt_dev *btdev = hu->priv; struct device *dev = &btdev->serdev->dev; struct hci_nokia_neg_hdr *hdr; struct hci_nokia_neg_evt *evt; int ret = 0; hdr = (struct hci_nokia_neg_hdr *)skb->data; if (hdr->dlen != sizeof(*evt)) { btdev->init_error = -EIO; ret = -EIO; goto finish_neg; } evt = skb_pull(skb, sizeof(*hdr)); if (evt->ack != NOKIA_NEG_ACK) { dev_err(dev, "Negotiation received: wrong reply"); btdev->init_error = -EINVAL; ret = -EINVAL; goto finish_neg; } btdev->man_id = evt->man_id; btdev->ver_id = evt->ver_id; dev_dbg(dev, "Negotiation received: baud=%u:clk=%u:manu=%u:vers=%u", evt->baud, evt->sys_clk, evt->man_id, evt->ver_id); finish_neg: complete(&btdev->init_completion); kfree_skb(skb); return ret; }
static int ti_st_send_frame(struct sk_buff *skb) { struct hci_dev *hdev; struct ti_st *hst; long len; hdev = (struct hci_dev *)skb->dev; if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; hst = hci_get_drvdata(hdev); /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); /* Insert skb to shared transport layer's transmit queue. * Freeing skb memory is taken care in shared transport layer, * so don't free skb memory here. */ len = hst->st_write(skb); if (len < 0) { kfree_skb(skb); BT_ERR("ST write failed (%ld)", len); /* Try Again, would only fail if UART has gone bad */ return -EAGAIN; } /* ST accepted our skb. So, Go ahead and do rest */ hdev->stat.byte_tx += len; ti_st_tx_complete(hst, bt_cb(skb)->pkt_type); return 0; }
BthIsr(int irq, void *dev_instance, struct pt_regs *regs) #endif { struct hci_dev *hdev = (struct hci_dev *)dev_instance; struct rtbt_os_ctrl *os_ctrl; int retval = -1; //printk("-->Into BthIsr()\n"); ASSERT(hdev); if (!test_bit(HCI_RUNNING, &hdev->flags)) { printk("%s():-->HCI_RUNNING not set!\n", __FUNCTION__); goto done; } if (hdev){ os_ctrl = (struct rtbt_os_ctrl *) hci_get_drvdata(hdev); ASSERT(os_ctrl); if (os_ctrl && os_ctrl->if_ops.pci_ops.isr) { retval = (os_ctrl->if_ops.pci_ops.isr)(os_ctrl->dev_ctrl); } else { if (os_ctrl) printk("Err, Shiang, os_ctrl->if_ops.pci_ops.isr=0x%p\n", os_ctrl->if_ops.pci_ops.isr); } } done: //printk("<--BthIsr Done, retval=%d\n", retval); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) return IRQ_HANDLED; #endif }
static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { struct bluecard_info *info = hci_get_drvdata(hdev); switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: hdev->stat.sco_tx++; break; } /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); skb_queue_tail(&(info->txq), skb); bluecard_write_wakeup(info); return 0; }
static int hci_uart_setup(struct hci_dev *hdev) { struct hci_uart *hu = hci_get_drvdata(hdev); struct hci_rp_read_local_version *ver; struct sk_buff *skb; unsigned int speed; int err; /* Init speed if any */ if (hu->init_speed) speed = hu->init_speed; else if (hu->proto->init_speed) speed = hu->proto->init_speed; else speed = 0; if (speed) hci_uart_set_baudrate(hu, speed); /* Operational speed if any */ if (hu->oper_speed) speed = hu->oper_speed; else if (hu->proto->oper_speed) speed = hu->proto->oper_speed; else speed = 0; if (hu->proto->set_baudrate && speed) { err = hu->proto->set_baudrate(hu, speed); if (!err) hci_uart_set_baudrate(hu, speed); } if (hu->proto->setup) return hu->proto->setup(hu); if (!test_bit(HCI_UART_VND_DETECT, &hu->hdev_flags)) return 0; skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { BT_ERR("%s: Reading local version information failed (%ld)", hdev->name, PTR_ERR(skb)); return 0; } if (skb->len != sizeof(*ver)) { BT_ERR("%s: Event length mismatch for version information", hdev->name); goto done; } ver = (struct hci_rp_read_local_version *)skb->data; switch (le16_to_cpu(ver->manufacturer)) { #ifdef CONFIG_BT_HCIUART_INTEL case 2: hdev->set_bdaddr = btintel_set_bdaddr; btintel_check_bdaddr(hdev); break; #endif #ifdef CONFIG_BT_HCIUART_BCM case 15: hdev->set_bdaddr = btbcm_set_bdaddr; btbcm_check_bdaddr(hdev); break; #endif } done: kfree_skb(skb); return 0; }
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, const unsigned char *buffer, int count, const struct h4_recv_pkt *pkts, int pkts_count) { struct hci_uart *hu = hci_get_drvdata(hdev); u8 alignment = hu->alignment ? hu->alignment : 1; while (count) { int i, len; /* remove padding bytes from buffer */ for (; hu->padding && count > 0; hu->padding--) { count--; buffer++; } if (!count) break; if (!skb) { for (i = 0; i < pkts_count; i++) { if (buffer[0] != (&pkts[i])->type) continue; skb = bt_skb_alloc((&pkts[i])->maxlen, GFP_ATOMIC); if (!skb) return ERR_PTR(-ENOMEM); hci_skb_pkt_type(skb) = (&pkts[i])->type; hci_skb_expect(skb) = (&pkts[i])->hlen; break; } /* Check for invalid packet type */ if (!skb) return ERR_PTR(-EILSEQ); count -= 1; buffer += 1; } len = min_t(uint, hci_skb_expect(skb) - skb->len, count); skb_put_data(skb, buffer, len); count -= len; buffer += len; /* Check for partial packet */ if (skb->len < hci_skb_expect(skb)) continue; for (i = 0; i < pkts_count; i++) { if (hci_skb_pkt_type(skb) == (&pkts[i])->type) break; } if (i >= pkts_count) { kfree_skb(skb); return ERR_PTR(-EILSEQ); } if (skb->len == (&pkts[i])->hlen) { u16 dlen; switch ((&pkts[i])->lsize) { case 0: /* No variable data length */ dlen = 0; break; case 1: /* Single octet variable length */ dlen = skb->data[(&pkts[i])->loff]; hci_skb_expect(skb) += dlen; if (skb_tailroom(skb) < dlen) { kfree_skb(skb); return ERR_PTR(-EMSGSIZE); } break; case 2: /* Double octet variable length */ dlen = get_unaligned_le16(skb->data + (&pkts[i])->loff); hci_skb_expect(skb) += dlen; if (skb_tailroom(skb) < dlen) { kfree_skb(skb); return ERR_PTR(-EMSGSIZE); } break; default: /* Unsupported variable length */ kfree_skb(skb); return ERR_PTR(-EILSEQ); } if (!dlen) { hu->padding = (skb->len - 1) % alignment; hu->padding = (alignment - hu->padding) % alignment; /* No more data, complete frame */ (&pkts[i])->recv(hdev, skb); skb = NULL; } } else { hu->padding = (skb->len - 1) % alignment; hu->padding = (alignment - hu->padding) % alignment; /* Complete frame */ (&pkts[i])->recv(hdev, skb); skb = NULL; } } return skb; }
static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { struct bfusb_data *data = hci_get_drvdata(hdev); struct sk_buff *nskb; unsigned char buf[3]; int sent = 0, size, count; BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len); switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: hdev->stat.sco_tx++; break; } /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); count = skb->len; /* Max HCI frame size seems to be 1511 + 1 */ nskb = bt_skb_alloc(count + 32, GFP_ATOMIC); if (!nskb) { BT_ERR("Can't allocate memory for new packet"); return -ENOMEM; } nskb->dev = (void *) data; while (count) { size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE); buf[0] = 0xc1 | ((sent == 0) ? 0x04 : 0) | ((count == size) ? 0x08 : 0); buf[1] = 0x00; buf[2] = (size == BFUSB_MAX_BLOCK_SIZE) ? 0 : size; memcpy(skb_put(nskb, 3), buf, 3); skb_copy_from_linear_data_offset(skb, sent, skb_put(nskb, size), size); sent += size; count -= size; } /* Don't send frame with multiple size of bulk max packet */ if ((nskb->len % data->bulk_pkt_size) == 0) { buf[0] = 0xdd; buf[1] = 0x00; memcpy(skb_put(nskb, 2), buf, 2); } read_lock(&data->lock); skb_queue_tail(&data->transmit_q, nskb); bfusb_tx_wakeup(data); read_unlock(&data->lock); kfree_skb(skb); return 0; }
static int btusb_setup_bcm_patchram(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct usb_device *udev = data->udev; char fw_name[64]; const struct firmware *fw; const u8 *fw_ptr; size_t fw_size; const struct hci_command_hdr *cmd; const u8 *cmd_param; u16 opcode; struct sk_buff *skb; struct hci_rp_read_local_version *ver; long ret; snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd", udev->product ? udev->product : "BCM", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); ret = request_firmware(&fw, fw_name, &hdev->dev); if (ret < 0) { BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name); return 0; } /* Reset */ skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret); goto done; } kfree_skb(skb); /* Read Local Version Info */ skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", hdev->name, ret); goto done; } if (skb->len != sizeof(*ver)) { BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", hdev->name); kfree_skb(skb); ret = -EIO; goto done; } ver = (struct hci_rp_read_local_version *) skb->data; BT_INFO("%s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x " "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, ver->lmp_ver, ver->lmp_subver); kfree_skb(skb); /* Start Download */ skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: BCM: Download Minidrv command failed (%ld)", hdev->name, ret); goto reset_fw; } kfree_skb(skb); /* 50 msec delay after Download Minidrv completes */ msleep(50); fw_ptr = fw->data; fw_size = fw->size; while (fw_size >= sizeof(*cmd)) { cmd = (struct hci_command_hdr *) fw_ptr; fw_ptr += sizeof(*cmd); fw_size -= sizeof(*cmd); if (fw_size < cmd->plen) { BT_ERR("%s: BCM: patch %s is corrupted", hdev->name, fw_name); ret = -EINVAL; goto reset_fw; } cmd_param = fw_ptr; fw_ptr += cmd->plen; fw_size -= cmd->plen; opcode = le16_to_cpu(cmd->opcode); skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: BCM: patch command %04x failed (%ld)", hdev->name, opcode, ret); goto reset_fw; } kfree_skb(skb); } /* 250 msec delay after Launch Ram completes */ msleep(250); reset_fw: /* Reset */ skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret); goto done; } kfree_skb(skb); /* Read Local Version Info */ skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", hdev->name, ret); goto done; } if (skb->len != sizeof(*ver)) { BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", hdev->name); kfree_skb(skb); ret = -EIO; goto done; } ver = (struct hci_rp_read_local_version *) skb->data; BT_INFO("%s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x " "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, ver->lmp_ver, ver->lmp_subver); kfree_skb(skb); done: release_firmware(fw); return ret; }
static int btusb_send_frame(struct sk_buff *skb) { struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct btusb_data *data = hci_get_drvdata(hdev); struct usb_ctrlrequest *dr; struct urb *urb; unsigned int pipe; int err; BT_DBG("%s", hdev->name); if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; dr = kmalloc(sizeof(*dr), GFP_ATOMIC); if (!dr) { usb_free_urb(urb); return -ENOMEM; } dr->bRequestType = data->cmdreq_type; dr->bRequest = 0; dr->wIndex = 0; dr->wValue = 0; dr->wLength = __cpu_to_le16(skb->len); pipe = usb_sndctrlpipe(data->udev, 0x00); usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, skb->data, skb->len, btusb_tx_complete, skb); hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: if (!data->bulk_tx_ep) return -ENODEV; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, btusb_tx_complete, skb); hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1) return -ENODEV; urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); if (!urb) return -ENOMEM; pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress); usb_fill_int_urb(urb, data->udev, pipe, skb->data, skb->len, btusb_isoc_tx_complete, skb, data->isoc_tx_ep->bInterval); urb->transfer_flags = URB_ISO_ASAP; __fill_isoc_descriptor(urb, skb->len, le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); hdev->stat.sco_tx++; goto skip_waking; default: return -EILSEQ; } err = inc_tx(data); if (err) { usb_anchor_urb(urb, &data->deferred); schedule_work(&data->waker); err = 0; goto done; } skip_waking: usb_anchor_urb(urb, &data->tx_anchor); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p submission failed (%d)", hdev->name, urb, -err); kfree(urb->setup_packet); usb_unanchor_urb(urb); } else { usb_mark_last_busy(data->udev); } done: usb_free_urb(urb); return err; }
int rtbt_hci_dev_send(struct hci_dev *hdev, struct sk_buff *skb) { //struct hci_dev *hdev = (struct hci_dev *)skb->dev; struct rtbt_os_ctrl *os_ctrl = (struct rtbt_os_ctrl *)hci_get_drvdata(hdev); struct rtbt_hps_ops *hps_ops; unsigned char pkt_type; int status; //printk("-->%s():\n", __FUNCTION__); pkt_type = rtbt_get_pkt_type(skb); //printk("hciName:%s type:%s(%d) len:%d\n", // hdev->name, pkt_type_str[pkt_type], // pkt_type, skb->len); // if (pkt_type == HCI_COMMAND_PKT) // hex_dump("rtbt_hci_dev_send: HCI_CMD", skb->data, skb->len); // else if (pkt_type == HCI_SCODATA_PKT) // hex_dump("rtbt_hci_dev_send: HCI_SCO", skb->data, skb->len); if (!os_ctrl || !os_ctrl->hps_ops) { kfree_skb(skb); return -1; } hps_ops = os_ctrl->hps_ops; if ((!hps_ops->hci_cmd) || (!hps_ops->hci_acl_data) || (!hps_ops->hci_sco_data)) { printk("Err, Null Handler!hci_cmd=0x%p, acl_data=0x%p, sco_data=0x%p!\n", hps_ops->hci_cmd, hps_ops->hci_acl_data, hps_ops->hci_sco_data); kfree_skb(skb); return -1; } switch (pkt_type) { case HCI_COMMAND_PKT: status = hps_ops->hci_cmd(os_ctrl->dev_ctrl, skb->data, skb->len); if( (hdev!=0) && (status == 0)){ hdev->stat.cmd_tx++; } break; case HCI_ACLDATA_PKT: status = hps_ops->hci_acl_data(os_ctrl->dev_ctrl, skb->data, skb->len); if( (hdev!=0) && (status == 0)){ hdev->stat.acl_tx++; } break; case HCI_SCODATA_PKT: printk("-->%s():sco len=%d,time=0x%lx\n", __FUNCTION__, skb->len, jiffies); //os_ctrl->sco_tx_seq = bt_cb(skb)->control.txseq; os_ctrl->sco_time_hci = jiffies; status = hps_ops->hci_sco_data(os_ctrl->dev_ctrl, skb->data, skb->len); if( (hdev!=0) && (status == 0)){ hdev->stat.sco_tx++; } printk("<--%s():sco done, time=0x%lx\n", __FUNCTION__, jiffies); break; case HCI_VENDOR_PKT: break; } if( (hdev!=0) && (status == 0)){ hdev->stat.byte_tx += skb->len; } else { hdev->stat.err_tx++; } kfree_skb(skb); //printk("<--%s():\n", __FUNCTION__); return 0; }
int rtbt_hci_dev_send(struct hci_dev *hdev, struct sk_buff *skb) { struct rtbt_os_ctrl *os_ctrl = (struct rtbt_os_ctrl *)hci_get_drvdata(hdev); struct rtbt_hps_ops *hps_ops; unsigned char pkt_type; int status; //printk("-->%s():\n", __FUNCTION__); pkt_type = rtbt_get_pkt_type(skb); //printk("hciName:%s type:%s(%d) len:%d\n", // hdev->name, pkt_type_str[pkt_type], // pkt_type, skb->len); // if (pkt_type == HCI_COMMAND_PKT) // hex_dump("rtbt_hci_dev_send: HCI_CMD", skb->data, skb->len); // else if (pkt_type == HCI_SCODATA_PKT) // hex_dump("rtbt_hci_dev_send: HCI_SCO", skb->data, skb->len); if (!os_ctrl || !os_ctrl->hps_ops) { kfree_skb(skb); return -1; } hps_ops = os_ctrl->hps_ops; if ((!hps_ops->hci_cmd) || (!hps_ops->hci_acl_data) || (!hps_ops->hci_sco_data)) { printk("Err, Null Handler!hci_cmd=0x%p, acl_data=0x%p, sco_data=0x%p!\n", hps_ops->hci_cmd, hps_ops->hci_acl_data, hps_ops->hci_sco_data); kfree_skb(skb); return -1; } switch (pkt_type) { case HCI_COMMAND_PKT: status = hps_ops->hci_cmd(os_ctrl->dev_ctrl, skb->data, skb->len); if( (hdev!=0) && (status == 0)){ hdev->stat.cmd_tx++; } break; case HCI_ACLDATA_PKT: status = hps_ops->hci_acl_data(os_ctrl->dev_ctrl, skb->data, skb->len); if( (hdev!=0) && (status == 0)){ hdev->stat.acl_tx++; } break; case HCI_SCODATA_PKT: printk("-->%s():sco len=%d,time=0x%lx\n", __FUNCTION__, skb->len, jiffies); /* Another kludge to get it to compile in 3.2.51 of debian. - The version is probably incorrect, but it is good enough for my purposes. */ #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,2,51) os_ctrl->sco_tx_seq = bt_cb(skb)->tx_seq; #else os_ctrl->sco_tx_seq = bt_cb(skb)->control.txseq; #endif os_ctrl->sco_time_hci = jiffies; status = hps_ops->hci_sco_data(os_ctrl->dev_ctrl, skb->data, skb->len); if( (hdev!=0) && (status == 0)){ hdev->stat.sco_tx++; } printk("<--%s():sco done, time=0x%lx\n", __FUNCTION__, jiffies); break; case HCI_VENDOR_PKT: break; } if( (hdev!=0) && (status == 0)){ hdev->stat.byte_tx += skb->len; } else { hdev->stat.err_tx++; } kfree_skb(skb); //printk("<--%s():\n", __FUNCTION__); return 0; }
static int bpa10x_send_frame(struct sk_buff *skb) { struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct bpa10x_data *data = hci_get_drvdata(hdev); struct usb_ctrlrequest *dr; struct urb *urb; unsigned int pipe; int err; BT_DBG("%s", hdev->name); if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; /* Prepend skb with frame type */ *skb_push(skb, 1) = bt_cb(skb)->pkt_type; switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: dr = kmalloc(sizeof(*dr), GFP_ATOMIC); if (!dr) { usb_free_urb(urb); return -ENOMEM; } dr->bRequestType = USB_TYPE_VENDOR; dr->bRequest = 0; dr->wIndex = 0; dr->wValue = 0; dr->wLength = __cpu_to_le16(skb->len); pipe = usb_sndctrlpipe(data->udev, 0x00); usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, skb->data, skb->len, bpa10x_tx_complete, skb); hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: pipe = usb_sndbulkpipe(data->udev, 0x02); usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, bpa10x_tx_complete, skb); hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: pipe = usb_sndbulkpipe(data->udev, 0x02); usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, bpa10x_tx_complete, skb); hdev->stat.sco_tx++; break; default: usb_free_urb(urb); return -EILSEQ; } usb_anchor_urb(urb, &data->tx_anchor); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { BT_ERR("%s urb %p submission failed", hdev->name, urb); kfree(urb->setup_packet); usb_unanchor_urb(urb); } usb_free_urb(urb); return 0; }
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count) { struct bpa10x_data *data = hci_get_drvdata(hdev); BT_DBG("%s queue %d buffer %p count %d", hdev->name, queue, buf, count); if (queue < 0 || queue > 1) return -EILSEQ; hdev->stat.byte_rx += count; while (count) { struct sk_buff *skb = data->rx_skb[queue]; struct { __u8 type; int expect; } *scb; int type, len = 0; if (!skb) { /* Start of the frame */ type = *((__u8 *) buf); count--; buf++; switch (type) { case HCI_EVENT_PKT: if (count >= HCI_EVENT_HDR_SIZE) { struct hci_event_hdr *h = buf; len = HCI_EVENT_HDR_SIZE + h->plen; } else return -EILSEQ; break; case HCI_ACLDATA_PKT: if (count >= HCI_ACL_HDR_SIZE) { struct hci_acl_hdr *h = buf; len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen); } else return -EILSEQ; break; case HCI_SCODATA_PKT: if (count >= HCI_SCO_HDR_SIZE) { struct hci_sco_hdr *h = buf; len = HCI_SCO_HDR_SIZE + h->dlen; } else return -EILSEQ; break; case HCI_VENDOR_PKT: if (count >= HCI_VENDOR_HDR_SIZE) { struct hci_vendor_hdr *h = buf; len = HCI_VENDOR_HDR_SIZE + __le16_to_cpu(h->dlen); } else return -EILSEQ; break; } skb = bt_skb_alloc(len, GFP_ATOMIC); if (!skb) { BT_ERR("%s no memory for packet", hdev->name); return -ENOMEM; } skb->dev = (void *) hdev; data->rx_skb[queue] = skb; scb = (void *) skb->cb; scb->type = type; scb->expect = len; } else { /* Continuation */ scb = (void *) skb->cb; len = scb->expect; } len = min(len, count); memcpy(skb_put(skb, len), buf, len); scb->expect -= len; if (scb->expect == 0) { /* Complete frame */ data->rx_skb[queue] = NULL; bt_cb(skb)->pkt_type = scb->type; hci_recv_frame(skb); } count -= len; buf += len; } return 0; }
/* Called from HCI core to initialize the device */ static int ti_st_open(struct hci_dev *hdev) { unsigned long timeleft; struct ti_st *hst; int err, i; BT_DBG("%s %p", hdev->name, hdev); if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; /* provide contexts for callbacks from ST */ hst = hci_get_drvdata(hdev); for (i = 0; i < MAX_BT_CHNL_IDS; i++) { ti_st_proto[i].priv_data = hst; ti_st_proto[i].max_frame_size = HCI_MAX_FRAME_SIZE; ti_st_proto[i].recv = st_receive; ti_st_proto[i].reg_complete_cb = st_reg_completion_cb; /* Prepare wait-for-completion handler */ init_completion(&hst->wait_reg_completion); /* Reset ST registration callback status flag, * this value will be updated in * st_reg_completion_cb() * function whenever it called from ST driver. */ hst->reg_status = -EINPROGRESS; err = st_register(&ti_st_proto[i]); if (!err) goto done; if (err != -EINPROGRESS) { clear_bit(HCI_RUNNING, &hdev->flags); BT_ERR("st_register failed %d", err); return err; } /* ST is busy with either protocol * registration or firmware download. */ BT_DBG("waiting for registration " "completion signal from ST"); timeleft = wait_for_completion_timeout (&hst->wait_reg_completion, msecs_to_jiffies(BT_REGISTER_TIMEOUT)); if (!timeleft) { clear_bit(HCI_RUNNING, &hdev->flags); BT_ERR("Timeout(%d sec),didn't get reg " "completion signal from ST", BT_REGISTER_TIMEOUT / 1000); return -ETIMEDOUT; } /* Is ST registration callback * called with ERROR status? */ if (hst->reg_status != 0) { clear_bit(HCI_RUNNING, &hdev->flags); BT_ERR("ST registration completed with invalid " "status %d", hst->reg_status); return -EAGAIN; } done: hst->st_write = ti_st_proto[i].write; if (!hst->st_write) { BT_ERR("undefined ST write function"); clear_bit(HCI_RUNNING, &hdev->flags); for (i = 0; i < MAX_BT_CHNL_IDS; i++) { /* Undo registration with ST */ err = st_unregister(&ti_st_proto[i]); if (err) BT_ERR("st_unregister() failed with " "error %d", err); hst->st_write = NULL; } return -EIO; } } return 0; }