You may want to take a look at the attached e-mail I got a while back... it's a hack to connect the onetouch button to the input subsystem as an extension of the usb-storage driver.
It's old, and likely suffering from bitrot, but should be useful to somebody. Matt On Wed, Jan 26, 2005 at 04:15:06PM -0500, Nick Sillik wrote: > Linux USB-Gurus > > I am writing in search of a little help on a kernel module/patch to add > functionality to the Maxtor OneTouch[1] external hard drive's user > programmable button. It will consist of two parts. The first will be a > kernel module or patch (although right now it is looking more like a > patch, unfortunately) > > I've run into a few roadblocks so far. The largest of which is the fact > that the device is already handled by an existing kernel module, namely > usb_storage. This presents a large problem, as I /also/ need access to > the device. I have already checked that the disk is only recognized as a > single device on the usb bus. My lsusb -v ouput is pasted below[2] > > If anyone has any ideas on my next step, other drivers to look at, etc. > the help would be greatly appreciated. Thanks in advance. (References > are below. > > Nick Sillik > [EMAIL PROTECTED] > > [1] > http://www.maxtor.com/portal/site/Maxtor/menuitem.6adb6b8313633595062e6be791346068/?channelpath=/en_us/Products/External%20Hard%20Drives/OneTouch%20Family > > [2] > Bus 003 Device 003: ID 0d49:7010 Maxtor > Device Descriptor: > bLength 18 > bDescriptorType 1 > bcdUSB 2.00 > bDeviceClass 0 (Defined at Interface level) > bDeviceSubClass 0 > bDeviceProtocol 0 > bMaxPacketSize0 64 > idVendor 0x0d49 Maxtor > idProduct 0x7010 > bcdDevice 2.00 > iManufacturer 1 > iProduct 3 > iSerial 2 > bNumConfigurations 1 > Configuration Descriptor: > bLength 9 > bDescriptorType 2 > wTotalLength 39 > bNumInterfaces 1 > bConfigurationValue 1 > iConfiguration 0 > bmAttributes 0xc0 > Self Powered > MaxPower 0mA > Interface Descriptor: > bLength 9 > bDescriptorType 4 > bInterfaceNumber 0 > bAlternateSetting 0 > bNumEndpoints 3 > bInterfaceClass 8 Mass Storage > bInterfaceSubClass 6 SCSI > bInterfaceProtocol 80 Bulk (Zip) > iInterface 0 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x02 EP 2 OUT > bmAttributes 2 > Transfer Type Bulk > Synch Type None > Usage Type Data > wMaxPacketSize 0x0200 1x 512 bytes > bInterval 0 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x88 EP 8 IN > bmAttributes 2 > Transfer Type Bulk > Synch Type None > Usage Type Data > wMaxPacketSize 0x0200 1x 512 bytes > bInterval 0 > ********I was told that this part was worth looking at******** > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x81 EP 1 IN > bmAttributes 3 > Transfer Type Interrupt > Synch Type None > Usage Type Data > wMaxPacketSize 0x0002 1x 2 bytes > bInterval 9 > ************************************************************** > Bus 003 Device 002: ID 04f9:0021 Brother Industries, Ltd > Device Descriptor: > bLength 18 > bDescriptorType 1 > bcdUSB 2.00 > bDeviceClass 0 (Defined at Interface level) > bDeviceSubClass 0 > bDeviceProtocol 0 > bMaxPacketSize0 64 > idVendor 0x04f9 Brother Industries, Ltd > idProduct 0x0021 > bcdDevice 1.00 > iManufacturer 1 > iProduct 2 > iSerial 3 > bNumConfigurations 1 > Configuration Descriptor: > bLength 9 > bDescriptorType 2 > wTotalLength 32 > bNumInterfaces 1 > bConfigurationValue 1 > iConfiguration 0 > bmAttributes 0xc0 > Self Powered > MaxPower 2mA > Interface Descriptor: > bLength 9 > bDescriptorType 4 > bInterfaceNumber 0 > bAlternateSetting 0 > bNumEndpoints 2 > bInterfaceClass 7 Printer > bInterfaceSubClass 1 Printer > bInterfaceProtocol 2 Bidirectional > iInterface 0 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x01 EP 1 OUT > bmAttributes 2 > Transfer Type Bulk > Synch Type None > Usage Type Data > wMaxPacketSize 0x0200 1x 512 bytes > bInterval 1 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x82 EP 2 IN > bmAttributes 2 > Transfer Type Bulk > Synch Type None > Usage Type Data > wMaxPacketSize 0x0200 1x 512 bytes > bInterval 1 > > Bus 003 Device 001: ID 0000:0000 > Device Descriptor: > bLength 18 > bDescriptorType 1 > bcdUSB 2.00 > bDeviceClass 9 Hub > bDeviceSubClass 0 Unused > bDeviceProtocol 1 Single TT > bMaxPacketSize0 8 > idVendor 0x0000 > idProduct 0x0000 > bcdDevice 2.06 > iManufacturer 3 > iProduct 2 > iSerial 1 > bNumConfigurations 1 > Configuration Descriptor: > bLength 9 > bDescriptorType 2 > wTotalLength 25 > bNumInterfaces 1 > bConfigurationValue 1 > iConfiguration 0 > bmAttributes 0xe0 > Self Powered > Remote Wakeup > MaxPower 0mA > Interface Descriptor: > bLength 9 > bDescriptorType 4 > bInterfaceNumber 0 > bAlternateSetting 0 > bNumEndpoints 1 > bInterfaceClass 9 Hub > bInterfaceSubClass 0 Unused > bInterfaceProtocol 0 > iInterface 0 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x81 EP 1 IN > bmAttributes 3 > Transfer Type Interrupt > Synch Type None > Usage Type Data > wMaxPacketSize 0x0002 1x 2 bytes > bInterval 12 > can't get hub descriptor: Operation not permitted > > Bus 002 Device 002: ID 045e:0040 Microsoft Corp. Wheel Mouse Optical > Device Descriptor: > bLength 18 > bDescriptorType 1 > bcdUSB 1.10 > bDeviceClass 0 (Defined at Interface level) > bDeviceSubClass 0 > bDeviceProtocol 0 > bMaxPacketSize0 8 > idVendor 0x045e Microsoft Corp. > idProduct 0x0040 Wheel Mouse Optical > bcdDevice 3.00 > iManufacturer 1 > iProduct 3 > iSerial 0 > bNumConfigurations 1 > Configuration Descriptor: > bLength 9 > bDescriptorType 2 > wTotalLength 34 > bNumInterfaces 1 > bConfigurationValue 1 > iConfiguration 0 > bmAttributes 0xa0 > Remote Wakeup > MaxPower 100mA > Interface Descriptor: > bLength 9 > bDescriptorType 4 > bInterfaceNumber 0 > bAlternateSetting 0 > bNumEndpoints 1 > bInterfaceClass 3 Human Interface Devices > bInterfaceSubClass 1 Boot Interface Subclass > bInterfaceProtocol 2 Mouse > iInterface 0 > HID Device Descriptor: > bLength 9 > bDescriptorType 33 > bcdHID 1.10 > bCountryCode 0 Not supported > bNumDescriptors 1 > bDescriptorType 34 Report > wDescriptorLength 72 > Report Descriptors: > ** UNAVAILABLE ** > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x81 EP 1 IN > bmAttributes 3 > Transfer Type Interrupt > Synch Type None > Usage Type Data > wMaxPacketSize 0x0004 1x 4 bytes > bInterval 10 > > Bus 002 Device 001: ID 0000:0000 > Device Descriptor: > bLength 18 > bDescriptorType 1 > bcdUSB 1.10 > bDeviceClass 9 Hub > bDeviceSubClass 0 Unused > bDeviceProtocol 0 > bMaxPacketSize0 8 > idVendor 0x0000 > idProduct 0x0000 > bcdDevice 2.06 > iManufacturer 3 > iProduct 2 > iSerial 1 > bNumConfigurations 1 > Configuration Descriptor: > bLength 9 > bDescriptorType 2 > wTotalLength 25 > bNumInterfaces 1 > bConfigurationValue 1 > iConfiguration 0 > bmAttributes 0xe0 > Self Powered > Remote Wakeup > MaxPower 0mA > Interface Descriptor: > bLength 9 > bDescriptorType 4 > bInterfaceNumber 0 > bAlternateSetting 0 > bNumEndpoints 1 > bInterfaceClass 9 Hub > bInterfaceSubClass 0 Unused > bInterfaceProtocol 0 > iInterface 0 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x81 EP 1 IN > bmAttributes 3 > Transfer Type Interrupt > Synch Type None > Usage Type Data > wMaxPacketSize 0x0002 1x 2 bytes > bInterval 255 > can't get hub descriptor: Operation not permitted > > Bus 001 Device 001: ID 0000:0000 > Device Descriptor: > bLength 18 > bDescriptorType 1 > bcdUSB 1.10 > bDeviceClass 9 Hub > bDeviceSubClass 0 Unused > bDeviceProtocol 0 > bMaxPacketSize0 8 > idVendor 0x0000 > idProduct 0x0000 > bcdDevice 2.06 > iManufacturer 3 > iProduct 2 > iSerial 1 > bNumConfigurations 1 > Configuration Descriptor: > bLength 9 > bDescriptorType 2 > wTotalLength 25 > bNumInterfaces 1 > bConfigurationValue 1 > iConfiguration 0 > bmAttributes 0xe0 > Self Powered > Remote Wakeup > MaxPower 0mA > Interface Descriptor: > bLength 9 > bDescriptorType 4 > bInterfaceNumber 0 > bAlternateSetting 0 > bNumEndpoints 1 > bInterfaceClass 9 Hub > bInterfaceSubClass 0 Unused > bInterfaceProtocol 0 > iInterface 0 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x81 EP 1 IN > bmAttributes 3 > Transfer Type Interrupt > Synch Type None > Usage Type Data > wMaxPacketSize 0x0002 1x 2 bytes > bInterval 255 > can't get hub descriptor: Operation not permitted -- Matthew Dharm Home: [EMAIL PROTECTED] Maintainer, Linux USB Mass Storage Driver What, are you one of those Microsoft-bashing Linux freaks? -- Customer to Greg User Friendly, 2/10/1999
From [EMAIL PROTECTED] Sat Nov 22 20:46:07 2003 Return-Path: <[EMAIL PROTECTED]> Received: from aun.it.uu.se (IDENT:[EMAIL PROTECTED] [130.238.12.36]) by ziggy.one-eyed-alien.net (8.11.6/8.11.6) with ESMTP id hAN4k6V20903 for <[EMAIL PROTECTED]>; Sat, 22 Nov 2003 20:46:07 -0800 Received: from hamberg.it.uu.se ([EMAIL PROTECTED] [130.238.9.198]) by aun.it.uu.se (8.12.10/8.12.10) with ESMTP id hAN4k4nU022724 for <[EMAIL PROTECTED]>; Sun, 23 Nov 2003 05:46:04 +0100 (MET) Received: from localhost ([EMAIL PROTECTED]) by hamberg.it.uu.se (8.12.10+Sun/8.12.10) with ESMTP id hAN4k3C7012664 for <[EMAIL PROTECTED]>; Sun, 23 Nov 2003 05:46:04 +0100 (MET) X-Authentication-Warning: hamberg.it.uu.se: erth7411 owned process doing -bs Date: Sun, 23 Nov 2003 05:46:03 +0100 (MET) From: Erik Thyren <[EMAIL PROTECTED]> X-X-Sender: [EMAIL PROTECTED] To: [EMAIL PROTECTED] Subject: Maxtor OneTouch USB hard drive Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from QUOTED-PRINTABLE to 8bit by ziggy.one-eyed-alien.net id hAN4k6V20903 X-Spam-Status: No, hits=-2.7 required=5.0 tests=FROM_ENDS_IN_NUMS,UNIFIED_PATCH,RCVD_IN_ORBZ version=2.11 X-Evolution: 0000016c-0000 X-Keywords: X-UID: 183 Status: RO X-Status: A Content-Length: 9602 Lines: 342 Hi I recently bought a Maxtor OneTouch USB hard drive and the mass storage driver made it work like a charm under linux. However, there is a button on the front of the OneTouch that can be used for simple tasks in Windows, such as backing up data from the regular hard drive to the OneTouch or basically launch any program you want. There was no support for this button in linux 2.6.0-test9. I wrote a small driver for the button which makes the button show up as a evdev device, and I also wrote a daemon which launches a script when the button is being pushed. This is practical for me cause I use the button to mount and unmount the drive. The daemon is very simple and is not included here. The driver has been tested with linux 2.6.0-test9. I haven't tested the driver with more than one OneTouch connected at a time, but a friend of mine is going to buy one soon, and when he does, I will be able to see if it works with more than one. Hopefully it will =) Some information about the hardware: The OneTouch has an interrupt endpoint and data is being sent on this endpoint when the button is being pressed and released. The driver just reads this data and generates events on the evdev device accordingly. The disk is a Maxtor OneTouch USB/Firewire 250GB Vendor id: 0x0d49. Vendor name: Maxtor. Product id: 0x7010. Product name: OneTouch. More information available at: http://www.maxtor.com/en/documentation/data_sheets/onetouch_data_sheet.pdf Thanks, Erik Appended is a a small patch for usb.c and Kconfig, generated with 'diff -urN' and the source of te driver. --- drivers/usb/storage/Kconfig.orig 2003-11-22 04:31:57.000000000 +0100 +++ drivers/usb/storage/Kconfig 2003-11-22 04:34:50.000000000 +0100 @@ -91,3 +91,10 @@ Say Y here to include additional code to support the Lexar Jumpshot USB CompactFlash reader. +config USB_STORAGE_ONETOUCH + bool "Maxtor OneTouch Hard Drive (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. + --- drivers/usb/storage/usb.c.orig 2003-11-22 04:31:23.000000000 +0100 +++ drivers/usb/storage/usb.c 2003-11-22 04:38:33.000000000 +0100 @@ -81,6 +81,12 @@ #ifdef CONFIG_USB_STORAGE_JUMPSHOT #include "jumpshot.h" #endif +#ifdef CONFIG_USB_STORAGE_ONETOUCH +#include "onetouch.h" +#else +static inline void onetouch_connect_input(struct us_data *ss) {} +static inline void onetouch_release_input(struct us_data *ss) {} +#endif #include <linux/module.h> @@ -949,7 +955,10 @@ result = get_pipes(us); if (result) goto BadDevice; - + + /* check for onetouch */ + onetouch_connect_input(us); + /* Acquire all the other resources */ result = usb_stor_acquire_resources(us); if (result) @@ -990,6 +999,9 @@ set_bit(US_FLIDX_DISCONNECTING, &us->flags); usb_stor_stop_transport(us); + /* check if onetouch */ + onetouch_release_input(us); + /* Dissociate from the USB device */ dissociate_dev(us); And here is the driver: drivers/usb/storage/onetouch.c /* * Support for the Maxtor OneTouch USB hard drive's button * * * Copyright (c) 2003 Erik Thyrén <[EMAIL PROTECTED]> * * 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/list.h> #include <linux/smp_lock.h> #include <linux/usb.h> #include "onetouch.h" #include "debug.h" 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; int open_count; /* reference count */ }; struct usb_onetouch_wrap { struct list_head list; struct usb_onetouch *onetouch; }; static LIST_HEAD(onetouch_list); static void onetouch_irq(struct urb *urb, struct pt_regs *regs) { struct usb_onetouch *onetouch = urb->context; int retval; switch (urb->status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto resubmit; } input_regs(&onetouch->dev, regs); //printk(KERN_INFO "input: %02x %02x\n", onetouch->data[0], onetouch->data[1]); input_report_key(&onetouch->dev, ONETOUCH_BUTTON, onetouch->data[0] & 0x02); input_sync(&onetouch->dev); resubmit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", __FUNCTION__, retval); } static int onetouch_open(struct input_dev *dev) { struct usb_onetouch *onetouch = dev->private; if (onetouch->open_count++) return 0; onetouch->irq->dev = onetouch->udev; if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) { onetouch->open_count--; return -EIO; } return 0; } static void onetouch_close(struct input_dev *dev) { struct usb_onetouch *onetouch = dev->private; if (!--onetouch->open_count) usb_unlink_urb(onetouch->irq); } void onetouch_connect_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; struct usb_onetouch_wrap *wrap; struct usb_onetouch *onetouch; char path[64]; if (udev->descriptor.idVendor != VENDOR_MAXTOR || udev->descriptor.idProduct != PRODUCT_ONETOUCH) { return; } US_DEBUGP("Connecting OneTouch device\n"); if ((onetouch = kmalloc (sizeof(struct usb_onetouch), GFP_KERNEL)) == NULL) { err("cannot allocate memory for new onetouch"); return; } memset(onetouch, 0, sizeof(struct usb_onetouch)); wrap = kmalloc (sizeof (struct usb_onetouch_wrap), GFP_KERNEL); if (!wrap) { err("cannot allocate memory for new onetouch wrapper"); kfree(onetouch); return; } onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN, SLAB_ATOMIC, &onetouch->data_dma); if (!onetouch->data) { kfree(onetouch); return; } onetouch->irq = usb_alloc_urb(0, GFP_KERNEL); if (!onetouch->irq) { err("cannot allocate memory for new onetouch interrupt urb"); usb_buffer_free(udev, ONETOUCH_PKT_LEN, onetouch->data, onetouch->data_dma); kfree(onetouch); return; } usb_fill_int_urb(onetouch->irq, udev, ss->recv_intr_pipe, onetouch->data, ONETOUCH_PKT_LEN, onetouch_irq, onetouch, ss->ep_bInterval); onetouch->irq->transfer_dma = onetouch->data_dma; onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; onetouch->udev = udev; onetouch->dev.id.bustype = BUS_USB; onetouch->dev.id.vendor = udev->descriptor.idVendor; onetouch->dev.id.product = udev->descriptor.idProduct; onetouch->dev.id.version = udev->descriptor.bcdDevice; onetouch->dev.private = onetouch; onetouch->dev.name = onetouch->name; onetouch->dev.phys = onetouch->phys; onetouch->dev.open = onetouch_open; onetouch->dev.close = onetouch_close; usb_make_path(udev, path, 64); snprintf(onetouch->phys, 64, "%s/input0", path); snprintf(onetouch->name, 128, "%s %s", ss->vendor, ss->product); if (!strlen(onetouch->name)) snprintf(onetouch->name, 128, "Maxtor OneTouch"); set_bit(EV_KEY, onetouch->dev.evbit); set_bit(ONETOUCH_BUTTON, onetouch->dev.keybit); clear_bit(0, onetouch->dev.keybit); input_register_device(&onetouch->dev); printk(KERN_INFO "input: %s on %s\n", onetouch->dev.name, path); wrap->onetouch = onetouch; list_add(&wrap->list, &onetouch_list); } void onetouch_release_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; struct usb_onetouch *onetouch; struct usb_onetouch_wrap *wrap; struct list_head *tmp1, *tmp2; if (udev->descriptor.idVendor != VENDOR_MAXTOR || udev->descriptor.idProduct != PRODUCT_ONETOUCH) { return; } US_DEBUGP("Trying to release OneTouch device..."); list_for_each_safe (tmp1, tmp2, &onetouch_list) { wrap = list_entry (tmp1, struct usb_onetouch_wrap, list); onetouch = wrap->onetouch; if (onetouch->udev == udev) { US_DEBUGP("device found: %s. Releasing\n", onetouch->phys); list_del (tmp1); usb_unlink_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); kfree(wrap); kfree(onetouch); } } } The header: drivers/usb/storage/onetouch.h #ifndef _ONETOUCH_H_ #define _ONETOUCH_H_ #include "usb.h" #include "linux/input.h" #define ONETOUCH_PKT_LEN 0x02 #define ONETOUCH_BUTTON KEY_PROG1 #define VENDOR_MAXTOR 0x0d49 #define PRODUCT_ONETOUCH 0x7010 void onetouch_connect_input(struct us_data *ss); void onetouch_release_input(struct us_data *ss); #endif
pgpT5EjfFdWUM.pgp
Description: PGP signature