xref: /linux/drivers/bluetooth/hci_h4.c (revision 13abf8130139c2ccd4962a7e5a8902be5e6cb5a7)
1 /*
2    BlueZ - Bluetooth protocol stack for Linux
3    Copyright (C) 2000-2001 Qualcomm Incorporated
4 
5    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License version 2 as
9    published by the Free Software Foundation;
10 
11    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 
20    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22    SOFTWARE IS DISCLAIMED.
23 */
24 
25 /*
26  * Bluetooth HCI UART(H4) protocol.
27  *
28  * $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $
29  */
30 #define VERSION "1.2"
31 
32 #include <linux/config.h>
33 #include <linux/module.h>
34 
35 #include <linux/kernel.h>
36 #include <linux/init.h>
37 #include <linux/sched.h>
38 #include <linux/types.h>
39 #include <linux/fcntl.h>
40 #include <linux/interrupt.h>
41 #include <linux/ptrace.h>
42 #include <linux/poll.h>
43 
44 #include <linux/slab.h>
45 #include <linux/tty.h>
46 #include <linux/errno.h>
47 #include <linux/string.h>
48 #include <linux/signal.h>
49 #include <linux/ioctl.h>
50 #include <linux/skbuff.h>
51 
52 #include <net/bluetooth/bluetooth.h>
53 #include <net/bluetooth/hci_core.h>
54 #include "hci_uart.h"
55 #include "hci_h4.h"
56 
57 #ifndef CONFIG_BT_HCIUART_DEBUG
58 #undef  BT_DBG
59 #define BT_DBG( A... )
60 #endif
61 
62 /* Initialize protocol */
63 static int h4_open(struct hci_uart *hu)
64 {
65 	struct h4_struct *h4;
66 
67 	BT_DBG("hu %p", hu);
68 
69 	h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
70 	if (!h4)
71 		return -ENOMEM;
72 	memset(h4, 0, sizeof(*h4));
73 
74 	skb_queue_head_init(&h4->txq);
75 
76 	hu->priv = h4;
77 	return 0;
78 }
79 
80 /* Flush protocol data */
81 static int h4_flush(struct hci_uart *hu)
82 {
83 	struct h4_struct *h4 = hu->priv;
84 
85 	BT_DBG("hu %p", hu);
86 	skb_queue_purge(&h4->txq);
87 	return 0;
88 }
89 
90 /* Close protocol */
91 static int h4_close(struct hci_uart *hu)
92 {
93 	struct h4_struct *h4 = hu->priv;
94 	hu->priv = NULL;
95 
96 	BT_DBG("hu %p", hu);
97 
98 	skb_queue_purge(&h4->txq);
99 	if (h4->rx_skb)
100 		kfree_skb(h4->rx_skb);
101 
102 	hu->priv = NULL;
103 	kfree(h4);
104 	return 0;
105 }
106 
107 /* Enqueue frame for transmittion (padding, crc, etc) */
108 static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
109 {
110 	struct h4_struct *h4 = hu->priv;
111 
112 	BT_DBG("hu %p skb %p", hu, skb);
113 
114 	/* Prepend skb with frame type */
115 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
116 	skb_queue_tail(&h4->txq, skb);
117 	return 0;
118 }
119 
120 static inline int h4_check_data_len(struct h4_struct *h4, int len)
121 {
122 	register int room = skb_tailroom(h4->rx_skb);
123 
124 	BT_DBG("len %d room %d", len, room);
125 	if (!len) {
126 		hci_recv_frame(h4->rx_skb);
127 	} else if (len > room) {
128 		BT_ERR("Data length is too large");
129 		kfree_skb(h4->rx_skb);
130 	} else {
131 		h4->rx_state = H4_W4_DATA;
132 		h4->rx_count = len;
133 		return len;
134 	}
135 
136 	h4->rx_state = H4_W4_PACKET_TYPE;
137 	h4->rx_skb   = NULL;
138 	h4->rx_count = 0;
139 	return 0;
140 }
141 
142 /* Recv data */
143 static int h4_recv(struct hci_uart *hu, void *data, int count)
144 {
145 	struct h4_struct *h4 = hu->priv;
146 	register char *ptr;
147 	struct hci_event_hdr *eh;
148 	struct hci_acl_hdr   *ah;
149 	struct hci_sco_hdr   *sh;
150 	register int len, type, dlen;
151 
152 	BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
153 			hu, count, h4->rx_state, h4->rx_count);
154 
155 	ptr = data;
156 	while (count) {
157 		if (h4->rx_count) {
158 			len = min_t(unsigned int, h4->rx_count, count);
159 			memcpy(skb_put(h4->rx_skb, len), ptr, len);
160 			h4->rx_count -= len; count -= len; ptr += len;
161 
162 			if (h4->rx_count)
163 				continue;
164 
165 			switch (h4->rx_state) {
166 			case H4_W4_DATA:
167 				BT_DBG("Complete data");
168 
169 				hci_recv_frame(h4->rx_skb);
170 
171 				h4->rx_state = H4_W4_PACKET_TYPE;
172 				h4->rx_skb = NULL;
173 				continue;
174 
175 			case H4_W4_EVENT_HDR:
176 				eh = (struct hci_event_hdr *) h4->rx_skb->data;
177 
178 				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
179 
180 				h4_check_data_len(h4, eh->plen);
181 				continue;
182 
183 			case H4_W4_ACL_HDR:
184 				ah = (struct hci_acl_hdr *) h4->rx_skb->data;
185 				dlen = __le16_to_cpu(ah->dlen);
186 
187 				BT_DBG("ACL header: dlen %d", dlen);
188 
189 				h4_check_data_len(h4, dlen);
190 				continue;
191 
192 			case H4_W4_SCO_HDR:
193 				sh = (struct hci_sco_hdr *) h4->rx_skb->data;
194 
195 				BT_DBG("SCO header: dlen %d", sh->dlen);
196 
197 				h4_check_data_len(h4, sh->dlen);
198 				continue;
199 			}
200 		}
201 
202 		/* H4_W4_PACKET_TYPE */
203 		switch (*ptr) {
204 		case HCI_EVENT_PKT:
205 			BT_DBG("Event packet");
206 			h4->rx_state = H4_W4_EVENT_HDR;
207 			h4->rx_count = HCI_EVENT_HDR_SIZE;
208 			type = HCI_EVENT_PKT;
209 			break;
210 
211 		case HCI_ACLDATA_PKT:
212 			BT_DBG("ACL packet");
213 			h4->rx_state = H4_W4_ACL_HDR;
214 			h4->rx_count = HCI_ACL_HDR_SIZE;
215 			type = HCI_ACLDATA_PKT;
216 			break;
217 
218 		case HCI_SCODATA_PKT:
219 			BT_DBG("SCO packet");
220 			h4->rx_state = H4_W4_SCO_HDR;
221 			h4->rx_count = HCI_SCO_HDR_SIZE;
222 			type = HCI_SCODATA_PKT;
223 			break;
224 
225 		default:
226 			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
227 			hu->hdev->stat.err_rx++;
228 			ptr++; count--;
229 			continue;
230 		};
231 		ptr++; count--;
232 
233 		/* Allocate packet */
234 		h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
235 		if (!h4->rx_skb) {
236 			BT_ERR("Can't allocate mem for new packet");
237 			h4->rx_state = H4_W4_PACKET_TYPE;
238 			h4->rx_count = 0;
239 			return 0;
240 		}
241 		h4->rx_skb->dev = (void *) hu->hdev;
242 		bt_cb(h4->rx_skb)->pkt_type = type;
243 	}
244 	return count;
245 }
246 
247 static struct sk_buff *h4_dequeue(struct hci_uart *hu)
248 {
249 	struct h4_struct *h4 = hu->priv;
250 	return skb_dequeue(&h4->txq);
251 }
252 
253 static struct hci_uart_proto h4p = {
254 	.id      = HCI_UART_H4,
255 	.open    = h4_open,
256 	.close   = h4_close,
257 	.recv    = h4_recv,
258 	.enqueue = h4_enqueue,
259 	.dequeue = h4_dequeue,
260 	.flush   = h4_flush,
261 };
262 
263 int h4_init(void)
264 {
265 	int err = hci_uart_register_proto(&h4p);
266 	if (!err)
267 		BT_INFO("HCI H4 protocol initialized");
268 	else
269 		BT_ERR("HCI H4 protocol registration failed");
270 
271 	return err;
272 }
273 
274 int h4_deinit(void)
275 {
276 	return hci_uart_unregister_proto(&h4p);
277 }
278