blob: fed555bf9ff77390f9843cc4ddeee906281e73f2 [file] [log] [blame]
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001/* -*- linux-c -*-
2
3GTCO digitizer USB driver
4
Jeremy Robersona19ceb52007-01-18 08:10:25 -07005TO CHECK: Is pressure done right on report 5?
6
7Copyright (C) 2006 GTCO CalComp
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; version 2
12of the License.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
23Permission to use, copy, modify, distribute, and sell this software and its
24documentation for any purpose is hereby granted without fee, provided that
25the above copyright notice appear in all copies and that both that
26copyright notice and this permission notice appear in supporting
27documentation, and that the name of GTCO-CalComp not be used in advertising
28or publicity pertaining to distribution of the software without specific,
29written prior permission. GTCO-CalComp makes no representations about the
30suitability of this software for any purpose. It is provided "as is"
31without express or implied warranty.
32
33GTCO-CALCOMP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
34INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
35EVENT SHALL GTCO-CALCOMP BE LIABLE FOR ANY SPECIAL, INDIRECT OR
36CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
37DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38TORTIOUS ACTIONS, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39PERFORMANCE OF THIS SOFTWARE.
40
41GTCO CalComp, Inc.
427125 Riverwood Drive
43Columbia, MD 21046
44
45Jeremy Roberson jroberson@gtcocalcomp.com
46Scott Hill shill@gtcocalcomp.com
47*/
48
49
50
51/*#define DEBUG*/
52
53#include <linux/kernel.h>
54#include <linux/module.h>
55#include <linux/errno.h>
56#include <linux/init.h>
57#include <linux/slab.h>
58#include <linux/input.h>
59#include <linux/usb.h>
60#include <asm/uaccess.h>
61#include <asm/unaligned.h>
62#include <asm/byteorder.h>
63
64
Jeremy Robersona19ceb52007-01-18 08:10:25 -070065#include <linux/usb/input.h>
66
67/* Version with a Major number of 2 is for kernel inclusion only. */
68#define GTCO_VERSION "2.00.0006"
69
70
71/* MACROS */
72
73#define VENDOR_ID_GTCO 0x078C
74#define PID_400 0x400
75#define PID_401 0x401
76#define PID_1000 0x1000
77#define PID_1001 0x1001
78#define PID_1002 0x1002
79
80/* Max size of a single report */
81#define REPORT_MAX_SIZE 10
82
83
84/* Bitmask whether pen is in range */
85#define MASK_INRANGE 0x20
86#define MASK_BUTTON 0x01F
87
88#define PATHLENGTH 64
89
90/* DATA STRUCTURES */
91
92/* Device table */
Márton Németh9cb3ce52010-01-10 23:59:05 -080093static const struct usb_device_id gtco_usbid_table[] = {
Jeremy Robersona19ceb52007-01-18 08:10:25 -070094 { USB_DEVICE(VENDOR_ID_GTCO, PID_400) },
95 { USB_DEVICE(VENDOR_ID_GTCO, PID_401) },
96 { USB_DEVICE(VENDOR_ID_GTCO, PID_1000) },
97 { USB_DEVICE(VENDOR_ID_GTCO, PID_1001) },
98 { USB_DEVICE(VENDOR_ID_GTCO, PID_1002) },
99 { }
100};
101MODULE_DEVICE_TABLE (usb, gtco_usbid_table);
102
103
104/* Structure to hold all of our device specific stuff */
105struct gtco {
106
107 struct input_dev *inputdevice; /* input device struct pointer */
108 struct usb_device *usbdev; /* the usb device for this device */
109 struct urb *urbinfo; /* urb for incoming reports */
110 dma_addr_t buf_dma; /* dma addr of the data buffer*/
111 unsigned char * buffer; /* databuffer for reports */
112
113 char usbpath[PATHLENGTH];
114 int openCount;
115
116 /* Information pulled from Report Descriptor */
117 u32 usage;
118 u32 min_X;
119 u32 max_X;
120 u32 min_Y;
121 u32 max_Y;
122 s8 mintilt_X;
123 s8 maxtilt_X;
124 s8 mintilt_Y;
125 s8 maxtilt_Y;
126 u32 maxpressure;
127 u32 minpressure;
128};
129
130
131
132/* Code for parsing the HID REPORT DESCRIPTOR */
133
134/* From HID1.11 spec */
135struct hid_descriptor
136{
137 struct usb_descriptor_header header;
138 __le16 bcdHID;
139 u8 bCountryCode;
140 u8 bNumDescriptors;
141 u8 bDescriptorType;
142 __le16 wDescriptorLength;
143} __attribute__ ((packed));
144
145
146#define HID_DESCRIPTOR_SIZE 9
147#define HID_DEVICE_TYPE 33
148#define REPORT_DEVICE_TYPE 34
149
150
151#define PREF_TAG(x) ((x)>>4)
152#define PREF_TYPE(x) ((x>>2)&0x03)
153#define PREF_SIZE(x) ((x)&0x03)
154
155#define TYPE_MAIN 0
156#define TYPE_GLOBAL 1
157#define TYPE_LOCAL 2
158#define TYPE_RESERVED 3
159
160#define TAG_MAIN_INPUT 0x8
161#define TAG_MAIN_OUTPUT 0x9
162#define TAG_MAIN_FEATURE 0xB
163#define TAG_MAIN_COL_START 0xA
164#define TAG_MAIN_COL_END 0xC
165
166#define TAG_GLOB_USAGE 0
167#define TAG_GLOB_LOG_MIN 1
168#define TAG_GLOB_LOG_MAX 2
169#define TAG_GLOB_PHYS_MIN 3
170#define TAG_GLOB_PHYS_MAX 4
171#define TAG_GLOB_UNIT_EXP 5
172#define TAG_GLOB_UNIT 6
173#define TAG_GLOB_REPORT_SZ 7
174#define TAG_GLOB_REPORT_ID 8
175#define TAG_GLOB_REPORT_CNT 9
176#define TAG_GLOB_PUSH 10
177#define TAG_GLOB_POP 11
178
179#define TAG_GLOB_MAX 12
180
181#define DIGITIZER_USAGE_TIP_PRESSURE 0x30
182#define DIGITIZER_USAGE_TILT_X 0x3D
183#define DIGITIZER_USAGE_TILT_Y 0x3E
184
185
186/*
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700187 * This is an abbreviated parser for the HID Report Descriptor. We
188 * know what devices we are talking to, so this is by no means meant
189 * to be generic. We can make some safe assumptions:
190 *
191 * - We know there are no LONG tags, all short
192 * - We know that we have no MAIN Feature and MAIN Output items
193 * - We know what the IRQ reports are supposed to look like.
194 *
195 * The main purpose of this is to use the HID report desc to figure
196 * out the mins and maxs of the fields in the IRQ reports. The IRQ
197 * reports for 400/401 change slightly if the max X is bigger than 64K.
198 *
199 */
200static void parse_hid_report_descriptor(struct gtco *device, char * report,
201 int length)
202{
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400203 int x, i = 0;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700204
205 /* Tag primitive vars */
206 __u8 prefix;
207 __u8 size;
208 __u8 tag;
209 __u8 type;
210 __u8 data = 0;
211 __u16 data16 = 0;
212 __u32 data32 = 0;
213
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700214 /* For parsing logic */
215 int inputnum = 0;
216 __u32 usage = 0;
217
218 /* Global Values, indexed by TAG */
219 __u32 globalval[TAG_GLOB_MAX];
220 __u32 oldval[TAG_GLOB_MAX];
221
222 /* Debug stuff */
Dmitry Torokhovbc95f362007-05-01 00:24:54 -0400223 char maintype = 'x';
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700224 char globtype[12];
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400225 int indent = 0;
226 char indentstr[10] = "";
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700227
228
229 dbg("======>>>>>>PARSE<<<<<<======");
230
231 /* Walk this report and pull out the info we need */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400232 while (i < length) {
233 prefix = report[i];
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700234
235 /* Skip over prefix */
236 i++;
237
238 /* Determine data size and save the data in the proper variable */
239 size = PREF_SIZE(prefix);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400240 switch (size) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700241 case 1:
242 data = report[i];
243 break;
244 case 2:
Harvey Harrison858ad082008-04-29 01:03:34 -0700245 data16 = get_unaligned_le16(&report[i]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700246 break;
247 case 3:
248 size = 4;
Harvey Harrison858ad082008-04-29 01:03:34 -0700249 data32 = get_unaligned_le32(&report[i]);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400250 break;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700251 }
252
253 /* Skip size of data */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400254 i += size;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700255
256 /* What we do depends on the tag type */
257 tag = PREF_TAG(prefix);
258 type = PREF_TYPE(prefix);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400259 switch (type) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700260 case TYPE_MAIN:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400261 strcpy(globtype, "");
262 switch (tag) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700263
264 case TAG_MAIN_INPUT:
265 /*
266 * The INPUT MAIN tag signifies this is
267 * information from a report. We need to
268 * figure out what it is and store the
269 * min/max values
270 */
271
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400272 maintype = 'I';
273 if (data == 2)
274 strcpy(globtype, "Variable");
275 else if (data == 3)
276 strcpy(globtype, "Var|Const");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700277
278 dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400279 globalval[TAG_GLOB_REPORT_ID], inputnum,
280 globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX],
281 globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN],
282 globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700283
284
285 /*
286 We can assume that the first two input items
287 are always the X and Y coordinates. After
288 that, we look for everything else by
289 local usage value
290 */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400291 switch (inputnum) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700292 case 0: /* X coord */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400293 dbg("GER: X Usage: 0x%x", usage);
294 if (device->max_X == 0) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700295 device->max_X = globalval[TAG_GLOB_LOG_MAX];
296 device->min_X = globalval[TAG_GLOB_LOG_MIN];
297 }
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700298 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400299
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700300 case 1: /* Y coord */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400301 dbg("GER: Y Usage: 0x%x", usage);
302 if (device->max_Y == 0) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700303 device->max_Y = globalval[TAG_GLOB_LOG_MAX];
304 device->min_Y = globalval[TAG_GLOB_LOG_MIN];
305 }
306 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400307
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700308 default:
309 /* Tilt X */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400310 if (usage == DIGITIZER_USAGE_TILT_X) {
311 if (device->maxtilt_X == 0) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700312 device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX];
313 device->mintilt_X = globalval[TAG_GLOB_LOG_MIN];
314 }
315 }
316
317 /* Tilt Y */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400318 if (usage == DIGITIZER_USAGE_TILT_Y) {
319 if (device->maxtilt_Y == 0) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700320 device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX];
321 device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN];
322 }
323 }
324
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700325 /* Pressure */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400326 if (usage == DIGITIZER_USAGE_TIP_PRESSURE) {
327 if (device->maxpressure == 0) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700328 device->maxpressure = globalval[TAG_GLOB_LOG_MAX];
329 device->minpressure = globalval[TAG_GLOB_LOG_MIN];
330 }
331 }
332
333 break;
334 }
335
336 inputnum++;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700337 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400338
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700339 case TAG_MAIN_OUTPUT:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400340 maintype = 'O';
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700341 break;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700342
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400343 case TAG_MAIN_FEATURE:
344 maintype = 'F';
345 break;
346
347 case TAG_MAIN_COL_START:
348 maintype = 'S';
349
350 if (data == 0) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700351 dbg("======>>>>>> Physical");
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400352 strcpy(globtype, "Physical");
353 } else
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700354 dbg("======>>>>>>");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700355
356 /* Indent the debug output */
357 indent++;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400358 for (x = 0; x < indent; x++)
359 indentstr[x] = '-';
360 indentstr[x] = 0;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700361
362 /* Save global tags */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400363 for (x = 0; x < TAG_GLOB_MAX; x++)
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700364 oldval[x] = globalval[x];
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700365
366 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400367
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700368 case TAG_MAIN_COL_END:
369 dbg("<<<<<<======");
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400370 maintype = 'E';
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700371 indent--;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400372 for (x = 0; x < indent; x++)
373 indentstr[x] = '-';
374 indentstr[x] = 0;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700375
376 /* Copy global tags back */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400377 for (x = 0; x < TAG_GLOB_MAX; x++)
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700378 globalval[x] = oldval[x];
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700379
380 break;
381 }
382
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400383 switch (size) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700384 case 1:
385 dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400386 indentstr, tag, maintype, size, globtype, data);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700387 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400388
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700389 case 2:
390 dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400391 indentstr, tag, maintype, size, globtype, data16);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700392 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400393
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700394 case 4:
395 dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400396 indentstr, tag, maintype, size, globtype, data32);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700397 break;
398 }
399 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400400
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700401 case TYPE_GLOBAL:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400402 switch (tag) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700403 case TAG_GLOB_USAGE:
404 /*
405 * First time we hit the global usage tag,
406 * it should tell us the type of device
407 */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400408 if (device->usage == 0)
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700409 device->usage = data;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400410
411 strcpy(globtype, "USAGE");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700412 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400413
414 case TAG_GLOB_LOG_MIN:
415 strcpy(globtype, "LOG_MIN");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700416 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400417
418 case TAG_GLOB_LOG_MAX:
419 strcpy(globtype, "LOG_MAX");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700420 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400421
422 case TAG_GLOB_PHYS_MIN:
423 strcpy(globtype, "PHYS_MIN");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700424 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400425
426 case TAG_GLOB_PHYS_MAX:
427 strcpy(globtype, "PHYS_MAX");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700428 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400429
430 case TAG_GLOB_UNIT_EXP:
431 strcpy(globtype, "EXP");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700432 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400433
434 case TAG_GLOB_UNIT:
435 strcpy(globtype, "UNIT");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700436 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400437
438 case TAG_GLOB_REPORT_SZ:
439 strcpy(globtype, "REPORT_SZ");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700440 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400441
442 case TAG_GLOB_REPORT_ID:
443 strcpy(globtype, "REPORT_ID");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700444 /* New report, restart numbering */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400445 inputnum = 0;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700446 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400447
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700448 case TAG_GLOB_REPORT_CNT:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400449 strcpy(globtype, "REPORT_CNT");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700450 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400451
452 case TAG_GLOB_PUSH:
453 strcpy(globtype, "PUSH");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700454 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400455
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700456 case TAG_GLOB_POP:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400457 strcpy(globtype, "POP");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700458 break;
459 }
460
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700461 /* Check to make sure we have a good tag number
462 so we don't overflow array */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400463 if (tag < TAG_GLOB_MAX) {
464 switch (size) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700465 case 1:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400466 dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
467 indentstr, globtype, tag, size, data);
468 globalval[tag] = data;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700469 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400470
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700471 case 2:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400472 dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
473 indentstr, globtype, tag, size, data16);
474 globalval[tag] = data16;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700475 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400476
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700477 case 4:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400478 dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
479 indentstr, globtype, tag, size, data32);
480 globalval[tag] = data32;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700481 break;
482 }
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400483 } else {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700484 dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400485 indentstr, tag, size);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700486 }
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700487 break;
488
489 case TYPE_LOCAL:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400490 switch (tag) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700491 case TAG_GLOB_USAGE:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400492 strcpy(globtype, "USAGE");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700493 /* Always 1 byte */
494 usage = data;
495 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400496
497 case TAG_GLOB_LOG_MIN:
498 strcpy(globtype, "MIN");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700499 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400500
501 case TAG_GLOB_LOG_MAX:
502 strcpy(globtype, "MAX");
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700503 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400504
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700505 default:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400506 strcpy(globtype, "UNKNOWN");
507 break;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700508 }
509
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400510 switch (size) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700511 case 1:
512 dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400513 indentstr, tag, globtype, size, data);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700514 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400515
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700516 case 2:
517 dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400518 indentstr, tag, globtype, size, data16);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700519 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400520
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700521 case 4:
522 dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400523 indentstr, tag, globtype, size, data32);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700524 break;
525 }
526
527 break;
528 }
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700529 }
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700530}
531
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700532/* INPUT DRIVER Routines */
533
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700534/*
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400535 * Called when opening the input device. This will submit the URB to
536 * the usb system so we start getting reports
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700537 */
538static int gtco_input_open(struct input_dev *inputdev)
539{
Dmitry Torokhov7791bda2007-04-12 01:34:39 -0400540 struct gtco *device = input_get_drvdata(inputdev);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700541
542 device->urbinfo->dev = device->usbdev;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400543 if (usb_submit_urb(device->urbinfo, GFP_KERNEL))
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700544 return -EIO;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400545
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700546 return 0;
547}
548
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400549/*
550 * Called when closing the input device. This will unlink the URB
551 */
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700552static void gtco_input_close(struct input_dev *inputdev)
553{
Dmitry Torokhov7791bda2007-04-12 01:34:39 -0400554 struct gtco *device = input_get_drvdata(inputdev);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700555
556 usb_kill_urb(device->urbinfo);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700557}
558
559
560/*
561 * Setup input device capabilities. Tell the input system what this
562 * device is capable of generating.
563 *
564 * This information is based on what is read from the HID report and
565 * placed in the struct gtco structure
566 *
567 */
Dmitry Torokhov7791bda2007-04-12 01:34:39 -0400568static void gtco_setup_caps(struct input_dev *inputdev)
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700569{
Dmitry Torokhov7791bda2007-04-12 01:34:39 -0400570 struct gtco *device = input_get_drvdata(inputdev);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700571
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700572 /* Which events */
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700573 inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) |
574 BIT_MASK(EV_MSC);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700575
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700576 /* Misc event menu block */
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700577 inputdev->mscbit[0] = BIT_MASK(MSC_SCAN) | BIT_MASK(MSC_SERIAL) |
578 BIT_MASK(MSC_RAW);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700579
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700580 /* Absolute values based on HID report info */
581 input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X,
582 0, 0);
583 input_set_abs_params(inputdev, ABS_Y, device->min_Y, device->max_Y,
584 0, 0);
585
586 /* Proximity */
587 input_set_abs_params(inputdev, ABS_DISTANCE, 0, 1, 0, 0);
588
589 /* Tilt & pressure */
590 input_set_abs_params(inputdev, ABS_TILT_X, device->mintilt_X,
591 device->maxtilt_X, 0, 0);
592 input_set_abs_params(inputdev, ABS_TILT_Y, device->mintilt_Y,
593 device->maxtilt_Y, 0, 0);
594 input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure,
595 device->maxpressure, 0, 0);
596
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700597 /* Transducer */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400598 input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700599}
600
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700601/* USB Routines */
602
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700603/*
604 * URB callback routine. Called when we get IRQ reports from the
605 * digitizer.
606 *
607 * This bridges the USB and input device worlds. It generates events
608 * on the input device based on the USB reports.
609 */
610static void gtco_urb_callback(struct urb *urbinfo)
611{
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400612 struct gtco *device = urbinfo->context;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700613 struct input_dev *inputdev;
614 int rc;
615 u32 val = 0;
616 s8 valsigned = 0;
617 char le_buffer[2];
618
619 inputdev = device->inputdevice;
620
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700621 /* Was callback OK? */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400622 if (urbinfo->status == -ECONNRESET ||
623 urbinfo->status == -ENOENT ||
624 urbinfo->status == -ESHUTDOWN) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700625
626 /* Shutdown is occurring. Return and don't queue up any more */
627 return;
628 }
629
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400630 if (urbinfo->status != 0) {
631 /*
632 * Some unknown error. Hopefully temporary. Just go and
633 * requeue an URB
634 */
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700635 goto resubmit;
636 }
637
638 /*
639 * Good URB, now process
640 */
641
642 /* PID dependent when we interpret the report */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400643 if (inputdev->id.product == PID_1000 ||
644 inputdev->id.product == PID_1001 ||
645 inputdev->id.product == PID_1002) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700646
647 /*
648 * Switch on the report ID
649 * Conveniently, the reports have more information, the higher
650 * the report number. We can just fall through the case
651 * statements if we start with the highest number report
652 */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400653 switch (device->buffer[0]) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700654 case 5:
655 /* Pressure is 9 bits */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400656 val = ((u16)(device->buffer[8]) << 1);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700657 val |= (u16)(device->buffer[7] >> 7);
658 input_report_abs(inputdev, ABS_PRESSURE,
659 device->buffer[8]);
660
661 /* Mask out the Y tilt value used for pressure */
662 device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);
663
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700664 /* Fall thru */
665 case 4:
666 /* Tilt */
667
668 /* Sign extend these 7 bit numbers. */
669 if (device->buffer[6] & 0x40)
670 device->buffer[6] |= 0x80;
671
672 if (device->buffer[7] & 0x40)
673 device->buffer[7] |= 0x80;
674
675
676 valsigned = (device->buffer[6]);
677 input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned);
678
679 valsigned = (device->buffer[7]);
680 input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);
681
682 /* Fall thru */
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700683 case 2:
684 case 3:
685 /* Convert buttons, only 5 bits possible */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400686 val = (device->buffer[5]) & MASK_BUTTON;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700687
688 /* We don't apply any meaning to the bitmask,
689 just report */
690 input_event(inputdev, EV_MSC, MSC_SERIAL, val);
691
692 /* Fall thru */
693 case 1:
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700694 /* All reports have X and Y coords in the same place */
Harvey Harrison858ad082008-04-29 01:03:34 -0700695 val = get_unaligned_le16(&device->buffer[1]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700696 input_report_abs(inputdev, ABS_X, val);
697
Harvey Harrison858ad082008-04-29 01:03:34 -0700698 val = get_unaligned_le16(&device->buffer[3]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700699 input_report_abs(inputdev, ABS_Y, val);
700
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700701 /* Ditto for proximity bit */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400702 val = device->buffer[5] & MASK_INRANGE ? 1 : 0;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700703 input_report_abs(inputdev, ABS_DISTANCE, val);
704
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700705 /* Report 1 is an exception to how we handle buttons */
706 /* Buttons are an index, not a bitmask */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400707 if (device->buffer[0] == 1) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700708
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400709 /*
710 * Convert buttons, 5 bit index
711 * Report value of index set as one,
712 * the rest as 0
713 */
714 val = device->buffer[5] & MASK_BUTTON;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700715 dbg("======>>>>>>REPORT 1: val 0x%X(%d)",
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400716 val, val);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700717
718 /*
719 * We don't apply any meaning to the button
720 * index, just report it
721 */
722 input_event(inputdev, EV_MSC, MSC_SERIAL, val);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700723 }
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700724 break;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400725
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700726 case 7:
727 /* Menu blocks */
728 input_event(inputdev, EV_MSC, MSC_SCAN,
729 device->buffer[1]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700730 break;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700731 }
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700732 }
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400733
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700734 /* Other pid class */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400735 if (inputdev->id.product == PID_400 ||
736 inputdev->id.product == PID_401) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700737
738 /* Report 2 */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400739 if (device->buffer[0] == 2) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700740 /* Menu blocks */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400741 input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700742 }
743
744 /* Report 1 */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400745 if (device->buffer[0] == 1) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700746 char buttonbyte;
747
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700748 /* IF X max > 64K, we still a bit from the y report */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400749 if (device->max_X > 0x10000) {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700750
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400751 val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]);
752 val |= (u32)(((u8)device->buffer[3] & 0x1) << 16);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700753
754 input_report_abs(inputdev, ABS_X, val);
755
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400756 le_buffer[0] = (u8)((u8)(device->buffer[3]) >> 1);
757 le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700758
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400759 le_buffer[1] = (u8)(device->buffer[4] >> 1);
760 le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700761
Harvey Harrison858ad082008-04-29 01:03:34 -0700762 val = get_unaligned_le16(le_buffer);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700763 input_report_abs(inputdev, ABS_Y, val);
764
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700765 /*
766 * Shift the button byte right by one to
767 * make it look like the standard report
768 */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400769 buttonbyte = device->buffer[5] >> 1;
770 } else {
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700771
Harvey Harrison858ad082008-04-29 01:03:34 -0700772 val = get_unaligned_le16(&device->buffer[1]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700773 input_report_abs(inputdev, ABS_X, val);
774
Harvey Harrison858ad082008-04-29 01:03:34 -0700775 val = get_unaligned_le16(&device->buffer[3]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700776 input_report_abs(inputdev, ABS_Y, val);
777
778 buttonbyte = device->buffer[5];
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700779 }
780
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700781 /* BUTTONS and PROXIMITY */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400782 val = buttonbyte & MASK_INRANGE ? 1 : 0;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700783 input_report_abs(inputdev, ABS_DISTANCE, val);
784
785 /* Convert buttons, only 4 bits possible */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400786 val = buttonbyte & 0x0F;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700787#ifdef USE_BUTTONS
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400788 for (i = 0; i < 5; i++)
789 input_report_key(inputdev, BTN_DIGI + i, val & (1 << i));
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700790#else
791 /* We don't apply any meaning to the bitmask, just report */
792 input_event(inputdev, EV_MSC, MSC_SERIAL, val);
793#endif
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400794
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700795 /* TRANSDUCER */
796 input_report_abs(inputdev, ABS_MISC, device->buffer[6]);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700797 }
798 }
799
800 /* Everybody gets report ID's */
801 input_event(inputdev, EV_MSC, MSC_RAW, device->buffer[0]);
802
803 /* Sync it up */
804 input_sync(inputdev);
805
806 resubmit:
807 rc = usb_submit_urb(urbinfo, GFP_ATOMIC);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400808 if (rc != 0)
Greg Kroah-Hartman3bd95972012-04-25 14:48:39 -0700809 dev_err(&device->usbdev->dev,
810 "usb_submit_urb failed rc=0x%x\n", rc);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700811}
812
813/*
814 * The probe routine. This is called when the kernel find the matching USB
815 * vendor/product. We do the following:
816 *
817 * - Allocate mem for a local structure to manage the device
818 * - Request a HID Report Descriptor from the device and parse it to
819 * find out the device parameters
820 * - Create an input device and assign it attributes
821 * - Allocate an URB so the device can talk to us when the input
822 * queue is open
823 */
824static int gtco_probe(struct usb_interface *usbinterface,
825 const struct usb_device_id *id)
826{
827
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400828 struct gtco *gtco;
829 struct input_dev *input_dev;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700830 struct hid_descriptor *hid_desc;
Dmitry Torokhov501a5252008-05-30 10:40:28 -0400831 char *report;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400832 int result = 0, retry;
833 int error;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700834 struct usb_endpoint_descriptor *endpoint;
835
836 /* Allocate memory for device structure */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400837 gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL);
838 input_dev = input_allocate_device();
839 if (!gtco || !input_dev) {
Greg Kroah-Hartman3bd95972012-04-25 14:48:39 -0700840 dev_err(&usbinterface->dev, "No more memory\n");
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400841 error = -ENOMEM;
842 goto err_free_devs;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700843 }
844
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400845 /* Set pointer to the input device */
846 gtco->inputdevice = input_dev;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700847
848 /* Save interface information */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400849 gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700850
851 /* Allocate some data for incoming reports */
Daniel Mack997ea582010-04-12 13:17:25 +0200852 gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE,
853 GFP_KERNEL, &gtco->buf_dma);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400854 if (!gtco->buffer) {
Greg Kroah-Hartman3bd95972012-04-25 14:48:39 -0700855 dev_err(&usbinterface->dev, "No more memory for us buffers\n");
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400856 error = -ENOMEM;
857 goto err_free_devs;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700858 }
859
860 /* Allocate URB for reports */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400861 gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
862 if (!gtco->urbinfo) {
Greg Kroah-Hartman3bd95972012-04-25 14:48:39 -0700863 dev_err(&usbinterface->dev, "Failed to allocate URB\n");
Julia Lawallf4bc95d2008-07-03 12:10:58 -0400864 error = -ENOMEM;
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400865 goto err_free_buf;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700866 }
867
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700868 /*
869 * The endpoint is always altsetting 0, we know this since we know
870 * this device only has one interrupt endpoint
871 */
872 endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
873
874 /* Some debug */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400875 dbg("gtco # interfaces: %d", usbinterface->num_altsetting);
876 dbg("num endpoints: %d", usbinterface->cur_altsetting->desc.bNumEndpoints);
877 dbg("interface class: %d", usbinterface->cur_altsetting->desc.bInterfaceClass);
878 dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType);
Julia Lawalle941da32008-12-30 01:09:02 -0800879 if (usb_endpoint_xfer_int(endpoint))
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700880 dbg("endpoint: we have interrupt endpoint\n");
881
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400882 dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700883
884 /*
885 * Find the HID descriptor so we can find out the size of the
886 * HID report descriptor
887 */
888 if (usb_get_extra_descriptor(usbinterface->cur_altsetting,
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400889 HID_DEVICE_TYPE, &hid_desc) != 0){
Greg Kroah-Hartman3bd95972012-04-25 14:48:39 -0700890 dev_err(&usbinterface->dev,
891 "Can't retrieve exta USB descriptor to get hid report descriptor length\n");
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400892 error = -EIO;
893 goto err_free_urb;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700894 }
895
896 dbg("Extra descriptor success: type:%d len:%d",
897 hid_desc->bDescriptorType, hid_desc->wDescriptorLength);
898
Al Viro6b8588f2008-04-28 07:00:26 +0100899 report = kzalloc(le16_to_cpu(hid_desc->wDescriptorLength), GFP_KERNEL);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400900 if (!report) {
Greg Kroah-Hartman3bd95972012-04-25 14:48:39 -0700901 dev_err(&usbinterface->dev, "No more memory for report\n");
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400902 error = -ENOMEM;
903 goto err_free_urb;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700904 }
905
906 /* Couple of tries to get reply */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400907 for (retry = 0; retry < 3; retry++) {
908 result = usb_control_msg(gtco->usbdev,
909 usb_rcvctrlpipe(gtco->usbdev, 0),
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700910 USB_REQ_GET_DESCRIPTOR,
911 USB_RECIP_INTERFACE | USB_DIR_IN,
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400912 REPORT_DEVICE_TYPE << 8,
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700913 0, /* interface */
914 report,
Al Viro6b8588f2008-04-28 07:00:26 +0100915 le16_to_cpu(hid_desc->wDescriptorLength),
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700916 5000); /* 5 secs */
917
Dmitry Torokhov501a5252008-05-30 10:40:28 -0400918 dbg("usb_control_msg result: %d", result);
919 if (result == le16_to_cpu(hid_desc->wDescriptorLength)) {
920 parse_hid_report_descriptor(gtco, report, result);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700921 break;
Dmitry Torokhov501a5252008-05-30 10:40:28 -0400922 }
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700923 }
924
Dmitry Torokhov501a5252008-05-30 10:40:28 -0400925 kfree(report);
926
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700927 /* If we didn't get the report, fail */
Al Viro6b8588f2008-04-28 07:00:26 +0100928 if (result != le16_to_cpu(hid_desc->wDescriptorLength)) {
Greg Kroah-Hartman3bd95972012-04-25 14:48:39 -0700929 dev_err(&usbinterface->dev,
930 "Failed to get HID Report Descriptor of size: %d\n",
931 hid_desc->wDescriptorLength);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400932 error = -EIO;
933 goto err_free_urb;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700934 }
935
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700936 /* Create a device file node */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400937 usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath));
938 strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath));
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700939
940 /* Set Input device functions */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400941 input_dev->open = gtco_input_open;
942 input_dev->close = gtco_input_close;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700943
944 /* Set input device information */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400945 input_dev->name = "GTCO_CalComp";
946 input_dev->phys = gtco->usbpath;
Dmitry Torokhov7791bda2007-04-12 01:34:39 -0400947
948 input_set_drvdata(input_dev, gtco);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700949
950 /* Now set up all the input device capabilities */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400951 gtco_setup_caps(input_dev);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700952
953 /* Set input device required ID information */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400954 usb_to_input_id(gtco->usbdev, &input_dev->id);
Dmitry Torokhovc0f82d52007-04-12 01:35:03 -0400955 input_dev->dev.parent = &usbinterface->dev;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700956
957 /* Setup the URB, it will be posted later on open of input device */
958 endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
959
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400960 usb_fill_int_urb(gtco->urbinfo,
961 gtco->usbdev,
962 usb_rcvintpipe(gtco->usbdev,
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700963 endpoint->bEndpointAddress),
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400964 gtco->buffer,
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700965 REPORT_MAX_SIZE,
966 gtco_urb_callback,
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400967 gtco,
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700968 endpoint->bInterval);
969
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400970 gtco->urbinfo->transfer_dma = gtco->buf_dma;
971 gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700972
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400973 /* Save gtco pointer in USB interface gtco */
974 usb_set_intfdata(usbinterface, gtco);
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700975
976 /* All done, now register the input device */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400977 error = input_register_device(input_dev);
978 if (error)
979 goto err_free_urb;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700980
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700981 return 0;
982
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400983 err_free_urb:
984 usb_free_urb(gtco->urbinfo);
985 err_free_buf:
Daniel Mack997ea582010-04-12 13:17:25 +0200986 usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE,
987 gtco->buffer, gtco->buf_dma);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400988 err_free_devs:
Dmitry Torokhov1b726a02007-04-12 01:33:00 -0400989 input_free_device(input_dev);
990 kfree(gtco);
991 return error;
Jeremy Robersona19ceb52007-01-18 08:10:25 -0700992}
993
994/*
995 * This function is a standard USB function called when the USB device
996 * is disconnected. We will get rid of the URV, de-register the input
997 * device, and free up allocated memory
998 */
999static void gtco_disconnect(struct usb_interface *interface)
1000{
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001001 /* Grab private device ptr */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -04001002 struct gtco *gtco = usb_get_intfdata(interface);
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001003
1004 /* Now reverse all the registration stuff */
Dmitry Torokhov1b726a02007-04-12 01:33:00 -04001005 if (gtco) {
1006 input_unregister_device(gtco->inputdevice);
1007 usb_kill_urb(gtco->urbinfo);
1008 usb_free_urb(gtco->urbinfo);
Daniel Mack997ea582010-04-12 13:17:25 +02001009 usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE,
1010 gtco->buffer, gtco->buf_dma);
Dmitry Torokhov1b726a02007-04-12 01:33:00 -04001011 kfree(gtco);
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001012 }
1013
Greg Kroah-Hartman899ef6e2008-08-18 13:21:04 -07001014 dev_info(&interface->dev, "gtco driver disconnected\n");
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001015}
1016
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001017/* STANDARD MODULE LOAD ROUTINES */
1018
1019static struct usb_driver gtco_driverinfo_table = {
Dmitry Torokhov1b726a02007-04-12 01:33:00 -04001020 .name = "gtco",
1021 .id_table = gtco_usbid_table,
1022 .probe = gtco_probe,
1023 .disconnect = gtco_disconnect,
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001024};
Dmitry Torokhov1b726a02007-04-12 01:33:00 -04001025
Greg Kroah-Hartman08642e72011-11-18 09:48:31 -08001026module_usb_driver(gtco_driverinfo_table);
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001027
Dmitry Torokhov32a676f2009-04-17 20:12:35 -07001028MODULE_DESCRIPTION("GTCO digitizer USB driver");
Jeremy Robersona19ceb52007-01-18 08:10:25 -07001029MODULE_LICENSE("GPL");