hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/input/joystick/iforce/iforce-serio.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
34 * Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
....@@ -5,26 +6,26 @@
56 * USB/RS232 I-Force joysticks and wheels.
67 */
78
8
-/*
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; either version 2 of the License, or
12
- * (at your option) any later version.
13
- *
14
- * This program is distributed in the hope that it will be useful,
15
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- * GNU General Public License for more details.
18
- *
19
- * You should have received a copy of the GNU General Public License
20
- * along with this program; if not, write to the Free Software
21
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
- */
23
-
9
+#include <linux/serio.h>
2410 #include "iforce.h"
2511
26
-void iforce_serial_xmit(struct iforce *iforce)
12
+struct iforce_serio {
13
+ struct iforce iforce;
14
+
15
+ struct serio *serio;
16
+ int idx, pkt, len, id;
17
+ u8 csum;
18
+ u8 expect_packet;
19
+ u8 cmd_response[IFORCE_MAX_LENGTH];
20
+ u8 cmd_response_len;
21
+ u8 data_in[IFORCE_MAX_LENGTH];
22
+};
23
+
24
+static void iforce_serio_xmit(struct iforce *iforce)
2725 {
26
+ struct iforce_serio *iforce_serio = container_of(iforce,
27
+ struct iforce_serio,
28
+ iforce);
2829 unsigned char cs;
2930 int i;
3031 unsigned long flags;
....@@ -38,83 +39,148 @@
3839
3940 again:
4041 if (iforce->xmit.head == iforce->xmit.tail) {
41
- clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
42
+ iforce_clear_xmit_and_wake(iforce);
4243 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
4344 return;
4445 }
4546
4647 cs = 0x2b;
4748
48
- serio_write(iforce->serio, 0x2b);
49
+ serio_write(iforce_serio->serio, 0x2b);
4950
50
- serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
51
+ serio_write(iforce_serio->serio, iforce->xmit.buf[iforce->xmit.tail]);
5152 cs ^= iforce->xmit.buf[iforce->xmit.tail];
5253 XMIT_INC(iforce->xmit.tail, 1);
5354
5455 for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
55
- serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
56
+ serio_write(iforce_serio->serio,
57
+ iforce->xmit.buf[iforce->xmit.tail]);
5658 cs ^= iforce->xmit.buf[iforce->xmit.tail];
5759 XMIT_INC(iforce->xmit.tail, 1);
5860 }
5961
60
- serio_write(iforce->serio, cs);
62
+ serio_write(iforce_serio->serio, cs);
6163
6264 if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
6365 goto again;
6466
65
- clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
67
+ iforce_clear_xmit_and_wake(iforce);
6668
6769 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
6870 }
71
+
72
+static int iforce_serio_get_id(struct iforce *iforce, u8 id,
73
+ u8 *response_data, size_t *response_len)
74
+{
75
+ struct iforce_serio *iforce_serio = container_of(iforce,
76
+ struct iforce_serio,
77
+ iforce);
78
+
79
+ iforce_serio->expect_packet = HI(FF_CMD_QUERY);
80
+ iforce_serio->cmd_response_len = 0;
81
+
82
+ iforce_send_packet(iforce, FF_CMD_QUERY, &id);
83
+
84
+ wait_event_interruptible_timeout(iforce->wait,
85
+ !iforce_serio->expect_packet, HZ);
86
+
87
+ if (iforce_serio->expect_packet) {
88
+ iforce_serio->expect_packet = 0;
89
+ return -ETIMEDOUT;
90
+ }
91
+
92
+ if (iforce_serio->cmd_response[0] != id)
93
+ return -EIO;
94
+
95
+ memcpy(response_data, iforce_serio->cmd_response,
96
+ iforce_serio->cmd_response_len);
97
+ *response_len = iforce_serio->cmd_response_len;
98
+
99
+ return 0;
100
+}
101
+
102
+static int iforce_serio_start_io(struct iforce *iforce)
103
+{
104
+ /* No special handling required */
105
+ return 0;
106
+}
107
+
108
+static void iforce_serio_stop_io(struct iforce *iforce)
109
+{
110
+ //TODO: Wait for the last packets to be sent
111
+}
112
+
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,
118
+};
69119
70120 static void iforce_serio_write_wakeup(struct serio *serio)
71121 {
72122 struct iforce *iforce = serio_get_drvdata(serio);
73123
74
- iforce_serial_xmit(iforce);
124
+ iforce_serio_xmit(iforce);
75125 }
76126
77127 static irqreturn_t iforce_serio_irq(struct serio *serio,
78
- unsigned char data, unsigned int flags)
128
+ unsigned char data, unsigned int flags)
79129 {
80
- struct iforce *iforce = serio_get_drvdata(serio);
130
+ struct iforce_serio *iforce_serio = serio_get_drvdata(serio);
131
+ struct iforce *iforce = &iforce_serio->iforce;
81132
82
- if (!iforce->pkt) {
133
+ if (!iforce_serio->pkt) {
83134 if (data == 0x2b)
84
- iforce->pkt = 1;
135
+ iforce_serio->pkt = 1;
85136 goto out;
86137 }
87138
88
- if (!iforce->id) {
139
+ if (!iforce_serio->id) {
89140 if (data > 3 && data != 0xff)
90
- iforce->pkt = 0;
141
+ iforce_serio->pkt = 0;
91142 else
92
- iforce->id = data;
143
+ iforce_serio->id = data;
93144 goto out;
94145 }
95146
96
- if (!iforce->len) {
147
+ if (!iforce_serio->len) {
97148 if (data > IFORCE_MAX_LENGTH) {
98
- iforce->pkt = 0;
99
- iforce->id = 0;
149
+ iforce_serio->pkt = 0;
150
+ iforce_serio->id = 0;
100151 } else {
101
- iforce->len = data;
152
+ iforce_serio->len = data;
102153 }
103154 goto out;
104155 }
105156
106
- if (iforce->idx < iforce->len) {
107
- iforce->csum += iforce->data[iforce->idx++] = data;
157
+ if (iforce_serio->idx < iforce_serio->len) {
158
+ iforce_serio->data_in[iforce_serio->idx++] = data;
159
+ iforce_serio->csum += data;
108160 goto out;
109161 }
110162
111
- if (iforce->idx == iforce->len) {
112
- iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data);
113
- iforce->pkt = 0;
114
- iforce->id = 0;
115
- iforce->len = 0;
116
- iforce->idx = 0;
117
- iforce->csum = 0;
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;
170
+
171
+ /* Signal that command is done */
172
+ wake_up_all(&iforce->wait);
173
+ } else if (likely(iforce->type)) {
174
+ iforce_process_packet(iforce, iforce_serio->id,
175
+ iforce_serio->data_in,
176
+ iforce_serio->len);
177
+ }
178
+
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;
118184 }
119185 out:
120186 return IRQ_HANDLED;
....@@ -122,23 +188,23 @@
122188
123189 static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
124190 {
125
- struct iforce *iforce;
191
+ struct iforce_serio *iforce_serio;
126192 int err;
127193
128
- iforce = kzalloc(sizeof(struct iforce), GFP_KERNEL);
129
- if (!iforce)
194
+ iforce_serio = kzalloc(sizeof(*iforce_serio), GFP_KERNEL);
195
+ if (!iforce_serio)
130196 return -ENOMEM;
131197
132
- iforce->bus = IFORCE_232;
133
- iforce->serio = serio;
198
+ iforce_serio->iforce.xport_ops = &iforce_serio_xport_ops;
134199
135
- serio_set_drvdata(serio, iforce);
200
+ iforce_serio->serio = serio;
201
+ serio_set_drvdata(serio, iforce_serio);
136202
137203 err = serio_open(serio, drv);
138204 if (err)
139205 goto fail1;
140206
141
- err = iforce_init_device(iforce);
207
+ err = iforce_init_device(&serio->dev, BUS_RS232, &iforce_serio->iforce);
142208 if (err)
143209 goto fail2;
144210
....@@ -146,18 +212,18 @@
146212
147213 fail2: serio_close(serio);
148214 fail1: serio_set_drvdata(serio, NULL);
149
- kfree(iforce);
215
+ kfree(iforce_serio);
150216 return err;
151217 }
152218
153219 static void iforce_serio_disconnect(struct serio *serio)
154220 {
155
- struct iforce *iforce = serio_get_drvdata(serio);
221
+ struct iforce_serio *iforce_serio = serio_get_drvdata(serio);
156222
157
- input_unregister_device(iforce->dev);
223
+ input_unregister_device(iforce_serio->iforce.dev);
158224 serio_close(serio);
159225 serio_set_drvdata(serio, NULL);
160
- kfree(iforce);
226
+ kfree(iforce_serio);
161227 }
162228
163229 static const struct serio_device_id iforce_serio_ids[] = {
....@@ -183,3 +249,9 @@
183249 .connect = iforce_serio_connect,
184250 .disconnect = iforce_serio_disconnect,
185251 };
252
+
253
+module_serio_driver(iforce_serio_drv);
254
+
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");