~ubuntu-branches/ubuntu/saucy/joystick/saucy

« back to all changes in this revision

Viewing changes to .pc/ioctl-error-handling.patch/utils/inputattach.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Kitt
  • Date: 2011-04-04 16:56:39 UTC
  • mfrom: (1.1.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20110404165639-wwp0enzkfqi841i7
* New upstream version:
  - Builds with --as-needed. Closes: #607009.
  - inputattach supports W8001. Closes: #616443.
  - inputattach supports Zhen-Hua. LP: #648945.
* Drop all patches, merged upstream. Drop README.source explaining quilt
  usage, and --with-quilt directive to sh.
* Drop manpages, merged upstream.
* Drop store/restore tools, merged upstream.
* Rework udev rules:
  - provide agents to delay invoking inputattach or jscal-restore until
    they become available;
  - drop jskeepalive and use sleep instead to stop Acrux devices from
    going into a coma (as suggested by Oliver Neukum), for kernels prior
    to 2.6.39;
  - only apply the udev rules when adding devices (as suggested by
    Roberto Neri).
* Standards-Version 3.9.1, no change required.
* No longer ship evtest, its source is maintained separately (and will
  be removed from future upstream versions of joystick).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: inputattach.c,v 1.24 2006/02/08 12:19:31 vojtech Exp $
3
 
 *
4
 
 *  Copyright (c) 1999-2000 Vojtech Pavlik
5
 
 *
6
 
 *  Sponsored by SuSE
7
 
 *
8
 
 *  Twiddler support Copyright (c) 2001 Arndt Schoenewald
9
 
 *  Sponsored by Quelltext AG (http://www.quelltext-ag.de), Dortmund, Germany
10
 
 *
11
 
 *  Sahara Touchit-213 mode added by Claudio Nieder 2008-05-01.
12
 
 */
13
 
 
14
 
/*
15
 
 * Input line discipline attach program
16
 
 */
17
 
 
18
 
/*
19
 
 * This program is free software; you can redistribute it and/or modify
20
 
 * it under the terms of the GNU General Public License as published by
21
 
 * the Free Software Foundation; either version 2 of the License, or
22
 
 * (at your option) any later version.
23
 
 *
24
 
 * This program is distributed in the hope that it will be useful,
25
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 
 * GNU General Public License for more details.
28
 
 *
29
 
 * You should have received a copy of the GNU General Public License
30
 
 * along with this program; if not, write to the Free Software
31
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32
 
 *
33
 
 * Should you need to contact me, the author, you can do so either by
34
 
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
35
 
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
36
 
 */
37
 
 
38
 
#include <ctype.h>
39
 
#include <errno.h>
40
 
#include <fcntl.h>
41
 
#include <linux/serio.h>
42
 
#include "serio-ids.h"
43
 
#include <stdio.h>
44
 
#include <stdlib.h>
45
 
#include <string.h>
46
 
#include <sys/ioctl.h>
47
 
#include <termios.h>
48
 
#include <unistd.h>
49
 
 
50
 
static int readchar(int fd, unsigned char *c, int timeout)
51
 
{
52
 
        struct timeval tv;
53
 
        fd_set set;
54
 
 
55
 
        tv.tv_sec = 0;
56
 
        tv.tv_usec = timeout * 1000;
57
 
 
58
 
        FD_ZERO(&set);
59
 
        FD_SET(fd, &set);
60
 
 
61
 
        if (!select(fd + 1, &set, NULL, NULL, &tv))
62
 
                return -1;
63
 
 
64
 
        if (read(fd, c, 1) != 1)
65
 
                return -1;
66
 
 
67
 
        return 0;
68
 
}
69
 
 
70
 
static void setline(int fd, int flags, int speed)
71
 
{
72
 
        struct termios t;
73
 
 
74
 
        tcgetattr(fd, &t);
75
 
 
76
 
        t.c_cflag = flags | CREAD | HUPCL | CLOCAL;
77
 
        t.c_iflag = IGNBRK | IGNPAR;
78
 
        t.c_oflag = 0;
79
 
        t.c_lflag = 0;
80
 
        t.c_cc[VMIN ] = 1;
81
 
        t.c_cc[VTIME] = 0;
82
 
 
83
 
        cfsetispeed(&t, speed);
84
 
        cfsetospeed(&t, speed);
85
 
 
86
 
        tcsetattr(fd, TCSANOW, &t);
87
 
}
88
 
 
89
 
static int logitech_command(int fd, char *c)
90
 
{
91
 
        int i;
92
 
        unsigned char d;
93
 
 
94
 
        for (i = 0; c[i]; i++) {
95
 
                write(fd, c + i, 1);
96
 
                if (readchar(fd, &d, 1000))
97
 
                        return -1;
98
 
                if (c[i] != d)
99
 
                        return -1;
100
 
        }
101
 
        return 0;
102
 
}
103
 
 
104
 
static int magellan_init(int fd, unsigned long *id, unsigned long *extra)
105
 
{
106
 
        write(fd, "m3\rpBB\rz\r", 9);
107
 
        return 0;
108
 
}
109
 
 
110
 
static int warrior_init(int fd, unsigned long *id, unsigned long *extra)
111
 
{
112
 
        if (logitech_command(fd, "*S"))
113
 
                return -1;
114
 
 
115
 
        setline(fd, CS8, B4800);
116
 
        return 0;
117
 
}
118
 
 
119
 
static int spaceball_waitchar(int fd, unsigned char c, char *d,
120
 
                                int timeout)
121
 
{
122
 
        unsigned char b = 0;
123
 
 
124
 
        while (!readchar(fd, &b, timeout)) {
125
 
                if (b == 0x0a)
126
 
                        continue;
127
 
                *d++ = b;
128
 
                if (b == c)
129
 
                        break;
130
 
        }
131
 
 
132
 
        *d = 0;
133
 
 
134
 
        return -(b != c);
135
 
}
136
 
 
137
 
static int spaceball_waitcmd(int fd, char c, char *d)
138
 
{
139
 
        int i;
140
 
 
141
 
        for (i = 0; i < 8; i++) {
142
 
                if (spaceball_waitchar(fd, 0x0d, d, 1000))
143
 
                        return -1;
144
 
                if (d[0] == c)
145
 
                        return 0;
146
 
        }
147
 
 
148
 
        return -1;
149
 
}
150
 
 
151
 
static int spaceball_cmd(int fd, char *c, char *d)
152
 
{
153
 
        int i;
154
 
 
155
 
        for (i = 0; c[i]; i++)
156
 
                write(fd, c + i, 1);
157
 
        write(fd, "\r", 1);
158
 
 
159
 
        i = spaceball_waitcmd(fd, toupper(c[0]), d);
160
 
 
161
 
        return i;
162
 
}
163
 
 
164
 
#define SPACEBALL_1003          1
165
 
#define SPACEBALL_2003B         3
166
 
#define SPACEBALL_2003C         4
167
 
#define SPACEBALL_3003C         7
168
 
#define SPACEBALL_4000FLX       8
169
 
#define SPACEBALL_4000FLX_L     9
170
 
 
171
 
static int spaceball_init(int fd, unsigned long *id, unsigned long *extra)
172
 
{
173
 
        char r[64];
174
 
 
175
 
        if (spaceball_waitchar(fd, 0x11, r, 4000) ||
176
 
            spaceball_waitchar(fd, 0x0d, r, 1000))
177
 
                return -1;
178
 
 
179
 
        if (spaceball_waitcmd(fd, '@', r))
180
 
                return -1;
181
 
 
182
 
        if (strncmp("@1 Spaceball alive", r, 18))
183
 
                return -1;
184
 
 
185
 
        if (spaceball_waitcmd(fd, '@', r))
186
 
                return -1;
187
 
 
188
 
        if (spaceball_cmd(fd, "hm", r))
189
 
                return -1;
190
 
 
191
 
        if (!strncmp("Hm2003B", r, 7))
192
 
                *id = SPACEBALL_2003B;
193
 
        if (!strncmp("Hm2003C", r, 7))
194
 
                *id = SPACEBALL_2003C;
195
 
        if (!strncmp("Hm3003C", r, 7))
196
 
                *id = SPACEBALL_3003C;
197
 
 
198
 
        if (!strncmp("HvFirmware", r, 10)) {
199
 
 
200
 
                if (spaceball_cmd(fd, "\"", r))
201
 
                        return -1;
202
 
 
203
 
                if (strncmp("\"1 Spaceball 4000 FLX", r, 21))
204
 
                        return -1;
205
 
 
206
 
                if (spaceball_waitcmd(fd, '"', r))
207
 
                        return -1;
208
 
 
209
 
                if (strstr(r, " L "))
210
 
                        *id = SPACEBALL_4000FLX_L;
211
 
                else
212
 
                        *id = SPACEBALL_4000FLX;
213
 
 
214
 
                if (spaceball_waitcmd(fd, '"', r))
215
 
                        return -1;
216
 
 
217
 
                if (spaceball_cmd(fd, "YS", r))
218
 
                        return -1;
219
 
 
220
 
                if (spaceball_cmd(fd, "M", r))
221
 
                        return -1;
222
 
 
223
 
                return 0;
224
 
        }
225
 
 
226
 
        if (spaceball_cmd(fd, "P@A@A", r) ||
227
 
            spaceball_cmd(fd, "FT@", r)   ||
228
 
            spaceball_cmd(fd, "MSS", r))
229
 
                return -1;
230
 
 
231
 
        return 0;
232
 
}
233
 
 
234
 
static int stinger_init(int fd, unsigned long *id, unsigned long *extra)
235
 
{
236
 
        int i;
237
 
        unsigned char c;
238
 
        unsigned char *response = (unsigned char *)"\r\n0600520058C272";
239
 
 
240
 
        if (write(fd, " E5E5", 5) != 5)         /* Enable command */
241
 
                return -1;
242
 
 
243
 
        for (i = 0; i < 16; i++)                /* Check for Stinger */
244
 
                if (readchar(fd, &c, 200) || c != response[i])
245
 
                        return -1;
246
 
 
247
 
        return 0;
248
 
}
249
 
 
250
 
static int mzp_init(int fd, unsigned long *id, unsigned long *extra)
251
 
{
252
 
        if (logitech_command(fd, "*X*q"))
253
 
                return -1;
254
 
 
255
 
        setline(fd, CS8, B9600);
256
 
        return 0;
257
 
}
258
 
 
259
 
static int newton_init(int fd, unsigned long *id, unsigned long *extra)
260
 
{
261
 
        int i;
262
 
        unsigned char c;
263
 
        unsigned char response[35] = {
264
 
                0x16, 0x10, 0x02, 0x64, 0x5f, 0x69, 0x64, 0x00,
265
 
                0x00, 0x00, 0x0c, 0x6b, 0x79, 0x62, 0x64, 0x61,
266
 
                0x70, 0x70, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x6e,
267
 
                0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10,
268
 
                0x03, 0xdd, 0xe7
269
 
        };
270
 
 
271
 
        for (i = 0; i < sizeof(response); i++)
272
 
                if (readchar(fd, &c, 400) || c != response[i])
273
 
                        return -1;
274
 
 
275
 
        return 0;
276
 
}
277
 
 
278
 
static int twiddler_init(int fd, unsigned long *id, unsigned long *extra)
279
 
{
280
 
        unsigned char c[10];
281
 
        int count, line;
282
 
 
283
 
        /* Turn DTR off, otherwise the Twiddler won't send any data. */
284
 
        if (ioctl(fd, TIOCMGET, &line))
285
 
                return -1;
286
 
        line &= ~TIOCM_DTR;
287
 
        if (ioctl(fd, TIOCMSET, &line))
288
 
                return -1;
289
 
 
290
 
        /*
291
 
         * Check whether the device on the serial line is the Twiddler.
292
 
         *
293
 
         * The Twiddler sends data packets of 5 bytes which have the following
294
 
         * properties: the MSB is 0 on the first and 1 on all other bytes, and
295
 
         * the high order nibble of the last byte is always 0x8.
296
 
         *
297
 
         * We read and check two of those 5 byte packets to be sure that we
298
 
         * are indeed talking to a Twiddler.
299
 
         */
300
 
 
301
 
        /* Read at most 5 bytes until we find one with the MSB set to 0 */
302
 
        for (count = 0; count < 5; count++) {
303
 
                if (readchar(fd, c, 500))
304
 
                        return -1;
305
 
                if ((c[0] & 0x80) == 0)
306
 
                        break;
307
 
        }
308
 
 
309
 
        if (count == 5) {
310
 
                /* Could not find header byte in data stream */
311
 
                return -1;
312
 
        }
313
 
 
314
 
        /* Read remaining 4 bytes plus the full next data packet */
315
 
        for (count = 1; count < 10; count++)
316
 
                if (readchar(fd, c + count, 500))
317
 
                        return -1;
318
 
 
319
 
        /* Check whether the bytes of both data packets obey the rules */
320
 
        for (count = 1; count < 10; count++) {
321
 
                if ((count % 5 == 0 && (c[count] & 0x80) != 0x00) ||
322
 
                    (count % 5 == 4 && (c[count] & 0xF0) != 0x80) ||
323
 
                    (count % 5 != 0 && (c[count] & 0x80) != 0x80)) {
324
 
                        /* Invalid byte in data packet */
325
 
                        return -1;
326
 
                }
327
 
        }
328
 
 
329
 
        return 0;
330
 
}
331
 
 
332
 
static int fujitsu_init(int fd, unsigned long *id, unsigned long *extra)
333
 
{
334
 
        unsigned char cmd, data;
335
 
 
336
 
        /* Wake up the touchscreen */
337
 
        cmd = 0xff; /* Dummy data */;
338
 
        if (write(fd, &cmd, 1) != 1)
339
 
                return -1;
340
 
 
341
 
        /* Wait to settle down */
342
 
        usleep(100 * 1000); /* 100 ms */
343
 
 
344
 
        /* Reset the touchscreen */
345
 
        cmd = 0x81; /* Cold reset */
346
 
        if (write(fd, &cmd, 1) != 1)
347
 
                return -1;
348
 
 
349
 
        /* Read ACK */
350
 
        if (readchar(fd, &data, 100) || (data & 0xbf) != 0x90)
351
 
                return -1;
352
 
 
353
 
        /* Read status */
354
 
        if (readchar(fd, &data, 100) || data != 0x00)
355
 
                return -1;
356
 
 
357
 
        return 0;
358
 
}
359
 
 
360
 
static int t213_init(int fd, unsigned long *id, unsigned long *extra)
361
 
{
362
 
        char cmd[]={0x0a,1,'A'};
363
 
        int count=10;
364
 
        int state=0;
365
 
        unsigned char data;
366
 
 
367
 
        /*
368
 
         * In case the controller is in "ELO-mode" send a few times
369
 
         * the check active packet to force it into the documented
370
 
         * touchkit mode.
371
 
         */
372
 
        while (count>0) {
373
 
                if (write(fd, &cmd, 3) != 3)
374
 
                        return -1;
375
 
                while (!readchar(fd, &data, 100)) {
376
 
                        switch (state) {
377
 
                        case 0:
378
 
                                if (data==0x0a) {
379
 
                                        state=1;
380
 
                                }
381
 
                                break;
382
 
                        case 1:
383
 
                                if (data==1) {
384
 
                                        state=2;
385
 
                                } else if (data!=0x0a) {
386
 
                                        state=0;
387
 
                                }
388
 
                                break;
389
 
                        case 2:
390
 
                                if (data=='A') {
391
 
                                        return 0;
392
 
                                } else if (data==0x0a) {
393
 
                                        state=1;
394
 
                                } else {
395
 
                                        state=0;
396
 
                                }
397
 
                                break;
398
 
                        }
399
 
                                        
400
 
                }
401
 
                count--;
402
 
        }
403
 
        return -1;
404
 
}
405
 
 
406
 
static int dump_init(int fd, unsigned long *id, unsigned long *extra)
407
 
{
408
 
        unsigned char c, o = 0;
409
 
 
410
 
        c = 0x80;
411
 
 
412
 
        if (write(fd, &c, 1) != 1)         /* Enable command */
413
 
                return -1;
414
 
 
415
 
        while (1)
416
 
                if (!readchar(fd, &c, 1)) {
417
 
                        printf("%02x (%c) ", c, ((c > 32) && (c < 127)) ? c : 'x');
418
 
                        o = 1;
419
 
                } else {
420
 
                        if (o) {
421
 
                                printf("\n");
422
 
                                o = 0;
423
 
                        }
424
 
                }
425
 
}
426
 
 
427
 
struct input_types {
428
 
        const char *name;
429
 
        const char *name2;
430
 
        const char *desc;
431
 
        int speed;
432
 
        int flags;
433
 
        unsigned long type;
434
 
        unsigned long id;
435
 
        unsigned long extra;
436
 
        int flush;
437
 
        int (*init)(int fd, unsigned long *id, unsigned long *extra);
438
 
};
439
 
 
440
 
static struct input_types input_types[] = {
441
 
{ "--sunkbd",           "-skb",         "Sun Type 4 and Type 5 keyboards",
442
 
        B1200, CS8,
443
 
        SERIO_SUNKBD,           0x00,   0x00,   1,      NULL },
444
 
{ "--lkkbd",            "-lk",          "DEC LK201 / LK401 keyboards",
445
 
        B4800, CS8|CSTOPB,
446
 
        SERIO_LKKBD,            0x00,   0x00,   1,      NULL },
447
 
{ "--vsxxx-aa",         "-vs",
448
 
                        "DEC VSXXX-AA / VSXXX-GA mouse and VSXXX-A tablet",
449
 
        B4800, CS8|CSTOPB|PARENB|PARODD,
450
 
        SERIO_VSXXXAA,          0x00,   0x00,   1,      NULL },
451
 
{ "--spaceorb",         "-orb",         "SpaceOrb 360 / SpaceBall Avenger",
452
 
        B9600, CS8,
453
 
        SERIO_SPACEORB,         0x00,   0x00,   1,      NULL },
454
 
{ "--spaceball",        "-sbl",         "SpaceBall 2003 / 3003 / 4000 FLX",
455
 
        B9600, CS8,
456
 
        SERIO_SPACEBALL,        0x00,   0x00,   0,      spaceball_init },
457
 
{ "--magellan",         "-mag",         "Magellan / SpaceMouse",
458
 
        B9600, CS8 | CSTOPB | CRTSCTS,
459
 
        SERIO_MAGELLAN,         0x00,   0x00,   1,      magellan_init },
460
 
{ "--warrior",          "-war",         "WingMan Warrior",
461
 
        B1200, CS7 | CSTOPB,
462
 
        SERIO_WARRIOR,          0x00,   0x00,   1,      warrior_init },
463
 
{ "--stinger",          "-sting",       "Gravis Stinger",
464
 
        B1200, CS8,
465
 
        SERIO_STINGER,          0x00,   0x00,   1,      stinger_init },
466
 
{ "--mousesystems",     "-msc",         "3-button Mouse Systems mouse",
467
 
        B1200, CS8,
468
 
        SERIO_MSC,              0x00,   0x01,   1,      NULL },
469
 
{ "--sunmouse",         "-sun",         "3-button Sun mouse",
470
 
        B1200, CS8,
471
 
        SERIO_SUN,              0x00,   0x01,   1,      NULL },
472
 
{ "--microsoft",        "-bare",        "2-button Microsoft mouse",
473
 
        B1200, CS7,
474
 
        SERIO_MS,               0x00,   0x00,   1,      NULL },
475
 
{ "--mshack",           "-ms",          "3-button mouse in Microsoft mode",
476
 
        B1200, CS7,
477
 
        SERIO_MS,               0x00,   0x01,   1,      NULL },
478
 
{ "--mouseman",         "-mman",        "3-button Logitech / Genius mouse",
479
 
        B1200, CS7,
480
 
        SERIO_MP,               0x00,   0x01,   1,      NULL },
481
 
{ "--intellimouse",     "-ms3",         "Microsoft IntelliMouse",
482
 
        B1200, CS7,
483
 
        SERIO_MZ,               0x00,   0x11,   1,      NULL },
484
 
{ "--mmwheel",          "-mmw",
485
 
                        "Logitech mouse with 4-5 buttons or a wheel",
486
 
        B1200, CS7 | CSTOPB,
487
 
        SERIO_MZP,              0x00,   0x13,   1,      mzp_init },
488
 
{ "--iforce",           "-ifor",        "I-Force joystick or wheel",
489
 
        B38400, CS8,
490
 
        SERIO_IFORCE,           0x00,   0x00,   0,      NULL },
491
 
{ "--newtonkbd",        "-newt",        "Newton keyboard",
492
 
        B9600, CS8,
493
 
        SERIO_NEWTON,           0x00,   0x00,   1,      newton_init },
494
 
{ "--h3600ts",          "-ipaq",        "Ipaq h3600 touchscreen",
495
 
        B115200, CS8,
496
 
        SERIO_H3600,            0x00,   0x00,   0,      NULL },
497
 
{ "--stowawaykbd",      "-ipaqkbd",     "Stowaway keyboard",
498
 
        B115200, CS8,
499
 
        SERIO_STOWAWAY,         0x00,   0x00,   1,      NULL },
500
 
{ "--ps2serkbd",        "-ps2ser",      "PS/2 via serial keyboard",
501
 
        B1200, CS8,
502
 
        SERIO_PS2SER,           0x00,   0x00,   1,      NULL },
503
 
{ "--twiddler",         "-twid",        "Handykey Twiddler chording keyboard",
504
 
        B2400, CS8,
505
 
        SERIO_TWIDKBD,          0x00,   0x00,   0,      twiddler_init },
506
 
{ "--twiddler-joy",     "-twidjoy",     "Handykey Twiddler used as a joystick",
507
 
        B2400, CS8,
508
 
        SERIO_TWIDJOY,          0x00,   0x00,   0,      twiddler_init },
509
 
{ "--elotouch",         "-elo",         "ELO touchscreen, 10-byte mode",
510
 
        B9600, CS8 | CRTSCTS,
511
 
        SERIO_ELO,              0x00,   0x00,   0,      NULL },
512
 
{ "--elo4002",          "-elo6b",       "ELO touchscreen, 6-byte mode",
513
 
        B9600, CS8 | CRTSCTS,
514
 
        SERIO_ELO,              0x01,   0x00,   0,      NULL },
515
 
{ "--elo271-140",       "-elo4b",       "ELO touchscreen, 4-byte mode",
516
 
        B9600, CS8 | CRTSCTS,
517
 
        SERIO_ELO,              0x02,   0x00,   0,      NULL },
518
 
{ "--elo261-280",       "-elo3b",       "ELO Touchscreen, 3-byte mode",
519
 
        B9600, CS8 | CRTSCTS,
520
 
        SERIO_ELO,              0x03,   0x00,   0,      NULL },
521
 
{ "--mtouch",           "-mtouch",      "MicroTouch (3M) touchscreen",
522
 
        B9600, CS8 | CRTSCTS,
523
 
        SERIO_MICROTOUCH,       0x00,   0x00,   0,      NULL },
524
 
{ "--touchit213",       "-t213",        "Sahara Touch-iT213 Tablet PC",
525
 
        B9600, CS8,
526
 
        SERIO_TOUCHIT213,       0x00,   0x00,   0,      t213_init },
527
 
{ "--touchright",       "-tr",  "Touchright serial touchscreen",
528
 
        B9600, CS8 | CRTSCTS,
529
 
        SERIO_TOUCHRIGHT,       0x00,   0x00,   0,      NULL },
530
 
{ "--touchwin",         "-tw",  "Touchwindow serial touchscreen",
531
 
        B4800, CS8 | CRTSCTS,
532
 
        SERIO_TOUCHWIN,         0x00,   0x00,   0,      NULL },
533
 
{ "--penmount",         "-pm",  "Penmount touchscreen",
534
 
        B19200, CS8 | CRTSCTS,
535
 
        SERIO_PENMOUNT,         0x00,   0x00,   0,      NULL },
536
 
{ "--fujitsu",          "-fjt", "Fujitsu serial touchscreen",
537
 
        B9600, CS8,
538
 
        SERIO_FUJITSU,          0x00,   0x00,   1,      fujitsu_init },
539
 
{ "--dump",             "-dump",        "Just enable device",
540
 
        B2400, CS8,
541
 
        0,                      0x00,   0x00,   0,      dump_init },
542
 
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL }
543
 
};
544
 
 
545
 
static void show_help(void)
546
 
{
547
 
        struct input_types *type;
548
 
 
549
 
        puts("");
550
 
        puts("Usage: inputattach [--daemon] [--always] [--noinit] <mode> <device>");
551
 
        puts("");
552
 
        puts("Modes:");
553
 
 
554
 
        for (type = input_types; type->name; type++)
555
 
                printf("  %-16s %-8s  %s\n",
556
 
                        type->name, type->name2, type->desc);
557
 
 
558
 
        puts("");
559
 
}
560
 
 
561
 
int main(int argc, char **argv)
562
 
{
563
 
        unsigned long devt;
564
 
        int ldisc;
565
 
        struct input_types *type = NULL;
566
 
        const char *device = NULL;
567
 
        int daemon_mode = 0;
568
 
        int need_device = 0;
569
 
        unsigned long id, extra;
570
 
        int fd;
571
 
        int i;
572
 
        unsigned char c;
573
 
        int retval;
574
 
        int ignore_init_res = 0;
575
 
        int no_init = 0;
576
 
 
577
 
        for (i = 1; i < argc; i++) {
578
 
                if (!strcasecmp(argv[i], "--help")) {
579
 
                        show_help();
580
 
                        return EXIT_SUCCESS;
581
 
                } else if (!strcasecmp(argv[i], "--daemon")) {
582
 
                        daemon_mode = 1;
583
 
                } else if (!strcasecmp(argv[i], "--always")) {
584
 
                        ignore_init_res = 1;
585
 
                } else if (!strcasecmp(argv[i], "--noinit")) {
586
 
                        no_init = 1;
587
 
                } else if (need_device) {
588
 
                        device = argv[i];
589
 
                        need_device = 0;
590
 
                } else {
591
 
                        if (type && type->name) {
592
 
                                fprintf(stderr,
593
 
                                        "inputattach: '%s' - "
594
 
                                        "only one mode allowed\n", argv[i]);
595
 
                                return EXIT_FAILURE;
596
 
                        }
597
 
                        for (type = input_types; type->name; type++) {
598
 
                                if (!strcasecmp(argv[i], type->name) ||
599
 
                                    !strcasecmp(argv[i], type->name2)) {
600
 
                                        break;
601
 
                                }
602
 
                        }
603
 
                        if (!type->name) {
604
 
                                fprintf(stderr,
605
 
                                        "inputattach: invalid mode '%s'\n",
606
 
                                        argv[i]);
607
 
                                return EXIT_FAILURE;
608
 
                        }
609
 
                        need_device = 1;
610
 
                }
611
 
        }
612
 
 
613
 
        if (!type || !type->name) {
614
 
                fprintf(stderr, "inputattach: must specify mode\n");
615
 
                return EXIT_FAILURE;
616
 
        }
617
 
 
618
 
        if (need_device) {
619
 
                fprintf(stderr, "inputattach: must specify device\n");
620
 
                return EXIT_FAILURE;
621
 
        }
622
 
 
623
 
        fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
624
 
        if (fd < 0) {
625
 
                fprintf(stderr, "inputattach: '%s' - %s\n",
626
 
                        device, strerror(errno));
627
 
                return 1;
628
 
        }
629
 
 
630
 
        setline(fd, type->flags, type->speed);
631
 
 
632
 
        if (type->flush)
633
 
                while (!readchar(fd, &c, 100))
634
 
                        /* empty */;
635
 
 
636
 
        id = type->id;
637
 
        extra = type->extra;
638
 
 
639
 
        if (type->init && !no_init) {
640
 
                if (type->init(fd, &id, &extra)) {
641
 
                        if (ignore_init_res) {
642
 
                                fprintf(stderr, "inputattach: ignored device initialization failure\n");
643
 
                        } else {
644
 
                                fprintf(stderr, "inputattach: device initialization failed\n");
645
 
                                return EXIT_FAILURE;
646
 
                        }
647
 
                }
648
 
        }
649
 
 
650
 
        ldisc = N_MOUSE;
651
 
        if (ioctl(fd, TIOCSETD, &ldisc)) {
652
 
                fprintf(stderr, "inputattach: can't set line discipline\n");
653
 
                return EXIT_FAILURE;
654
 
        }
655
 
 
656
 
        devt = type->type | (id << 8) | (extra << 16);
657
 
 
658
 
        if (ioctl(fd, SPIOCSTYPE, &devt)) {
659
 
                fprintf(stderr, "inputattach: can't set device type\n");
660
 
                return EXIT_FAILURE;
661
 
        }
662
 
 
663
 
        retval = EXIT_SUCCESS;
664
 
        if (daemon_mode && daemon(0, 0) < 0) {
665
 
                perror("inputattach");
666
 
                retval = EXIT_FAILURE;
667
 
        }
668
 
 
669
 
        read(fd, NULL, 0);
670
 
 
671
 
        ldisc = 0;
672
 
        ioctl(fd, TIOCSETD, &ldisc);
673
 
        close(fd);
674
 
 
675
 
        return retval;
676
 
}