aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/sonypi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/sonypi.c')
-rw-r--r--drivers/char/sonypi.c146
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
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);
@@ -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);
1314out_infifo: 1301out_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);
1317out_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);
1320out_inkmallocinput1:
1321 free_irq(sonypi_device.irq, sonypi_irq); 1304 free_irq(sonypi_device.irq, sonypi_irq);
1322out_reqirq: 1305out_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