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