Example #1
0
File: hci_usb.c Project: nhanh0/hah
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);
}
Example #2
0
int n_hci_tx_wakeup(struct n_hci *n_hci)
{
	register struct tty_struct *tty = n_hci->tty;

	if (test_and_set_bit(TRANS_SENDING, &n_hci->tx_state)) {
		set_bit(TRANS_WAKEUP, &n_hci->tx_state);
		return 0;
	}

	DBG("");
	do {
		register struct sk_buff *skb;
		register int len;

		clear_bit(TRANS_WAKEUP, &n_hci->tx_state);

		if (!(skb = skb_dequeue(&n_hci->txq)))
			break;

		DMP(skb->data, skb->len);

		/* Send frame to TTY driver */
		tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
		len = tty->driver.write(tty, 0, skb->data, skb->len);

		n_hci->hdev.stat.byte_tx += len;

		DBG("sent %d", len);

		if (len == skb->len) {
			/* Full frame was sent */
			kfree_skb(skb);
		} else {
			/* Subtract sent part and requeue  */
			skb_pull(skb, len);
			skb_queue_head(&n_hci->txq, skb);
		}
	} while (test_bit(TRANS_WAKEUP, &n_hci->tx_state));
	clear_bit(TRANS_SENDING, &n_hci->tx_state);

	return 0;
}
Example #3
0
static inline int n_hci_check_data_len(struct n_hci *n_hci, int len)
{
	register int room = skb_tailroom(n_hci->rx_skb);

	DBG("len %d room %d", len, room);
	if (!len) {
		DMP(n_hci->rx_skb->data, n_hci->rx_skb->len);
		hci_recv_frame(n_hci->rx_skb);
	} else if (len > room) {
		ERR("Data length is to large");
		kfree_skb(n_hci->rx_skb);
		n_hci->hdev.stat.err_rx++;
	} else {
		n_hci->rx_state = WAIT_DATA;
		n_hci->rx_count = len;
		return len;
	}

	n_hci->rx_state = WAIT_PACKET_TYPE;
	n_hci->rx_skb   = NULL;
	n_hci->rx_count = 0;
	return 0;
}
Example #4
0
// Parse RAW data and store internally
rr_ret
rr_parse(rr_ctx *ctx, UInt32 len, UInt8 *d)
{
    rr_ret ret;
    UInt32 n, m;
    UInt32 (*fn)(rr_ctx *, UInt32, UInt8 *);
    int nextState;
    
    n = 0;
    
    while (n < len  &&  !ctx->done)
    {
        switch (ctx->state)
        {
            case DDS_INIT:
                DMP("INIT\n");
                fn = rr_init;
                nextState = DDS_INTERSPACE;
                break;
            case DDS_INTERSPACE:
                DMP("INTERSPACE\n");
                fn = rr_interspace;
                nextState = DDS_PULSE;
                break;
            case DDS_PULSE:
                DMP("PULSE\n");
                fn = rr_pulse;
                nextState = DDS_SPACE;
                break;
            case DDS_SPACE:
                DMP("SPACE\n");
                fn = rr_space;
                nextState = DDS_PULSE;
                break;
            default:
                fn = NULL;
        }
        
        m = fn(ctx, len - n, &d[n]);
        ctx->state = nextState;
        if (m > len - n) break;
        n += m;
    }
 
    ret.n = n;
    if (ctx->done)
    {
        ret.done = 1;
        if (ret.n >= 2)
        {
            ret.m = (ctx->done == 1 ? n - 2 : n); // partial
        } else
        {
            ret.m = ret.n;
        }
        ret.d[0] = ret.d[1] = 0; // 0 inter-space delay
        ctx->state = DDS_INIT;
        ctx->done = 0;
    } else
    {
        ret.done = 0;
        ret.m = ret.n;
    }
    
    return ret;
}
Example #5
0
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;
	}
}
Example #6
0
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;
	}
}