ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / bluetooth / hci_vhci.c
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 /*
26  * Bluetooth HCI virtual device driver.
27  *
28  * $Id: hci_vhci.c,v 1.3 2002/04/17 17:37:20 maxk Exp $ 
29  */
30 #define VERSION "1.1"
31
32 #include <linux/config.h>
33 #include <linux/module.h>
34
35 #include <linux/errno.h>
36 #include <linux/kernel.h>
37 #include <linux/major.h>
38 #include <linux/sched.h>
39 #include <linux/slab.h>
40 #include <linux/poll.h>
41 #include <linux/fcntl.h>
42 #include <linux/init.h>
43 #include <linux/random.h>
44
45 #include <linux/skbuff.h>
46 #include <linux/miscdevice.h>
47
48 #include <asm/system.h>
49 #include <asm/uaccess.h>
50
51 #include <net/bluetooth/bluetooth.h>
52 #include <net/bluetooth/hci_core.h>
53 #include "hci_vhci.h"
54
55 /* HCI device part */
56
57 static int hci_vhci_open(struct hci_dev *hdev)
58 {
59         set_bit(HCI_RUNNING, &hdev->flags);
60         return 0;
61 }
62
63 static int hci_vhci_flush(struct hci_dev *hdev)
64 {
65         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
66         skb_queue_purge(&hci_vhci->readq);
67         return 0;
68 }
69
70 static int hci_vhci_close(struct hci_dev *hdev)
71 {
72         if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
73                 return 0;
74
75         hci_vhci_flush(hdev);
76         return 0;
77 }
78
79 static void hci_vhci_destruct(struct hci_dev *hdev)
80 {
81         struct hci_vhci_struct *vhci;
82
83         if (!hdev) return;
84
85         vhci = (struct hci_vhci_struct *) hdev->driver_data;
86         kfree(vhci);
87 }
88
89 static int hci_vhci_send_frame(struct sk_buff *skb)
90 {
91         struct hci_dev* hdev = (struct hci_dev *) skb->dev;
92         struct hci_vhci_struct *hci_vhci;
93
94         if (!hdev) {
95                 BT_ERR("Frame for uknown device (hdev=NULL)");
96                 return -ENODEV;
97         }
98
99         if (!test_bit(HCI_RUNNING, &hdev->flags))
100                 return -EBUSY;
101
102         hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
103
104         memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
105         skb_queue_tail(&hci_vhci->readq, skb);
106
107         if (hci_vhci->flags & VHCI_FASYNC)
108                 kill_fasync(&hci_vhci->fasync, SIGIO, POLL_IN);
109         wake_up_interruptible(&hci_vhci->read_wait);
110
111         return 0;
112 }
113
114 /* Character device part */
115
116 /* Poll */
117 static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait)
118 {  
119         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
120
121         poll_wait(file, &hci_vhci->read_wait, wait);
122  
123         if (skb_queue_len(&hci_vhci->readq))
124                 return POLLIN | POLLRDNORM;
125
126         return POLLOUT | POLLWRNORM;
127 }
128
129 /* Get packet from user space buffer(already verified) */
130 static inline ssize_t hci_vhci_get_user(struct hci_vhci_struct *hci_vhci, const char *buf, size_t count)
131 {
132         struct sk_buff *skb;
133
134         if (count > HCI_MAX_FRAME_SIZE)
135                 return -EINVAL;
136
137         if (!(skb = bt_skb_alloc(count, GFP_KERNEL)))
138                 return -ENOMEM;
139         
140         if (copy_from_user(skb_put(skb, count), buf, count)) {
141                 kfree_skb(skb);
142                 return -EFAULT;
143         }
144
145         skb->dev = (void *) hci_vhci->hdev;
146         skb->pkt_type = *((__u8 *) skb->data);
147         skb_pull(skb, 1);
148
149         hci_recv_frame(skb);
150
151         return count;
152
153
154 /* Write */
155 static ssize_t hci_vhci_chr_write(struct file * file, const char * buf, 
156                              size_t count, loff_t *pos)
157 {
158         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
159
160         if (verify_area(VERIFY_READ, buf, count))
161                 return -EFAULT;
162
163         return hci_vhci_get_user(hci_vhci, buf, count);
164 }
165
166 /* Put packet to user space buffer(already verified) */
167 static inline ssize_t hci_vhci_put_user(struct hci_vhci_struct *hci_vhci,
168                                        struct sk_buff *skb, char *buf, int count)
169 {
170         int len = count, total = 0;
171         char *ptr = buf;
172
173         len = min_t(unsigned int, skb->len, len);
174         if (copy_to_user(ptr, skb->data, len))
175                 return -EFAULT;
176         total += len;
177
178         hci_vhci->hdev->stat.byte_tx += len;
179         switch (skb->pkt_type) {
180                 case HCI_COMMAND_PKT:
181                         hci_vhci->hdev->stat.cmd_tx++;
182                         break;
183
184                 case HCI_ACLDATA_PKT:
185                         hci_vhci->hdev->stat.acl_tx++;
186                         break;
187
188                 case HCI_SCODATA_PKT:
189                         hci_vhci->hdev->stat.cmd_tx++;
190                         break;
191         };
192
193         return total;
194 }
195
196 /* Read */
197 static ssize_t hci_vhci_chr_read(struct file * file, char * buf, size_t count, loff_t *pos)
198 {
199         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
200         DECLARE_WAITQUEUE(wait, current);
201         struct sk_buff *skb;
202         ssize_t ret = 0;
203
204         add_wait_queue(&hci_vhci->read_wait, &wait);
205         while (count) {
206                 set_current_state(TASK_INTERRUPTIBLE);
207
208                 /* Read frames from device queue */
209                 if (!(skb = skb_dequeue(&hci_vhci->readq))) {
210                         if (file->f_flags & O_NONBLOCK) {
211                                 ret = -EAGAIN;
212                                 break;
213                         }
214                         if (signal_pending(current)) {
215                                 ret = -ERESTARTSYS;
216                                 break;
217                         }
218
219                         /* Nothing to read, let's sleep */
220                         schedule();
221                         continue;
222                 }
223
224                 if (!verify_area(VERIFY_WRITE, buf, count))
225                         ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
226                 else
227                         ret = -EFAULT;
228
229                 kfree_skb(skb);
230                 break;
231         }
232         set_current_state(TASK_RUNNING);
233         remove_wait_queue(&hci_vhci->read_wait, &wait);
234
235         return ret;
236 }
237
238 static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
239 {
240         return -ESPIPE;
241 }
242
243 static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
244 {
245         return -EINVAL;
246 }
247
248 static int hci_vhci_chr_fasync(int fd, struct file *file, int on)
249 {
250         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
251         int ret;
252
253         if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
254                 return ret; 
255  
256         if (on)
257                 hci_vhci->flags |= VHCI_FASYNC;
258         else 
259                 hci_vhci->flags &= ~VHCI_FASYNC;
260
261         return 0;
262 }
263
264 static int hci_vhci_chr_open(struct inode *inode, struct file * file)
265 {
266         struct hci_vhci_struct *hci_vhci = NULL; 
267         struct hci_dev *hdev;
268
269         if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL)))
270                 return -ENOMEM;
271
272         memset(hci_vhci, 0, sizeof(struct hci_vhci_struct));
273
274         skb_queue_head_init(&hci_vhci->readq);
275         init_waitqueue_head(&hci_vhci->read_wait);
276
277         /* Initialize and register HCI device */
278         hdev = hci_alloc_dev();
279         if (!hdev) {
280                 kfree(hci_vhci);
281                 return -ENOMEM;
282         }
283
284         hci_vhci->hdev = hdev;
285
286         hdev->type = HCI_VHCI;
287         hdev->driver_data = hci_vhci;
288
289         hdev->open  = hci_vhci_open;
290         hdev->close = hci_vhci_close;
291         hdev->flush = hci_vhci_flush;
292         hdev->send  = hci_vhci_send_frame;
293         hdev->destruct = hci_vhci_destruct;
294
295         hdev->owner = THIS_MODULE;
296         
297         if (hci_register_dev(hdev) < 0) {
298                 kfree(hci_vhci);
299                 hci_free_dev(hdev);
300                 return -EBUSY;
301         }
302
303         file->private_data = hci_vhci;
304         return 0;   
305 }
306
307 static int hci_vhci_chr_close(struct inode *inode, struct file *file)
308 {
309         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
310
311         if (hci_unregister_dev(hci_vhci->hdev) < 0) {
312                 BT_ERR("Can't unregister HCI device %s", hci_vhci->hdev->name);
313         }
314
315         hci_free_dev(hci_vhci->hdev);
316
317         file->private_data = NULL;
318         return 0;
319 }
320
321 static struct file_operations hci_vhci_fops = {
322         .owner  = THIS_MODULE,  
323         .llseek = hci_vhci_chr_lseek,
324         .read   = hci_vhci_chr_read,
325         .write  = hci_vhci_chr_write,
326         .poll   = hci_vhci_chr_poll,
327         .ioctl  = hci_vhci_chr_ioctl,
328         .open   = hci_vhci_chr_open,
329         .release        = hci_vhci_chr_close,
330         .fasync = hci_vhci_chr_fasync           
331 };
332
333 static struct miscdevice hci_vhci_miscdev=
334 {
335         VHCI_MINOR,
336         "hci_vhci",
337         &hci_vhci_fops
338 };
339
340 int __init hci_vhci_init(void)
341 {
342         BT_INFO("VHCI driver ver %s", VERSION);
343
344         if (misc_register(&hci_vhci_miscdev)) {
345                 BT_ERR("Can't register misc device %d\n", VHCI_MINOR);
346                 return -EIO;
347         }
348
349         return 0;
350 }
351
352 void hci_vhci_cleanup(void)
353 {
354         misc_deregister(&hci_vhci_miscdev);
355 }
356
357 module_init(hci_vhci_init);
358 module_exit(hci_vhci_cleanup);
359
360 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
361 MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION);
362 MODULE_LICENSE("GPL");