[go: nahoru, domu]

11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
3598972d4fb39c8a0826b396e45dc2a8c1dbe4f11Johann Deneux *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  USB/RS232 I-Force joysticks and wheels.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful,
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Should you need to contact me, the author, you can do so either by
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "iforce.h"
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the magnitude of a constant force effect
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return error code
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: caller must ensure exclusive access to device
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int make_magnitude_modifier(struct iforce* iforce,
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod_chunk, int no_alloc, __s16 level)
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data[3];
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!no_alloc) {
4372ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_lock(&iforce->mem_mutex);
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iforce->device_memory.start, iforce->device_memory.end, 2L,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			NULL, NULL)) {
4772ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar			mutex_unlock(&iforce->mem_mutex);
48fe65b97a5885a84baa103d7213754ff29e8f872fAnssi Hannula			return -ENOSPC;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5072ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_unlock(&iforce->mem_mutex);
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[0] = LO(mod_chunk->start);
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[1] = HI(mod_chunk->start);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[2] = HIFIX80(level);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iforce_send_packet(iforce, FF_CMD_MAGNITUDE, data);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iforce_dump_packet("magnitude: ", FF_CMD_MAGNITUDE, data);
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Upload the component of an effect dealing with the period, phase and magnitude
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int make_period_modifier(struct iforce* iforce,
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod_chunk, int no_alloc,
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__s16 magnitude, __s16 offset, u16 period, u16 phase)
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data[7];
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	period = TIME_SCALE(period);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!no_alloc) {
7672ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_lock(&iforce->mem_mutex);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iforce->device_memory.start, iforce->device_memory.end, 2L,
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			NULL, NULL)) {
8072ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar			mutex_unlock(&iforce->mem_mutex);
81fe65b97a5885a84baa103d7213754ff29e8f872fAnssi Hannula			return -ENOSPC;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8372ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_unlock(&iforce->mem_mutex);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[0] = LO(mod_chunk->start);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[1] = HI(mod_chunk->start);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[2] = HIFIX80(magnitude);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[3] = HIFIX80(offset);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[4] = HI(phase);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[5] = LO(period);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[6] = HI(period);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iforce_send_packet(iforce, FF_CMD_PERIOD, data);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Uploads the part of an effect setting the envelope of the force
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int make_envelope_modifier(struct iforce* iforce,
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod_chunk, int no_alloc,
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 attack_duration, __s16 initial_level,
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 fade_duration, __s16 final_level)
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data[8];
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	attack_duration = TIME_SCALE(attack_duration);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fade_duration = TIME_SCALE(fade_duration);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!no_alloc) {
11672ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_lock(&iforce->mem_mutex);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iforce->device_memory.start, iforce->device_memory.end, 2L,
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			NULL, NULL)) {
12072ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar			mutex_unlock(&iforce->mem_mutex);
121fe65b97a5885a84baa103d7213754ff29e8f872fAnssi Hannula			return -ENOSPC;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12372ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_unlock(&iforce->mem_mutex);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[0] = LO(mod_chunk->start);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[1] = HI(mod_chunk->start);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[2] = LO(attack_duration);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[3] = HI(attack_duration);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[4] = HI(initial_level);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[5] = LO(fade_duration);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[6] = HI(fade_duration);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[7] = HI(final_level);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iforce_send_packet(iforce, FF_CMD_ENVELOPE, data);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Component of spring, friction, inertia... effects
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int make_condition_modifier(struct iforce* iforce,
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod_chunk, int no_alloc,
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u16 rsat, __u16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center)
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data[10];
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!no_alloc) {
15372ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_lock(&iforce->mem_mutex);
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iforce->device_memory.start, iforce->device_memory.end, 2L,
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			NULL, NULL)) {
15772ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar			mutex_unlock(&iforce->mem_mutex);
158fe65b97a5885a84baa103d7213754ff29e8f872fAnssi Hannula			return -ENOSPC;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16072ba9f0ce09c5508ec4b0cf30e88899872a83f75Ingo Molnar		mutex_unlock(&iforce->mem_mutex);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[0] = LO(mod_chunk->start);
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[1] = HI(mod_chunk->start);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
166f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	data[2] = (100 * rk) >> 15;	/* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */
167f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	data[3] = (100 * lk) >> 15; /* This code is incorrect on cpus lacking arith shift */
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
169f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	center = (500 * center) >> 15;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[4] = LO(center);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[5] = HI(center);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
173f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	db = (1000 * db) >> 16;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[6] = LO(db);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[7] = HI(db);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
177f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	data[8] = (100 * rsat) >> 16;
178f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	data[9] = (100 * lsat) >> 16;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iforce_send_packet(iforce, FF_CMD_CONDITION, data);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iforce_dump_packet("condition", FF_CMD_CONDITION, data);
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char find_button(struct iforce *iforce, signed short button)
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
189f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; iforce->type->btn[i] >= 0; i++)
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (iforce->type->btn[i] == button)
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return i + 1;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Analyse the changes in an effect, and tell if we need to send an condition
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parameter packet
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2001817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartmanstatic int need_condition_modifier(struct iforce *iforce,
2011817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman				   struct ff_effect *old,
2021817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman				   struct ff_effect *new)
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
204f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	int ret = 0;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new->type != FF_SPRING && new->type != FF_FRICTION) {
2081817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman		dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
2091817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman			 __func__);
210f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		return 0;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
213f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	for (i = 0; i < 2; i++) {
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret |= old->u.condition[i].right_saturation != new->u.condition[i].right_saturation
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			|| old->u.condition[i].left_saturation != new->u.condition[i].left_saturation
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			|| old->u.condition[i].right_coeff != new->u.condition[i].right_coeff
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			|| old->u.condition[i].left_coeff != new->u.condition[i].left_coeff
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			|| old->u.condition[i].deadband != new->u.condition[i].deadband
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			|| old->u.condition[i].center != new->u.condition[i].center;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Analyse the changes in an effect, and tell if we need to send a magnitude
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parameter packet
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2281817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartmanstatic int need_magnitude_modifier(struct iforce *iforce,
2291817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman				   struct ff_effect *old,
2301817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman				   struct ff_effect *effect)
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (effect->type != FF_CONSTANT) {
2331817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman		dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
2341817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman			 __func__);
235f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		return 0;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
238f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	return old->u.constant.level != effect->u.constant.level;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Analyse the changes in an effect, and tell if we need to send an envelope
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parameter packet
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2451817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartmanstatic int need_envelope_modifier(struct iforce *iforce, struct ff_effect *old,
2461817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman				  struct ff_effect *effect)
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (effect->type) {
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FF_CONSTANT:
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (old->u.constant.envelope.attack_length != effect->u.constant.envelope.attack_length
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.constant.envelope.attack_level != effect->u.constant.envelope.attack_level
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.constant.envelope.fade_length != effect->u.constant.envelope.fade_length
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.constant.envelope.fade_level != effect->u.constant.envelope.fade_level)
254f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return 1;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FF_PERIODIC:
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (old->u.periodic.envelope.attack_length != effect->u.periodic.envelope.attack_length
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.periodic.envelope.attack_level != effect->u.periodic.envelope.attack_level
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.periodic.envelope.fade_length != effect->u.periodic.envelope.fade_length
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.periodic.envelope.fade_level != effect->u.periodic.envelope.fade_level)
262f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return 1;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
2661817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman		dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
2671817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman			 __func__);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
270f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	return 0;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Analyse the changes in an effect, and tell if we need to send a periodic
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parameter effect
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2771817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartmanstatic int need_period_modifier(struct iforce *iforce, struct ff_effect *old,
2781817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman				struct ff_effect *new)
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new->type != FF_PERIODIC) {
2811817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman		dev_warn(&iforce->dev->dev, "bad effect type in %s\n",
2821817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman			 __func__);
283f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		return 0;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (old->u.periodic.period != new->u.periodic.period
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.periodic.magnitude != new->u.periodic.magnitude
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.periodic.offset != new->u.periodic.offset
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->u.periodic.phase != new->u.periodic.phase);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Analyse the changes in an effect, and tell if we need to send an effect
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * packet
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
295f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannulastatic int need_core(struct ff_effect *old, struct ff_effect *new)
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (old->direction != new->direction
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->trigger.button != new->trigger.button
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->trigger.interval != new->trigger.interval
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->replay.length != new->replay.length
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| old->replay.delay != new->replay.delay)
302f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		return 1;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	return 0;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send the part common to all effects to the device
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2,
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 effect_type, u8 axes, u16 duration, u16 delay, u16 button,
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 interval, u16 direction)
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char data[14];
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	duration = TIME_SCALE(duration);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	delay    = TIME_SCALE(delay);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	interval = TIME_SCALE(interval);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[0]  = LO(id);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[1]  = effect_type;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[2]  = LO(axes) | find_button(iforce, button);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[3]  = LO(duration);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[4]  = HI(duration);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[5]  = HI(direction);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[6]  = LO(interval);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[7]  = HI(interval);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[8]  = LO(mod_id1);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[9]  = HI(mod_id1);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[10] = LO(mod_id2);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[11] = HI(mod_id2);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[12] = LO(delay);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data[13] = HI(delay);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Stop effect */
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*	iforce_control_playback(iforce, id, 0);*/
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iforce_send_packet(iforce, FF_CMD_EFFECT, data);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If needed, restart effect */
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[id].flags)) {
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* BUG: perhaps we should replay n times, instead of 1. But we do not know n */
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iforce_control_playback(iforce, id, 1);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Upload a periodic effect to the device
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See also iforce_upload_constant.
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
357f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannulaint iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old)
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 wave_code;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int core_id = effect->id;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int param1_err = 1;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int param2_err = 1;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int core_err = 0;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman	if (!old || need_period_modifier(iforce, old, effect)) {
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		param1_err = make_period_modifier(iforce, mod1_chunk,
370f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			old != NULL,
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.periodic.magnitude, effect->u.periodic.offset,
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.periodic.period, effect->u.periodic.phase);
373f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		if (param1_err)
374f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return param1_err;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(FF_MOD1_IS_USED, core_effect->flags);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman	if (!old || need_envelope_modifier(iforce, old, effect)) {
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		param2_err = make_envelope_modifier(iforce, mod2_chunk,
380f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			old !=NULL,
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.periodic.envelope.attack_length,
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.periodic.envelope.attack_level,
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.periodic.envelope.fade_length,
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.periodic.envelope.fade_level);
385f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		if (param2_err)
386f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return param2_err;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(FF_MOD2_IS_USED, core_effect->flags);
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (effect->u.periodic.waveform) {
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FF_SQUARE:		wave_code = 0x20; break;
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FF_TRIANGLE:	wave_code = 0x21; break;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FF_SINE:		wave_code = 0x22; break;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FF_SAW_UP:		wave_code = 0x23; break;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FF_SAW_DOWN:	wave_code = 0x24; break;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:		wave_code = 0x20; break;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
399f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	if (!old || need_core(old, effect)) {
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		core_err = make_core(iforce, effect->id,
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mod1_chunk->start,
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mod2_chunk->start,
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			wave_code,
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0x20,
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->replay.length,
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->replay.delay,
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->trigger.button,
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->trigger.interval,
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->direction);
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If one of the parameter creation failed, we already returned an
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * error code.
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the core creation failed, we return its error code.
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Else: if one parameter at least was created, we return 0
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *       else we return 1;
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return core_err < 0 ? core_err : (param1_err && param2_err);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Upload a constant force effect
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value:
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  <0 Error code
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  0 Ok, effect created or updated
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  1 effect did not change since last upload, and no packet was therefore sent
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
428f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannulaint iforce_upload_constant(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int core_id = effect->id;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int param1_err = 1;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int param2_err = 1;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int core_err = 0;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4381817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman	if (!old || need_magnitude_modifier(iforce, old, effect)) {
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		param1_err = make_magnitude_modifier(iforce, mod1_chunk,
440f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			old != NULL,
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.constant.level);
442f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		if (param1_err)
443f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return param1_err;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(FF_MOD1_IS_USED, core_effect->flags);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman	if (!old || need_envelope_modifier(iforce, old, effect)) {
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		param2_err = make_envelope_modifier(iforce, mod2_chunk,
449f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			old != NULL,
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.constant.envelope.attack_length,
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.constant.envelope.attack_level,
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.constant.envelope.fade_length,
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.constant.envelope.fade_level);
454f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		if (param2_err)
455f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return param2_err;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(FF_MOD2_IS_USED, core_effect->flags);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
459f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	if (!old || need_core(old, effect)) {
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		core_err = make_core(iforce, effect->id,
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mod1_chunk->start,
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mod2_chunk->start,
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0x00,
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			0x20,
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->replay.length,
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->replay.delay,
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->trigger.button,
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->trigger.interval,
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->direction);
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If one of the parameter creation failed, we already returned an
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * error code.
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the core creation failed, we return its error code.
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Else: if one parameter at least was created, we return 0
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *       else we return 1;
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return core_err < 0 ? core_err : (param1_err && param2_err);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Upload an condition effect. Those are for example friction, inertia, springs...
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
484f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannulaint iforce_upload_condition(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old)
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int core_id = effect->id;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod1_chunk = &(core_effect->mod1_chunk);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource* mod2_chunk = &(core_effect->mod2_chunk);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 type;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int param_err = 1;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int core_err = 0;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (effect->type) {
495f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		case FF_SPRING:	type = 0x40; break;
496f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		case FF_DAMPER:	type = 0x41; break;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default: return -1;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5001817b1692a2eab022e805d32e910f4556c89dce8Greg Kroah-Hartman	if (!old || need_condition_modifier(iforce, old, effect)) {
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		param_err = make_condition_modifier(iforce, mod1_chunk,
502f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			old != NULL,
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[0].right_saturation,
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[0].left_saturation,
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[0].right_coeff,
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[0].left_coeff,
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[0].deadband,
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[0].center);
509f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		if (param_err)
510f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return param_err;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(FF_MOD1_IS_USED, core_effect->flags);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		param_err = make_condition_modifier(iforce, mod2_chunk,
514f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			old != NULL,
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[1].right_saturation,
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[1].left_saturation,
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[1].right_coeff,
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[1].left_coeff,
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[1].deadband,
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->u.condition[1].center);
521f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula		if (param_err)
522f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula			return param_err;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_bit(FF_MOD2_IS_USED, core_effect->flags);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
527f6a01c85965c9e6fa8fb893c1fa5db16130d0ccbAnssi Hannula	if (!old || need_core(old, effect)) {
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		core_err = make_core(iforce, effect->id,
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mod1_chunk->start, mod2_chunk->start,
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			type, 0xc0,
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->replay.length, effect->replay.delay,
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->trigger.button, effect->trigger.interval,
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			effect->direction);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the parameter creation failed, we already returned an
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * error code.
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the core creation failed, we return its error code.
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Else: if a parameter  was created, we return 0
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *       else we return 1;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return core_err < 0 ? core_err : param_err;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
544