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  * BlueZ 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/version.h>
36 #include <linux/kernel.h>
37 #include <linux/init.h>
38 #include <linux/sched.h>
39 #include <linux/types.h>
40 #include <linux/fcntl.h>
41 #include <linux/interrupt.h>
42 #include <linux/ptrace.h>
43 #include <linux/poll.h>
44 
45 #include <linux/slab.h>
46 #include <linux/tty.h>
47 #include <linux/errno.h>
48 #include <linux/string.h>
49 #include <linux/signal.h>
50 #include <linux/ioctl.h>
51 #include <linux/skbuff.h>
52 
53 #include <net/bluetooth/bluetooth.h>
54 #include <net/bluetooth/hci_core.h>
55 #include "hci_uart.h"
56 #include "hci_h4.h"
57 
58 #ifndef HCI_UART_DEBUG
59 #undef  BT_DBG
60 #define BT_DBG( A... )
61 #undef  BT_DMP
62 #define BT_DMP( A... )
63 #endif
64 
65 /* Initialize protocol */
h4_open(struct hci_uart * hu)66 static int h4_open(struct hci_uart *hu)
67 {
68 	struct h4_struct *h4;
69 
70 	BT_DBG("hu %p", hu);
71 
72 	h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
73 	if (!h4)
74 		return -ENOMEM;
75 	memset(h4, 0, sizeof(*h4));
76 
77 	skb_queue_head_init(&h4->txq);
78 
79 	hu->priv = h4;
80 	return 0;
81 }
82 
83 /* Flush protocol data */
h4_flush(struct hci_uart * hu)84 static int h4_flush(struct hci_uart *hu)
85 {
86 	struct h4_struct *h4 = hu->priv;
87 
88 	BT_DBG("hu %p", hu);
89 	skb_queue_purge(&h4->txq);
90 	return 0;
91 }
92 
93 /* Close protocol */
h4_close(struct hci_uart * hu)94 static int h4_close(struct hci_uart *hu)
95 {
96 	struct h4_struct *h4 = hu->priv;
97 	hu->priv = NULL;
98 
99 	BT_DBG("hu %p", hu);
100 
101 	skb_queue_purge(&h4->txq);
102 	if (h4->rx_skb)
103 		kfree_skb(h4->rx_skb);
104 
105 	hu->priv = NULL;
106 	kfree(h4);
107 	return 0;
108 }
109 
110 /* Enqueue frame for transmittion (padding, crc, etc) */
h4_enqueue(struct hci_uart * hu,struct sk_buff * skb)111 static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
112 {
113 	struct h4_struct *h4 = hu->priv;
114 
115 	BT_DBG("hu %p skb %p", hu, skb);
116 
117 	/* Prepend skb with frame type */
118 	memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
119 	skb_queue_tail(&h4->txq, skb);
120 	return 0;
121 }
122 
h4_check_data_len(struct h4_struct * h4,int len)123 static inline int h4_check_data_len(struct h4_struct *h4, int len)
124 {
125 	register int room = skb_tailroom(h4->rx_skb);
126 
127 	BT_DBG("len %d room %d", len, room);
128 	if (!len) {
129 		BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
130 		hci_recv_frame(h4->rx_skb);
131 	} else if (len > room) {
132 		BT_ERR("Data length is too large");
133 		kfree_skb(h4->rx_skb);
134 	} else {
135 		h4->rx_state = H4_W4_DATA;
136 		h4->rx_count = len;
137 		return len;
138 	}
139 
140 	h4->rx_state = H4_W4_PACKET_TYPE;
141 	h4->rx_skb   = NULL;
142 	h4->rx_count = 0;
143 	return 0;
144 }
145 
146 /* Recv data */
h4_recv(struct hci_uart * hu,void * data,int count)147 static int h4_recv(struct hci_uart *hu, void *data, int count)
148 {
149 	struct h4_struct *h4 = hu->priv;
150 	register char *ptr;
151 	hci_event_hdr *eh;
152 	hci_acl_hdr   *ah;
153 	hci_sco_hdr   *sh;
154 	register int len, type, dlen;
155 
156 	BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
157 			hu, count, h4->rx_state, h4->rx_count);
158 
159 	ptr = data;
160 	while (count) {
161 		if (h4->rx_count) {
162 			len = MIN(h4->rx_count, count);
163 			memcpy(skb_put(h4->rx_skb, len), ptr, len);
164 			h4->rx_count -= len; count -= len; ptr += len;
165 
166 			if (h4->rx_count)
167 				continue;
168 
169 			switch (h4->rx_state) {
170 			case H4_W4_DATA:
171 				BT_DBG("Complete data");
172 
173 				BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
174 
175 				hci_recv_frame(h4->rx_skb);
176 
177 				h4->rx_state = H4_W4_PACKET_TYPE;
178 				h4->rx_skb = NULL;
179 				continue;
180 
181 			case H4_W4_EVENT_HDR:
182 				eh = (hci_event_hdr *) h4->rx_skb->data;
183 
184 				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
185 
186 				h4_check_data_len(h4, eh->plen);
187 				continue;
188 
189 			case H4_W4_ACL_HDR:
190 				ah = (hci_acl_hdr *) h4->rx_skb->data;
191 				dlen = __le16_to_cpu(ah->dlen);
192 
193 				BT_DBG("ACL header: dlen %d", dlen);
194 
195 				h4_check_data_len(h4, dlen);
196 				continue;
197 
198 			case H4_W4_SCO_HDR:
199 				sh = (hci_sco_hdr *) h4->rx_skb->data;
200 
201 				BT_DBG("SCO header: dlen %d", sh->dlen);
202 
203 				h4_check_data_len(h4, sh->dlen);
204 				continue;
205 			}
206 		}
207 
208 		/* H4_W4_PACKET_TYPE */
209 		switch (*ptr) {
210 		case HCI_EVENT_PKT:
211 			BT_DBG("Event packet");
212 			h4->rx_state = H4_W4_EVENT_HDR;
213 			h4->rx_count = HCI_EVENT_HDR_SIZE;
214 			type = HCI_EVENT_PKT;
215 			break;
216 
217 		case HCI_ACLDATA_PKT:
218 			BT_DBG("ACL packet");
219 			h4->rx_state = H4_W4_ACL_HDR;
220 			h4->rx_count = HCI_ACL_HDR_SIZE;
221 			type = HCI_ACLDATA_PKT;
222 			break;
223 
224 		case HCI_SCODATA_PKT:
225 			BT_DBG("SCO packet");
226 			h4->rx_state = H4_W4_SCO_HDR;
227 			h4->rx_count = HCI_SCO_HDR_SIZE;
228 			type = HCI_SCODATA_PKT;
229 			break;
230 
231 		default:
232 			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
233 			hu->hdev.stat.err_rx++;
234 			ptr++; count--;
235 			continue;
236 		};
237 		ptr++; count--;
238 
239 		/* Allocate packet */
240 		h4->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
241 		if (!h4->rx_skb) {
242 			BT_ERR("Can't allocate mem for new packet");
243 			h4->rx_state = H4_W4_PACKET_TYPE;
244 			h4->rx_count = 0;
245 			return 0;
246 		}
247 		h4->rx_skb->dev = (void *) &hu->hdev;
248 		h4->rx_skb->pkt_type = type;
249 	}
250 	return count;
251 }
252 
h4_dequeue(struct hci_uart * hu)253 static struct sk_buff *h4_dequeue(struct hci_uart *hu)
254 {
255 	struct h4_struct *h4 = hu->priv;
256 	return skb_dequeue(&h4->txq);
257 }
258 
259 static struct hci_uart_proto h4p = {
260 	id:      HCI_UART_H4,
261 	open:    h4_open,
262 	close:   h4_close,
263 	recv:    h4_recv,
264 	enqueue: h4_enqueue,
265 	dequeue: h4_dequeue,
266 	flush:   h4_flush,
267 };
268 
h4_init(void)269 int h4_init(void)
270 {
271 	return hci_uart_register_proto(&h4p);
272 }
273 
h4_deinit(void)274 int h4_deinit(void)
275 {
276 	return hci_uart_unregister_proto(&h4p);
277 }
278