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