Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d664fba authored by Johan Hedberg's avatar Johan Hedberg Committed by Gustavo Padovan
Browse files

Bluetooth: Add basic state tracking to Three-wire UART driver



This patch adds basic state tracking and socket buffer handling to the
Three-wire UART (H5) HCI driver.

Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
parent 7dec65c8
Loading
Loading
Loading
Loading
+92 −4
Original line number Diff line number Diff line
@@ -30,14 +30,48 @@

#include "hci_uart.h"

struct h5 {
	struct sk_buff_head unack;	/* Unack'ed packets queue */
	struct sk_buff_head rel;	/* Reliable packets queue */
	struct sk_buff_head unrel;	/* Unreliable packets queue */

	struct sk_buff *rx_skb;

	bool txack_req;

	u8 msgq_txseq;
};

static int h5_open(struct hci_uart *hu)
{
	return -ENOSYS;
	struct h5 *h5;

	BT_DBG("hu %p", hu);

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

	hu->priv = h5;

	skb_queue_head_init(&h5->unack);
	skb_queue_head_init(&h5->rel);
	skb_queue_head_init(&h5->unrel);

	return 0;
}

static int h5_close(struct hci_uart *hu)
{
	return -ENOSYS;
	struct h5 *h5 = hu->priv;

	skb_queue_purge(&h5->unack);
	skb_queue_purge(&h5->rel);
	skb_queue_purge(&h5->unrel);

	kfree(h5);

	return 0;
}

static int h5_recv(struct hci_uart *hu, void *data, int count)
@@ -47,17 +81,71 @@ static int h5_recv(struct hci_uart *hu, void *data, int count)

static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
	return -ENOSYS;
	struct h5 *h5 = hu->priv;

	if (skb->len > 0xfff) {
		BT_ERR("Packet too long (%u bytes)", skb->len);
		kfree_skb(skb);
		return 0;
	}

	switch (bt_cb(skb)->pkt_type) {
	case HCI_ACLDATA_PKT:
	case HCI_COMMAND_PKT:
		skb_queue_tail(&h5->rel, skb);
		break;

	case HCI_SCODATA_PKT:
		skb_queue_tail(&h5->unrel, skb);
		break;

	default:
		BT_ERR("Unknown packet type %u", bt_cb(skb)->pkt_type);
		kfree_skb(skb);
		break;
	}

	return 0;
}

static struct sk_buff *h5_prepare_pkt(struct h5 *h5, struct sk_buff *skb)
{
	h5->txack_req = false;
	return NULL;
}

static struct sk_buff *h5_prepare_ack(struct h5 *h5)
{
	h5->txack_req = false;
	return NULL;
}

static struct sk_buff *h5_dequeue(struct hci_uart *hu)
{
	struct h5 *h5 = hu->priv;
	struct sk_buff *skb, *nskb;

	if ((skb = skb_dequeue(&h5->unrel)) != NULL) {
		nskb = h5_prepare_pkt(h5, skb);
		if (nskb) {
			kfree_skb(skb);
			return nskb;
		}

		skb_queue_head(&h5->unrel, skb);
		BT_ERR("Could not dequeue pkt because alloc_skb failed");
	}

	if (h5->txack_req)
		return h5_prepare_ack(h5);

	return NULL;
}

static int h5_flush(struct hci_uart *hu)
{
	return -ENOSYS;
	BT_DBG("hu %p", hu);
	return 0;
}

static struct hci_uart_proto h5p = {