コード例 #1
0
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);
	}
}
コード例 #2
0
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;
}
コード例 #3
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;
}
コード例 #4
0
ファイル: hci_ldisc.c プロジェクト: Kratos1982/UbuntuTouch
/* 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;
}
コード例 #5
0
ファイル: hci_nokia.c プロジェクト: farrellpeng/MX283Linux
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;
}
コード例 #6
0
ファイル: btwilink.c プロジェクト: 119-org/lamobo-d1
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;
}
コード例 #7
0
ファイル: rtbth_core_pci.c プロジェクト: andyvand/rtbth
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
}
コード例 #8
0
ファイル: bluecard_cs.c プロジェクト: 0x000000FF/edison-linux
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;
}
コード例 #9
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;
}
コード例 #10
0
ファイル: hci_h4.c プロジェクト: AlexShiLucky/linux
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;
}
コード例 #11
0
ファイル: bfusb.c プロジェクト: caseyparker/linux
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;
}
コード例 #12
0
ファイル: btusb.c プロジェクト: Kanel/CloudMAC-VAP-Driver
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;
}
コード例 #13
0
ファイル: btusb.c プロジェクト: AiWinters/linux
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;
}
コード例 #14
0
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;
}
コード例 #15
0
ファイル: rtbth_core_bluez.c プロジェクト: vhallac/rtbth
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;
}
コード例 #16
0
ファイル: bpa10x.c プロジェクト: Kratos1982/UbuntuTouch
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;
}
コード例 #17
0
ファイル: bpa10x.c プロジェクト: Kratos1982/UbuntuTouch
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;
}
コード例 #18
0
ファイル: btwilink.c プロジェクト: 119-org/lamobo-d1
/* 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;
}