aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/sonypi.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2005-06-30 01:50:10 -0400
committerDmitry Torokhov <dtor_core@ameritech.net>2005-06-30 01:50:10 -0400
commitfb2ce3c005ede30b65b891c58ff56398df6089f8 (patch)
treebe8eb5861c8a5f65d65cdfa0e4705e3b0b5db5b3 /drivers/char/sonypi.c
parent16a334c0de5a94b1d10a1ac9a33f4dedac89a075 (diff)
Sonypi: make sure that input_work is not running when unloading
the module; submit/retrieve key release data into/from input_fifo in one shot. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/char/sonypi.c')
-rw-r--r--drivers/char/sonypi.c122
1 files changed, 63 insertions, 59 deletions
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index fd042060809a..983915bf87f1 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -439,6 +439,11 @@ static struct {
439 { 0, 0 }, 439 { 0, 0 },
440}; 440};
441 441
442struct sonypi_keypress {
443 struct input_dev *dev;
444 int key;
445};
446
442static struct sonypi_device { 447static struct sonypi_device {
443 struct pci_dev *dev; 448 struct pci_dev *dev;
444 struct platform_device *pdev; 449 struct platform_device *pdev;
@@ -710,22 +715,61 @@ static void sonypi_setbluetoothpower(u8 state)
710 715
711static void input_keyrelease(void *data) 716static void input_keyrelease(void *data)
712{ 717{
713 struct input_dev *input_dev; 718 struct sonypi_keypress kp;
714 int key;
715
716 while (1) {
717 if (kfifo_get(sonypi_device.input_fifo,
718 (unsigned char *)&input_dev,
719 sizeof(input_dev)) != sizeof(input_dev))
720 return;
721 if (kfifo_get(sonypi_device.input_fifo,
722 (unsigned char *)&key,
723 sizeof(key)) != sizeof(key))
724 return;
725 719
720 while (kfifo_get(sonypi_device.input_fifo, (unsigned char *)&kp,
721 sizeof(kp)) == sizeof(kp)) {
726 msleep(10); 722 msleep(10);
727 input_report_key(input_dev, key, 0); 723 input_report_key(kp.dev, kp.key, 0);
728 input_sync(input_dev); 724 input_sync(kp.dev);
725 }
726}
727
728static void sonypi_report_input_event(u8 event)
729{
730 struct input_dev *jog_dev = &sonypi_device.input_jog_dev;
731 struct input_dev *key_dev = &sonypi_device.input_key_dev;
732 struct sonypi_keypress kp = { NULL };
733 int i;
734
735 switch (event) {
736 case SONYPI_EVENT_JOGDIAL_UP:
737 case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
738 input_report_rel(jog_dev, REL_WHEEL, 1);
739 input_sync(jog_dev);
740 break;
741
742 case SONYPI_EVENT_JOGDIAL_DOWN:
743 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
744 input_report_rel(jog_dev, REL_WHEEL, -1);
745 input_sync(jog_dev);
746 break;
747
748 case SONYPI_EVENT_JOGDIAL_PRESSED:
749 kp.key = BTN_MIDDLE;
750 kp.dev = jog_dev;
751 break;
752
753 case SONYPI_EVENT_FNKEY_RELEASED:
754 /* Nothing, not all VAIOs generate this event */
755 break;
756
757 default:
758 for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
759 if (event == sonypi_inputkeys[i].sonypiev) {
760 kp.dev = key_dev;
761 kp.key = sonypi_inputkeys[i].inputev;
762 break;
763 }
764 break;
765 }
766
767 if (kp.dev) {
768 input_report_key(kp.dev, kp.key, 1);
769 input_sync(kp.dev);
770 kfifo_put(sonypi_device.input_fifo,
771 (unsigned char *)&kp, sizeof(kp));
772 schedule_work(&sonypi_device.input_work);
729 } 773 }
730} 774}
731 775
@@ -768,51 +812,8 @@ found:
768 printk(KERN_INFO 812 printk(KERN_INFO
769 "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2); 813 "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2);
770 814
771 if (useinput) { 815 if (useinput)
772 struct input_dev *input_jog_dev = &sonypi_device.input_jog_dev; 816 sonypi_report_input_event(event);
773 struct input_dev *input_key_dev = &sonypi_device.input_key_dev;
774 switch (event) {
775 case SONYPI_EVENT_JOGDIAL_UP:
776 case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
777 input_report_rel(input_jog_dev, REL_WHEEL, 1);
778 break;
779 case SONYPI_EVENT_JOGDIAL_DOWN:
780 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
781 input_report_rel(input_jog_dev, REL_WHEEL, -1);
782 break;
783 case SONYPI_EVENT_JOGDIAL_PRESSED: {
784 int key = BTN_MIDDLE;
785 input_report_key(input_jog_dev, key, 1);
786 kfifo_put(sonypi_device.input_fifo,
787 (unsigned char *)&input_jog_dev,
788 sizeof(input_jog_dev));
789 kfifo_put(sonypi_device.input_fifo,
790 (unsigned char *)&key, sizeof(key));
791 break;
792 }
793 case SONYPI_EVENT_FNKEY_RELEASED:
794 /* Nothing, not all VAIOs generate this event */
795 break;
796 }
797 input_sync(input_jog_dev);
798
799 for (i = 0; sonypi_inputkeys[i].sonypiev; i++) {
800 int key;
801
802 if (event != sonypi_inputkeys[i].sonypiev)
803 continue;
804
805 key = sonypi_inputkeys[i].inputev;
806 input_report_key(input_key_dev, key, 1);
807 kfifo_put(sonypi_device.input_fifo,
808 (unsigned char *)&input_key_dev,
809 sizeof(input_key_dev));
810 kfifo_put(sonypi_device.input_fifo,
811 (unsigned char *)&key, sizeof(key));
812 }
813 input_sync(input_key_dev);
814 schedule_work(&sonypi_device.input_work);
815 }
816 817
817 kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); 818 kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
818 kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); 819 kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
@@ -1337,6 +1338,9 @@ static void __devexit sonypi_remove(void)
1337{ 1338{
1338 sonypi_disable(); 1339 sonypi_disable();
1339 1340
1341 synchronize_sched(); /* Allow sonypi interrupt to complete. */
1342 flush_scheduled_work();
1343
1340 platform_device_unregister(sonypi_device.pdev); 1344 platform_device_unregister(sonypi_device.pdev);
1341 1345
1342 if (useinput) { 1346 if (useinput) {