diff mbox

media: av7110: switch to useing timer_setup()

Message ID 20171025004005.hyb43h3yvovp4is2@dtor-ws (mailing list archive)
State New, archived
Headers show

Commit Message

Dmitry Torokhov Oct. 25, 2017, 12:40 a.m. UTC
In preparation for unconditionally passing the struct timer_list pointer to
all timer callbacks, switch to using the new timer_setup() and from_timer()
to pass the timer pointer explicitly.

Also stop poking into input core internals and override its autorepeat
timer function. I am not sure why we have such convoluted autorepeat
handling in this driver instead of letting input core handle autorepeat,
but this preserves current behavior of allowing controlling autorepeat
delay and forcing autorepeat period to be whatever the hardware has.

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---

Note that this has not been tested on the hardware. But it should
compile, so I have that going for me.

 drivers/media/pci/ttpci/av7110.h    |  4 ++--
 drivers/media/pci/ttpci/av7110_ir.c | 40 +++++++++++++++++--------------------
 2 files changed, 20 insertions(+), 24 deletions(-)

Comments

Jaejoong Kim Oct. 25, 2017, 1:03 a.m. UTC | #1
Hi,

[PATCH] media: av7110: switch to useing timer_setup()
                                                       ^^^^^^^
typo error.

2017-10-25 9:40 GMT+09:00 Dmitry Torokhov <dmitry.torokhov@gmail.com>:
> In preparation for unconditionally passing the struct timer_list pointer to
> all timer callbacks, switch to using the new timer_setup() and from_timer()
> to pass the timer pointer explicitly.
>
> Also stop poking into input core internals and override its autorepeat
> timer function. I am not sure why we have such convoluted autorepeat
> handling in this driver instead of letting input core handle autorepeat,
> but this preserves current behavior of allowing controlling autorepeat
> delay and forcing autorepeat period to be whatever the hardware has.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>
> Note that this has not been tested on the hardware. But it should
> compile, so I have that going for me.
>
>  drivers/media/pci/ttpci/av7110.h    |  4 ++--
>  drivers/media/pci/ttpci/av7110_ir.c | 40 +++++++++++++++++--------------------
>  2 files changed, 20 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h
> index 347827925c14..0aa3c6f01853 100644
> --- a/drivers/media/pci/ttpci/av7110.h
> +++ b/drivers/media/pci/ttpci/av7110.h
> @@ -80,10 +80,11 @@ struct av7110;
>
>  /* infrared remote control */
>  struct infrared {
> -       u16     key_map[256];
> +       u16                     key_map[256];
>         struct input_dev        *input_dev;
>         char                    input_phys[32];
>         struct timer_list       keyup_timer;
> +       unsigned long           keydown_time;
>         struct tasklet_struct   ir_tasklet;
>         void                    (*ir_handler)(struct av7110 *av7110, u32 ircom);
>         u32                     ir_command;
> @@ -93,7 +94,6 @@ struct infrared {
>         u8                      inversion;
>         u16                     last_key;
>         u16                     last_toggle;
> -       u8                      delay_timer_finished;
>  };
>
>
> diff --git a/drivers/media/pci/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c
> index ca05198de2c2..b602e64b3412 100644
> --- a/drivers/media/pci/ttpci/av7110_ir.c
> +++ b/drivers/media/pci/ttpci/av7110_ir.c
> @@ -84,9 +84,9 @@ static u16 default_key_map [256] = {
>
>
>  /* key-up timer */
> -static void av7110_emit_keyup(unsigned long parm)
> +static void av7110_emit_keyup(struct timer_list *t)
>  {
> -       struct infrared *ir = (struct infrared *) parm;
> +       struct infrared *ir = from_timer(ir, keyup_timer, t);
>
>         if (!ir || !test_bit(ir->last_key, ir->input_dev->key))
>                 return;
> @@ -152,19 +152,20 @@ static void av7110_emit_key(unsigned long parm)
>                 return;
>         }
>
> -       if (timer_pending(&ir->keyup_timer)) {
> -               del_timer(&ir->keyup_timer);
> +       if (del_timer(&ir->keyup_timer)) {
>                 if (ir->last_key != keycode || toggle != ir->last_toggle) {
> -                       ir->delay_timer_finished = 0;
> +                       ir->keydown_time = jiffies;
>                         input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
>                         input_event(ir->input_dev, EV_KEY, keycode, 1);
>                         input_sync(ir->input_dev);
> -               } else if (ir->delay_timer_finished) {
> +               } else if (time_after(jiffies, ir->keydown_time +
> +                               msecs_to_jiffies(
> +                                       ir->input_dev->rep[REP_PERIOD]))) {
>                         input_event(ir->input_dev, EV_KEY, keycode, 2);
>                         input_sync(ir->input_dev);
>                 }
>         } else {
> -               ir->delay_timer_finished = 0;
> +               ir->keydown_time = jiffies;
>                 input_event(ir->input_dev, EV_KEY, keycode, 1);
>                 input_sync(ir->input_dev);
>         }
> @@ -172,9 +173,7 @@ static void av7110_emit_key(unsigned long parm)
>         ir->last_key = keycode;
>         ir->last_toggle = toggle;
>
> -       ir->keyup_timer.expires = jiffies + UP_TIMEOUT;
> -       add_timer(&ir->keyup_timer);
> -
> +       mod_timer(&ir->keyup_timer, jiffies + UP_TIMEOUT);
>  }
>
>
> @@ -184,12 +183,19 @@ static void input_register_keys(struct infrared *ir)
>         int i;
>
>         set_bit(EV_KEY, ir->input_dev->evbit);
> -       set_bit(EV_REP, ir->input_dev->evbit);
>         set_bit(EV_MSC, ir->input_dev->evbit);
>
>         set_bit(MSC_RAW, ir->input_dev->mscbit);
>         set_bit(MSC_SCAN, ir->input_dev->mscbit);
>
> +       set_bit(EV_REP, ir->input_dev->evbit);
> +       /*
> +        * By setting the delay before registering input device we
> +        * indicate that we will be implementing the autorepeat
> +        * ourselves.
> +        */
> +       ir->input_dev->rep[REP_DELAY] = 250;
> +
>         memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
>
>         for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) {
> @@ -205,15 +211,6 @@ static void input_register_keys(struct infrared *ir)
>  }
>
>
> -/* called by the input driver after rep[REP_DELAY] ms */
> -static void input_repeat_key(unsigned long parm)
> -{
> -       struct infrared *ir = (struct infrared *) parm;
> -
> -       ir->delay_timer_finished = 1;
> -}
> -
> -
>  /* check for configuration changes */
>  int av7110_check_ir_config(struct av7110 *av7110, int force)
>  {
> @@ -333,8 +330,7 @@ int av7110_ir_init(struct av7110 *av7110)
>         av_list[av_cnt++] = av7110;
>         av7110_check_ir_config(av7110, true);
>
> -       setup_timer(&av7110->ir.keyup_timer, av7110_emit_keyup,
> -                   (unsigned long)&av7110->ir);
> +       timer_setup(&av7110->ir.keyup_timer, av7110_emit_keyup, 0);
>
>         input_dev = input_allocate_device();
>         if (!input_dev)
> --
> 2.15.0.rc0.271.g36b669edcc-goog
>
>
> --
> Dmitry
kernel test robot Oct. 26, 2017, 6:27 p.m. UTC | #2
Hi Dmitry,

Thank you for the patch! Yet we hit a small issue.
[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.14-rc6 next-20171018]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Dmitry-Torokhov/media-av7110-switch-to-useing-timer_setup/20171027-014646
base:   git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-x001-201743 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/list.h:8:0,
                    from include/linux/module.h:9,
                    from drivers/media//pci/ttpci/av7110_ir.c:24:
   drivers/media//pci/ttpci/av7110_ir.c: In function 'av7110_emit_keyup':
>> drivers/media//pci/ttpci/av7110_ir.c:89:39: error: 'keyup_timer' undeclared (first use in this function)
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                                          ^
   include/linux/kernel.h:927:26: note: in definition of macro 'container_of'
     void *__mptr = (void *)(ptr);     \
                             ^~~
>> drivers/media//pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   drivers/media//pci/ttpci/av7110_ir.c:89:39: note: each undeclared identifier is reported only once for each function it appears in
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                                          ^
   include/linux/kernel.h:927:26: note: in definition of macro 'container_of'
     void *__mptr = (void *)(ptr);     \
                             ^~~
>> drivers/media//pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from drivers/media//pci/ttpci/av7110_ir.c:22:
>> include/linux/kernel.h:928:51: error: 'struct infrared' has no member named 't'
     BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
                                                      ^
   include/linux/compiler.h:553:19: note: in definition of macro '__compiletime_assert'
      bool __cond = !(condition);    \
                      ^~~~~~~~~
   include/linux/compiler.h:576:2: note: in expansion of macro '_compiletime_assert'
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
     ^~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:46:37: note: in expansion of macro 'compiletime_assert'
    #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
                                        ^~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:928:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
     BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
     ^~~~~~~~~~~~~~~~
   include/linux/kernel.h:928:20: note: in expansion of macro '__same_type'
     BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
                       ^~~~~~~~~~~
   include/linux/timer.h:183:2: note: in expansion of macro 'container_of'
     container_of(callback_timer, typeof(*var), timer_fieldname)
     ^~~~~~~~~~~~
>> drivers/media//pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   In file included from include/linux/compiler.h:58:0,
                    from include/uapi/linux/stddef.h:1,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from drivers/media//pci/ttpci/av7110_ir.c:22:
>> include/linux/compiler-gcc.h:165:2: error: 'struct infrared' has no member named 't'
     __builtin_offsetof(a, b)
     ^
   include/linux/stddef.h:16:32: note: in expansion of macro '__compiler_offsetof'
    #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
                                   ^~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:931:21: note: in expansion of macro 'offsetof'
     ((type *)(__mptr - offsetof(type, member))); })
                        ^~~~~~~~
   include/linux/timer.h:183:2: note: in expansion of macro 'container_of'
     container_of(callback_timer, typeof(*var), timer_fieldname)
     ^~~~~~~~~~~~
>> drivers/media//pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   drivers/media//pci/ttpci/av7110_ir.c: In function 'av7110_ir_init':
>> drivers/media//pci/ttpci/av7110_ir.c:364:30: error: 'input_repeat_key' undeclared (first use in this function)
     input_dev->timer.function = input_repeat_key;
                                 ^~~~~~~~~~~~~~~~
--
   In file included from include/linux/list.h:8:0,
                    from include/linux/module.h:9,
                    from drivers/media/pci/ttpci/av7110_ir.c:24:
   drivers/media/pci/ttpci/av7110_ir.c: In function 'av7110_emit_keyup':
   drivers/media/pci/ttpci/av7110_ir.c:89:39: error: 'keyup_timer' undeclared (first use in this function)
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                                          ^
   include/linux/kernel.h:927:26: note: in definition of macro 'container_of'
     void *__mptr = (void *)(ptr);     \
                             ^~~
   drivers/media/pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   drivers/media/pci/ttpci/av7110_ir.c:89:39: note: each undeclared identifier is reported only once for each function it appears in
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                                          ^
   include/linux/kernel.h:927:26: note: in definition of macro 'container_of'
     void *__mptr = (void *)(ptr);     \
                             ^~~
   drivers/media/pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from drivers/media/pci/ttpci/av7110_ir.c:22:
>> include/linux/kernel.h:928:51: error: 'struct infrared' has no member named 't'
     BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
                                                      ^
   include/linux/compiler.h:553:19: note: in definition of macro '__compiletime_assert'
      bool __cond = !(condition);    \
                      ^~~~~~~~~
   include/linux/compiler.h:576:2: note: in expansion of macro '_compiletime_assert'
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
     ^~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:46:37: note: in expansion of macro 'compiletime_assert'
    #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
                                        ^~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:928:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
     BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
     ^~~~~~~~~~~~~~~~
   include/linux/kernel.h:928:20: note: in expansion of macro '__same_type'
     BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
                       ^~~~~~~~~~~
   include/linux/timer.h:183:2: note: in expansion of macro 'container_of'
     container_of(callback_timer, typeof(*var), timer_fieldname)
     ^~~~~~~~~~~~
   drivers/media/pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   In file included from include/linux/compiler.h:58:0,
                    from include/uapi/linux/stddef.h:1,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from drivers/media/pci/ttpci/av7110_ir.c:22:
>> include/linux/compiler-gcc.h:165:2: error: 'struct infrared' has no member named 't'
     __builtin_offsetof(a, b)
     ^
   include/linux/stddef.h:16:32: note: in expansion of macro '__compiler_offsetof'
    #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
                                   ^~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:931:21: note: in expansion of macro 'offsetof'
     ((type *)(__mptr - offsetof(type, member))); })
                        ^~~~~~~~
   include/linux/timer.h:183:2: note: in expansion of macro 'container_of'
     container_of(callback_timer, typeof(*var), timer_fieldname)
     ^~~~~~~~~~~~
   drivers/media/pci/ttpci/av7110_ir.c:89:24: note: in expansion of macro 'from_timer'
     struct infrared *ir = from_timer(ir, keyup_timer, t);
                           ^~~~~~~~~~
   drivers/media/pci/ttpci/av7110_ir.c: In function 'av7110_ir_init':
   drivers/media/pci/ttpci/av7110_ir.c:364:30: error: 'input_repeat_key' undeclared (first use in this function)
     input_dev->timer.function = input_repeat_key;
                                 ^~~~~~~~~~~~~~~~

vim +/keyup_timer +89 drivers/media//pci/ttpci/av7110_ir.c

  > 24	#include <linux/module.h>
    25	#include <linux/proc_fs.h>
    26	#include <linux/kernel.h>
    27	#include <linux/bitops.h>
    28	
    29	#include "av7110.h"
    30	#include "av7110_hw.h"
    31	
    32	
    33	#define AV_CNT		4
    34	
    35	#define IR_RC5		0
    36	#define IR_RCMM		1
    37	#define IR_RC5_EXT	2 /* internal only */
    38	
    39	#define IR_ALL		0xffffffff
    40	
    41	#define UP_TIMEOUT	(HZ*7/25)
    42	
    43	
    44	/* Note: enable ir debugging by or'ing debug with 16 */
    45	
    46	static int ir_protocol[AV_CNT] = { IR_RCMM, IR_RCMM, IR_RCMM, IR_RCMM};
    47	module_param_array(ir_protocol, int, NULL, 0644);
    48	MODULE_PARM_DESC(ir_protocol, "Infrared protocol: 0 RC5, 1 RCMM (default)");
    49	
    50	static int ir_inversion[AV_CNT];
    51	module_param_array(ir_inversion, int, NULL, 0644);
    52	MODULE_PARM_DESC(ir_inversion, "Inversion of infrared signal: 0 not inverted (default), 1 inverted");
    53	
    54	static uint ir_device_mask[AV_CNT] = { IR_ALL, IR_ALL, IR_ALL, IR_ALL };
    55	module_param_array(ir_device_mask, uint, NULL, 0644);
    56	MODULE_PARM_DESC(ir_device_mask, "Bitmask of infrared devices: bit 0..31 = device 0..31 (default: all)");
    57	
    58	
    59	static int av_cnt;
    60	static struct av7110 *av_list[AV_CNT];
    61	
    62	static u16 default_key_map [256] = {
    63		KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
    64		KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
    65		KEY_VOLUMEUP, KEY_VOLUMEDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    66		KEY_CHANNELUP, KEY_CHANNELDOWN, 0, 0, 0, 0, 0, 0,
    67		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    68		0, 0, 0, 0, KEY_TEXT, 0, 0, KEY_TV, 0, 0, 0, 0, 0, KEY_SETUP, 0, 0,
    69		0, 0, 0, KEY_SUBTITLE, 0, 0, KEY_LANGUAGE, 0,
    70		KEY_RADIO, 0, 0, 0, 0, KEY_EXIT, 0, 0,
    71		KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_OK, 0, 0, 0,
    72		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RED, KEY_GREEN, KEY_YELLOW,
    73		KEY_BLUE, 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_LIST, 0, 0, 0, 0, 0, 0,
    74		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    75		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    76		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    77		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    78		0, 0, 0, 0, KEY_UP, KEY_UP, KEY_DOWN, KEY_DOWN,
    79		0, 0, 0, 0, KEY_EPG, 0, 0, 0,
    80		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    81		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    82		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_VCR
    83	};
    84	
    85	
    86	/* key-up timer */
    87	static void av7110_emit_keyup(struct timer_list *t)
    88	{
  > 89		struct infrared *ir = from_timer(ir, keyup_timer, t);
    90	
    91		if (!ir || !test_bit(ir->last_key, ir->input_dev->key))
    92			return;
    93	
    94		input_report_key(ir->input_dev, ir->last_key, 0);
    95		input_sync(ir->input_dev);
    96	}
    97	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Kees Cook Oct. 30, 2017, 10:14 p.m. UTC | #3
On Tue, Oct 24, 2017 at 5:40 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> In preparation for unconditionally passing the struct timer_list pointer to
> all timer callbacks, switch to using the new timer_setup() and from_timer()
> to pass the timer pointer explicitly.
>
> Also stop poking into input core internals and override its autorepeat
> timer function. I am not sure why we have such convoluted autorepeat
> handling in this driver instead of letting input core handle autorepeat,
> but this preserves current behavior of allowing controlling autorepeat
> delay and forcing autorepeat period to be whatever the hardware has.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Reviewed-by: Kees Cook <keescook@chromium.org>
(with the Subject typo fixed)

Hans, since this depends on the input side not changing first, I think
it makes sense for Dmitry to carry this in the Input tree before the
Input timer updates. Would that be okay?

Thanks!

-Kees

> ---
>
> Note that this has not been tested on the hardware. But it should
> compile, so I have that going for me.
>
>  drivers/media/pci/ttpci/av7110.h    |  4 ++--
>  drivers/media/pci/ttpci/av7110_ir.c | 40 +++++++++++++++++--------------------
>  2 files changed, 20 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h
> index 347827925c14..0aa3c6f01853 100644
> --- a/drivers/media/pci/ttpci/av7110.h
> +++ b/drivers/media/pci/ttpci/av7110.h
> @@ -80,10 +80,11 @@ struct av7110;
>
>  /* infrared remote control */
>  struct infrared {
> -       u16     key_map[256];
> +       u16                     key_map[256];
>         struct input_dev        *input_dev;
>         char                    input_phys[32];
>         struct timer_list       keyup_timer;
> +       unsigned long           keydown_time;
>         struct tasklet_struct   ir_tasklet;
>         void                    (*ir_handler)(struct av7110 *av7110, u32 ircom);
>         u32                     ir_command;
> @@ -93,7 +94,6 @@ struct infrared {
>         u8                      inversion;
>         u16                     last_key;
>         u16                     last_toggle;
> -       u8                      delay_timer_finished;
>  };
>
>
> diff --git a/drivers/media/pci/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c
> index ca05198de2c2..b602e64b3412 100644
> --- a/drivers/media/pci/ttpci/av7110_ir.c
> +++ b/drivers/media/pci/ttpci/av7110_ir.c
> @@ -84,9 +84,9 @@ static u16 default_key_map [256] = {
>
>
>  /* key-up timer */
> -static void av7110_emit_keyup(unsigned long parm)
> +static void av7110_emit_keyup(struct timer_list *t)
>  {
> -       struct infrared *ir = (struct infrared *) parm;
> +       struct infrared *ir = from_timer(ir, keyup_timer, t);
>
>         if (!ir || !test_bit(ir->last_key, ir->input_dev->key))
>                 return;
> @@ -152,19 +152,20 @@ static void av7110_emit_key(unsigned long parm)
>                 return;
>         }
>
> -       if (timer_pending(&ir->keyup_timer)) {
> -               del_timer(&ir->keyup_timer);
> +       if (del_timer(&ir->keyup_timer)) {
>                 if (ir->last_key != keycode || toggle != ir->last_toggle) {
> -                       ir->delay_timer_finished = 0;
> +                       ir->keydown_time = jiffies;
>                         input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
>                         input_event(ir->input_dev, EV_KEY, keycode, 1);
>                         input_sync(ir->input_dev);
> -               } else if (ir->delay_timer_finished) {
> +               } else if (time_after(jiffies, ir->keydown_time +
> +                               msecs_to_jiffies(
> +                                       ir->input_dev->rep[REP_PERIOD]))) {
>                         input_event(ir->input_dev, EV_KEY, keycode, 2);
>                         input_sync(ir->input_dev);
>                 }
>         } else {
> -               ir->delay_timer_finished = 0;
> +               ir->keydown_time = jiffies;
>                 input_event(ir->input_dev, EV_KEY, keycode, 1);
>                 input_sync(ir->input_dev);
>         }
> @@ -172,9 +173,7 @@ static void av7110_emit_key(unsigned long parm)
>         ir->last_key = keycode;
>         ir->last_toggle = toggle;
>
> -       ir->keyup_timer.expires = jiffies + UP_TIMEOUT;
> -       add_timer(&ir->keyup_timer);
> -
> +       mod_timer(&ir->keyup_timer, jiffies + UP_TIMEOUT);
>  }
>
>
> @@ -184,12 +183,19 @@ static void input_register_keys(struct infrared *ir)
>         int i;
>
>         set_bit(EV_KEY, ir->input_dev->evbit);
> -       set_bit(EV_REP, ir->input_dev->evbit);
>         set_bit(EV_MSC, ir->input_dev->evbit);
>
>         set_bit(MSC_RAW, ir->input_dev->mscbit);
>         set_bit(MSC_SCAN, ir->input_dev->mscbit);
>
> +       set_bit(EV_REP, ir->input_dev->evbit);
> +       /*
> +        * By setting the delay before registering input device we
> +        * indicate that we will be implementing the autorepeat
> +        * ourselves.
> +        */
> +       ir->input_dev->rep[REP_DELAY] = 250;
> +
>         memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
>
>         for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) {
> @@ -205,15 +211,6 @@ static void input_register_keys(struct infrared *ir)
>  }
>
>
> -/* called by the input driver after rep[REP_DELAY] ms */
> -static void input_repeat_key(unsigned long parm)
> -{
> -       struct infrared *ir = (struct infrared *) parm;
> -
> -       ir->delay_timer_finished = 1;
> -}
> -
> -
>  /* check for configuration changes */
>  int av7110_check_ir_config(struct av7110 *av7110, int force)
>  {
> @@ -333,8 +330,7 @@ int av7110_ir_init(struct av7110 *av7110)
>         av_list[av_cnt++] = av7110;
>         av7110_check_ir_config(av7110, true);
>
> -       setup_timer(&av7110->ir.keyup_timer, av7110_emit_keyup,
> -                   (unsigned long)&av7110->ir);
> +       timer_setup(&av7110->ir.keyup_timer, av7110_emit_keyup, 0);
>
>         input_dev = input_allocate_device();
>         if (!input_dev)
> --
> 2.15.0.rc0.271.g36b669edcc-goog
>
>
> --
> Dmitry
Sean Young Oct. 31, 2017, 5:27 p.m. UTC | #4
On Tue, Oct 24, 2017 at 05:40:05PM -0700, Dmitry Torokhov wrote:
> In preparation for unconditionally passing the struct timer_list pointer to
> all timer callbacks, switch to using the new timer_setup() and from_timer()
> to pass the timer pointer explicitly.
> 
> Also stop poking into input core internals and override its autorepeat
> timer function. I am not sure why we have such convoluted autorepeat
> handling in this driver instead of letting input core handle autorepeat,
> but this preserves current behavior of allowing controlling autorepeat
> delay and forcing autorepeat period to be whatever the hardware has.

I think a better solution is to remove the autorepeat handling completely,
and leave it up to the input layer. This simplies the driver greatly and
I don't see how this makes sense for an IR driver. The IR protocols
specify the IR should repeat the message at set intervals whilst a 
button is pressed; this has no relation to autorepeat.

Ideally this driver would be converted to rc-core, but without access to
the hardware I'm not sure that is a great idea. The keymap handling is
very convolated so I have no idea what the scancodes for the remote(s) are,
for example. Any suggestions for what hardware to get off ebay for this?

New patch will be reply this.

Thanks,

Sean
Mauro Carvalho Chehab Oct. 31, 2017, 6:14 p.m. UTC | #5
Em Tue, 31 Oct 2017 17:27:58 +0000
Sean Young <sean@mess.org> escreveu:

> On Tue, Oct 24, 2017 at 05:40:05PM -0700, Dmitry Torokhov wrote:
> > In preparation for unconditionally passing the struct timer_list pointer to
> > all timer callbacks, switch to using the new timer_setup() and from_timer()
> > to pass the timer pointer explicitly.
> > 
> > Also stop poking into input core internals and override its autorepeat
> > timer function. I am not sure why we have such convoluted autorepeat
> > handling in this driver instead of letting input core handle autorepeat,
> > but this preserves current behavior of allowing controlling autorepeat
> > delay and forcing autorepeat period to be whatever the hardware has.  

IR devices basically have only something equivalent to key press events.
They don't have key release ones.

Depending on the device and on the IR protocol, they may have extra events
when a key is kept pressed.

I've seen two types of IR devices: the ones that emit an special "repeat"
event (usually on every 100ms-200ms if a key is kept pressing) and the
ones that just repeat the key's scan code if the key is kept pressed.

The way IR drivers current work is that they send a key press event when
a key is pressed, and if no repeat event happens on an expected time, it
sends a release event.

Thanks,
Mauro
diff mbox

Patch

diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h
index 347827925c14..0aa3c6f01853 100644
--- a/drivers/media/pci/ttpci/av7110.h
+++ b/drivers/media/pci/ttpci/av7110.h
@@ -80,10 +80,11 @@  struct av7110;
 
 /* infrared remote control */
 struct infrared {
-	u16	key_map[256];
+	u16			key_map[256];
 	struct input_dev	*input_dev;
 	char			input_phys[32];
 	struct timer_list	keyup_timer;
+	unsigned long		keydown_time;
 	struct tasklet_struct	ir_tasklet;
 	void			(*ir_handler)(struct av7110 *av7110, u32 ircom);
 	u32			ir_command;
@@ -93,7 +94,6 @@  struct infrared {
 	u8			inversion;
 	u16			last_key;
 	u16			last_toggle;
-	u8			delay_timer_finished;
 };
 
 
diff --git a/drivers/media/pci/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c
index ca05198de2c2..b602e64b3412 100644
--- a/drivers/media/pci/ttpci/av7110_ir.c
+++ b/drivers/media/pci/ttpci/av7110_ir.c
@@ -84,9 +84,9 @@  static u16 default_key_map [256] = {
 
 
 /* key-up timer */
-static void av7110_emit_keyup(unsigned long parm)
+static void av7110_emit_keyup(struct timer_list *t)
 {
-	struct infrared *ir = (struct infrared *) parm;
+	struct infrared *ir = from_timer(ir, keyup_timer, t);
 
 	if (!ir || !test_bit(ir->last_key, ir->input_dev->key))
 		return;
@@ -152,19 +152,20 @@  static void av7110_emit_key(unsigned long parm)
 		return;
 	}
 
-	if (timer_pending(&ir->keyup_timer)) {
-		del_timer(&ir->keyup_timer);
+	if (del_timer(&ir->keyup_timer)) {
 		if (ir->last_key != keycode || toggle != ir->last_toggle) {
-			ir->delay_timer_finished = 0;
+			ir->keydown_time = jiffies;
 			input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
 			input_event(ir->input_dev, EV_KEY, keycode, 1);
 			input_sync(ir->input_dev);
-		} else if (ir->delay_timer_finished) {
+		} else if (time_after(jiffies, ir->keydown_time +
+				msecs_to_jiffies(
+					ir->input_dev->rep[REP_PERIOD]))) {
 			input_event(ir->input_dev, EV_KEY, keycode, 2);
 			input_sync(ir->input_dev);
 		}
 	} else {
-		ir->delay_timer_finished = 0;
+		ir->keydown_time = jiffies;
 		input_event(ir->input_dev, EV_KEY, keycode, 1);
 		input_sync(ir->input_dev);
 	}
@@ -172,9 +173,7 @@  static void av7110_emit_key(unsigned long parm)
 	ir->last_key = keycode;
 	ir->last_toggle = toggle;
 
-	ir->keyup_timer.expires = jiffies + UP_TIMEOUT;
-	add_timer(&ir->keyup_timer);
-
+	mod_timer(&ir->keyup_timer, jiffies + UP_TIMEOUT);
 }
 
 
@@ -184,12 +183,19 @@  static void input_register_keys(struct infrared *ir)
 	int i;
 
 	set_bit(EV_KEY, ir->input_dev->evbit);
-	set_bit(EV_REP, ir->input_dev->evbit);
 	set_bit(EV_MSC, ir->input_dev->evbit);
 
 	set_bit(MSC_RAW, ir->input_dev->mscbit);
 	set_bit(MSC_SCAN, ir->input_dev->mscbit);
 
+	set_bit(EV_REP, ir->input_dev->evbit);
+	/*
+	 * By setting the delay before registering input device we
+	 * indicate that we will be implementing the autorepeat
+	 * ourselves.
+	 */
+	ir->input_dev->rep[REP_DELAY] = 250;
+
 	memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
 
 	for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) {
@@ -205,15 +211,6 @@  static void input_register_keys(struct infrared *ir)
 }
 
 
-/* called by the input driver after rep[REP_DELAY] ms */
-static void input_repeat_key(unsigned long parm)
-{
-	struct infrared *ir = (struct infrared *) parm;
-
-	ir->delay_timer_finished = 1;
-}
-
-
 /* check for configuration changes */
 int av7110_check_ir_config(struct av7110 *av7110, int force)
 {
@@ -333,8 +330,7 @@  int av7110_ir_init(struct av7110 *av7110)
 	av_list[av_cnt++] = av7110;
 	av7110_check_ir_config(av7110, true);
 
-	setup_timer(&av7110->ir.keyup_timer, av7110_emit_keyup,
-		    (unsigned long)&av7110->ir);
+	timer_setup(&av7110->ir.keyup_timer, av7110_emit_keyup, 0);
 
 	input_dev = input_allocate_device();
 	if (!input_dev)