diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/misc/rotary_encoder.c | 77 |
1 files changed, 44 insertions, 33 deletions
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 7e64d01..077b80b 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -40,50 +40,62 @@ struct rotary_encoder { unsigned char dir; /* 0 - clockwise, 1 - CCW */ }; -static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) +static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) { - struct rotary_encoder *encoder = dev_id; - struct rotary_encoder_platform_data *pdata = encoder->pdata; int a = !!gpio_get_value(pdata->gpio_a); int b = !!gpio_get_value(pdata->gpio_b); - int state; a ^= pdata->inverted_a; b ^= pdata->inverted_b; - state = (a << 1) | b; - switch (state) { + return ((a << 1) | b); +} - case 0x0: - if (!encoder->armed) - break; +static void rotary_encoder_report_event(struct rotary_encoder *encoder) +{ + struct rotary_encoder_platform_data *pdata = encoder->pdata; - if (pdata->relative_axis) { - input_report_rel(encoder->input, pdata->axis, - encoder->dir ? -1 : 1); - } else { - unsigned int pos = encoder->pos; - - if (encoder->dir) { - /* turning counter-clockwise */ - if (pdata->rollover) - pos += pdata->steps; - if (pos) - pos--; - } else { - /* turning clockwise */ - if (pdata->rollover || pos < pdata->steps) - pos++; - } + if (pdata->relative_axis) { + input_report_rel(encoder->input, + pdata->axis, encoder->dir ? -1 : 1); + } else { + unsigned int pos = encoder->pos; + + if (encoder->dir) { + /* turning counter-clockwise */ if (pdata->rollover) - pos %= pdata->steps; - encoder->pos = pos; - input_report_abs(encoder->input, pdata->axis, - encoder->pos); + pos += pdata->steps; + if (pos) + pos--; + } else { + /* turning clockwise */ + if (pdata->rollover || pos < pdata->steps) + pos++; } - input_sync(encoder->input); - encoder->armed = false; + if (pdata->rollover) + pos %= pdata->steps; + + encoder->pos = pos; + input_report_abs(encoder->input, pdata->axis, encoder->pos); + } + + input_sync(encoder->input); +} + +static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) +{ + struct rotary_encoder *encoder = dev_id; + int state; + + state = rotary_encoder_get_state(encoder->pdata); + + switch (state) { + case 0x0: + if (encoder->armed) { + rotary_encoder_report_event(encoder); + encoder->armed = false; + } break; case 0x1: @@ -254,4 +266,3 @@ MODULE_ALIAS("platform:" DRV_NAME); MODULE_DESCRIPTION("GPIO rotary encoder driver"); MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); MODULE_LICENSE("GPL v2"); - |