xref: /linux/drivers/bluetooth/hci_vhci.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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");
365