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_len(&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 *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 * buf,
156 size_t count, loff_t *pos)
158 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
160 if (verify_area(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 *buf, int count)
170 int len = count, total = 0;
173 len = min_t(unsigned int, skb->len, len);
174 if (copy_to_user(ptr, skb->data, len))
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++;
184 case HCI_ACLDATA_PKT:
185 hci_vhci->hdev->stat.acl_tx++;
188 case HCI_SCODATA_PKT:
189 hci_vhci->hdev->stat.cmd_tx++;
197 static ssize_t hci_vhci_chr_read(struct file * file, char * buf, size_t count, loff_t *pos)
199 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
200 DECLARE_WAITQUEUE(wait, current);
204 add_wait_queue(&hci_vhci->read_wait, &wait);
206 set_current_state(TASK_INTERRUPTIBLE);
208 /* Read frames from device queue */
209 if (!(skb = skb_dequeue(&hci_vhci->readq))) {
210 if (file->f_flags & O_NONBLOCK) {
214 if (signal_pending(current)) {
219 /* Nothing to read, let's sleep */
224 if (!verify_area(VERIFY_WRITE, buf, count))
225 ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
232 set_current_state(TASK_RUNNING);
233 remove_wait_queue(&hci_vhci->read_wait, &wait);
238 static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
243 static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
248 static int hci_vhci_chr_fasync(int fd, struct file *file, int on)
250 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
253 if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
257 hci_vhci->flags |= VHCI_FASYNC;
259 hci_vhci->flags &= ~VHCI_FASYNC;
264 static int hci_vhci_chr_open(struct inode *inode, struct file * file)
266 struct hci_vhci_struct *hci_vhci = NULL;
267 struct hci_dev *hdev;
269 if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL)))
272 memset(hci_vhci, 0, sizeof(struct hci_vhci_struct));
274 skb_queue_head_init(&hci_vhci->readq);
275 init_waitqueue_head(&hci_vhci->read_wait);
277 /* Initialize and register HCI device */
278 hdev = hci_alloc_dev();
284 hci_vhci->hdev = hdev;
286 hdev->type = HCI_VHCI;
287 hdev->driver_data = hci_vhci;
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;
295 hdev->owner = THIS_MODULE;
297 if (hci_register_dev(hdev) < 0) {
303 file->private_data = hci_vhci;
307 static int hci_vhci_chr_close(struct inode *inode, struct file *file)
309 struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
311 if (hci_unregister_dev(hci_vhci->hdev) < 0) {
312 BT_ERR("Can't unregister HCI device %s", hci_vhci->hdev->name);
315 hci_free_dev(hci_vhci->hdev);
317 file->private_data = NULL;
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
333 static struct miscdevice hci_vhci_miscdev=
340 int __init hci_vhci_init(void)
342 BT_INFO("VHCI driver ver %s", VERSION);
344 if (misc_register(&hci_vhci_miscdev)) {
345 BT_ERR("Can't register misc device %d\n", VHCI_MINOR);
352 void hci_vhci_cleanup(void)
354 misc_deregister(&hci_vhci_miscdev);
357 module_init(hci_vhci_init);
358 module_exit(hci_vhci_cleanup);
360 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
361 MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION);
362 MODULE_LICENSE("GPL");