|
@@ -121,11 +121,9 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
|
|
|
int position[3];
|
|
|
int i;
|
|
|
|
|
|
- mutex_lock(&lis3->mutex);
|
|
|
position[0] = lis3->read_data(lis3, OUTX);
|
|
|
position[1] = lis3->read_data(lis3, OUTY);
|
|
|
position[2] = lis3->read_data(lis3, OUTZ);
|
|
|
- mutex_unlock(&lis3->mutex);
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
|
|
@@ -249,6 +247,19 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
|
|
|
EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
|
|
|
|
|
|
|
|
|
+static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
|
|
|
+{
|
|
|
+ int x, y, z;
|
|
|
+
|
|
|
+ mutex_lock(&lis3_dev.mutex);
|
|
|
+ lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
|
|
|
+ input_report_abs(pidev->input, ABS_X, x);
|
|
|
+ input_report_abs(pidev->input, ABS_Y, y);
|
|
|
+ input_report_abs(pidev->input, ABS_Z, z);
|
|
|
+ input_sync(pidev->input);
|
|
|
+ mutex_unlock(&lis3_dev.mutex);
|
|
|
+}
|
|
|
+
|
|
|
static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
|
|
|
{
|
|
|
if (!test_bit(0, &lis3_dev.misc_opened))
|
|
@@ -270,13 +281,71 @@ out:
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
+static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
|
|
|
+{
|
|
|
+ struct input_dev *dev = lis3->idev->input;
|
|
|
+ u8 click_src;
|
|
|
+
|
|
|
+ mutex_lock(&lis3->mutex);
|
|
|
+ lis3->read(lis3, CLICK_SRC, &click_src);
|
|
|
+
|
|
|
+ if (click_src & CLICK_SINGLE_X) {
|
|
|
+ input_report_key(dev, lis3->mapped_btns[0], 1);
|
|
|
+ input_report_key(dev, lis3->mapped_btns[0], 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (click_src & CLICK_SINGLE_Y) {
|
|
|
+ input_report_key(dev, lis3->mapped_btns[1], 1);
|
|
|
+ input_report_key(dev, lis3->mapped_btns[1], 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (click_src & CLICK_SINGLE_Z) {
|
|
|
+ input_report_key(dev, lis3->mapped_btns[2], 1);
|
|
|
+ input_report_key(dev, lis3->mapped_btns[2], 0);
|
|
|
+ }
|
|
|
+ input_sync(dev);
|
|
|
+ mutex_unlock(&lis3->mutex);
|
|
|
+}
|
|
|
+
|
|
|
+static void lis302dl_interrupt_handle_ff_wu(struct lis3lv02d *lis3)
|
|
|
+{
|
|
|
+ u8 wu1_src;
|
|
|
+ u8 wu2_src;
|
|
|
+
|
|
|
+ lis3->read(lis3, FF_WU_SRC_1, &wu1_src);
|
|
|
+ lis3->read(lis3, FF_WU_SRC_2, &wu2_src);
|
|
|
+
|
|
|
+ wu1_src = wu1_src & FF_WU_SRC_IA ? wu1_src : 0;
|
|
|
+ wu2_src = wu2_src & FF_WU_SRC_IA ? wu2_src : 0;
|
|
|
+
|
|
|
+ /* joystick poll is internally protected by the lis3->mutex. */
|
|
|
+ if (wu1_src || wu2_src)
|
|
|
+ lis3lv02d_joystick_poll(lis3_dev.idev);
|
|
|
+}
|
|
|
+
|
|
|
static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
|
|
|
{
|
|
|
+
|
|
|
+ struct lis3lv02d *lis3 = data;
|
|
|
+
|
|
|
+ if ((lis3->pdata->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
|
|
|
+ lis302dl_interrupt_handle_click(lis3);
|
|
|
+ else
|
|
|
+ lis302dl_interrupt_handle_ff_wu(lis3);
|
|
|
+
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
|
|
|
{
|
|
|
+
|
|
|
+ struct lis3lv02d *lis3 = data;
|
|
|
+
|
|
|
+ if ((lis3->pdata->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
|
|
|
+ lis302dl_interrupt_handle_click(lis3);
|
|
|
+ else
|
|
|
+ lis302dl_interrupt_handle_ff_wu(lis3);
|
|
|
+
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
@@ -374,22 +443,12 @@ static struct miscdevice lis3lv02d_misc_device = {
|
|
|
.fops = &lis3lv02d_misc_fops,
|
|
|
};
|
|
|
|
|
|
-static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
|
|
|
-{
|
|
|
- int x, y, z;
|
|
|
-
|
|
|
- lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
|
|
|
- input_report_abs(pidev->input, ABS_X, x);
|
|
|
- input_report_abs(pidev->input, ABS_Y, y);
|
|
|
- input_report_abs(pidev->input, ABS_Z, z);
|
|
|
- input_sync(pidev->input);
|
|
|
-}
|
|
|
-
|
|
|
int lis3lv02d_joystick_enable(void)
|
|
|
{
|
|
|
struct input_dev *input_dev;
|
|
|
int err;
|
|
|
int max_val, fuzz, flat;
|
|
|
+ int btns[] = {BTN_X, BTN_Y, BTN_Z};
|
|
|
|
|
|
if (lis3_dev.idev)
|
|
|
return -EINVAL;
|
|
@@ -416,6 +475,10 @@ int lis3lv02d_joystick_enable(void)
|
|
|
input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
|
|
|
input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
|
|
|
|
|
|
+ lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
|
|
|
+ lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
|
|
|
+ lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
|
|
|
+
|
|
|
err = input_register_polled_device(lis3_dev.idev);
|
|
|
if (err) {
|
|
|
input_free_polled_device(lis3_dev.idev);
|
|
@@ -461,7 +524,9 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
|
|
|
{
|
|
|
int x, y, z;
|
|
|
|
|
|
+ mutex_lock(&lis3_dev.mutex);
|
|
|
lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
|
|
|
+ mutex_unlock(&lis3_dev.mutex);
|
|
|
return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
|
|
|
}
|
|
|
|
|
@@ -535,6 +600,13 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
|
|
|
dev->write(dev, CLICK_THSY_X,
|
|
|
(p->click_thresh_x & 0xf) |
|
|
|
(p->click_thresh_y << 4));
|
|
|
+
|
|
|
+ if (dev->idev) {
|
|
|
+ struct input_dev *input_dev = lis3_dev.idev->input;
|
|
|
+ input_set_capability(input_dev, EV_KEY, BTN_X);
|
|
|
+ input_set_capability(input_dev, EV_KEY, BTN_Y);
|
|
|
+ input_set_capability(input_dev, EV_KEY, BTN_Z);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (p->wakeup_flags) {
|