-----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