aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/onetouch.c
diff options
context:
space:
mode:
authorMatthew Dharm <mdharm-usb@one-eyed-alien.net>2005-07-28 17:49:01 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 19:22:55 -0400
commit34008dbfe8c00eca67f97bad484eb5cb03bafe66 (patch)
tree72b7a8dc823dc1f1e77041025c7572499e65db64 /drivers/usb/storage/onetouch.c
parent26186ba77b493204ae0fadc3c88a67b14f22168f (diff)
[PATCH] USB Storage: add support for Maxtor One-Touch button
This patch is originally from Nick Sillik, and has been rediffed against the latest tree. This patch adds usability to the OneTouch Button on Maxtor External USB Hard Drives. Using an unusual device entry it declares an extra init function which claims the interrupt endpoint associated with this button. The button is connected to the input system. Signed-off-by: Nick Sillik <n.sillik@temple.edu> Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/storage/onetouch.c')
-rw-r--r--drivers/usb/storage/onetouch.c205
1 files changed, 205 insertions, 0 deletions
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 @@
1/*
2 * Support for the Maxtor OneTouch USB hard drive's button
3 *
4 * Current development and maintenance by:
5 * Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu>
6 *
7 * Initial work by:
8 * Copyright (c) 2003 Erik Thyrén <erth7411@student.uu.se>
9 *
10 * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann)
11 *
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 */
30
31#include <linux/config.h>
32#include <linux/kernel.h>
33#include <linux/input.h>
34#include <linux/init.h>
35#include <linux/slab.h>
36#include <linux/module.h>
37#include <linux/usb.h>
38#include "usb.h"
39#include "onetouch.h"
40#include "debug.h"
41
42void onetouch_release_input(void *onetouch_);
43
44struct usb_onetouch {
45 char name[128];
46 char phys[64];
47 struct input_dev dev; /* input device interface */
48 struct usb_device *udev; /* usb device */
49
50 struct urb *irq; /* urb for interrupt in report */
51 unsigned char *data; /* input data */
52 dma_addr_t data_dma;
53};
54
55static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
56{
57 struct usb_onetouch *onetouch = urb->context;
58 signed char *data = onetouch->data;
59 struct input_dev *dev = &onetouch->dev;
60 int status;
61
62 switch (urb->status) {
63 case 0: /* success */
64 break;
65 case -ECONNRESET: /* unlink */
66 case -ENOENT:
67 case -ESHUTDOWN:
68 return;
69 /* -EPIPE: should clear the halt */
70 default: /* error */
71 goto resubmit;
72 }
73
74 input_regs(dev, regs);
75
76 input_report_key(&onetouch->dev, ONETOUCH_BUTTON,
77 data[0] & 0x02);
78
79 input_sync(dev);
80resubmit:
81 status = usb_submit_urb (urb, SLAB_ATOMIC);
82 if (status)
83 err ("can't resubmit intr, %s-%s/input0, status %d",
84 onetouch->udev->bus->bus_name,
85 onetouch->udev->devpath, status);
86}
87
88static int usb_onetouch_open(struct input_dev *dev)
89{
90 struct usb_onetouch *onetouch = dev->private;
91
92 onetouch->irq->dev = onetouch->udev;
93 if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
94 err("usb_submit_urb failed");
95 return -EIO;
96 }
97
98 return 0;
99}
100
101static void usb_onetouch_close(struct input_dev *dev)
102{
103 struct usb_onetouch *onetouch = dev->private;
104
105 usb_kill_urb(onetouch->irq);
106}
107
108int onetouch_connect_input(struct us_data *ss)
109{
110 struct usb_device *udev = ss->pusb_dev;
111 struct usb_host_interface *interface;
112 struct usb_endpoint_descriptor *endpoint;
113 struct usb_onetouch *onetouch;
114 int pipe, maxp;
115 char path[64];
116
117 interface = ss->pusb_intf->cur_altsetting;
118
119 endpoint = &interface->endpoint[2].desc;
120 if(!(endpoint->bEndpointAddress & 0x80))
121 return -ENODEV;
122 if((endpoint->bmAttributes & 3) != 3)
123 return -ENODEV;
124
125 pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
126 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
127
128 if (!(onetouch = kcalloc(1, sizeof(struct usb_onetouch), GFP_KERNEL)))
129 return -ENOMEM;
130
131 onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN, SLAB_ATOMIC, &onetouch->data_dma);
132 if (!onetouch->data){
133 kfree(onetouch);
134 return -ENOMEM;
135 }
136
137 onetouch->irq = usb_alloc_urb(0, GFP_KERNEL);
138 if (!onetouch->irq){
139 kfree(onetouch);
140 usb_buffer_free(udev, ONETOUCH_PKT_LEN, onetouch->data, onetouch->data_dma);
141 return -ENODEV;
142 }
143
144
145 onetouch->udev = udev;
146
147 set_bit(EV_KEY, onetouch->dev.evbit);
148 set_bit(ONETOUCH_BUTTON, onetouch->dev.keybit);
149 clear_bit(0, onetouch->dev.keybit);
150
151 onetouch->dev.private = onetouch;
152 onetouch->dev.open = usb_onetouch_open;
153 onetouch->dev.close = usb_onetouch_close;
154
155 usb_make_path(udev, path, 64);
156 sprintf(onetouch->phys, "%s/input0", path);
157
158 onetouch->dev.name = onetouch->name;
159 onetouch->dev.phys = onetouch->phys;
160
161 onetouch->dev.id.bustype = BUS_USB;
162 onetouch->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor);
163 onetouch->dev.id.product = le16_to_cpu(udev->descriptor.idProduct);
164 onetouch->dev.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
165
166 onetouch->dev.dev = &udev->dev;
167
168 if (udev->manufacturer)
169 strcat(onetouch->name, udev->manufacturer);
170 if (udev->product)
171 sprintf(onetouch->name, "%s %s", onetouch->name,
172 udev->product);
173 if (!strlen(onetouch->name))
174 sprintf(onetouch->name, "Maxtor Onetouch %04x:%04x",
175 onetouch->dev.id.vendor, onetouch->dev.id.product);
176
177 usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
178 (maxp > 8 ? 8 : maxp),
179 usb_onetouch_irq, onetouch, endpoint->bInterval);
180 onetouch->irq->transfer_dma = onetouch->data_dma;
181 onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
182
183 ss->extra_destructor = onetouch_release_input;
184 ss->extra = onetouch;
185
186 input_register_device(&onetouch->dev);
187 printk(KERN_INFO "usb-input: %s on %s\n", onetouch->dev.name, path);
188
189 return 0;
190}
191
192void onetouch_release_input(void *onetouch_)
193{
194 struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_;
195
196 if (onetouch) {
197 usb_kill_urb(onetouch->irq);
198 input_unregister_device(&onetouch->dev);
199 usb_free_urb(onetouch->irq);
200 usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN,
201 onetouch->data, onetouch->data_dma);
202 printk(KERN_INFO "Maxtor Onetouch %04x:%04x Deregistered\n",
203 onetouch->dev.id.vendor, onetouch->dev.id.product);
204 }
205}