2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
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;
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.
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.
26 * Bluetooth HCI virtual device driver.
28 * $Id: hci_vhci.c,v 1.3 2002/04/17 17:37:20 maxk Exp $
32 #include <linux/config.h>
33 #include <linux/module.h>
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>
45 #include <linux/skbuff.h>
46 #include <linux/miscdevice.h>
48 #include <asm/system.h>
49 #include <asm/uaccess.h>
51 #include <net/bluetooth/bluetooth.h>
52 #include <net/bluetooth/hci_core.h>
57 static int hci_vhci_open(struct hci_dev *hdev)
59 set_bit(HCI_RUNNING, &hdev->flags);
63 static int hci_vhci_flush(struct hci_dev *hdev)
65 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
66 skb_queue_purge(&hci_vhci->readq);
70 static int hci_vhci_close(struct hci_dev *hdev)
72 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
79 static void hci_vhci_destruct(struct hci_dev *hdev)
81 struct hci_vhci_struct *vhci;
85 vhci = (struct hci_vhci_struct *) hdev->driver_data;
89 static int hci_vhci_send_frame(struct sk_buff *skb)
91 struct hci_dev* hdev = (struct hci_dev *) skb->dev;
92 struct hci_vhci_struct *hci_vhci;
95 BT_ERR("Frame for uknown device (hdev=NULL)");
99 if (!test_bit(HCI_RUNNING, &hdev->flags))
102 hci_vhci = (struct hci_vhci_struct *) hdev->driver_data;
104 memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
105 skb_queue_tail(&hci_vhci->readq, skb);
107 if (hci_vhci->flags & VHCI_FASYNC)
108 kill_fasync(&hci_vhci->fasync, SIGIO, POLL_IN);
109 wake_up_interruptible(&hci_vhci->read_wait);
114 /* Character device part */
117 static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait)
119 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
121 poll_wait(file, &hci_vhci->read_wait, wait);
123 if (!skb_queue_empty(&hci_vhci->readq))
124 return POLLIN | POLLRDNORM;
126 return POLLOUT | POLLWRNORM;
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)
134 if (count > HCI_MAX_FRAME_SIZE)
137 if (!(skb = bt_skb_alloc(count, GFP_KERNEL)))
140 if (copy_from_user(skb_put(skb, count), buf, count)) {
145 skb->dev = (void *) hci_vhci->hdev;
146 skb->pkt_type = *((__u8 *) skb->data);
155 static ssize_t hci_vhci_chr_write(struct file * file, const char __user * buf,
156 size_t count, loff_t *pos)
158 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
160 if (!access_ok(VERIFY_READ, buf, count))
163 return hci_vhci_get_user(hci_vhci, buf, count);
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,
171 int len = count, total = 0;
172 char __user *ptr = buf;
174 len = min_t(unsigned int, skb->len, len);
175 if (copy_to_user(ptr, skb->data, len))
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++;
185 case HCI_ACLDATA_PKT:
186 hci_vhci->hdev->stat.acl_tx++;
189 case HCI_SCODATA_PKT:
190 hci_vhci->hdev->stat.cmd_tx++;
198 static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
200 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
201 DECLARE_WAITQUEUE(wait, current);
205 add_wait_queue(&hci_vhci->read_wait, &wait);
207 set_current_state(TASK_INTERRUPTIBLE);
209 /* Read frames from device queue */
210 if (!(skb = skb_dequeue(&hci_vhci->readq))) {
211 if (file->f_flags & O_NONBLOCK) {
215 if (signal_pending(current)) {
220 /* Nothing to read, let's sleep */
225 if (access_ok(VERIFY_WRITE, buf, count))
226 ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
233 set_current_state(TASK_RUNNING);
234 remove_wait_queue(&hci_vhci->read_wait, &wait);
239 static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
244 static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
249 static int hci_vhci_chr_fasync(int fd, struct file *file, int on)
251 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
254 if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
258 hci_vhci->flags |= VHCI_FASYNC;
260 hci_vhci->flags &= ~VHCI_FASYNC;
265 static int hci_vhci_chr_open(struct inode *inode, struct file * file)
267 struct hci_vhci_struct *hci_vhci = NULL;
268 struct hci_dev *hdev;
270 if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL)))
273 memset(hci_vhci, 0, sizeof(struct hci_vhci_struct));
275 skb_queue_head_init(&hci_vhci->readq);
276 init_waitqueue_head(&hci_vhci->read_wait);
278 /* Initialize and register HCI device */
279 hdev = hci_alloc_dev();
285 hci_vhci->hdev = hdev;
287 hdev->type = HCI_VHCI;
288 hdev->driver_data = hci_vhci;
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;
296 hdev->owner = THIS_MODULE;
298 if (hci_register_dev(hdev) < 0) {
304 file->private_data = hci_vhci;
305 return nonseekable_open(inode, file);
308 static int hci_vhci_chr_close(struct inode *inode, struct file *file)
310 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
311 struct hci_dev *hdev = hci_vhci->hdev;
313 if (hci_unregister_dev(hdev) < 0) {
314 BT_ERR("Can't unregister HCI device %s", hdev->name);
319 file->private_data = NULL;
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
335 static struct miscdevice hci_vhci_miscdev=
342 static int __init hci_vhci_init(void)
344 BT_INFO("VHCI driver ver %s", VERSION);
346 if (misc_register(&hci_vhci_miscdev)) {
347 BT_ERR("Can't register misc device %d\n", VHCI_MINOR);
354 static void hci_vhci_cleanup(void)
356 misc_deregister(&hci_vhci_miscdev);
359 module_init(hci_vhci_init);
360 module_exit(hci_vhci_cleanup);
362 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
363 MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION);
364 MODULE_LICENSE("GPL");