diff options
Diffstat (limited to 'drivers/char/sonypi.c')
-rw-r--r-- | drivers/char/sonypi.c | 146 |
1 files changed, 65 insertions, 81 deletions
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index fd042060809a..cefbe985e55c 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 | ||
442 | struct sonypi_keypress { | ||
443 | struct input_dev *dev; | ||
444 | int key; | ||
445 | }; | ||
446 | |||
442 | static struct sonypi_device { | 447 | static 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 | ||
711 | static void input_keyrelease(void *data) | 716 | static 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 | |||
728 | static 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); |
@@ -1227,14 +1228,7 @@ static int __devinit sonypi_probe(void) | |||
1227 | sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] = | 1228 | sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] = |
1228 | BIT(BTN_MIDDLE); | 1229 | BIT(BTN_MIDDLE); |
1229 | sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL); | 1230 | sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL); |
1230 | sonypi_device.input_jog_dev.name = | 1231 | sonypi_device.input_jog_dev.name = SONYPI_JOG_INPUTNAME; |
1231 | kmalloc(sizeof(SONYPI_JOG_INPUTNAME), GFP_KERNEL); | ||
1232 | if (!sonypi_device.input_jog_dev.name) { | ||
1233 | printk(KERN_ERR "sonypi: kmalloc failed\n"); | ||
1234 | ret = -ENOMEM; | ||
1235 | goto out_inkmallocinput1; | ||
1236 | } | ||
1237 | sprintf(sonypi_device.input_jog_dev.name, SONYPI_JOG_INPUTNAME); | ||
1238 | sonypi_device.input_jog_dev.id.bustype = BUS_ISA; | 1232 | sonypi_device.input_jog_dev.id.bustype = BUS_ISA; |
1239 | sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY; | 1233 | sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY; |
1240 | 1234 | ||
@@ -1248,14 +1242,7 @@ static int __devinit sonypi_probe(void) | |||
1248 | if (sonypi_inputkeys[i].inputev) | 1242 | if (sonypi_inputkeys[i].inputev) |
1249 | set_bit(sonypi_inputkeys[i].inputev, | 1243 | set_bit(sonypi_inputkeys[i].inputev, |
1250 | sonypi_device.input_key_dev.keybit); | 1244 | sonypi_device.input_key_dev.keybit); |
1251 | sonypi_device.input_key_dev.name = | 1245 | sonypi_device.input_key_dev.name = SONYPI_KEY_INPUTNAME; |
1252 | kmalloc(sizeof(SONYPI_KEY_INPUTNAME), GFP_KERNEL); | ||
1253 | if (!sonypi_device.input_key_dev.name) { | ||
1254 | printk(KERN_ERR "sonypi: kmalloc failed\n"); | ||
1255 | ret = -ENOMEM; | ||
1256 | goto out_inkmallocinput2; | ||
1257 | } | ||
1258 | sprintf(sonypi_device.input_key_dev.name, SONYPI_KEY_INPUTNAME); | ||
1259 | sonypi_device.input_key_dev.id.bustype = BUS_ISA; | 1246 | sonypi_device.input_key_dev.id.bustype = BUS_ISA; |
1260 | sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY; | 1247 | sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY; |
1261 | 1248 | ||
@@ -1313,11 +1300,7 @@ out_platformdev: | |||
1313 | kfifo_free(sonypi_device.input_fifo); | 1300 | kfifo_free(sonypi_device.input_fifo); |
1314 | out_infifo: | 1301 | out_infifo: |
1315 | input_unregister_device(&sonypi_device.input_key_dev); | 1302 | input_unregister_device(&sonypi_device.input_key_dev); |
1316 | kfree(sonypi_device.input_key_dev.name); | ||
1317 | out_inkmallocinput2: | ||
1318 | input_unregister_device(&sonypi_device.input_jog_dev); | 1303 | input_unregister_device(&sonypi_device.input_jog_dev); |
1319 | kfree(sonypi_device.input_jog_dev.name); | ||
1320 | out_inkmallocinput1: | ||
1321 | free_irq(sonypi_device.irq, sonypi_irq); | 1304 | free_irq(sonypi_device.irq, sonypi_irq); |
1322 | out_reqirq: | 1305 | out_reqirq: |
1323 | release_region(sonypi_device.ioport1, sonypi_device.region_size); | 1306 | release_region(sonypi_device.ioport1, sonypi_device.region_size); |
@@ -1337,13 +1320,14 @@ static void __devexit sonypi_remove(void) | |||
1337 | { | 1320 | { |
1338 | sonypi_disable(); | 1321 | sonypi_disable(); |
1339 | 1322 | ||
1323 | synchronize_sched(); /* Allow sonypi interrupt to complete. */ | ||
1324 | flush_scheduled_work(); | ||
1325 | |||
1340 | platform_device_unregister(sonypi_device.pdev); | 1326 | platform_device_unregister(sonypi_device.pdev); |
1341 | 1327 | ||
1342 | if (useinput) { | 1328 | if (useinput) { |
1343 | input_unregister_device(&sonypi_device.input_key_dev); | 1329 | input_unregister_device(&sonypi_device.input_key_dev); |
1344 | kfree(sonypi_device.input_key_dev.name); | ||
1345 | input_unregister_device(&sonypi_device.input_jog_dev); | 1330 | input_unregister_device(&sonypi_device.input_jog_dev); |
1346 | kfree(sonypi_device.input_jog_dev.name); | ||
1347 | kfifo_free(sonypi_device.input_fifo); | 1331 | kfifo_free(sonypi_device.input_fifo); |
1348 | } | 1332 | } |
1349 | 1333 | ||