Linux-2.6.12-rc2
[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 __user *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 __user * 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 (!access_ok(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 __user *buf,
169                                        int count)
170 {
171         int len = count, total = 0;
172         char __user *ptr = buf;
173
174         len = min_t(unsigned int, skb->len, len);
175         if (copy_to_user(ptr, skb->data, len))
176                 return -EFAULT;
177         total += len;
178
179         hci_vhci->hdev->stat.byte_tx += len;
180         switch (skb->pkt_type) {
181                 case HCI_COMMAND_PKT:
182                         hci_vhci->hdev->stat.cmd_tx++;
183                         break;
184
185                 case HCI_ACLDATA_PKT:
186                         hci_vhci->hdev->stat.acl_tx++;
187                         break;
188
189                 case HCI_SCODATA_PKT:
190                         hci_vhci->hdev->stat.cmd_tx++;
191                         break;
192         };
193
194         return total;
195 }
196
197 /* Read */
198 static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
199 {
200         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
201         DECLARE_WAITQUEUE(wait, current);
202         struct sk_buff *skb;
203         ssize_t ret = 0;
204
205         add_wait_queue(&hci_vhci->read_wait, &wait);
206         while (count) {
207                 set_current_state(TASK_INTERRUPTIBLE);
208
209                 /* Read frames from device queue */
210                 if (!(skb = skb_dequeue(&hci_vhci->readq))) {
211                         if (file->f_flags & O_NONBLOCK) {
212                                 ret = -EAGAIN;
213                                 break;
214                         }
215                         if (signal_pending(current)) {
216                                 ret = -ERESTARTSYS;
217                                 break;
218                         }
219
220                         /* Nothing to read, let's sleep */
221                         schedule();
222                         continue;
223                 }
224
225                 if (access_ok(VERIFY_WRITE, buf, count))
226                         ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
227                 else
228                         ret = -EFAULT;
229
230                 kfree_skb(skb);
231                 break;
232         }
233         set_current_state(TASK_RUNNING);
234         remove_wait_queue(&hci_vhci->read_wait, &wait);
235
236         return ret;
237 }
238
239 static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
240 {
241         return -ESPIPE;
242 }
243
244 static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
245 {
246         return -EINVAL;
247 }
248
249 static int hci_vhci_chr_fasync(int fd, struct file *file, int on)
250 {
251         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
252         int ret;
253
254         if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
255                 return ret; 
256  
257         if (on)
258                 hci_vhci->flags |= VHCI_FASYNC;
259         else 
260                 hci_vhci->flags &= ~VHCI_FASYNC;
261
262         return 0;
263 }
264
265 static int hci_vhci_chr_open(struct inode *inode, struct file * file)
266 {
267         struct hci_vhci_struct *hci_vhci = NULL; 
268         struct hci_dev *hdev;
269
270         if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL)))
271                 return -ENOMEM;
272
273         memset(hci_vhci, 0, sizeof(struct hci_vhci_struct));
274
275         skb_queue_head_init(&hci_vhci->readq);
276         init_waitqueue_head(&hci_vhci->read_wait);
277
278         /* Initialize and register HCI device */
279         hdev = hci_alloc_dev();
280         if (!hdev) {
281                 kfree(hci_vhci);
282                 return -ENOMEM;
283         }
284
285         hci_vhci->hdev = hdev;
286
287         hdev->type = HCI_VHCI;
288         hdev->driver_data = hci_vhci;
289
290         hdev->open  = hci_vhci_open;
291         hdev->close = hci_vhci_close;
292         hdev->flush = hci_vhci_flush;
293         hdev->send  = hci_vhci_send_frame;
294         hdev->destruct = hci_vhci_destruct;
295
296         hdev->owner = THIS_MODULE;
297         
298         if (hci_register_dev(hdev) < 0) {
299                 kfree(hci_vhci);
300                 hci_free_dev(hdev);
301                 return -EBUSY;
302         }
303
304         file->private_data = hci_vhci;
305         return nonseekable_open(inode, file);   
306 }
307
308 static int hci_vhci_chr_close(struct inode *inode, struct file *file)
309 {
310         struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
311         struct hci_dev *hdev = hci_vhci->hdev;
312
313         if (hci_unregister_dev(hdev) < 0) {
314                 BT_ERR("Can't unregister HCI device %s", hdev->name);
315         }
316
317         hci_free_dev(hdev);
318
319         file->private_data = NULL;
320         return 0;
321 }
322
323 static struct file_operations hci_vhci_fops = {
324         .owner  = THIS_MODULE,  
325         .llseek = hci_vhci_chr_lseek,
326         .read   = hci_vhci_chr_read,
327         .write  = hci_vhci_chr_write,
328         .poll   = hci_vhci_chr_poll,
329         .ioctl  = hci_vhci_chr_ioctl,
330         .open   = hci_vhci_chr_open,
331         .release        = hci_vhci_chr_close,
332         .fasync = hci_vhci_chr_fasync           
333 };
334
335 static struct miscdevice hci_vhci_miscdev=
336 {
337         VHCI_MINOR,
338         "hci_vhci",
339         &hci_vhci_fops
340 };
341
342 static int __init hci_vhci_init(void)
343 {
344         BT_INFO("VHCI driver ver %s", VERSION);
345
346         if (misc_register(&hci_vhci_miscdev)) {
347                 BT_ERR("Can't register misc device %d\n", VHCI_MINOR);
348                 return -EIO;
349         }
350
351         return 0;
352 }
353
354 static void hci_vhci_cleanup(void)
355 {
356         misc_deregister(&hci_vhci_miscdev);
357 }
358
359 module_init(hci_vhci_init);
360 module_exit(hci_vhci_cleanup);
361
362 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
363 MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION);
364 MODULE_LICENSE("GPL");