diff options
-rw-r--r-- | drivers/usb/storage/Kconfig | 12 | ||||
-rw-r--r-- | drivers/usb/storage/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/storage/onetouch.c | 205 | ||||
-rw-r--r-- | drivers/usb/storage/onetouch.h | 9 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_devs.h | 12 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 4 |
6 files changed, 242 insertions, 1 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index f1f1c0608c22..bb9819cc8826 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -111,3 +111,15 @@ config USB_STORAGE_JUMPSHOT Say Y here to include additional code to support the Lexar Jumpshot USB CompactFlash reader. + +config USB_STORAGE_ONETOUCH + bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)" + depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL + help + Say Y here to include additional code to support the Maxtor OneTouch + USB hard drive's onetouch button. + + This code registers the button on the front of Maxtor OneTouch USB + hard drive's as an input device. An action can be associated with + this input in any keybinding software. (e.g. gnome's keyboard short- + cuts) diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 56652ccc2881..44ab8f9978fe 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -18,6 +18,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o +usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o $(usb-storage-obj-y) diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c new file mode 100644 index 000000000000..07fd29ceb347 --- /dev/null +++ b/drivers/usb/storage/onetouch.c @@ -0,0 +1,205 @@ +/* + * Support for the Maxtor OneTouch USB hard drive's button + * + * Current development and maintenance by: + * Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu> + * + * Initial work by: + * Copyright (c) 2003 Erik Thyrén <erth7411@student.uu.se> + * + * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann) + * + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/input.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/usb.h> +#include "usb.h" +#include "onetouch.h" +#include "debug.h" + +void onetouch_release_input(void *onetouch_); + +struct usb_onetouch { + char name[128]; + char phys[64]; + struct input_dev dev; /* input device interface */ + struct usb_device *udev; /* usb device */ + + struct urb *irq; /* urb for interrupt in report */ + unsigned char *data; /* input data */ + dma_addr_t data_dma; +}; + +static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs) +{ + struct usb_onetouch *onetouch = urb->context; + signed char *data = onetouch->data; + struct input_dev *dev = &onetouch->dev; + int status; + + switch (urb->status) { + case 0: /* success */ + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + return; + /* -EPIPE: should clear the halt */ + default: /* error */ + goto resubmit; + } + + input_regs(dev, regs); + + input_report_key(&onetouch->dev, ONETOUCH_BUTTON, + data[0] & 0x02); + + input_sync(dev); +resubmit: + status = usb_submit_urb (urb, SLAB_ATOMIC); + if (status) + err ("can't resubmit intr, %s-%s/input0, status %d", + onetouch->udev->bus->bus_name, + onetouch->udev->devpath, status); +} + +static int usb_onetouch_open(struct input_dev *dev) +{ + struct usb_onetouch *onetouch = dev->private; + + onetouch->irq->dev = onetouch->udev; + if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) { + err("usb_submit_urb failed"); + return -EIO; + } + + return 0; +} + +static void usb_onetouch_close(struct input_dev *dev) +{ + struct usb_onetouch *onetouch = dev->private; + + usb_kill_urb(onetouch->irq); +} + +int onetouch_connect_input(struct us_data *ss) +{ + struct usb_device *udev = ss->pusb_dev; + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_onetouch *onetouch; + int pipe, maxp; + char path[64]; + + interface = ss->pusb_intf->cur_altsetting; + + endpoint = &interface->endpoint[2].desc; + if(!(endpoint->bEndpointAddress & 0x80)) + return -ENODEV; + if((endpoint->bmAttributes & 3) != 3) + return -ENODEV; + + pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + + if (!(onetouch = kcalloc(1, sizeof(struct usb_onetouch), GFP_KERNEL))) + return -ENOMEM; + + onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN, SLAB_ATOMIC, &onetouch->data_dma); + if (!onetouch->data){ + kfree(onetouch); + return -ENOMEM; + } + + onetouch->irq = usb_alloc_urb(0, GFP_KERNEL); + if (!onetouch->irq){ + kfree(onetouch); + usb_buffer_free(udev, ONETOUCH_PKT_LEN, onetouch->data, onetouch->data_dma); + return -ENODEV; + } + + + onetouch->udev = udev; + + set_bit(EV_KEY, onetouch->dev.evbit); + set_bit(ONETOUCH_BUTTON, onetouch->dev.keybit); + clear_bit(0, onetouch->dev.keybit); + + onetouch->dev.private = onetouch; + onetouch->dev.open = usb_onetouch_open; + onetouch->dev.close = usb_onetouch_close; + + usb_make_path(udev, path, 64); + sprintf(onetouch->phys, "%s/input0", path); + + onetouch->dev.name = onetouch->name; + onetouch->dev.phys = onetouch->phys; + + onetouch->dev.id.bustype = BUS_USB; + onetouch->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); + onetouch->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); + onetouch->dev.id.version = le16_to_cpu(udev->descriptor.bcdDevice); + + onetouch->dev.dev = &udev->dev; + + if (udev->manufacturer) + strcat(onetouch->name, udev->manufacturer); + if (udev->product) + sprintf(onetouch->name, "%s %s", onetouch->name, + udev->product); + if (!strlen(onetouch->name)) + sprintf(onetouch->name, "Maxtor Onetouch %04x:%04x", + onetouch->dev.id.vendor, onetouch->dev.id.product); + + usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, + (maxp > 8 ? 8 : maxp), + usb_onetouch_irq, onetouch, endpoint->bInterval); + onetouch->irq->transfer_dma = onetouch->data_dma; + onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + ss->extra_destructor = onetouch_release_input; + ss->extra = onetouch; + + input_register_device(&onetouch->dev); + printk(KERN_INFO "usb-input: %s on %s\n", onetouch->dev.name, path); + + return 0; +} + +void onetouch_release_input(void *onetouch_) +{ + struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_; + + if (onetouch) { + usb_kill_urb(onetouch->irq); + input_unregister_device(&onetouch->dev); + usb_free_urb(onetouch->irq); + usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN, + onetouch->data, onetouch->data_dma); + printk(KERN_INFO "Maxtor Onetouch %04x:%04x Deregistered\n", + onetouch->dev.id.vendor, onetouch->dev.id.product); + } +} diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h new file mode 100644 index 000000000000..41c7aa8f0446 --- /dev/null +++ b/drivers/usb/storage/onetouch.h @@ -0,0 +1,9 @@ +#ifndef _ONETOUCH_H_ +#define _ONETOUCH_H_ + +#define ONETOUCH_PKT_LEN 0x02 +#define ONETOUCH_BUTTON KEY_PROG1 + +int onetouch_connect_input(struct us_data *ss); + +#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index e7ed8351f6ea..ad0cfd7a782f 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -936,6 +936,18 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, US_FL_SINGLE_LUN ), #endif +/* Submitted by: Nick Sillik <n.sillik@temple.edu> + * Needed for OneTouch extension to usb-storage + * + */ +#ifdef CONFIG_USB_STORAGE_ONETOUCH + UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, + "Maxtor", + "OneTouch External Harddrive", + US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + 0), +#endif + /* Submitted by Joris Struyve <joris@struyve.be> */ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, "Medion", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 97b9ebb8a082..cb4c770baf32 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -90,7 +90,9 @@ #ifdef CONFIG_USB_STORAGE_JUMPSHOT #include "jumpshot.h" #endif - +#ifdef CONFIG_USB_STORAGE_ONETOUCH +#include "onetouch.h" +#endif /* Some informational data */ MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); |