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