OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [bluetooth/] [hci_h4.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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.1.1.1 2004-04-15 02:29:47 phoenix 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 */
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 */
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 */
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) */
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
 
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 */
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
 
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
 
269
int h4_init(void)
270
{
271
        return hci_uart_register_proto(&h4p);
272
}
273
 
274
int h4_deinit(void)
275
{
276
        return hci_uart_unregister_proto(&h4p);
277
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.