xref: /openbmc/linux/drivers/hid/usbhid/hid-pidff.c (revision afd700d9)
16db3dfefSJiri Kosina /*
26db3dfefSJiri Kosina  *  Force feedback driver for USB HID PID compliant devices
36db3dfefSJiri Kosina  *
46db3dfefSJiri Kosina  *  Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com>
56db3dfefSJiri Kosina  */
66db3dfefSJiri Kosina 
76db3dfefSJiri Kosina /*
86db3dfefSJiri Kosina  * This program is free software; you can redistribute it and/or modify
96db3dfefSJiri Kosina  * it under the terms of the GNU General Public License as published by
106db3dfefSJiri Kosina  * the Free Software Foundation; either version 2 of the License, or
116db3dfefSJiri Kosina  * (at your option) any later version.
126db3dfefSJiri Kosina  *
136db3dfefSJiri Kosina  * This program is distributed in the hope that it will be useful,
146db3dfefSJiri Kosina  * but WITHOUT ANY WARRANTY; without even the implied warranty of
156db3dfefSJiri Kosina  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
166db3dfefSJiri Kosina  * GNU General Public License for more details.
176db3dfefSJiri Kosina  *
186db3dfefSJiri Kosina  * You should have received a copy of the GNU General Public License
196db3dfefSJiri Kosina  * along with this program; if not, write to the Free Software
206db3dfefSJiri Kosina  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
216db3dfefSJiri Kosina  */
226db3dfefSJiri Kosina 
236db3dfefSJiri Kosina /* #define DEBUG */
246db3dfefSJiri Kosina 
254291ee30SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
266db3dfefSJiri Kosina 
276db3dfefSJiri Kosina #include <linux/input.h>
285a0e3ad6STejun Heo #include <linux/slab.h>
296db3dfefSJiri Kosina #include <linux/usb.h>
306db3dfefSJiri Kosina 
316db3dfefSJiri Kosina #include <linux/hid.h>
326db3dfefSJiri Kosina 
336db3dfefSJiri Kosina #include "usbhid.h"
346db3dfefSJiri Kosina 
356db3dfefSJiri Kosina #define	PID_EFFECTS_MAX		64
366db3dfefSJiri Kosina 
376db3dfefSJiri Kosina /* Report usage table used to put reports into an array */
386db3dfefSJiri Kosina 
396db3dfefSJiri Kosina #define PID_SET_EFFECT		0
406db3dfefSJiri Kosina #define PID_EFFECT_OPERATION	1
416db3dfefSJiri Kosina #define PID_DEVICE_GAIN		2
426db3dfefSJiri Kosina #define PID_POOL		3
436db3dfefSJiri Kosina #define PID_BLOCK_LOAD		4
446db3dfefSJiri Kosina #define PID_BLOCK_FREE		5
456db3dfefSJiri Kosina #define PID_DEVICE_CONTROL	6
466db3dfefSJiri Kosina #define PID_CREATE_NEW_EFFECT	7
476db3dfefSJiri Kosina 
486db3dfefSJiri Kosina #define PID_REQUIRED_REPORTS	7
496db3dfefSJiri Kosina 
506db3dfefSJiri Kosina #define PID_SET_ENVELOPE	8
516db3dfefSJiri Kosina #define PID_SET_CONDITION	9
526db3dfefSJiri Kosina #define PID_SET_PERIODIC	10
536db3dfefSJiri Kosina #define PID_SET_CONSTANT	11
546db3dfefSJiri Kosina #define PID_SET_RAMP		12
556db3dfefSJiri Kosina static const u8 pidff_reports[] = {
566db3dfefSJiri Kosina 	0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab,
576db3dfefSJiri Kosina 	0x5a, 0x5f, 0x6e, 0x73, 0x74
586db3dfefSJiri Kosina };
596db3dfefSJiri Kosina 
606db3dfefSJiri Kosina /* device_control is really 0x95, but 0x96 specified as it is the usage of
616db3dfefSJiri Kosina the only field in that report */
626db3dfefSJiri Kosina 
636db3dfefSJiri Kosina /* Value usage tables used to put fields and values into arrays */
646db3dfefSJiri Kosina 
656db3dfefSJiri Kosina #define PID_EFFECT_BLOCK_INDEX	0
666db3dfefSJiri Kosina 
676db3dfefSJiri Kosina #define PID_DURATION		1
686db3dfefSJiri Kosina #define PID_GAIN		2
696db3dfefSJiri Kosina #define PID_TRIGGER_BUTTON	3
706db3dfefSJiri Kosina #define PID_TRIGGER_REPEAT_INT	4
716db3dfefSJiri Kosina #define PID_DIRECTION_ENABLE	5
726db3dfefSJiri Kosina #define PID_START_DELAY		6
736db3dfefSJiri Kosina static const u8 pidff_set_effect[] = {
746db3dfefSJiri Kosina 	0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7
756db3dfefSJiri Kosina };
766db3dfefSJiri Kosina 
776db3dfefSJiri Kosina #define PID_ATTACK_LEVEL	1
786db3dfefSJiri Kosina #define PID_ATTACK_TIME		2
796db3dfefSJiri Kosina #define PID_FADE_LEVEL		3
806db3dfefSJiri Kosina #define PID_FADE_TIME		4
816db3dfefSJiri Kosina static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e };
826db3dfefSJiri Kosina 
836db3dfefSJiri Kosina #define PID_PARAM_BLOCK_OFFSET	1
846db3dfefSJiri Kosina #define PID_CP_OFFSET		2
856db3dfefSJiri Kosina #define PID_POS_COEFFICIENT	3
866db3dfefSJiri Kosina #define PID_NEG_COEFFICIENT	4
876db3dfefSJiri Kosina #define PID_POS_SATURATION	5
886db3dfefSJiri Kosina #define PID_NEG_SATURATION	6
896db3dfefSJiri Kosina #define PID_DEAD_BAND		7
906db3dfefSJiri Kosina static const u8 pidff_set_condition[] = {
916db3dfefSJiri Kosina 	0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65
926db3dfefSJiri Kosina };
936db3dfefSJiri Kosina 
946db3dfefSJiri Kosina #define PID_MAGNITUDE		1
956db3dfefSJiri Kosina #define PID_OFFSET		2
966db3dfefSJiri Kosina #define PID_PHASE		3
976db3dfefSJiri Kosina #define PID_PERIOD		4
986db3dfefSJiri Kosina static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 };
996db3dfefSJiri Kosina static const u8 pidff_set_constant[] = { 0x22, 0x70 };
1006db3dfefSJiri Kosina 
1016db3dfefSJiri Kosina #define PID_RAMP_START		1
1026db3dfefSJiri Kosina #define PID_RAMP_END		2
1036db3dfefSJiri Kosina static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 };
1046db3dfefSJiri Kosina 
1056db3dfefSJiri Kosina #define PID_RAM_POOL_AVAILABLE	1
1066db3dfefSJiri Kosina static const u8 pidff_block_load[] = { 0x22, 0xac };
1076db3dfefSJiri Kosina 
1086db3dfefSJiri Kosina #define PID_LOOP_COUNT		1
1096db3dfefSJiri Kosina static const u8 pidff_effect_operation[] = { 0x22, 0x7c };
1106db3dfefSJiri Kosina 
1116db3dfefSJiri Kosina static const u8 pidff_block_free[] = { 0x22 };
1126db3dfefSJiri Kosina 
1136db3dfefSJiri Kosina #define PID_DEVICE_GAIN_FIELD	0
1146db3dfefSJiri Kosina static const u8 pidff_device_gain[] = { 0x7e };
1156db3dfefSJiri Kosina 
1166db3dfefSJiri Kosina #define PID_RAM_POOL_SIZE	0
1176db3dfefSJiri Kosina #define PID_SIMULTANEOUS_MAX	1
1186db3dfefSJiri Kosina #define PID_DEVICE_MANAGED_POOL	2
1196db3dfefSJiri Kosina static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
1206db3dfefSJiri Kosina 
1216db3dfefSJiri Kosina /* Special field key tables used to put special field keys into arrays */
1226db3dfefSJiri Kosina 
1236db3dfefSJiri Kosina #define PID_ENABLE_ACTUATORS	0
1246db3dfefSJiri Kosina #define PID_RESET		1
1256db3dfefSJiri Kosina static const u8 pidff_device_control[] = { 0x97, 0x9a };
1266db3dfefSJiri Kosina 
1276db3dfefSJiri Kosina #define PID_CONSTANT	0
1286db3dfefSJiri Kosina #define PID_RAMP	1
1296db3dfefSJiri Kosina #define PID_SQUARE	2
1306db3dfefSJiri Kosina #define PID_SINE	3
1316db3dfefSJiri Kosina #define PID_TRIANGLE	4
1326db3dfefSJiri Kosina #define PID_SAW_UP	5
1336db3dfefSJiri Kosina #define PID_SAW_DOWN	6
1346db3dfefSJiri Kosina #define PID_SPRING	7
1356db3dfefSJiri Kosina #define PID_DAMPER	8
1366db3dfefSJiri Kosina #define PID_INERTIA	9
1376db3dfefSJiri Kosina #define PID_FRICTION	10
1386db3dfefSJiri Kosina static const u8 pidff_effect_types[] = {
1396db3dfefSJiri Kosina 	0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34,
1406db3dfefSJiri Kosina 	0x40, 0x41, 0x42, 0x43
1416db3dfefSJiri Kosina };
1426db3dfefSJiri Kosina 
1436db3dfefSJiri Kosina #define PID_BLOCK_LOAD_SUCCESS	0
1446db3dfefSJiri Kosina #define PID_BLOCK_LOAD_FULL	1
1456db3dfefSJiri Kosina static const u8 pidff_block_load_status[] = { 0x8c, 0x8d };
1466db3dfefSJiri Kosina 
1476db3dfefSJiri Kosina #define PID_EFFECT_START	0
1486db3dfefSJiri Kosina #define PID_EFFECT_STOP		1
1496db3dfefSJiri Kosina static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
1506db3dfefSJiri Kosina 
1516db3dfefSJiri Kosina struct pidff_usage {
1526db3dfefSJiri Kosina 	struct hid_field *field;
1536db3dfefSJiri Kosina 	s32 *value;
1546db3dfefSJiri Kosina };
1556db3dfefSJiri Kosina 
1566db3dfefSJiri Kosina struct pidff_device {
1576db3dfefSJiri Kosina 	struct hid_device *hid;
1586db3dfefSJiri Kosina 
1596db3dfefSJiri Kosina 	struct hid_report *reports[sizeof(pidff_reports)];
1606db3dfefSJiri Kosina 
1616db3dfefSJiri Kosina 	struct pidff_usage set_effect[sizeof(pidff_set_effect)];
1626db3dfefSJiri Kosina 	struct pidff_usage set_envelope[sizeof(pidff_set_envelope)];
1636db3dfefSJiri Kosina 	struct pidff_usage set_condition[sizeof(pidff_set_condition)];
1646db3dfefSJiri Kosina 	struct pidff_usage set_periodic[sizeof(pidff_set_periodic)];
1656db3dfefSJiri Kosina 	struct pidff_usage set_constant[sizeof(pidff_set_constant)];
1666db3dfefSJiri Kosina 	struct pidff_usage set_ramp[sizeof(pidff_set_ramp)];
1676db3dfefSJiri Kosina 
1686db3dfefSJiri Kosina 	struct pidff_usage device_gain[sizeof(pidff_device_gain)];
1696db3dfefSJiri Kosina 	struct pidff_usage block_load[sizeof(pidff_block_load)];
1706db3dfefSJiri Kosina 	struct pidff_usage pool[sizeof(pidff_pool)];
1716db3dfefSJiri Kosina 	struct pidff_usage effect_operation[sizeof(pidff_effect_operation)];
1726db3dfefSJiri Kosina 	struct pidff_usage block_free[sizeof(pidff_block_free)];
1736db3dfefSJiri Kosina 
1746db3dfefSJiri Kosina 	/* Special field is a field that is not composed of
1756db3dfefSJiri Kosina 	   usage<->value pairs that pidff_usage values are */
1766db3dfefSJiri Kosina 
1776db3dfefSJiri Kosina 	/* Special field in create_new_effect */
1786db3dfefSJiri Kosina 	struct hid_field *create_new_effect_type;
1796db3dfefSJiri Kosina 
1806db3dfefSJiri Kosina 	/* Special fields in set_effect */
1816db3dfefSJiri Kosina 	struct hid_field *set_effect_type;
1826db3dfefSJiri Kosina 	struct hid_field *effect_direction;
1836db3dfefSJiri Kosina 
1846db3dfefSJiri Kosina 	/* Special field in device_control */
1856db3dfefSJiri Kosina 	struct hid_field *device_control;
1866db3dfefSJiri Kosina 
1876db3dfefSJiri Kosina 	/* Special field in block_load */
1886db3dfefSJiri Kosina 	struct hid_field *block_load_status;
1896db3dfefSJiri Kosina 
1906db3dfefSJiri Kosina 	/* Special field in effect_operation */
1916db3dfefSJiri Kosina 	struct hid_field *effect_operation_status;
1926db3dfefSJiri Kosina 
1936db3dfefSJiri Kosina 	int control_id[sizeof(pidff_device_control)];
1946db3dfefSJiri Kosina 	int type_id[sizeof(pidff_effect_types)];
1956db3dfefSJiri Kosina 	int status_id[sizeof(pidff_block_load_status)];
1966db3dfefSJiri Kosina 	int operation_id[sizeof(pidff_effect_operation_status)];
1976db3dfefSJiri Kosina 
1986db3dfefSJiri Kosina 	int pid_id[PID_EFFECTS_MAX];
1996db3dfefSJiri Kosina };
2006db3dfefSJiri Kosina 
2016db3dfefSJiri Kosina /*
2026db3dfefSJiri Kosina  * Scale an unsigned value with range 0..max for the given field
2036db3dfefSJiri Kosina  */
2046db3dfefSJiri Kosina static int pidff_rescale(int i, int max, struct hid_field *field)
2056db3dfefSJiri Kosina {
2066db3dfefSJiri Kosina 	return i * (field->logical_maximum - field->logical_minimum) / max +
2076db3dfefSJiri Kosina 	    field->logical_minimum;
2086db3dfefSJiri Kosina }
2096db3dfefSJiri Kosina 
2106db3dfefSJiri Kosina /*
2116db3dfefSJiri Kosina  * Scale a signed value in range -0x8000..0x7fff for the given field
2126db3dfefSJiri Kosina  */
2136db3dfefSJiri Kosina static int pidff_rescale_signed(int i, struct hid_field *field)
2146db3dfefSJiri Kosina {
2156db3dfefSJiri Kosina 	return i == 0 ? 0 : i >
2166db3dfefSJiri Kosina 	    0 ? i * field->logical_maximum / 0x7fff : i *
2176db3dfefSJiri Kosina 	    field->logical_minimum / -0x8000;
2186db3dfefSJiri Kosina }
2196db3dfefSJiri Kosina 
2206db3dfefSJiri Kosina static void pidff_set(struct pidff_usage *usage, u16 value)
2216db3dfefSJiri Kosina {
2226db3dfefSJiri Kosina 	usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
2234291ee30SJoe Perches 	pr_debug("calculated from %d to %d\n", value, usage->value[0]);
2246db3dfefSJiri Kosina }
2256db3dfefSJiri Kosina 
2266db3dfefSJiri Kosina static void pidff_set_signed(struct pidff_usage *usage, s16 value)
2276db3dfefSJiri Kosina {
2286db3dfefSJiri Kosina 	if (usage->field->logical_minimum < 0)
2296db3dfefSJiri Kosina 		usage->value[0] = pidff_rescale_signed(value, usage->field);
2306db3dfefSJiri Kosina 	else {
2316db3dfefSJiri Kosina 		if (value < 0)
2326db3dfefSJiri Kosina 			usage->value[0] =
2336db3dfefSJiri Kosina 			    pidff_rescale(-value, 0x8000, usage->field);
2346db3dfefSJiri Kosina 		else
2356db3dfefSJiri Kosina 			usage->value[0] =
2366db3dfefSJiri Kosina 			    pidff_rescale(value, 0x7fff, usage->field);
2376db3dfefSJiri Kosina 	}
2384291ee30SJoe Perches 	pr_debug("calculated from %d to %d\n", value, usage->value[0]);
2396db3dfefSJiri Kosina }
2406db3dfefSJiri Kosina 
2416db3dfefSJiri Kosina /*
2426db3dfefSJiri Kosina  * Send envelope report to the device
2436db3dfefSJiri Kosina  */
2446db3dfefSJiri Kosina static void pidff_set_envelope_report(struct pidff_device *pidff,
2456db3dfefSJiri Kosina 				      struct ff_envelope *envelope)
2466db3dfefSJiri Kosina {
2476db3dfefSJiri Kosina 	pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] =
2486db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
2496db3dfefSJiri Kosina 
2506db3dfefSJiri Kosina 	pidff->set_envelope[PID_ATTACK_LEVEL].value[0] =
2516db3dfefSJiri Kosina 	    pidff_rescale(envelope->attack_level >
2526db3dfefSJiri Kosina 			  0x7fff ? 0x7fff : envelope->attack_level, 0x7fff,
2536db3dfefSJiri Kosina 			  pidff->set_envelope[PID_ATTACK_LEVEL].field);
2546db3dfefSJiri Kosina 	pidff->set_envelope[PID_FADE_LEVEL].value[0] =
2556db3dfefSJiri Kosina 	    pidff_rescale(envelope->fade_level >
2566db3dfefSJiri Kosina 			  0x7fff ? 0x7fff : envelope->fade_level, 0x7fff,
2576db3dfefSJiri Kosina 			  pidff->set_envelope[PID_FADE_LEVEL].field);
2586db3dfefSJiri Kosina 
2596db3dfefSJiri Kosina 	pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length;
2606db3dfefSJiri Kosina 	pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length;
2616db3dfefSJiri Kosina 
2624291ee30SJoe Perches 	hid_dbg(pidff->hid, "attack %u => %d\n",
2634291ee30SJoe Perches 		envelope->attack_level,
2646db3dfefSJiri Kosina 		pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
2656db3dfefSJiri Kosina 
266d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
267d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
2686db3dfefSJiri Kosina }
2696db3dfefSJiri Kosina 
2706db3dfefSJiri Kosina /*
2716db3dfefSJiri Kosina  * Test if the new envelope differs from old one
2726db3dfefSJiri Kosina  */
2736db3dfefSJiri Kosina static int pidff_needs_set_envelope(struct ff_envelope *envelope,
2746db3dfefSJiri Kosina 				    struct ff_envelope *old)
2756db3dfefSJiri Kosina {
2766db3dfefSJiri Kosina 	return envelope->attack_level != old->attack_level ||
2776db3dfefSJiri Kosina 	       envelope->fade_level != old->fade_level ||
2786db3dfefSJiri Kosina 	       envelope->attack_length != old->attack_length ||
2796db3dfefSJiri Kosina 	       envelope->fade_length != old->fade_length;
2806db3dfefSJiri Kosina }
2816db3dfefSJiri Kosina 
2826db3dfefSJiri Kosina /*
2836db3dfefSJiri Kosina  * Send constant force report to the device
2846db3dfefSJiri Kosina  */
2856db3dfefSJiri Kosina static void pidff_set_constant_force_report(struct pidff_device *pidff,
2866db3dfefSJiri Kosina 					    struct ff_effect *effect)
2876db3dfefSJiri Kosina {
2886db3dfefSJiri Kosina 	pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] =
2896db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
2906db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
2916db3dfefSJiri Kosina 			 effect->u.constant.level);
2926db3dfefSJiri Kosina 
293d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT],
294d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
2956db3dfefSJiri Kosina }
2966db3dfefSJiri Kosina 
2976db3dfefSJiri Kosina /*
2986db3dfefSJiri Kosina  * Test if the constant parameters have changed between effects
2996db3dfefSJiri Kosina  */
3006db3dfefSJiri Kosina static int pidff_needs_set_constant(struct ff_effect *effect,
3016db3dfefSJiri Kosina 				    struct ff_effect *old)
3026db3dfefSJiri Kosina {
3036db3dfefSJiri Kosina 	return effect->u.constant.level != old->u.constant.level;
3046db3dfefSJiri Kosina }
3056db3dfefSJiri Kosina 
3066db3dfefSJiri Kosina /*
3076db3dfefSJiri Kosina  * Send set effect report to the device
3086db3dfefSJiri Kosina  */
3096db3dfefSJiri Kosina static void pidff_set_effect_report(struct pidff_device *pidff,
3106db3dfefSJiri Kosina 				    struct ff_effect *effect)
3116db3dfefSJiri Kosina {
3126db3dfefSJiri Kosina 	pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
3136db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
3146db3dfefSJiri Kosina 	pidff->set_effect_type->value[0] =
3156db3dfefSJiri Kosina 		pidff->create_new_effect_type->value[0];
3166db3dfefSJiri Kosina 	pidff->set_effect[PID_DURATION].value[0] = effect->replay.length;
3176db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
3186db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] =
3196db3dfefSJiri Kosina 		effect->trigger.interval;
3206db3dfefSJiri Kosina 	pidff->set_effect[PID_GAIN].value[0] =
3216db3dfefSJiri Kosina 		pidff->set_effect[PID_GAIN].field->logical_maximum;
3226db3dfefSJiri Kosina 	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
3236db3dfefSJiri Kosina 	pidff->effect_direction->value[0] =
3246db3dfefSJiri Kosina 		pidff_rescale(effect->direction, 0xffff,
3256db3dfefSJiri Kosina 				pidff->effect_direction);
3266db3dfefSJiri Kosina 	pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
3276db3dfefSJiri Kosina 
328d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
329d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
3306db3dfefSJiri Kosina }
3316db3dfefSJiri Kosina 
3326db3dfefSJiri Kosina /*
3336db3dfefSJiri Kosina  * Test if the values used in set_effect have changed
3346db3dfefSJiri Kosina  */
3356db3dfefSJiri Kosina static int pidff_needs_set_effect(struct ff_effect *effect,
3366db3dfefSJiri Kosina 				  struct ff_effect *old)
3376db3dfefSJiri Kosina {
3386db3dfefSJiri Kosina 	return effect->replay.length != old->replay.length ||
3396db3dfefSJiri Kosina 	       effect->trigger.interval != old->trigger.interval ||
3406db3dfefSJiri Kosina 	       effect->trigger.button != old->trigger.button ||
3416db3dfefSJiri Kosina 	       effect->direction != old->direction ||
3426db3dfefSJiri Kosina 	       effect->replay.delay != old->replay.delay;
3436db3dfefSJiri Kosina }
3446db3dfefSJiri Kosina 
3456db3dfefSJiri Kosina /*
3466db3dfefSJiri Kosina  * Send periodic effect report to the device
3476db3dfefSJiri Kosina  */
3486db3dfefSJiri Kosina static void pidff_set_periodic_report(struct pidff_device *pidff,
3496db3dfefSJiri Kosina 				      struct ff_effect *effect)
3506db3dfefSJiri Kosina {
3516db3dfefSJiri Kosina 	pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] =
3526db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
3536db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE],
3546db3dfefSJiri Kosina 			 effect->u.periodic.magnitude);
3556db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_periodic[PID_OFFSET],
3566db3dfefSJiri Kosina 			 effect->u.periodic.offset);
3576db3dfefSJiri Kosina 	pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
3586db3dfefSJiri Kosina 	pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
3596db3dfefSJiri Kosina 
360d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
361d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
3626db3dfefSJiri Kosina 
3636db3dfefSJiri Kosina }
3646db3dfefSJiri Kosina 
3656db3dfefSJiri Kosina /*
3666db3dfefSJiri Kosina  * Test if periodic effect parameters have changed
3676db3dfefSJiri Kosina  */
3686db3dfefSJiri Kosina static int pidff_needs_set_periodic(struct ff_effect *effect,
3696db3dfefSJiri Kosina 				    struct ff_effect *old)
3706db3dfefSJiri Kosina {
3716db3dfefSJiri Kosina 	return effect->u.periodic.magnitude != old->u.periodic.magnitude ||
3726db3dfefSJiri Kosina 	       effect->u.periodic.offset != old->u.periodic.offset ||
3736db3dfefSJiri Kosina 	       effect->u.periodic.phase != old->u.periodic.phase ||
3746db3dfefSJiri Kosina 	       effect->u.periodic.period != old->u.periodic.period;
3756db3dfefSJiri Kosina }
3766db3dfefSJiri Kosina 
3776db3dfefSJiri Kosina /*
3786db3dfefSJiri Kosina  * Send condition effect reports to the device
3796db3dfefSJiri Kosina  */
3806db3dfefSJiri Kosina static void pidff_set_condition_report(struct pidff_device *pidff,
3816db3dfefSJiri Kosina 				       struct ff_effect *effect)
3826db3dfefSJiri Kosina {
3836db3dfefSJiri Kosina 	int i;
3846db3dfefSJiri Kosina 
3856db3dfefSJiri Kosina 	pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] =
3866db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
3876db3dfefSJiri Kosina 
3886db3dfefSJiri Kosina 	for (i = 0; i < 2; i++) {
3896db3dfefSJiri Kosina 		pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
3906db3dfefSJiri Kosina 		pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET],
3916db3dfefSJiri Kosina 				 effect->u.condition[i].center);
3926db3dfefSJiri Kosina 		pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT],
3936db3dfefSJiri Kosina 				 effect->u.condition[i].right_coeff);
3946db3dfefSJiri Kosina 		pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT],
3956db3dfefSJiri Kosina 				 effect->u.condition[i].left_coeff);
3966db3dfefSJiri Kosina 		pidff_set(&pidff->set_condition[PID_POS_SATURATION],
3976db3dfefSJiri Kosina 			  effect->u.condition[i].right_saturation);
3986db3dfefSJiri Kosina 		pidff_set(&pidff->set_condition[PID_NEG_SATURATION],
3996db3dfefSJiri Kosina 			  effect->u.condition[i].left_saturation);
4006db3dfefSJiri Kosina 		pidff_set(&pidff->set_condition[PID_DEAD_BAND],
4016db3dfefSJiri Kosina 			  effect->u.condition[i].deadband);
402d8814272SBenjamin Tissoires 		hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION],
403d8814272SBenjamin Tissoires 				HID_REQ_SET_REPORT);
4046db3dfefSJiri Kosina 	}
4056db3dfefSJiri Kosina }
4066db3dfefSJiri Kosina 
4076db3dfefSJiri Kosina /*
4086db3dfefSJiri Kosina  * Test if condition effect parameters have changed
4096db3dfefSJiri Kosina  */
4106db3dfefSJiri Kosina static int pidff_needs_set_condition(struct ff_effect *effect,
4116db3dfefSJiri Kosina 				     struct ff_effect *old)
4126db3dfefSJiri Kosina {
4136db3dfefSJiri Kosina 	int i;
4146db3dfefSJiri Kosina 	int ret = 0;
4156db3dfefSJiri Kosina 
4166db3dfefSJiri Kosina 	for (i = 0; i < 2; i++) {
4176db3dfefSJiri Kosina 		struct ff_condition_effect *cond = &effect->u.condition[i];
4186db3dfefSJiri Kosina 		struct ff_condition_effect *old_cond = &old->u.condition[i];
4196db3dfefSJiri Kosina 
4206db3dfefSJiri Kosina 		ret |= cond->center != old_cond->center ||
4216db3dfefSJiri Kosina 		       cond->right_coeff != old_cond->right_coeff ||
4226db3dfefSJiri Kosina 		       cond->left_coeff != old_cond->left_coeff ||
4236db3dfefSJiri Kosina 		       cond->right_saturation != old_cond->right_saturation ||
4246db3dfefSJiri Kosina 		       cond->left_saturation != old_cond->left_saturation ||
4256db3dfefSJiri Kosina 		       cond->deadband != old_cond->deadband;
4266db3dfefSJiri Kosina 	}
4276db3dfefSJiri Kosina 
4286db3dfefSJiri Kosina 	return ret;
4296db3dfefSJiri Kosina }
4306db3dfefSJiri Kosina 
4316db3dfefSJiri Kosina /*
4326db3dfefSJiri Kosina  * Send ramp force report to the device
4336db3dfefSJiri Kosina  */
4346db3dfefSJiri Kosina static void pidff_set_ramp_force_report(struct pidff_device *pidff,
4356db3dfefSJiri Kosina 					struct ff_effect *effect)
4366db3dfefSJiri Kosina {
4376db3dfefSJiri Kosina 	pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] =
4386db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
4396db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_ramp[PID_RAMP_START],
4406db3dfefSJiri Kosina 			 effect->u.ramp.start_level);
4416db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
4426db3dfefSJiri Kosina 			 effect->u.ramp.end_level);
443d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP],
444d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
4456db3dfefSJiri Kosina }
4466db3dfefSJiri Kosina 
4476db3dfefSJiri Kosina /*
4486db3dfefSJiri Kosina  * Test if ramp force parameters have changed
4496db3dfefSJiri Kosina  */
4506db3dfefSJiri Kosina static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old)
4516db3dfefSJiri Kosina {
4526db3dfefSJiri Kosina 	return effect->u.ramp.start_level != old->u.ramp.start_level ||
4536db3dfefSJiri Kosina 	       effect->u.ramp.end_level != old->u.ramp.end_level;
4546db3dfefSJiri Kosina }
4556db3dfefSJiri Kosina 
4566db3dfefSJiri Kosina /*
4576db3dfefSJiri Kosina  * Send a request for effect upload to the device
4586db3dfefSJiri Kosina  *
4596db3dfefSJiri Kosina  * Returns 0 if device reported success, -ENOSPC if the device reported memory
4606db3dfefSJiri Kosina  * is full. Upon unknown response the function will retry for 60 times, if
4616db3dfefSJiri Kosina  * still unsuccessful -EIO is returned.
4626db3dfefSJiri Kosina  */
4636db3dfefSJiri Kosina static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
4646db3dfefSJiri Kosina {
4656db3dfefSJiri Kosina 	int j;
4666db3dfefSJiri Kosina 
4676db3dfefSJiri Kosina 	pidff->create_new_effect_type->value[0] = efnum;
468d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
469d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
4704291ee30SJoe Perches 	hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
4716db3dfefSJiri Kosina 
4726db3dfefSJiri Kosina 	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
4736db3dfefSJiri Kosina 	pidff->block_load_status->value[0] = 0;
474b7966a4dSBenjamin Tissoires 	hid_hw_wait(pidff->hid);
4756db3dfefSJiri Kosina 
4766db3dfefSJiri Kosina 	for (j = 0; j < 60; j++) {
4774291ee30SJoe Perches 		hid_dbg(pidff->hid, "pid_block_load requested\n");
478d8814272SBenjamin Tissoires 		hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
479d8814272SBenjamin Tissoires 				HID_REQ_GET_REPORT);
480b7966a4dSBenjamin Tissoires 		hid_hw_wait(pidff->hid);
4816db3dfefSJiri Kosina 		if (pidff->block_load_status->value[0] ==
4826db3dfefSJiri Kosina 		    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
4834291ee30SJoe Perches 			hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
4846db3dfefSJiri Kosina 				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
4856db3dfefSJiri Kosina 				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
4866db3dfefSJiri Kosina 			return 0;
4876db3dfefSJiri Kosina 		}
4886db3dfefSJiri Kosina 		if (pidff->block_load_status->value[0] ==
4896db3dfefSJiri Kosina 		    pidff->status_id[PID_BLOCK_LOAD_FULL]) {
4904291ee30SJoe Perches 			hid_dbg(pidff->hid, "not enough memory free: %d bytes\n",
4916db3dfefSJiri Kosina 				pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
4926db3dfefSJiri Kosina 				pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
4936db3dfefSJiri Kosina 			return -ENOSPC;
4946db3dfefSJiri Kosina 		}
4956db3dfefSJiri Kosina 	}
4964291ee30SJoe Perches 	hid_err(pidff->hid, "pid_block_load failed 60 times\n");
4976db3dfefSJiri Kosina 	return -EIO;
4986db3dfefSJiri Kosina }
4996db3dfefSJiri Kosina 
5006db3dfefSJiri Kosina /*
5016db3dfefSJiri Kosina  * Play the effect with PID id n times
5026db3dfefSJiri Kosina  */
5036db3dfefSJiri Kosina static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
5046db3dfefSJiri Kosina {
5056db3dfefSJiri Kosina 	pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
5066db3dfefSJiri Kosina 
5076db3dfefSJiri Kosina 	if (n == 0) {
5086db3dfefSJiri Kosina 		pidff->effect_operation_status->value[0] =
5096db3dfefSJiri Kosina 			pidff->operation_id[PID_EFFECT_STOP];
5106db3dfefSJiri Kosina 	} else {
5116db3dfefSJiri Kosina 		pidff->effect_operation_status->value[0] =
5126db3dfefSJiri Kosina 			pidff->operation_id[PID_EFFECT_START];
5136db3dfefSJiri Kosina 		pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
5146db3dfefSJiri Kosina 	}
5156db3dfefSJiri Kosina 
516d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
517d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
5186db3dfefSJiri Kosina }
5196db3dfefSJiri Kosina 
5206db3dfefSJiri Kosina /**
5216db3dfefSJiri Kosina  * Play the effect with effect id @effect_id for @value times
5226db3dfefSJiri Kosina  */
5236db3dfefSJiri Kosina static int pidff_playback(struct input_dev *dev, int effect_id, int value)
5246db3dfefSJiri Kosina {
5256db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
5266db3dfefSJiri Kosina 
5276db3dfefSJiri Kosina 	pidff_playback_pid(pidff, pidff->pid_id[effect_id], value);
5286db3dfefSJiri Kosina 
5296db3dfefSJiri Kosina 	return 0;
5306db3dfefSJiri Kosina }
5316db3dfefSJiri Kosina 
5326db3dfefSJiri Kosina /*
5336db3dfefSJiri Kosina  * Erase effect with PID id
5346db3dfefSJiri Kosina  */
5356db3dfefSJiri Kosina static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
5366db3dfefSJiri Kosina {
5376db3dfefSJiri Kosina 	pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
538d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
539d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
5406db3dfefSJiri Kosina }
5416db3dfefSJiri Kosina 
5426db3dfefSJiri Kosina /*
5436db3dfefSJiri Kosina  * Stop and erase effect with effect_id
5446db3dfefSJiri Kosina  */
5456db3dfefSJiri Kosina static int pidff_erase_effect(struct input_dev *dev, int effect_id)
5466db3dfefSJiri Kosina {
5476db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
5486db3dfefSJiri Kosina 	int pid_id = pidff->pid_id[effect_id];
5496db3dfefSJiri Kosina 
5504291ee30SJoe Perches 	hid_dbg(pidff->hid, "starting to erase %d/%d\n",
5514291ee30SJoe Perches 		effect_id, pidff->pid_id[effect_id]);
552f129ea6dSAnssi Hannula 	/* Wait for the queue to clear. We do not want a full fifo to
553f129ea6dSAnssi Hannula 	   prevent the effect removal. */
554b7966a4dSBenjamin Tissoires 	hid_hw_wait(pidff->hid);
5556db3dfefSJiri Kosina 	pidff_playback_pid(pidff, pid_id, 0);
5566db3dfefSJiri Kosina 	pidff_erase_pid(pidff, pid_id);
5576db3dfefSJiri Kosina 
5586db3dfefSJiri Kosina 	return 0;
5596db3dfefSJiri Kosina }
5606db3dfefSJiri Kosina 
5616db3dfefSJiri Kosina /*
5626db3dfefSJiri Kosina  * Effect upload handler
5636db3dfefSJiri Kosina  */
5646db3dfefSJiri Kosina static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
5656db3dfefSJiri Kosina 			       struct ff_effect *old)
5666db3dfefSJiri Kosina {
5676db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
5686db3dfefSJiri Kosina 	int type_id;
5696db3dfefSJiri Kosina 	int error;
5706db3dfefSJiri Kosina 
5716db3dfefSJiri Kosina 	switch (effect->type) {
5726db3dfefSJiri Kosina 	case FF_CONSTANT:
5736db3dfefSJiri Kosina 		if (!old) {
5746db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
5756db3dfefSJiri Kosina 					pidff->type_id[PID_CONSTANT]);
5766db3dfefSJiri Kosina 			if (error)
5776db3dfefSJiri Kosina 				return error;
5786db3dfefSJiri Kosina 		}
5796db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
5806db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
5816db3dfefSJiri Kosina 		if (!old || pidff_needs_set_constant(effect, old))
5826db3dfefSJiri Kosina 			pidff_set_constant_force_report(pidff, effect);
5836db3dfefSJiri Kosina 		if (!old ||
5846db3dfefSJiri Kosina 		    pidff_needs_set_envelope(&effect->u.constant.envelope,
5856db3dfefSJiri Kosina 					&old->u.constant.envelope))
5866db3dfefSJiri Kosina 			pidff_set_envelope_report(pidff,
5876db3dfefSJiri Kosina 					&effect->u.constant.envelope);
5886db3dfefSJiri Kosina 		break;
5896db3dfefSJiri Kosina 
5906db3dfefSJiri Kosina 	case FF_PERIODIC:
5916db3dfefSJiri Kosina 		if (!old) {
5926db3dfefSJiri Kosina 			switch (effect->u.periodic.waveform) {
5936db3dfefSJiri Kosina 			case FF_SQUARE:
5946db3dfefSJiri Kosina 				type_id = PID_SQUARE;
5956db3dfefSJiri Kosina 				break;
5966db3dfefSJiri Kosina 			case FF_TRIANGLE:
5976db3dfefSJiri Kosina 				type_id = PID_TRIANGLE;
5986db3dfefSJiri Kosina 				break;
5996db3dfefSJiri Kosina 			case FF_SINE:
6006db3dfefSJiri Kosina 				type_id = PID_SINE;
6016db3dfefSJiri Kosina 				break;
6026db3dfefSJiri Kosina 			case FF_SAW_UP:
6036db3dfefSJiri Kosina 				type_id = PID_SAW_UP;
6046db3dfefSJiri Kosina 				break;
6056db3dfefSJiri Kosina 			case FF_SAW_DOWN:
6066db3dfefSJiri Kosina 				type_id = PID_SAW_DOWN;
6076db3dfefSJiri Kosina 				break;
6086db3dfefSJiri Kosina 			default:
6094291ee30SJoe Perches 				hid_err(pidff->hid, "invalid waveform\n");
6106db3dfefSJiri Kosina 				return -EINVAL;
6116db3dfefSJiri Kosina 			}
6126db3dfefSJiri Kosina 
6136db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6146db3dfefSJiri Kosina 					pidff->type_id[type_id]);
6156db3dfefSJiri Kosina 			if (error)
6166db3dfefSJiri Kosina 				return error;
6176db3dfefSJiri Kosina 		}
6186db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6196db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6206db3dfefSJiri Kosina 		if (!old || pidff_needs_set_periodic(effect, old))
6216db3dfefSJiri Kosina 			pidff_set_periodic_report(pidff, effect);
6226db3dfefSJiri Kosina 		if (!old ||
6236db3dfefSJiri Kosina 		    pidff_needs_set_envelope(&effect->u.periodic.envelope,
6246db3dfefSJiri Kosina 					&old->u.periodic.envelope))
6256db3dfefSJiri Kosina 			pidff_set_envelope_report(pidff,
6266db3dfefSJiri Kosina 					&effect->u.periodic.envelope);
6276db3dfefSJiri Kosina 		break;
6286db3dfefSJiri Kosina 
6296db3dfefSJiri Kosina 	case FF_RAMP:
6306db3dfefSJiri Kosina 		if (!old) {
6316db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6326db3dfefSJiri Kosina 					pidff->type_id[PID_RAMP]);
6336db3dfefSJiri Kosina 			if (error)
6346db3dfefSJiri Kosina 				return error;
6356db3dfefSJiri Kosina 		}
6366db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6376db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6386db3dfefSJiri Kosina 		if (!old || pidff_needs_set_ramp(effect, old))
6396db3dfefSJiri Kosina 			pidff_set_ramp_force_report(pidff, effect);
6406db3dfefSJiri Kosina 		if (!old ||
6416db3dfefSJiri Kosina 		    pidff_needs_set_envelope(&effect->u.ramp.envelope,
6426db3dfefSJiri Kosina 					&old->u.ramp.envelope))
6436db3dfefSJiri Kosina 			pidff_set_envelope_report(pidff,
6446db3dfefSJiri Kosina 					&effect->u.ramp.envelope);
6456db3dfefSJiri Kosina 		break;
6466db3dfefSJiri Kosina 
6476db3dfefSJiri Kosina 	case FF_SPRING:
6486db3dfefSJiri Kosina 		if (!old) {
6496db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6506db3dfefSJiri Kosina 					pidff->type_id[PID_SPRING]);
6516db3dfefSJiri Kosina 			if (error)
6526db3dfefSJiri Kosina 				return error;
6536db3dfefSJiri Kosina 		}
6546db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6556db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6566db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6576db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6586db3dfefSJiri Kosina 		break;
6596db3dfefSJiri Kosina 
6606db3dfefSJiri Kosina 	case FF_FRICTION:
6616db3dfefSJiri Kosina 		if (!old) {
6626db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6636db3dfefSJiri Kosina 					pidff->type_id[PID_FRICTION]);
6646db3dfefSJiri Kosina 			if (error)
6656db3dfefSJiri Kosina 				return error;
6666db3dfefSJiri Kosina 		}
6676db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6686db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6696db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6706db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6716db3dfefSJiri Kosina 		break;
6726db3dfefSJiri Kosina 
6736db3dfefSJiri Kosina 	case FF_DAMPER:
6746db3dfefSJiri Kosina 		if (!old) {
6756db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6766db3dfefSJiri Kosina 					pidff->type_id[PID_DAMPER]);
6776db3dfefSJiri Kosina 			if (error)
6786db3dfefSJiri Kosina 				return error;
6796db3dfefSJiri Kosina 		}
6806db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6816db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6826db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6836db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6846db3dfefSJiri Kosina 		break;
6856db3dfefSJiri Kosina 
6866db3dfefSJiri Kosina 	case FF_INERTIA:
6876db3dfefSJiri Kosina 		if (!old) {
6886db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6896db3dfefSJiri Kosina 					pidff->type_id[PID_INERTIA]);
6906db3dfefSJiri Kosina 			if (error)
6916db3dfefSJiri Kosina 				return error;
6926db3dfefSJiri Kosina 		}
6936db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6946db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6956db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6966db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6976db3dfefSJiri Kosina 		break;
6986db3dfefSJiri Kosina 
6996db3dfefSJiri Kosina 	default:
7004291ee30SJoe Perches 		hid_err(pidff->hid, "invalid type\n");
7016db3dfefSJiri Kosina 		return -EINVAL;
7026db3dfefSJiri Kosina 	}
7036db3dfefSJiri Kosina 
7046db3dfefSJiri Kosina 	if (!old)
7056db3dfefSJiri Kosina 		pidff->pid_id[effect->id] =
7066db3dfefSJiri Kosina 		    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
7076db3dfefSJiri Kosina 
7084291ee30SJoe Perches 	hid_dbg(pidff->hid, "uploaded\n");
7096db3dfefSJiri Kosina 
7106db3dfefSJiri Kosina 	return 0;
7116db3dfefSJiri Kosina }
7126db3dfefSJiri Kosina 
7136db3dfefSJiri Kosina /*
7146db3dfefSJiri Kosina  * set_gain() handler
7156db3dfefSJiri Kosina  */
7166db3dfefSJiri Kosina static void pidff_set_gain(struct input_dev *dev, u16 gain)
7176db3dfefSJiri Kosina {
7186db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
7196db3dfefSJiri Kosina 
7206db3dfefSJiri Kosina 	pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
721d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
722d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
7236db3dfefSJiri Kosina }
7246db3dfefSJiri Kosina 
7256db3dfefSJiri Kosina static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
7266db3dfefSJiri Kosina {
7276db3dfefSJiri Kosina 	struct hid_field *field =
7286db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].field;
7296db3dfefSJiri Kosina 
7306db3dfefSJiri Kosina 	if (!magnitude) {
7316db3dfefSJiri Kosina 		pidff_playback_pid(pidff, field->logical_minimum, 0);
7326db3dfefSJiri Kosina 		return;
7336db3dfefSJiri Kosina 	}
7346db3dfefSJiri Kosina 
7356db3dfefSJiri Kosina 	pidff_playback_pid(pidff, field->logical_minimum, 1);
7366db3dfefSJiri Kosina 
7376db3dfefSJiri Kosina 	pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
7386db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum;
7396db3dfefSJiri Kosina 	pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING];
7406db3dfefSJiri Kosina 	pidff->set_effect[PID_DURATION].value[0] = 0;
7416db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
7426db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
7436db3dfefSJiri Kosina 	pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
744816cbfdaSDiogo Kastrup 	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
7456db3dfefSJiri Kosina 	pidff->set_effect[PID_START_DELAY].value[0] = 0;
7466db3dfefSJiri Kosina 
747d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
748d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
7496db3dfefSJiri Kosina }
7506db3dfefSJiri Kosina 
7516db3dfefSJiri Kosina /*
7526db3dfefSJiri Kosina  * pidff_set_autocenter() handler
7536db3dfefSJiri Kosina  */
7546db3dfefSJiri Kosina static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
7556db3dfefSJiri Kosina {
7566db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
7576db3dfefSJiri Kosina 
7586db3dfefSJiri Kosina 	pidff_autocenter(pidff, magnitude);
7596db3dfefSJiri Kosina }
7606db3dfefSJiri Kosina 
7616db3dfefSJiri Kosina /*
7626db3dfefSJiri Kosina  * Find fields from a report and fill a pidff_usage
7636db3dfefSJiri Kosina  */
7646db3dfefSJiri Kosina static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
7656db3dfefSJiri Kosina 			     struct hid_report *report, int count, int strict)
7666db3dfefSJiri Kosina {
7676db3dfefSJiri Kosina 	int i, j, k, found;
7686db3dfefSJiri Kosina 
7696db3dfefSJiri Kosina 	for (k = 0; k < count; k++) {
7706db3dfefSJiri Kosina 		found = 0;
7716db3dfefSJiri Kosina 		for (i = 0; i < report->maxfield; i++) {
7726db3dfefSJiri Kosina 			if (report->field[i]->maxusage !=
7736db3dfefSJiri Kosina 			    report->field[i]->report_count) {
7744291ee30SJoe Perches 				pr_debug("maxusage and report_count do not match, skipping\n");
7756db3dfefSJiri Kosina 				continue;
7766db3dfefSJiri Kosina 			}
7776db3dfefSJiri Kosina 			for (j = 0; j < report->field[i]->maxusage; j++) {
7786db3dfefSJiri Kosina 				if (report->field[i]->usage[j].hid ==
7796db3dfefSJiri Kosina 				    (HID_UP_PID | table[k])) {
7804291ee30SJoe Perches 					pr_debug("found %d at %d->%d\n",
7814291ee30SJoe Perches 						 k, i, j);
7826db3dfefSJiri Kosina 					usage[k].field = report->field[i];
7836db3dfefSJiri Kosina 					usage[k].value =
7846db3dfefSJiri Kosina 						&report->field[i]->value[j];
7856db3dfefSJiri Kosina 					found = 1;
7866db3dfefSJiri Kosina 					break;
7876db3dfefSJiri Kosina 				}
7886db3dfefSJiri Kosina 			}
7896db3dfefSJiri Kosina 			if (found)
7906db3dfefSJiri Kosina 				break;
7916db3dfefSJiri Kosina 		}
7926db3dfefSJiri Kosina 		if (!found && strict) {
7934291ee30SJoe Perches 			pr_debug("failed to locate %d\n", k);
7946db3dfefSJiri Kosina 			return -1;
7956db3dfefSJiri Kosina 		}
7966db3dfefSJiri Kosina 	}
7976db3dfefSJiri Kosina 	return 0;
7986db3dfefSJiri Kosina }
7996db3dfefSJiri Kosina 
8006db3dfefSJiri Kosina /*
8016db3dfefSJiri Kosina  * Return index into pidff_reports for the given usage
8026db3dfefSJiri Kosina  */
8036db3dfefSJiri Kosina static int pidff_check_usage(int usage)
8046db3dfefSJiri Kosina {
8056db3dfefSJiri Kosina 	int i;
8066db3dfefSJiri Kosina 
8076db3dfefSJiri Kosina 	for (i = 0; i < sizeof(pidff_reports); i++)
8086db3dfefSJiri Kosina 		if (usage == (HID_UP_PID | pidff_reports[i]))
8096db3dfefSJiri Kosina 			return i;
8106db3dfefSJiri Kosina 
8116db3dfefSJiri Kosina 	return -1;
8126db3dfefSJiri Kosina }
8136db3dfefSJiri Kosina 
8146db3dfefSJiri Kosina /*
8156db3dfefSJiri Kosina  * Find the reports and fill pidff->reports[]
8166db3dfefSJiri Kosina  * report_type specifies either OUTPUT or FEATURE reports
8176db3dfefSJiri Kosina  */
8186db3dfefSJiri Kosina static void pidff_find_reports(struct hid_device *hid, int report_type,
8196db3dfefSJiri Kosina 			       struct pidff_device *pidff)
8206db3dfefSJiri Kosina {
8216db3dfefSJiri Kosina 	struct hid_report *report;
8226db3dfefSJiri Kosina 	int i, ret;
8236db3dfefSJiri Kosina 
8246db3dfefSJiri Kosina 	list_for_each_entry(report,
8256db3dfefSJiri Kosina 			    &hid->report_enum[report_type].report_list, list) {
8266db3dfefSJiri Kosina 		if (report->maxfield < 1)
8276db3dfefSJiri Kosina 			continue;
8286db3dfefSJiri Kosina 		ret = pidff_check_usage(report->field[0]->logical);
8296db3dfefSJiri Kosina 		if (ret != -1) {
8304291ee30SJoe Perches 			hid_dbg(hid, "found usage 0x%02x from field->logical\n",
8316db3dfefSJiri Kosina 				pidff_reports[ret]);
8326db3dfefSJiri Kosina 			pidff->reports[ret] = report;
8336db3dfefSJiri Kosina 			continue;
8346db3dfefSJiri Kosina 		}
8356db3dfefSJiri Kosina 
8366db3dfefSJiri Kosina 		/*
8376db3dfefSJiri Kosina 		 * Sometimes logical collections are stacked to indicate
8386db3dfefSJiri Kosina 		 * different usages for the report and the field, in which
8396db3dfefSJiri Kosina 		 * case we want the usage of the parent. However, Linux HID
8406db3dfefSJiri Kosina 		 * implementation hides this fact, so we have to dig it up
8416db3dfefSJiri Kosina 		 * ourselves
8426db3dfefSJiri Kosina 		 */
8436db3dfefSJiri Kosina 		i = report->field[0]->usage[0].collection_index;
8446db3dfefSJiri Kosina 		if (i <= 0 ||
8456db3dfefSJiri Kosina 		    hid->collection[i - 1].type != HID_COLLECTION_LOGICAL)
8466db3dfefSJiri Kosina 			continue;
8476db3dfefSJiri Kosina 		ret = pidff_check_usage(hid->collection[i - 1].usage);
8486db3dfefSJiri Kosina 		if (ret != -1 && !pidff->reports[ret]) {
8494291ee30SJoe Perches 			hid_dbg(hid,
8504291ee30SJoe Perches 				"found usage 0x%02x from collection array\n",
8516db3dfefSJiri Kosina 				pidff_reports[ret]);
8526db3dfefSJiri Kosina 			pidff->reports[ret] = report;
8536db3dfefSJiri Kosina 		}
8546db3dfefSJiri Kosina 	}
8556db3dfefSJiri Kosina }
8566db3dfefSJiri Kosina 
8576db3dfefSJiri Kosina /*
8586db3dfefSJiri Kosina  * Test if the required reports have been found
8596db3dfefSJiri Kosina  */
8606db3dfefSJiri Kosina static int pidff_reports_ok(struct pidff_device *pidff)
8616db3dfefSJiri Kosina {
8626db3dfefSJiri Kosina 	int i;
8636db3dfefSJiri Kosina 
8646db3dfefSJiri Kosina 	for (i = 0; i <= PID_REQUIRED_REPORTS; i++) {
8656db3dfefSJiri Kosina 		if (!pidff->reports[i]) {
8664291ee30SJoe Perches 			hid_dbg(pidff->hid, "%d missing\n", i);
8676db3dfefSJiri Kosina 			return 0;
8686db3dfefSJiri Kosina 		}
8696db3dfefSJiri Kosina 	}
8706db3dfefSJiri Kosina 
8716db3dfefSJiri Kosina 	return 1;
8726db3dfefSJiri Kosina }
8736db3dfefSJiri Kosina 
8746db3dfefSJiri Kosina /*
8756db3dfefSJiri Kosina  * Find a field with a specific usage within a report
8766db3dfefSJiri Kosina  */
8776db3dfefSJiri Kosina static struct hid_field *pidff_find_special_field(struct hid_report *report,
8786db3dfefSJiri Kosina 						  int usage, int enforce_min)
8796db3dfefSJiri Kosina {
8806db3dfefSJiri Kosina 	int i;
8816db3dfefSJiri Kosina 
8826db3dfefSJiri Kosina 	for (i = 0; i < report->maxfield; i++) {
8836db3dfefSJiri Kosina 		if (report->field[i]->logical == (HID_UP_PID | usage) &&
8846db3dfefSJiri Kosina 		    report->field[i]->report_count > 0) {
8856db3dfefSJiri Kosina 			if (!enforce_min ||
8866db3dfefSJiri Kosina 			    report->field[i]->logical_minimum == 1)
8876db3dfefSJiri Kosina 				return report->field[i];
8886db3dfefSJiri Kosina 			else {
8894291ee30SJoe Perches 				pr_err("logical_minimum is not 1 as it should be\n");
8906db3dfefSJiri Kosina 				return NULL;
8916db3dfefSJiri Kosina 			}
8926db3dfefSJiri Kosina 		}
8936db3dfefSJiri Kosina 	}
8946db3dfefSJiri Kosina 	return NULL;
8956db3dfefSJiri Kosina }
8966db3dfefSJiri Kosina 
8976db3dfefSJiri Kosina /*
8986db3dfefSJiri Kosina  * Fill a pidff->*_id struct table
8996db3dfefSJiri Kosina  */
9006db3dfefSJiri Kosina static int pidff_find_special_keys(int *keys, struct hid_field *fld,
9016db3dfefSJiri Kosina 				   const u8 *usagetable, int count)
9026db3dfefSJiri Kosina {
9036db3dfefSJiri Kosina 
9046db3dfefSJiri Kosina 	int i, j;
9056db3dfefSJiri Kosina 	int found = 0;
9066db3dfefSJiri Kosina 
9076db3dfefSJiri Kosina 	for (i = 0; i < count; i++) {
9086db3dfefSJiri Kosina 		for (j = 0; j < fld->maxusage; j++) {
9096db3dfefSJiri Kosina 			if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) {
9106db3dfefSJiri Kosina 				keys[i] = j + 1;
9116db3dfefSJiri Kosina 				found++;
9126db3dfefSJiri Kosina 				break;
9136db3dfefSJiri Kosina 			}
9146db3dfefSJiri Kosina 		}
9156db3dfefSJiri Kosina 	}
9166db3dfefSJiri Kosina 	return found;
9176db3dfefSJiri Kosina }
9186db3dfefSJiri Kosina 
9196db3dfefSJiri Kosina #define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \
9206db3dfefSJiri Kosina 	pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \
9216db3dfefSJiri Kosina 		sizeof(pidff_ ## name))
9226db3dfefSJiri Kosina 
9236db3dfefSJiri Kosina /*
9246db3dfefSJiri Kosina  * Find and check the special fields
9256db3dfefSJiri Kosina  */
9266db3dfefSJiri Kosina static int pidff_find_special_fields(struct pidff_device *pidff)
9276db3dfefSJiri Kosina {
9284291ee30SJoe Perches 	hid_dbg(pidff->hid, "finding special fields\n");
9296db3dfefSJiri Kosina 
9306db3dfefSJiri Kosina 	pidff->create_new_effect_type =
9316db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
9326db3dfefSJiri Kosina 					 0x25, 1);
9336db3dfefSJiri Kosina 	pidff->set_effect_type =
9346db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
9356db3dfefSJiri Kosina 					 0x25, 1);
9366db3dfefSJiri Kosina 	pidff->effect_direction =
9376db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
9386db3dfefSJiri Kosina 					 0x57, 0);
9396db3dfefSJiri Kosina 	pidff->device_control =
9406db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
9416db3dfefSJiri Kosina 					 0x96, 1);
9426db3dfefSJiri Kosina 	pidff->block_load_status =
9436db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
9446db3dfefSJiri Kosina 					 0x8b, 1);
9456db3dfefSJiri Kosina 	pidff->effect_operation_status =
9466db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION],
9476db3dfefSJiri Kosina 					 0x78, 1);
9486db3dfefSJiri Kosina 
9494291ee30SJoe Perches 	hid_dbg(pidff->hid, "search done\n");
9506db3dfefSJiri Kosina 
9516db3dfefSJiri Kosina 	if (!pidff->create_new_effect_type || !pidff->set_effect_type) {
9524291ee30SJoe Perches 		hid_err(pidff->hid, "effect lists not found\n");
9536db3dfefSJiri Kosina 		return -1;
9546db3dfefSJiri Kosina 	}
9556db3dfefSJiri Kosina 
9566db3dfefSJiri Kosina 	if (!pidff->effect_direction) {
9574291ee30SJoe Perches 		hid_err(pidff->hid, "direction field not found\n");
9586db3dfefSJiri Kosina 		return -1;
9596db3dfefSJiri Kosina 	}
9606db3dfefSJiri Kosina 
9616db3dfefSJiri Kosina 	if (!pidff->device_control) {
9624291ee30SJoe Perches 		hid_err(pidff->hid, "device control field not found\n");
9636db3dfefSJiri Kosina 		return -1;
9646db3dfefSJiri Kosina 	}
9656db3dfefSJiri Kosina 
9666db3dfefSJiri Kosina 	if (!pidff->block_load_status) {
9674291ee30SJoe Perches 		hid_err(pidff->hid, "block load status field not found\n");
9686db3dfefSJiri Kosina 		return -1;
9696db3dfefSJiri Kosina 	}
9706db3dfefSJiri Kosina 
9716db3dfefSJiri Kosina 	if (!pidff->effect_operation_status) {
9724291ee30SJoe Perches 		hid_err(pidff->hid, "effect operation field not found\n");
9736db3dfefSJiri Kosina 		return -1;
9746db3dfefSJiri Kosina 	}
9756db3dfefSJiri Kosina 
9766db3dfefSJiri Kosina 	pidff_find_special_keys(pidff->control_id, pidff->device_control,
9776db3dfefSJiri Kosina 				pidff_device_control,
9786db3dfefSJiri Kosina 				sizeof(pidff_device_control));
9796db3dfefSJiri Kosina 
9806db3dfefSJiri Kosina 	PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control);
9816db3dfefSJiri Kosina 
9826db3dfefSJiri Kosina 	if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type,
9836db3dfefSJiri Kosina 				     effect_types)) {
9844291ee30SJoe Perches 		hid_err(pidff->hid, "no effect types found\n");
9856db3dfefSJiri Kosina 		return -1;
9866db3dfefSJiri Kosina 	}
9876db3dfefSJiri Kosina 
9886db3dfefSJiri Kosina 	if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status,
9896db3dfefSJiri Kosina 				    block_load_status) !=
9906db3dfefSJiri Kosina 			sizeof(pidff_block_load_status)) {
9914291ee30SJoe Perches 		hid_err(pidff->hid,
9924291ee30SJoe Perches 			"block load status identifiers not found\n");
9936db3dfefSJiri Kosina 		return -1;
9946db3dfefSJiri Kosina 	}
9956db3dfefSJiri Kosina 
9966db3dfefSJiri Kosina 	if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status,
9976db3dfefSJiri Kosina 				    effect_operation_status) !=
9986db3dfefSJiri Kosina 			sizeof(pidff_effect_operation_status)) {
9994291ee30SJoe Perches 		hid_err(pidff->hid, "effect operation identifiers not found\n");
10006db3dfefSJiri Kosina 		return -1;
10016db3dfefSJiri Kosina 	}
10026db3dfefSJiri Kosina 
10036db3dfefSJiri Kosina 	return 0;
10046db3dfefSJiri Kosina }
10056db3dfefSJiri Kosina 
10066db3dfefSJiri Kosina /**
10076db3dfefSJiri Kosina  * Find the implemented effect types
10086db3dfefSJiri Kosina  */
10096db3dfefSJiri Kosina static int pidff_find_effects(struct pidff_device *pidff,
10106db3dfefSJiri Kosina 			      struct input_dev *dev)
10116db3dfefSJiri Kosina {
10126db3dfefSJiri Kosina 	int i;
10136db3dfefSJiri Kosina 
10146db3dfefSJiri Kosina 	for (i = 0; i < sizeof(pidff_effect_types); i++) {
10156db3dfefSJiri Kosina 		int pidff_type = pidff->type_id[i];
10166db3dfefSJiri Kosina 		if (pidff->set_effect_type->usage[pidff_type].hid !=
10176db3dfefSJiri Kosina 		    pidff->create_new_effect_type->usage[pidff_type].hid) {
10184291ee30SJoe Perches 			hid_err(pidff->hid,
10196db3dfefSJiri Kosina 				"effect type number %d is invalid\n", i);
10206db3dfefSJiri Kosina 			return -1;
10216db3dfefSJiri Kosina 		}
10226db3dfefSJiri Kosina 	}
10236db3dfefSJiri Kosina 
10246db3dfefSJiri Kosina 	if (pidff->type_id[PID_CONSTANT])
10256db3dfefSJiri Kosina 		set_bit(FF_CONSTANT, dev->ffbit);
10266db3dfefSJiri Kosina 	if (pidff->type_id[PID_RAMP])
10276db3dfefSJiri Kosina 		set_bit(FF_RAMP, dev->ffbit);
10286db3dfefSJiri Kosina 	if (pidff->type_id[PID_SQUARE]) {
10296db3dfefSJiri Kosina 		set_bit(FF_SQUARE, dev->ffbit);
10306db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10316db3dfefSJiri Kosina 	}
10326db3dfefSJiri Kosina 	if (pidff->type_id[PID_SINE]) {
10336db3dfefSJiri Kosina 		set_bit(FF_SINE, dev->ffbit);
10346db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10356db3dfefSJiri Kosina 	}
10366db3dfefSJiri Kosina 	if (pidff->type_id[PID_TRIANGLE]) {
10376db3dfefSJiri Kosina 		set_bit(FF_TRIANGLE, dev->ffbit);
10386db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10396db3dfefSJiri Kosina 	}
10406db3dfefSJiri Kosina 	if (pidff->type_id[PID_SAW_UP]) {
10416db3dfefSJiri Kosina 		set_bit(FF_SAW_UP, dev->ffbit);
10426db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10436db3dfefSJiri Kosina 	}
10446db3dfefSJiri Kosina 	if (pidff->type_id[PID_SAW_DOWN]) {
10456db3dfefSJiri Kosina 		set_bit(FF_SAW_DOWN, dev->ffbit);
10466db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10476db3dfefSJiri Kosina 	}
10486db3dfefSJiri Kosina 	if (pidff->type_id[PID_SPRING])
10496db3dfefSJiri Kosina 		set_bit(FF_SPRING, dev->ffbit);
10506db3dfefSJiri Kosina 	if (pidff->type_id[PID_DAMPER])
10516db3dfefSJiri Kosina 		set_bit(FF_DAMPER, dev->ffbit);
10526db3dfefSJiri Kosina 	if (pidff->type_id[PID_INERTIA])
10536db3dfefSJiri Kosina 		set_bit(FF_INERTIA, dev->ffbit);
10546db3dfefSJiri Kosina 	if (pidff->type_id[PID_FRICTION])
10556db3dfefSJiri Kosina 		set_bit(FF_FRICTION, dev->ffbit);
10566db3dfefSJiri Kosina 
10576db3dfefSJiri Kosina 	return 0;
10586db3dfefSJiri Kosina 
10596db3dfefSJiri Kosina }
10606db3dfefSJiri Kosina 
10616db3dfefSJiri Kosina #define PIDFF_FIND_FIELDS(name, report, strict) \
10626db3dfefSJiri Kosina 	pidff_find_fields(pidff->name, pidff_ ## name, \
10636db3dfefSJiri Kosina 		pidff->reports[report], \
10646db3dfefSJiri Kosina 		sizeof(pidff_ ## name), strict)
10656db3dfefSJiri Kosina 
10666db3dfefSJiri Kosina /*
10676db3dfefSJiri Kosina  * Fill and check the pidff_usages
10686db3dfefSJiri Kosina  */
10696db3dfefSJiri Kosina static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
10706db3dfefSJiri Kosina {
10716db3dfefSJiri Kosina 	int envelope_ok = 0;
10726db3dfefSJiri Kosina 
10736db3dfefSJiri Kosina 	if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
10744291ee30SJoe Perches 		hid_err(pidff->hid, "unknown set_effect report layout\n");
10756db3dfefSJiri Kosina 		return -ENODEV;
10766db3dfefSJiri Kosina 	}
10776db3dfefSJiri Kosina 
10786db3dfefSJiri Kosina 	PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
10796db3dfefSJiri Kosina 	if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
10804291ee30SJoe Perches 		hid_err(pidff->hid, "unknown pid_block_load report layout\n");
10816db3dfefSJiri Kosina 		return -ENODEV;
10826db3dfefSJiri Kosina 	}
10836db3dfefSJiri Kosina 
10846db3dfefSJiri Kosina 	if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) {
10854291ee30SJoe Perches 		hid_err(pidff->hid, "unknown effect_operation report layout\n");
10866db3dfefSJiri Kosina 		return -ENODEV;
10876db3dfefSJiri Kosina 	}
10886db3dfefSJiri Kosina 
10896db3dfefSJiri Kosina 	if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) {
10904291ee30SJoe Perches 		hid_err(pidff->hid, "unknown pid_block_free report layout\n");
10916db3dfefSJiri Kosina 		return -ENODEV;
10926db3dfefSJiri Kosina 	}
10936db3dfefSJiri Kosina 
10946db3dfefSJiri Kosina 	if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1))
10956db3dfefSJiri Kosina 		envelope_ok = 1;
10966db3dfefSJiri Kosina 
10976db3dfefSJiri Kosina 	if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev))
10986db3dfefSJiri Kosina 		return -ENODEV;
10996db3dfefSJiri Kosina 
11006db3dfefSJiri Kosina 	if (!envelope_ok) {
11016db3dfefSJiri Kosina 		if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
11024291ee30SJoe Perches 			hid_warn(pidff->hid,
11036db3dfefSJiri Kosina 				 "has constant effect but no envelope\n");
11046db3dfefSJiri Kosina 		if (test_and_clear_bit(FF_RAMP, dev->ffbit))
11054291ee30SJoe Perches 			hid_warn(pidff->hid,
11066db3dfefSJiri Kosina 				 "has ramp effect but no envelope\n");
11076db3dfefSJiri Kosina 
11086db3dfefSJiri Kosina 		if (test_and_clear_bit(FF_PERIODIC, dev->ffbit))
11094291ee30SJoe Perches 			hid_warn(pidff->hid,
11106db3dfefSJiri Kosina 				 "has periodic effect but no envelope\n");
11116db3dfefSJiri Kosina 	}
11126db3dfefSJiri Kosina 
11136db3dfefSJiri Kosina 	if (test_bit(FF_CONSTANT, dev->ffbit) &&
11146db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) {
11154291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown constant effect layout\n");
11166db3dfefSJiri Kosina 		clear_bit(FF_CONSTANT, dev->ffbit);
11176db3dfefSJiri Kosina 	}
11186db3dfefSJiri Kosina 
11196db3dfefSJiri Kosina 	if (test_bit(FF_RAMP, dev->ffbit) &&
11206db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) {
11214291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown ramp effect layout\n");
11226db3dfefSJiri Kosina 		clear_bit(FF_RAMP, dev->ffbit);
11236db3dfefSJiri Kosina 	}
11246db3dfefSJiri Kosina 
11256db3dfefSJiri Kosina 	if ((test_bit(FF_SPRING, dev->ffbit) ||
11266db3dfefSJiri Kosina 	     test_bit(FF_DAMPER, dev->ffbit) ||
11276db3dfefSJiri Kosina 	     test_bit(FF_FRICTION, dev->ffbit) ||
11286db3dfefSJiri Kosina 	     test_bit(FF_INERTIA, dev->ffbit)) &&
11296db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
11304291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown condition effect layout\n");
11316db3dfefSJiri Kosina 		clear_bit(FF_SPRING, dev->ffbit);
11326db3dfefSJiri Kosina 		clear_bit(FF_DAMPER, dev->ffbit);
11336db3dfefSJiri Kosina 		clear_bit(FF_FRICTION, dev->ffbit);
11346db3dfefSJiri Kosina 		clear_bit(FF_INERTIA, dev->ffbit);
11356db3dfefSJiri Kosina 	}
11366db3dfefSJiri Kosina 
11376db3dfefSJiri Kosina 	if (test_bit(FF_PERIODIC, dev->ffbit) &&
11386db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) {
11394291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown periodic effect layout\n");
11406db3dfefSJiri Kosina 		clear_bit(FF_PERIODIC, dev->ffbit);
11416db3dfefSJiri Kosina 	}
11426db3dfefSJiri Kosina 
11436db3dfefSJiri Kosina 	PIDFF_FIND_FIELDS(pool, PID_POOL, 0);
11446db3dfefSJiri Kosina 
11456db3dfefSJiri Kosina 	if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1))
11466db3dfefSJiri Kosina 		set_bit(FF_GAIN, dev->ffbit);
11476db3dfefSJiri Kosina 
11486db3dfefSJiri Kosina 	return 0;
11496db3dfefSJiri Kosina }
11506db3dfefSJiri Kosina 
11516db3dfefSJiri Kosina /*
11526db3dfefSJiri Kosina  * Reset the device
11536db3dfefSJiri Kosina  */
11546db3dfefSJiri Kosina static void pidff_reset(struct pidff_device *pidff)
11556db3dfefSJiri Kosina {
11566db3dfefSJiri Kosina 	struct hid_device *hid = pidff->hid;
11576db3dfefSJiri Kosina 	int i = 0;
11586db3dfefSJiri Kosina 
11596db3dfefSJiri Kosina 	pidff->device_control->value[0] = pidff->control_id[PID_RESET];
11606db3dfefSJiri Kosina 	/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
1161d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
1162b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
1163d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
1164b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
11656db3dfefSJiri Kosina 
11666db3dfefSJiri Kosina 	pidff->device_control->value[0] =
11676db3dfefSJiri Kosina 		pidff->control_id[PID_ENABLE_ACTUATORS];
1168d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
1169b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
11706db3dfefSJiri Kosina 
11716db3dfefSJiri Kosina 	/* pool report is sometimes messed up, refetch it */
1172d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
1173b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
11746db3dfefSJiri Kosina 
11756db3dfefSJiri Kosina 	if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
11761168df7eSAnssi Hannula 		while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
11776db3dfefSJiri Kosina 			if (i++ > 20) {
11784291ee30SJoe Perches 				hid_warn(pidff->hid,
11794291ee30SJoe Perches 					 "device reports %d simultaneous effects\n",
11801168df7eSAnssi Hannula 					 pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
11816db3dfefSJiri Kosina 				break;
11826db3dfefSJiri Kosina 			}
11834291ee30SJoe Perches 			hid_dbg(pidff->hid, "pid_pool requested again\n");
1184d8814272SBenjamin Tissoires 			hid_hw_request(hid, pidff->reports[PID_POOL],
1185d8814272SBenjamin Tissoires 					  HID_REQ_GET_REPORT);
1186b7966a4dSBenjamin Tissoires 			hid_hw_wait(hid);
11876db3dfefSJiri Kosina 		}
11886db3dfefSJiri Kosina 	}
11896db3dfefSJiri Kosina }
11906db3dfefSJiri Kosina 
11916db3dfefSJiri Kosina /*
11926db3dfefSJiri Kosina  * Test if autocenter modification is using the supported method
11936db3dfefSJiri Kosina  */
11946db3dfefSJiri Kosina static int pidff_check_autocenter(struct pidff_device *pidff,
11956db3dfefSJiri Kosina 				  struct input_dev *dev)
11966db3dfefSJiri Kosina {
11976db3dfefSJiri Kosina 	int error;
11986db3dfefSJiri Kosina 
11996db3dfefSJiri Kosina 	/*
12006db3dfefSJiri Kosina 	 * Let's find out if autocenter modification is supported
12016db3dfefSJiri Kosina 	 * Specification doesn't specify anything, so we request an
12026db3dfefSJiri Kosina 	 * effect upload and cancel it immediately. If the approved
12036db3dfefSJiri Kosina 	 * effect id was one above the minimum, then we assume the first
12046db3dfefSJiri Kosina 	 * effect id is a built-in spring type effect used for autocenter
12056db3dfefSJiri Kosina 	 */
12066db3dfefSJiri Kosina 
12076db3dfefSJiri Kosina 	error = pidff_request_effect_upload(pidff, 1);
12086db3dfefSJiri Kosina 	if (error) {
12094291ee30SJoe Perches 		hid_err(pidff->hid, "upload request failed\n");
12106db3dfefSJiri Kosina 		return error;
12116db3dfefSJiri Kosina 	}
12126db3dfefSJiri Kosina 
12136db3dfefSJiri Kosina 	if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] ==
12146db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) {
12156db3dfefSJiri Kosina 		pidff_autocenter(pidff, 0xffff);
12166db3dfefSJiri Kosina 		set_bit(FF_AUTOCENTER, dev->ffbit);
12176db3dfefSJiri Kosina 	} else {
12184291ee30SJoe Perches 		hid_notice(pidff->hid,
12196db3dfefSJiri Kosina 			   "device has unknown autocenter control method\n");
12206db3dfefSJiri Kosina 	}
12216db3dfefSJiri Kosina 
12226db3dfefSJiri Kosina 	pidff_erase_pid(pidff,
12236db3dfefSJiri Kosina 			pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]);
12246db3dfefSJiri Kosina 
12256db3dfefSJiri Kosina 	return 0;
12266db3dfefSJiri Kosina 
12276db3dfefSJiri Kosina }
12286db3dfefSJiri Kosina 
12296db3dfefSJiri Kosina /*
12306db3dfefSJiri Kosina  * Check if the device is PID and initialize it
12316db3dfefSJiri Kosina  */
12326db3dfefSJiri Kosina int hid_pidff_init(struct hid_device *hid)
12336db3dfefSJiri Kosina {
12346db3dfefSJiri Kosina 	struct pidff_device *pidff;
12356db3dfefSJiri Kosina 	struct hid_input *hidinput = list_entry(hid->inputs.next,
12366db3dfefSJiri Kosina 						struct hid_input, list);
12376db3dfefSJiri Kosina 	struct input_dev *dev = hidinput->input;
12386db3dfefSJiri Kosina 	struct ff_device *ff;
12396db3dfefSJiri Kosina 	int max_effects;
12406db3dfefSJiri Kosina 	int error;
12416db3dfefSJiri Kosina 
12424291ee30SJoe Perches 	hid_dbg(hid, "starting pid init\n");
12436db3dfefSJiri Kosina 
12446db3dfefSJiri Kosina 	if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) {
12454291ee30SJoe Perches 		hid_dbg(hid, "not a PID device, no output report\n");
12466db3dfefSJiri Kosina 		return -ENODEV;
12476db3dfefSJiri Kosina 	}
12486db3dfefSJiri Kosina 
12496db3dfefSJiri Kosina 	pidff = kzalloc(sizeof(*pidff), GFP_KERNEL);
12506db3dfefSJiri Kosina 	if (!pidff)
12516db3dfefSJiri Kosina 		return -ENOMEM;
12526db3dfefSJiri Kosina 
12536db3dfefSJiri Kosina 	pidff->hid = hid;
12546db3dfefSJiri Kosina 
1255afd700d9SJim Keir 	hid_device_io_start(hid);
1256afd700d9SJim Keir 
12576db3dfefSJiri Kosina 	pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff);
12586db3dfefSJiri Kosina 	pidff_find_reports(hid, HID_FEATURE_REPORT, pidff);
12596db3dfefSJiri Kosina 
12606db3dfefSJiri Kosina 	if (!pidff_reports_ok(pidff)) {
12614291ee30SJoe Perches 		hid_dbg(hid, "reports not ok, aborting\n");
12626db3dfefSJiri Kosina 		error = -ENODEV;
12636db3dfefSJiri Kosina 		goto fail;
12646db3dfefSJiri Kosina 	}
12656db3dfefSJiri Kosina 
12666db3dfefSJiri Kosina 	error = pidff_init_fields(pidff, dev);
12676db3dfefSJiri Kosina 	if (error)
12686db3dfefSJiri Kosina 		goto fail;
12696db3dfefSJiri Kosina 
12706db3dfefSJiri Kosina 	pidff_reset(pidff);
12716db3dfefSJiri Kosina 
12726db3dfefSJiri Kosina 	if (test_bit(FF_GAIN, dev->ffbit)) {
12736db3dfefSJiri Kosina 		pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
1274d8814272SBenjamin Tissoires 		hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
1275d8814272SBenjamin Tissoires 				     HID_REQ_SET_REPORT);
12766db3dfefSJiri Kosina 	}
12776db3dfefSJiri Kosina 
12786db3dfefSJiri Kosina 	error = pidff_check_autocenter(pidff, dev);
12796db3dfefSJiri Kosina 	if (error)
12806db3dfefSJiri Kosina 		goto fail;
12816db3dfefSJiri Kosina 
12826db3dfefSJiri Kosina 	max_effects =
12836db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum -
12846db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum +
12856db3dfefSJiri Kosina 	    1;
12864291ee30SJoe Perches 	hid_dbg(hid, "max effects is %d\n", max_effects);
12876db3dfefSJiri Kosina 
12886db3dfefSJiri Kosina 	if (max_effects > PID_EFFECTS_MAX)
12896db3dfefSJiri Kosina 		max_effects = PID_EFFECTS_MAX;
12906db3dfefSJiri Kosina 
12916db3dfefSJiri Kosina 	if (pidff->pool[PID_SIMULTANEOUS_MAX].value)
12924291ee30SJoe Perches 		hid_dbg(hid, "max simultaneous effects is %d\n",
12936db3dfefSJiri Kosina 			pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
12946db3dfefSJiri Kosina 
12956db3dfefSJiri Kosina 	if (pidff->pool[PID_RAM_POOL_SIZE].value)
12964291ee30SJoe Perches 		hid_dbg(hid, "device memory size is %d bytes\n",
12976db3dfefSJiri Kosina 			pidff->pool[PID_RAM_POOL_SIZE].value[0]);
12986db3dfefSJiri Kosina 
12996db3dfefSJiri Kosina 	if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
13006db3dfefSJiri Kosina 	    pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
13014291ee30SJoe Perches 		hid_notice(hid,
13026db3dfefSJiri Kosina 			   "device does not support device managed pool\n");
13036db3dfefSJiri Kosina 		goto fail;
13046db3dfefSJiri Kosina 	}
13056db3dfefSJiri Kosina 
13066db3dfefSJiri Kosina 	error = input_ff_create(dev, max_effects);
13076db3dfefSJiri Kosina 	if (error)
13086db3dfefSJiri Kosina 		goto fail;
13096db3dfefSJiri Kosina 
13106db3dfefSJiri Kosina 	ff = dev->ff;
13116db3dfefSJiri Kosina 	ff->private = pidff;
13126db3dfefSJiri Kosina 	ff->upload = pidff_upload_effect;
13136db3dfefSJiri Kosina 	ff->erase = pidff_erase_effect;
13146db3dfefSJiri Kosina 	ff->set_gain = pidff_set_gain;
13156db3dfefSJiri Kosina 	ff->set_autocenter = pidff_set_autocenter;
13166db3dfefSJiri Kosina 	ff->playback = pidff_playback;
13176db3dfefSJiri Kosina 
13184291ee30SJoe Perches 	hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
13196db3dfefSJiri Kosina 
1320afd700d9SJim Keir 	hid_device_io_stop(hid);
1321afd700d9SJim Keir 
13226db3dfefSJiri Kosina 	return 0;
13236db3dfefSJiri Kosina 
13246db3dfefSJiri Kosina  fail:
1325afd700d9SJim Keir 	hid_device_io_stop(hid);
1326afd700d9SJim Keir 
13276db3dfefSJiri Kosina 	kfree(pidff);
13286db3dfefSJiri Kosina 	return error;
13296db3dfefSJiri Kosina }
1330