Beispiel #1
0
/* may be cabrcmed from two simultaneous tasklets */
static int brcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
	//unsigned long flags = 0;
	struct brcm_struct *brcm = hu->priv;

	BT_DBG("hu %p skb %p", hu, skb);

	/* Prepend skb with frame type */
	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
#if 0
	/* lock hcibrcm state */
	spin_lock_irqsave(&brcm->hcibrcm_lock, flags);

	/* act according to current state */
	switch (brcm->hcibrcm_state) {
	case HCIBRCM_AWAKE:
		BT_DBG("device awake, sending normabrcmy");
		skb_queue_tail(&brcm->txq, skb);
		break;
	case HCIBRCM_ASLEEP:
		BT_DBG("device asleep, waking up and queueing packet");
		__brcm_msm_serial_clock_on(hu->tty);
		/* save packet for later */
		skb_queue_tail(&brcm->tx_wait_q, skb);
		/* awake device */
		if (send_hcibrcm_cmd(HCIBRCM_WAKE_UP_IND, hu) < 0) {
			BT_ERR("cannot wake up device");
			break;
		}
		brcm->hcibrcm_state = HCIBRCM_ASLEEP_TO_AWAKE;
		break;
	case HCIBRCM_ASLEEP_TO_AWAKE:
		BT_DBG("device waking up, queueing packet");
		/* transient state; just keep packet for later */
		skb_queue_tail(&brcm->tx_wait_q, skb);
		break;
	default:
		BT_ERR("ibrcmegal hcibrcm state: %ld (losing packet)", brcm->hcibrcm_state);
		kfree_skb(skb);
		break;
	}

	spin_unlock_irqrestore(&brcm->hcibrcm_lock, flags);
#endif

    serial_awake(hu);

	skb_queue_tail(&brcm->txq, skb);

        brcm->is_there_activity = 1;
        if (brcm->hcibrcm_state == HCIBRCM_ASLEEP)
        {
            BT_DBG("Asserting wake signal, moves to AWAKE");
            /* assert BT_WAKE signal */
            assert_bt_wake();
            brcm->hcibrcm_state = HCIBRCM_AWAKE;
        }

	return 0;
}
/* Initialize protocol */
static int brcm_open(struct hci_uart *hu)
{
	struct brcm_struct *brcm;
	BT_DBG("hu %p", hu);

	brcm = kzalloc(sizeof(*brcm), GFP_ATOMIC);
	if (!brcm)
		return -ENOMEM;

	skb_queue_head_init(&brcm->txq);
	skb_queue_head_init(&brcm->tx_wait_q);
	spin_lock_init(&brcm->hcibrcm_lock);

	brcm->hcibrcm_state = HCIBRCM_AWAKE;
	hw_struct = kzalloc(sizeof(*hw_struct), GFP_ATOMIC);
	if (!hw_struct)
		return -ENOMEM;
	hw_struct = bcm_bzhw_start(hu->tty);
	if (hw_struct != NULL) {
		brcm->btwake_gpio = hw_struct->pdata->gpio_bt_wake;
		brcm->hostwake_gpio = hw_struct->pdata->gpio_host_wake;
		brcm->lqos_node = &hw_struct->qos_node;
		init_timer(&sleep_timer);
		brcm->is_there_activity = 0;
		hu->priv = brcm;
		sleep_timer.expires = jiffies + msecs_to_jiffies(TIMER_PERIOD);
		sleep_timer.data = (unsigned long)brcm;
		sleep_timer.function = sleep_timer_function;
		add_timer(&sleep_timer);
		__brcm_bcm_serial_clock_on(hu);
		assert_bt_wake(brcm->btwake_gpio, brcm->lqos_node, hu->tty);
	} else
		return -EFAULT;
	return 0;
}
Beispiel #3
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);

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