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

Reply via email to