Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/tablet/acecad.c
15111 views
1
/*
2
* Copyright (c) 2001-2005 Edouard TISSERANT <[email protected]>
3
* Copyright (c) 2004-2005 Stephane VOLTZ <[email protected]>
4
*
5
* USB Acecad "Acecad Flair" tablet support
6
*
7
* Changelog:
8
* v3.2 - Added sysfs support
9
*/
10
11
/*
12
* This program is free software; you can redistribute it and/or modify
13
* it under the terms of the GNU General Public License as published by
14
* the Free Software Foundation; either version 2 of the License, or
15
* (at your option) any later version.
16
*
17
* This program is distributed in the hope that it will be useful,
18
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
* GNU General Public License for more details.
21
*
22
* You should have received a copy of the GNU General Public License
23
* along with this program; if not, write to the Free Software
24
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
*
26
*/
27
28
#include <linux/kernel.h>
29
#include <linux/slab.h>
30
#include <linux/module.h>
31
#include <linux/init.h>
32
#include <linux/usb/input.h>
33
34
/*
35
* Version Information
36
*/
37
#define DRIVER_VERSION "v3.2"
38
#define DRIVER_DESC "USB Acecad Flair tablet driver"
39
#define DRIVER_LICENSE "GPL"
40
#define DRIVER_AUTHOR "Edouard TISSERANT <[email protected]>"
41
42
MODULE_AUTHOR(DRIVER_AUTHOR);
43
MODULE_DESCRIPTION(DRIVER_DESC);
44
MODULE_LICENSE(DRIVER_LICENSE);
45
46
#define USB_VENDOR_ID_ACECAD 0x0460
47
#define USB_DEVICE_ID_FLAIR 0x0004
48
#define USB_DEVICE_ID_302 0x0008
49
50
struct usb_acecad {
51
char name[128];
52
char phys[64];
53
struct usb_device *usbdev;
54
struct input_dev *input;
55
struct urb *irq;
56
57
unsigned char *data;
58
dma_addr_t data_dma;
59
};
60
61
static void usb_acecad_irq(struct urb *urb)
62
{
63
struct usb_acecad *acecad = urb->context;
64
unsigned char *data = acecad->data;
65
struct input_dev *dev = acecad->input;
66
int prox, status;
67
68
switch (urb->status) {
69
case 0:
70
/* success */
71
break;
72
case -ECONNRESET:
73
case -ENOENT:
74
case -ESHUTDOWN:
75
/* this urb is terminated, clean up */
76
dbg("%s - urb shutting down with status: %d", __func__, urb->status);
77
return;
78
default:
79
dbg("%s - nonzero urb status received: %d", __func__, urb->status);
80
goto resubmit;
81
}
82
83
prox = (data[0] & 0x04) >> 2;
84
input_report_key(dev, BTN_TOOL_PEN, prox);
85
86
if (prox) {
87
int x = data[1] | (data[2] << 8);
88
int y = data[3] | (data[4] << 8);
89
/* Pressure should compute the same way for flair and 302 */
90
int pressure = data[5] | (data[6] << 8);
91
int touch = data[0] & 0x01;
92
int stylus = (data[0] & 0x10) >> 4;
93
int stylus2 = (data[0] & 0x20) >> 5;
94
input_report_abs(dev, ABS_X, x);
95
input_report_abs(dev, ABS_Y, y);
96
input_report_abs(dev, ABS_PRESSURE, pressure);
97
input_report_key(dev, BTN_TOUCH, touch);
98
input_report_key(dev, BTN_STYLUS, stylus);
99
input_report_key(dev, BTN_STYLUS2, stylus2);
100
}
101
102
/* event termination */
103
input_sync(dev);
104
105
resubmit:
106
status = usb_submit_urb(urb, GFP_ATOMIC);
107
if (status)
108
err("can't resubmit intr, %s-%s/input0, status %d",
109
acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status);
110
}
111
112
static int usb_acecad_open(struct input_dev *dev)
113
{
114
struct usb_acecad *acecad = input_get_drvdata(dev);
115
116
acecad->irq->dev = acecad->usbdev;
117
if (usb_submit_urb(acecad->irq, GFP_KERNEL))
118
return -EIO;
119
120
return 0;
121
}
122
123
static void usb_acecad_close(struct input_dev *dev)
124
{
125
struct usb_acecad *acecad = input_get_drvdata(dev);
126
127
usb_kill_urb(acecad->irq);
128
}
129
130
static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id)
131
{
132
struct usb_device *dev = interface_to_usbdev(intf);
133
struct usb_host_interface *interface = intf->cur_altsetting;
134
struct usb_endpoint_descriptor *endpoint;
135
struct usb_acecad *acecad;
136
struct input_dev *input_dev;
137
int pipe, maxp;
138
int err;
139
140
if (interface->desc.bNumEndpoints != 1)
141
return -ENODEV;
142
143
endpoint = &interface->endpoint[0].desc;
144
145
if (!usb_endpoint_is_int_in(endpoint))
146
return -ENODEV;
147
148
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
149
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
150
151
acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
152
input_dev = input_allocate_device();
153
if (!acecad || !input_dev) {
154
err = -ENOMEM;
155
goto fail1;
156
}
157
158
acecad->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &acecad->data_dma);
159
if (!acecad->data) {
160
err= -ENOMEM;
161
goto fail1;
162
}
163
164
acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
165
if (!acecad->irq) {
166
err = -ENOMEM;
167
goto fail2;
168
}
169
170
acecad->usbdev = dev;
171
acecad->input = input_dev;
172
173
if (dev->manufacturer)
174
strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
175
176
if (dev->product) {
177
if (dev->manufacturer)
178
strlcat(acecad->name, " ", sizeof(acecad->name));
179
strlcat(acecad->name, dev->product, sizeof(acecad->name));
180
}
181
182
usb_make_path(dev, acecad->phys, sizeof(acecad->phys));
183
strlcat(acecad->phys, "/input0", sizeof(acecad->phys));
184
185
input_dev->name = acecad->name;
186
input_dev->phys = acecad->phys;
187
usb_to_input_id(dev, &input_dev->id);
188
input_dev->dev.parent = &intf->dev;
189
190
input_set_drvdata(input_dev, acecad);
191
192
input_dev->open = usb_acecad_open;
193
input_dev->close = usb_acecad_close;
194
195
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
196
input_dev->keybit[BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_TOOL_PEN) |
197
BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS) |
198
BIT_MASK(BTN_STYLUS2);
199
200
switch (id->driver_info) {
201
case 0:
202
input_set_abs_params(input_dev, ABS_X, 0, 5000, 4, 0);
203
input_set_abs_params(input_dev, ABS_Y, 0, 3750, 4, 0);
204
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 512, 0, 0);
205
if (!strlen(acecad->name))
206
snprintf(acecad->name, sizeof(acecad->name),
207
"USB Acecad Flair Tablet %04x:%04x",
208
le16_to_cpu(dev->descriptor.idVendor),
209
le16_to_cpu(dev->descriptor.idProduct));
210
break;
211
212
case 1:
213
input_set_abs_params(input_dev, ABS_X, 0, 53000, 4, 0);
214
input_set_abs_params(input_dev, ABS_Y, 0, 2250, 4, 0);
215
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1024, 0, 0);
216
if (!strlen(acecad->name))
217
snprintf(acecad->name, sizeof(acecad->name),
218
"USB Acecad 302 Tablet %04x:%04x",
219
le16_to_cpu(dev->descriptor.idVendor),
220
le16_to_cpu(dev->descriptor.idProduct));
221
break;
222
}
223
224
usb_fill_int_urb(acecad->irq, dev, pipe,
225
acecad->data, maxp > 8 ? 8 : maxp,
226
usb_acecad_irq, acecad, endpoint->bInterval);
227
acecad->irq->transfer_dma = acecad->data_dma;
228
acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
229
230
err = input_register_device(acecad->input);
231
if (err)
232
goto fail3;
233
234
usb_set_intfdata(intf, acecad);
235
236
return 0;
237
238
fail3: usb_free_urb(acecad->irq);
239
fail2: usb_free_coherent(dev, 8, acecad->data, acecad->data_dma);
240
fail1: input_free_device(input_dev);
241
kfree(acecad);
242
return err;
243
}
244
245
static void usb_acecad_disconnect(struct usb_interface *intf)
246
{
247
struct usb_acecad *acecad = usb_get_intfdata(intf);
248
249
usb_set_intfdata(intf, NULL);
250
251
input_unregister_device(acecad->input);
252
usb_free_urb(acecad->irq);
253
usb_free_coherent(acecad->usbdev, 8, acecad->data, acecad->data_dma);
254
kfree(acecad);
255
}
256
257
static struct usb_device_id usb_acecad_id_table [] = {
258
{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 },
259
{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 },
260
{ }
261
};
262
263
MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);
264
265
static struct usb_driver usb_acecad_driver = {
266
.name = "usb_acecad",
267
.probe = usb_acecad_probe,
268
.disconnect = usb_acecad_disconnect,
269
.id_table = usb_acecad_id_table,
270
};
271
272
static int __init usb_acecad_init(void)
273
{
274
int result = usb_register(&usb_acecad_driver);
275
if (result == 0)
276
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
277
DRIVER_DESC "\n");
278
return result;
279
}
280
281
static void __exit usb_acecad_exit(void)
282
{
283
usb_deregister(&usb_acecad_driver);
284
}
285
286
module_init(usb_acecad_init);
287
module_exit(usb_acecad_exit);
288
289