1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
4 * Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
6 * USB/RS232 I-Force joysticks and wheels.
9 #include <asm/unaligned.h>
15 } iforce_hat_to_axis
[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
18 void iforce_dump_packet(struct iforce
*iforce
, char *msg
, u16 cmd
, unsigned char *data
)
20 dev_dbg(iforce
->dev
->dev
.parent
, "%s %s cmd = %04x, data = %*ph\n",
21 __func__
, msg
, cmd
, LO(cmd
), data
);
25 * Send a packet of bytes to the device
27 int iforce_send_packet(struct iforce
*iforce
, u16 cmd
, unsigned char* data
)
29 /* Copy data to buffer */
37 * Update head and tail of xmit buffer
39 spin_lock_irqsave(&iforce
->xmit_lock
, flags
);
41 head
= iforce
->xmit
.head
;
42 tail
= iforce
->xmit
.tail
;
45 if (CIRC_SPACE(head
, tail
, XMIT_SIZE
) < n
+2) {
46 dev_warn(&iforce
->dev
->dev
,
47 "not enough space in xmit buffer to send new packet\n");
48 spin_unlock_irqrestore(&iforce
->xmit_lock
, flags
);
53 XMIT_INC(iforce
->xmit
.head
, n
+2);
56 * Store packet in xmit buffer
58 iforce
->xmit
.buf
[head
] = HI(cmd
);
60 iforce
->xmit
.buf
[head
] = LO(cmd
);
63 c
= CIRC_SPACE_TO_END(head
, tail
, XMIT_SIZE
);
66 memcpy(&iforce
->xmit
.buf
[head
],
70 memcpy(&iforce
->xmit
.buf
[0],
76 spin_unlock_irqrestore(&iforce
->xmit_lock
, flags
);
78 * If necessary, start the transmission
81 iforce
->xport_ops
->xmit(iforce
);
85 EXPORT_SYMBOL(iforce_send_packet
);
87 /* Start or stop an effect */
88 int iforce_control_playback(struct iforce
* iforce
, u16 id
, unsigned int value
)
90 unsigned char data
[3];
93 data
[1] = (value
> 0) ? ((value
> 1) ? 0x41 : 0x01) : 0;
95 return iforce_send_packet(iforce
, FF_CMD_PLAY
, data
);
98 /* Mark an effect that was being updated as ready. That means it can be updated
100 static int mark_core_as_ready(struct iforce
*iforce
, unsigned short addr
)
104 if (!iforce
->dev
->ff
)
107 for (i
= 0; i
< iforce
->dev
->ff
->max_effects
; ++i
) {
108 if (test_bit(FF_CORE_IS_USED
, iforce
->core_effects
[i
].flags
) &&
109 (iforce
->core_effects
[i
].mod1_chunk
.start
== addr
||
110 iforce
->core_effects
[i
].mod2_chunk
.start
== addr
)) {
111 clear_bit(FF_CORE_UPDATE
, iforce
->core_effects
[i
].flags
);
115 dev_warn(&iforce
->dev
->dev
, "unused effect %04x updated !!!\n", addr
);
119 static void iforce_report_hats_buttons(struct iforce
*iforce
, u8
*data
)
121 struct input_dev
*dev
= iforce
->dev
;
124 input_report_abs(dev
, ABS_HAT0X
, iforce_hat_to_axis
[data
[6] >> 4].x
);
125 input_report_abs(dev
, ABS_HAT0Y
, iforce_hat_to_axis
[data
[6] >> 4].y
);
127 for (i
= 0; iforce
->type
->btn
[i
] >= 0; i
++)
128 input_report_key(dev
, iforce
->type
->btn
[i
],
129 data
[(i
>> 3) + 5] & (1 << (i
& 7)));
131 /* If there are untouched bits left, interpret them as the second hat */
135 if (test_bit(ABS_HAT1X
, dev
->absbit
)) {
137 input_report_abs(dev
, ABS_HAT1X
, -1);
138 else if (btns
& BIT(1))
139 input_report_abs(dev
, ABS_HAT1X
, 1);
141 input_report_abs(dev
, ABS_HAT1X
, 0);
144 if (test_bit(ABS_HAT1Y
, dev
->absbit
)) {
146 input_report_abs(dev
, ABS_HAT1Y
, -1);
147 else if (btns
& BIT(2))
148 input_report_abs(dev
, ABS_HAT1Y
, 1);
150 input_report_abs(dev
, ABS_HAT1Y
, 0);
155 void iforce_process_packet(struct iforce
*iforce
,
156 u8 packet_id
, u8
*data
, size_t len
)
158 struct input_dev
*dev
= iforce
->dev
;
163 case 0x01: /* joystick position data */
164 input_report_abs(dev
, ABS_X
,
165 (__s16
) get_unaligned_le16(data
));
166 input_report_abs(dev
, ABS_Y
,
167 (__s16
) get_unaligned_le16(data
+ 2));
168 input_report_abs(dev
, ABS_THROTTLE
, 255 - data
[4]);
170 if (len
>= 8 && test_bit(ABS_RUDDER
,dev
->absbit
))
171 input_report_abs(dev
, ABS_RUDDER
, (__s8
)data
[7]);
173 iforce_report_hats_buttons(iforce
, data
);
178 case 0x03: /* wheel position data */
179 input_report_abs(dev
, ABS_WHEEL
,
180 (__s16
) get_unaligned_le16(data
));
181 input_report_abs(dev
, ABS_GAS
, 255 - data
[2]);
182 input_report_abs(dev
, ABS_BRAKE
, 255 - data
[3]);
184 iforce_report_hats_buttons(iforce
, data
);
189 case 0x02: /* status report */
190 input_report_key(dev
, BTN_DEAD
, data
[0] & 0x02);
193 /* Check if an effect was just started or stopped */
195 if (data
[1] & 0x80) {
196 if (!test_and_set_bit(FF_CORE_IS_PLAYED
, iforce
->core_effects
[i
].flags
)) {
197 /* Report play event */
198 input_report_ff_status(dev
, i
, FF_STATUS_PLAYING
);
200 } else if (test_and_clear_bit(FF_CORE_IS_PLAYED
, iforce
->core_effects
[i
].flags
)) {
201 /* Report stop event */
202 input_report_ff_status(dev
, i
, FF_STATUS_STOPPED
);
205 for (j
= 3; j
< len
; j
+= 2)
206 mark_core_as_ready(iforce
, get_unaligned_le16(data
+ j
));
211 EXPORT_SYMBOL(iforce_process_packet
);