Skip to content

Commit ff66b8e

Browse files
Angela CzubakBenjamin Tissoires
authored andcommitted
HID: haptic: add hid_haptic_switch_mode
Function hid_haptic_switch_mode() can be used to switch between device-controlled mode and host-controlled mode. Uploading a WAVEFORMPRESS or WAVEFORMRELEASE effect triggers host-controlled mode if the device is in device-controlled mode. Signed-off-by: Angela Czubak <aczubak@google.com> Co-developed-by: Jonathan Denose <jdenose@google.com> Signed-off-by: Jonathan Denose <jdenose@google.com> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
1 parent 4e584ac commit ff66b8e

1 file changed

Lines changed: 59 additions & 7 deletions

File tree

drivers/hid/hid-haptic.c

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (c) 2021 Angela Czubak <acz@semihalf.com>
66
*/
77

8+
#include <linux/input/mt.h>
89
#include <linux/module.h>
910

1011
#include "hid-haptic.h"
@@ -197,12 +198,46 @@ static void fill_effect_buf(struct hid_haptic_device *haptic,
197198
mutex_unlock(&haptic->manual_trigger_mutex);
198199
}
199200

201+
static void switch_mode(struct hid_device *hdev, struct hid_haptic_device *haptic,
202+
int mode)
203+
{
204+
struct hid_report *rep = haptic->auto_trigger_report;
205+
struct hid_field *field;
206+
s32 value;
207+
int i, j;
208+
209+
if (mode == HID_HAPTIC_MODE_HOST)
210+
value = HID_HAPTIC_ORDINAL_WAVEFORMSTOP;
211+
else
212+
value = haptic->default_auto_trigger;
213+
214+
mutex_lock(&haptic->auto_trigger_mutex);
215+
for (i = 0; i < rep->maxfield; i++) {
216+
field = rep->field[i];
217+
/* Ignore if report count is out of bounds. */
218+
if (field->report_count < 1)
219+
continue;
220+
221+
for (j = 0; j < field->maxusage; j++) {
222+
if (field->usage[j].hid == HID_HP_AUTOTRIGGER)
223+
field->value[j] = value;
224+
}
225+
}
226+
227+
/* send the report */
228+
hid_hw_request(hdev, rep, HID_REQ_SET_REPORT);
229+
mutex_unlock(&haptic->auto_trigger_mutex);
230+
haptic->mode = mode;
231+
}
232+
200233
static int hid_haptic_upload_effect(struct input_dev *dev, struct ff_effect *effect,
201234
struct ff_effect *old)
202235
{
236+
struct hid_device *hdev = input_get_drvdata(dev);
203237
struct ff_device *ff = dev->ff;
204238
struct hid_haptic_device *haptic = ff->private;
205239
int i, ordinal = 0;
240+
bool switch_modes = false;
206241

207242
/* If vendor range, check vendor id and page */
208243
if (effect->u.haptic.hid_usage >= (HID_HP_VENDORWAVEFORMMIN & HID_USAGE) &&
@@ -225,6 +260,16 @@ static int hid_haptic_upload_effect(struct input_dev *dev, struct ff_effect *eff
225260
fill_effect_buf(haptic, &effect->u.haptic, &haptic->effect[effect->id],
226261
ordinal);
227262

263+
if (effect->u.haptic.hid_usage == (HID_HP_WAVEFORMPRESS & HID_USAGE) ||
264+
effect->u.haptic.hid_usage == (HID_HP_WAVEFORMRELEASE & HID_USAGE))
265+
switch_modes = true;
266+
267+
/* If device is in autonomous mode, and the uploaded effect signals userspace
268+
* wants control of the device, change modes
269+
*/
270+
if (switch_modes && haptic->mode == HID_HAPTIC_MODE_DEVICE)
271+
switch_mode(hdev, haptic, HID_HAPTIC_MODE_HOST);
272+
228273
return 0;
229274
}
230275

@@ -290,27 +335,33 @@ static void effect_set_default(struct ff_effect *effect)
290335
static int hid_haptic_erase(struct input_dev *dev, int effect_id)
291336
{
292337
struct hid_haptic_device *haptic = dev->ff->private;
338+
struct hid_device *hdev = input_get_drvdata(dev);
293339
struct ff_effect effect;
294340
int ordinal;
295341

296342
effect_set_default(&effect);
297343

298344
if (effect.u.haptic.hid_usage == (HID_HP_WAVEFORMRELEASE & HID_USAGE)) {
299345
ordinal = haptic->release_ordinal;
300-
if (!ordinal)
346+
if (!ordinal) {
301347
ordinal = HID_HAPTIC_ORDINAL_WAVEFORMNONE;
302-
else
303-
effect.u.haptic.hid_usage = HID_HP_WAVEFORMRELEASE &
304-
HID_USAGE;
348+
if (haptic->mode == HID_HAPTIC_MODE_HOST)
349+
switch_mode(hdev, haptic, HID_HAPTIC_MODE_DEVICE);
350+
} else
351+
effect.u.haptic.hid_usage = HID_HP_WAVEFORMRELEASE & HID_USAGE;
352+
305353
fill_effect_buf(haptic, &effect.u.haptic, &haptic->effect[effect_id],
306354
ordinal);
307355
} else if (effect.u.haptic.hid_usage == (HID_HP_WAVEFORMPRESS & HID_USAGE)) {
308356
ordinal = haptic->press_ordinal;
309-
if (!ordinal)
357+
if (!ordinal) {
310358
ordinal = HID_HAPTIC_ORDINAL_WAVEFORMNONE;
359+
if (haptic->mode == HID_HAPTIC_MODE_HOST)
360+
switch_mode(hdev, haptic, HID_HAPTIC_MODE_DEVICE);
361+
}
311362
else
312-
effect.u.haptic.hid_usage = HID_HP_WAVEFORMPRESS &
313-
HID_USAGE;
363+
effect.u.haptic.hid_usage = HID_HP_WAVEFORMPRESS & HID_USAGE;
364+
314365
fill_effect_buf(haptic, &effect.u.haptic, &haptic->effect[effect_id],
315366
ordinal);
316367
}
@@ -392,6 +443,7 @@ int hid_haptic_init(struct hid_device *hdev,
392443
haptic->hid_usage_map[HID_HAPTIC_ORDINAL_WAVEFORMSTOP] =
393444
HID_HP_WAVEFORMSTOP & HID_USAGE;
394445

446+
mutex_init(&haptic->auto_trigger_mutex);
395447
for (r = 0; r < haptic->auto_trigger_report->maxfield; r++)
396448
parse_auto_trigger_field(haptic, haptic->auto_trigger_report->field[r]);
397449

0 commit comments

Comments
 (0)