aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorH Hartley Sweeten <hartleys@visionengravers.com>2009-04-17 20:12:35 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-04-17 20:37:21 -0700
commitbd3ce6556072bdc8ea66dfd5448e184f189bdc7f (patch)
tree264a0272647abe0ae4a7093abb3d6afc9b0a1bd2 /drivers
parent3f3e7c6e139f704e2f48ea3b45ff7724a8d46456 (diff)
Input: rotary_encoder - add support for REL_* axes
The rotary encoder driver only supports returning input events for ABS_* axes, this adds support for REL_* axes. The relative axis input event is reported as -1 for each counter-clockwise step and +1 for each clockwise step. The ability to clamp the position of ABS_* axes between 0 and a maximum of "steps" has also been added. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/misc/rotary_encoder.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index 5bb3ab51b8c..c806fbf1e17 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -26,13 +26,17 @@
#define DRV_NAME "rotary-encoder"
struct rotary_encoder {
- unsigned int irq_a;
- unsigned int irq_b;
- unsigned int pos;
- unsigned int armed;
- unsigned int dir;
struct input_dev *input;
struct rotary_encoder_platform_data *pdata;
+
+ unsigned int axis;
+ unsigned int pos;
+
+ unsigned int irq_a;
+ unsigned int irq_b;
+
+ bool armed;
+ unsigned char dir; /* 0 - clockwise, 1 - CCW */
};
static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
@@ -53,21 +57,32 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
if (!encoder->armed)
break;
- if (encoder->dir) {
- /* turning counter-clockwise */
- encoder->pos += pdata->steps;
- encoder->pos--;
- encoder->pos %= pdata->steps;
+ if (pdata->relative_axis) {
+ input_report_rel(encoder->input, pdata->axis,
+ encoder->dir ? -1 : 1);
} else {
- /* turning clockwise */
- encoder->pos++;
- encoder->pos %= pdata->steps;
+ 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->rollover)
+ pos %= pdata->steps;
+ encoder->pos = pos;
+ input_report_abs(encoder->input, pdata->axis,
+ encoder->pos);
}
-
- input_report_abs(encoder->input, pdata->axis, encoder->pos);
input_sync(encoder->input);
- encoder->armed = 0;
+ encoder->armed = false;
break;
case 0x1:
@@ -77,7 +92,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
break;
case 0x3:
- encoder->armed = 1;
+ encoder->armed = true;
break;
}
@@ -113,9 +128,15 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
input->name = pdev->name;
input->id.bustype = BUS_HOST;
input->dev.parent = &pdev->dev;
- input->evbit[0] = BIT_MASK(EV_ABS);
- input_set_abs_params(encoder->input,
- pdata->axis, 0, pdata->steps, 0, 1);
+
+ if (pdata->relative_axis) {
+ input->evbit[0] = BIT_MASK(EV_REL);
+ input->relbit[0] = BIT_MASK(pdata->axis);
+ } else {
+ input->evbit[0] = BIT_MASK(EV_ABS);
+ input_set_abs_params(encoder->input,
+ pdata->axis, 0, pdata->steps, 0, 1);
+ }
err = input_register_device(input);
if (err) {