1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
4 * Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
6 * USB/RS232 I-Force joysticks and wheels.
9 #include <linux/serio.h>
16 int idx
, pkt
, len
, id
;
19 u8 cmd_response
[IFORCE_MAX_LENGTH
];
21 u8 data_in
[IFORCE_MAX_LENGTH
];
24 static void iforce_serio_xmit(struct iforce
*iforce
)
26 struct iforce_serio
*iforce_serio
= container_of(iforce
,
33 if (test_and_set_bit(IFORCE_XMIT_RUNNING
, iforce
->xmit_flags
)) {
34 set_bit(IFORCE_XMIT_AGAIN
, iforce
->xmit_flags
);
38 spin_lock_irqsave(&iforce
->xmit_lock
, flags
);
41 if (iforce
->xmit
.head
== iforce
->xmit
.tail
) {
42 clear_bit(IFORCE_XMIT_RUNNING
, iforce
->xmit_flags
);
43 spin_unlock_irqrestore(&iforce
->xmit_lock
, flags
);
49 serio_write(iforce_serio
->serio
, 0x2b);
51 serio_write(iforce_serio
->serio
, iforce
->xmit
.buf
[iforce
->xmit
.tail
]);
52 cs
^= iforce
->xmit
.buf
[iforce
->xmit
.tail
];
53 XMIT_INC(iforce
->xmit
.tail
, 1);
55 for (i
=iforce
->xmit
.buf
[iforce
->xmit
.tail
]; i
>= 0; --i
) {
56 serio_write(iforce_serio
->serio
,
57 iforce
->xmit
.buf
[iforce
->xmit
.tail
]);
58 cs
^= iforce
->xmit
.buf
[iforce
->xmit
.tail
];
59 XMIT_INC(iforce
->xmit
.tail
, 1);
62 serio_write(iforce_serio
->serio
, cs
);
64 if (test_and_clear_bit(IFORCE_XMIT_AGAIN
, iforce
->xmit_flags
))
67 clear_bit(IFORCE_XMIT_RUNNING
, iforce
->xmit_flags
);
69 spin_unlock_irqrestore(&iforce
->xmit_lock
, flags
);
72 static int iforce_serio_get_id(struct iforce
*iforce
, u8 id
,
73 u8
*response_data
, size_t *response_len
)
75 struct iforce_serio
*iforce_serio
= container_of(iforce
,
79 iforce_serio
->expect_packet
= HI(FF_CMD_QUERY
);
80 iforce_serio
->cmd_response_len
= 0;
82 iforce_send_packet(iforce
, FF_CMD_QUERY
, &id
);
84 wait_event_interruptible_timeout(iforce
->wait
,
85 !iforce_serio
->expect_packet
, HZ
);
87 if (iforce_serio
->expect_packet
) {
88 iforce_serio
->expect_packet
= 0;
92 if (iforce_serio
->cmd_response
[0] != id
)
95 memcpy(response_data
, iforce_serio
->cmd_response
,
96 iforce_serio
->cmd_response_len
);
97 *response_len
= iforce_serio
->cmd_response_len
;
102 static int iforce_serio_start_io(struct iforce
*iforce
)
104 /* No special handling required */
108 static void iforce_serio_stop_io(struct iforce
*iforce
)
110 //TODO: Wait for the last packets to be sent
113 static const struct iforce_xport_ops iforce_serio_xport_ops
= {
114 .xmit
= iforce_serio_xmit
,
115 .get_id
= iforce_serio_get_id
,
116 .start_io
= iforce_serio_start_io
,
117 .stop_io
= iforce_serio_stop_io
,
120 static void iforce_serio_write_wakeup(struct serio
*serio
)
122 struct iforce
*iforce
= serio_get_drvdata(serio
);
124 iforce_serio_xmit(iforce
);
127 static irqreturn_t
iforce_serio_irq(struct serio
*serio
,
128 unsigned char data
, unsigned int flags
)
130 struct iforce_serio
*iforce_serio
= serio_get_drvdata(serio
);
131 struct iforce
*iforce
= &iforce_serio
->iforce
;
133 if (!iforce_serio
->pkt
) {
135 iforce_serio
->pkt
= 1;
139 if (!iforce_serio
->id
) {
140 if (data
> 3 && data
!= 0xff)
141 iforce_serio
->pkt
= 0;
143 iforce_serio
->id
= data
;
147 if (!iforce_serio
->len
) {
148 if (data
> IFORCE_MAX_LENGTH
) {
149 iforce_serio
->pkt
= 0;
150 iforce_serio
->id
= 0;
152 iforce_serio
->len
= data
;
157 if (iforce_serio
->idx
< iforce_serio
->len
) {
158 iforce_serio
->data_in
[iforce_serio
->idx
++] = data
;
159 iforce_serio
->csum
+= data
;
163 if (iforce_serio
->idx
== iforce_serio
->len
) {
164 /* Handle command completion */
165 if (iforce_serio
->expect_packet
== iforce_serio
->id
) {
166 iforce_serio
->expect_packet
= 0;
167 memcpy(iforce_serio
->cmd_response
,
168 iforce_serio
->data_in
, IFORCE_MAX_LENGTH
);
169 iforce_serio
->cmd_response_len
= iforce_serio
->len
;
171 /* Signal that command is done */
172 wake_up(&iforce
->wait
);
173 } else if (likely(iforce
->type
)) {
174 iforce_process_packet(iforce
, iforce_serio
->id
,
175 iforce_serio
->data_in
,
179 iforce_serio
->pkt
= 0;
180 iforce_serio
->id
= 0;
181 iforce_serio
->len
= 0;
182 iforce_serio
->idx
= 0;
183 iforce_serio
->csum
= 0;
189 static int iforce_serio_connect(struct serio
*serio
, struct serio_driver
*drv
)
191 struct iforce_serio
*iforce_serio
;
194 iforce_serio
= kzalloc(sizeof(*iforce_serio
), GFP_KERNEL
);
198 iforce_serio
->iforce
.xport_ops
= &iforce_serio_xport_ops
;
200 iforce_serio
->serio
= serio
;
201 serio_set_drvdata(serio
, iforce_serio
);
203 err
= serio_open(serio
, drv
);
207 err
= iforce_init_device(&serio
->dev
, BUS_RS232
, &iforce_serio
->iforce
);
213 fail2
: serio_close(serio
);
214 fail1
: serio_set_drvdata(serio
, NULL
);
219 static void iforce_serio_disconnect(struct serio
*serio
)
221 struct iforce_serio
*iforce_serio
= serio_get_drvdata(serio
);
223 input_unregister_device(iforce_serio
->iforce
.dev
);
225 serio_set_drvdata(serio
, NULL
);
229 static const struct serio_device_id iforce_serio_ids
[] = {
232 .proto
= SERIO_IFORCE
,
239 MODULE_DEVICE_TABLE(serio
, iforce_serio_ids
);
241 struct serio_driver iforce_serio_drv
= {
245 .description
= "RS232 I-Force joysticks and wheels driver",
246 .id_table
= iforce_serio_ids
,
247 .write_wakeup
= iforce_serio_write_wakeup
,
248 .interrupt
= iforce_serio_irq
,
249 .connect
= iforce_serio_connect
,
250 .disconnect
= iforce_serio_disconnect
,
253 module_serio_driver(iforce_serio_drv
);
255 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
256 MODULE_DESCRIPTION("RS232 I-Force joysticks and wheels driver");
257 MODULE_LICENSE("GPL");