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