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+
200233static 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)
290335static 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