diff options
Diffstat (limited to 'drivers/bluetooth/hci_h4.c')
-rw-r--r-- | drivers/bluetooth/hci_h4.c | 101 |
1 files changed, 62 insertions, 39 deletions
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index cf8a22d58d96..12e369a66fc2 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c | |||
@@ -1,33 +1,27 @@ | |||
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 | /* | 1 | /* |
26 | * Bluetooth HCI UART(H4) protocol. | ||
27 | * | 2 | * |
28 | * $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $ | 3 | * Bluetooth HCI UART driver |
4 | * | ||
5 | * Copyright (C) 2000-2001 Qualcomm Incorporated | ||
6 | * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> | ||
7 | * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> | ||
8 | * | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
29 | */ | 24 | */ |
30 | #define VERSION "1.2" | ||
31 | 25 | ||
32 | #include <linux/config.h> | 26 | #include <linux/config.h> |
33 | #include <linux/module.h> | 27 | #include <linux/module.h> |
@@ -51,24 +45,41 @@ | |||
51 | 45 | ||
52 | #include <net/bluetooth/bluetooth.h> | 46 | #include <net/bluetooth/bluetooth.h> |
53 | #include <net/bluetooth/hci_core.h> | 47 | #include <net/bluetooth/hci_core.h> |
48 | |||
54 | #include "hci_uart.h" | 49 | #include "hci_uart.h" |
55 | #include "hci_h4.h" | ||
56 | 50 | ||
57 | #ifndef CONFIG_BT_HCIUART_DEBUG | 51 | #ifndef CONFIG_BT_HCIUART_DEBUG |
58 | #undef BT_DBG | 52 | #undef BT_DBG |
59 | #define BT_DBG( A... ) | 53 | #define BT_DBG( A... ) |
60 | #endif | 54 | #endif |
61 | 55 | ||
56 | #define VERSION "1.2" | ||
57 | |||
58 | struct h4_struct { | ||
59 | unsigned long rx_state; | ||
60 | unsigned long rx_count; | ||
61 | struct sk_buff *rx_skb; | ||
62 | struct sk_buff_head txq; | ||
63 | }; | ||
64 | |||
65 | /* H4 receiver States */ | ||
66 | #define H4_W4_PACKET_TYPE 0 | ||
67 | #define H4_W4_EVENT_HDR 1 | ||
68 | #define H4_W4_ACL_HDR 2 | ||
69 | #define H4_W4_SCO_HDR 3 | ||
70 | #define H4_W4_DATA 4 | ||
71 | |||
62 | /* Initialize protocol */ | 72 | /* Initialize protocol */ |
63 | static int h4_open(struct hci_uart *hu) | 73 | static int h4_open(struct hci_uart *hu) |
64 | { | 74 | { |
65 | struct h4_struct *h4; | 75 | struct h4_struct *h4; |
66 | 76 | ||
67 | BT_DBG("hu %p", hu); | 77 | BT_DBG("hu %p", hu); |
68 | 78 | ||
69 | h4 = kmalloc(sizeof(*h4), GFP_ATOMIC); | 79 | h4 = kmalloc(sizeof(*h4), GFP_ATOMIC); |
70 | if (!h4) | 80 | if (!h4) |
71 | return -ENOMEM; | 81 | return -ENOMEM; |
82 | |||
72 | memset(h4, 0, sizeof(*h4)); | 83 | memset(h4, 0, sizeof(*h4)); |
73 | 84 | ||
74 | skb_queue_head_init(&h4->txq); | 85 | skb_queue_head_init(&h4->txq); |
@@ -83,7 +94,9 @@ static int h4_flush(struct hci_uart *hu) | |||
83 | struct h4_struct *h4 = hu->priv; | 94 | struct h4_struct *h4 = hu->priv; |
84 | 95 | ||
85 | BT_DBG("hu %p", hu); | 96 | BT_DBG("hu %p", hu); |
97 | |||
86 | skb_queue_purge(&h4->txq); | 98 | skb_queue_purge(&h4->txq); |
99 | |||
87 | return 0; | 100 | return 0; |
88 | } | 101 | } |
89 | 102 | ||
@@ -91,16 +104,19 @@ static int h4_flush(struct hci_uart *hu) | |||
91 | static int h4_close(struct hci_uart *hu) | 104 | static int h4_close(struct hci_uart *hu) |
92 | { | 105 | { |
93 | struct h4_struct *h4 = hu->priv; | 106 | struct h4_struct *h4 = hu->priv; |
107 | |||
94 | hu->priv = NULL; | 108 | hu->priv = NULL; |
95 | 109 | ||
96 | BT_DBG("hu %p", hu); | 110 | BT_DBG("hu %p", hu); |
97 | 111 | ||
98 | skb_queue_purge(&h4->txq); | 112 | skb_queue_purge(&h4->txq); |
113 | |||
99 | if (h4->rx_skb) | 114 | if (h4->rx_skb) |
100 | kfree_skb(h4->rx_skb); | 115 | kfree_skb(h4->rx_skb); |
101 | 116 | ||
102 | hu->priv = NULL; | 117 | hu->priv = NULL; |
103 | kfree(h4); | 118 | kfree(h4); |
119 | |||
104 | return 0; | 120 | return 0; |
105 | } | 121 | } |
106 | 122 | ||
@@ -114,6 +130,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb) | |||
114 | /* Prepend skb with frame type */ | 130 | /* Prepend skb with frame type */ |
115 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); | 131 | memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); |
116 | skb_queue_tail(&h4->txq, skb); | 132 | skb_queue_tail(&h4->txq, skb); |
133 | |||
117 | return 0; | 134 | return 0; |
118 | } | 135 | } |
119 | 136 | ||
@@ -122,6 +139,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) | |||
122 | register int room = skb_tailroom(h4->rx_skb); | 139 | register int room = skb_tailroom(h4->rx_skb); |
123 | 140 | ||
124 | BT_DBG("len %d room %d", len, room); | 141 | BT_DBG("len %d room %d", len, room); |
142 | |||
125 | if (!len) { | 143 | if (!len) { |
126 | hci_recv_frame(h4->rx_skb); | 144 | hci_recv_frame(h4->rx_skb); |
127 | } else if (len > room) { | 145 | } else if (len > room) { |
@@ -136,6 +154,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) | |||
136 | h4->rx_state = H4_W4_PACKET_TYPE; | 154 | h4->rx_state = H4_W4_PACKET_TYPE; |
137 | h4->rx_skb = NULL; | 155 | h4->rx_skb = NULL; |
138 | h4->rx_count = 0; | 156 | h4->rx_count = 0; |
157 | |||
139 | return 0; | 158 | return 0; |
140 | } | 159 | } |
141 | 160 | ||
@@ -228,6 +247,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) | |||
228 | ptr++; count--; | 247 | ptr++; count--; |
229 | continue; | 248 | continue; |
230 | }; | 249 | }; |
250 | |||
231 | ptr++; count--; | 251 | ptr++; count--; |
232 | 252 | ||
233 | /* Allocate packet */ | 253 | /* Allocate packet */ |
@@ -238,9 +258,11 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) | |||
238 | h4->rx_count = 0; | 258 | h4->rx_count = 0; |
239 | return 0; | 259 | return 0; |
240 | } | 260 | } |
261 | |||
241 | h4->rx_skb->dev = (void *) hu->hdev; | 262 | h4->rx_skb->dev = (void *) hu->hdev; |
242 | bt_cb(h4->rx_skb)->pkt_type = type; | 263 | bt_cb(h4->rx_skb)->pkt_type = type; |
243 | } | 264 | } |
265 | |||
244 | return count; | 266 | return count; |
245 | } | 267 | } |
246 | 268 | ||
@@ -251,23 +273,24 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu) | |||
251 | } | 273 | } |
252 | 274 | ||
253 | static struct hci_uart_proto h4p = { | 275 | static struct hci_uart_proto h4p = { |
254 | .id = HCI_UART_H4, | 276 | .id = HCI_UART_H4, |
255 | .open = h4_open, | 277 | .open = h4_open, |
256 | .close = h4_close, | 278 | .close = h4_close, |
257 | .recv = h4_recv, | 279 | .recv = h4_recv, |
258 | .enqueue = h4_enqueue, | 280 | .enqueue = h4_enqueue, |
259 | .dequeue = h4_dequeue, | 281 | .dequeue = h4_dequeue, |
260 | .flush = h4_flush, | 282 | .flush = h4_flush, |
261 | }; | 283 | }; |
262 | 284 | ||
263 | int h4_init(void) | 285 | int h4_init(void) |
264 | { | 286 | { |
265 | int err = hci_uart_register_proto(&h4p); | 287 | int err = hci_uart_register_proto(&h4p); |
288 | |||
266 | if (!err) | 289 | if (!err) |
267 | BT_INFO("HCI H4 protocol initialized"); | 290 | BT_INFO("HCI H4 protocol initialized"); |
268 | else | 291 | else |
269 | BT_ERR("HCI H4 protocol registration failed"); | 292 | BT_ERR("HCI H4 protocol registration failed"); |
270 | 293 | ||
271 | return err; | 294 | return err; |
272 | } | 295 | } |
273 | 296 | ||