aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-06-11 08:47:43 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-11 08:47:43 -0400
commitbb400801c2f40bbd9a688818323ad09abfc4e581 (patch)
treebf23baef0cdc7590b73a53e6b1e88565ba455cf1 /drivers
parent130aa61a77b8518f1ea618e1b7d214d60b405f10 (diff)
parent611b30f74b5d8ca036a9923b3bf6e0ee10a21a53 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bluetooth/hci_vhci.c90
1 files changed, 19 insertions, 71 deletions
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 0bbefba6469c..1df9dda2e377 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -40,7 +40,7 @@
40#include <net/bluetooth/bluetooth.h> 40#include <net/bluetooth/bluetooth.h>
41#include <net/bluetooth/hci_core.h> 41#include <net/bluetooth/hci_core.h>
42 42
43#define VERSION "1.2" 43#define VERSION "1.3"
44 44
45static int minor = MISC_DYNAMIC_MINOR; 45static int minor = MISC_DYNAMIC_MINOR;
46 46
@@ -51,14 +51,8 @@ struct vhci_data {
51 51
52 wait_queue_head_t read_wait; 52 wait_queue_head_t read_wait;
53 struct sk_buff_head readq; 53 struct sk_buff_head readq;
54
55 struct fasync_struct *fasync;
56}; 54};
57 55
58#define VHCI_FASYNC 0x0010
59
60static struct miscdevice vhci_miscdev;
61
62static int vhci_open_dev(struct hci_dev *hdev) 56static int vhci_open_dev(struct hci_dev *hdev)
63{ 57{
64 set_bit(HCI_RUNNING, &hdev->flags); 58 set_bit(HCI_RUNNING, &hdev->flags);
@@ -105,9 +99,6 @@ static int vhci_send_frame(struct sk_buff *skb)
105 memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); 99 memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
106 skb_queue_tail(&data->readq, skb); 100 skb_queue_tail(&data->readq, skb);
107 101
108 if (data->flags & VHCI_FASYNC)
109 kill_fasync(&data->fasync, SIGIO, POLL_IN);
110
111 wake_up_interruptible(&data->read_wait); 102 wake_up_interruptible(&data->read_wait);
112 103
113 return 0; 104 return 0;
@@ -179,41 +170,31 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
179static ssize_t vhci_read(struct file *file, 170static ssize_t vhci_read(struct file *file,
180 char __user *buf, size_t count, loff_t *pos) 171 char __user *buf, size_t count, loff_t *pos)
181{ 172{
182 DECLARE_WAITQUEUE(wait, current);
183 struct vhci_data *data = file->private_data; 173 struct vhci_data *data = file->private_data;
184 struct sk_buff *skb; 174 struct sk_buff *skb;
185 ssize_t ret = 0; 175 ssize_t ret = 0;
186 176
187 add_wait_queue(&data->read_wait, &wait);
188 while (count) { 177 while (count) {
189 set_current_state(TASK_INTERRUPTIBLE);
190
191 skb = skb_dequeue(&data->readq); 178 skb = skb_dequeue(&data->readq);
192 if (!skb) { 179 if (skb) {
193 if (file->f_flags & O_NONBLOCK) { 180 ret = vhci_put_user(data, skb, buf, count);
194 ret = -EAGAIN; 181 if (ret < 0)
195 break; 182 skb_queue_head(&data->readq, skb);
196 } 183 else
197 184 kfree_skb(skb);
198 if (signal_pending(current)) { 185 break;
199 ret = -ERESTARTSYS;
200 break;
201 }
202
203 schedule();
204 continue;
205 } 186 }
206 187
207 if (access_ok(VERIFY_WRITE, buf, count)) 188 if (file->f_flags & O_NONBLOCK) {
208 ret = vhci_put_user(data, skb, buf, count); 189 ret = -EAGAIN;
209 else 190 break;
210 ret = -EFAULT; 191 }
211 192
212 kfree_skb(skb); 193 ret = wait_event_interruptible(data->read_wait,
213 break; 194 !skb_queue_empty(&data->readq));
195 if (ret < 0)
196 break;
214 } 197 }
215 set_current_state(TASK_RUNNING);
216 remove_wait_queue(&data->read_wait, &wait);
217 198
218 return ret; 199 return ret;
219} 200}
@@ -223,9 +204,6 @@ static ssize_t vhci_write(struct file *file,
223{ 204{
224 struct vhci_data *data = file->private_data; 205 struct vhci_data *data = file->private_data;
225 206
226 if (!access_ok(VERIFY_READ, buf, count))
227 return -EFAULT;
228
229 return vhci_get_user(data, buf, count); 207 return vhci_get_user(data, buf, count);
230} 208}
231 209
@@ -259,11 +237,9 @@ static int vhci_open(struct inode *inode, struct file *file)
259 skb_queue_head_init(&data->readq); 237 skb_queue_head_init(&data->readq);
260 init_waitqueue_head(&data->read_wait); 238 init_waitqueue_head(&data->read_wait);
261 239
262 lock_kernel();
263 hdev = hci_alloc_dev(); 240 hdev = hci_alloc_dev();
264 if (!hdev) { 241 if (!hdev) {
265 kfree(data); 242 kfree(data);
266 unlock_kernel();
267 return -ENOMEM; 243 return -ENOMEM;
268 } 244 }
269 245
@@ -284,12 +260,10 @@ static int vhci_open(struct inode *inode, struct file *file)
284 BT_ERR("Can't register HCI device"); 260 BT_ERR("Can't register HCI device");
285 kfree(data); 261 kfree(data);
286 hci_free_dev(hdev); 262 hci_free_dev(hdev);
287 unlock_kernel();
288 return -EBUSY; 263 return -EBUSY;
289 } 264 }
290 265
291 file->private_data = data; 266 file->private_data = data;
292 unlock_kernel();
293 267
294 return nonseekable_open(inode, file); 268 return nonseekable_open(inode, file);
295} 269}
@@ -310,48 +284,25 @@ static int vhci_release(struct inode *inode, struct file *file)
310 return 0; 284 return 0;
311} 285}
312 286
313static int vhci_fasync(int fd, struct file *file, int on)
314{
315 struct vhci_data *data = file->private_data;
316 int err = 0;
317
318 lock_kernel();
319 err = fasync_helper(fd, file, on, &data->fasync);
320 if (err < 0)
321 goto out;
322
323 if (on)
324 data->flags |= VHCI_FASYNC;
325 else
326 data->flags &= ~VHCI_FASYNC;
327
328out:
329 unlock_kernel();
330 return err;
331}
332
333static const struct file_operations vhci_fops = { 287static const struct file_operations vhci_fops = {
334 .owner = THIS_MODULE,
335 .read = vhci_read, 288 .read = vhci_read,
336 .write = vhci_write, 289 .write = vhci_write,
337 .poll = vhci_poll, 290 .poll = vhci_poll,
338 .ioctl = vhci_ioctl, 291 .ioctl = vhci_ioctl,
339 .open = vhci_open, 292 .open = vhci_open,
340 .release = vhci_release, 293 .release = vhci_release,
341 .fasync = vhci_fasync,
342}; 294};
343 295
344static struct miscdevice vhci_miscdev= { 296static struct miscdevice vhci_miscdev= {
345 .name = "vhci", 297 .name = "vhci",
346 .fops = &vhci_fops, 298 .fops = &vhci_fops,
299 .minor = MISC_DYNAMIC_MINOR,
347}; 300};
348 301
349static int __init vhci_init(void) 302static int __init vhci_init(void)
350{ 303{
351 BT_INFO("Virtual HCI driver ver %s", VERSION); 304 BT_INFO("Virtual HCI driver ver %s", VERSION);
352 305
353 vhci_miscdev.minor = minor;
354
355 if (misc_register(&vhci_miscdev) < 0) { 306 if (misc_register(&vhci_miscdev) < 0) {
356 BT_ERR("Can't register misc device with minor %d", minor); 307 BT_ERR("Can't register misc device with minor %d", minor);
357 return -EIO; 308 return -EIO;
@@ -369,9 +320,6 @@ static void __exit vhci_exit(void)
369module_init(vhci_init); 320module_init(vhci_init);
370module_exit(vhci_exit); 321module_exit(vhci_exit);
371 322
372module_param(minor, int, 0444);
373MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
374
375MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 323MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
376MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); 324MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
377MODULE_VERSION(VERSION); 325MODULE_VERSION(VERSION);