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/] [hidp/] [sock.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
   HIDP implementation for Linux Bluetooth stack (BlueZ).
3
   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
4
 
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License version 2 as
7
   published by the Free Software Foundation;
8
 
9
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 
18
   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20
   SOFTWARE IS DISCLAIMED.
21
*/
22
 
23
#include <linux/module.h>
24
 
25
#include <linux/types.h>
26
#include <linux/capability.h>
27
#include <linux/errno.h>
28
#include <linux/kernel.h>
29
#include <linux/slab.h>
30
#include <linux/poll.h>
31
#include <linux/fcntl.h>
32
#include <linux/skbuff.h>
33
#include <linux/socket.h>
34
#include <linux/ioctl.h>
35
#include <linux/file.h>
36
#include <linux/init.h>
37
#include <linux/compat.h>
38
#include <net/sock.h>
39
 
40
#include "hidp.h"
41
 
42
#ifndef CONFIG_BT_HIDP_DEBUG
43
#undef  BT_DBG
44
#define BT_DBG(D...)
45
#endif
46
 
47
static int hidp_sock_release(struct socket *sock)
48
{
49
        struct sock *sk = sock->sk;
50
 
51
        BT_DBG("sock %p sk %p", sock, sk);
52
 
53
        if (!sk)
54
                return 0;
55
 
56
        sock_orphan(sk);
57
        sock_put(sk);
58
 
59
        return 0;
60
}
61
 
62
static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
63
{
64
        void __user *argp = (void __user *) arg;
65
        struct hidp_connadd_req ca;
66
        struct hidp_conndel_req cd;
67
        struct hidp_connlist_req cl;
68
        struct hidp_conninfo ci;
69
        struct socket *csock;
70
        struct socket *isock;
71
        int err;
72
 
73
        BT_DBG("cmd %x arg %lx", cmd, arg);
74
 
75
        switch (cmd) {
76
        case HIDPCONNADD:
77
                if (!capable(CAP_NET_ADMIN))
78
                        return -EACCES;
79
 
80
                if (copy_from_user(&ca, argp, sizeof(ca)))
81
                        return -EFAULT;
82
 
83
                csock = sockfd_lookup(ca.ctrl_sock, &err);
84
                if (!csock)
85
                        return err;
86
 
87
                isock = sockfd_lookup(ca.intr_sock, &err);
88
                if (!isock) {
89
                        fput(csock->file);
90
                        return err;
91
                }
92
 
93
                if (csock->sk->sk_state != BT_CONNECTED || isock->sk->sk_state != BT_CONNECTED) {
94
                        fput(csock->file);
95
                        fput(isock->file);
96
                        return -EBADFD;
97
                }
98
 
99
                err = hidp_add_connection(&ca, csock, isock);
100
                if (!err) {
101
                        if (copy_to_user(argp, &ca, sizeof(ca)))
102
                                err = -EFAULT;
103
                } else {
104
                        fput(csock->file);
105
                        fput(isock->file);
106
                }
107
 
108
                return err;
109
 
110
        case HIDPCONNDEL:
111
                if (!capable(CAP_NET_ADMIN))
112
                        return -EACCES;
113
 
114
                if (copy_from_user(&cd, argp, sizeof(cd)))
115
                        return -EFAULT;
116
 
117
                return hidp_del_connection(&cd);
118
 
119
        case HIDPGETCONNLIST:
120
                if (copy_from_user(&cl, argp, sizeof(cl)))
121
                        return -EFAULT;
122
 
123
                if (cl.cnum <= 0)
124
                        return -EINVAL;
125
 
126
                err = hidp_get_connlist(&cl);
127
                if (!err && copy_to_user(argp, &cl, sizeof(cl)))
128
                        return -EFAULT;
129
 
130
                return err;
131
 
132
        case HIDPGETCONNINFO:
133
                if (copy_from_user(&ci, argp, sizeof(ci)))
134
                        return -EFAULT;
135
 
136
                err = hidp_get_conninfo(&ci);
137
                if (!err && copy_to_user(argp, &ci, sizeof(ci)))
138
                        return -EFAULT;
139
 
140
                return err;
141
        }
142
 
143
        return -EINVAL;
144
}
145
 
146
#ifdef CONFIG_COMPAT
147
struct compat_hidp_connadd_req {
148
        int   ctrl_sock;        // Connected control socket
149
        int   intr_sock;        // Connteted interrupt socket
150
        __u16 parser;
151
        __u16 rd_size;
152
        compat_uptr_t rd_data;
153
        __u8  country;
154
        __u8  subclass;
155
        __u16 vendor;
156
        __u16 product;
157
        __u16 version;
158
        __u32 flags;
159
        __u32 idle_to;
160
        char  name[128];
161
};
162
 
163
static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
164
{
165
        if (cmd == HIDPGETCONNLIST) {
166
                struct hidp_connlist_req cl;
167
                uint32_t uci;
168
                int err;
169
 
170
                if (get_user(cl.cnum, (uint32_t __user *) arg) ||
171
                                get_user(uci, (u32 __user *) (arg + 4)))
172
                        return -EFAULT;
173
 
174
                cl.ci = compat_ptr(uci);
175
 
176
                if (cl.cnum <= 0)
177
                        return -EINVAL;
178
 
179
                err = hidp_get_connlist(&cl);
180
 
181
                if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
182
                        err = -EFAULT;
183
 
184
                return err;
185
        } else if (cmd == HIDPCONNADD) {
186
                struct compat_hidp_connadd_req ca;
187
                struct hidp_connadd_req __user *uca;
188
 
189
                uca = compat_alloc_user_space(sizeof(*uca));
190
 
191
                if (copy_from_user(&ca, (void __user *) arg, sizeof(ca)))
192
                        return -EFAULT;
193
 
194
                if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
195
                                put_user(ca.intr_sock, &uca->intr_sock) ||
196
                                put_user(ca.parser, &uca->parser) ||
197
                                put_user(ca.rd_size, &uca->rd_size) ||
198
                                put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
199
                                put_user(ca.country, &uca->country) ||
200
                                put_user(ca.subclass, &uca->subclass) ||
201
                                put_user(ca.vendor, &uca->vendor) ||
202
                                put_user(ca.product, &uca->product) ||
203
                                put_user(ca.version, &uca->version) ||
204
                                put_user(ca.flags, &uca->flags) ||
205
                                put_user(ca.idle_to, &uca->idle_to) ||
206
                                copy_to_user(&uca->name[0], &ca.name[0], 128))
207
                        return -EFAULT;
208
 
209
                arg = (unsigned long) uca;
210
 
211
                /* Fall through. We don't actually write back any _changes_
212
                   to the structure anyway, so there's no need to copy back
213
                   into the original compat version */
214
        }
215
 
216
        return hidp_sock_ioctl(sock, cmd, arg);
217
}
218
#endif
219
 
220
static const struct proto_ops hidp_sock_ops = {
221
        .family         = PF_BLUETOOTH,
222
        .owner          = THIS_MODULE,
223
        .release        = hidp_sock_release,
224
        .ioctl          = hidp_sock_ioctl,
225
#ifdef CONFIG_COMPAT
226
        .compat_ioctl   = hidp_sock_compat_ioctl,
227
#endif
228
        .bind           = sock_no_bind,
229
        .getname        = sock_no_getname,
230
        .sendmsg        = sock_no_sendmsg,
231
        .recvmsg        = sock_no_recvmsg,
232
        .poll           = sock_no_poll,
233
        .listen         = sock_no_listen,
234
        .shutdown       = sock_no_shutdown,
235
        .setsockopt     = sock_no_setsockopt,
236
        .getsockopt     = sock_no_getsockopt,
237
        .connect        = sock_no_connect,
238
        .socketpair     = sock_no_socketpair,
239
        .accept         = sock_no_accept,
240
        .mmap           = sock_no_mmap
241
};
242
 
243
static struct proto hidp_proto = {
244
        .name           = "HIDP",
245
        .owner          = THIS_MODULE,
246
        .obj_size       = sizeof(struct bt_sock)
247
};
248
 
249
static int hidp_sock_create(struct net *net, struct socket *sock, int protocol)
250
{
251
        struct sock *sk;
252
 
253
        BT_DBG("sock %p", sock);
254
 
255
        if (sock->type != SOCK_RAW)
256
                return -ESOCKTNOSUPPORT;
257
 
258
        sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto);
259
        if (!sk)
260
                return -ENOMEM;
261
 
262
        sock_init_data(sock, sk);
263
 
264
        sock->ops = &hidp_sock_ops;
265
 
266
        sock->state = SS_UNCONNECTED;
267
 
268
        sock_reset_flag(sk, SOCK_ZAPPED);
269
 
270
        sk->sk_protocol = protocol;
271
        sk->sk_state    = BT_OPEN;
272
 
273
        return 0;
274
}
275
 
276
static struct net_proto_family hidp_sock_family_ops = {
277
        .family = PF_BLUETOOTH,
278
        .owner  = THIS_MODULE,
279
        .create = hidp_sock_create
280
};
281
 
282
int __init hidp_init_sockets(void)
283
{
284
        int err;
285
 
286
        err = proto_register(&hidp_proto, 0);
287
        if (err < 0)
288
                return err;
289
 
290
        err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops);
291
        if (err < 0)
292
                goto error;
293
 
294
        return 0;
295
 
296
error:
297
        BT_ERR("Can't register HIDP socket");
298
        proto_unregister(&hidp_proto);
299
        return err;
300
}
301
 
302
void __exit hidp_cleanup_sockets(void)
303
{
304
        if (bt_sock_unregister(BTPROTO_HIDP) < 0)
305
                BT_ERR("Can't unregister HIDP socket");
306
 
307
        proto_unregister(&hidp_proto);
308
}

powered by: WebSVN 2.1.0

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