diff options
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-input.c')
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-input.c | 172 |
1 files changed, 101 insertions, 71 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 046223de1e91..2dc1be00b8b8 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c | |||
@@ -1,25 +1,21 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | handle em28xx IR remotes via linux kernel input layer. | 2 | // |
3 | 3 | // handle em28xx IR remotes via linux kernel input layer. | |
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> | 4 | // |
5 | Markus Rechberger <mrechberger@gmail.com> | 5 | // Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
6 | Mauro Carvalho Chehab <mchehab@infradead.org> | 6 | // Markus Rechberger <mrechberger@gmail.com> |
7 | Sascha Sommer <saschasommer@freenet.de> | 7 | // Mauro Carvalho Chehab <mchehab@infradead.org> |
8 | 8 | // Sascha Sommer <saschasommer@freenet.de> | |
9 | This program is free software; you can redistribute it and/or modify | 9 | // |
10 | it under the terms of the GNU General Public License as published by | 10 | // This program is free software; you can redistribute it and/or modify |
11 | the Free Software Foundation; either version 2 of the License, or | 11 | // it under the terms of the GNU General Public License as published by |
12 | (at your option) any later version. | 12 | // the Free Software Foundation; either version 2 of the License, or |
13 | 13 | // (at your option) any later version. | |
14 | This program is distributed in the hope that it will be useful, | 14 | // |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | // This program is distributed in the hope that it will be useful, |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | GNU General Public License for more details. | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | 18 | // GNU General Public License for more details. | |
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | 19 | ||
24 | #include "em28xx.h" | 20 | #include "em28xx.h" |
25 | 21 | ||
@@ -41,15 +37,15 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); | |||
41 | 37 | ||
42 | #define MODULE_NAME "em28xx" | 38 | #define MODULE_NAME "em28xx" |
43 | 39 | ||
44 | #define dprintk( fmt, arg...) do { \ | 40 | #define dprintk(fmt, arg...) do { \ |
45 | if (ir_debug) \ | 41 | if (ir_debug) \ |
46 | dev_printk(KERN_DEBUG, &ir->dev->intf->dev, \ | 42 | dev_printk(KERN_DEBUG, &ir->dev->intf->dev, \ |
47 | "input: %s: " fmt, __func__, ## arg); \ | 43 | "input: %s: " fmt, __func__, ## arg); \ |
48 | } while (0) | 44 | } while (0) |
49 | 45 | ||
50 | /********************************************************** | 46 | /* |
51 | Polling structure used by em28xx IR's | 47 | * Polling structure used by em28xx IR's |
52 | **********************************************************/ | 48 | */ |
53 | 49 | ||
54 | struct em28xx_ir_poll_result { | 50 | struct em28xx_ir_poll_result { |
55 | unsigned int toggle_bit:1; | 51 | unsigned int toggle_bit:1; |
@@ -76,24 +72,31 @@ struct em28xx_IR { | |||
76 | 72 | ||
77 | int (*get_key_i2c)(struct i2c_client *ir, enum rc_proto *protocol, | 73 | int (*get_key_i2c)(struct i2c_client *ir, enum rc_proto *protocol, |
78 | u32 *scancode); | 74 | u32 *scancode); |
79 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); | 75 | int (*get_key)(struct em28xx_IR *ir, struct em28xx_ir_poll_result *r); |
80 | }; | 76 | }; |
81 | 77 | ||
82 | /********************************************************** | 78 | /* |
83 | I2C IR based get keycodes - should be used with ir-kbd-i2c | 79 | * I2C IR based get keycodes - should be used with ir-kbd-i2c |
84 | **********************************************************/ | 80 | */ |
85 | 81 | ||
86 | static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, | 82 | static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, |
87 | enum rc_proto *protocol, u32 *scancode) | 83 | enum rc_proto *protocol, u32 *scancode) |
88 | { | 84 | { |
85 | int rc; | ||
89 | unsigned char b; | 86 | unsigned char b; |
90 | 87 | ||
91 | /* poll IR chip */ | 88 | /* poll IR chip */ |
92 | if (1 != i2c_master_recv(i2c_dev, &b, 1)) | 89 | rc = i2c_master_recv(i2c_dev, &b, 1); |
90 | if (rc != 1) { | ||
91 | if (rc < 0) | ||
92 | return rc; | ||
93 | return -EIO; | 93 | return -EIO; |
94 | } | ||
94 | 95 | ||
95 | /* it seems that 0xFE indicates that a button is still hold | 96 | /* |
96 | down, while 0xff indicates that no button is hold down. */ | 97 | * it seems that 0xFE indicates that a button is still hold |
98 | * down, while 0xff indicates that no button is hold down. | ||
99 | */ | ||
97 | 100 | ||
98 | if (b == 0xff) | 101 | if (b == 0xff) |
99 | return 0; | 102 | return 0; |
@@ -145,7 +148,7 @@ static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev, | |||
145 | 148 | ||
146 | /* poll IR chip */ | 149 | /* poll IR chip */ |
147 | 150 | ||
148 | if (3 != i2c_master_recv(i2c_dev, buf, 3)) | 151 | if (i2c_master_recv(i2c_dev, buf, 3) != 3) |
149 | return -EIO; | 152 | return -EIO; |
150 | 153 | ||
151 | if (buf[0] != 0x00) | 154 | if (buf[0] != 0x00) |
@@ -162,18 +165,28 @@ static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev, | |||
162 | { | 165 | { |
163 | unsigned char subaddr, keydetect, key; | 166 | unsigned char subaddr, keydetect, key; |
164 | 167 | ||
165 | struct i2c_msg msg[] = { { .addr = i2c_dev->addr, .flags = 0, .buf = &subaddr, .len = 1}, | 168 | struct i2c_msg msg[] = { |
166 | { .addr = i2c_dev->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} }; | 169 | { |
170 | .addr = i2c_dev->addr, | ||
171 | .flags = 0, | ||
172 | .buf = &subaddr, .len = 1 | ||
173 | }, { | ||
174 | .addr = i2c_dev->addr, | ||
175 | .flags = I2C_M_RD, | ||
176 | .buf = &keydetect, | ||
177 | .len = 1 | ||
178 | } | ||
179 | }; | ||
167 | 180 | ||
168 | subaddr = 0x10; | 181 | subaddr = 0x10; |
169 | if (2 != i2c_transfer(i2c_dev->adapter, msg, 2)) | 182 | if (i2c_transfer(i2c_dev->adapter, msg, 2) != 2) |
170 | return -EIO; | 183 | return -EIO; |
171 | if (keydetect == 0x00) | 184 | if (keydetect == 0x00) |
172 | return 0; | 185 | return 0; |
173 | 186 | ||
174 | subaddr = 0x00; | 187 | subaddr = 0x00; |
175 | msg[1].buf = &key; | 188 | msg[1].buf = &key; |
176 | if (2 != i2c_transfer(i2c_dev->adapter, msg, 2)) | 189 | if (i2c_transfer(i2c_dev->adapter, msg, 2) != 2) |
177 | return -EIO; | 190 | return -EIO; |
178 | if (key == 0x00) | 191 | if (key == 0x00) |
179 | return 0; | 192 | return 0; |
@@ -183,9 +196,9 @@ static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev, | |||
183 | return 1; | 196 | return 1; |
184 | } | 197 | } |
185 | 198 | ||
186 | /********************************************************** | 199 | /* |
187 | Poll based get keycode functions | 200 | * Poll based get keycode functions |
188 | **********************************************************/ | 201 | */ |
189 | 202 | ||
190 | /* This is for the em2860/em2880 */ | 203 | /* This is for the em2860/em2880 */ |
191 | static int default_polling_getkey(struct em28xx_IR *ir, | 204 | static int default_polling_getkey(struct em28xx_IR *ir, |
@@ -195,8 +208,9 @@ static int default_polling_getkey(struct em28xx_IR *ir, | |||
195 | int rc; | 208 | int rc; |
196 | u8 msg[3] = { 0, 0, 0 }; | 209 | u8 msg[3] = { 0, 0, 0 }; |
197 | 210 | ||
198 | /* Read key toggle, brand, and key code | 211 | /* |
199 | on registers 0x45, 0x46 and 0x47 | 212 | * Read key toggle, brand, and key code |
213 | * on registers 0x45, 0x46 and 0x47 | ||
200 | */ | 214 | */ |
201 | rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR, | 215 | rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR, |
202 | msg, sizeof(msg)); | 216 | msg, sizeof(msg)); |
@@ -237,8 +251,9 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, | |||
237 | int rc; | 251 | int rc; |
238 | u8 msg[5] = { 0, 0, 0, 0, 0 }; | 252 | u8 msg[5] = { 0, 0, 0, 0, 0 }; |
239 | 253 | ||
240 | /* Read key toggle, brand, and key code | 254 | /* |
241 | on registers 0x51-55 | 255 | * Read key toggle, brand, and key code |
256 | * on registers 0x51-55 | ||
242 | */ | 257 | */ |
243 | rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR, | 258 | rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR, |
244 | msg, sizeof(msg)); | 259 | msg, sizeof(msg)); |
@@ -294,9 +309,9 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, | |||
294 | return 0; | 309 | return 0; |
295 | } | 310 | } |
296 | 311 | ||
297 | /********************************************************** | 312 | /* |
298 | Polling code for em28xx | 313 | * Polling code for em28xx |
299 | **********************************************************/ | 314 | */ |
300 | 315 | ||
301 | static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir) | 316 | static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir) |
302 | { | 317 | { |
@@ -347,11 +362,14 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) | |||
347 | 362 | ||
348 | if (ir->dev->chip_id == CHIP_ID_EM2874 || | 363 | if (ir->dev->chip_id == CHIP_ID_EM2874 || |
349 | ir->dev->chip_id == CHIP_ID_EM2884) | 364 | ir->dev->chip_id == CHIP_ID_EM2884) |
350 | /* The em2874 clears the readcount field every time the | 365 | /* |
351 | register is read. The em2860/2880 datasheet says that it | 366 | * The em2874 clears the readcount field every time the |
352 | is supposed to clear the readcount, but it doesn't. So with | 367 | * register is read. The em2860/2880 datasheet says |
353 | the em2874, we are looking for a non-zero read count as | 368 | * that it is supposed to clear the readcount, but it |
354 | opposed to a readcount that is incrementing */ | 369 | * doesn't. So with the em2874, we are looking for a |
370 | * non-zero read count as opposed to a readcount | ||
371 | * that is incrementing | ||
372 | */ | ||
355 | ir->last_readcount = 0; | 373 | ir->last_readcount = 0; |
356 | else | 374 | else |
357 | ir->last_readcount = poll_result.read_count; | 375 | ir->last_readcount = poll_result.read_count; |
@@ -476,15 +494,18 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_proto) | |||
476 | static int em28xx_probe_i2c_ir(struct em28xx *dev) | 494 | static int em28xx_probe_i2c_ir(struct em28xx *dev) |
477 | { | 495 | { |
478 | int i = 0; | 496 | int i = 0; |
479 | /* Leadtek winfast tv USBII deluxe can find a non working IR-device */ | 497 | /* |
480 | /* at address 0x18, so if that address is needed for another board in */ | 498 | * Leadtek winfast tv USBII deluxe can find a non working IR-device |
481 | /* the future, please put it after 0x1f. */ | 499 | * at address 0x18, so if that address is needed for another board in |
500 | * the future, please put it after 0x1f. | ||
501 | */ | ||
482 | const unsigned short addr_list[] = { | 502 | const unsigned short addr_list[] = { |
483 | 0x1f, 0x30, 0x47, I2C_CLIENT_END | 503 | 0x1f, 0x30, 0x47, I2C_CLIENT_END |
484 | }; | 504 | }; |
485 | 505 | ||
486 | while (addr_list[i] != I2C_CLIENT_END) { | 506 | while (addr_list[i] != I2C_CLIENT_END) { |
487 | if (i2c_probe_func_quick_read(&dev->i2c_adap[dev->def_i2c_bus], addr_list[i]) == 1) | 507 | if (i2c_probe_func_quick_read(&dev->i2c_adap[dev->def_i2c_bus], |
508 | addr_list[i]) == 1) | ||
488 | return addr_list[i]; | 509 | return addr_list[i]; |
489 | i++; | 510 | i++; |
490 | } | 511 | } |
@@ -492,9 +513,9 @@ static int em28xx_probe_i2c_ir(struct em28xx *dev) | |||
492 | return -ENODEV; | 513 | return -ENODEV; |
493 | } | 514 | } |
494 | 515 | ||
495 | /********************************************************** | 516 | /* |
496 | Handle buttons | 517 | * Handle buttons |
497 | **********************************************************/ | 518 | */ |
498 | 519 | ||
499 | static void em28xx_query_buttons(struct work_struct *work) | 520 | static void em28xx_query_buttons(struct work_struct *work) |
500 | { | 521 | { |
@@ -515,7 +536,10 @@ static void em28xx_query_buttons(struct work_struct *work) | |||
515 | j = 0; | 536 | j = 0; |
516 | while (dev->board.buttons[j].role >= 0 && | 537 | while (dev->board.buttons[j].role >= 0 && |
517 | dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) { | 538 | dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) { |
518 | struct em28xx_button *button = &dev->board.buttons[j]; | 539 | const struct em28xx_button *button; |
540 | |||
541 | button = &dev->board.buttons[j]; | ||
542 | |||
519 | /* Check if button uses the current address */ | 543 | /* Check if button uses the current address */ |
520 | if (button->reg_r != dev->button_polling_addresses[i]) { | 544 | if (button->reg_r != dev->button_polling_addresses[i]) { |
521 | j++; | 545 | j++; |
@@ -618,7 +642,8 @@ static void em28xx_init_buttons(struct em28xx *dev) | |||
618 | dev->button_polling_interval = EM28XX_BUTTONS_DEBOUNCED_QUERY_INTERVAL; | 642 | dev->button_polling_interval = EM28XX_BUTTONS_DEBOUNCED_QUERY_INTERVAL; |
619 | while (dev->board.buttons[i].role >= 0 && | 643 | while (dev->board.buttons[i].role >= 0 && |
620 | dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) { | 644 | dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) { |
621 | struct em28xx_button *button = &dev->board.buttons[i]; | 645 | const struct em28xx_button *button = &dev->board.buttons[i]; |
646 | |||
622 | /* Check if polling address is already on the list */ | 647 | /* Check if polling address is already on the list */ |
623 | addr_new = true; | 648 | addr_new = true; |
624 | for (j = 0; j < dev->num_button_polling_addresses; j++) { | 649 | for (j = 0; j < dev->num_button_polling_addresses; j++) { |
@@ -649,6 +674,7 @@ static void em28xx_init_buttons(struct em28xx *dev) | |||
649 | /* Add read address to list of polling addresses */ | 674 | /* Add read address to list of polling addresses */ |
650 | if (addr_new) { | 675 | if (addr_new) { |
651 | unsigned int index = dev->num_button_polling_addresses; | 676 | unsigned int index = dev->num_button_polling_addresses; |
677 | |||
652 | dev->button_polling_addresses[index] = button->reg_r; | 678 | dev->button_polling_addresses[index] = button->reg_r; |
653 | dev->num_button_polling_addresses++; | 679 | dev->num_button_polling_addresses++; |
654 | } | 680 | } |
@@ -677,7 +703,7 @@ static void em28xx_shutdown_buttons(struct em28xx *dev) | |||
677 | /* Clear polling addresses list */ | 703 | /* Clear polling addresses list */ |
678 | dev->num_button_polling_addresses = 0; | 704 | dev->num_button_polling_addresses = 0; |
679 | /* Deregister input devices */ | 705 | /* Deregister input devices */ |
680 | if (dev->sbutton_input_dev != NULL) { | 706 | if (dev->sbutton_input_dev) { |
681 | dev_info(&dev->intf->dev, "Deregistering snapshot button\n"); | 707 | dev_info(&dev->intf->dev, "Deregistering snapshot button\n"); |
682 | input_unregister_device(dev->sbutton_input_dev); | 708 | input_unregister_device(dev->sbutton_input_dev); |
683 | dev->sbutton_input_dev = NULL; | 709 | dev->sbutton_input_dev = NULL; |
@@ -714,7 +740,7 @@ static int em28xx_ir_init(struct em28xx *dev) | |||
714 | } | 740 | } |
715 | } | 741 | } |
716 | 742 | ||
717 | if (dev->board.ir_codes == NULL && !dev->board.has_ir_i2c) { | 743 | if (!dev->board.ir_codes && !dev->board.has_ir_i2c) { |
718 | /* No remote control support */ | 744 | /* No remote control support */ |
719 | dev_warn(&dev->intf->dev, | 745 | dev_warn(&dev->intf->dev, |
720 | "Remote control support is not available for this card.\n"); | 746 | "Remote control support is not available for this card.\n"); |
@@ -764,7 +790,7 @@ static int em28xx_ir_init(struct em28xx *dev) | |||
764 | goto error; | 790 | goto error; |
765 | } | 791 | } |
766 | 792 | ||
767 | ir->i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 793 | ir->i2c_client = kzalloc(sizeof(*ir->i2c_client), GFP_KERNEL); |
768 | if (!ir->i2c_client) | 794 | if (!ir->i2c_client) |
769 | goto error; | 795 | goto error; |
770 | ir->i2c_client->adapter = &ir->dev->i2c_adap[dev->def_i2c_bus]; | 796 | ir->i2c_client->adapter = &ir->dev->i2c_adap[dev->def_i2c_bus]; |
@@ -881,9 +907,11 @@ static int em28xx_ir_suspend(struct em28xx *dev) | |||
881 | if (ir) | 907 | if (ir) |
882 | cancel_delayed_work_sync(&ir->work); | 908 | cancel_delayed_work_sync(&ir->work); |
883 | cancel_delayed_work_sync(&dev->buttons_query_work); | 909 | cancel_delayed_work_sync(&dev->buttons_query_work); |
884 | /* is canceling delayed work sufficient or does the rc event | 910 | /* |
885 | kthread needs stopping? kthread is stopped in | 911 | * is canceling delayed work sufficient or does the rc event |
886 | ir_raw_event_unregister() */ | 912 | * kthread needs stopping? kthread is stopped in |
913 | * ir_raw_event_unregister() | ||
914 | */ | ||
887 | return 0; | 915 | return 0; |
888 | } | 916 | } |
889 | 917 | ||
@@ -895,8 +923,10 @@ static int em28xx_ir_resume(struct em28xx *dev) | |||
895 | return 0; | 923 | return 0; |
896 | 924 | ||
897 | dev_info(&dev->intf->dev, "Resuming input extension\n"); | 925 | dev_info(&dev->intf->dev, "Resuming input extension\n"); |
898 | /* if suspend calls ir_raw_event_unregister(), the should call | 926 | /* |
899 | ir_raw_event_register() */ | 927 | * if suspend calls ir_raw_event_unregister(), the should call |
928 | * ir_raw_event_register() | ||
929 | */ | ||
900 | if (ir) | 930 | if (ir) |
901 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | 931 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); |
902 | if (dev->num_button_polling_addresses) | 932 | if (dev->num_button_polling_addresses) |
@@ -924,7 +954,7 @@ static void __exit em28xx_rc_unregister(void) | |||
924 | em28xx_unregister_extension(&rc_ops); | 954 | em28xx_unregister_extension(&rc_ops); |
925 | } | 955 | } |
926 | 956 | ||
927 | MODULE_LICENSE("GPL"); | 957 | MODULE_LICENSE("GPL v2"); |
928 | MODULE_AUTHOR("Mauro Carvalho Chehab"); | 958 | MODULE_AUTHOR("Mauro Carvalho Chehab"); |
929 | MODULE_DESCRIPTION(DRIVER_DESC " - input interface"); | 959 | MODULE_DESCRIPTION(DRIVER_DESC " - input interface"); |
930 | MODULE_VERSION(EM28XX_VERSION); | 960 | MODULE_VERSION(EM28XX_VERSION); |