xref: /openbmc/linux/drivers/hid/usbhid/hid-pidff.c (revision 3dd653c0)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
26db3dfefSJiri Kosina /*
36db3dfefSJiri Kosina  *  Force feedback driver for USB HID PID compliant devices
46db3dfefSJiri Kosina  *
56db3dfefSJiri Kosina  *  Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com>
66db3dfefSJiri Kosina  */
76db3dfefSJiri Kosina 
86db3dfefSJiri Kosina /*
96db3dfefSJiri Kosina  */
106db3dfefSJiri Kosina 
116db3dfefSJiri Kosina /* #define DEBUG */
126db3dfefSJiri Kosina 
134291ee30SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
146db3dfefSJiri Kosina 
156db3dfefSJiri Kosina #include <linux/input.h>
165a0e3ad6STejun Heo #include <linux/slab.h>
176db3dfefSJiri Kosina #include <linux/usb.h>
186db3dfefSJiri Kosina 
196db3dfefSJiri Kosina #include <linux/hid.h>
206db3dfefSJiri Kosina 
216db3dfefSJiri Kosina #include "usbhid.h"
226db3dfefSJiri Kosina 
236db3dfefSJiri Kosina #define	PID_EFFECTS_MAX		64
246db3dfefSJiri Kosina 
256db3dfefSJiri Kosina /* Report usage table used to put reports into an array */
266db3dfefSJiri Kosina 
276db3dfefSJiri Kosina #define PID_SET_EFFECT		0
286db3dfefSJiri Kosina #define PID_EFFECT_OPERATION	1
296db3dfefSJiri Kosina #define PID_DEVICE_GAIN		2
306db3dfefSJiri Kosina #define PID_POOL		3
316db3dfefSJiri Kosina #define PID_BLOCK_LOAD		4
326db3dfefSJiri Kosina #define PID_BLOCK_FREE		5
336db3dfefSJiri Kosina #define PID_DEVICE_CONTROL	6
346db3dfefSJiri Kosina #define PID_CREATE_NEW_EFFECT	7
356db3dfefSJiri Kosina 
366db3dfefSJiri Kosina #define PID_REQUIRED_REPORTS	7
376db3dfefSJiri Kosina 
386db3dfefSJiri Kosina #define PID_SET_ENVELOPE	8
396db3dfefSJiri Kosina #define PID_SET_CONDITION	9
406db3dfefSJiri Kosina #define PID_SET_PERIODIC	10
416db3dfefSJiri Kosina #define PID_SET_CONSTANT	11
426db3dfefSJiri Kosina #define PID_SET_RAMP		12
436db3dfefSJiri Kosina static const u8 pidff_reports[] = {
446db3dfefSJiri Kosina 	0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab,
456db3dfefSJiri Kosina 	0x5a, 0x5f, 0x6e, 0x73, 0x74
466db3dfefSJiri Kosina };
476db3dfefSJiri Kosina 
486db3dfefSJiri Kosina /* device_control is really 0x95, but 0x96 specified as it is the usage of
496db3dfefSJiri Kosina the only field in that report */
506db3dfefSJiri Kosina 
516db3dfefSJiri Kosina /* Value usage tables used to put fields and values into arrays */
526db3dfefSJiri Kosina 
536db3dfefSJiri Kosina #define PID_EFFECT_BLOCK_INDEX	0
546db3dfefSJiri Kosina 
556db3dfefSJiri Kosina #define PID_DURATION		1
566db3dfefSJiri Kosina #define PID_GAIN		2
576db3dfefSJiri Kosina #define PID_TRIGGER_BUTTON	3
586db3dfefSJiri Kosina #define PID_TRIGGER_REPEAT_INT	4
596db3dfefSJiri Kosina #define PID_DIRECTION_ENABLE	5
606db3dfefSJiri Kosina #define PID_START_DELAY		6
616db3dfefSJiri Kosina static const u8 pidff_set_effect[] = {
626db3dfefSJiri Kosina 	0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7
636db3dfefSJiri Kosina };
646db3dfefSJiri Kosina 
656db3dfefSJiri Kosina #define PID_ATTACK_LEVEL	1
666db3dfefSJiri Kosina #define PID_ATTACK_TIME		2
676db3dfefSJiri Kosina #define PID_FADE_LEVEL		3
686db3dfefSJiri Kosina #define PID_FADE_TIME		4
696db3dfefSJiri Kosina static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e };
706db3dfefSJiri Kosina 
716db3dfefSJiri Kosina #define PID_PARAM_BLOCK_OFFSET	1
726db3dfefSJiri Kosina #define PID_CP_OFFSET		2
736db3dfefSJiri Kosina #define PID_POS_COEFFICIENT	3
746db3dfefSJiri Kosina #define PID_NEG_COEFFICIENT	4
756db3dfefSJiri Kosina #define PID_POS_SATURATION	5
766db3dfefSJiri Kosina #define PID_NEG_SATURATION	6
776db3dfefSJiri Kosina #define PID_DEAD_BAND		7
786db3dfefSJiri Kosina static const u8 pidff_set_condition[] = {
796db3dfefSJiri Kosina 	0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65
806db3dfefSJiri Kosina };
816db3dfefSJiri Kosina 
826db3dfefSJiri Kosina #define PID_MAGNITUDE		1
836db3dfefSJiri Kosina #define PID_OFFSET		2
846db3dfefSJiri Kosina #define PID_PHASE		3
856db3dfefSJiri Kosina #define PID_PERIOD		4
866db3dfefSJiri Kosina static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 };
876db3dfefSJiri Kosina static const u8 pidff_set_constant[] = { 0x22, 0x70 };
886db3dfefSJiri Kosina 
896db3dfefSJiri Kosina #define PID_RAMP_START		1
906db3dfefSJiri Kosina #define PID_RAMP_END		2
916db3dfefSJiri Kosina static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 };
926db3dfefSJiri Kosina 
936db3dfefSJiri Kosina #define PID_RAM_POOL_AVAILABLE	1
946db3dfefSJiri Kosina static const u8 pidff_block_load[] = { 0x22, 0xac };
956db3dfefSJiri Kosina 
966db3dfefSJiri Kosina #define PID_LOOP_COUNT		1
976db3dfefSJiri Kosina static const u8 pidff_effect_operation[] = { 0x22, 0x7c };
986db3dfefSJiri Kosina 
996db3dfefSJiri Kosina static const u8 pidff_block_free[] = { 0x22 };
1006db3dfefSJiri Kosina 
1016db3dfefSJiri Kosina #define PID_DEVICE_GAIN_FIELD	0
1026db3dfefSJiri Kosina static const u8 pidff_device_gain[] = { 0x7e };
1036db3dfefSJiri Kosina 
1046db3dfefSJiri Kosina #define PID_RAM_POOL_SIZE	0
1056db3dfefSJiri Kosina #define PID_SIMULTANEOUS_MAX	1
1066db3dfefSJiri Kosina #define PID_DEVICE_MANAGED_POOL	2
1076db3dfefSJiri Kosina static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 };
1086db3dfefSJiri Kosina 
1096db3dfefSJiri Kosina /* Special field key tables used to put special field keys into arrays */
1106db3dfefSJiri Kosina 
1116db3dfefSJiri Kosina #define PID_ENABLE_ACTUATORS	0
1126db3dfefSJiri Kosina #define PID_RESET		1
1136db3dfefSJiri Kosina static const u8 pidff_device_control[] = { 0x97, 0x9a };
1146db3dfefSJiri Kosina 
1156db3dfefSJiri Kosina #define PID_CONSTANT	0
1166db3dfefSJiri Kosina #define PID_RAMP	1
1176db3dfefSJiri Kosina #define PID_SQUARE	2
1186db3dfefSJiri Kosina #define PID_SINE	3
1196db3dfefSJiri Kosina #define PID_TRIANGLE	4
1206db3dfefSJiri Kosina #define PID_SAW_UP	5
1216db3dfefSJiri Kosina #define PID_SAW_DOWN	6
1226db3dfefSJiri Kosina #define PID_SPRING	7
1236db3dfefSJiri Kosina #define PID_DAMPER	8
1246db3dfefSJiri Kosina #define PID_INERTIA	9
1256db3dfefSJiri Kosina #define PID_FRICTION	10
1266db3dfefSJiri Kosina static const u8 pidff_effect_types[] = {
1276db3dfefSJiri Kosina 	0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34,
1286db3dfefSJiri Kosina 	0x40, 0x41, 0x42, 0x43
1296db3dfefSJiri Kosina };
1306db3dfefSJiri Kosina 
1316db3dfefSJiri Kosina #define PID_BLOCK_LOAD_SUCCESS	0
1326db3dfefSJiri Kosina #define PID_BLOCK_LOAD_FULL	1
1336db3dfefSJiri Kosina static const u8 pidff_block_load_status[] = { 0x8c, 0x8d };
1346db3dfefSJiri Kosina 
1356db3dfefSJiri Kosina #define PID_EFFECT_START	0
1366db3dfefSJiri Kosina #define PID_EFFECT_STOP		1
1376db3dfefSJiri Kosina static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
1386db3dfefSJiri Kosina 
1396db3dfefSJiri Kosina struct pidff_usage {
1406db3dfefSJiri Kosina 	struct hid_field *field;
1416db3dfefSJiri Kosina 	s32 *value;
1426db3dfefSJiri Kosina };
1436db3dfefSJiri Kosina 
1446db3dfefSJiri Kosina struct pidff_device {
1456db3dfefSJiri Kosina 	struct hid_device *hid;
1466db3dfefSJiri Kosina 
1476db3dfefSJiri Kosina 	struct hid_report *reports[sizeof(pidff_reports)];
1486db3dfefSJiri Kosina 
1496db3dfefSJiri Kosina 	struct pidff_usage set_effect[sizeof(pidff_set_effect)];
1506db3dfefSJiri Kosina 	struct pidff_usage set_envelope[sizeof(pidff_set_envelope)];
1516db3dfefSJiri Kosina 	struct pidff_usage set_condition[sizeof(pidff_set_condition)];
1526db3dfefSJiri Kosina 	struct pidff_usage set_periodic[sizeof(pidff_set_periodic)];
1536db3dfefSJiri Kosina 	struct pidff_usage set_constant[sizeof(pidff_set_constant)];
1546db3dfefSJiri Kosina 	struct pidff_usage set_ramp[sizeof(pidff_set_ramp)];
1556db3dfefSJiri Kosina 
1566db3dfefSJiri Kosina 	struct pidff_usage device_gain[sizeof(pidff_device_gain)];
1576db3dfefSJiri Kosina 	struct pidff_usage block_load[sizeof(pidff_block_load)];
1586db3dfefSJiri Kosina 	struct pidff_usage pool[sizeof(pidff_pool)];
1596db3dfefSJiri Kosina 	struct pidff_usage effect_operation[sizeof(pidff_effect_operation)];
1606db3dfefSJiri Kosina 	struct pidff_usage block_free[sizeof(pidff_block_free)];
1616db3dfefSJiri Kosina 
1626db3dfefSJiri Kosina 	/* Special field is a field that is not composed of
1636db3dfefSJiri Kosina 	   usage<->value pairs that pidff_usage values are */
1646db3dfefSJiri Kosina 
1656db3dfefSJiri Kosina 	/* Special field in create_new_effect */
1666db3dfefSJiri Kosina 	struct hid_field *create_new_effect_type;
1676db3dfefSJiri Kosina 
1686db3dfefSJiri Kosina 	/* Special fields in set_effect */
1696db3dfefSJiri Kosina 	struct hid_field *set_effect_type;
1706db3dfefSJiri Kosina 	struct hid_field *effect_direction;
1716db3dfefSJiri Kosina 
1726db3dfefSJiri Kosina 	/* Special field in device_control */
1736db3dfefSJiri Kosina 	struct hid_field *device_control;
1746db3dfefSJiri Kosina 
1756db3dfefSJiri Kosina 	/* Special field in block_load */
1766db3dfefSJiri Kosina 	struct hid_field *block_load_status;
1776db3dfefSJiri Kosina 
1786db3dfefSJiri Kosina 	/* Special field in effect_operation */
1796db3dfefSJiri Kosina 	struct hid_field *effect_operation_status;
1806db3dfefSJiri Kosina 
1816db3dfefSJiri Kosina 	int control_id[sizeof(pidff_device_control)];
1826db3dfefSJiri Kosina 	int type_id[sizeof(pidff_effect_types)];
1836db3dfefSJiri Kosina 	int status_id[sizeof(pidff_block_load_status)];
1846db3dfefSJiri Kosina 	int operation_id[sizeof(pidff_effect_operation_status)];
1856db3dfefSJiri Kosina 
1866db3dfefSJiri Kosina 	int pid_id[PID_EFFECTS_MAX];
1876db3dfefSJiri Kosina };
1886db3dfefSJiri Kosina 
1896db3dfefSJiri Kosina /*
1906db3dfefSJiri Kosina  * Scale an unsigned value with range 0..max for the given field
1916db3dfefSJiri Kosina  */
pidff_rescale(int i,int max,struct hid_field * field)1926db3dfefSJiri Kosina static int pidff_rescale(int i, int max, struct hid_field *field)
1936db3dfefSJiri Kosina {
1946db3dfefSJiri Kosina 	return i * (field->logical_maximum - field->logical_minimum) / max +
1956db3dfefSJiri Kosina 	    field->logical_minimum;
1966db3dfefSJiri Kosina }
1976db3dfefSJiri Kosina 
1986db3dfefSJiri Kosina /*
1996db3dfefSJiri Kosina  * Scale a signed value in range -0x8000..0x7fff for the given field
2006db3dfefSJiri Kosina  */
pidff_rescale_signed(int i,struct hid_field * field)2016db3dfefSJiri Kosina static int pidff_rescale_signed(int i, struct hid_field *field)
2026db3dfefSJiri Kosina {
2036db3dfefSJiri Kosina 	return i == 0 ? 0 : i >
2046db3dfefSJiri Kosina 	    0 ? i * field->logical_maximum / 0x7fff : i *
2056db3dfefSJiri Kosina 	    field->logical_minimum / -0x8000;
2066db3dfefSJiri Kosina }
2076db3dfefSJiri Kosina 
pidff_set(struct pidff_usage * usage,u16 value)2086db3dfefSJiri Kosina static void pidff_set(struct pidff_usage *usage, u16 value)
2096db3dfefSJiri Kosina {
2106db3dfefSJiri Kosina 	usage->value[0] = pidff_rescale(value, 0xffff, usage->field);
2114291ee30SJoe Perches 	pr_debug("calculated from %d to %d\n", value, usage->value[0]);
2126db3dfefSJiri Kosina }
2136db3dfefSJiri Kosina 
pidff_set_signed(struct pidff_usage * usage,s16 value)2146db3dfefSJiri Kosina static void pidff_set_signed(struct pidff_usage *usage, s16 value)
2156db3dfefSJiri Kosina {
2166db3dfefSJiri Kosina 	if (usage->field->logical_minimum < 0)
2176db3dfefSJiri Kosina 		usage->value[0] = pidff_rescale_signed(value, usage->field);
2186db3dfefSJiri Kosina 	else {
2196db3dfefSJiri Kosina 		if (value < 0)
2206db3dfefSJiri Kosina 			usage->value[0] =
2216db3dfefSJiri Kosina 			    pidff_rescale(-value, 0x8000, usage->field);
2226db3dfefSJiri Kosina 		else
2236db3dfefSJiri Kosina 			usage->value[0] =
2246db3dfefSJiri Kosina 			    pidff_rescale(value, 0x7fff, usage->field);
2256db3dfefSJiri Kosina 	}
2264291ee30SJoe Perches 	pr_debug("calculated from %d to %d\n", value, usage->value[0]);
2276db3dfefSJiri Kosina }
2286db3dfefSJiri Kosina 
2296db3dfefSJiri Kosina /*
2306db3dfefSJiri Kosina  * Send envelope report to the device
2316db3dfefSJiri Kosina  */
pidff_set_envelope_report(struct pidff_device * pidff,struct ff_envelope * envelope)2326db3dfefSJiri Kosina static void pidff_set_envelope_report(struct pidff_device *pidff,
2336db3dfefSJiri Kosina 				      struct ff_envelope *envelope)
2346db3dfefSJiri Kosina {
2356db3dfefSJiri Kosina 	pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] =
2366db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
2376db3dfefSJiri Kosina 
2386db3dfefSJiri Kosina 	pidff->set_envelope[PID_ATTACK_LEVEL].value[0] =
2396db3dfefSJiri Kosina 	    pidff_rescale(envelope->attack_level >
2406db3dfefSJiri Kosina 			  0x7fff ? 0x7fff : envelope->attack_level, 0x7fff,
2416db3dfefSJiri Kosina 			  pidff->set_envelope[PID_ATTACK_LEVEL].field);
2426db3dfefSJiri Kosina 	pidff->set_envelope[PID_FADE_LEVEL].value[0] =
2436db3dfefSJiri Kosina 	    pidff_rescale(envelope->fade_level >
2446db3dfefSJiri Kosina 			  0x7fff ? 0x7fff : envelope->fade_level, 0x7fff,
2456db3dfefSJiri Kosina 			  pidff->set_envelope[PID_FADE_LEVEL].field);
2466db3dfefSJiri Kosina 
2476db3dfefSJiri Kosina 	pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length;
2486db3dfefSJiri Kosina 	pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length;
2496db3dfefSJiri Kosina 
2504291ee30SJoe Perches 	hid_dbg(pidff->hid, "attack %u => %d\n",
2514291ee30SJoe Perches 		envelope->attack_level,
2526db3dfefSJiri Kosina 		pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
2536db3dfefSJiri Kosina 
254d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
255d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
2566db3dfefSJiri Kosina }
2576db3dfefSJiri Kosina 
2586db3dfefSJiri Kosina /*
2596db3dfefSJiri Kosina  * Test if the new envelope differs from old one
2606db3dfefSJiri Kosina  */
pidff_needs_set_envelope(struct ff_envelope * envelope,struct ff_envelope * old)2616db3dfefSJiri Kosina static int pidff_needs_set_envelope(struct ff_envelope *envelope,
2626db3dfefSJiri Kosina 				    struct ff_envelope *old)
2636db3dfefSJiri Kosina {
2646db3dfefSJiri Kosina 	return envelope->attack_level != old->attack_level ||
2656db3dfefSJiri Kosina 	       envelope->fade_level != old->fade_level ||
2666db3dfefSJiri Kosina 	       envelope->attack_length != old->attack_length ||
2676db3dfefSJiri Kosina 	       envelope->fade_length != old->fade_length;
2686db3dfefSJiri Kosina }
2696db3dfefSJiri Kosina 
2706db3dfefSJiri Kosina /*
2716db3dfefSJiri Kosina  * Send constant force report to the device
2726db3dfefSJiri Kosina  */
pidff_set_constant_force_report(struct pidff_device * pidff,struct ff_effect * effect)2736db3dfefSJiri Kosina static void pidff_set_constant_force_report(struct pidff_device *pidff,
2746db3dfefSJiri Kosina 					    struct ff_effect *effect)
2756db3dfefSJiri Kosina {
2766db3dfefSJiri Kosina 	pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] =
2776db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
2786db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
2796db3dfefSJiri Kosina 			 effect->u.constant.level);
2806db3dfefSJiri Kosina 
281d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT],
282d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
2836db3dfefSJiri Kosina }
2846db3dfefSJiri Kosina 
2856db3dfefSJiri Kosina /*
2866db3dfefSJiri Kosina  * Test if the constant parameters have changed between effects
2876db3dfefSJiri Kosina  */
pidff_needs_set_constant(struct ff_effect * effect,struct ff_effect * old)2886db3dfefSJiri Kosina static int pidff_needs_set_constant(struct ff_effect *effect,
2896db3dfefSJiri Kosina 				    struct ff_effect *old)
2906db3dfefSJiri Kosina {
2916db3dfefSJiri Kosina 	return effect->u.constant.level != old->u.constant.level;
2926db3dfefSJiri Kosina }
2936db3dfefSJiri Kosina 
2946db3dfefSJiri Kosina /*
2956db3dfefSJiri Kosina  * Send set effect report to the device
2966db3dfefSJiri Kosina  */
pidff_set_effect_report(struct pidff_device * pidff,struct ff_effect * effect)2976db3dfefSJiri Kosina static void pidff_set_effect_report(struct pidff_device *pidff,
2986db3dfefSJiri Kosina 				    struct ff_effect *effect)
2996db3dfefSJiri Kosina {
3006db3dfefSJiri Kosina 	pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
3016db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
3026db3dfefSJiri Kosina 	pidff->set_effect_type->value[0] =
3036db3dfefSJiri Kosina 		pidff->create_new_effect_type->value[0];
3046db3dfefSJiri Kosina 	pidff->set_effect[PID_DURATION].value[0] = effect->replay.length;
3056db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
3066db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] =
3076db3dfefSJiri Kosina 		effect->trigger.interval;
3086db3dfefSJiri Kosina 	pidff->set_effect[PID_GAIN].value[0] =
3096db3dfefSJiri Kosina 		pidff->set_effect[PID_GAIN].field->logical_maximum;
3106db3dfefSJiri Kosina 	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
3116db3dfefSJiri Kosina 	pidff->effect_direction->value[0] =
3126db3dfefSJiri Kosina 		pidff_rescale(effect->direction, 0xffff,
3136db3dfefSJiri Kosina 				pidff->effect_direction);
3146db3dfefSJiri Kosina 	pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
3156db3dfefSJiri Kosina 
316d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
317d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
3186db3dfefSJiri Kosina }
3196db3dfefSJiri Kosina 
3206db3dfefSJiri Kosina /*
3216db3dfefSJiri Kosina  * Test if the values used in set_effect have changed
3226db3dfefSJiri Kosina  */
pidff_needs_set_effect(struct ff_effect * effect,struct ff_effect * old)3236db3dfefSJiri Kosina static int pidff_needs_set_effect(struct ff_effect *effect,
3246db3dfefSJiri Kosina 				  struct ff_effect *old)
3256db3dfefSJiri Kosina {
3266db3dfefSJiri Kosina 	return effect->replay.length != old->replay.length ||
3276db3dfefSJiri Kosina 	       effect->trigger.interval != old->trigger.interval ||
3286db3dfefSJiri Kosina 	       effect->trigger.button != old->trigger.button ||
3296db3dfefSJiri Kosina 	       effect->direction != old->direction ||
3306db3dfefSJiri Kosina 	       effect->replay.delay != old->replay.delay;
3316db3dfefSJiri Kosina }
3326db3dfefSJiri Kosina 
3336db3dfefSJiri Kosina /*
3346db3dfefSJiri Kosina  * Send periodic effect report to the device
3356db3dfefSJiri Kosina  */
pidff_set_periodic_report(struct pidff_device * pidff,struct ff_effect * effect)3366db3dfefSJiri Kosina static void pidff_set_periodic_report(struct pidff_device *pidff,
3376db3dfefSJiri Kosina 				      struct ff_effect *effect)
3386db3dfefSJiri Kosina {
3396db3dfefSJiri Kosina 	pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] =
3406db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
3416db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE],
3426db3dfefSJiri Kosina 			 effect->u.periodic.magnitude);
3436db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_periodic[PID_OFFSET],
3446db3dfefSJiri Kosina 			 effect->u.periodic.offset);
3456db3dfefSJiri Kosina 	pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
3466db3dfefSJiri Kosina 	pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
3476db3dfefSJiri Kosina 
348d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
349d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
3506db3dfefSJiri Kosina 
3516db3dfefSJiri Kosina }
3526db3dfefSJiri Kosina 
3536db3dfefSJiri Kosina /*
3546db3dfefSJiri Kosina  * Test if periodic effect parameters have changed
3556db3dfefSJiri Kosina  */
pidff_needs_set_periodic(struct ff_effect * effect,struct ff_effect * old)3566db3dfefSJiri Kosina static int pidff_needs_set_periodic(struct ff_effect *effect,
3576db3dfefSJiri Kosina 				    struct ff_effect *old)
3586db3dfefSJiri Kosina {
3596db3dfefSJiri Kosina 	return effect->u.periodic.magnitude != old->u.periodic.magnitude ||
3606db3dfefSJiri Kosina 	       effect->u.periodic.offset != old->u.periodic.offset ||
3616db3dfefSJiri Kosina 	       effect->u.periodic.phase != old->u.periodic.phase ||
3626db3dfefSJiri Kosina 	       effect->u.periodic.period != old->u.periodic.period;
3636db3dfefSJiri Kosina }
3646db3dfefSJiri Kosina 
3656db3dfefSJiri Kosina /*
3666db3dfefSJiri Kosina  * Send condition effect reports to the device
3676db3dfefSJiri Kosina  */
pidff_set_condition_report(struct pidff_device * pidff,struct ff_effect * effect)3686db3dfefSJiri Kosina static void pidff_set_condition_report(struct pidff_device *pidff,
3696db3dfefSJiri Kosina 				       struct ff_effect *effect)
3706db3dfefSJiri Kosina {
3716db3dfefSJiri Kosina 	int i;
3726db3dfefSJiri Kosina 
3736db3dfefSJiri Kosina 	pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] =
3746db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
3756db3dfefSJiri Kosina 
3766db3dfefSJiri Kosina 	for (i = 0; i < 2; i++) {
3776db3dfefSJiri Kosina 		pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i;
3786db3dfefSJiri Kosina 		pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET],
3796db3dfefSJiri Kosina 				 effect->u.condition[i].center);
3806db3dfefSJiri Kosina 		pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT],
3816db3dfefSJiri Kosina 				 effect->u.condition[i].right_coeff);
3826db3dfefSJiri Kosina 		pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT],
3836db3dfefSJiri Kosina 				 effect->u.condition[i].left_coeff);
3846db3dfefSJiri Kosina 		pidff_set(&pidff->set_condition[PID_POS_SATURATION],
3856db3dfefSJiri Kosina 			  effect->u.condition[i].right_saturation);
3866db3dfefSJiri Kosina 		pidff_set(&pidff->set_condition[PID_NEG_SATURATION],
3876db3dfefSJiri Kosina 			  effect->u.condition[i].left_saturation);
3886db3dfefSJiri Kosina 		pidff_set(&pidff->set_condition[PID_DEAD_BAND],
3896db3dfefSJiri Kosina 			  effect->u.condition[i].deadband);
390d8814272SBenjamin Tissoires 		hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION],
391d8814272SBenjamin Tissoires 				HID_REQ_SET_REPORT);
3926db3dfefSJiri Kosina 	}
3936db3dfefSJiri Kosina }
3946db3dfefSJiri Kosina 
3956db3dfefSJiri Kosina /*
3966db3dfefSJiri Kosina  * Test if condition effect parameters have changed
3976db3dfefSJiri Kosina  */
pidff_needs_set_condition(struct ff_effect * effect,struct ff_effect * old)3986db3dfefSJiri Kosina static int pidff_needs_set_condition(struct ff_effect *effect,
3996db3dfefSJiri Kosina 				     struct ff_effect *old)
4006db3dfefSJiri Kosina {
4016db3dfefSJiri Kosina 	int i;
4026db3dfefSJiri Kosina 	int ret = 0;
4036db3dfefSJiri Kosina 
4046db3dfefSJiri Kosina 	for (i = 0; i < 2; i++) {
4056db3dfefSJiri Kosina 		struct ff_condition_effect *cond = &effect->u.condition[i];
4066db3dfefSJiri Kosina 		struct ff_condition_effect *old_cond = &old->u.condition[i];
4076db3dfefSJiri Kosina 
4086db3dfefSJiri Kosina 		ret |= cond->center != old_cond->center ||
4096db3dfefSJiri Kosina 		       cond->right_coeff != old_cond->right_coeff ||
4106db3dfefSJiri Kosina 		       cond->left_coeff != old_cond->left_coeff ||
4116db3dfefSJiri Kosina 		       cond->right_saturation != old_cond->right_saturation ||
4126db3dfefSJiri Kosina 		       cond->left_saturation != old_cond->left_saturation ||
4136db3dfefSJiri Kosina 		       cond->deadband != old_cond->deadband;
4146db3dfefSJiri Kosina 	}
4156db3dfefSJiri Kosina 
4166db3dfefSJiri Kosina 	return ret;
4176db3dfefSJiri Kosina }
4186db3dfefSJiri Kosina 
4196db3dfefSJiri Kosina /*
4206db3dfefSJiri Kosina  * Send ramp force report to the device
4216db3dfefSJiri Kosina  */
pidff_set_ramp_force_report(struct pidff_device * pidff,struct ff_effect * effect)4226db3dfefSJiri Kosina static void pidff_set_ramp_force_report(struct pidff_device *pidff,
4236db3dfefSJiri Kosina 					struct ff_effect *effect)
4246db3dfefSJiri Kosina {
4256db3dfefSJiri Kosina 	pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] =
4266db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
4276db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_ramp[PID_RAMP_START],
4286db3dfefSJiri Kosina 			 effect->u.ramp.start_level);
4296db3dfefSJiri Kosina 	pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
4306db3dfefSJiri Kosina 			 effect->u.ramp.end_level);
431d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP],
432d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
4336db3dfefSJiri Kosina }
4346db3dfefSJiri Kosina 
4356db3dfefSJiri Kosina /*
4366db3dfefSJiri Kosina  * Test if ramp force parameters have changed
4376db3dfefSJiri Kosina  */
pidff_needs_set_ramp(struct ff_effect * effect,struct ff_effect * old)4386db3dfefSJiri Kosina static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old)
4396db3dfefSJiri Kosina {
4406db3dfefSJiri Kosina 	return effect->u.ramp.start_level != old->u.ramp.start_level ||
4416db3dfefSJiri Kosina 	       effect->u.ramp.end_level != old->u.ramp.end_level;
4426db3dfefSJiri Kosina }
4436db3dfefSJiri Kosina 
4446db3dfefSJiri Kosina /*
4456db3dfefSJiri Kosina  * Send a request for effect upload to the device
4466db3dfefSJiri Kosina  *
4476db3dfefSJiri Kosina  * Returns 0 if device reported success, -ENOSPC if the device reported memory
4486db3dfefSJiri Kosina  * is full. Upon unknown response the function will retry for 60 times, if
4496db3dfefSJiri Kosina  * still unsuccessful -EIO is returned.
4506db3dfefSJiri Kosina  */
pidff_request_effect_upload(struct pidff_device * pidff,int efnum)4516db3dfefSJiri Kosina static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
4526db3dfefSJiri Kosina {
4536db3dfefSJiri Kosina 	int j;
4546db3dfefSJiri Kosina 
4556db3dfefSJiri Kosina 	pidff->create_new_effect_type->value[0] = efnum;
456d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
457d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
4584291ee30SJoe Perches 	hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
4596db3dfefSJiri Kosina 
4606db3dfefSJiri Kosina 	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
4616db3dfefSJiri Kosina 	pidff->block_load_status->value[0] = 0;
462b7966a4dSBenjamin Tissoires 	hid_hw_wait(pidff->hid);
4636db3dfefSJiri Kosina 
4646db3dfefSJiri Kosina 	for (j = 0; j < 60; j++) {
4654291ee30SJoe Perches 		hid_dbg(pidff->hid, "pid_block_load requested\n");
466d8814272SBenjamin Tissoires 		hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
467d8814272SBenjamin Tissoires 				HID_REQ_GET_REPORT);
468b7966a4dSBenjamin Tissoires 		hid_hw_wait(pidff->hid);
4696db3dfefSJiri Kosina 		if (pidff->block_load_status->value[0] ==
4706db3dfefSJiri Kosina 		    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
4714291ee30SJoe Perches 			hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
4726db3dfefSJiri Kosina 				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
4736db3dfefSJiri Kosina 				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
4746db3dfefSJiri Kosina 			return 0;
4756db3dfefSJiri Kosina 		}
4766db3dfefSJiri Kosina 		if (pidff->block_load_status->value[0] ==
4776db3dfefSJiri Kosina 		    pidff->status_id[PID_BLOCK_LOAD_FULL]) {
4784291ee30SJoe Perches 			hid_dbg(pidff->hid, "not enough memory free: %d bytes\n",
4796db3dfefSJiri Kosina 				pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
4806db3dfefSJiri Kosina 				pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
4816db3dfefSJiri Kosina 			return -ENOSPC;
4826db3dfefSJiri Kosina 		}
4836db3dfefSJiri Kosina 	}
4844291ee30SJoe Perches 	hid_err(pidff->hid, "pid_block_load failed 60 times\n");
4856db3dfefSJiri Kosina 	return -EIO;
4866db3dfefSJiri Kosina }
4876db3dfefSJiri Kosina 
4886db3dfefSJiri Kosina /*
4896db3dfefSJiri Kosina  * Play the effect with PID id n times
4906db3dfefSJiri Kosina  */
pidff_playback_pid(struct pidff_device * pidff,int pid_id,int n)4916db3dfefSJiri Kosina static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
4926db3dfefSJiri Kosina {
4936db3dfefSJiri Kosina 	pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
4946db3dfefSJiri Kosina 
4956db3dfefSJiri Kosina 	if (n == 0) {
4966db3dfefSJiri Kosina 		pidff->effect_operation_status->value[0] =
4976db3dfefSJiri Kosina 			pidff->operation_id[PID_EFFECT_STOP];
4986db3dfefSJiri Kosina 	} else {
4996db3dfefSJiri Kosina 		pidff->effect_operation_status->value[0] =
5006db3dfefSJiri Kosina 			pidff->operation_id[PID_EFFECT_START];
5016db3dfefSJiri Kosina 		pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
5026db3dfefSJiri Kosina 	}
5036db3dfefSJiri Kosina 
504d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
505d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
5066db3dfefSJiri Kosina }
5076db3dfefSJiri Kosina 
508fbe352aaSLee Jones /*
5096db3dfefSJiri Kosina  * Play the effect with effect id @effect_id for @value times
5106db3dfefSJiri Kosina  */
pidff_playback(struct input_dev * dev,int effect_id,int value)5116db3dfefSJiri Kosina static int pidff_playback(struct input_dev *dev, int effect_id, int value)
5126db3dfefSJiri Kosina {
5136db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
5146db3dfefSJiri Kosina 
5156db3dfefSJiri Kosina 	pidff_playback_pid(pidff, pidff->pid_id[effect_id], value);
5166db3dfefSJiri Kosina 
5176db3dfefSJiri Kosina 	return 0;
5186db3dfefSJiri Kosina }
5196db3dfefSJiri Kosina 
5206db3dfefSJiri Kosina /*
5216db3dfefSJiri Kosina  * Erase effect with PID id
5226db3dfefSJiri Kosina  */
pidff_erase_pid(struct pidff_device * pidff,int pid_id)5236db3dfefSJiri Kosina static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
5246db3dfefSJiri Kosina {
5256db3dfefSJiri Kosina 	pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
526d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
527d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
5286db3dfefSJiri Kosina }
5296db3dfefSJiri Kosina 
5306db3dfefSJiri Kosina /*
5316db3dfefSJiri Kosina  * Stop and erase effect with effect_id
5326db3dfefSJiri Kosina  */
pidff_erase_effect(struct input_dev * dev,int effect_id)5336db3dfefSJiri Kosina static int pidff_erase_effect(struct input_dev *dev, int effect_id)
5346db3dfefSJiri Kosina {
5356db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
5366db3dfefSJiri Kosina 	int pid_id = pidff->pid_id[effect_id];
5376db3dfefSJiri Kosina 
5384291ee30SJoe Perches 	hid_dbg(pidff->hid, "starting to erase %d/%d\n",
5394291ee30SJoe Perches 		effect_id, pidff->pid_id[effect_id]);
540f129ea6dSAnssi Hannula 	/* Wait for the queue to clear. We do not want a full fifo to
541f129ea6dSAnssi Hannula 	   prevent the effect removal. */
542b7966a4dSBenjamin Tissoires 	hid_hw_wait(pidff->hid);
5436db3dfefSJiri Kosina 	pidff_playback_pid(pidff, pid_id, 0);
5446db3dfefSJiri Kosina 	pidff_erase_pid(pidff, pid_id);
5456db3dfefSJiri Kosina 
5466db3dfefSJiri Kosina 	return 0;
5476db3dfefSJiri Kosina }
5486db3dfefSJiri Kosina 
5496db3dfefSJiri Kosina /*
5506db3dfefSJiri Kosina  * Effect upload handler
5516db3dfefSJiri Kosina  */
pidff_upload_effect(struct input_dev * dev,struct ff_effect * effect,struct ff_effect * old)5526db3dfefSJiri Kosina static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
5536db3dfefSJiri Kosina 			       struct ff_effect *old)
5546db3dfefSJiri Kosina {
5556db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
5566db3dfefSJiri Kosina 	int type_id;
5576db3dfefSJiri Kosina 	int error;
5586db3dfefSJiri Kosina 
559e8f46e4fSJim Keir 	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
560b9e9cd32SJiri Kosina 	if (old) {
561e8f46e4fSJim Keir 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] =
562e8f46e4fSJim Keir 			pidff->pid_id[effect->id];
563e8f46e4fSJim Keir 	}
564e8f46e4fSJim Keir 
5656db3dfefSJiri Kosina 	switch (effect->type) {
5666db3dfefSJiri Kosina 	case FF_CONSTANT:
5676db3dfefSJiri Kosina 		if (!old) {
5686db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
5696db3dfefSJiri Kosina 					pidff->type_id[PID_CONSTANT]);
5706db3dfefSJiri Kosina 			if (error)
5716db3dfefSJiri Kosina 				return error;
5726db3dfefSJiri Kosina 		}
5736db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
5746db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
5756db3dfefSJiri Kosina 		if (!old || pidff_needs_set_constant(effect, old))
5766db3dfefSJiri Kosina 			pidff_set_constant_force_report(pidff, effect);
5776db3dfefSJiri Kosina 		if (!old ||
5786db3dfefSJiri Kosina 		    pidff_needs_set_envelope(&effect->u.constant.envelope,
5796db3dfefSJiri Kosina 					&old->u.constant.envelope))
5806db3dfefSJiri Kosina 			pidff_set_envelope_report(pidff,
5816db3dfefSJiri Kosina 					&effect->u.constant.envelope);
5826db3dfefSJiri Kosina 		break;
5836db3dfefSJiri Kosina 
5846db3dfefSJiri Kosina 	case FF_PERIODIC:
5856db3dfefSJiri Kosina 		if (!old) {
5866db3dfefSJiri Kosina 			switch (effect->u.periodic.waveform) {
5876db3dfefSJiri Kosina 			case FF_SQUARE:
5886db3dfefSJiri Kosina 				type_id = PID_SQUARE;
5896db3dfefSJiri Kosina 				break;
5906db3dfefSJiri Kosina 			case FF_TRIANGLE:
5916db3dfefSJiri Kosina 				type_id = PID_TRIANGLE;
5926db3dfefSJiri Kosina 				break;
5936db3dfefSJiri Kosina 			case FF_SINE:
5946db3dfefSJiri Kosina 				type_id = PID_SINE;
5956db3dfefSJiri Kosina 				break;
5966db3dfefSJiri Kosina 			case FF_SAW_UP:
5976db3dfefSJiri Kosina 				type_id = PID_SAW_UP;
5986db3dfefSJiri Kosina 				break;
5996db3dfefSJiri Kosina 			case FF_SAW_DOWN:
6006db3dfefSJiri Kosina 				type_id = PID_SAW_DOWN;
6016db3dfefSJiri Kosina 				break;
6026db3dfefSJiri Kosina 			default:
6034291ee30SJoe Perches 				hid_err(pidff->hid, "invalid waveform\n");
6046db3dfefSJiri Kosina 				return -EINVAL;
6056db3dfefSJiri Kosina 			}
6066db3dfefSJiri Kosina 
6076db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6086db3dfefSJiri Kosina 					pidff->type_id[type_id]);
6096db3dfefSJiri Kosina 			if (error)
6106db3dfefSJiri Kosina 				return error;
6116db3dfefSJiri Kosina 		}
6126db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6136db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6146db3dfefSJiri Kosina 		if (!old || pidff_needs_set_periodic(effect, old))
6156db3dfefSJiri Kosina 			pidff_set_periodic_report(pidff, effect);
6166db3dfefSJiri Kosina 		if (!old ||
6176db3dfefSJiri Kosina 		    pidff_needs_set_envelope(&effect->u.periodic.envelope,
6186db3dfefSJiri Kosina 					&old->u.periodic.envelope))
6196db3dfefSJiri Kosina 			pidff_set_envelope_report(pidff,
6206db3dfefSJiri Kosina 					&effect->u.periodic.envelope);
6216db3dfefSJiri Kosina 		break;
6226db3dfefSJiri Kosina 
6236db3dfefSJiri Kosina 	case FF_RAMP:
6246db3dfefSJiri Kosina 		if (!old) {
6256db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6266db3dfefSJiri Kosina 					pidff->type_id[PID_RAMP]);
6276db3dfefSJiri Kosina 			if (error)
6286db3dfefSJiri Kosina 				return error;
6296db3dfefSJiri Kosina 		}
6306db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6316db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6326db3dfefSJiri Kosina 		if (!old || pidff_needs_set_ramp(effect, old))
6336db3dfefSJiri Kosina 			pidff_set_ramp_force_report(pidff, effect);
6346db3dfefSJiri Kosina 		if (!old ||
6356db3dfefSJiri Kosina 		    pidff_needs_set_envelope(&effect->u.ramp.envelope,
6366db3dfefSJiri Kosina 					&old->u.ramp.envelope))
6376db3dfefSJiri Kosina 			pidff_set_envelope_report(pidff,
6386db3dfefSJiri Kosina 					&effect->u.ramp.envelope);
6396db3dfefSJiri Kosina 		break;
6406db3dfefSJiri Kosina 
6416db3dfefSJiri Kosina 	case FF_SPRING:
6426db3dfefSJiri Kosina 		if (!old) {
6436db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6446db3dfefSJiri Kosina 					pidff->type_id[PID_SPRING]);
6456db3dfefSJiri Kosina 			if (error)
6466db3dfefSJiri Kosina 				return error;
6476db3dfefSJiri Kosina 		}
6486db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6496db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6506db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6516db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6526db3dfefSJiri Kosina 		break;
6536db3dfefSJiri Kosina 
6546db3dfefSJiri Kosina 	case FF_FRICTION:
6556db3dfefSJiri Kosina 		if (!old) {
6566db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6576db3dfefSJiri Kosina 					pidff->type_id[PID_FRICTION]);
6586db3dfefSJiri Kosina 			if (error)
6596db3dfefSJiri Kosina 				return error;
6606db3dfefSJiri Kosina 		}
6616db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6626db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6636db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6646db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6656db3dfefSJiri Kosina 		break;
6666db3dfefSJiri Kosina 
6676db3dfefSJiri Kosina 	case FF_DAMPER:
6686db3dfefSJiri Kosina 		if (!old) {
6696db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6706db3dfefSJiri Kosina 					pidff->type_id[PID_DAMPER]);
6716db3dfefSJiri Kosina 			if (error)
6726db3dfefSJiri Kosina 				return error;
6736db3dfefSJiri Kosina 		}
6746db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6756db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6766db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6776db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6786db3dfefSJiri Kosina 		break;
6796db3dfefSJiri Kosina 
6806db3dfefSJiri Kosina 	case FF_INERTIA:
6816db3dfefSJiri Kosina 		if (!old) {
6826db3dfefSJiri Kosina 			error = pidff_request_effect_upload(pidff,
6836db3dfefSJiri Kosina 					pidff->type_id[PID_INERTIA]);
6846db3dfefSJiri Kosina 			if (error)
6856db3dfefSJiri Kosina 				return error;
6866db3dfefSJiri Kosina 		}
6876db3dfefSJiri Kosina 		if (!old || pidff_needs_set_effect(effect, old))
6886db3dfefSJiri Kosina 			pidff_set_effect_report(pidff, effect);
6896db3dfefSJiri Kosina 		if (!old || pidff_needs_set_condition(effect, old))
6906db3dfefSJiri Kosina 			pidff_set_condition_report(pidff, effect);
6916db3dfefSJiri Kosina 		break;
6926db3dfefSJiri Kosina 
6936db3dfefSJiri Kosina 	default:
6944291ee30SJoe Perches 		hid_err(pidff->hid, "invalid type\n");
6956db3dfefSJiri Kosina 		return -EINVAL;
6966db3dfefSJiri Kosina 	}
6976db3dfefSJiri Kosina 
6986db3dfefSJiri Kosina 	if (!old)
6996db3dfefSJiri Kosina 		pidff->pid_id[effect->id] =
7006db3dfefSJiri Kosina 		    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
7016db3dfefSJiri Kosina 
7024291ee30SJoe Perches 	hid_dbg(pidff->hid, "uploaded\n");
7036db3dfefSJiri Kosina 
7046db3dfefSJiri Kosina 	return 0;
7056db3dfefSJiri Kosina }
7066db3dfefSJiri Kosina 
7076db3dfefSJiri Kosina /*
7086db3dfefSJiri Kosina  * set_gain() handler
7096db3dfefSJiri Kosina  */
pidff_set_gain(struct input_dev * dev,u16 gain)7106db3dfefSJiri Kosina static void pidff_set_gain(struct input_dev *dev, u16 gain)
7116db3dfefSJiri Kosina {
7126db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
7136db3dfefSJiri Kosina 
7146db3dfefSJiri Kosina 	pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
715d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
716d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
7176db3dfefSJiri Kosina }
7186db3dfefSJiri Kosina 
pidff_autocenter(struct pidff_device * pidff,u16 magnitude)7196db3dfefSJiri Kosina static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
7206db3dfefSJiri Kosina {
7216db3dfefSJiri Kosina 	struct hid_field *field =
7226db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].field;
7236db3dfefSJiri Kosina 
7246db3dfefSJiri Kosina 	if (!magnitude) {
7256db3dfefSJiri Kosina 		pidff_playback_pid(pidff, field->logical_minimum, 0);
7266db3dfefSJiri Kosina 		return;
7276db3dfefSJiri Kosina 	}
7286db3dfefSJiri Kosina 
7296db3dfefSJiri Kosina 	pidff_playback_pid(pidff, field->logical_minimum, 1);
7306db3dfefSJiri Kosina 
7316db3dfefSJiri Kosina 	pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
7326db3dfefSJiri Kosina 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum;
7336db3dfefSJiri Kosina 	pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING];
7346db3dfefSJiri Kosina 	pidff->set_effect[PID_DURATION].value[0] = 0;
7356db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
7366db3dfefSJiri Kosina 	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
7376db3dfefSJiri Kosina 	pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
738816cbfdaSDiogo Kastrup 	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
7396db3dfefSJiri Kosina 	pidff->set_effect[PID_START_DELAY].value[0] = 0;
7406db3dfefSJiri Kosina 
741d8814272SBenjamin Tissoires 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
742d8814272SBenjamin Tissoires 			HID_REQ_SET_REPORT);
7436db3dfefSJiri Kosina }
7446db3dfefSJiri Kosina 
7456db3dfefSJiri Kosina /*
7466db3dfefSJiri Kosina  * pidff_set_autocenter() handler
7476db3dfefSJiri Kosina  */
pidff_set_autocenter(struct input_dev * dev,u16 magnitude)7486db3dfefSJiri Kosina static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
7496db3dfefSJiri Kosina {
7506db3dfefSJiri Kosina 	struct pidff_device *pidff = dev->ff->private;
7516db3dfefSJiri Kosina 
7526db3dfefSJiri Kosina 	pidff_autocenter(pidff, magnitude);
7536db3dfefSJiri Kosina }
7546db3dfefSJiri Kosina 
7556db3dfefSJiri Kosina /*
7566db3dfefSJiri Kosina  * Find fields from a report and fill a pidff_usage
7576db3dfefSJiri Kosina  */
pidff_find_fields(struct pidff_usage * usage,const u8 * table,struct hid_report * report,int count,int strict)7586db3dfefSJiri Kosina static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
7596db3dfefSJiri Kosina 			     struct hid_report *report, int count, int strict)
7606db3dfefSJiri Kosina {
7616db3dfefSJiri Kosina 	int i, j, k, found;
7626db3dfefSJiri Kosina 
7636db3dfefSJiri Kosina 	for (k = 0; k < count; k++) {
7646db3dfefSJiri Kosina 		found = 0;
7656db3dfefSJiri Kosina 		for (i = 0; i < report->maxfield; i++) {
7666db3dfefSJiri Kosina 			if (report->field[i]->maxusage !=
7676db3dfefSJiri Kosina 			    report->field[i]->report_count) {
7684291ee30SJoe Perches 				pr_debug("maxusage and report_count do not match, skipping\n");
7696db3dfefSJiri Kosina 				continue;
7706db3dfefSJiri Kosina 			}
7716db3dfefSJiri Kosina 			for (j = 0; j < report->field[i]->maxusage; j++) {
7726db3dfefSJiri Kosina 				if (report->field[i]->usage[j].hid ==
7736db3dfefSJiri Kosina 				    (HID_UP_PID | table[k])) {
7744291ee30SJoe Perches 					pr_debug("found %d at %d->%d\n",
7754291ee30SJoe Perches 						 k, i, j);
7766db3dfefSJiri Kosina 					usage[k].field = report->field[i];
7776db3dfefSJiri Kosina 					usage[k].value =
7786db3dfefSJiri Kosina 						&report->field[i]->value[j];
7796db3dfefSJiri Kosina 					found = 1;
7806db3dfefSJiri Kosina 					break;
7816db3dfefSJiri Kosina 				}
7826db3dfefSJiri Kosina 			}
7836db3dfefSJiri Kosina 			if (found)
7846db3dfefSJiri Kosina 				break;
7856db3dfefSJiri Kosina 		}
7866db3dfefSJiri Kosina 		if (!found && strict) {
7874291ee30SJoe Perches 			pr_debug("failed to locate %d\n", k);
7886db3dfefSJiri Kosina 			return -1;
7896db3dfefSJiri Kosina 		}
7906db3dfefSJiri Kosina 	}
7916db3dfefSJiri Kosina 	return 0;
7926db3dfefSJiri Kosina }
7936db3dfefSJiri Kosina 
7946db3dfefSJiri Kosina /*
7956db3dfefSJiri Kosina  * Return index into pidff_reports for the given usage
7966db3dfefSJiri Kosina  */
pidff_check_usage(int usage)7976db3dfefSJiri Kosina static int pidff_check_usage(int usage)
7986db3dfefSJiri Kosina {
7996db3dfefSJiri Kosina 	int i;
8006db3dfefSJiri Kosina 
8016db3dfefSJiri Kosina 	for (i = 0; i < sizeof(pidff_reports); i++)
8026db3dfefSJiri Kosina 		if (usage == (HID_UP_PID | pidff_reports[i]))
8036db3dfefSJiri Kosina 			return i;
8046db3dfefSJiri Kosina 
8056db3dfefSJiri Kosina 	return -1;
8066db3dfefSJiri Kosina }
8076db3dfefSJiri Kosina 
8086db3dfefSJiri Kosina /*
8096db3dfefSJiri Kosina  * Find the reports and fill pidff->reports[]
8106db3dfefSJiri Kosina  * report_type specifies either OUTPUT or FEATURE reports
8116db3dfefSJiri Kosina  */
pidff_find_reports(struct hid_device * hid,int report_type,struct pidff_device * pidff)8126db3dfefSJiri Kosina static void pidff_find_reports(struct hid_device *hid, int report_type,
8136db3dfefSJiri Kosina 			       struct pidff_device *pidff)
8146db3dfefSJiri Kosina {
8156db3dfefSJiri Kosina 	struct hid_report *report;
8166db3dfefSJiri Kosina 	int i, ret;
8176db3dfefSJiri Kosina 
8186db3dfefSJiri Kosina 	list_for_each_entry(report,
8196db3dfefSJiri Kosina 			    &hid->report_enum[report_type].report_list, list) {
8206db3dfefSJiri Kosina 		if (report->maxfield < 1)
8216db3dfefSJiri Kosina 			continue;
8226db3dfefSJiri Kosina 		ret = pidff_check_usage(report->field[0]->logical);
8236db3dfefSJiri Kosina 		if (ret != -1) {
8244291ee30SJoe Perches 			hid_dbg(hid, "found usage 0x%02x from field->logical\n",
8256db3dfefSJiri Kosina 				pidff_reports[ret]);
8266db3dfefSJiri Kosina 			pidff->reports[ret] = report;
8276db3dfefSJiri Kosina 			continue;
8286db3dfefSJiri Kosina 		}
8296db3dfefSJiri Kosina 
8306db3dfefSJiri Kosina 		/*
8316db3dfefSJiri Kosina 		 * Sometimes logical collections are stacked to indicate
8326db3dfefSJiri Kosina 		 * different usages for the report and the field, in which
8336db3dfefSJiri Kosina 		 * case we want the usage of the parent. However, Linux HID
8346db3dfefSJiri Kosina 		 * implementation hides this fact, so we have to dig it up
8356db3dfefSJiri Kosina 		 * ourselves
8366db3dfefSJiri Kosina 		 */
8376db3dfefSJiri Kosina 		i = report->field[0]->usage[0].collection_index;
8386db3dfefSJiri Kosina 		if (i <= 0 ||
8396db3dfefSJiri Kosina 		    hid->collection[i - 1].type != HID_COLLECTION_LOGICAL)
8406db3dfefSJiri Kosina 			continue;
8416db3dfefSJiri Kosina 		ret = pidff_check_usage(hid->collection[i - 1].usage);
8426db3dfefSJiri Kosina 		if (ret != -1 && !pidff->reports[ret]) {
8434291ee30SJoe Perches 			hid_dbg(hid,
8444291ee30SJoe Perches 				"found usage 0x%02x from collection array\n",
8456db3dfefSJiri Kosina 				pidff_reports[ret]);
8466db3dfefSJiri Kosina 			pidff->reports[ret] = report;
8476db3dfefSJiri Kosina 		}
8486db3dfefSJiri Kosina 	}
8496db3dfefSJiri Kosina }
8506db3dfefSJiri Kosina 
8516db3dfefSJiri Kosina /*
8526db3dfefSJiri Kosina  * Test if the required reports have been found
8536db3dfefSJiri Kosina  */
pidff_reports_ok(struct pidff_device * pidff)8546db3dfefSJiri Kosina static int pidff_reports_ok(struct pidff_device *pidff)
8556db3dfefSJiri Kosina {
8566db3dfefSJiri Kosina 	int i;
8576db3dfefSJiri Kosina 
8586db3dfefSJiri Kosina 	for (i = 0; i <= PID_REQUIRED_REPORTS; i++) {
8596db3dfefSJiri Kosina 		if (!pidff->reports[i]) {
8604291ee30SJoe Perches 			hid_dbg(pidff->hid, "%d missing\n", i);
8616db3dfefSJiri Kosina 			return 0;
8626db3dfefSJiri Kosina 		}
8636db3dfefSJiri Kosina 	}
8646db3dfefSJiri Kosina 
8656db3dfefSJiri Kosina 	return 1;
8666db3dfefSJiri Kosina }
8676db3dfefSJiri Kosina 
8686db3dfefSJiri Kosina /*
8696db3dfefSJiri Kosina  * Find a field with a specific usage within a report
8706db3dfefSJiri Kosina  */
pidff_find_special_field(struct hid_report * report,int usage,int enforce_min)8716db3dfefSJiri Kosina static struct hid_field *pidff_find_special_field(struct hid_report *report,
8726db3dfefSJiri Kosina 						  int usage, int enforce_min)
8736db3dfefSJiri Kosina {
8746db3dfefSJiri Kosina 	int i;
8756db3dfefSJiri Kosina 
8766db3dfefSJiri Kosina 	for (i = 0; i < report->maxfield; i++) {
8776db3dfefSJiri Kosina 		if (report->field[i]->logical == (HID_UP_PID | usage) &&
8786db3dfefSJiri Kosina 		    report->field[i]->report_count > 0) {
8796db3dfefSJiri Kosina 			if (!enforce_min ||
8806db3dfefSJiri Kosina 			    report->field[i]->logical_minimum == 1)
8816db3dfefSJiri Kosina 				return report->field[i];
8826db3dfefSJiri Kosina 			else {
8834291ee30SJoe Perches 				pr_err("logical_minimum is not 1 as it should be\n");
8846db3dfefSJiri Kosina 				return NULL;
8856db3dfefSJiri Kosina 			}
8866db3dfefSJiri Kosina 		}
8876db3dfefSJiri Kosina 	}
8886db3dfefSJiri Kosina 	return NULL;
8896db3dfefSJiri Kosina }
8906db3dfefSJiri Kosina 
8916db3dfefSJiri Kosina /*
8926db3dfefSJiri Kosina  * Fill a pidff->*_id struct table
8936db3dfefSJiri Kosina  */
pidff_find_special_keys(int * keys,struct hid_field * fld,const u8 * usagetable,int count)8946db3dfefSJiri Kosina static int pidff_find_special_keys(int *keys, struct hid_field *fld,
8956db3dfefSJiri Kosina 				   const u8 *usagetable, int count)
8966db3dfefSJiri Kosina {
8976db3dfefSJiri Kosina 
8986db3dfefSJiri Kosina 	int i, j;
8996db3dfefSJiri Kosina 	int found = 0;
9006db3dfefSJiri Kosina 
9016db3dfefSJiri Kosina 	for (i = 0; i < count; i++) {
9026db3dfefSJiri Kosina 		for (j = 0; j < fld->maxusage; j++) {
9036db3dfefSJiri Kosina 			if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) {
9046db3dfefSJiri Kosina 				keys[i] = j + 1;
9056db3dfefSJiri Kosina 				found++;
9066db3dfefSJiri Kosina 				break;
9076db3dfefSJiri Kosina 			}
9086db3dfefSJiri Kosina 		}
9096db3dfefSJiri Kosina 	}
9106db3dfefSJiri Kosina 	return found;
9116db3dfefSJiri Kosina }
9126db3dfefSJiri Kosina 
9136db3dfefSJiri Kosina #define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \
9146db3dfefSJiri Kosina 	pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \
9156db3dfefSJiri Kosina 		sizeof(pidff_ ## name))
9166db3dfefSJiri Kosina 
9176db3dfefSJiri Kosina /*
9186db3dfefSJiri Kosina  * Find and check the special fields
9196db3dfefSJiri Kosina  */
pidff_find_special_fields(struct pidff_device * pidff)9206db3dfefSJiri Kosina static int pidff_find_special_fields(struct pidff_device *pidff)
9216db3dfefSJiri Kosina {
9224291ee30SJoe Perches 	hid_dbg(pidff->hid, "finding special fields\n");
9236db3dfefSJiri Kosina 
9246db3dfefSJiri Kosina 	pidff->create_new_effect_type =
9256db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT],
9266db3dfefSJiri Kosina 					 0x25, 1);
9276db3dfefSJiri Kosina 	pidff->set_effect_type =
9286db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
9296db3dfefSJiri Kosina 					 0x25, 1);
9306db3dfefSJiri Kosina 	pidff->effect_direction =
9316db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
9326db3dfefSJiri Kosina 					 0x57, 0);
9336db3dfefSJiri Kosina 	pidff->device_control =
9346db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
9356db3dfefSJiri Kosina 					 0x96, 1);
9366db3dfefSJiri Kosina 	pidff->block_load_status =
9376db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
9386db3dfefSJiri Kosina 					 0x8b, 1);
9396db3dfefSJiri Kosina 	pidff->effect_operation_status =
9406db3dfefSJiri Kosina 		pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION],
9416db3dfefSJiri Kosina 					 0x78, 1);
9426db3dfefSJiri Kosina 
9434291ee30SJoe Perches 	hid_dbg(pidff->hid, "search done\n");
9446db3dfefSJiri Kosina 
9456db3dfefSJiri Kosina 	if (!pidff->create_new_effect_type || !pidff->set_effect_type) {
9464291ee30SJoe Perches 		hid_err(pidff->hid, "effect lists not found\n");
9476db3dfefSJiri Kosina 		return -1;
9486db3dfefSJiri Kosina 	}
9496db3dfefSJiri Kosina 
9506db3dfefSJiri Kosina 	if (!pidff->effect_direction) {
9514291ee30SJoe Perches 		hid_err(pidff->hid, "direction field not found\n");
9526db3dfefSJiri Kosina 		return -1;
9536db3dfefSJiri Kosina 	}
9546db3dfefSJiri Kosina 
9556db3dfefSJiri Kosina 	if (!pidff->device_control) {
9564291ee30SJoe Perches 		hid_err(pidff->hid, "device control field not found\n");
9576db3dfefSJiri Kosina 		return -1;
9586db3dfefSJiri Kosina 	}
9596db3dfefSJiri Kosina 
9606db3dfefSJiri Kosina 	if (!pidff->block_load_status) {
9614291ee30SJoe Perches 		hid_err(pidff->hid, "block load status field not found\n");
9626db3dfefSJiri Kosina 		return -1;
9636db3dfefSJiri Kosina 	}
9646db3dfefSJiri Kosina 
9656db3dfefSJiri Kosina 	if (!pidff->effect_operation_status) {
9664291ee30SJoe Perches 		hid_err(pidff->hid, "effect operation field not found\n");
9676db3dfefSJiri Kosina 		return -1;
9686db3dfefSJiri Kosina 	}
9696db3dfefSJiri Kosina 
9706db3dfefSJiri Kosina 	pidff_find_special_keys(pidff->control_id, pidff->device_control,
9716db3dfefSJiri Kosina 				pidff_device_control,
9726db3dfefSJiri Kosina 				sizeof(pidff_device_control));
9736db3dfefSJiri Kosina 
9746db3dfefSJiri Kosina 	PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control);
9756db3dfefSJiri Kosina 
9766db3dfefSJiri Kosina 	if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type,
9776db3dfefSJiri Kosina 				     effect_types)) {
9784291ee30SJoe Perches 		hid_err(pidff->hid, "no effect types found\n");
9796db3dfefSJiri Kosina 		return -1;
9806db3dfefSJiri Kosina 	}
9816db3dfefSJiri Kosina 
9826db3dfefSJiri Kosina 	if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status,
9836db3dfefSJiri Kosina 				    block_load_status) !=
9846db3dfefSJiri Kosina 			sizeof(pidff_block_load_status)) {
9854291ee30SJoe Perches 		hid_err(pidff->hid,
9864291ee30SJoe Perches 			"block load status identifiers not found\n");
9876db3dfefSJiri Kosina 		return -1;
9886db3dfefSJiri Kosina 	}
9896db3dfefSJiri Kosina 
9906db3dfefSJiri Kosina 	if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status,
9916db3dfefSJiri Kosina 				    effect_operation_status) !=
9926db3dfefSJiri Kosina 			sizeof(pidff_effect_operation_status)) {
9934291ee30SJoe Perches 		hid_err(pidff->hid, "effect operation identifiers not found\n");
9946db3dfefSJiri Kosina 		return -1;
9956db3dfefSJiri Kosina 	}
9966db3dfefSJiri Kosina 
9976db3dfefSJiri Kosina 	return 0;
9986db3dfefSJiri Kosina }
9996db3dfefSJiri Kosina 
1000fbe352aaSLee Jones /*
10016db3dfefSJiri Kosina  * Find the implemented effect types
10026db3dfefSJiri Kosina  */
pidff_find_effects(struct pidff_device * pidff,struct input_dev * dev)10036db3dfefSJiri Kosina static int pidff_find_effects(struct pidff_device *pidff,
10046db3dfefSJiri Kosina 			      struct input_dev *dev)
10056db3dfefSJiri Kosina {
10066db3dfefSJiri Kosina 	int i;
10076db3dfefSJiri Kosina 
10086db3dfefSJiri Kosina 	for (i = 0; i < sizeof(pidff_effect_types); i++) {
10096db3dfefSJiri Kosina 		int pidff_type = pidff->type_id[i];
10106db3dfefSJiri Kosina 		if (pidff->set_effect_type->usage[pidff_type].hid !=
10116db3dfefSJiri Kosina 		    pidff->create_new_effect_type->usage[pidff_type].hid) {
10124291ee30SJoe Perches 			hid_err(pidff->hid,
10136db3dfefSJiri Kosina 				"effect type number %d is invalid\n", i);
10146db3dfefSJiri Kosina 			return -1;
10156db3dfefSJiri Kosina 		}
10166db3dfefSJiri Kosina 	}
10176db3dfefSJiri Kosina 
10186db3dfefSJiri Kosina 	if (pidff->type_id[PID_CONSTANT])
10196db3dfefSJiri Kosina 		set_bit(FF_CONSTANT, dev->ffbit);
10206db3dfefSJiri Kosina 	if (pidff->type_id[PID_RAMP])
10216db3dfefSJiri Kosina 		set_bit(FF_RAMP, dev->ffbit);
10226db3dfefSJiri Kosina 	if (pidff->type_id[PID_SQUARE]) {
10236db3dfefSJiri Kosina 		set_bit(FF_SQUARE, dev->ffbit);
10246db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10256db3dfefSJiri Kosina 	}
10266db3dfefSJiri Kosina 	if (pidff->type_id[PID_SINE]) {
10276db3dfefSJiri Kosina 		set_bit(FF_SINE, dev->ffbit);
10286db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10296db3dfefSJiri Kosina 	}
10306db3dfefSJiri Kosina 	if (pidff->type_id[PID_TRIANGLE]) {
10316db3dfefSJiri Kosina 		set_bit(FF_TRIANGLE, dev->ffbit);
10326db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10336db3dfefSJiri Kosina 	}
10346db3dfefSJiri Kosina 	if (pidff->type_id[PID_SAW_UP]) {
10356db3dfefSJiri Kosina 		set_bit(FF_SAW_UP, dev->ffbit);
10366db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10376db3dfefSJiri Kosina 	}
10386db3dfefSJiri Kosina 	if (pidff->type_id[PID_SAW_DOWN]) {
10396db3dfefSJiri Kosina 		set_bit(FF_SAW_DOWN, dev->ffbit);
10406db3dfefSJiri Kosina 		set_bit(FF_PERIODIC, dev->ffbit);
10416db3dfefSJiri Kosina 	}
10426db3dfefSJiri Kosina 	if (pidff->type_id[PID_SPRING])
10436db3dfefSJiri Kosina 		set_bit(FF_SPRING, dev->ffbit);
10446db3dfefSJiri Kosina 	if (pidff->type_id[PID_DAMPER])
10456db3dfefSJiri Kosina 		set_bit(FF_DAMPER, dev->ffbit);
10466db3dfefSJiri Kosina 	if (pidff->type_id[PID_INERTIA])
10476db3dfefSJiri Kosina 		set_bit(FF_INERTIA, dev->ffbit);
10486db3dfefSJiri Kosina 	if (pidff->type_id[PID_FRICTION])
10496db3dfefSJiri Kosina 		set_bit(FF_FRICTION, dev->ffbit);
10506db3dfefSJiri Kosina 
10516db3dfefSJiri Kosina 	return 0;
10526db3dfefSJiri Kosina 
10536db3dfefSJiri Kosina }
10546db3dfefSJiri Kosina 
10556db3dfefSJiri Kosina #define PIDFF_FIND_FIELDS(name, report, strict) \
10566db3dfefSJiri Kosina 	pidff_find_fields(pidff->name, pidff_ ## name, \
10576db3dfefSJiri Kosina 		pidff->reports[report], \
10586db3dfefSJiri Kosina 		sizeof(pidff_ ## name), strict)
10596db3dfefSJiri Kosina 
10606db3dfefSJiri Kosina /*
10616db3dfefSJiri Kosina  * Fill and check the pidff_usages
10626db3dfefSJiri Kosina  */
pidff_init_fields(struct pidff_device * pidff,struct input_dev * dev)10636db3dfefSJiri Kosina static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
10646db3dfefSJiri Kosina {
10656db3dfefSJiri Kosina 	int envelope_ok = 0;
10666db3dfefSJiri Kosina 
10676db3dfefSJiri Kosina 	if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
10684291ee30SJoe Perches 		hid_err(pidff->hid, "unknown set_effect report layout\n");
10696db3dfefSJiri Kosina 		return -ENODEV;
10706db3dfefSJiri Kosina 	}
10716db3dfefSJiri Kosina 
10726db3dfefSJiri Kosina 	PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
10736db3dfefSJiri Kosina 	if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
10744291ee30SJoe Perches 		hid_err(pidff->hid, "unknown pid_block_load report layout\n");
10756db3dfefSJiri Kosina 		return -ENODEV;
10766db3dfefSJiri Kosina 	}
10776db3dfefSJiri Kosina 
10786db3dfefSJiri Kosina 	if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) {
10794291ee30SJoe Perches 		hid_err(pidff->hid, "unknown effect_operation report layout\n");
10806db3dfefSJiri Kosina 		return -ENODEV;
10816db3dfefSJiri Kosina 	}
10826db3dfefSJiri Kosina 
10836db3dfefSJiri Kosina 	if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) {
10844291ee30SJoe Perches 		hid_err(pidff->hid, "unknown pid_block_free report layout\n");
10856db3dfefSJiri Kosina 		return -ENODEV;
10866db3dfefSJiri Kosina 	}
10876db3dfefSJiri Kosina 
10886db3dfefSJiri Kosina 	if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1))
10896db3dfefSJiri Kosina 		envelope_ok = 1;
10906db3dfefSJiri Kosina 
10916db3dfefSJiri Kosina 	if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev))
10926db3dfefSJiri Kosina 		return -ENODEV;
10936db3dfefSJiri Kosina 
10946db3dfefSJiri Kosina 	if (!envelope_ok) {
10956db3dfefSJiri Kosina 		if (test_and_clear_bit(FF_CONSTANT, dev->ffbit))
10964291ee30SJoe Perches 			hid_warn(pidff->hid,
10976db3dfefSJiri Kosina 				 "has constant effect but no envelope\n");
10986db3dfefSJiri Kosina 		if (test_and_clear_bit(FF_RAMP, dev->ffbit))
10994291ee30SJoe Perches 			hid_warn(pidff->hid,
11006db3dfefSJiri Kosina 				 "has ramp effect but no envelope\n");
11016db3dfefSJiri Kosina 
11026db3dfefSJiri Kosina 		if (test_and_clear_bit(FF_PERIODIC, dev->ffbit))
11034291ee30SJoe Perches 			hid_warn(pidff->hid,
11046db3dfefSJiri Kosina 				 "has periodic effect but no envelope\n");
11056db3dfefSJiri Kosina 	}
11066db3dfefSJiri Kosina 
11076db3dfefSJiri Kosina 	if (test_bit(FF_CONSTANT, dev->ffbit) &&
11086db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) {
11094291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown constant effect layout\n");
11106db3dfefSJiri Kosina 		clear_bit(FF_CONSTANT, dev->ffbit);
11116db3dfefSJiri Kosina 	}
11126db3dfefSJiri Kosina 
11136db3dfefSJiri Kosina 	if (test_bit(FF_RAMP, dev->ffbit) &&
11146db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) {
11154291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown ramp effect layout\n");
11166db3dfefSJiri Kosina 		clear_bit(FF_RAMP, dev->ffbit);
11176db3dfefSJiri Kosina 	}
11186db3dfefSJiri Kosina 
11196db3dfefSJiri Kosina 	if ((test_bit(FF_SPRING, dev->ffbit) ||
11206db3dfefSJiri Kosina 	     test_bit(FF_DAMPER, dev->ffbit) ||
11216db3dfefSJiri Kosina 	     test_bit(FF_FRICTION, dev->ffbit) ||
11226db3dfefSJiri Kosina 	     test_bit(FF_INERTIA, dev->ffbit)) &&
11236db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
11244291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown condition effect layout\n");
11256db3dfefSJiri Kosina 		clear_bit(FF_SPRING, dev->ffbit);
11266db3dfefSJiri Kosina 		clear_bit(FF_DAMPER, dev->ffbit);
11276db3dfefSJiri Kosina 		clear_bit(FF_FRICTION, dev->ffbit);
11286db3dfefSJiri Kosina 		clear_bit(FF_INERTIA, dev->ffbit);
11296db3dfefSJiri Kosina 	}
11306db3dfefSJiri Kosina 
11316db3dfefSJiri Kosina 	if (test_bit(FF_PERIODIC, dev->ffbit) &&
11326db3dfefSJiri Kosina 	    PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) {
11334291ee30SJoe Perches 		hid_warn(pidff->hid, "unknown periodic effect layout\n");
11346db3dfefSJiri Kosina 		clear_bit(FF_PERIODIC, dev->ffbit);
11356db3dfefSJiri Kosina 	}
11366db3dfefSJiri Kosina 
11376db3dfefSJiri Kosina 	PIDFF_FIND_FIELDS(pool, PID_POOL, 0);
11386db3dfefSJiri Kosina 
11396db3dfefSJiri Kosina 	if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1))
11406db3dfefSJiri Kosina 		set_bit(FF_GAIN, dev->ffbit);
11416db3dfefSJiri Kosina 
11426db3dfefSJiri Kosina 	return 0;
11436db3dfefSJiri Kosina }
11446db3dfefSJiri Kosina 
11456db3dfefSJiri Kosina /*
11466db3dfefSJiri Kosina  * Reset the device
11476db3dfefSJiri Kosina  */
pidff_reset(struct pidff_device * pidff)11486db3dfefSJiri Kosina static void pidff_reset(struct pidff_device *pidff)
11496db3dfefSJiri Kosina {
11506db3dfefSJiri Kosina 	struct hid_device *hid = pidff->hid;
11516db3dfefSJiri Kosina 	int i = 0;
11526db3dfefSJiri Kosina 
11536db3dfefSJiri Kosina 	pidff->device_control->value[0] = pidff->control_id[PID_RESET];
11546db3dfefSJiri Kosina 	/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
1155d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
1156b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
1157d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
1158b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
11596db3dfefSJiri Kosina 
11606db3dfefSJiri Kosina 	pidff->device_control->value[0] =
11616db3dfefSJiri Kosina 		pidff->control_id[PID_ENABLE_ACTUATORS];
1162d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
1163b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
11646db3dfefSJiri Kosina 
11656db3dfefSJiri Kosina 	/* pool report is sometimes messed up, refetch it */
1166d8814272SBenjamin Tissoires 	hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
1167b7966a4dSBenjamin Tissoires 	hid_hw_wait(hid);
11686db3dfefSJiri Kosina 
11696db3dfefSJiri Kosina 	if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
11701168df7eSAnssi Hannula 		while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
11716db3dfefSJiri Kosina 			if (i++ > 20) {
11724291ee30SJoe Perches 				hid_warn(pidff->hid,
11734291ee30SJoe Perches 					 "device reports %d simultaneous effects\n",
11741168df7eSAnssi Hannula 					 pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
11756db3dfefSJiri Kosina 				break;
11766db3dfefSJiri Kosina 			}
11774291ee30SJoe Perches 			hid_dbg(pidff->hid, "pid_pool requested again\n");
1178d8814272SBenjamin Tissoires 			hid_hw_request(hid, pidff->reports[PID_POOL],
1179d8814272SBenjamin Tissoires 					  HID_REQ_GET_REPORT);
1180b7966a4dSBenjamin Tissoires 			hid_hw_wait(hid);
11816db3dfefSJiri Kosina 		}
11826db3dfefSJiri Kosina 	}
11836db3dfefSJiri Kosina }
11846db3dfefSJiri Kosina 
11856db3dfefSJiri Kosina /*
11866db3dfefSJiri Kosina  * Test if autocenter modification is using the supported method
11876db3dfefSJiri Kosina  */
pidff_check_autocenter(struct pidff_device * pidff,struct input_dev * dev)11886db3dfefSJiri Kosina static int pidff_check_autocenter(struct pidff_device *pidff,
11896db3dfefSJiri Kosina 				  struct input_dev *dev)
11906db3dfefSJiri Kosina {
11916db3dfefSJiri Kosina 	int error;
11926db3dfefSJiri Kosina 
11936db3dfefSJiri Kosina 	/*
11946db3dfefSJiri Kosina 	 * Let's find out if autocenter modification is supported
11956db3dfefSJiri Kosina 	 * Specification doesn't specify anything, so we request an
11966db3dfefSJiri Kosina 	 * effect upload and cancel it immediately. If the approved
11976db3dfefSJiri Kosina 	 * effect id was one above the minimum, then we assume the first
11986db3dfefSJiri Kosina 	 * effect id is a built-in spring type effect used for autocenter
11996db3dfefSJiri Kosina 	 */
12006db3dfefSJiri Kosina 
12016db3dfefSJiri Kosina 	error = pidff_request_effect_upload(pidff, 1);
12026db3dfefSJiri Kosina 	if (error) {
12034291ee30SJoe Perches 		hid_err(pidff->hid, "upload request failed\n");
12046db3dfefSJiri Kosina 		return error;
12056db3dfefSJiri Kosina 	}
12066db3dfefSJiri Kosina 
12076db3dfefSJiri Kosina 	if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] ==
12086db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) {
12096db3dfefSJiri Kosina 		pidff_autocenter(pidff, 0xffff);
12106db3dfefSJiri Kosina 		set_bit(FF_AUTOCENTER, dev->ffbit);
12116db3dfefSJiri Kosina 	} else {
12124291ee30SJoe Perches 		hid_notice(pidff->hid,
12136db3dfefSJiri Kosina 			   "device has unknown autocenter control method\n");
12146db3dfefSJiri Kosina 	}
12156db3dfefSJiri Kosina 
12166db3dfefSJiri Kosina 	pidff_erase_pid(pidff,
12176db3dfefSJiri Kosina 			pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]);
12186db3dfefSJiri Kosina 
12196db3dfefSJiri Kosina 	return 0;
12206db3dfefSJiri Kosina 
12216db3dfefSJiri Kosina }
12226db3dfefSJiri Kosina 
12236db3dfefSJiri Kosina /*
12246db3dfefSJiri Kosina  * Check if the device is PID and initialize it
12256db3dfefSJiri Kosina  */
hid_pidff_init(struct hid_device * hid)12266db3dfefSJiri Kosina int hid_pidff_init(struct hid_device *hid)
12276db3dfefSJiri Kosina {
12286db3dfefSJiri Kosina 	struct pidff_device *pidff;
12296db3dfefSJiri Kosina 	struct hid_input *hidinput = list_entry(hid->inputs.next,
12306db3dfefSJiri Kosina 						struct hid_input, list);
12316db3dfefSJiri Kosina 	struct input_dev *dev = hidinput->input;
12326db3dfefSJiri Kosina 	struct ff_device *ff;
12336db3dfefSJiri Kosina 	int max_effects;
12346db3dfefSJiri Kosina 	int error;
12356db3dfefSJiri Kosina 
12364291ee30SJoe Perches 	hid_dbg(hid, "starting pid init\n");
12376db3dfefSJiri Kosina 
12386db3dfefSJiri Kosina 	if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) {
12394291ee30SJoe Perches 		hid_dbg(hid, "not a PID device, no output report\n");
12406db3dfefSJiri Kosina 		return -ENODEV;
12416db3dfefSJiri Kosina 	}
12426db3dfefSJiri Kosina 
12436db3dfefSJiri Kosina 	pidff = kzalloc(sizeof(*pidff), GFP_KERNEL);
12446db3dfefSJiri Kosina 	if (!pidff)
12456db3dfefSJiri Kosina 		return -ENOMEM;
12466db3dfefSJiri Kosina 
12476db3dfefSJiri Kosina 	pidff->hid = hid;
12486db3dfefSJiri Kosina 
1249afd700d9SJim Keir 	hid_device_io_start(hid);
1250afd700d9SJim Keir 
12516db3dfefSJiri Kosina 	pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff);
12526db3dfefSJiri Kosina 	pidff_find_reports(hid, HID_FEATURE_REPORT, pidff);
12536db3dfefSJiri Kosina 
12546db3dfefSJiri Kosina 	if (!pidff_reports_ok(pidff)) {
12554291ee30SJoe Perches 		hid_dbg(hid, "reports not ok, aborting\n");
12566db3dfefSJiri Kosina 		error = -ENODEV;
12576db3dfefSJiri Kosina 		goto fail;
12586db3dfefSJiri Kosina 	}
12596db3dfefSJiri Kosina 
12606db3dfefSJiri Kosina 	error = pidff_init_fields(pidff, dev);
12616db3dfefSJiri Kosina 	if (error)
12626db3dfefSJiri Kosina 		goto fail;
12636db3dfefSJiri Kosina 
12646db3dfefSJiri Kosina 	pidff_reset(pidff);
12656db3dfefSJiri Kosina 
12666db3dfefSJiri Kosina 	if (test_bit(FF_GAIN, dev->ffbit)) {
12676db3dfefSJiri Kosina 		pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
1268d8814272SBenjamin Tissoires 		hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
1269d8814272SBenjamin Tissoires 				     HID_REQ_SET_REPORT);
12706db3dfefSJiri Kosina 	}
12716db3dfefSJiri Kosina 
12726db3dfefSJiri Kosina 	error = pidff_check_autocenter(pidff, dev);
12736db3dfefSJiri Kosina 	if (error)
12746db3dfefSJiri Kosina 		goto fail;
12756db3dfefSJiri Kosina 
12766db3dfefSJiri Kosina 	max_effects =
12776db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum -
12786db3dfefSJiri Kosina 	    pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum +
12796db3dfefSJiri Kosina 	    1;
12804291ee30SJoe Perches 	hid_dbg(hid, "max effects is %d\n", max_effects);
12816db3dfefSJiri Kosina 
12826db3dfefSJiri Kosina 	if (max_effects > PID_EFFECTS_MAX)
12836db3dfefSJiri Kosina 		max_effects = PID_EFFECTS_MAX;
12846db3dfefSJiri Kosina 
12856db3dfefSJiri Kosina 	if (pidff->pool[PID_SIMULTANEOUS_MAX].value)
12864291ee30SJoe Perches 		hid_dbg(hid, "max simultaneous effects is %d\n",
12876db3dfefSJiri Kosina 			pidff->pool[PID_SIMULTANEOUS_MAX].value[0]);
12886db3dfefSJiri Kosina 
12896db3dfefSJiri Kosina 	if (pidff->pool[PID_RAM_POOL_SIZE].value)
12904291ee30SJoe Perches 		hid_dbg(hid, "device memory size is %d bytes\n",
12916db3dfefSJiri Kosina 			pidff->pool[PID_RAM_POOL_SIZE].value[0]);
12926db3dfefSJiri Kosina 
12936db3dfefSJiri Kosina 	if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
12946db3dfefSJiri Kosina 	    pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
1295*3dd653c0SZhen Lei 		error = -EPERM;
12964291ee30SJoe Perches 		hid_notice(hid,
12976db3dfefSJiri Kosina 			   "device does not support device managed pool\n");
12986db3dfefSJiri Kosina 		goto fail;
12996db3dfefSJiri Kosina 	}
13006db3dfefSJiri Kosina 
13016db3dfefSJiri Kosina 	error = input_ff_create(dev, max_effects);
13026db3dfefSJiri Kosina 	if (error)
13036db3dfefSJiri Kosina 		goto fail;
13046db3dfefSJiri Kosina 
13056db3dfefSJiri Kosina 	ff = dev->ff;
13066db3dfefSJiri Kosina 	ff->private = pidff;
13076db3dfefSJiri Kosina 	ff->upload = pidff_upload_effect;
13086db3dfefSJiri Kosina 	ff->erase = pidff_erase_effect;
13096db3dfefSJiri Kosina 	ff->set_gain = pidff_set_gain;
13106db3dfefSJiri Kosina 	ff->set_autocenter = pidff_set_autocenter;
13116db3dfefSJiri Kosina 	ff->playback = pidff_playback;
13126db3dfefSJiri Kosina 
13134291ee30SJoe Perches 	hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
13146db3dfefSJiri Kosina 
1315afd700d9SJim Keir 	hid_device_io_stop(hid);
1316afd700d9SJim Keir 
13176db3dfefSJiri Kosina 	return 0;
13186db3dfefSJiri Kosina 
13196db3dfefSJiri Kosina  fail:
1320afd700d9SJim Keir 	hid_device_io_stop(hid);
1321afd700d9SJim Keir 
13226db3dfefSJiri Kosina 	kfree(pidff);
13236db3dfefSJiri Kosina 	return error;
13246db3dfefSJiri Kosina }
1325