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 <linux/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 */
36 * Update head and tail of xmit buffer
38 scoped_guard(spinlock_irqsave
, &iforce
->xmit_lock
) {
39 head
= iforce
->xmit
.head
;
40 tail
= iforce
->xmit
.tail
;
42 if (CIRC_SPACE(head
, tail
, XMIT_SIZE
) < n
+ 2) {
43 dev_warn(&iforce
->dev
->dev
,
44 "not enough space in xmit buffer to send new packet\n");
49 XMIT_INC(iforce
->xmit
.head
, n
+ 2);
52 * Store packet in xmit buffer
54 iforce
->xmit
.buf
[head
] = HI(cmd
);
56 iforce
->xmit
.buf
[head
] = LO(cmd
);
59 c
= CIRC_SPACE_TO_END(head
, tail
, XMIT_SIZE
);
63 memcpy(&iforce
->xmit
.buf
[head
], data
, c
);
65 memcpy(&iforce
->xmit
.buf
[0], data
+ c
, n
- c
);
71 * If necessary, start the transmission
74 iforce
->xport_ops
->xmit(iforce
);
78 EXPORT_SYMBOL(iforce_send_packet
);
80 /* Start or stop an effect */
81 int iforce_control_playback(struct iforce
* iforce
, u16 id
, unsigned int value
)
83 unsigned char data
[3];
86 data
[1] = (value
> 0) ? ((value
> 1) ? 0x41 : 0x01) : 0;
88 return iforce_send_packet(iforce
, FF_CMD_PLAY
, data
);
91 /* Mark an effect that was being updated as ready. That means it can be updated
93 static int mark_core_as_ready(struct iforce
*iforce
, unsigned short addr
)
100 for (i
= 0; i
< iforce
->dev
->ff
->max_effects
; ++i
) {
101 if (test_bit(FF_CORE_IS_USED
, iforce
->core_effects
[i
].flags
) &&
102 (iforce
->core_effects
[i
].mod1_chunk
.start
== addr
||
103 iforce
->core_effects
[i
].mod2_chunk
.start
== addr
)) {
104 clear_bit(FF_CORE_UPDATE
, iforce
->core_effects
[i
].flags
);
108 dev_warn(&iforce
->dev
->dev
, "unused effect %04x updated !!!\n", addr
);
112 static void iforce_report_hats_buttons(struct iforce
*iforce
, u8
*data
)
114 struct input_dev
*dev
= iforce
->dev
;
117 input_report_abs(dev
, ABS_HAT0X
, iforce_hat_to_axis
[data
[6] >> 4].x
);
118 input_report_abs(dev
, ABS_HAT0Y
, iforce_hat_to_axis
[data
[6] >> 4].y
);
120 for (i
= 0; iforce
->type
->btn
[i
] >= 0; i
++)
121 input_report_key(dev
, iforce
->type
->btn
[i
],
122 data
[(i
>> 3) + 5] & (1 << (i
& 7)));
124 /* If there are untouched bits left, interpret them as the second hat */
128 if (test_bit(ABS_HAT1X
, dev
->absbit
)) {
130 input_report_abs(dev
, ABS_HAT1X
, -1);
131 else if (btns
& BIT(1))
132 input_report_abs(dev
, ABS_HAT1X
, 1);
134 input_report_abs(dev
, ABS_HAT1X
, 0);
137 if (test_bit(ABS_HAT1Y
, dev
->absbit
)) {
139 input_report_abs(dev
, ABS_HAT1Y
, -1);
140 else if (btns
& BIT(2))
141 input_report_abs(dev
, ABS_HAT1Y
, 1);
143 input_report_abs(dev
, ABS_HAT1Y
, 0);
148 void iforce_process_packet(struct iforce
*iforce
,
149 u8 packet_id
, u8
*data
, size_t len
)
151 struct input_dev
*dev
= iforce
->dev
;
156 case 0x01: /* joystick position data */
157 input_report_abs(dev
, ABS_X
,
158 (__s16
) get_unaligned_le16(data
));
159 input_report_abs(dev
, ABS_Y
,
160 (__s16
) get_unaligned_le16(data
+ 2));
161 input_report_abs(dev
, ABS_THROTTLE
, 255 - data
[4]);
163 if (len
>= 8 && test_bit(ABS_RUDDER
,dev
->absbit
))
164 input_report_abs(dev
, ABS_RUDDER
, (__s8
)data
[7]);
166 iforce_report_hats_buttons(iforce
, data
);
171 case 0x03: /* wheel position data */
172 input_report_abs(dev
, ABS_WHEEL
,
173 (__s16
) get_unaligned_le16(data
));
174 input_report_abs(dev
, ABS_GAS
, 255 - data
[2]);
175 input_report_abs(dev
, ABS_BRAKE
, 255 - data
[3]);
177 iforce_report_hats_buttons(iforce
, data
);
182 case 0x02: /* status report */
183 input_report_key(dev
, BTN_DEAD
, data
[0] & 0x02);
186 /* Check if an effect was just started or stopped */
188 if (data
[1] & 0x80) {
189 if (!test_and_set_bit(FF_CORE_IS_PLAYED
, iforce
->core_effects
[i
].flags
)) {
190 /* Report play event */
191 input_report_ff_status(dev
, i
, FF_STATUS_PLAYING
);
193 } else if (test_and_clear_bit(FF_CORE_IS_PLAYED
, iforce
->core_effects
[i
].flags
)) {
194 /* Report stop event */
195 input_report_ff_status(dev
, i
, FF_STATUS_STOPPED
);
198 for (j
= 3; j
< len
; j
+= 2)
199 mark_core_as_ready(iforce
, get_unaligned_le16(data
+ j
));
204 EXPORT_SYMBOL(iforce_process_packet
);