Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002  /*
0003  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
0004  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
0005  *
0006  *  USB/RS232 I-Force joysticks and wheels.
0007  */
0008 
0009 #include <linux/usb.h>
0010 #include "iforce.h"
0011 
0012 struct iforce_usb {
0013     struct iforce iforce;
0014 
0015     struct usb_device *usbdev;
0016     struct usb_interface *intf;
0017     struct urb *irq, *out;
0018 
0019     u8 data_in[IFORCE_MAX_LENGTH] ____cacheline_aligned;
0020     u8 data_out[IFORCE_MAX_LENGTH] ____cacheline_aligned;
0021 };
0022 
0023 static void __iforce_usb_xmit(struct iforce *iforce)
0024 {
0025     struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
0026                              iforce);
0027     int n, c;
0028     unsigned long flags;
0029 
0030     spin_lock_irqsave(&iforce->xmit_lock, flags);
0031 
0032     if (iforce->xmit.head == iforce->xmit.tail) {
0033         iforce_clear_xmit_and_wake(iforce);
0034         spin_unlock_irqrestore(&iforce->xmit_lock, flags);
0035         return;
0036     }
0037 
0038     ((char *)iforce_usb->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
0039     XMIT_INC(iforce->xmit.tail, 1);
0040     n = iforce->xmit.buf[iforce->xmit.tail];
0041     XMIT_INC(iforce->xmit.tail, 1);
0042 
0043     iforce_usb->out->transfer_buffer_length = n + 1;
0044     iforce_usb->out->dev = iforce_usb->usbdev;
0045 
0046     /* Copy rest of data then */
0047     c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
0048     if (n < c) c=n;
0049 
0050     memcpy(iforce_usb->out->transfer_buffer + 1,
0051            &iforce->xmit.buf[iforce->xmit.tail],
0052            c);
0053     if (n != c) {
0054         memcpy(iforce_usb->out->transfer_buffer + 1 + c,
0055                &iforce->xmit.buf[0],
0056                n-c);
0057     }
0058     XMIT_INC(iforce->xmit.tail, n);
0059 
0060     if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) {
0061         dev_warn(&iforce_usb->intf->dev,
0062              "usb_submit_urb failed %d\n", n);
0063         iforce_clear_xmit_and_wake(iforce);
0064     }
0065 
0066     /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
0067      * As long as the urb completion handler is not called, the transmiting
0068      * is considered to be running */
0069     spin_unlock_irqrestore(&iforce->xmit_lock, flags);
0070 }
0071 
0072 static void iforce_usb_xmit(struct iforce *iforce)
0073 {
0074     if (!test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags))
0075         __iforce_usb_xmit(iforce);
0076 }
0077 
0078 static int iforce_usb_get_id(struct iforce *iforce, u8 id,
0079                  u8 *response_data, size_t *response_len)
0080 {
0081     struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
0082                              iforce);
0083     u8 *buf;
0084     int status;
0085 
0086     buf = kmalloc(IFORCE_MAX_LENGTH, GFP_KERNEL);
0087     if (!buf)
0088         return -ENOMEM;
0089 
0090     status = usb_control_msg(iforce_usb->usbdev,
0091                  usb_rcvctrlpipe(iforce_usb->usbdev, 0),
0092                  id,
0093                  USB_TYPE_VENDOR | USB_DIR_IN |
0094                     USB_RECIP_INTERFACE,
0095                  0, 0, buf, IFORCE_MAX_LENGTH, 1000);
0096     if (status < 0) {
0097         dev_err(&iforce_usb->intf->dev,
0098             "usb_submit_urb failed: %d\n", status);
0099     } else if (buf[0] != id) {
0100         status = -EIO;
0101     } else {
0102         memcpy(response_data, buf, status);
0103         *response_len = status;
0104         status = 0;
0105     }
0106 
0107     kfree(buf);
0108     return status;
0109 }
0110 
0111 static int iforce_usb_start_io(struct iforce *iforce)
0112 {
0113     struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
0114                              iforce);
0115 
0116     if (usb_submit_urb(iforce_usb->irq, GFP_KERNEL))
0117         return -EIO;
0118 
0119     return 0;
0120 }
0121 
0122 static void iforce_usb_stop_io(struct iforce *iforce)
0123 {
0124     struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb,
0125                              iforce);
0126 
0127     usb_kill_urb(iforce_usb->irq);
0128     usb_kill_urb(iforce_usb->out);
0129 }
0130 
0131 static const struct iforce_xport_ops iforce_usb_xport_ops = {
0132     .xmit       = iforce_usb_xmit,
0133     .get_id     = iforce_usb_get_id,
0134     .start_io   = iforce_usb_start_io,
0135     .stop_io    = iforce_usb_stop_io,
0136 };
0137 
0138 static void iforce_usb_irq(struct urb *urb)
0139 {
0140     struct iforce_usb *iforce_usb = urb->context;
0141     struct iforce *iforce = &iforce_usb->iforce;
0142     struct device *dev = &iforce_usb->intf->dev;
0143     int status;
0144 
0145     switch (urb->status) {
0146     case 0:
0147         /* success */
0148         break;
0149     case -ECONNRESET:
0150     case -ENOENT:
0151     case -ESHUTDOWN:
0152         /* this urb is terminated, clean up */
0153         dev_dbg(dev, "%s - urb shutting down with status: %d\n",
0154             __func__, urb->status);
0155         return;
0156     default:
0157         dev_dbg(dev, "%s - urb has status of: %d\n",
0158             __func__, urb->status);
0159         goto exit;
0160     }
0161 
0162     iforce_process_packet(iforce, iforce_usb->data_in[0],
0163                   iforce_usb->data_in + 1, urb->actual_length - 1);
0164 
0165 exit:
0166     status = usb_submit_urb(urb, GFP_ATOMIC);
0167     if (status)
0168         dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
0169             __func__, status);
0170 }
0171 
0172 static void iforce_usb_out(struct urb *urb)
0173 {
0174     struct iforce_usb *iforce_usb = urb->context;
0175     struct iforce *iforce = &iforce_usb->iforce;
0176 
0177     if (urb->status) {
0178         dev_dbg(&iforce_usb->intf->dev, "urb->status %d, exiting\n",
0179             urb->status);
0180         iforce_clear_xmit_and_wake(iforce);
0181         return;
0182     }
0183 
0184     __iforce_usb_xmit(iforce);
0185 
0186     wake_up_all(&iforce->wait);
0187 }
0188 
0189 static int iforce_usb_probe(struct usb_interface *intf,
0190                 const struct usb_device_id *id)
0191 {
0192     struct usb_device *dev = interface_to_usbdev(intf);
0193     struct usb_host_interface *interface;
0194     struct usb_endpoint_descriptor *epirq, *epout;
0195     struct iforce_usb *iforce_usb;
0196     int err = -ENOMEM;
0197 
0198     interface = intf->cur_altsetting;
0199 
0200     if (interface->desc.bNumEndpoints < 2)
0201         return -ENODEV;
0202 
0203     epirq = &interface->endpoint[0].desc;
0204     if (!usb_endpoint_is_int_in(epirq))
0205         return -ENODEV;
0206 
0207     epout = &interface->endpoint[1].desc;
0208     if (!usb_endpoint_is_int_out(epout))
0209         return -ENODEV;
0210 
0211     iforce_usb = kzalloc(sizeof(*iforce_usb), GFP_KERNEL);
0212     if (!iforce_usb)
0213         goto fail;
0214 
0215     iforce_usb->irq = usb_alloc_urb(0, GFP_KERNEL);
0216     if (!iforce_usb->irq)
0217         goto fail;
0218 
0219     iforce_usb->out = usb_alloc_urb(0, GFP_KERNEL);
0220     if (!iforce_usb->out)
0221         goto fail;
0222 
0223     iforce_usb->iforce.xport_ops = &iforce_usb_xport_ops;
0224 
0225     iforce_usb->usbdev = dev;
0226     iforce_usb->intf = intf;
0227 
0228     usb_fill_int_urb(iforce_usb->irq, dev,
0229              usb_rcvintpipe(dev, epirq->bEndpointAddress),
0230              iforce_usb->data_in, sizeof(iforce_usb->data_in),
0231              iforce_usb_irq, iforce_usb, epirq->bInterval);
0232 
0233     usb_fill_int_urb(iforce_usb->out, dev,
0234              usb_sndintpipe(dev, epout->bEndpointAddress),
0235              iforce_usb->data_out, sizeof(iforce_usb->data_out),
0236              iforce_usb_out, iforce_usb, epout->bInterval);
0237 
0238     err = iforce_init_device(&intf->dev, BUS_USB, &iforce_usb->iforce);
0239     if (err)
0240         goto fail;
0241 
0242     usb_set_intfdata(intf, iforce_usb);
0243     return 0;
0244 
0245 fail:
0246     if (iforce_usb) {
0247         usb_free_urb(iforce_usb->irq);
0248         usb_free_urb(iforce_usb->out);
0249         kfree(iforce_usb);
0250     }
0251 
0252     return err;
0253 }
0254 
0255 static void iforce_usb_disconnect(struct usb_interface *intf)
0256 {
0257     struct iforce_usb *iforce_usb = usb_get_intfdata(intf);
0258 
0259     usb_set_intfdata(intf, NULL);
0260 
0261     input_unregister_device(iforce_usb->iforce.dev);
0262 
0263     usb_free_urb(iforce_usb->irq);
0264     usb_free_urb(iforce_usb->out);
0265 
0266     kfree(iforce_usb);
0267 }
0268 
0269 static const struct usb_device_id iforce_usb_ids[] = {
0270     { USB_DEVICE(0x044f, 0xa01c) },     /* Thrustmaster Motor Sport GT */
0271     { USB_DEVICE(0x046d, 0xc281) },     /* Logitech WingMan Force */
0272     { USB_DEVICE(0x046d, 0xc291) },     /* Logitech WingMan Formula Force */
0273     { USB_DEVICE(0x05ef, 0x020a) },     /* AVB Top Shot Pegasus */
0274     { USB_DEVICE(0x05ef, 0x8884) },     /* AVB Mag Turbo Force */
0275     { USB_DEVICE(0x05ef, 0x8888) },     /* AVB Top Shot FFB Racing Wheel */
0276     { USB_DEVICE(0x061c, 0xc0a4) },         /* ACT LABS Force RS */
0277     { USB_DEVICE(0x061c, 0xc084) },         /* ACT LABS Force RS */
0278     { USB_DEVICE(0x06a3, 0xff04) },     /* Saitek R440 Force Wheel */
0279     { USB_DEVICE(0x06f8, 0x0001) },     /* Guillemot Race Leader Force Feedback */
0280     { USB_DEVICE(0x06f8, 0x0003) },     /* Guillemot Jet Leader Force Feedback */
0281     { USB_DEVICE(0x06f8, 0x0004) },     /* Guillemot Force Feedback Racing Wheel */
0282     { USB_DEVICE(0x06f8, 0xa302) },     /* Guillemot Jet Leader 3D */
0283     { }                 /* Terminating entry */
0284 };
0285 
0286 MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
0287 
0288 struct usb_driver iforce_usb_driver = {
0289     .name =     "iforce",
0290     .probe =    iforce_usb_probe,
0291     .disconnect =   iforce_usb_disconnect,
0292     .id_table = iforce_usb_ids,
0293 };
0294 
0295 module_usb_driver(iforce_usb_driver);
0296 
0297 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
0298 MODULE_DESCRIPTION("USB I-Force joysticks and wheels driver");
0299 MODULE_LICENSE("GPL");