mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
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>
This commit is contained in:
parent
3f3e7c6e13
commit
bd3ce65560
3 changed files with 51 additions and 21 deletions
|
@ -67,7 +67,12 @@ data with it.
|
||||||
struct rotary_encoder_platform_data is declared in
|
struct rotary_encoder_platform_data is declared in
|
||||||
include/linux/rotary-encoder.h and needs to be filled with the number of
|
include/linux/rotary-encoder.h and needs to be filled with the number of
|
||||||
steps the encoder has and can carry information about externally inverted
|
steps the encoder has and can carry information about externally inverted
|
||||||
signals (because of used invertig buffer or other reasons).
|
signals (because of an inverting buffer or other reasons). The encoder
|
||||||
|
can be set up to deliver input information as either an absolute or relative
|
||||||
|
axes. For relative axes the input event returns +/-1 for each step. For
|
||||||
|
absolute axes the position of the encoder can either roll over between zero
|
||||||
|
and the number of steps or will clamp at the maximum and zero depending on
|
||||||
|
the configuration.
|
||||||
|
|
||||||
Because GPIO to IRQ mapping is platform specific, this information must
|
Because GPIO to IRQ mapping is platform specific, this information must
|
||||||
be given in seperately to the driver. See the example below.
|
be given in seperately to the driver. See the example below.
|
||||||
|
@ -85,6 +90,8 @@ be given in seperately to the driver. See the example below.
|
||||||
static struct rotary_encoder_platform_data my_rotary_encoder_info = {
|
static struct rotary_encoder_platform_data my_rotary_encoder_info = {
|
||||||
.steps = 24,
|
.steps = 24,
|
||||||
.axis = ABS_X,
|
.axis = ABS_X,
|
||||||
|
.relative_axis = false,
|
||||||
|
.rollover = false,
|
||||||
.gpio_a = GPIO_ROTARY_A,
|
.gpio_a = GPIO_ROTARY_A,
|
||||||
.gpio_b = GPIO_ROTARY_B,
|
.gpio_b = GPIO_ROTARY_B,
|
||||||
.inverted_a = 0,
|
.inverted_a = 0,
|
||||||
|
|
|
@ -26,13 +26,17 @@
|
||||||
#define DRV_NAME "rotary-encoder"
|
#define DRV_NAME "rotary-encoder"
|
||||||
|
|
||||||
struct 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 input_dev *input;
|
||||||
struct rotary_encoder_platform_data *pdata;
|
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)
|
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)
|
if (!encoder->armed)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (encoder->dir) {
|
if (pdata->relative_axis) {
|
||||||
/* turning counter-clockwise */
|
input_report_rel(encoder->input, pdata->axis,
|
||||||
encoder->pos += pdata->steps;
|
encoder->dir ? -1 : 1);
|
||||||
encoder->pos--;
|
|
||||||
encoder->pos %= pdata->steps;
|
|
||||||
} else {
|
} else {
|
||||||
/* turning clockwise */
|
unsigned int pos = encoder->pos;
|
||||||
encoder->pos++;
|
|
||||||
encoder->pos %= pdata->steps;
|
|
||||||
}
|
|
||||||
|
|
||||||
input_report_abs(encoder->input, pdata->axis, 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_sync(encoder->input);
|
input_sync(encoder->input);
|
||||||
|
|
||||||
encoder->armed = 0;
|
encoder->armed = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1:
|
case 0x1:
|
||||||
|
@ -77,7 +92,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3:
|
case 0x3:
|
||||||
encoder->armed = 1;
|
encoder->armed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,9 +128,15 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
||||||
input->name = pdev->name;
|
input->name = pdev->name;
|
||||||
input->id.bustype = BUS_HOST;
|
input->id.bustype = BUS_HOST;
|
||||||
input->dev.parent = &pdev->dev;
|
input->dev.parent = &pdev->dev;
|
||||||
input->evbit[0] = BIT_MASK(EV_ABS);
|
|
||||||
input_set_abs_params(encoder->input,
|
if (pdata->relative_axis) {
|
||||||
pdata->axis, 0, pdata->steps, 0, 1);
|
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);
|
err = input_register_device(input);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -8,6 +8,8 @@ struct rotary_encoder_platform_data {
|
||||||
unsigned int gpio_b;
|
unsigned int gpio_b;
|
||||||
unsigned int inverted_a;
|
unsigned int inverted_a;
|
||||||
unsigned int inverted_b;
|
unsigned int inverted_b;
|
||||||
|
bool relative_axis;
|
||||||
|
bool rollover;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ROTARY_ENCODER_H__ */
|
#endif /* __ROTARY_ENCODER_H__ */
|
||||||
|
|
Loading…
Reference in a new issue