aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-07-16 09:12:03 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-07-17 13:34:40 -0400
commit7d664fbafaf992e501159c013b4264a03ee1efac (patch)
treed503d2bdba545c429f33b95cda401a8514f09501 /drivers/bluetooth
parent7dec65c8a7fdab87d23bcf3c7e7eff662d180853 (diff)
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: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/hci_h5.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index 6353d00ba864..6b7ec643f3da 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -30,14 +30,48 @@
30 30
31#include "hci_uart.h" 31#include "hci_uart.h"
32 32
33struct h5 {
34 struct sk_buff_head unack; /* Unack'ed packets queue */
35 struct sk_buff_head rel; /* Reliable packets queue */
36 struct sk_buff_head unrel; /* Unreliable packets queue */
37
38 struct sk_buff *rx_skb;
39
40 bool txack_req;
41
42 u8 msgq_txseq;
43};
44
33static int h5_open(struct hci_uart *hu) 45static int h5_open(struct hci_uart *hu)
34{ 46{
35 return -ENOSYS; 47 struct h5 *h5;
48
49 BT_DBG("hu %p", hu);
50
51 h5 = kzalloc(sizeof(*h5), GFP_KERNEL);
52 if (!h5)
53 return -ENOMEM;
54
55 hu->priv = h5;
56
57 skb_queue_head_init(&h5->unack);
58 skb_queue_head_init(&h5->rel);
59 skb_queue_head_init(&h5->unrel);
60
61 return 0;
36} 62}
37 63
38static int h5_close(struct hci_uart *hu) 64static int h5_close(struct hci_uart *hu)
39{ 65{
40 return -ENOSYS; 66 struct h5 *h5 = hu->priv;
67
68 skb_queue_purge(&h5->unack);
69 skb_queue_purge(&h5->rel);
70 skb_queue_purge(&h5->unrel);
71
72 kfree(h5);
73
74 return 0;
41} 75}
42 76
43static int h5_recv(struct hci_uart *hu, void *data, int count) 77static 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)
47 81
48static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb) 82static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
49{ 83{
50 return -ENOSYS; 84 struct h5 *h5 = hu->priv;
85
86 if (skb->len > 0xfff) {
87 BT_ERR("Packet too long (%u bytes)", skb->len);
88 kfree_skb(skb);
89 return 0;
90 }
91
92 switch (bt_cb(skb)->pkt_type) {
93 case HCI_ACLDATA_PKT:
94 case HCI_COMMAND_PKT:
95 skb_queue_tail(&h5->rel, skb);
96 break;
97
98 case HCI_SCODATA_PKT:
99 skb_queue_tail(&h5->unrel, skb);
100 break;
101
102 default:
103 BT_ERR("Unknown packet type %u", bt_cb(skb)->pkt_type);
104 kfree_skb(skb);
105 break;
106 }
107
108 return 0;
109}
110
111static struct sk_buff *h5_prepare_pkt(struct h5 *h5, struct sk_buff *skb)
112{
113 h5->txack_req = false;
114 return NULL;
115}
116
117static struct sk_buff *h5_prepare_ack(struct h5 *h5)
118{
119 h5->txack_req = false;
120 return NULL;
51} 121}
52 122
53static struct sk_buff *h5_dequeue(struct hci_uart *hu) 123static struct sk_buff *h5_dequeue(struct hci_uart *hu)
54{ 124{
125 struct h5 *h5 = hu->priv;
126 struct sk_buff *skb, *nskb;
127
128 if ((skb = skb_dequeue(&h5->unrel)) != NULL) {
129 nskb = h5_prepare_pkt(h5, skb);
130 if (nskb) {
131 kfree_skb(skb);
132 return nskb;
133 }
134
135 skb_queue_head(&h5->unrel, skb);
136 BT_ERR("Could not dequeue pkt because alloc_skb failed");
137 }
138
139 if (h5->txack_req)
140 return h5_prepare_ack(h5);
141
55 return NULL; 142 return NULL;
56} 143}
57 144
58static int h5_flush(struct hci_uart *hu) 145static int h5_flush(struct hci_uart *hu)
59{ 146{
60 return -ENOSYS; 147 BT_DBG("hu %p", hu);
148 return 0;
61} 149}
62 150
63static struct hci_uart_proto h5p = { 151static struct hci_uart_proto h5p = {