diff options
Diffstat (limited to 'drivers/misc/ibmasm/ibmasmfs.c')
-rw-r--r-- | drivers/misc/ibmasm/ibmasmfs.c | 125 |
1 files changed, 27 insertions, 98 deletions
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 866e867e68f2..5c550fcac2c4 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c | |||
@@ -37,9 +37,7 @@ | |||
37 | * | |-- event | 37 | * | |-- event |
38 | * | |-- reverse_heartbeat | 38 | * | |-- reverse_heartbeat |
39 | * | `-- remote_video | 39 | * | `-- remote_video |
40 | * | |-- connected | ||
41 | * | |-- depth | 40 | * | |-- depth |
42 | * | |-- events | ||
43 | * | |-- height | 41 | * | |-- height |
44 | * | `-- width | 42 | * | `-- width |
45 | * . | 43 | * . |
@@ -50,9 +48,7 @@ | |||
50 | * |-- event | 48 | * |-- event |
51 | * |-- reverse_heartbeat | 49 | * |-- reverse_heartbeat |
52 | * `-- remote_video | 50 | * `-- remote_video |
53 | * |-- connected | ||
54 | * |-- depth | 51 | * |-- depth |
55 | * |-- events | ||
56 | * |-- height | 52 | * |-- height |
57 | * `-- width | 53 | * `-- width |
58 | * | 54 | * |
@@ -75,14 +71,6 @@ | |||
75 | * remote_video/width: control remote display settings | 71 | * remote_video/width: control remote display settings |
76 | * write: set value | 72 | * write: set value |
77 | * read: read value | 73 | * read: read value |
78 | * | ||
79 | * remote_video/connected | ||
80 | * read: return "1" if web browser VNC java applet is connected, | ||
81 | * "0" otherwise | ||
82 | * | ||
83 | * remote_video/events | ||
84 | * read: sleep until a remote mouse or keyboard event occurs, then return | ||
85 | * then event. | ||
86 | */ | 74 | */ |
87 | 75 | ||
88 | #include <linux/fs.h> | 76 | #include <linux/fs.h> |
@@ -333,7 +321,7 @@ static ssize_t command_file_write(struct file *file, const char __user *ubuff, s | |||
333 | if (command_data->command) | 321 | if (command_data->command) |
334 | return -EAGAIN; | 322 | return -EAGAIN; |
335 | 323 | ||
336 | cmd = ibmasm_new_command(count); | 324 | cmd = ibmasm_new_command(command_data->sp, count); |
337 | if (!cmd) | 325 | if (!cmd) |
338 | return -ENOMEM; | 326 | return -ENOMEM; |
339 | 327 | ||
@@ -374,6 +362,7 @@ static int event_file_open(struct inode *inode, struct file *file) | |||
374 | ibmasm_event_reader_register(sp, &event_data->reader); | 362 | ibmasm_event_reader_register(sp, &event_data->reader); |
375 | 363 | ||
376 | event_data->sp = sp; | 364 | event_data->sp = sp; |
365 | event_data->active = 0; | ||
377 | file->private_data = event_data; | 366 | file->private_data = event_data; |
378 | return 0; | 367 | return 0; |
379 | } | 368 | } |
@@ -391,7 +380,9 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count | |||
391 | { | 380 | { |
392 | struct ibmasmfs_event_data *event_data = file->private_data; | 381 | struct ibmasmfs_event_data *event_data = file->private_data; |
393 | struct event_reader *reader = &event_data->reader; | 382 | struct event_reader *reader = &event_data->reader; |
383 | struct service_processor *sp = event_data->sp; | ||
394 | int ret; | 384 | int ret; |
385 | unsigned long flags; | ||
395 | 386 | ||
396 | if (*offset < 0) | 387 | if (*offset < 0) |
397 | return -EINVAL; | 388 | return -EINVAL; |
@@ -400,17 +391,32 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count | |||
400 | if (*offset != 0) | 391 | if (*offset != 0) |
401 | return 0; | 392 | return 0; |
402 | 393 | ||
403 | ret = ibmasm_get_next_event(event_data->sp, reader); | 394 | spin_lock_irqsave(&sp->lock, flags); |
395 | if (event_data->active) { | ||
396 | spin_unlock_irqrestore(&sp->lock, flags); | ||
397 | return -EBUSY; | ||
398 | } | ||
399 | event_data->active = 1; | ||
400 | spin_unlock_irqrestore(&sp->lock, flags); | ||
401 | |||
402 | ret = ibmasm_get_next_event(sp, reader); | ||
404 | if (ret <= 0) | 403 | if (ret <= 0) |
405 | return ret; | 404 | goto out; |
406 | 405 | ||
407 | if (count < reader->data_size) | 406 | if (count < reader->data_size) { |
408 | return -EINVAL; | 407 | ret = -EINVAL; |
408 | goto out; | ||
409 | } | ||
409 | 410 | ||
410 | if (copy_to_user(buf, reader->data, reader->data_size)) | 411 | if (copy_to_user(buf, reader->data, reader->data_size)) { |
411 | return -EFAULT; | 412 | ret = -EFAULT; |
413 | goto out; | ||
414 | } | ||
415 | ret = reader->data_size; | ||
412 | 416 | ||
413 | return reader->data_size; | 417 | out: |
418 | event_data->active = 0; | ||
419 | return ret; | ||
414 | } | 420 | } |
415 | 421 | ||
416 | static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) | 422 | static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) |
@@ -424,7 +430,7 @@ static ssize_t event_file_write(struct file *file, const char __user *buf, size_ | |||
424 | if (*offset != 0) | 430 | if (*offset != 0) |
425 | return 0; | 431 | return 0; |
426 | 432 | ||
427 | wake_up_interruptible(&event_data->reader.wait); | 433 | ibmasm_cancel_next_event(&event_data->reader); |
428 | return 0; | 434 | return 0; |
429 | } | 435 | } |
430 | 436 | ||
@@ -575,75 +581,6 @@ static ssize_t remote_settings_file_write(struct file *file, const char __user * | |||
575 | return count; | 581 | return count; |
576 | } | 582 | } |
577 | 583 | ||
578 | static int remote_event_file_open(struct inode *inode, struct file *file) | ||
579 | { | ||
580 | struct service_processor *sp; | ||
581 | unsigned long flags; | ||
582 | struct remote_queue *q; | ||
583 | |||
584 | file->private_data = inode->u.generic_ip; | ||
585 | sp = file->private_data; | ||
586 | q = &sp->remote_queue; | ||
587 | |||
588 | /* allow only one event reader */ | ||
589 | spin_lock_irqsave(&sp->lock, flags); | ||
590 | if (q->open) { | ||
591 | spin_unlock_irqrestore(&sp->lock, flags); | ||
592 | return -EBUSY; | ||
593 | } | ||
594 | q->open = 1; | ||
595 | spin_unlock_irqrestore(&sp->lock, flags); | ||
596 | |||
597 | enable_mouse_interrupts(sp); | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static int remote_event_file_close(struct inode *inode, struct file *file) | ||
603 | { | ||
604 | struct service_processor *sp = file->private_data; | ||
605 | |||
606 | disable_mouse_interrupts(sp); | ||
607 | wake_up_interruptible(&sp->remote_queue.wait); | ||
608 | sp->remote_queue.open = 0; | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static ssize_t remote_event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) | ||
614 | { | ||
615 | struct service_processor *sp = file->private_data; | ||
616 | struct remote_queue *q = &sp->remote_queue; | ||
617 | size_t data_size; | ||
618 | struct remote_event *reader = q->reader; | ||
619 | size_t num_events; | ||
620 | |||
621 | if (*offset < 0) | ||
622 | return -EINVAL; | ||
623 | if (count == 0 || count > 1024) | ||
624 | return 0; | ||
625 | if (*offset != 0) | ||
626 | return 0; | ||
627 | |||
628 | if (wait_event_interruptible(q->wait, q->reader != q->writer)) | ||
629 | return -ERESTARTSYS; | ||
630 | |||
631 | /* only get multiples of struct remote_event */ | ||
632 | num_events = min((count/sizeof(struct remote_event)), ibmasm_events_available(q)); | ||
633 | if (!num_events) | ||
634 | return 0; | ||
635 | |||
636 | data_size = num_events * sizeof(struct remote_event); | ||
637 | |||
638 | if (copy_to_user(buf, reader, data_size)) | ||
639 | return -EFAULT; | ||
640 | |||
641 | ibmasm_advance_reader(q, num_events); | ||
642 | |||
643 | return data_size; | ||
644 | } | ||
645 | |||
646 | |||
647 | static struct file_operations command_fops = { | 584 | static struct file_operations command_fops = { |
648 | .open = command_file_open, | 585 | .open = command_file_open, |
649 | .release = command_file_close, | 586 | .release = command_file_close, |
@@ -672,12 +609,6 @@ static struct file_operations remote_settings_fops = { | |||
672 | .write = remote_settings_file_write, | 609 | .write = remote_settings_file_write, |
673 | }; | 610 | }; |
674 | 611 | ||
675 | static struct file_operations remote_event_fops = { | ||
676 | .open = remote_event_file_open, | ||
677 | .release = remote_event_file_close, | ||
678 | .read = remote_event_file_read, | ||
679 | }; | ||
680 | |||
681 | 612 | ||
682 | static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root) | 613 | static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root) |
683 | { | 614 | { |
@@ -703,7 +634,5 @@ static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root) | |||
703 | ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR); | 634 | ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR); |
704 | ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR); | 635 | ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR); |
705 | ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR); | 636 | ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR); |
706 | ibmasmfs_create_file(sb, remote_dir, "connected", &remote_settings_fops, (void *)vnc_status(sp), S_IRUSR); | ||
707 | ibmasmfs_create_file(sb, remote_dir, "events", &remote_event_fops, (void *)sp, S_IRUSR); | ||
708 | } | 637 | } |
709 | } | 638 | } |