[PATCH] sparse (compat_ioctl): CDROM_SEND_PACKET handling
[linux-2.6/history.git] / drivers / bluetooth / hci_vhci.c
blob871f3832961014330f8fb226bdb74445a3fa69a7
1 /*
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 $
30 #define VERSION "1.1"
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>
53 #include "hci_vhci.h"
55 /* HCI device part */
57 static int hci_vhci_open(struct hci_dev *hdev)
59 set_bit(HCI_RUNNING, &hdev->flags);
60 return 0;
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);
67 return 0;
70 static int hci_vhci_close(struct hci_dev *hdev)
72 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
73 return 0;
75 hci_vhci_flush(hdev);
76 return 0;
79 static void hci_vhci_destruct(struct hci_dev *hdev)
81 struct hci_vhci_struct *vhci;
83 if (!hdev) return;
85 vhci = (struct hci_vhci_struct *) hdev->driver_data;
86 kfree(vhci);
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;
94 if (!hdev) {
95 BT_ERR("Frame for uknown device (hdev=NULL)");
96 return -ENODEV;
99 if (!test_bit(HCI_RUNNING, &hdev->flags))
100 return -EBUSY;
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);
111 return 0;
114 /* Character device part */
116 /* Poll */
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)
132 struct sk_buff *skb;
134 if (count > HCI_MAX_FRAME_SIZE)
135 return -EINVAL;
137 if (!(skb = bt_skb_alloc(count, GFP_KERNEL)))
138 return -ENOMEM;
140 if (copy_from_user(skb_put(skb, count), buf, count)) {
141 kfree_skb(skb);
142 return -EFAULT;
145 skb->dev = (void *) hci_vhci->hdev;
146 skb->pkt_type = *((__u8 *) skb->data);
147 skb_pull(skb, 1);
149 hci_recv_frame(skb);
151 return count;
154 /* Write */
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))
161 return -EFAULT;
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;
171 char *ptr = buf;
173 len = min_t(unsigned int, skb->len, len);
174 if (copy_to_user(ptr, skb->data, len))
175 return -EFAULT;
176 total += 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++;
182 break;
184 case HCI_ACLDATA_PKT:
185 hci_vhci->hdev->stat.acl_tx++;
186 break;
188 case HCI_SCODATA_PKT:
189 hci_vhci->hdev->stat.cmd_tx++;
190 break;
193 return total;
196 /* Read */
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);
201 struct sk_buff *skb;
202 ssize_t ret = 0;
204 add_wait_queue(&hci_vhci->read_wait, &wait);
205 while (count) {
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) {
211 ret = -EAGAIN;
212 break;
214 if (signal_pending(current)) {
215 ret = -ERESTARTSYS;
216 break;
219 /* Nothing to read, let's sleep */
220 schedule();
221 continue;
224 if (!verify_area(VERIFY_WRITE, buf, count))
225 ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
226 else
227 ret = -EFAULT;
229 kfree_skb(skb);
230 break;
232 set_current_state(TASK_RUNNING);
233 remove_wait_queue(&hci_vhci->read_wait, &wait);
235 return ret;
238 static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin)
240 return -ESPIPE;
243 static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
245 return -EINVAL;
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;
251 int ret;
253 if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0)
254 return ret;
256 if (on)
257 hci_vhci->flags |= VHCI_FASYNC;
258 else
259 hci_vhci->flags &= ~VHCI_FASYNC;
261 return 0;
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)))
270 return -ENOMEM;
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();
279 if (!hdev) {
280 kfree(hci_vhci);
281 return -ENOMEM;
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) {
298 kfree(hci_vhci);
299 hci_free_dev(hdev);
300 return -EBUSY;
303 file->private_data = hci_vhci;
304 return 0;
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;
318 return 0;
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=
335 VHCI_MINOR,
336 "hci_vhci",
337 &hci_vhci_fops
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);
346 return -EIO;
349 return 0;
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");