Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Support for the Maxtor OneTouch USB hard drive's button
0004  *
0005  * Current development and maintenance by:
0006  *  Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu>
0007  *
0008  * Initial work by:
0009  *  Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se>
0010  *
0011  * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann)
0012  *
0013  */
0014 #include <linux/kernel.h>
0015 #include <linux/input.h>
0016 #include <linux/slab.h>
0017 #include <linux/module.h>
0018 #include <linux/usb/input.h>
0019 #include "usb.h"
0020 #include "debug.h"
0021 #include "scsiglue.h"
0022 
0023 #define DRV_NAME "ums-onetouch"
0024 
0025 MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver");
0026 MODULE_AUTHOR("Nick Sillik <n.sillik@temple.edu>");
0027 MODULE_LICENSE("GPL");
0028 MODULE_IMPORT_NS(USB_STORAGE);
0029 
0030 #define ONETOUCH_PKT_LEN        0x02
0031 #define ONETOUCH_BUTTON         KEY_PROG1
0032 
0033 static int onetouch_connect_input(struct us_data *ss);
0034 static void onetouch_release_input(void *onetouch_);
0035 
0036 struct usb_onetouch {
0037     char name[128];
0038     char phys[64];
0039     struct input_dev *dev;  /* input device interface */
0040     struct usb_device *udev;    /* usb device */
0041 
0042     struct urb *irq;    /* urb for interrupt in report */
0043     unsigned char *data;    /* input data */
0044     dma_addr_t data_dma;
0045     unsigned int is_open:1;
0046 };
0047 
0048 
0049 /*
0050  * The table of devices
0051  */
0052 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
0053             vendorName, productName, useProtocol, useTransport, \
0054             initFunction, flags) \
0055 { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
0056   .driver_info = (flags) }
0057 
0058 static struct usb_device_id onetouch_usb_ids[] = {
0059 #   include "unusual_onetouch.h"
0060     { }     /* Terminating entry */
0061 };
0062 MODULE_DEVICE_TABLE(usb, onetouch_usb_ids);
0063 
0064 #undef UNUSUAL_DEV
0065 
0066 /*
0067  * The flags table
0068  */
0069 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
0070             vendor_name, product_name, use_protocol, use_transport, \
0071             init_function, Flags) \
0072 { \
0073     .vendorName = vendor_name,  \
0074     .productName = product_name,    \
0075     .useProtocol = use_protocol,    \
0076     .useTransport = use_transport,  \
0077     .initFunction = init_function,  \
0078 }
0079 
0080 static struct us_unusual_dev onetouch_unusual_dev_list[] = {
0081 #   include "unusual_onetouch.h"
0082     { }     /* Terminating entry */
0083 };
0084 
0085 #undef UNUSUAL_DEV
0086 
0087 
0088 static void usb_onetouch_irq(struct urb *urb)
0089 {
0090     struct usb_onetouch *onetouch = urb->context;
0091     signed char *data = onetouch->data;
0092     struct input_dev *dev = onetouch->dev;
0093     int status = urb->status;
0094     int retval;
0095 
0096     switch (status) {
0097     case 0:         /* success */
0098         break;
0099     case -ECONNRESET:   /* unlink */
0100     case -ENOENT:
0101     case -ESHUTDOWN:
0102         return;
0103     /* -EPIPE:  should clear the halt */
0104     default:        /* error */
0105         goto resubmit;
0106     }
0107 
0108     input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02);
0109     input_sync(dev);
0110 
0111 resubmit:
0112     retval = usb_submit_urb (urb, GFP_ATOMIC);
0113     if (retval)
0114         dev_err(&dev->dev, "can't resubmit intr, %s-%s/input0, "
0115             "retval %d\n", onetouch->udev->bus->bus_name,
0116             onetouch->udev->devpath, retval);
0117 }
0118 
0119 static int usb_onetouch_open(struct input_dev *dev)
0120 {
0121     struct usb_onetouch *onetouch = input_get_drvdata(dev);
0122 
0123     onetouch->is_open = 1;
0124     onetouch->irq->dev = onetouch->udev;
0125     if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
0126         dev_err(&dev->dev, "usb_submit_urb failed\n");
0127         return -EIO;
0128     }
0129 
0130     return 0;
0131 }
0132 
0133 static void usb_onetouch_close(struct input_dev *dev)
0134 {
0135     struct usb_onetouch *onetouch = input_get_drvdata(dev);
0136 
0137     usb_kill_urb(onetouch->irq);
0138     onetouch->is_open = 0;
0139 }
0140 
0141 #ifdef CONFIG_PM
0142 static void usb_onetouch_pm_hook(struct us_data *us, int action)
0143 {
0144     struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra;
0145 
0146     if (onetouch->is_open) {
0147         switch (action) {
0148         case US_SUSPEND:
0149             usb_kill_urb(onetouch->irq);
0150             break;
0151         case US_RESUME:
0152             if (usb_submit_urb(onetouch->irq, GFP_NOIO) != 0)
0153                 dev_err(&onetouch->irq->dev->dev,
0154                     "usb_submit_urb failed\n");
0155             break;
0156         default:
0157             break;
0158         }
0159     }
0160 }
0161 #endif /* CONFIG_PM */
0162 
0163 static int onetouch_connect_input(struct us_data *ss)
0164 {
0165     struct usb_device *udev = ss->pusb_dev;
0166     struct usb_host_interface *interface;
0167     struct usb_endpoint_descriptor *endpoint;
0168     struct usb_onetouch *onetouch;
0169     struct input_dev *input_dev;
0170     int pipe, maxp;
0171     int error = -ENOMEM;
0172 
0173     interface = ss->pusb_intf->cur_altsetting;
0174 
0175     if (interface->desc.bNumEndpoints != 3)
0176         return -ENODEV;
0177 
0178     endpoint = &interface->endpoint[2].desc;
0179     if (!usb_endpoint_is_int_in(endpoint))
0180         return -ENODEV;
0181 
0182     pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
0183     maxp = usb_maxpacket(udev, pipe);
0184     maxp = min(maxp, ONETOUCH_PKT_LEN);
0185 
0186     onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
0187     input_dev = input_allocate_device();
0188     if (!onetouch || !input_dev)
0189         goto fail1;
0190 
0191     onetouch->data = usb_alloc_coherent(udev, ONETOUCH_PKT_LEN,
0192                         GFP_KERNEL, &onetouch->data_dma);
0193     if (!onetouch->data)
0194         goto fail1;
0195 
0196     onetouch->irq = usb_alloc_urb(0, GFP_KERNEL);
0197     if (!onetouch->irq)
0198         goto fail2;
0199 
0200     onetouch->udev = udev;
0201     onetouch->dev = input_dev;
0202 
0203     if (udev->manufacturer)
0204         strlcpy(onetouch->name, udev->manufacturer,
0205             sizeof(onetouch->name));
0206     if (udev->product) {
0207         if (udev->manufacturer)
0208             strlcat(onetouch->name, " ", sizeof(onetouch->name));
0209         strlcat(onetouch->name, udev->product, sizeof(onetouch->name));
0210     }
0211 
0212     if (!strlen(onetouch->name))
0213         snprintf(onetouch->name, sizeof(onetouch->name),
0214              "Maxtor Onetouch %04x:%04x",
0215              le16_to_cpu(udev->descriptor.idVendor),
0216              le16_to_cpu(udev->descriptor.idProduct));
0217 
0218     usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys));
0219     strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys));
0220 
0221     input_dev->name = onetouch->name;
0222     input_dev->phys = onetouch->phys;
0223     usb_to_input_id(udev, &input_dev->id);
0224     input_dev->dev.parent = &udev->dev;
0225 
0226     set_bit(EV_KEY, input_dev->evbit);
0227     set_bit(ONETOUCH_BUTTON, input_dev->keybit);
0228     clear_bit(0, input_dev->keybit);
0229 
0230     input_set_drvdata(input_dev, onetouch);
0231 
0232     input_dev->open = usb_onetouch_open;
0233     input_dev->close = usb_onetouch_close;
0234 
0235     usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, maxp,
0236              usb_onetouch_irq, onetouch, endpoint->bInterval);
0237     onetouch->irq->transfer_dma = onetouch->data_dma;
0238     onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
0239 
0240     ss->extra_destructor = onetouch_release_input;
0241     ss->extra = onetouch;
0242 #ifdef CONFIG_PM
0243     ss->suspend_resume_hook = usb_onetouch_pm_hook;
0244 #endif
0245 
0246     error = input_register_device(onetouch->dev);
0247     if (error)
0248         goto fail3;
0249 
0250     return 0;
0251 
0252  fail3: usb_free_urb(onetouch->irq);
0253  fail2: usb_free_coherent(udev, ONETOUCH_PKT_LEN,
0254               onetouch->data, onetouch->data_dma);
0255  fail1: kfree(onetouch);
0256     input_free_device(input_dev);
0257     return error;
0258 }
0259 
0260 static void onetouch_release_input(void *onetouch_)
0261 {
0262     struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_;
0263 
0264     if (onetouch) {
0265         usb_kill_urb(onetouch->irq);
0266         input_unregister_device(onetouch->dev);
0267         usb_free_urb(onetouch->irq);
0268         usb_free_coherent(onetouch->udev, ONETOUCH_PKT_LEN,
0269                   onetouch->data, onetouch->data_dma);
0270     }
0271 }
0272 
0273 static struct scsi_host_template onetouch_host_template;
0274 
0275 static int onetouch_probe(struct usb_interface *intf,
0276              const struct usb_device_id *id)
0277 {
0278     struct us_data *us;
0279     int result;
0280 
0281     result = usb_stor_probe1(&us, intf, id,
0282             (id - onetouch_usb_ids) + onetouch_unusual_dev_list,
0283             &onetouch_host_template);
0284     if (result)
0285         return result;
0286 
0287     /* Use default transport and protocol */
0288 
0289     result = usb_stor_probe2(us);
0290     return result;
0291 }
0292 
0293 static struct usb_driver onetouch_driver = {
0294     .name =     DRV_NAME,
0295     .probe =    onetouch_probe,
0296     .disconnect =   usb_stor_disconnect,
0297     .suspend =  usb_stor_suspend,
0298     .resume =   usb_stor_resume,
0299     .reset_resume = usb_stor_reset_resume,
0300     .pre_reset =    usb_stor_pre_reset,
0301     .post_reset =   usb_stor_post_reset,
0302     .id_table = onetouch_usb_ids,
0303     .soft_unbind =  1,
0304     .no_dynamic_id = 1,
0305 };
0306 
0307 module_usb_stor_driver(onetouch_driver, onetouch_host_template, DRV_NAME);