コード例 #1
0
static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
				__u8 code, __u8 ident, __u16 dlen, void *data)
{
	struct sk_buff *skb, **frag;
	l2cap_cmd_hdr *cmd;
	l2cap_hdr *lh;
	int len, count;

	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", conn, code, ident, dlen);

	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
	count = MIN(conn->mtu, len);
	
	skb = bluez_skb_alloc(count, GFP_ATOMIC);
	if (!skb)
		return NULL;

	lh = (l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
	lh->len = __cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
	lh->cid = __cpu_to_le16(0x0001);

	cmd = (l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
	cmd->code  = code;
	cmd->ident = ident;
	cmd->len   = __cpu_to_le16(dlen);

	if (dlen) {
		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
		memcpy(skb_put(skb, count), data, count);
		data += count;
	}

	len -= skb->len;
	
	/* Continuation fragments (no L2CAP header) */
	frag = &skb_shinfo(skb)->frag_list;
	while (len) {
		count = MIN(conn->mtu, len);

		*frag = bluez_skb_alloc(count, GFP_ATOMIC);
		if (!*frag)
			goto fail;
		
		memcpy(skb_put(*frag, count), data, count);

		len  -= count;
		data += count;
		
		frag = &(*frag)->next;
	}

	return skb;

fail:
	kfree_skb(skb);
	return NULL;
}
コード例 #2
0
/* General internal stack event */
void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
{
	hci_event_hdr *eh;
	evt_stack_internal *si;
	struct sk_buff *skb;
	int size;
	void *ptr;

	size = HCI_EVENT_HDR_SIZE + EVT_STACK_INTERNAL_SIZE + dlen;
	skb  = bluez_skb_alloc(size, GFP_ATOMIC);
	if (!skb)
		return;

	ptr = skb_put(skb, size);

	eh = ptr;
       	eh->evt  = EVT_STACK_INTERNAL;
	eh->plen = EVT_STACK_INTERNAL_SIZE + dlen;
	ptr += HCI_EVENT_HDR_SIZE;

	si = ptr;
	si->type = type;
	memcpy(si->data, data, dlen);
	
	skb->pkt_type = HCI_EVENT_PKT;
	skb->dev = (void *) hdev;
	hci_send_to_sock(hdev, skb);
	kfree_skb(skb);
}
コード例 #3
0
ファイル: hci_usb.c プロジェクト: TitaniumBoy/lin
static void hci_usb_bulk_read(struct urb *urb)
{
	struct hci_usb *husb = (struct hci_usb *) urb->context;
	unsigned char *data = urb->transfer_buffer;
	int count = urb->actual_length, status;
	struct sk_buff *skb;
	hci_acl_hdr *ah;
	register __u16 dlen;

	if (!husb)
		return;

	DBG("%s status %d, count %d, flags %x", husb->hdev.name, urb->status, count, urb->transfer_flags);

	if (urb->status) {
		/* Do not re-submit URB on critical errors */
		switch (urb->status) {
			case -ENOENT:
				return;
			default:
				goto resubmit;
		};
	}
	if (!count)
		goto resubmit;

	DMP(data, count);

	ah = (hci_acl_hdr *) data;
	dlen = le16_to_cpu(ah->dlen);

	/* Verify frame len and completeness */
	if ((count - HCI_ACL_HDR_SIZE) != dlen) {
		ERR("%s corrupted ACL packet: count %d, plen %d", husb->hdev.name, count, dlen);
		goto resubmit;
	}

	/* Allocate packet */
	if (!(skb = bluez_skb_alloc(count, GFP_ATOMIC))) {
		ERR("Can't allocate mem for new packet");
		goto resubmit;
	}

	memcpy(skb_put(skb, count), data, count);
	skb->dev = (void *) &husb->hdev;
	skb->pkt_type = HCI_ACLDATA_PKT;

	husb->hdev.stat.byte_rx += skb->len;

	hci_recv_frame(skb);

resubmit:
	husb->read_urb->dev = husb->udev;
	if ((status = usb_submit_urb(husb->read_urb)))
		DBG("%s read URB submit failed %d", husb->hdev.name, status);

	DBG("%s read URB re-submited", husb->hdev.name);
}
コード例 #4
0
static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
{
	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
	struct sk_buff *skb;

	/* Ericsson baud rate command */
	unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };

	if (!(skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
		printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n");
		return -1;
	}

	switch (baud) {
	case 460800:
		cmd[4] = 0x00;
		skb->pkt_type = PKT_BAUD_RATE_460800;
		break;
	case 230400:
		cmd[4] = 0x01;
		skb->pkt_type = PKT_BAUD_RATE_230400;
		break;
	case 115200:
		cmd[4] = 0x02;
		skb->pkt_type = PKT_BAUD_RATE_115200;
		break;
	case 57600:
		/* Fall through... */
	default:
		cmd[4] = 0x03;
		skb->pkt_type = PKT_BAUD_RATE_57600;
		break;
	}

	memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));

	skb_queue_tail(&(info->txq), skb);

	bluecard_write_wakeup(info);

	return 0;
}
/* Get packet from user space buffer(already verified) */
static inline ssize_t hci_vhci_get_user(struct hci_vhci_struct *hci_vhci, const char *buf, size_t count)
{
	struct sk_buff *skb;

	if (count > HCI_MAX_FRAME_SIZE)
		return -EINVAL;

	if (!(skb = bluez_skb_alloc(count, GFP_KERNEL)))
		return -ENOMEM;
	
	copy_from_user(skb_put(skb, count), buf, count); 

	skb->dev = (void *) &hci_vhci->hdev;
	skb->pkt_type = *((__u8 *) skb->data);
	skb_pull(skb, 1);

	hci_recv_frame(skb);

	return count;
} 
コード例 #6
0
static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, __u16 flags)
{
	struct l2cap_conn *conn = hcon->l2cap_data;

	if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
		goto drop;

	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);

	if (flags & ACL_START) {
		l2cap_hdr *hdr;
		int len;

		if (conn->rx_len) {
			BT_ERR("Unexpected start frame (len %d)", skb->len);
			kfree_skb(conn->rx_skb);
			conn->rx_skb = NULL;
			conn->rx_len = 0;
			l2cap_conn_unreliable(conn, ECOMM);
		}

		if (skb->len < 2) {
			BT_ERR("Frame is too short (len %d)", skb->len);
			l2cap_conn_unreliable(conn, ECOMM);
			goto drop;
		}

		hdr = (l2cap_hdr *) skb->data;
		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;

		if (len == skb->len) {
			/* Complete frame received */
			l2cap_recv_frame(conn, skb);
			return 0;
		}

		BT_DBG("Start: total len %d, frag len %d", len, skb->len);

		if (skb->len > len) {
			BT_ERR("Frame is too long (len %d, expected len %d)",
				skb->len, len);
			l2cap_conn_unreliable(conn, ECOMM);
			goto drop;
		}

		/* Allocate skb for the complete frame including header */
		conn->rx_skb = bluez_skb_alloc(len, GFP_ATOMIC);
		if (!conn->rx_skb)
			goto drop;

		memcpy(skb_put(conn->rx_skb, skb->len), skb->data, skb->len);
		conn->rx_len = len - skb->len;
	} else {
		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);

		if (!conn->rx_len) {
			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
			l2cap_conn_unreliable(conn, ECOMM);
			goto drop;
		}

		if (skb->len > conn->rx_len) {
			BT_ERR("Fragment is too long (len %d, expected %d)",
					skb->len, conn->rx_len);
			kfree_skb(conn->rx_skb);
			conn->rx_skb = NULL;
			conn->rx_len = 0;
			l2cap_conn_unreliable(conn, ECOMM);
			goto drop;
		}

		memcpy(skb_put(conn->rx_skb, skb->len), skb->data, skb->len);
		conn->rx_len -= skb->len;

		if (!conn->rx_len) {
			/* Complete frame received */
			l2cap_recv_frame(conn, conn->rx_skb);
			conn->rx_skb = NULL;
		}
	}

drop:
	kfree_skb(skb);
	return 0;
}
コード例 #7
0
ファイル: hci_usb.c プロジェクト: TitaniumBoy/lin
static void hci_usb_intr(struct urb *urb)
{
	struct hci_usb *husb = (struct hci_usb *) urb->context;
	unsigned char *data = urb->transfer_buffer;
	register int count  = urb->actual_length;
	register struct sk_buff *skb = husb->intr_skb;
	hci_event_hdr *eh;
	register int len;

	if (!husb)
		return;

	DBG("%s count %d", husb->hdev.name, count);

	if (urb->status || !count) {
		DBG("%s intr status %d, count %d", husb->hdev.name, urb->status, count);
		return;
	}

	/* Do we really have to handle continuations here ? */
	if (!skb) {
		/* New frame */
		if (count < HCI_EVENT_HDR_SIZE) {
			DBG("%s bad frame len %d", husb->hdev.name, count);
			return;
		}

		eh = (hci_event_hdr *) data;
		len = eh->plen + HCI_EVENT_HDR_SIZE;

		if (count > len) {
			DBG("%s corrupted frame, len %d", husb->hdev.name, count);
			return;
		}

		/* Allocate skb */
		if (!(skb = bluez_skb_alloc(len, GFP_ATOMIC))) {
			ERR("Can't allocate mem for new packet");
			return;
		}
		skb->dev = (void *) &husb->hdev;
		skb->pkt_type = HCI_EVENT_PKT;

		husb->intr_skb = skb;
		husb->intr_count = len;
	} else {
		/* Continuation */
		if (count > husb->intr_count) {
			ERR("%s bad frame len %d (expected %d)", husb->hdev.name, count, husb->intr_count);

			kfree_skb(skb);
			husb->intr_skb = NULL;
			husb->intr_count = 0;
			return;
		}
	}

	memcpy(skb_put(skb, count), data, count);
	husb->intr_count -= count;

	DMP(data, count);

	if (!husb->intr_count) {
		/* Got complete frame */

		husb->hdev.stat.byte_rx += skb->len;
		hci_recv_frame(skb);

		husb->intr_skb = NULL;
	}
}
コード例 #8
0
ファイル: hci_h4.c プロジェクト: romanalexander/Trickles
/* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count)
{
	struct h4_struct *h4 = hu->priv;
	register char *ptr;
	hci_event_hdr *eh;
	hci_acl_hdr   *ah;
	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(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 = (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 = (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 = (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 = bluez_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;
	}
	return count;
}
コード例 #9
0
ファイル: hci_uart.c プロジェクト: nhanh0/hah
static inline void n_hci_rx(struct n_hci *n_hci, const __u8 * data, char *flags, int count)
{
	register const char *ptr;
	hci_event_hdr *eh;
	hci_acl_hdr   *ah;
	hci_sco_hdr   *sh;
	register int len, type, dlen;

	DBG("count %d state %ld rx_count %ld", count, n_hci->rx_state, n_hci->rx_count);

	n_hci->hdev.stat.byte_rx += count;

	ptr = data;
	while (count) {
		if (n_hci->rx_count) {
			len = MIN(n_hci->rx_count, count);
			memcpy(skb_put(n_hci->rx_skb, len), ptr, len);
			n_hci->rx_count -= len; count -= len; ptr += len;

			if (n_hci->rx_count)
				continue;

			switch (n_hci->rx_state) {
				case WAIT_DATA:
					DBG("Complete data");

					DMP(n_hci->rx_skb->data, n_hci->rx_skb->len);

					hci_recv_frame(n_hci->rx_skb);

					n_hci->rx_state = WAIT_PACKET_TYPE;
					n_hci->rx_skb = NULL;
					continue;

				case WAIT_EVENT_HDR:
					eh = (hci_event_hdr *) n_hci->rx_skb->data;

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

					n_hci_check_data_len(n_hci, eh->plen);
					continue;

				case WAIT_ACL_HDR:
					ah = (hci_acl_hdr *) n_hci->rx_skb->data;
					dlen = __le16_to_cpu(ah->dlen);

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

					n_hci_check_data_len(n_hci, dlen);
					continue;

				case WAIT_SCO_HDR:
					sh = (hci_sco_hdr *) n_hci->rx_skb->data;

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

					n_hci_check_data_len(n_hci, sh->dlen);
					continue;
			};
		}

		/* WAIT_PACKET_TYPE */
		switch (*ptr) {
			case HCI_EVENT_PKT:
				DBG("Event packet");
				n_hci->rx_state = WAIT_EVENT_HDR;
				n_hci->rx_count = HCI_EVENT_HDR_SIZE;
				type = HCI_EVENT_PKT;
				break;

			case HCI_ACLDATA_PKT:
				DBG("ACL packet");
				n_hci->rx_state = WAIT_ACL_HDR;
				n_hci->rx_count = HCI_ACL_HDR_SIZE;
				type = HCI_ACLDATA_PKT;
				break;

			case HCI_SCODATA_PKT:
				DBG("SCO packet");
				n_hci->rx_state = WAIT_SCO_HDR;
				n_hci->rx_count = HCI_SCO_HDR_SIZE;
				type = HCI_SCODATA_PKT;
				break;

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

		/* Allocate packet */
		if (!(n_hci->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
			ERR("Can't allocate mem for new packet");

			n_hci->rx_state = WAIT_PACKET_TYPE;
			n_hci->rx_count = 0;
			return;
		}
		n_hci->rx_skb->dev = (void *) &n_hci->hdev;
		n_hci->rx_skb->pkt_type = type;
	}
}
コード例 #10
0
static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
{
	unsigned int iobase;
	unsigned char buf[31];
	int i, len;

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

	iobase = info->link.io.BasePort1;

	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 = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
				printk(KERN_WARNING "bluecard_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 = buf[i];

			switch (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 */
				printk(KERN_WARNING "bluecard_cs: Unknown HCI packet with type 0x%02x received.\n", 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;
				hci_event_hdr *eh;
				hci_acl_hdr *ah;
				hci_sco_hdr *sh;

				switch (info->rx_state) {

				case RECV_WAIT_EVENT_HEADER:
					eh = (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 = (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 = (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;

				}

			}

		}


	}

	info->hdev.stat.byte_rx += len;
}