-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I made all of the changes you (Alan, Matt, Greg) talked about. I'll send you the code to make sure I got everything.
And here is what I've added to unusual_devs.h: #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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) iD8DBQFCP5GH2hKwjhIv2aMRAuGBAKCXgMVWnLnChDCHjK6gnWZHuoYYsACcCYc0 ivUjGZ2FLARwHiI4qWJpvCc= =Y96d -----END PGP SIGNATURE-----
/* * Support for the Maxtor OneTouch USB hard drive's button * * Current development and maintenance by: * Copyright (c) 2005 Nick Sillik <[EMAIL PROTECTED]> * * Initial work by: * 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/spinlock.h> #include <linux/usb.h> #include "onetouch.h" #include "debug.h" spinlock_t onetouch_list_lock = SPIN_LOCK_UNLOCKED; 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 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_kill_urb(onetouch->irq); } int onetouch_connect_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; struct usb_onetouch *onetouch; char path[64]; if (udev->descriptor.idVendor != VENDOR_MAXTOR || udev->descriptor.idProduct != PRODUCT_ONETOUCH) { /* Not a onetouch device, nothing to see here */ return 1; } US_DEBUGP("Connecting OneTouch device\n"); onetouch = kmalloc(sizeof(struct usb_onetouch), GFP_KERNEL); if (onetouch == NULL) { err("cannot allocate memory for new onetouch"); return 1; } memset(onetouch, 0, sizeof(struct usb_onetouch)); onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN, SLAB_ATOMIC, &onetouch->data_dma); if (!onetouch->data) { kfree(onetouch); return 1; } 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 1; } ss->extra_destructor = onetouch_release_input; ss->extra = ss; 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); spin_lock(&onetouch_list_lock); list_add(&onetouch->list, &onetouch_list); spin_unlock(&onetouch_list_lock); return 0; } void onetouch_release_input(void *ss_) { struct us_data *ss = (struct us_data *) ss_; struct usb_device *udev = ss->pusb_dev; struct usb_onetouch *onetouch; struct usb_onetouch *entry; if (udev->descriptor.idVendor != VENDOR_MAXTOR || udev->descriptor.idProduct != PRODUCT_ONETOUCH) { /* Not a onetouch device, nothing to see here */ return; } US_DEBUGP("Trying to release OneTouch device..."); onetouch = NULL; spin_lock(&onetouch_list_lock); list_for_each_entry(entry, &onetouch_list, list) { if (entry->udev == udev) { onetouch = entry; list_del(&onetouch->list); break; } } spin_unlock(&onetouch_list_lock); if (onetouch) { US_DEBUGP("device found: %s. Releasing\n", onetouch->phys); 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(onetouch); } return; }
#ifndef _ONETOUCH_H_ #define _ONETOUCH_H_ #include <linux/config.h> #include <linux/input.h> #include "usb.h" #define ONETOUCH_PKT_LEN 0x02 #define ONETOUCH_BUTTON KEY_PROG1 #define VENDOR_MAXTOR 0x0d49 #define PRODUCT_ONETOUCH 0x7010 int onetouch_connect_input(struct us_data *ss); void onetouch_release_input(void *ss_); #endif