diff options
Diffstat (limited to 'drivers/input/tablet/wacom_sys.c')
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c new file mode 100644 index 000000000000..83bddef66067 --- /dev/null +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * drivers/input/tablet/wacom_sys.c | ||
3 | * | ||
4 | * USB Wacom Graphire and Wacom Intuos tablet support - system specific code | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include "wacom.h" | ||
15 | #include "wacom_wac.h" | ||
16 | |||
17 | #define USB_REQ_GET_REPORT 0x01 | ||
18 | #define USB_REQ_SET_REPORT 0x09 | ||
19 | |||
20 | static int usb_get_report(struct usb_interface *intf, unsigned char type, | ||
21 | unsigned char id, void *buf, int size) | ||
22 | { | ||
23 | return usb_control_msg(interface_to_usbdev(intf), | ||
24 | usb_rcvctrlpipe(interface_to_usbdev(intf), 0), | ||
25 | USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
26 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
27 | buf, size, 100); | ||
28 | } | ||
29 | |||
30 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | ||
31 | unsigned char id, void *buf, int size) | ||
32 | { | ||
33 | return usb_control_msg(interface_to_usbdev(intf), | ||
34 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | ||
35 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
36 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
37 | buf, size, 1000); | ||
38 | } | ||
39 | |||
40 | static struct input_dev * get_input_dev(struct wacom_combo *wcombo) | ||
41 | { | ||
42 | return wcombo->wacom->dev; | ||
43 | } | ||
44 | |||
45 | static void wacom_sys_irq(struct urb *urb) | ||
46 | { | ||
47 | struct wacom *wacom = urb->context; | ||
48 | struct wacom_combo wcombo; | ||
49 | int retval; | ||
50 | |||
51 | switch (urb->status) { | ||
52 | case 0: | ||
53 | /* success */ | ||
54 | break; | ||
55 | case -ECONNRESET: | ||
56 | case -ENOENT: | ||
57 | case -ESHUTDOWN: | ||
58 | /* this urb is terminated, clean up */ | ||
59 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
60 | return; | ||
61 | default: | ||
62 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
63 | goto exit; | ||
64 | } | ||
65 | |||
66 | wcombo.wacom = wacom; | ||
67 | wcombo.urb = urb; | ||
68 | |||
69 | if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo)) | ||
70 | input_sync(get_input_dev(&wcombo)); | ||
71 | |||
72 | exit: | ||
73 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
74 | if (retval) | ||
75 | err ("%s - usb_submit_urb failed with result %d", | ||
76 | __FUNCTION__, retval); | ||
77 | } | ||
78 | |||
79 | void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) | ||
80 | { | ||
81 | input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data); | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data) | ||
86 | { | ||
87 | input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data) | ||
92 | { | ||
93 | input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data); | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value) | ||
98 | { | ||
99 | input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | __u16 wacom_be16_to_cpu(unsigned char *data) | ||
104 | { | ||
105 | __u16 value; | ||
106 | value = be16_to_cpu(*(__be16 *) data); | ||
107 | return value; | ||
108 | } | ||
109 | |||
110 | __u16 wacom_le16_to_cpu(unsigned char *data) | ||
111 | { | ||
112 | __u16 value; | ||
113 | value = le16_to_cpu(*(__le16 *) data); | ||
114 | return value; | ||
115 | } | ||
116 | |||
117 | void wacom_input_sync(void *wcombo) | ||
118 | { | ||
119 | input_sync(get_input_dev((struct wacom_combo *)wcombo)); | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | static int wacom_open(struct input_dev *dev) | ||
124 | { | ||
125 | struct wacom *wacom = input_get_drvdata(dev); | ||
126 | |||
127 | wacom->irq->dev = wacom->usbdev; | ||
128 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) | ||
129 | return -EIO; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static void wacom_close(struct input_dev *dev) | ||
135 | { | ||
136 | struct wacom *wacom = input_get_drvdata(dev); | ||
137 | |||
138 | usb_kill_urb(wacom->irq); | ||
139 | } | ||
140 | |||
141 | void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
142 | { | ||
143 | input_dev->evbit[0] |= BIT(EV_MSC); | ||
144 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
145 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
146 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_4); | ||
147 | } | ||
148 | |||
149 | void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
150 | { | ||
151 | input_dev->evbit[0] |= BIT(EV_REL); | ||
152 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
153 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
154 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | ||
155 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | ||
156 | } | ||
157 | |||
158 | void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
159 | { | ||
160 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
161 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3); | ||
162 | input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); | ||
163 | } | ||
164 | |||
165 | void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
166 | { | ||
167 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
168 | input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); | ||
169 | } | ||
170 | |||
171 | void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
172 | { | ||
173 | input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); | ||
174 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
175 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
176 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
177 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | ||
178 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | ||
179 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | ||
180 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | ||
181 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | ||
182 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | ||
183 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | ||
184 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | ||
185 | } | ||
186 | |||
187 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
188 | { | ||
189 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | ||
190 | } | ||
191 | |||
192 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
193 | { | ||
194 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER); | ||
195 | } | ||
196 | |||
197 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
198 | { | ||
199 | struct usb_device *dev = interface_to_usbdev(intf); | ||
200 | struct usb_endpoint_descriptor *endpoint; | ||
201 | struct wacom *wacom; | ||
202 | struct wacom_wac *wacom_wac; | ||
203 | struct input_dev *input_dev; | ||
204 | int error = -ENOMEM; | ||
205 | char rep_data[2], limit = 0; | ||
206 | |||
207 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | ||
208 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); | ||
209 | input_dev = input_allocate_device(); | ||
210 | if (!wacom || !input_dev || !wacom_wac) | ||
211 | goto fail1; | ||
212 | |||
213 | wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); | ||
214 | if (!wacom_wac->data) | ||
215 | goto fail1; | ||
216 | |||
217 | wacom->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
218 | if (!wacom->irq) | ||
219 | goto fail2; | ||
220 | |||
221 | wacom->usbdev = dev; | ||
222 | wacom->dev = input_dev; | ||
223 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | ||
224 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | ||
225 | |||
226 | wacom_wac->features = get_wacom_feature(id); | ||
227 | BUG_ON(wacom_wac->features->pktlen > 10); | ||
228 | |||
229 | input_dev->name = wacom_wac->features->name; | ||
230 | wacom->wacom_wac = wacom_wac; | ||
231 | usb_to_input_id(dev, &input_dev->id); | ||
232 | |||
233 | input_dev->dev.parent = &intf->dev; | ||
234 | |||
235 | input_set_drvdata(input_dev, wacom); | ||
236 | |||
237 | input_dev->open = wacom_open; | ||
238 | input_dev->close = wacom_close; | ||
239 | |||
240 | input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); | ||
241 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); | ||
242 | input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0); | ||
243 | input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); | ||
244 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); | ||
245 | input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC); | ||
246 | |||
247 | wacom_init_input_dev(input_dev, wacom_wac); | ||
248 | |||
249 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
250 | |||
251 | usb_fill_int_urb(wacom->irq, dev, | ||
252 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
253 | wacom_wac->data, wacom_wac->features->pktlen, | ||
254 | wacom_sys_irq, wacom, endpoint->bInterval); | ||
255 | wacom->irq->transfer_dma = wacom->data_dma; | ||
256 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
257 | |||
258 | error = input_register_device(wacom->dev); | ||
259 | if (error) | ||
260 | goto fail3; | ||
261 | |||
262 | /* Ask the tablet to report tablet data. Repeat until it succeeds */ | ||
263 | do { | ||
264 | rep_data[0] = 2; | ||
265 | rep_data[1] = 2; | ||
266 | usb_set_report(intf, 3, 2, rep_data, 2); | ||
267 | usb_get_report(intf, 3, 2, rep_data, 2); | ||
268 | } while (rep_data[1] != 2 && limit++ < 5); | ||
269 | |||
270 | usb_set_intfdata(intf, wacom); | ||
271 | return 0; | ||
272 | |||
273 | fail3: usb_free_urb(wacom->irq); | ||
274 | fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); | ||
275 | fail1: input_free_device(input_dev); | ||
276 | kfree(wacom); | ||
277 | kfree(wacom_wac); | ||
278 | return error; | ||
279 | } | ||
280 | |||
281 | static void wacom_disconnect(struct usb_interface *intf) | ||
282 | { | ||
283 | struct wacom *wacom = usb_get_intfdata (intf); | ||
284 | |||
285 | usb_set_intfdata(intf, NULL); | ||
286 | if (wacom) { | ||
287 | usb_kill_urb(wacom->irq); | ||
288 | input_unregister_device(wacom->dev); | ||
289 | usb_free_urb(wacom->irq); | ||
290 | usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); | ||
291 | kfree(wacom->wacom_wac); | ||
292 | kfree(wacom); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static struct usb_driver wacom_driver = { | ||
297 | .name = "wacom", | ||
298 | .probe = wacom_probe, | ||
299 | .disconnect = wacom_disconnect, | ||
300 | }; | ||
301 | |||
302 | static int __init wacom_init(void) | ||
303 | { | ||
304 | int result; | ||
305 | wacom_driver.id_table = get_device_table(); | ||
306 | result = usb_register(&wacom_driver); | ||
307 | if (result == 0) | ||
308 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
309 | return result; | ||
310 | } | ||
311 | |||
312 | static void __exit wacom_exit(void) | ||
313 | { | ||
314 | usb_deregister(&wacom_driver); | ||
315 | } | ||
316 | |||
317 | module_init(wacom_init); | ||
318 | module_exit(wacom_exit); | ||