diff options
| author | Roland Dreier <rolandd@cisco.com> | 2005-10-28 18:50:51 -0400 |
|---|---|---|
| committer | Roland Dreier <rolandd@cisco.com> | 2005-10-28 18:50:51 -0400 |
| commit | a4da0628efd788eb199dd9df225e296035ec2539 (patch) | |
| tree | 1e611030c993e1480dc2f07f26976d2d33002b0d /drivers/bluetooth/hci_h4.c | |
| parent | 70a30e16a8a9d22396a4d1e96af86e43594df584 (diff) | |
| parent | 20731945ae743034353a88c307920d1f16cf8ac8 (diff) | |
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
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 | ||
