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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [net/] [bluetooth/] [bnep/] [netdev.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
   BNEP implementation for Linux Bluetooth stack (BlueZ).
3
   Copyright (C) 2001-2002 Inventel Systemes
4
   Written 2001-2002 by
5
        Clément Moreau <clement.moreau@inventel.fr>
6
        David Libault  <david.libault@inventel.fr>
7
 
8
   Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
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 version 2 as
12
   published by the Free Software Foundation;
13
 
14
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
18
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
 
23
   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
25
   SOFTWARE IS DISCLAIMED.
26
*/
27
 
28
/*
29
 * $Id: netdev.c,v 1.8 2002/08/04 21:23:58 maxk Exp $
30
 */
31
 
32
#include <linux/module.h>
33
 
34
#include <linux/socket.h>
35
#include <linux/netdevice.h>
36
#include <linux/etherdevice.h>
37
#include <linux/skbuff.h>
38
#include <linux/wait.h>
39
 
40
#include <asm/unaligned.h>
41
 
42
#include <net/bluetooth/bluetooth.h>
43
#include <net/bluetooth/hci_core.h>
44
#include <net/bluetooth/l2cap.h>
45
 
46
#include "bnep.h"
47
 
48
#ifndef CONFIG_BT_BNEP_DEBUG
49
#undef  BT_DBG
50
#define BT_DBG( A... )
51
#endif
52
 
53
#define BNEP_TX_QUEUE_LEN 20
54
 
55
static int bnep_net_open(struct net_device *dev)
56
{
57
        netif_start_queue(dev);
58
        return 0;
59
}
60
 
61
static int bnep_net_close(struct net_device *dev)
62
{
63
        netif_stop_queue(dev);
64
        return 0;
65
}
66
 
67
static struct net_device_stats *bnep_net_get_stats(struct net_device *dev)
68
{
69
        struct bnep_session *s = dev->priv;
70
        return &s->stats;
71
}
72
 
73
static void bnep_net_set_mc_list(struct net_device *dev)
74
{
75
#ifdef CONFIG_BT_BNEP_MC_FILTER
76
        struct bnep_session *s = dev->priv;
77
        struct sock *sk = s->sock->sk;
78
        struct bnep_set_filter_req *r;
79
        struct sk_buff *skb;
80
        int size;
81
 
82
        BT_DBG("%s mc_count %d", dev->name, dev->mc_count);
83
 
84
        size = sizeof(*r) + (BNEP_MAX_MULTICAST_FILTERS + 1) * ETH_ALEN * 2;
85
        skb  = alloc_skb(size, GFP_ATOMIC);
86
        if (!skb) {
87
                BT_ERR("%s Multicast list allocation failed", dev->name);
88
                return;
89
        }
90
 
91
        r = (void *) skb->data;
92
        __skb_put(skb, sizeof(*r));
93
 
94
        r->type = BNEP_CONTROL;
95
        r->ctrl = BNEP_FILTER_MULTI_ADDR_SET;
96
 
97
        if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
98
                u8 start[ETH_ALEN] = { 0x01 };
99
 
100
                /* Request all addresses */
101
                memcpy(__skb_put(skb, ETH_ALEN), start, ETH_ALEN);
102
                memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
103
                r->len = htons(ETH_ALEN * 2);
104
        } else {
105
                struct dev_mc_list *dmi = dev->mc_list;
106
                int i, len = skb->len;
107
 
108
                if (dev->flags & IFF_BROADCAST) {
109
                        memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
110
                        memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
111
                }
112
 
113
                /* FIXME: We should group addresses here. */
114
 
115
                for (i = 0; i < dev->mc_count && i < BNEP_MAX_MULTICAST_FILTERS; i++) {
116
                        memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN);
117
                        memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN);
118
                        dmi = dmi->next;
119
                }
120
                r->len = htons(skb->len - len);
121
        }
122
 
123
        skb_queue_tail(&sk->sk_write_queue, skb);
124
        wake_up_interruptible(sk->sk_sleep);
125
#endif
126
}
127
 
128
static int bnep_net_set_mac_addr(struct net_device *dev, void *arg)
129
{
130
        BT_DBG("%s", dev->name);
131
        return 0;
132
}
133
 
134
static void bnep_net_timeout(struct net_device *dev)
135
{
136
        BT_DBG("net_timeout");
137
        netif_wake_queue(dev);
138
}
139
 
140
static int bnep_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
141
{
142
        return -EINVAL;
143
}
144
 
145
#ifdef CONFIG_BT_BNEP_MC_FILTER
146
static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s)
147
{
148
        struct ethhdr *eh = (void *) skb->data;
149
 
150
        if ((eh->h_dest[0] & 1) && !test_bit(bnep_mc_hash(eh->h_dest), (ulong *) &s->mc_filter))
151
                return 1;
152
        return 0;
153
}
154
#endif
155
 
156
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
157
/* Determine ether protocol. Based on eth_type_trans. */
158
static inline u16 bnep_net_eth_proto(struct sk_buff *skb)
159
{
160
        struct ethhdr *eh = (void *) skb->data;
161
        u16 proto = ntohs(eh->h_proto);
162
 
163
        if (proto >= 1536)
164
                return proto;
165
 
166
        if (get_unaligned((__be16 *) skb->data) == htons(0xFFFF))
167
                return ETH_P_802_3;
168
 
169
        return ETH_P_802_2;
170
}
171
 
172
static inline int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s)
173
{
174
        u16 proto = bnep_net_eth_proto(skb);
175
        struct bnep_proto_filter *f = s->proto_filter;
176
        int i;
177
 
178
        for (i = 0; i < BNEP_MAX_PROTO_FILTERS && f[i].end; i++) {
179
                if (proto >= f[i].start && proto <= f[i].end)
180
                        return 0;
181
        }
182
 
183
        BT_DBG("BNEP: filtered skb %p, proto 0x%.4x", skb, proto);
184
        return 1;
185
}
186
#endif
187
 
188
static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
189
{
190
        struct bnep_session *s = dev->priv;
191
        struct sock *sk = s->sock->sk;
192
 
193
        BT_DBG("skb %p, dev %p", skb, dev);
194
 
195
#ifdef CONFIG_BT_BNEP_MC_FILTER
196
        if (bnep_net_mc_filter(skb, s)) {
197
                kfree_skb(skb);
198
                return 0;
199
        }
200
#endif
201
 
202
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
203
        if (bnep_net_proto_filter(skb, s)) {
204
                kfree_skb(skb);
205
                return 0;
206
        }
207
#endif
208
 
209
        /*
210
         * We cannot send L2CAP packets from here as we are potentially in a bh.
211
         * So we have to queue them and wake up session thread which is sleeping
212
         * on the sk->sk_sleep.
213
         */
214
        dev->trans_start = jiffies;
215
        skb_queue_tail(&sk->sk_write_queue, skb);
216
        wake_up_interruptible(sk->sk_sleep);
217
 
218
        if (skb_queue_len(&sk->sk_write_queue) >= BNEP_TX_QUEUE_LEN) {
219
                BT_DBG("tx queue is full");
220
 
221
                /* Stop queuing.
222
                 * Session thread will do netif_wake_queue() */
223
                netif_stop_queue(dev);
224
        }
225
 
226
        return 0;
227
}
228
 
229
void bnep_net_setup(struct net_device *dev)
230
{
231
 
232
        memset(dev->broadcast, 0xff, ETH_ALEN);
233
        dev->addr_len = ETH_ALEN;
234
 
235
        ether_setup(dev);
236
 
237
        dev->open            = bnep_net_open;
238
        dev->stop            = bnep_net_close;
239
        dev->hard_start_xmit = bnep_net_xmit;
240
        dev->get_stats       = bnep_net_get_stats;
241
        dev->do_ioctl        = bnep_net_ioctl;
242
        dev->set_mac_address = bnep_net_set_mac_addr;
243
        dev->set_multicast_list = bnep_net_set_mc_list;
244
 
245
        dev->watchdog_timeo  = HZ * 2;
246
        dev->tx_timeout      = bnep_net_timeout;
247
}

powered by: WebSVN 2.1.0

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