0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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;
0040 struct usb_device *udev;
0041
0042 struct urb *irq;
0043 unsigned char *data;
0044 dma_addr_t data_dma;
0045 unsigned int is_open:1;
0046 };
0047
0048
0049
0050
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 { }
0061 };
0062 MODULE_DEVICE_TABLE(usb, onetouch_usb_ids);
0063
0064 #undef UNUSUAL_DEV
0065
0066
0067
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 { }
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:
0098 break;
0099 case -ECONNRESET:
0100 case -ENOENT:
0101 case -ESHUTDOWN:
0102 return;
0103
0104 default:
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
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
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);