1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Support for the Maxtor OneTouch USB hard drive's button 4 * 5 * Current development and maintenance by: 6 * Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu> 7 * 8 * Initial work by: 9 * Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se> 10 * 11 * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann) 12 * 13 */ 14 #include <linux/kernel.h> 15 #include <linux/input.h> 16 #include <linux/slab.h> 17 #include <linux/module.h> 18 #include <linux/usb/input.h> 19 #include "usb.h" 20 #include "debug.h" 21 #include "scsiglue.h" 22 23 #define DRV_NAME "ums-onetouch" 24 25 MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver"); 26 MODULE_AUTHOR("Nick Sillik <n.sillik@temple.edu>"); 27 MODULE_LICENSE("GPL"); 28 MODULE_IMPORT_NS(USB_STORAGE); 29 30 #define ONETOUCH_PKT_LEN 0x02 31 #define ONETOUCH_BUTTON KEY_PROG1 32 33 static int onetouch_connect_input(struct us_data *ss); 34 static void onetouch_release_input(void *onetouch_); 35 36 struct usb_onetouch { 37 char name[128]; 38 char phys[64]; 39 struct input_dev *dev; /* input device interface */ 40 struct usb_device *udev; /* usb device */ 41 42 struct urb *irq; /* urb for interrupt in report */ 43 unsigned char *data; /* input data */ 44 dma_addr_t data_dma; 45 unsigned int is_open:1; 46 }; 47 48 49 /* 50 * The table of devices 51 */ 52 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ 53 vendorName, productName, useProtocol, useTransport, \ 54 initFunction, flags) \ 55 { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ 56 .driver_info = (flags) } 57 58 static struct usb_device_id onetouch_usb_ids[] = { 59 # include "unusual_onetouch.h" 60 { } /* Terminating entry */ 61 }; 62 MODULE_DEVICE_TABLE(usb, onetouch_usb_ids); 63 64 #undef UNUSUAL_DEV 65 66 /* 67 * The flags table 68 */ 69 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ 70 vendor_name, product_name, use_protocol, use_transport, \ 71 init_function, Flags) \ 72 { \ 73 .vendorName = vendor_name, \ 74 .productName = product_name, \ 75 .useProtocol = use_protocol, \ 76 .useTransport = use_transport, \ 77 .initFunction = init_function, \ 78 } 79 80 static struct us_unusual_dev onetouch_unusual_dev_list[] = { 81 # include "unusual_onetouch.h" 82 { } /* Terminating entry */ 83 }; 84 85 #undef UNUSUAL_DEV 86 87 88 static void usb_onetouch_irq(struct urb *urb) 89 { 90 struct usb_onetouch *onetouch = urb->context; 91 signed char *data = onetouch->data; 92 struct input_dev *dev = onetouch->dev; 93 int status = urb->status; 94 int retval; 95 96 switch (status) { 97 case 0: /* success */ 98 break; 99 case -ECONNRESET: /* unlink */ 100 case -ENOENT: 101 case -ESHUTDOWN: 102 return; 103 /* -EPIPE: should clear the halt */ 104 default: /* error */ 105 goto resubmit; 106 } 107 108 input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02); 109 input_sync(dev); 110 111 resubmit: 112 retval = usb_submit_urb (urb, GFP_ATOMIC); 113 if (retval) 114 dev_err(&dev->dev, "can't resubmit intr, %s-%s/input0, " 115 "retval %d\n", onetouch->udev->bus->bus_name, 116 onetouch->udev->devpath, retval); 117 } 118 119 static int usb_onetouch_open(struct input_dev *dev) 120 { 121 struct usb_onetouch *onetouch = input_get_drvdata(dev); 122 123 onetouch->is_open = 1; 124 onetouch->irq->dev = onetouch->udev; 125 if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) { 126 dev_err(&dev->dev, "usb_submit_urb failed\n"); 127 return -EIO; 128 } 129 130 return 0; 131 } 132 133 static void usb_onetouch_close(struct input_dev *dev) 134 { 135 struct usb_onetouch *onetouch = input_get_drvdata(dev); 136 137 usb_kill_urb(onetouch->irq); 138 onetouch->is_open = 0; 139 } 140 141 #ifdef CONFIG_PM 142 static void usb_onetouch_pm_hook(struct us_data *us, int action) 143 { 144 struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra; 145 146 if (onetouch->is_open) { 147 switch (action) { 148 case US_SUSPEND: 149 usb_kill_urb(onetouch->irq); 150 break; 151 case US_RESUME: 152 if (usb_submit_urb(onetouch->irq, GFP_NOIO) != 0) 153 dev_err(&onetouch->irq->dev->dev, 154 "usb_submit_urb failed\n"); 155 break; 156 default: 157 break; 158 } 159 } 160 } 161 #endif /* CONFIG_PM */ 162 163 static int onetouch_connect_input(struct us_data *ss) 164 { 165 struct usb_device *udev = ss->pusb_dev; 166 struct usb_host_interface *interface; 167 struct usb_endpoint_descriptor *endpoint; 168 struct usb_onetouch *onetouch; 169 struct input_dev *input_dev; 170 int pipe, maxp; 171 int error = -ENOMEM; 172 173 interface = ss->pusb_intf->cur_altsetting; 174 175 if (interface->desc.bNumEndpoints != 3) 176 return -ENODEV; 177 178 endpoint = &interface->endpoint[2].desc; 179 if (!usb_endpoint_is_int_in(endpoint)) 180 return -ENODEV; 181 182 pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); 183 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); 184 maxp = min(maxp, ONETOUCH_PKT_LEN); 185 186 onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL); 187 input_dev = input_allocate_device(); 188 if (!onetouch || !input_dev) 189 goto fail1; 190 191 onetouch->data = usb_alloc_coherent(udev, ONETOUCH_PKT_LEN, 192 GFP_KERNEL, &onetouch->data_dma); 193 if (!onetouch->data) 194 goto fail1; 195 196 onetouch->irq = usb_alloc_urb(0, GFP_KERNEL); 197 if (!onetouch->irq) 198 goto fail2; 199 200 onetouch->udev = udev; 201 onetouch->dev = input_dev; 202 203 if (udev->manufacturer) 204 strlcpy(onetouch->name, udev->manufacturer, 205 sizeof(onetouch->name)); 206 if (udev->product) { 207 if (udev->manufacturer) 208 strlcat(onetouch->name, " ", sizeof(onetouch->name)); 209 strlcat(onetouch->name, udev->product, sizeof(onetouch->name)); 210 } 211 212 if (!strlen(onetouch->name)) 213 snprintf(onetouch->name, sizeof(onetouch->name), 214 "Maxtor Onetouch %04x:%04x", 215 le16_to_cpu(udev->descriptor.idVendor), 216 le16_to_cpu(udev->descriptor.idProduct)); 217 218 usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys)); 219 strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys)); 220 221 input_dev->name = onetouch->name; 222 input_dev->phys = onetouch->phys; 223 usb_to_input_id(udev, &input_dev->id); 224 input_dev->dev.parent = &udev->dev; 225 226 set_bit(EV_KEY, input_dev->evbit); 227 set_bit(ONETOUCH_BUTTON, input_dev->keybit); 228 clear_bit(0, input_dev->keybit); 229 230 input_set_drvdata(input_dev, onetouch); 231 232 input_dev->open = usb_onetouch_open; 233 input_dev->close = usb_onetouch_close; 234 235 usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, maxp, 236 usb_onetouch_irq, onetouch, endpoint->bInterval); 237 onetouch->irq->transfer_dma = onetouch->data_dma; 238 onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 239 240 ss->extra_destructor = onetouch_release_input; 241 ss->extra = onetouch; 242 #ifdef CONFIG_PM 243 ss->suspend_resume_hook = usb_onetouch_pm_hook; 244 #endif 245 246 error = input_register_device(onetouch->dev); 247 if (error) 248 goto fail3; 249 250 return 0; 251 252 fail3: usb_free_urb(onetouch->irq); 253 fail2: usb_free_coherent(udev, ONETOUCH_PKT_LEN, 254 onetouch->data, onetouch->data_dma); 255 fail1: kfree(onetouch); 256 input_free_device(input_dev); 257 return error; 258 } 259 260 static void onetouch_release_input(void *onetouch_) 261 { 262 struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_; 263 264 if (onetouch) { 265 usb_kill_urb(onetouch->irq); 266 input_unregister_device(onetouch->dev); 267 usb_free_urb(onetouch->irq); 268 usb_free_coherent(onetouch->udev, ONETOUCH_PKT_LEN, 269 onetouch->data, onetouch->data_dma); 270 } 271 } 272 273 static struct scsi_host_template onetouch_host_template; 274 275 static int onetouch_probe(struct usb_interface *intf, 276 const struct usb_device_id *id) 277 { 278 struct us_data *us; 279 int result; 280 281 result = usb_stor_probe1(&us, intf, id, 282 (id - onetouch_usb_ids) + onetouch_unusual_dev_list, 283 &onetouch_host_template); 284 if (result) 285 return result; 286 287 /* Use default transport and protocol */ 288 289 result = usb_stor_probe2(us); 290 return result; 291 } 292 293 static struct usb_driver onetouch_driver = { 294 .name = DRV_NAME, 295 .probe = onetouch_probe, 296 .disconnect = usb_stor_disconnect, 297 .suspend = usb_stor_suspend, 298 .resume = usb_stor_resume, 299 .reset_resume = usb_stor_reset_resume, 300 .pre_reset = usb_stor_pre_reset, 301 .post_reset = usb_stor_post_reset, 302 .id_table = onetouch_usb_ids, 303 .soft_unbind = 1, 304 .no_dynamic_id = 1, 305 }; 306 307 module_usb_stor_driver(onetouch_driver, onetouch_host_template, DRV_NAME); 308