Пример #1
0
static void btuart_receive(btuart_info_t *info)
{
	unsigned int iobase;
	int boguscount = 0;

	if (!info) {
		BT_ERR("Unknown device");
		return;
	}

	iobase = info->p_dev->resource[0]->start;

	do {
		info->hdev->stat.byte_rx++;

		/* Allocate packet */
		if (info->rx_skb == NULL) {
			info->rx_state = RECV_WAIT_PACKET_TYPE;
			info->rx_count = 0;
			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
				BT_ERR("Can't allocate mem for new packet");
				return;
			}
		}

		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {

			info->rx_skb->dev = (void *) info->hdev;
			bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);

			switch (bt_cb(info->rx_skb)->pkt_type) {

			case HCI_EVENT_PKT:
				info->rx_state = RECV_WAIT_EVENT_HEADER;
				info->rx_count = HCI_EVENT_HDR_SIZE;
				break;

			case HCI_ACLDATA_PKT:
				info->rx_state = RECV_WAIT_ACL_HEADER;
				info->rx_count = HCI_ACL_HDR_SIZE;
				break;

			case HCI_SCODATA_PKT:
				info->rx_state = RECV_WAIT_SCO_HEADER;
				info->rx_count = HCI_SCO_HDR_SIZE;
				break;

			default:
				/* Unknown packet */
				BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
				info->hdev->stat.err_rx++;
				clear_bit(HCI_RUNNING, &(info->hdev->flags));

				kfree_skb(info->rx_skb);
				info->rx_skb = NULL;
				break;

			}

		} else {

			*skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
			info->rx_count--;

			if (info->rx_count == 0) {

				int dlen;
				struct hci_event_hdr *eh;
				struct hci_acl_hdr *ah;
				struct hci_sco_hdr *sh;


				switch (info->rx_state) {

				case RECV_WAIT_EVENT_HEADER:
					eh = hci_event_hdr(info->rx_skb);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = eh->plen;
					break;

				case RECV_WAIT_ACL_HEADER:
					ah = hci_acl_hdr(info->rx_skb);
					dlen = __le16_to_cpu(ah->dlen);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = dlen;
					break;

				case RECV_WAIT_SCO_HEADER:
					sh = hci_sco_hdr(info->rx_skb);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = sh->dlen;
					break;

				case RECV_WAIT_DATA:
					hci_recv_frame(info->rx_skb);
					info->rx_skb = NULL;
					break;

				}

			}

		}

		/* Make sure we don't stay here too long */
		if (boguscount++ > 16)
			break;

	} while (inb(iobase + UART_LSR) & UART_LSR_DR);
}
Пример #2
0
static inline ssize_t vhci_get_user(struct vhci_data *data,
				    const char __user *buf, size_t count)
{
	struct sk_buff *skb;
	__u8 pkt_type, dev_type;
	int ret;

	if (count < 2 || count > HCI_MAX_FRAME_SIZE)
		return -EINVAL;

	skb = bt_skb_alloc(count, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	if (copy_from_user(skb_put(skb, count), buf, count)) {
		kfree_skb(skb);
		return -EFAULT;
	}

	pkt_type = *((__u8 *) skb->data);
	skb_pull(skb, 1);

	switch (pkt_type) {
	case HCI_EVENT_PKT:
	case HCI_ACLDATA_PKT:
	case HCI_SCODATA_PKT:
		if (!data->hdev) {
			kfree_skb(skb);
			return -ENODEV;
		}

		bt_cb(skb)->pkt_type = pkt_type;

		ret = hci_recv_frame(data->hdev, skb);
		break;

	case HCI_VENDOR_PKT:
		if (data->hdev) {
			kfree_skb(skb);
			return -EBADFD;
		}

		cancel_delayed_work_sync(&data->open_timeout);

		dev_type = *((__u8 *) skb->data);
		skb_pull(skb, 1);

		if (skb->len > 0) {
			kfree_skb(skb);
			return -EINVAL;
		}

		kfree_skb(skb);

		if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
			return -EINVAL;

		ret = vhci_create_device(data, dev_type);
		break;

	default:
		kfree_skb(skb);
		return -EINVAL;
	}

	return (ret < 0) ? ret : count;
}
Пример #3
0
static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
{
	unsigned int iobase;
	unsigned char buf[31];
	int i, len;

	if (!info) {
		BT_ERR("Unknown device");
		return;
	}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
	iobase = info->p_dev->resource[0]->start;
#else
	iobase = info->p_dev->io.BasePort1;
#endif

	if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
		bluecard_enable_activity_led(info);

	len = bluecard_read(iobase, offset, buf, sizeof(buf));

	for (i = 0; i < len; i++) {

		/* Allocate packet */
		if (info->rx_skb == NULL) {
			info->rx_state = RECV_WAIT_PACKET_TYPE;
			info->rx_count = 0;
			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
				BT_ERR("Can't allocate mem for new packet");
				return;
			}
		}

		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {

			info->rx_skb->dev = (void *) info->hdev;
			bt_cb(info->rx_skb)->pkt_type = buf[i];

			switch (bt_cb(info->rx_skb)->pkt_type) {

			case 0x00:
				/* init packet */
				if (offset != 0x00) {
					set_bit(XMIT_BUF_ONE_READY, &(info->tx_state));
					set_bit(XMIT_BUF_TWO_READY, &(info->tx_state));
					set_bit(XMIT_SENDING_READY, &(info->tx_state));
					bluecard_write_wakeup(info);
				}

				kfree_skb(info->rx_skb);
				info->rx_skb = NULL;
				break;

			case HCI_EVENT_PKT:
				info->rx_state = RECV_WAIT_EVENT_HEADER;
				info->rx_count = HCI_EVENT_HDR_SIZE;
				break;

			case HCI_ACLDATA_PKT:
				info->rx_state = RECV_WAIT_ACL_HEADER;
				info->rx_count = HCI_ACL_HDR_SIZE;
				break;

			case HCI_SCODATA_PKT:
				info->rx_state = RECV_WAIT_SCO_HEADER;
				info->rx_count = HCI_SCO_HDR_SIZE;
				break;

			default:
				/* unknown packet */
				BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
				info->hdev->stat.err_rx++;

				kfree_skb(info->rx_skb);
				info->rx_skb = NULL;
				break;

			}

		} else {

			*skb_put(info->rx_skb, 1) = buf[i];
			info->rx_count--;

			if (info->rx_count == 0) {

				int dlen;
				struct hci_event_hdr *eh;
				struct hci_acl_hdr *ah;
				struct hci_sco_hdr *sh;

				switch (info->rx_state) {

				case RECV_WAIT_EVENT_HEADER:
					eh = hci_event_hdr(info->rx_skb);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = eh->plen;
					break;

				case RECV_WAIT_ACL_HEADER:
					ah = hci_acl_hdr(info->rx_skb);
					dlen = __le16_to_cpu(ah->dlen);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = dlen;
					break;

				case RECV_WAIT_SCO_HEADER:
					sh = hci_sco_hdr(info->rx_skb);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = sh->dlen;
					break;

				case RECV_WAIT_DATA:
					hci_recv_frame(info->rx_skb);
					info->rx_skb = NULL;
					break;

				}

			}

		}


	}

	info->hdev->stat.byte_rx += len;
}
Пример #4
0
/* Decodes received RAW data and forwards to corresponding
 * client drivers (Bluetooth,FM,GPS..etc).
 *
 */
void st_int_recv(void *disc_data,
	const unsigned char *data, long count)
{
	register char *ptr;
	struct hci_event_hdr *eh;
	struct hci_acl_hdr *ah;
	struct hci_sco_hdr *sh;
	struct fm_event_hdr *fm;
	struct gps_event_hdr *gps;
	register int len = 0, type = 0, dlen = 0;
	static enum proto_type protoid = ST_MAX;
	struct st_data_s *st_gdata = (struct st_data_s *)disc_data;

	ptr = (char *)data;
	/* tty_receive sent null ? */
	if (unlikely(ptr == NULL) || (st_gdata == NULL)) {
		pr_err(" received null from TTY ");
		return;
	}

	pr_info("count %ld rx_state %ld"
		   "rx_count %ld", count, st_gdata->rx_state,
		   st_gdata->rx_count);

	/* Decode received bytes here */
	while (count) {
		if (st_gdata->rx_count) {
			len = min_t(unsigned int, st_gdata->rx_count, count);
			memcpy(skb_put(st_gdata->rx_skb, len), ptr, len);
			st_gdata->rx_count -= len;
			count -= len;
			ptr += len;

			if (st_gdata->rx_count)
				continue;

			/* Check ST RX state machine , where are we? */
			switch (st_gdata->rx_state) {

				/* Waiting for complete packet ? */
			case ST_BT_W4_DATA:
				pr_info("Complete pkt received");

				/* Ask ST CORE to forward
				 * the packet to protocol driver */
				st_send_frame(protoid, st_gdata);

				st_gdata->rx_state = ST_W4_PACKET_TYPE;
				st_gdata->rx_skb = NULL;
				protoid = ST_MAX;	/* is this required ? */
				continue;

				/* Waiting for Bluetooth event header ? */
			case ST_BT_W4_EVENT_HDR:
				eh = (struct hci_event_hdr *)st_gdata->rx_skb->
				    data;

				pr_info("Event header: evt 0x%2.2x"
					   "plen %d", eh->evt, eh->plen);

				st_check_data_len(st_gdata, protoid, eh->plen);
				continue;

				/* Waiting for Bluetooth acl header ? */
			case ST_BT_W4_ACL_HDR:
				ah = (struct hci_acl_hdr *)st_gdata->rx_skb->
				    data;
				dlen = __le16_to_cpu(ah->dlen);

				pr_info("ACL header: dlen %d", dlen);

				st_check_data_len(st_gdata, protoid, dlen);
				continue;

				/* Waiting for Bluetooth sco header ? */
			case ST_BT_W4_SCO_HDR:
				sh = (struct hci_sco_hdr *)st_gdata->rx_skb->
				    data;

				pr_info("SCO header: dlen %d", sh->dlen);

				st_check_data_len(st_gdata, protoid, sh->dlen);
				continue;
			case ST_FM_W4_EVENT_HDR:
				fm = (struct fm_event_hdr *)st_gdata->rx_skb->
				    data;
				pr_info("FM Header: ");
				st_check_data_len(st_gdata, ST_FM, fm->plen);
				continue;
				/* TODO : Add GPS packet machine logic here */
			case ST_GPS_W4_EVENT_HDR:
				/* [0x09 pkt hdr][R/W byte][2 byte len] */
				gps = (struct gps_event_hdr *)st_gdata->rx_skb->
				     data;
				pr_info("GPS Header: ");
				st_check_data_len(st_gdata, ST_GPS, gps->plen);
				continue;
			}	/* end of switch rx_state */
		}

		/* end of if rx_count */
		/* Check first byte of packet and identify module
		 * owner (BT/FM/GPS) */
		switch (*ptr) {

			/* Bluetooth event packet? */
		case HCI_EVENT_PKT:
			pr_info("Event packet");
			st_gdata->rx_state = ST_BT_W4_EVENT_HDR;
			st_gdata->rx_count = HCI_EVENT_HDR_SIZE;
			type = HCI_EVENT_PKT;
			protoid = ST_BT;
			break;

			/* Bluetooth acl packet? */
		case HCI_ACLDATA_PKT:
			pr_info("ACL packet");
			st_gdata->rx_state = ST_BT_W4_ACL_HDR;
			st_gdata->rx_count = HCI_ACL_HDR_SIZE;
			type = HCI_ACLDATA_PKT;
			protoid = ST_BT;
			break;

			/* Bluetooth sco packet? */
		case HCI_SCODATA_PKT:
			pr_info("SCO packet");
			st_gdata->rx_state = ST_BT_W4_SCO_HDR;
			st_gdata->rx_count = HCI_SCO_HDR_SIZE;
			type = HCI_SCODATA_PKT;
			protoid = ST_BT;
			break;

			/* Channel 8(FM) packet? */
		case ST_FM_CH8_PKT:
			pr_info("FM CH8 packet");
			type = ST_FM_CH8_PKT;
			st_gdata->rx_state = ST_FM_W4_EVENT_HDR;
			st_gdata->rx_count = FM_EVENT_HDR_SIZE;
			protoid = ST_FM;
			break;

			/* Channel 9(GPS) packet? */
		case 0x9:	/*ST_LL_GPS_CH9_PKT */
			pr_info("GPS CH9 packet");
			type = 0x9;	/* ST_LL_GPS_CH9_PKT; */
			protoid = ST_GPS;
			st_gdata->rx_state = ST_GPS_W4_EVENT_HDR;
			st_gdata->rx_count = 3;	/* GPS_EVENT_HDR_SIZE -1*/
			break;
		case LL_SLEEP_IND:
		case LL_SLEEP_ACK:
		case LL_WAKE_UP_IND:
			pr_info("PM packet");
			/* this takes appropriate action based on
			 * sleep state received --
			 */
			st_ll_sleep_state(st_gdata, *ptr);
			ptr++;
			count--;
			continue;
		case LL_WAKE_UP_ACK:
			pr_info("PM packet");
			/* wake up ack received */
			st_wakeup_ack(st_gdata, *ptr);
			ptr++;
			count--;
			continue;
			/* Unknow packet? */
		default:
			pr_err("Unknown packet type %2.2x", (__u8) *ptr);
			ptr++;
			count--;
			continue;
		};
		ptr++;
		count--;

		switch (protoid) {
		case ST_BT:
			/* Allocate new packet to hold received data */
			st_gdata->rx_skb =
			    bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
			if (!st_gdata->rx_skb) {
				pr_err("Can't allocate mem for new packet");
				st_gdata->rx_state = ST_W4_PACKET_TYPE;
				st_gdata->rx_count = 0;
				return;
			}
			bt_cb(st_gdata->rx_skb)->pkt_type = type;
			break;
		case ST_FM:	/* for FM */
			st_gdata->rx_skb =
			    alloc_skb(FM_MAX_FRAME_SIZE, GFP_ATOMIC);
			if (!st_gdata->rx_skb) {
				pr_err("Can't allocate mem for new packet");
				st_gdata->rx_state = ST_W4_PACKET_TYPE;
				st_gdata->rx_count = 0;
				return;
			}
			/* place holder 0x08 */
			skb_reserve(st_gdata->rx_skb, 1);
			st_gdata->rx_skb->cb[0] = ST_FM_CH8_PKT;
			break;
		case ST_GPS:
			/* for GPS */
			st_gdata->rx_skb =
			    alloc_skb(100 /*GPS_MAX_FRAME_SIZE */ , GFP_ATOMIC);
			if (!st_gdata->rx_skb) {
				pr_err("Can't allocate mem for new packet");
				st_gdata->rx_state = ST_W4_PACKET_TYPE;
				st_gdata->rx_count = 0;
				return;
			}
			/* place holder 0x09 */
			skb_reserve(st_gdata->rx_skb, 1);
			st_gdata->rx_skb->cb[0] = 0x09;	/*ST_GPS_CH9_PKT; */
			break;
		case ST_MAX:
			break;
		}
	}
Пример #5
0
/* Recv data */
static int ibs_recv(struct hci_uart *hu, void *data, int count)
{
	struct ibs_struct *ibs = hu->priv;
	register char *ptr;
	struct hci_event_hdr *eh;
	struct hci_acl_hdr   *ah;
	struct hci_sco_hdr   *sh;
	register int len, type, dlen;

	BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
			hu, count, ibs->rx_state, ibs->rx_count);

	ptr = data;
	while (count) {
		if (ibs->rx_count) {
			len = min_t(unsigned int, ibs->rx_count, count);
			memcpy(skb_put(ibs->rx_skb, len), ptr, len);
			ibs->rx_count -= len; count -= len; ptr += len;

			if (ibs->rx_count)
				continue;

			switch (ibs->rx_state) {
			case HCI_IBS_W4_DATA:
				BT_DBG("Complete data");
				hci_recv_frame(ibs->rx_skb);

				ibs->rx_state = HCI_IBS_W4_PACKET_TYPE;
				ibs->rx_skb = NULL;
				continue;

			case HCI_IBS_W4_EVENT_HDR:
				eh = (struct hci_event_hdr *) ibs->rx_skb->data;

				BT_DBG("Event header: evt 0x%2.2x plen %d",
					eh->evt, eh->plen);

				ibs_check_data_len(ibs, eh->plen);
				continue;

			case HCI_IBS_W4_ACL_HDR:
				ah = (struct hci_acl_hdr *) ibs->rx_skb->data;
				dlen = __le16_to_cpu(ah->dlen);

				BT_DBG("ACL header: dlen %d", dlen);

				ibs_check_data_len(ibs, dlen);
				continue;

			case HCI_IBS_W4_SCO_HDR:
				sh = (struct hci_sco_hdr *) ibs->rx_skb->data;

				BT_DBG("SCO header: dlen %d", sh->dlen);

				ibs_check_data_len(ibs, sh->dlen);
				continue;
			}
		}

		/* HCI_IBS_W4_PACKET_TYPE */
		switch (*ptr) {
		case HCI_EVENT_PKT:
			BT_DBG("Event packet");
			ibs->rx_state = HCI_IBS_W4_EVENT_HDR;
			ibs->rx_count = HCI_EVENT_HDR_SIZE;
			type = HCI_EVENT_PKT;
			break;

		case HCI_ACLDATA_PKT:
			BT_DBG("ACL packet");
			ibs->rx_state = HCI_IBS_W4_ACL_HDR;
			ibs->rx_count = HCI_ACL_HDR_SIZE;
			type = HCI_ACLDATA_PKT;
			break;

		case HCI_SCODATA_PKT:
			BT_DBG("SCO packet");
			ibs->rx_state = HCI_IBS_W4_SCO_HDR;
			ibs->rx_count = HCI_SCO_HDR_SIZE;
			type = HCI_SCODATA_PKT;
			break;

		/* HCI_IBS signals */
		case HCI_IBS_SLEEP_IND:
			BT_DBG("HCI_IBS_SLEEP_IND packet");
			ibs_device_want_to_sleep(hu);
			ptr++; count--;
			continue;

		case HCI_IBS_WAKE_IND:
			BT_DBG("HCI_IBS_WAKE_IND packet");
			ibs_device_want_to_wakeup(hu);
			ptr++; count--;
			continue;

		case HCI_IBS_WAKE_ACK:
			BT_DBG("HCI_IBS_WAKE_ACK packet");
			ibs_device_woke_up(hu);
			ptr++; count--;
			continue;

		default:
			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
			hu->hdev->stat.err_rx++;
			ptr++; count--;
			continue;
		};

		ptr++; count--;

		/* Allocate packet */
		ibs->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
		if (!ibs->rx_skb) {
			BT_ERR("Can't allocate mem for new packet");
			ibs->rx_state = HCI_IBS_W4_PACKET_TYPE;
			ibs->rx_count = 0;
			return 0;
		}

		ibs->rx_skb->dev = (void *) hu->hdev;
		bt_cb(ibs->rx_skb)->pkt_type = type;
	}
Пример #6
0
static int vhci_create_device(struct vhci_data *data, __u8 opcode)
{
	struct hci_dev *hdev;
	struct sk_buff *skb;
	__u8 dev_type;

	/* bits 0-1 are dev_type (BR/EDR or AMP) */
	dev_type = opcode & 0x03;

	if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
		return -EINVAL;

	/* bits 2-5 are reserved (must be zero) */
	if (opcode & 0x3c)
		return -EINVAL;

	skb = bt_skb_alloc(4, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	hdev = hci_alloc_dev();
	if (!hdev) {
		kfree_skb(skb);
		return -ENOMEM;
	}

	data->hdev = hdev;

	hdev->bus = HCI_VIRTUAL;
	hdev->dev_type = dev_type;
	hci_set_drvdata(hdev, data);

	hdev->open  = vhci_open_dev;
	hdev->close = vhci_close_dev;
	hdev->flush = vhci_flush;
	hdev->send  = vhci_send_frame;

	/* bit 6 is for external configuration */
	if (opcode & 0x40)
		set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);

	/* bit 7 is for raw device */
	if (opcode & 0x80)
		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);

	if (hci_register_dev(hdev) < 0) {
		BT_ERR("Can't register HCI device");
		hci_free_dev(hdev);
		data->hdev = NULL;
		kfree_skb(skb);
		return -EBUSY;
	}

	bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;

	*skb_put(skb, 1) = 0xff;
	*skb_put(skb, 1) = opcode;
	put_unaligned_le16(hdev->id, skb_put(skb, 2));
	skb_queue_tail(&data->readq, skb);

	wake_up_interruptible(&data->read_wait);
	return 0;
}
Пример #7
0
static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len)
{
	BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len);

	if (hdr & 0x10) {
		BT_ERR("%s error in block", data->hdev->name);
		kfree_skb(data->reassembly);
		data->reassembly = NULL;
		return -EIO;
	}

	if (hdr & 0x04) {
		struct sk_buff *skb;
		unsigned char pkt_type;
		int pkt_len = 0;

		if (data->reassembly) {
			BT_ERR("%s unexpected start block", data->hdev->name);
			kfree_skb(data->reassembly);
			data->reassembly = NULL;
		}

		if (len < 1) {
			BT_ERR("%s no packet type found", data->hdev->name);
			return -EPROTO;
		}

		pkt_type = *buf++; len--;

		switch (pkt_type) {
		case HCI_EVENT_PKT:
			if (len >= HCI_EVENT_HDR_SIZE) {
				struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf;
				pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
			} else {
				BT_ERR("%s event block is too short", data->hdev->name);
				return -EILSEQ;
			}
			break;

		case HCI_ACLDATA_PKT:
			if (len >= HCI_ACL_HDR_SIZE) {
				struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf;
				pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen);
			} else {
				BT_ERR("%s data block is too short", data->hdev->name);
				return -EILSEQ;
			}
			break;

		case HCI_SCODATA_PKT:
			if (len >= HCI_SCO_HDR_SIZE) {
				struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf;
				pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
			} else {
				BT_ERR("%s audio block is too short", data->hdev->name);
				return -EILSEQ;
			}
			break;
		}

		skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
		if (!skb) {
			BT_ERR("%s no memory for the packet", data->hdev->name);
			return -ENOMEM;
		}

		skb->dev = (void *) data->hdev;
		bt_cb(skb)->pkt_type = pkt_type;

		data->reassembly = skb;
	} else {
		if (!data->reassembly) {
			BT_ERR("%s unexpected continuation block", data->hdev->name);
			return -EIO;
		}
	}

	if (len > 0)
		memcpy(skb_put(data->reassembly, len), buf, len);

	if (hdr & 0x08) {
		hci_recv_frame(data->reassembly);
		data->reassembly = NULL;
	}

	return 0;
}
Пример #8
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)
{
	while (count) {
		int i, len;

		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);

				bt_cb(skb)->pkt_type = (&pkts[i])->type;
				bt_cb(skb)->expect = (&pkts[i])->hlen;
				break;
			}

			/* Check for invalid packet type */
			if (!skb)
				return ERR_PTR(-EILSEQ);

			count -= 1;
			buffer += 1;
		}

		len = min_t(uint, bt_cb(skb)->expect - skb->len, count);
		memcpy(skb_put(skb, len), buffer, len);

		count -= len;
		buffer += len;

		/* Check for partial packet */
		if (skb->len < bt_cb(skb)->expect)
			continue;

		for (i = 0; i < pkts_count; i++) {
			if (bt_cb(skb)->pkt_type == (&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 */
				(&pkts[i])->recv(hdev, skb);
				skb = NULL;
				break;
			case 1:
				/* Single octet variable length */
				dlen = skb->data[(&pkts[i])->loff];
				bt_cb(skb)->expect += 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);
				bt_cb(skb)->expect += 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);
			}
		} else {
			/* Complete frame */
			(&pkts[i])->recv(hdev, skb);
			skb = NULL;
		}
	}

	return skb;
}
Пример #9
0
void* tdsp_bt_skb_alloc_atomic(unsigned long size)
{
	return (void*)(bt_skb_alloc(size, GFP_ATOMIC));
}
Пример #10
0
int rtbt_hci_dev_receive(void *bt_dev, int pkt_type, char *buf, int len)
{
	//struct hci_event_hdr hdr;
    //struct hci_dev *hdev = (struct hci_dev *)skb->dev;
    struct hci_dev *hdev = 0;
    struct sk_buff *skb;
	int status;
	//int pkt_len;

//printk("-->%s(): receive info: pkt_type=%d(%s), len=%d!\n", __FUNCTION__, pkt_type, pkt_type <= 5 ? pkt_type_str[pkt_type] : "ErrPktType", len);

	switch (pkt_type) {
		case HCI_EVENT_PKT:
			if (len < HCI_EVENT_HDR_SIZE) {
				BT_ERR("event block is too short");
				return -EILSEQ;
			}
			break;

		case HCI_ACLDATA_PKT:
			if (len < HCI_ACL_HDR_SIZE) {
				BT_ERR("data block is too short");
				return -EILSEQ;
			}
			break;

		case HCI_SCODATA_PKT:
			if (len < HCI_SCO_HDR_SIZE) {
				BT_ERR("audio block is too short");
				return -EILSEQ;
			}
			break;
	}

	skb = bt_skb_alloc(len, GFP_ATOMIC);
	if (!skb) {
		printk("%s no memory for the packet", ((struct hci_dev *)bt_dev)->name);
		return -ENOMEM;
	}

	skb->dev = g_hdev;
	rtbt_set_pkt_type(skb, pkt_type);
	memcpy(skb_put(skb, len), buf, len);

if (pkt_type == HCI_SCODATA_PKT)
	printk("-->%s(): send sco data to OS, time=0x%lx\n", __FUNCTION__, jiffies);

    hdev = (struct hci_dev *)skb->dev;
    if(hdev){
        hdev->stat.byte_rx += len;
    }

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,7)
	status = hci_recv_frame(skb);
#else
	status = hci_recv_frame(hdev, skb);
#endif

//printk("<--%s()\n", __FUNCTION__);

	return status;
}
Пример #11
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;
}
Пример #12
0
static inline void brf6150_rx(struct brf6150_info *info)
{
	u8 byte;

	NBT_DBG_TRANSFER("rx_tasklet woke up\ndata ");

	while (brf6150_inb(info, UART_LSR) & UART_LSR_DR) {
		if (info->rx_skb == NULL) {
			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
			if (!info->rx_skb) {
				printk(KERN_WARNING "brf6150: Can't allocate memory for new packet\n");
				return;
			}
			info->rx_state = WAIT_FOR_PKT_TYPE;
			info->rx_skb->dev = (void *)info->hdev;
			brf6150_disable_pm_rx(info);
			clk_enable(info->uart_ck);
		}

		byte = brf6150_inb(info, UART_RX);
		if (info->garbage_bytes) {
			info->garbage_bytes--;
			info->hdev->stat.err_rx++;
			continue;
		}
		info->hdev->stat.byte_rx++;
		NBT_DBG_TRANSFER_NF("0x%.2x  ", byte);
		switch (info->rx_state) {
		case WAIT_FOR_PKT_TYPE:
			bt_cb(info->rx_skb)->pkt_type = byte;
			info->rx_count = brf6150_get_hdr_len(byte);
			if (info->rx_count >= 0) {
				info->rx_state = WAIT_FOR_HEADER;
			} else {
				info->hdev->stat.err_rx++;
				kfree_skb(info->rx_skb);
				info->rx_skb = NULL;
				clk_disable(info->uart_ck);
			}
			break;
		case WAIT_FOR_HEADER:
			info->rx_count--;
			*skb_put(info->rx_skb, 1) = byte;
			if (info->rx_count == 0) {
				info->rx_count = brf6150_get_data_len(info, info->rx_skb);
				if (info->rx_count > skb_tailroom(info->rx_skb)) {
					printk(KERN_WARNING "brf6150: Frame is %ld bytes too long.\n",
					       info->rx_count - skb_tailroom(info->rx_skb));
					info->rx_skb = NULL;
					info->garbage_bytes = info->rx_count - skb_tailroom(info->rx_skb);
					clk_disable(info->uart_ck);
					break;
				}
				info->rx_state = WAIT_FOR_DATA;
				if (bt_cb(info->rx_skb)->pkt_type == H4_NEG_PKT) {
					brf6150_negotiation_packet(info, info->rx_skb);
					info->rx_skb = NULL;
					clk_disable(info->uart_ck);
					return;
				}
				if (bt_cb(info->rx_skb)->pkt_type == H4_ALIVE_PKT) {
					brf6150_alive_packet(info, info->rx_skb);
					info->rx_skb = NULL;
					clk_disable(info->uart_ck);
					return;
				}
			}
			break;
		case WAIT_FOR_DATA:
			info->rx_count--;
			*skb_put(info->rx_skb, 1) = byte;
			if (info->rx_count == 0) {
				brf6150_recv_frame(info, info->rx_skb);
				info->rx_skb = NULL;
				clk_disable(info->uart_ck);
			}
			break;
		default:
			WARN_ON(1);
			break;
		}
	}

	NBT_DBG_TRANSFER_NF("\n");
}
Пример #13
0
/* receive function called during firmware download
 * - firmware download responses on different UART drivers
 *   have been observed to come in bursts of different
 *   tty_receive and hence the logic
 */
void kim_int_recv(const unsigned char *data, long count)
{
	register char *ptr;
	struct hci_event_hdr *eh;
	register int len = 0, type = 0;

	ST_KIM_DBG("%s", __func__);
	/* Decode received bytes here */
	ptr = (char *)data;
	if (unlikely(ptr == NULL)) {
		ST_KIM_ERR(" received null from TTY ");
		return;
	}
	while (count) {
		if (kim_gdata->rx_count) {
			len = min_t(unsigned int, kim_gdata->rx_count, count);
			memcpy(skb_put(kim_gdata->rx_skb, len), ptr, len);
			kim_gdata->rx_count -= len;
			count -= len;
			ptr += len;

			if (kim_gdata->rx_count)
				continue;

			/* Check ST RX state machine , where are we? */
			switch (kim_gdata->rx_state) {
				/* Waiting for complete packet ? */
			case ST_BT_W4_DATA:
				ST_KIM_DBG("Complete pkt received");
				validate_firmware_response(kim_gdata->rx_skb);
				kim_gdata->rx_state = ST_W4_PACKET_TYPE;
				kim_gdata->rx_skb = NULL;
				continue;
				/* Waiting for Bluetooth event header ? */
			case ST_BT_W4_EVENT_HDR:
				eh = (struct hci_event_hdr *)kim_gdata->
				    rx_skb->data;
				ST_KIM_DBG("Event header: evt 0x%2.2x "
					   "plen %d", eh->evt, eh->plen);
				kim_check_data_len(eh->plen);
				continue;
			}	/* end of switch */
		}		/* end of if rx_state */
		switch (*ptr) {
			/* Bluetooth event packet? */
		case HCI_EVENT_PKT:
			ST_KIM_DBG("Event packet");
			kim_gdata->rx_state = ST_BT_W4_EVENT_HDR;
			kim_gdata->rx_count = HCI_EVENT_HDR_SIZE;
			type = HCI_EVENT_PKT;
			break;
		default:
			ST_KIM_DBG("unknown packet");
			ptr++;
			count--;
			continue;
		}		/* end of switch *ptr */
		ptr++;
		count--;
		kim_gdata->rx_skb =
		    bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
		if (!kim_gdata->rx_skb) {
			ST_KIM_ERR("can't allocate mem for new packet");
			kim_gdata->rx_state = ST_W4_PACKET_TYPE;
			kim_gdata->rx_count = 0;
			return;
		} /* not necessary in this case */
		bt_cb(kim_gdata->rx_skb)->pkt_type = type;
	}			/* end of while count */
Пример #14
0
static int nokia_send_negotiation(struct hci_uart *hu)
{
	struct nokia_bt_dev *btdev = hu->priv;
	struct device *dev = &btdev->serdev->dev;
	struct hci_nokia_neg_cmd *neg_cmd;
	struct hci_nokia_neg_hdr *neg_hdr;
	struct sk_buff *skb;
	int len, err;
	u16 baud = DIV_ROUND_CLOSEST(btdev->sysclk_speed * 10, SETUP_BAUD_RATE);
	int sysclk = btdev->sysclk_speed / 1000;

	len = H4_TYPE_SIZE + sizeof(*neg_hdr) + sizeof(*neg_cmd);
	skb = bt_skb_alloc(len, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	hci_skb_pkt_type(skb) = HCI_NOKIA_NEG_PKT;

	neg_hdr = skb_put(skb, sizeof(*neg_hdr));
	neg_hdr->dlen = sizeof(*neg_cmd);

	neg_cmd = skb_put(skb, sizeof(*neg_cmd));
	neg_cmd->ack = NOKIA_NEG_REQ;
	neg_cmd->baud = cpu_to_le16(baud);
	neg_cmd->unused1 = 0x0000;
	neg_cmd->proto = NOKIA_PROTO_BYTE;
	neg_cmd->sys_clk = cpu_to_le16(sysclk);
	neg_cmd->unused2 = 0x0000;

	btdev->init_error = 0;
	init_completion(&btdev->init_completion);

	nokia_enqueue(hu, skb);
	hci_uart_tx_wakeup(hu);

	dev_dbg(dev, "Negotiation sent");

	if (!wait_for_completion_interruptible_timeout(&btdev->init_completion,
		msecs_to_jiffies(10000))) {
		return -ETIMEDOUT;
	}

	if (btdev->init_error < 0)
		return btdev->init_error;

	/* Change to previously negotiated speed. Flow Control
	 * is disabled until bluetooth adapter is ready to avoid
	 * broken bytes being received.
	 */
	nokia_flow_control(btdev->serdev, false);
	serdev_device_set_baudrate(btdev->serdev, SETUP_BAUD_RATE);
	err = serdev_device_wait_for_cts(btdev->serdev, true, 200);
	if (err < 0) {
		dev_err(dev, "CTS not received: %d", err);
		return err;
	}
	nokia_flow_control(btdev->serdev, true);

	dev_dbg(dev, "Negotiation successful");

	return 0;
}
Пример #15
0
/**
 *  @brief This function reads data from the card.
 *
 *  @param priv     A pointer to bt_private structure
 *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
static int
sd_card_to_host(bt_private *priv)
{
	int ret = BT_STATUS_SUCCESS;
	u16 buf_len = 0;
	int buf_block_len;
	int blksz;
	struct sk_buff *skb = NULL;
	u32 type;
	u8 *payload = NULL;
	struct mbt_dev *mbt_dev = NULL;
	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
	struct m_dev *mdev_fm = &(priv->bt_dev.m_dev[FM_SEQ]);
	struct m_dev *mdev_nfc = &(priv->bt_dev.m_dev[NFC_SEQ]);
	struct nfc_dev *nfc_dev =
		(struct nfc_dev *)priv->bt_dev.m_dev[NFC_SEQ].dev_pointer;
	struct fm_dev *fm_dev =
		(struct fm_dev *)priv->bt_dev.m_dev[FM_SEQ].dev_pointer;
	struct m_dev *mdev_debug = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
	struct debug_dev *debug_dev =
		(struct debug_dev *)priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer;
	struct sdio_mmc_card *card = priv->bt_dev.card;

	ENTER();
	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
		mbt_dev = (struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer;
	if (!card || !card->func) {
		PRINTM(ERROR, "BT: card or function is NULL!\n");
		ret = BT_STATUS_FAILURE;
		goto exit;
	}

	/* Read the length of data to be transferred */
	ret = sd_read_rx_len(priv, &buf_len);
	if (ret < 0) {
		PRINTM(ERROR, "BT: card_to_host, read scratch reg failed\n");
		ret = BT_STATUS_FAILURE;
		goto exit;
	}

	/* Allocate buffer */
	blksz = SD_BLOCK_SIZE;
	buf_block_len = (buf_len + blksz - 1) / blksz;
	if (buf_len <= BT_HEADER_LEN ||
	    (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
		PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n",
		       buf_len);
		ret = BT_STATUS_FAILURE;
		goto exit;
	}
	skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
	if (skb == NULL) {
		PRINTM(WARN, "BT: No free skb\n");
		goto exit;
	}
	if ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)) {
		skb_put(skb,
			DMA_ALIGNMENT -
			((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
		skb_pull(skb,
			 DMA_ALIGNMENT -
			 ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
	}

	payload = skb->data;
	ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
			  buf_block_len * blksz);
	if (ret < 0) {
		PRINTM(ERROR, "BT: card_to_host, read iomem failed: %d\n", ret);
		kfree_skb(skb);
		skb = NULL;
		ret = BT_STATUS_FAILURE;
		goto exit;
	}
	/* This is SDIO specific header length: byte[2][1][0], * type: byte[3]
	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
	buf_len = payload[0];
	buf_len |= (u16) payload[1] << 8;
	type = payload[3];
	PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", mbt_dev->name,
	       buf_len, type);
	if (buf_len > buf_block_len * blksz) {
		PRINTM(ERROR,
		       "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
		       buf_len, buf_block_len * blksz);
		ret = BT_STATUS_FAILURE;
		kfree_skb(skb);
		skb = NULL;
		goto exit;
	}
	DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
	switch (type) {
	case HCI_ACLDATA_PKT:
		bt_cb(skb)->pkt_type = type;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (mbt_dev) {
			skb->dev = (void *)mdev_bt;
			mdev_recv_frame(skb);
			mdev_bt->stat.byte_rx += buf_len;
		}
		break;
	case HCI_SCODATA_PKT:
		bt_cb(skb)->pkt_type = type;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (mbt_dev) {
			skb->dev = (void *)mdev_bt;
			mdev_recv_frame(skb);
			mdev_bt->stat.byte_rx += buf_len;
		}
		break;
	case HCI_EVENT_PKT:
		/** add EVT Demux */
		bt_cb(skb)->pkt_type = type;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
			break;
		switch (skb->data[0]) {
		case 0x0E:
			/** cmd complete */
			if (priv->debug_device_pending) {
				if (priv->debug_ocf_ogf[0] == skb->data[3] &&
				    priv->debug_ocf_ogf[1] == skb->data[4]) {
					priv->debug_device_pending = 0;
					priv->debug_ocf_ogf[0] = 0;
					priv->debug_ocf_ogf[1] = 0;
					/** debug cmd complete */
					if (debug_dev) {
						skb->dev = (void *)mdev_debug;
						mdev_recv_frame(skb);
						mdev_debug->stat.byte_rx +=
							buf_len;
					}
					break;
				}
			}
			if (skb->data[3] == 0x80 && skb->data[4] == 0xFE) {
				/** FM cmd complete */
				if (fm_dev) {
					skb->dev = (void *)mdev_fm;
					mdev_recv_frame(skb);
					mdev_fm->stat.byte_rx += buf_len;
				}
			} else if (skb->data[3] == 0x81 && skb->data[4] == 0xFE) {
				/** NFC cmd complete */
				if (nfc_dev) {
					skb->dev = (void *)mdev_nfc;
					mdev_recv_frame(skb);
					mdev_nfc->stat.byte_rx += buf_len;
				}
			} else {
				if (mbt_dev) {
					skb->dev = (void *)mdev_bt;
					mdev_recv_frame(skb);
					mdev_bt->stat.byte_rx += buf_len;
				}
			}
			break;
		case 0x0F:
			/** cmd status */
			if (skb->data[4] == 0x80 && skb->data[5] == 0xFE) {
				/** FM cmd ststus */
				if (fm_dev) {
					skb->dev = (void *)mdev_fm;
					mdev_recv_frame(skb);
					mdev_fm->stat.byte_rx += buf_len;
				}
			} else if (skb->data[4] == 0x81 && skb->data[5] == 0xFE) {
				/** NFC cmd ststus */
				if (nfc_dev) {
					skb->dev = (void *)mdev_nfc;
					mdev_recv_frame(skb);
					mdev_nfc->stat.byte_rx += buf_len;
				}
			} else {
				/** BT cmd status */
				if (mbt_dev) {
					skb->dev = (void *)mdev_bt;
					mdev_recv_frame(skb);
					mdev_bt->stat.byte_rx += buf_len;
				}
			}
			break;
		case 0xFF:
			/** Vendor specific pkt */
			if (skb->data[2] == 0xC0) {
				/** NFC EVT */
				if (nfc_dev) {
					skb->dev = (void *)mdev_nfc;
					mdev_recv_frame(skb);
					mdev_nfc->stat.byte_rx += buf_len;
				}
			} else if (skb->data[2] >= 0x80 && skb->data[2] <= 0xAF) {
				/** FM EVT */
				if (fm_dev) {
					skb->dev = (void *)mdev_fm;
					mdev_recv_frame(skb);
					mdev_fm->stat.byte_rx += buf_len;
				}
			} else {
				/** BT EVT */
				if (mbt_dev) {
					skb->dev = (void *)mdev_bt;
					mdev_recv_frame(skb);
					mdev_bt->stat.byte_rx += buf_len;
				}
			}
			break;
		default:
			/** BT EVT */
			if (mbt_dev) {
				skb->dev = (void *)mdev_bt;
				mdev_recv_frame(skb);
				mdev_bt->stat.byte_rx += buf_len;
			}
			break;
		}
		break;
	case MRVL_VENDOR_PKT:
		/* Just think here need to back compatible FM */
		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (mbt_dev) {
			if (BT_STATUS_SUCCESS != bt_process_event(priv, skb)) {
				skb->dev = (void *)mdev_bt;
				mdev_recv_frame(skb);
				mdev_bt->stat.byte_rx += buf_len;
			}
		}

		break;
	default:
		/* Driver specified event and command resp should be handle
		   here */
		PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
		kfree_skb(skb);
		skb = NULL;
		break;
	}
exit:
	if (ret) {
		if (mbt_dev)
			mdev_bt->stat.err_rx++;
		PRINTM(ERROR, "error when recv pkt!\n");
	}

	LEAVE();
	return ret;
}
Пример #16
0
/* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count)
{
#ifdef CONFIG_RADIO_BCM4343S
    struct h4_struct *h4 = hu->priv;
    register char *ptr;
    struct hci_event_hdr *eh;
    struct hci_acl_hdr   *ah;
    struct hci_sco_hdr   *sh;
    struct fm_event_hdr *fm;
    register int len, type, dlen;
    static enum proto_type protoid = PROTO_SH_MAX;

    BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, h4->rx_state, h4->rx_count);

    ptr = (char *)data;
    while (count) {
        if (h4->rx_count) {
            len = min_t(unsigned int, h4->rx_count, count);
              memcpy(skb_put(h4->rx_skb, len), ptr, len);
            h4->rx_count -= len; count -= len; ptr += len;

            if (h4->rx_count)
                continue;

            switch (h4->rx_state) {
            case H4_W4_DATA:

                BT_DBG("%2x %2x %2x %2x",h4->rx_skb->data[0], h4->rx_skb->data[1], h4->rx_skb->data[2], h4->rx_skb->data[3]);
                BT_DBG("%2x %2x %2x %2x",h4->rx_skb->data[4], h4->rx_skb->data[5], h4->rx_skb->data[6], h4->rx_skb->data[7]);

                BT_DBG("Complete data");

                if ( ( h4->rx_skb->data[3] == 0x15 && h4->rx_skb->data[4] == 0xfc )
                  || ( h4->rx_skb->data[0] == 0xff && h4->rx_skb->data[1] == 0x01 && h4->rx_skb->data[2] == 0x08 )
               )
                {
                   BT_DBG("FM Event change to FM CH8 packet");
                   type = FM_CH8_PKT;
                   h4->rx_skb->cb[0] = FM_CH8_PKT;
                   h4->rx_state = FM_W4_EVENT_HDR;
                   protoid = PROTO_SH_FM;
                }

                hci_uart_route_frame(protoid, hu, h4->rx_skb);

                h4->rx_state = H4_W4_PACKET_TYPE;
                h4->rx_skb = NULL;
                protoid = PROTO_SH_MAX;
                continue;

            case H4_W4_EVENT_HDR:
                eh = hci_event_hdr(h4->rx_skb);

                BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);

                h4_check_data_len(h4, hu, protoid, eh->plen);
                continue;

            case H4_W4_ACL_HDR:
                ah = hci_acl_hdr(h4->rx_skb);

                dlen = __le16_to_cpu(ah->dlen);

                BT_DBG("ACL header: dlen %d", dlen);

                h4_check_data_len(h4, hu, protoid, dlen);
                continue;

            case H4_W4_SCO_HDR:
                sh = hci_sco_hdr(h4->rx_skb);

                BT_DBG("SCO header: dlen %d", sh->dlen);

                h4_check_data_len(h4, hu, protoid, sh->dlen);
                continue;

            case FM_W4_EVENT_HDR:
                fm = (struct fm_event_hdr *)h4->rx_skb->data;
                BT_DBG("FM Header: evt 0x%2.2x plen %d",
                    fm->event, fm->plen);
                h4_check_data_len(h4, hu, PROTO_SH_FM, fm->plen);
                continue;

            }
        }

        /* H4_W4_PACKET_TYPE */
        switch (*ptr) {
        case HCI_EVENT_PKT:
            BT_DBG("Event packet");

            BT_DBG("%2x %2x %2x %2x",ptr[0], ptr[1], ptr[2], ptr[3]);
            BT_DBG("%2x %2x %2x %2x",ptr[4], ptr[5], ptr[6], ptr[7]);
            if ( ptr[4] == 0x15 && ptr[5] == 0xfc )
            {
               BT_DBG("FM Event change to FM CH8 packet");
               type = FM_CH8_PKT;
               h4->rx_state = FM_W4_EVENT_HDR;
               h4->rx_count = FM_EVENT_HDR_SIZE;
               protoid = PROTO_SH_FM;
            }
            else
            {
               BT_DBG("FM Event is not detected");
               h4->rx_state = H4_W4_EVENT_HDR;
               h4->rx_count = HCI_EVENT_HDR_SIZE;
               type = HCI_EVENT_PKT;
               protoid = PROTO_SH_BT;
            }
            break;

        case HCI_ACLDATA_PKT:
            BT_DBG("ACL packet");
            h4->rx_state = H4_W4_ACL_HDR;
            h4->rx_count = HCI_ACL_HDR_SIZE;
            type = HCI_ACLDATA_PKT;
            protoid = PROTO_SH_BT;
            break;

        case HCI_SCODATA_PKT:
            BT_DBG("SCO packet");
            h4->rx_state = H4_W4_SCO_HDR;
            h4->rx_count = HCI_SCO_HDR_SIZE;
            type = HCI_SCODATA_PKT;
            protoid = PROTO_SH_BT;
            break;

        /* Channel 8(FM) packet */
        case FM_CH8_PKT:
            BT_DBG("FM CH8 packet");
            type = FM_CH8_PKT;
            h4->rx_state = FM_W4_EVENT_HDR;
            h4->rx_count = FM_EVENT_HDR_SIZE;
            protoid = PROTO_SH_FM;
            break;

        default:
            BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
            hu->hdev->stat.err_rx++;
            ptr++; count--;
            continue;
        };

        ptr++; count--;

        switch (protoid)
        {
            case PROTO_SH_BT:
            case PROTO_SH_FM:
                /* Allocate new packet to hold received data */
                h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
                if (!h4->rx_skb)
                {
                    BT_ERR("Can't allocate mem for new packet");
                    h4->rx_state = H4_W4_PACKET_TYPE;
                    h4->rx_count = 0;
                    return -ENOMEM;
                }
                h4->rx_skb->dev = (void *) hu->hdev;
                sh_ldisc_cb(h4->rx_skb)->pkt_type = type;
                break;
#if 0
            case PROTO_SH_FM:    /* for FM */
                h4->rx_skb = bt_skb_alloc(FM_MAX_FRAME_SIZE, GFP_ATOMIC);
                if (!h4->rx_skb)
                {
                    BT_ERR("Can't allocate mem for new packet");
                    h4->rx_state = H4_W4_PACKET_TYPE;
                    h4->rx_count = 0;
                    return -ENOMEM;
                }
                /* place holder 0x08 */
                /* skb_reserve(h4->rx_skb, 1); */
                sh_ldisc_cb(h4->rx_skb)->pkt_type = FM_CH8_PKT;
                break;
#endif
            case PROTO_SH_MAX:
            case PROTO_SH_GPS:
                break;
        }

    }
Пример #17
0
static inline ssize_t vhci_get_user(struct vhci_data *data,
				    struct iov_iter *from)
{
	size_t len = iov_iter_count(from);
	struct sk_buff *skb;
	__u8 pkt_type, opcode;
	int ret;
#else
static inline ssize_t vhci_get_user(struct vhci_data *data,
				    const struct iovec *iov,
				    unsigned long count)
{
	size_t len = iov_length(iov, count);
	struct sk_buff *skb;
	__u8 pkt_type, opcode;
	unsigned long i;
	int ret;
#endif

	if (len < 2 || len > HCI_MAX_FRAME_SIZE)
		return -EINVAL;

	skb = bt_skb_alloc(len, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)
	if (copy_from_iter(skb_put(skb, len), len, from) != len) {
		kfree_skb(skb);
		return -EFAULT;
	}
#else
	for (i = 0; i < count; i++) {
		if (copy_from_user(skb_put(skb, iov[i].iov_len),
				   iov[i].iov_base, iov[i].iov_len)) {
			kfree_skb(skb);
			return -EFAULT;
		}
	}
#endif

	pkt_type = *((__u8 *) skb->data);
	skb_pull(skb, 1);

	switch (pkt_type) {
	case HCI_EVENT_PKT:
	case HCI_ACLDATA_PKT:
	case HCI_SCODATA_PKT:
		if (!data->hdev) {
			kfree_skb(skb);
			return -ENODEV;
		}

		bt_cb(skb)->pkt_type = pkt_type;

		ret = hci_recv_frame(data->hdev, skb);
		break;

	case HCI_VENDOR_PKT:
		if (data->hdev) {
			kfree_skb(skb);
			return -EBADFD;
		}

		cancel_delayed_work_sync(&data->open_timeout);

		opcode = *((__u8 *) skb->data);
		skb_pull(skb, 1);

		if (skb->len > 0) {
			kfree_skb(skb);
			return -EINVAL;
		}

		kfree_skb(skb);

		ret = vhci_create_device(data, opcode);
		break;

	default:
		kfree_skb(skb);
		return -EINVAL;
	}

	return (ret < 0) ? ret : len;
}
Пример #18
0
/** 
 *  @brief This function reads data from the card.
 *  
 *  @param priv    	A pointer to bt_private structure
 *  @return 	   	BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
static int
sd_card_to_host(bt_private * priv)
{
    int ret = BT_STATUS_SUCCESS;
    u16 buf_len = 0;
    int buf_block_len;
    int blksz;
    struct sk_buff *skb = NULL;
    u32 type;
    u8 *payload = NULL;
    struct hci_dev *hdev = priv->bt_dev.hcidev;
    struct sdio_mmc_card *card = priv->bt_dev.card;

    ENTER();

    if (!card || !card->func) {
        PRINTM(ERROR, "BT: card or function is NULL!\n");
        ret = BT_STATUS_FAILURE;
        goto exit;
    }

    /* Read the length of data to be transferred */
    ret = sd_read_rx_len(priv, &buf_len);
    if (ret < 0) {
        PRINTM(ERROR, "BT: card_to_host, read scratch reg failed\n");
        ret = BT_STATUS_FAILURE;
        goto exit;
    }

    /* Allocate buffer */
    blksz = SD_BLOCK_SIZE;
    buf_block_len = (buf_len + blksz - 1) / blksz;
    if (buf_len <= BT_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
        PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n", buf_len);
        ret = BT_STATUS_FAILURE;
        goto exit;
    }
    skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
    if (skb == NULL) {
        PRINTM(WARN, "BT: No free skb\n");
        goto exit;
    }
    if ((u32) skb->data & (DMA_ALIGNMENT - 1)) {
        skb_put(skb, DMA_ALIGNMENT - ((u32) skb->data & (DMA_ALIGNMENT - 1)));
        skb_pull(skb, DMA_ALIGNMENT - ((u32) skb->data & (DMA_ALIGNMENT - 1)));
    }

    payload = skb->tail;
    ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
                      buf_block_len * blksz);
    if (ret < 0) {
        PRINTM(ERROR, "BT: card_to_host, read iomem failed: %d\n", ret);
        kfree_skb(skb);
        skb = NULL;
        ret = BT_STATUS_FAILURE;
        goto exit;
    }
    /* This is SDIO specific header length: byte[2][1][0], type: byte[3]
       (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
    buf_len = payload[0];
    buf_len |= (u16) payload[1] << 8;
    type = payload[3];
    PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", hdev->name, buf_len,
           type);
    if (buf_len > buf_block_len * blksz) {
        PRINTM(ERROR,
               "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
               buf_len, buf_block_len * blksz);
        ret = BT_STATUS_FAILURE;
        kfree_skb(skb);
        skb = NULL;
        goto exit;
    }
    DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
    switch (type) {
    case HCI_ACLDATA_PKT:
    case HCI_SCODATA_PKT:
    case HCI_EVENT_PKT:
        bt_cb(skb)->pkt_type = type;
        skb->dev = (void *) hdev;
        skb_put(skb, buf_len);
        skb_pull(skb, BT_HEADER_LEN);
        if (type == HCI_EVENT_PKT) {
            if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
                break;
        }
        hci_recv_frame(skb);
        hdev->stat.byte_rx += buf_len;
        break;
    case MRVL_VENDOR_PKT:
        bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
        skb->dev = (void *) hdev;
        skb_put(skb, buf_len);
        skb_pull(skb, BT_HEADER_LEN);
        if (BT_STATUS_SUCCESS != bt_process_event(priv, skb))
            hci_recv_frame(skb);
        hdev->stat.byte_rx += buf_len;
        break;
    default:
        /* Driver specified event and command resp should be handle here */
        PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
        kfree_skb(skb);
        skb = NULL;
        break;
    }
  exit:
    if (ret) {
        hdev->stat.err_rx++;
    }

    LEAVE();
    return ret;
}
Пример #19
0
static void bt3c_receive(bt3c_info_t *info)
{
	unsigned int iobase;
	int size = 0, avail;

	if (!info) {
		printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n");
		return;
	}

	iobase = info->link.io.BasePort1;

	avail = bt3c_read(iobase, 0x7006);
	//printk("bt3c_cs: receiving %d bytes\n", avail);

	bt3c_address(iobase, 0x7480);
	while (size < avail) {
		size++;
		info->hdev.stat.byte_rx++;

		/* Allocate packet */
		if (info->rx_skb == NULL) {
			info->rx_state = RECV_WAIT_PACKET_TYPE;
			info->rx_count = 0;
			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
				printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n");
				return;
			}
		}


		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {

			info->rx_skb->dev = (void *)&(info->hdev);
			info->rx_skb->pkt_type = inb(iobase + DATA_L);
			inb(iobase + DATA_H);
			//printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type);

			switch (info->rx_skb->pkt_type) {

			case HCI_EVENT_PKT:
				info->rx_state = RECV_WAIT_EVENT_HEADER;
				info->rx_count = HCI_EVENT_HDR_SIZE;
				break;

			case HCI_ACLDATA_PKT:
				info->rx_state = RECV_WAIT_ACL_HEADER;
				info->rx_count = HCI_ACL_HDR_SIZE;
				break;

			case HCI_SCODATA_PKT:
				info->rx_state = RECV_WAIT_SCO_HEADER;
				info->rx_count = HCI_SCO_HDR_SIZE;
				break;

			default:
				/* Unknown packet */
				printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
				info->hdev.stat.err_rx++;
				clear_bit(HCI_RUNNING, &(info->hdev.flags));

				dev_kfree_skb_any(info->rx_skb);
				info->rx_skb = NULL;
				break;

			}

		} else {

			__u8 x = inb(iobase + DATA_L);

			*skb_put(info->rx_skb, 1) = x;
			inb(iobase + DATA_H);
			info->rx_count--;

			if (info->rx_count == 0) {

				int dlen;
				struct hci_event_hdr *eh;
				struct hci_acl_hdr *ah;
				struct hci_sco_hdr *sh;

				switch (info->rx_state) {

				case RECV_WAIT_EVENT_HEADER:
					eh = (struct hci_event_hdr *)(info->rx_skb->data);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = eh->plen;
					break;

				case RECV_WAIT_ACL_HEADER:
					ah = (struct hci_acl_hdr *)(info->rx_skb->data);
					dlen = __le16_to_cpu(ah->dlen);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = dlen;
					break;

				case RECV_WAIT_SCO_HEADER:
					sh = (struct hci_sco_hdr *)(info->rx_skb->data);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = sh->dlen;
					break;

				case RECV_WAIT_DATA:
					hci_recv_frame(info->rx_skb);
					info->rx_skb = NULL;
					break;

				}

			}

		}

	}

	bt3c_io_write(iobase, 0x7006, 0x0000);
}
Пример #20
0
/* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count)
{
	struct h4_struct *h4 = hu->priv;
	register char *ptr;
	struct hci_event_hdr *eh;
	struct hci_acl_hdr   *ah;
	struct hci_sco_hdr   *sh;
	register int len, type, dlen;

	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", 
			hu, count, h4->rx_state, h4->rx_count);

	ptr = data;
	while (count) {
		if (h4->rx_count) {
			len = min_t(unsigned int, h4->rx_count, count);
			memcpy(skb_put(h4->rx_skb, len), ptr, len);
			h4->rx_count -= len; count -= len; ptr += len;

			if (h4->rx_count)
				continue;

			switch (h4->rx_state) {
			case H4_W4_DATA:
				BT_DBG("Complete data");

				BT_DMP(h4->rx_skb->data, h4->rx_skb->len);

				hci_recv_frame(h4->rx_skb);

				h4->rx_state = H4_W4_PACKET_TYPE;
				h4->rx_skb = NULL;
				continue;

			case H4_W4_EVENT_HDR:
				eh = (struct hci_event_hdr *) h4->rx_skb->data;

				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);

				h4_check_data_len(h4, eh->plen);
				continue;

			case H4_W4_ACL_HDR:
				ah = (struct hci_acl_hdr *) h4->rx_skb->data;
				dlen = __le16_to_cpu(ah->dlen);

				BT_DBG("ACL header: dlen %d", dlen);

				h4_check_data_len(h4, dlen);
				continue;

			case H4_W4_SCO_HDR:
				sh = (struct hci_sco_hdr *) h4->rx_skb->data;

				BT_DBG("SCO header: dlen %d", sh->dlen);

				h4_check_data_len(h4, sh->dlen);
				continue;
			}
		}

		/* H4_W4_PACKET_TYPE */
		switch (*ptr) {
		case HCI_EVENT_PKT:
			BT_DBG("Event packet");
			h4->rx_state = H4_W4_EVENT_HDR;
			h4->rx_count = HCI_EVENT_HDR_SIZE;
			type = HCI_EVENT_PKT;
			break;

		case HCI_ACLDATA_PKT:
			BT_DBG("ACL packet");
			h4->rx_state = H4_W4_ACL_HDR;
			h4->rx_count = HCI_ACL_HDR_SIZE;
			type = HCI_ACLDATA_PKT;
			break;

		case HCI_SCODATA_PKT:
			BT_DBG("SCO packet");
			h4->rx_state = H4_W4_SCO_HDR;
			h4->rx_count = HCI_SCO_HDR_SIZE;
			type = HCI_SCODATA_PKT;
			break;

		default:
			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
			hu->hdev->stat.err_rx++;
			ptr++; count--;
			continue;
		};
		ptr++; count--;

		/* Allocate packet */
		h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
		if (!h4->rx_skb) {
			BT_ERR("Can't allocate mem for new packet");
			h4->rx_state = H4_W4_PACKET_TYPE;
			h4->rx_count = 0;
			return 0;
		}
		h4->rx_skb->dev = (void *) hu->hdev;
		h4->rx_skb->pkt_type = type;
	}
Пример #21
0
static int bfusb_send_frame(struct sk_buff *skb)
{
	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
	struct bfusb_data *data;
	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);

	if (!hdev) {
		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
		return -ENODEV;
	}

	if (!test_bit(HCI_RUNNING, &hdev->flags))
		return -EBUSY;

	data = hdev->driver_data;

	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;
}
Пример #22
0
/* Recv data */
static int ll_recv(struct hci_uart *hu, void *data, int count)
{
	struct ll_struct *ll = hu->priv;
	char *ptr;
	struct hci_event_hdr *eh;
	struct hci_acl_hdr   *ah;
	struct hci_sco_hdr   *sh;
	int len, type, dlen;

	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count);

	ptr = data;
	while (count) {
		if (ll->rx_count) {
			len = min_t(unsigned int, ll->rx_count, count);
			memcpy(skb_put(ll->rx_skb, len), ptr, len);
			ll->rx_count -= len; count -= len; ptr += len;

			if (ll->rx_count)
				continue;

			switch (ll->rx_state) {
			case HCILL_W4_DATA:
				BT_DBG("Complete data");
				hci_recv_frame(hu->hdev, ll->rx_skb);

				ll->rx_state = HCILL_W4_PACKET_TYPE;
				ll->rx_skb = NULL;
				continue;

			case HCILL_W4_EVENT_HDR:
				eh = hci_event_hdr(ll->rx_skb);

				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);

				ll_check_data_len(hu->hdev, ll, eh->plen);
				continue;

			case HCILL_W4_ACL_HDR:
				ah = hci_acl_hdr(ll->rx_skb);
				dlen = __le16_to_cpu(ah->dlen);

				BT_DBG("ACL header: dlen %d", dlen);

				ll_check_data_len(hu->hdev, ll, dlen);
				continue;

			case HCILL_W4_SCO_HDR:
				sh = hci_sco_hdr(ll->rx_skb);

				BT_DBG("SCO header: dlen %d", sh->dlen);

				ll_check_data_len(hu->hdev, ll, sh->dlen);
				continue;
			}
		}

		/* HCILL_W4_PACKET_TYPE */
		switch (*ptr) {
		case HCI_EVENT_PKT:
			BT_DBG("Event packet");
			ll->rx_state = HCILL_W4_EVENT_HDR;
			ll->rx_count = HCI_EVENT_HDR_SIZE;
			type = HCI_EVENT_PKT;
			break;

		case HCI_ACLDATA_PKT:
			BT_DBG("ACL packet");
			ll->rx_state = HCILL_W4_ACL_HDR;
			ll->rx_count = HCI_ACL_HDR_SIZE;
			type = HCI_ACLDATA_PKT;
			break;

		case HCI_SCODATA_PKT:
			BT_DBG("SCO packet");
			ll->rx_state = HCILL_W4_SCO_HDR;
			ll->rx_count = HCI_SCO_HDR_SIZE;
			type = HCI_SCODATA_PKT;
			break;

		/* HCILL signals */
		case HCILL_GO_TO_SLEEP_IND:
			BT_DBG("HCILL_GO_TO_SLEEP_IND packet");
			ll_device_want_to_sleep(hu);
			ptr++; count--;
			continue;

		case HCILL_GO_TO_SLEEP_ACK:
			/* shouldn't happen */
			BT_ERR("received HCILL_GO_TO_SLEEP_ACK (in state %ld)", ll->hcill_state);
			ptr++; count--;
			continue;

		case HCILL_WAKE_UP_IND:
			BT_DBG("HCILL_WAKE_UP_IND packet");
			ll_device_want_to_wakeup(hu);
			ptr++; count--;
			continue;

		case HCILL_WAKE_UP_ACK:
			BT_DBG("HCILL_WAKE_UP_ACK packet");
			ll_device_woke_up(hu);
			ptr++; count--;
			continue;

		default:
			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
			hu->hdev->stat.err_rx++;
			ptr++; count--;
			continue;
		}

		ptr++; count--;

		/* Allocate packet */
		ll->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
		if (!ll->rx_skb) {
			BT_ERR("Can't allocate mem for new packet");
			ll->rx_state = HCILL_W4_PACKET_TYPE;
			ll->rx_count = 0;
			return -ENOMEM;
		}

		bt_cb(ll->rx_skb)->pkt_type = type;
	}
Пример #23
0
static int btusb_probe(struct usb_interface *intf,
				const struct usb_device_id *id)
{
	struct usb_endpoint_descriptor *ep_desc;
	struct btusb_data *data;
	struct hci_dev *hdev;
	int i, err;

	BT_DBG("intf %p id %p", intf, id);

	/* interface numbers are hardcoded in the spec */
	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
		return -ENODEV;

	if (!id->driver_info) {
		const struct usb_device_id *match;
		match = usb_match_id(intf, blacklist_table);
		if (match)
			id = match;
	}

	if (id->driver_info == BTUSB_IGNORE)
		return -ENODEV;

	if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
		return -ENODEV;

	if (ignore_csr && id->driver_info & BTUSB_CSR)
		return -ENODEV;

	if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
		return -ENODEV;

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
		ep_desc = &intf->cur_altsetting->endpoint[i].desc;

		if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
			data->intr_ep = ep_desc;
			continue;
		}

		if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
			data->bulk_tx_ep = ep_desc;
			continue;
		}

		if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
			data->bulk_rx_ep = ep_desc;
			continue;
		}
	}

	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
		kfree(data);
		return -ENODEV;
	}

	data->cmdreq_type = USB_TYPE_CLASS;

	data->udev = interface_to_usbdev(intf);
	data->intf = intf;

	spin_lock_init(&data->lock);

	INIT_WORK(&data->work, btusb_work);
	INIT_WORK(&data->waker, btusb_waker);
	spin_lock_init(&data->txlock);

	init_usb_anchor(&data->tx_anchor);
	init_usb_anchor(&data->intr_anchor);
	init_usb_anchor(&data->bulk_anchor);
	init_usb_anchor(&data->isoc_anchor);
	init_usb_anchor(&data->deferred);

	hdev = hci_alloc_dev();
	if (!hdev) {
		kfree(data);
		return -ENOMEM;
	}

	hdev->bus = HCI_USB;
	hdev->driver_data = data;

	data->hdev = hdev;

	SET_HCIDEV_DEV(hdev, &intf->dev);

	hdev->open     = btusb_open;
	hdev->close    = btusb_close;
	hdev->flush    = btusb_flush;
	hdev->send     = btusb_send_frame;
	hdev->destruct = btusb_destruct;
	hdev->notify   = btusb_notify;

	hdev->owner = THIS_MODULE;

	/* Interface numbers are hardcoded in the specification */
	data->isoc = usb_ifnum_to_if(data->udev, 1);

	if (!reset)
		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);

	if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
		if (!disable_scofix)
			set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
	}

	if (id->driver_info & BTUSB_BROKEN_ISOC)
		data->isoc = NULL;

	if (id->driver_info & BTUSB_DIGIANSWER) {
		data->cmdreq_type = USB_TYPE_VENDOR;
		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
	}

	if (id->driver_info & BTUSB_CSR) {
		struct usb_device *udev = data->udev;

		/* Old firmware would otherwise execute USB reset */
		if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
			set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
	}

	if (id->driver_info & BTUSB_SNIFFER) {
		struct usb_device *udev = data->udev;

		/* New sniffer firmware has crippled HCI interface */
		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
			set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);

		data->isoc = NULL;
	}

	if (id->driver_info & BTUSB_BCM92035) {
		unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
		struct sk_buff *skb;

		skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
		if (skb) {
			memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
			skb_queue_tail(&hdev->driver_init, skb);
		}
	}

	if (data->isoc) {
		err = usb_driver_claim_interface(&btusb_driver,
							data->isoc, data);
		if (err < 0) {
			hci_free_dev(hdev);
			kfree(data);
			return err;
		}
	}

	err = hci_register_dev(hdev);
	if (err < 0) {
		hci_free_dev(hdev);
		kfree(data);
		return err;
	}

	usb_set_intfdata(intf, data);

	return 0;
}
Пример #24
0
static void dtl1_receive(struct dtl1_info *info)
{
	unsigned int iobase;
	struct nsh *nsh;
	int boguscount = 0;

	if (!info) {
		BT_ERR("Unknown device");
		return;
	}

	iobase = info->p_dev->resource[0]->start;

	do {
		info->hdev->stat.byte_rx++;

		/* Allocate packet */
		if (info->rx_skb == NULL) {
			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
			if (!info->rx_skb) {
				BT_ERR("Can't allocate mem for new packet");
				info->rx_state = RECV_WAIT_NSH;
				info->rx_count = NSHL;
				return;
			}
		}

		*skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
		nsh = (struct nsh *)info->rx_skb->data;

		info->rx_count--;

		if (info->rx_count == 0) {

			switch (info->rx_state) {
			case RECV_WAIT_NSH:
				info->rx_state = RECV_WAIT_DATA;
				info->rx_count = nsh->len + (nsh->len & 0x0001);
				break;
			case RECV_WAIT_DATA:
				bt_cb(info->rx_skb)->pkt_type = nsh->type;

				/* remove PAD byte if it exists */
				if (nsh->len & 0x0001) {
					info->rx_skb->tail--;
					info->rx_skb->len--;
				}

				/* remove NSH */
				skb_pull(info->rx_skb, NSHL);

				switch (bt_cb(info->rx_skb)->pkt_type) {
				case 0x80:
					/* control data for the Nokia Card */
					dtl1_control(info, info->rx_skb);
					break;
				case 0x82:
				case 0x83:
				case 0x84:
					/* send frame to the HCI layer */
					bt_cb(info->rx_skb)->pkt_type &= 0x0f;
					hci_recv_frame(info->hdev, info->rx_skb);
					break;
				default:
					/* unknown packet */
					BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
					kfree_skb(info->rx_skb);
					break;
				}

				info->rx_state = RECV_WAIT_NSH;
				info->rx_count = NSHL;
				info->rx_skb = NULL;
				break;
			}

		}

		/* Make sure we don't stay here too long */
		if (boguscount++ > 32)
			break;

	} while (inb(iobase + UART_LSR) & UART_LSR_DR);
}
Пример #25
0
/* Recv data */
static int brcm_recv(struct hci_uart *hu, void *data, int count)
{
	struct brcm_struct *brcm = hu->priv;
	register char *ptr;
	struct hci_event_hdr *eh;
	struct hci_acl_hdr   *ah;
	struct hci_sco_hdr   *sh;
	register int len, type, dlen;

	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, brcm->rx_state, brcm->rx_count);

    serial_awake(hu);

    brcm->is_there_activity = 1;
    if (brcm->hcibrcm_state == HCIBRCM_ASLEEP)
    {
        BT_DBG("Assert wake signal, moves to AWAKE");
        /* assert BT_WAKE signal */
        assert_bt_wake();
        brcm->hcibrcm_state = HCIBRCM_AWAKE;
    }
	ptr = data;
	while (count) {
		if (brcm->rx_count) {
			len = min_t(unsigned int, brcm->rx_count, count);
			memcpy(skb_put(brcm->rx_skb, len), ptr, len);
			brcm->rx_count -= len; count -= len; ptr += len;

			if (brcm->rx_count)
				continue;

			switch (brcm->rx_state) {
			case HCIBRCM_W4_DATA:
				BT_DBG("Complete data");
				hci_recv_frame(brcm->rx_skb);

				brcm->rx_state = HCIBRCM_W4_PACKET_TYPE;
				brcm->rx_skb = NULL;
				continue;

			case HCIBRCM_W4_EVENT_HDR:
				eh = (struct hci_event_hdr *) brcm->rx_skb->data;

				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);

				brcm_check_data_len(brcm, eh->plen);
				continue;

			case HCIBRCM_W4_ACL_HDR:
				ah = (struct hci_acl_hdr *) brcm->rx_skb->data;
				dlen = __le16_to_cpu(ah->dlen);

				BT_DBG("ACL header: dlen %d", dlen);

				brcm_check_data_len(brcm, dlen);
				continue;

			case HCIBRCM_W4_SCO_HDR:
				sh = (struct hci_sco_hdr *) brcm->rx_skb->data;

				BT_DBG("SCO header: dlen %d", sh->dlen);

				brcm_check_data_len(brcm, sh->dlen);
				continue;
			}
		}

		/* HCIBRCM_W4_PACKET_TYPE */
		switch (*ptr) {
		case HCI_EVENT_PKT:
			BT_DBG("Event packet");
			brcm->rx_state = HCIBRCM_W4_EVENT_HDR;
			brcm->rx_count = HCI_EVENT_HDR_SIZE;
			type = HCI_EVENT_PKT;
			break;

		case HCI_ACLDATA_PKT:
			BT_DBG("ACL packet");
			brcm->rx_state = HCIBRCM_W4_ACL_HDR;
			brcm->rx_count = HCI_ACL_HDR_SIZE;
			type = HCI_ACLDATA_PKT;
			break;

		case HCI_SCODATA_PKT:
			BT_DBG("SCO packet");
			brcm->rx_state = HCIBRCM_W4_SCO_HDR;
			brcm->rx_count = HCI_SCO_HDR_SIZE;
			type = HCI_SCODATA_PKT;
			break;

		/* HCIBRCM signals */
		case HCIBRCM_GO_TO_SLEEP_IND:
			BT_DBG("HCIBRCM_GO_TO_SLEEP_IND packet");
			brcm_device_want_to_sleep(hu);
			ptr++; count--;
			continue;

		case HCIBRCM_GO_TO_SLEEP_ACK:
			/* shouldn't happen */
			BT_ERR("received HCIBRCM_GO_TO_SLEEP_ACK (in state %ld)", brcm->hcibrcm_state);
			ptr++; count--;
			continue;

		case HCIBRCM_WAKE_UP_IND:
			BT_DBG("HCIBRCM_WAKE_UP_IND packet");
			brcm_device_want_to_wakeup(hu);
			ptr++; count--;
			continue;

		case HCIBRCM_WAKE_UP_ACK:
			BT_DBG("HCIBRCM_WAKE_UP_ACK packet");
			brcm_device_woke_up(hu);
			ptr++; count--;
			continue;

		default:
			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
			hu->hdev->stat.err_rx++;
			ptr++; count--;
			continue;
		};

		ptr++; count--;

		/* Abrcmocate packet */
		brcm->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
		if (!brcm->rx_skb) {
			BT_ERR("Can't allocate mem for new packet");
			brcm->rx_state = HCIBRCM_W4_PACKET_TYPE;
			brcm->rx_count = 0;
			return 0;
		}

		brcm->rx_skb->dev = (void *) hu->hdev;
		bt_cb(brcm->rx_skb)->pkt_type = type;
	}
Пример #26
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;
}