1 // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
4  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
5  *
6  *  USB/RS232 I-Force joysticks and wheels.
7  */
8 
9 /*
10  */
11 
12 #include <linux/usb.h>
13 #include "iforce.h"
14 
15 struct iforce_usb {
16 	struct iforce iforce;
17 
18 	struct usb_device *usbdev;
19 	struct usb_interface *intf;
20 	struct urb *irq, *out;
21 
22 	u8 data_in[IFORCE_MAX_LENGTH] ____cacheline_aligned;
23 	u8 data_out[IFORCE_MAX_LENGTH] ____cacheline_aligned;
24 };
25 
26 static void __iforce_usb_xmit(struct iforce *iforce)
27 {
28 	struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
29 						     iforce);
30 	int n, c;
31 	unsigned long flags;
32 
33 	spin_lock_irqsave(&iforce->xmit_lock, flags);
34 
35 	if (iforce->xmit.head == iforce->xmit.tail) {
36 		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
37 		spin_unlock_irqrestore(&iforce->xmit_lock, flags);
38 		return;
39 	}
40 
41 	((char *)iforce_usb->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
42 	XMIT_INC(iforce->xmit.tail, 1);
43 	n = iforce->xmit.buf[iforce->xmit.tail];
44 	XMIT_INC(iforce->xmit.tail, 1);
45 
46 	iforce_usb->out->transfer_buffer_length = n + 1;
47 	iforce_usb->out->dev = iforce_usb->usbdev;
48 
49 	/* Copy rest of data then */
50 	c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
51 	if (n < c) c=n;
52 
53 	memcpy(iforce_usb->out->transfer_buffer + 1,
54 	       &iforce->xmit.buf[iforce->xmit.tail],
55 	       c);
56 	if (n != c) {
57 		memcpy(iforce_usb->out->transfer_buffer + 1 + c,
58 		       &iforce->xmit.buf[0],
59 		       n-c);
60 	}
61 	XMIT_INC(iforce->xmit.tail, n);
62 
63 	if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) {
64 		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
65 		dev_warn(&iforce_usb->intf->dev,
66 			 "usb_submit_urb failed %d\n", n);
67 	}
68 
69 	/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
70 	 * As long as the urb completion handler is not called, the transmiting
71 	 * is considered to be running */
72 	spin_unlock_irqrestore(&iforce->xmit_lock, flags);
73 }
74 
75 static void iforce_usb_xmit(struct iforce *iforce)
76 {
77 	if (!test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags))
78 		__iforce_usb_xmit(iforce);
79 }
80 
81 static int iforce_usb_get_id(struct iforce *iforce, u8 id,
82 			     u8 *response_data, size_t *response_len)
83 {
84 	struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
85 						     iforce);
86 	u8 *buf;
87 	int status;
88 
89 	buf = kmalloc(IFORCE_MAX_LENGTH, GFP_KERNEL);
90 	if (!buf)
91 		return -ENOMEM;
92 
93 	status = usb_control_msg(iforce_usb->usbdev,
94 				 usb_rcvctrlpipe(iforce_usb->usbdev, 0),
95 				 id,
96 				 USB_TYPE_VENDOR | USB_DIR_IN |
97 					USB_RECIP_INTERFACE,
98 				 0, 0, buf, IFORCE_MAX_LENGTH, HZ);
99 	if (status < 0) {
100 		dev_err(&iforce_usb->intf->dev,
101 			"usb_submit_urb failed: %d\n", status);
102 	} else if (buf[0] != id) {
103 		status = -EIO;
104 	} else {
105 		memcpy(response_data, buf, status);
106 		*response_len = status;
107 		status = 0;
108 	}
109 
110 	kfree(buf);
111 	return status;
112 }
113 
114 static int iforce_usb_start_io(struct iforce *iforce)
115 {
116 	struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
117 						     iforce);
118 
119 	if (usb_submit_urb(iforce_usb->irq, GFP_KERNEL))
120 		return -EIO;
121 
122 	return 0;
123 }
124 
125 static void iforce_usb_stop_io(struct iforce *iforce)
126 {
127 	struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
128 						     iforce);
129 
130 	usb_kill_urb(iforce_usb->irq);
131 	usb_kill_urb(iforce_usb->out);
132 }
133 
134 static const struct iforce_xport_ops iforce_usb_xport_ops = {
135 	.xmit		= iforce_usb_xmit,
136 	.get_id		= iforce_usb_get_id,
137 	.start_io	= iforce_usb_start_io,
138 	.stop_io	= iforce_usb_stop_io,
139 };
140 
141 static void iforce_usb_irq(struct urb *urb)
142 {
143 	struct iforce_usb *iforce_usb = urb->context;
144 	struct iforce *iforce = &iforce_usb->iforce;
145 	struct device *dev = &iforce_usb->intf->dev;
146 	int status;
147 
148 	switch (urb->status) {
149 	case 0:
150 		/* success */
151 		break;
152 	case -ECONNRESET:
153 	case -ENOENT:
154 	case -ESHUTDOWN:
155 		/* this urb is terminated, clean up */
156 		dev_dbg(dev, "%s - urb shutting down with status: %d\n",
157 			__func__, urb->status);
158 		return;
159 	default:
160 		dev_dbg(dev, "%s - urb has status of: %d\n",
161 			__func__, urb->status);
162 		goto exit;
163 	}
164 
165 	iforce_process_packet(iforce, iforce_usb->data_in[0],
166 			      iforce_usb->data_in + 1, urb->actual_length - 1);
167 
168 exit:
169 	status = usb_submit_urb(urb, GFP_ATOMIC);
170 	if (status)
171 		dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
172 			__func__, status);
173 }
174 
175 static void iforce_usb_out(struct urb *urb)
176 {
177 	struct iforce_usb *iforce_usb = urb->context;
178 	struct iforce *iforce = &iforce_usb->iforce;
179 
180 	if (urb->status) {
181 		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
182 		dev_dbg(&iforce_usb->intf->dev, "urb->status %d, exiting\n",
183 			urb->status);
184 		return;
185 	}
186 
187 	__iforce_usb_xmit(iforce);
188 
189 	wake_up(&iforce->wait);
190 }
191 
192 static int iforce_usb_probe(struct usb_interface *intf,
193 				const struct usb_device_id *id)
194 {
195 	struct usb_device *dev = interface_to_usbdev(intf);
196 	struct usb_host_interface *interface;
197 	struct usb_endpoint_descriptor *epirq, *epout;
198 	struct iforce_usb *iforce_usb;
199 	int err = -ENOMEM;
200 
201 	interface = intf->cur_altsetting;
202 
203 	if (interface->desc.bNumEndpoints < 2)
204 		return -ENODEV;
205 
206 	epirq = &interface->endpoint[0].desc;
207 	epout = &interface->endpoint[1].desc;
208 
209 	iforce_usb = kzalloc(sizeof(*iforce_usb), GFP_KERNEL);
210 	if (!iforce_usb)
211 		goto fail;
212 
213 	iforce_usb->irq = usb_alloc_urb(0, GFP_KERNEL);
214 	if (!iforce_usb->irq)
215 		goto fail;
216 
217 	iforce_usb->out = usb_alloc_urb(0, GFP_KERNEL);
218 	if (!iforce_usb->out)
219 		goto fail;
220 
221 	iforce_usb->iforce.xport_ops = &iforce_usb_xport_ops;
222 
223 	iforce_usb->usbdev = dev;
224 	iforce_usb->intf = intf;
225 
226 	usb_fill_int_urb(iforce_usb->irq, dev,
227 			 usb_rcvintpipe(dev, epirq->bEndpointAddress),
228 			 iforce_usb->data_in, sizeof(iforce_usb->data_in),
229 			 iforce_usb_irq, iforce_usb, epirq->bInterval);
230 
231 	usb_fill_int_urb(iforce_usb->out, dev,
232 			 usb_sndintpipe(dev, epout->bEndpointAddress),
233 			 iforce_usb->data_out, sizeof(iforce_usb->data_out),
234 			 iforce_usb_out, iforce_usb, epout->bInterval);
235 
236 	err = iforce_init_device(&intf->dev, BUS_USB, &iforce_usb->iforce);
237 	if (err)
238 		goto fail;
239 
240 	usb_set_intfdata(intf, iforce_usb);
241 	return 0;
242 
243 fail:
244 	if (iforce_usb) {
245 		usb_free_urb(iforce_usb->irq);
246 		usb_free_urb(iforce_usb->out);
247 		kfree(iforce_usb);
248 	}
249 
250 	return err;
251 }
252 
253 static void iforce_usb_disconnect(struct usb_interface *intf)
254 {
255 	struct iforce_usb *iforce_usb = usb_get_intfdata(intf);
256 
257 	usb_set_intfdata(intf, NULL);
258 
259 	input_unregister_device(iforce_usb->iforce.dev);
260 
261 	usb_free_urb(iforce_usb->irq);
262 	usb_free_urb(iforce_usb->out);
263 
264 	kfree(iforce_usb);
265 }
266 
267 static const struct usb_device_id iforce_usb_ids[] = {
268 	{ USB_DEVICE(0x044f, 0xa01c) },		/* Thrustmaster Motor Sport GT */
269 	{ USB_DEVICE(0x046d, 0xc281) },		/* Logitech WingMan Force */
270 	{ USB_DEVICE(0x046d, 0xc291) },		/* Logitech WingMan Formula Force */
271 	{ USB_DEVICE(0x05ef, 0x020a) },		/* AVB Top Shot Pegasus */
272 	{ USB_DEVICE(0x05ef, 0x8884) },		/* AVB Mag Turbo Force */
273 	{ USB_DEVICE(0x05ef, 0x8888) },		/* AVB Top Shot FFB Racing Wheel */
274 	{ USB_DEVICE(0x061c, 0xc0a4) },         /* ACT LABS Force RS */
275 	{ USB_DEVICE(0x061c, 0xc084) },         /* ACT LABS Force RS */
276 	{ USB_DEVICE(0x06a3, 0xff04) },		/* Saitek R440 Force Wheel */
277 	{ USB_DEVICE(0x06f8, 0x0001) },		/* Guillemot Race Leader Force Feedback */
278 	{ USB_DEVICE(0x06f8, 0x0003) },		/* Guillemot Jet Leader Force Feedback */
279 	{ USB_DEVICE(0x06f8, 0x0004) },		/* Guillemot Force Feedback Racing Wheel */
280 	{ USB_DEVICE(0x06f8, 0xa302) },		/* Guillemot Jet Leader 3D */
281 	{ }					/* Terminating entry */
282 };
283 
284 MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
285 
286 struct usb_driver iforce_usb_driver = {
287 	.name =		"iforce",
288 	.probe =	iforce_usb_probe,
289 	.disconnect =	iforce_usb_disconnect,
290 	.id_table =	iforce_usb_ids,
291 };
292 
293 module_usb_driver(iforce_usb_driver);
294 
295 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
296 MODULE_DESCRIPTION("USB I-Force joysticks and wheels driver");
297 MODULE_LICENSE("GPL");
298