VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xmouse/xorg70/pnp.c@ 7261

Last change on this file since 7261 was 7261, checked in by vboxsync, 17 years ago

Additions/x11: ifdef-ed some unnecessary debug logging in the mouse drivers

  • Property svn:eol-style set to native
File size: 19.8 KB
Line 
1/*
2 * Copyright 1998 by Kazutaka YOKOTA <[email protected]>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Kazutaka YOKOTA not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Kazutaka YOKOTA makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
13 *
14 * KAZUTAKA YOKOTA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KAZUTAKA YOKOTA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#define NEED_EVENTS
28#include <X11/X.h>
29#include <X11/Xproto.h>
30#include "inputstr.h"
31#include "scrnintstr.h"
32#include "xf86.h"
33#include "xf86Priv.h"
34#include "xf86Xinput.h"
35#include "xf86_OSproc.h"
36#include "xf86OSmouse.h"
37#include "xf86_ansic.h"
38#include "mouse.h"
39#include "mousePriv.h"
40
41#ifdef MOUSEINITDEBUG
42# define DEBUG
43# define EXTMOUSEDEBUG
44#endif
45
46/* serial PnP ID string */
47typedef struct {
48 int revision; /* PnP revision, 100 for 1.00 */
49 char *eisaid; /* EISA ID including mfr ID and product ID */
50 char *serial; /* serial No, optional */
51 char *class; /* device class, optional */
52 char *compat; /* list of compatible drivers, optional */
53 char *description; /* product description, optional */
54 int neisaid; /* length of the above fields... */
55 int nserial;
56 int nclass;
57 int ncompat;
58 int ndescription;
59} pnpid_t;
60
61/* symbol table entry */
62typedef struct {
63 char *name;
64 MouseProtocolID val;
65} symtab_t;
66
67/* PnP EISA/product IDs */
68static symtab_t pnpprod[] = {
69 { "KML0001", PROT_THINKING }, /* Kensignton ThinkingMouse */
70 { "MSH0001", PROT_IMSERIAL }, /* MS IntelliMouse */
71 { "MSH0004", PROT_IMSERIAL }, /* MS IntelliMouse TrackBall */
72 { "KYEEZ00", PROT_MS }, /* Genius EZScroll */
73 { "KYE0001", PROT_MS }, /* Genius PnP Mouse */
74 { "KYE0002", PROT_MS }, /* MouseSystem (Genius?) SmartScroll */
75 { "KYE0003", PROT_IMSERIAL }, /* Genius NetMouse */
76 { "LGI800C", PROT_IMSERIAL }, /* Logitech MouseMan (4 button model) */
77 { "LGI8033", PROT_IMSERIAL }, /* Logitech Cordless MouseMan Wheel */
78 { "LGI8050", PROT_IMSERIAL }, /* Logitech MouseMan+ */
79 { "LGI8051", PROT_IMSERIAL }, /* Logitech FirstMouse+ */
80 { "LGI8001", PROT_LOGIMAN }, /* Logitech serial */
81 { "A4W0005", PROT_IMSERIAL }, /* A4 Tech 4D/4D+ Mouse */
82 { "PEC9802", PROT_IMSERIAL }, /* 8D Scroll Mouse */
83
84 { "PNP0F00", PROT_BM }, /* MS bus */
85 { "PNP0F01", PROT_MS }, /* MS serial */
86 { "PNP0F02", PROT_BM }, /* MS InPort */
87 { "PNP0F03", PROT_PS2 }, /* MS PS/2 */
88 /*
89 * EzScroll returns PNP0F04 in the compatible device field; but it
90 * doesn't look compatible... XXX
91 */
92 { "PNP0F04", PROT_MSC }, /* MouseSystems */
93 { "PNP0F05", PROT_MSC }, /* MouseSystems */
94#ifdef notyet
95 { "PNP0F06", PROT_??? }, /* Genius Mouse */
96 { "PNP0F07", PROT_??? }, /* Genius Mouse */
97#endif
98 { "PNP0F08", PROT_LOGIMAN }, /* Logitech serial */
99 { "PNP0F09", PROT_MS }, /* MS BallPoint serial */
100 { "PNP0F0A", PROT_MS }, /* MS PnP serial */
101 { "PNP0F0B", PROT_MS }, /* MS PnP BallPoint serial */
102 { "PNP0F0C", PROT_MS }, /* MS serial comatible */
103 { "PNP0F0D", PROT_BM }, /* MS InPort comatible */
104 { "PNP0F0E", PROT_PS2 }, /* MS PS/2 comatible */
105 { "PNP0F0F", PROT_MS }, /* MS BallPoint comatible */
106#ifdef notyet
107 { "PNP0F10", PROT_??? }, /* TI QuickPort */
108#endif
109 { "PNP0F11", PROT_BM }, /* MS bus comatible */
110 { "PNP0F12", PROT_PS2 }, /* Logitech PS/2 */
111 { "PNP0F13", PROT_PS2 }, /* PS/2 */
112#ifdef notyet
113 { "PNP0F14", PROT_??? }, /* MS Kids Mouse */
114#endif
115 { "PNP0F15", PROT_BM }, /* Logitech bus */
116#ifdef notyet
117 { "PNP0F16", PROT_??? }, /* Logitech SWIFT */
118#endif
119 { "PNP0F17", PROT_LOGIMAN }, /* Logitech serial compat */
120 { "PNP0F18", PROT_BM }, /* Logitech bus compatible */
121 { "PNP0F19", PROT_PS2 }, /* Logitech PS/2 compatible */
122#ifdef notyet
123 { "PNP0F1A", PROT_??? }, /* Logitech SWIFT compatible */
124 { "PNP0F1B", PROT_??? }, /* HP Omnibook */
125 { "PNP0F1C", PROT_??? }, /* Compaq LTE TrackBall PS/2 */
126 { "PNP0F1D", PROT_??? }, /* Compaq LTE TrackBall serial */
127 { "PNP0F1E", PROT_??? }, /* MS Kids Trackball */
128#endif
129 { NULL, PROT_UNKNOWN },
130};
131
132static const char *pnpSerial[] = {
133 "BaudRate", "1200",
134 "DataBits", "7",
135 "StopBits", "1",
136 "Parity", "None",
137 "FlowControl", "None",
138 "VTime", "0",
139 "VMin", "1",
140 NULL
141};
142
143static int pnpgets(InputInfoPtr, char *, Bool *prePNP);
144static int pnpparse(InputInfoPtr, pnpid_t *, char *, int);
145static MouseProtocolID prepnpparse(InputInfoPtr pInfo, char *buf);
146static symtab_t *pnpproto(pnpid_t *);
147static symtab_t *gettoken(symtab_t *, char *, int);
148static MouseProtocolID getPs2ProtocolPnP(InputInfoPtr pInfo);
149static MouseProtocolID probePs2ProtocolPnP(InputInfoPtr pInfo);
150
151static MouseProtocolID
152MouseGetSerialPnpProtocol(InputInfoPtr pInfo)
153{
154 char buf[256]; /* PnP ID string may be up to 256 bytes long */
155 pnpid_t pnpid;
156 symtab_t *t;
157 int len;
158 Bool prePNP;
159
160 if ((len = pnpgets(pInfo, buf, &prePNP)) > 0)
161 {
162 if (!prePNP) {
163 if (pnpparse(pInfo, &pnpid, buf, len) &&
164 (t = pnpproto(&pnpid)) != NULL) {
165 xf86MsgVerb(X_INFO, 2, "%s: PnP-detected protocol ID: %d\n",
166 pInfo->name, t->val);
167 return (t->val);
168 }
169 } else
170 return prepnpparse(pInfo,buf);
171 }
172 return PROT_UNKNOWN;
173}
174
175MouseProtocolID
176MouseGetPnpProtocol(InputInfoPtr pInfo)
177{
178 MouseDevPtr pMse = pInfo->private;
179 mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
180 MouseProtocolID val;
181 CARD32 last;
182
183 if ((val = MouseGetSerialPnpProtocol(pInfo)) != PROT_UNKNOWN) {
184 if (val == MouseGetSerialPnpProtocol(pInfo))
185 return val;
186 }
187
188#if 1
189 last = mPriv->pnpLast;
190 mPriv->pnpLast = currentTime.milliseconds;
191
192 if (last) {
193 if (last - currentTime.milliseconds < 100
194 || (mPriv->disablePnPauto
195 && (last - currentTime.milliseconds < 10000))) {
196#ifdef EXTMOUSEDEBUG
197 xf86ErrorF("Mouse: Disabling PnP\n");
198#endif
199 mPriv->disablePnPauto = TRUE;
200 return PROT_UNKNOWN;
201 }
202 }
203
204#ifdef EXTMOUSEDEBUG
205 if (mPriv->disablePnPauto)
206 xf86ErrorF("Mouse: Enabling PnP\n");
207#endif
208 mPriv->disablePnPauto = FALSE;
209
210 if (mPriv->soft)
211 return getPs2ProtocolPnP(pInfo);
212 else
213 return probePs2ProtocolPnP(pInfo);
214#else
215 return PROT_UNKNOWN;
216#endif
217}
218
219/*
220 * Try to elicit a PnP ID as described in
221 * Microsoft, Hayes: "Plug and Play External COM Device Specification,
222 * rev 1.00", 1995.
223 *
224 * The routine does not fully implement the COM Enumerator as per Section
225 * 2.1 of the document. In particular, we don't have idle state in which
226 * the driver software monitors the com port for dynamic connection or
227 * removal of a device at the port, because `moused' simply quits if no
228 * device is found.
229 *
230 * In addition, as PnP COM device enumeration procedure slightly has
231 * changed since its first publication, devices which follow earlier
232 * revisions of the above spec. may fail to respond if the rev 1.0
233 * procedure is used. XXX
234 */
235static int
236pnpgets(InputInfoPtr pInfo, char *buf, Bool *prePNP)
237{
238 int i;
239 char c;
240 pointer pnpOpts;
241
242#if 0
243 /*
244 * This is the procedure described in rev 1.0 of PnP COM device spec.
245 * Unfortunately, some devices which comform to earlier revisions of
246 * the spec gets confused and do not return the ID string...
247 */
248
249 /* port initialization (2.1.2) */
250 if ((i = xf86GetSerialModemState(pInfo->fd)) == -1)
251 return 0;
252 i |= XF86_M_DTR; /* DTR = 1 */
253 i &= ~XF86_M_RTS; /* RTS = 0 */
254 if (xf86SetSerialModemState(pInfo->fd, i) == -1)
255 goto disconnect_idle;
256 usleep(200000);
257 if ((i = xf86GetSerialModemState(pInfo->fd)) == -1 ||
258 (i & XF86_M_DSR) == 0)
259 goto disconnect_idle;
260
261 /* port setup, 1st phase (2.1.3) */
262 pnpOpts = xf86OptionListCreate(pnpSerial, -1, 1);
263 xf86SetSerial(pInfo->fd, pnpOpts);
264 i = TIOCM_DTR | TIOCM_RTS; /* DTR = 0, RTS = 0 */
265 xf86SerialModemClearBits(pInfo->fd, i);
266 usleep(200000);
267 i = TIOCM_DTR; /* DTR = 1, RTS = 0 */
268 xf86SerialModemSetBits(pInfo->fd, i);
269 usleep(200000);
270
271 /* wait for response, 1st phase (2.1.4) */
272 xf86FlushInput(pInfo->fd);
273 i = TIOCM_RTS; /* DTR = 1, RTS = 1 */
274 xf86SerialModemSetBits(pInfo->fd, i);
275
276 /* try to read something */
277 if (xf86WaitForInput(pInfo->fd, 200000) <= 0) {
278
279 /* port setup, 2nd phase (2.1.5) */
280 i = TIOCM_DTR | TIOCM_RTS; /* DTR = 0, RTS = 0 */
281 xf86SerialModemClearBits(pInfo->fd, i);
282 usleep(200000);
283
284 /* wait for respose, 2nd phase (2.1.6) */
285 xf86FlushInput(pInfo->fd);
286 i = TIOCM_DTR | TIOCM_RTS; /* DTR = 1, RTS = 1 */
287 xf86SerialModemSetBits(pInfo->fd, i);
288
289 /* try to read something */
290 if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
291 goto connect_idle;
292 }
293#else
294 /*
295 * This is a simplified procedure; it simply toggles RTS.
296 */
297
298 if ((i = xf86GetSerialModemState(pInfo->fd)) == -1)
299 return 0;
300 i |= XF86_M_DTR; /* DTR = 1 */
301 i &= ~XF86_M_RTS; /* RTS = 0 */
302 if (xf86SetSerialModemState(pInfo->fd, i) == -1)
303 goto disconnect_idle;
304 usleep(200000);
305
306 pnpOpts = xf86OptionListCreate(pnpSerial, -1, 1);
307 xf86SetSerial(pInfo->fd, pnpOpts);
308
309 /* wait for respose */
310 xf86FlushInput(pInfo->fd);
311 i = XF86_M_DTR | XF86_M_RTS; /* DTR = 1, RTS = 1 */
312 xf86SerialModemSetBits(pInfo->fd, i);
313
314 /* try to read something */
315 if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
316 goto connect_idle;
317#endif
318
319 /* collect PnP COM device ID (2.1.7) */
320 i = 0;
321 *prePNP = FALSE;
322
323 usleep(200000); /* the mouse must send `Begin ID' within 200msec */
324 while (xf86ReadSerial(pInfo->fd, &c, 1) == 1) {
325 /* we may see "M", or "M3..." before `Begin ID' */
326 if (c == 'M')
327 *prePNP = TRUE;
328
329 if ((c == 0x08) || (c == 0x28)) { /* Begin ID */
330 *prePNP = FALSE;
331 buf[0] = c;
332 i = 1;
333 break;
334 }
335 if (*prePNP)
336 buf[i++] = c;
337
338 if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
339 break;
340 }
341 if (i <= 0) {
342 /* we haven't seen `Begin ID' in time... */
343 goto connect_idle;
344 }
345 if (*prePNP)
346 return i;
347
348 ++c; /* make it `End ID' */
349 for (;;) {
350 if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
351 break;
352
353 xf86ReadSerial(pInfo->fd, &buf[i], 1);
354 if (buf[i++] == c) /* End ID */
355 break;
356 if (i >= 256)
357 break;
358 }
359 if (buf[i - 1] != c)
360 goto connect_idle;
361 return i;
362
363 /*
364 * According to PnP spec, we should set DTR = 1 and RTS = 0 while
365 * in idle state. But, `moused' shall set DTR = RTS = 1 and proceed,
366 * assuming there is something at the port even if it didn't
367 * respond to the PnP enumeration procedure.
368 */
369disconnect_idle:
370 i = XF86_M_DTR | XF86_M_RTS; /* DTR = 1, RTS = 1 */
371 xf86SerialModemSetBits(pInfo->fd, i);
372connect_idle:
373 return 0;
374}
375
376static int
377pnpparse(InputInfoPtr pInfo, pnpid_t *id, char *buf, int len)
378{
379 char s[3];
380 int offset;
381 int sum = 0;
382 int i, j;
383
384 id->revision = 0;
385 id->eisaid = NULL;
386 id->serial = NULL;
387 id->class = NULL;
388 id->compat = NULL;
389 id->description = NULL;
390 id->neisaid = 0;
391 id->nserial = 0;
392 id->nclass = 0;
393 id->ncompat = 0;
394 id->ndescription = 0;
395
396 offset = 0x28 - buf[0];
397
398 /* calculate checksum */
399 for (i = 0; i < len - 3; ++i) {
400 sum += buf[i];
401 buf[i] += offset;
402 }
403 sum += buf[len - 1];
404 for (; i < len; ++i)
405 buf[i] += offset;
406 xf86MsgVerb(X_INFO, 2, "%s: PnP ID string: `%*.*s'\n", pInfo->name,
407 len, len, buf);
408
409 /* revision */
410 buf[1] -= offset;
411 buf[2] -= offset;
412 id->revision = ((buf[1] & 0x3f) << 6) | (buf[2] & 0x3f);
413 xf86MsgVerb(X_INFO, 2, "%s: PnP rev %d.%02d\n", pInfo->name,
414 id->revision / 100, id->revision % 100);
415
416 /* EISA vender and product ID */
417 id->eisaid = &buf[3];
418 id->neisaid = 7;
419
420 /* option strings */
421 i = 10;
422 if (buf[i] == '\\') {
423 /* device serial # */
424 for (j = ++i; i < len; ++i) {
425 if (buf[i] == '\\')
426 break;
427 }
428 if (i >= len)
429 i -= 3;
430 if (i - j == 8) {
431 id->serial = &buf[j];
432 id->nserial = 8;
433 }
434 }
435 if (buf[i] == '\\') {
436 /* PnP class */
437 for (j = ++i; i < len; ++i) {
438 if (buf[i] == '\\')
439 break;
440 }
441 if (i >= len)
442 i -= 3;
443 if (i > j + 1) {
444 id->class = &buf[j];
445 id->nclass = i - j;
446 }
447 }
448 if (buf[i] == '\\') {
449 /* compatible driver */
450 for (j = ++i; i < len; ++i) {
451 if (buf[i] == '\\')
452 break;
453 }
454 /*
455 * PnP COM spec prior to v0.96 allowed '*' in this field,
456 * it's not allowed now; just ignore it.
457 */
458 if (buf[j] == '*')
459 ++j;
460 if (i >= len)
461 i -= 3;
462 if (i > j + 1) {
463 id->compat = &buf[j];
464 id->ncompat = i - j;
465 }
466 }
467 if (buf[i] == '\\') {
468 /* product description */
469 for (j = ++i; i < len; ++i) {
470 if (buf[i] == ';')
471 break;
472 }
473 if (i >= len)
474 i -= 3;
475 if (i > j + 1) {
476 id->description = &buf[j];
477 id->ndescription = i - j;
478 }
479 }
480
481 /* checksum exists if there are any optional fields */
482 if ((id->nserial > 0) || (id->nclass > 0)
483 || (id->ncompat > 0) || (id->ndescription > 0)) {
484 xf86MsgVerb(X_INFO, 4, "%s: PnP checksum: 0x%02X\n", pInfo->name, sum);
485 sprintf(s, "%02X", sum & 0x0ff);
486 if (strncmp(s, &buf[len - 3], 2) != 0) {
487#if 0
488 /*
489 * Checksum error!!
490 * I found some mice do not comply with the PnP COM device
491 * spec regarding checksum... XXX
492 */
493 return FALSE;
494#endif
495 }
496 }
497
498 return TRUE;
499}
500
501/* We can only identify MS at the moment */
502static MouseProtocolID
503prepnpparse(InputInfoPtr pInfo, char *buf)
504{
505 if (buf[0] == 'M' && buf[1] == '3')
506 return PROT_MS;
507 return PROT_UNKNOWN;
508}
509
510
511static symtab_t *
512pnpproto(pnpid_t *id)
513{
514 symtab_t *t;
515 int i, j;
516
517 if (id->nclass > 0)
518 if (strncmp(id->class, "MOUSE", id->nclass) != 0)
519 /* this is not a mouse! */
520 return NULL;
521
522 if (id->neisaid > 0) {
523 t = gettoken(pnpprod, id->eisaid, id->neisaid);
524 if (t->val != -1)
525 return t;
526 }
527
528 /*
529 * The 'Compatible drivers' field may contain more than one
530 * ID separated by ','.
531 */
532 if (id->ncompat <= 0)
533 return NULL;
534 for (i = 0; i < id->ncompat; ++i) {
535 for (j = i; id->compat[i] != ','; ++i)
536 if (i >= id->ncompat)
537 break;
538 if (i > j) {
539 t = gettoken(pnpprod, id->compat + j, i - j);
540 if (t->val != -1)
541 return t;
542 }
543 }
544
545 return NULL;
546}
547
548/* name/val mapping */
549
550static symtab_t *
551gettoken(tab, s, len)
552symtab_t *tab;
553char *s;
554int len;
555{
556 int i;
557
558 for (i = 0; tab[i].name != NULL; ++i) {
559 if (strncmp(tab[i].name, s, len) == 0)
560 break;
561 }
562 return &tab[i];
563}
564
565/******************* PS/2 PnP probing ****************/
566
567static int
568readMouse(InputInfoPtr pInfo, unsigned char *u)
569{
570
571 if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
572 return FALSE;
573
574 xf86ReadSerial(pInfo->fd, u, 1);
575 return TRUE;
576}
577
578static void
579ps2DisableWrapMode(InputInfoPtr pInfo)
580{
581 unsigned char reset_wrap_mode[] = { 0xEC };
582 ps2SendPacket(pInfo, reset_wrap_mode, sizeof(reset_wrap_mode));
583}
584
585Bool
586ps2SendPacket(InputInfoPtr pInfo, unsigned char *bytes, int len)
587{
588 unsigned char c;
589 int i,j;
590
591#ifdef MOUSE_DEBUG
592 xf86ErrorF("Ps/2 data package:");
593 for (i = 0; i < len; i++)
594 xf86ErrorF(" %x", *(bytes + i));
595 xf86ErrorF("\n");
596#endif
597
598 for (i = 0; i < len; i++) {
599 for (j = 0; j < 10; j++) {
600 xf86WriteSerial(pInfo->fd, bytes + i, 1);
601 usleep(10000);
602 if (!readMouse(pInfo,&c)) {
603#ifdef MOUSE_DEBUG
604 xf86ErrorF("sending 0x%x to PS/2 unsuccessful\n",*(bytes + i));
605#endif
606 return FALSE;
607 }
608#ifdef MOUSE_DEBUG
609 xf86ErrorF("Recieved: 0x%x\n",c);
610#endif
611 if (c == 0xFA) /* ACK */
612 break;
613
614 if (c == 0xFE) /* resend */
615 continue;
616
617
618 if (c == 0xFC) /* error */
619 return FALSE;
620
621 /* Some mice accidently enter wrap mode during init */
622 if (c == *(bytes + i) /* wrap mode */
623 && (*(bytes + i) != 0xEC)) /* avoid recursion */
624 ps2DisableWrapMode(pInfo);
625
626 return FALSE;
627 }
628 if (j == 10)
629 return FALSE;
630 }
631
632 return TRUE;
633}
634
635static Bool
636ps2DisableDataReporting(InputInfoPtr pInfo)
637{
638 unsigned char packet[] = { 0xF5 };
639 return ps2SendPacket(pInfo, packet, sizeof(packet));
640}
641
642Bool
643ps2EnableDataReporting(InputInfoPtr pInfo)
644{
645 unsigned char packet[] = { 0xF4 };
646 return ps2SendPacket(pInfo, packet, sizeof(packet));
647}
648
649int
650ps2GetDeviceID(InputInfoPtr pInfo)
651{
652 unsigned char u;
653 unsigned char packet[] = { 0xf2 };
654
655 usleep(30000);
656 xf86FlushInput(pInfo->fd);
657 if (!ps2SendPacket(pInfo, packet, sizeof(packet)))
658 return -1;
659 while (1) {
660 if (!readMouse(pInfo,&u))
661 return -1;
662 if (u != 0xFA)
663 break;
664 }
665#ifdef MOUSE_DEBUG
666 xf86ErrorF("Obtained Mouse Type: %x\n",u);
667#endif
668 return (int) u;
669}
670
671Bool
672ps2Reset(InputInfoPtr pInfo)
673{
674 unsigned char u;
675 unsigned char packet[] = { 0xff };
676 unsigned char reply[] = { 0xaa, 0x00 };
677 unsigned int i;
678#ifdef MOUSE_DEBUG
679 xf86ErrorF("PS/2 Mouse reset\n");
680#endif
681 if (!ps2SendPacket(pInfo, packet, sizeof(packet)))
682 return FALSE;
683 /* we need a little delay here */
684 xf86WaitForInput(pInfo->fd, 500000);
685 for (i = 0; i < sizeof(reply) ; i++) {
686 if (!readMouse(pInfo,&u)) {
687 goto EXIT;
688 }
689 if (u != reply[i])
690 goto EXIT;
691 }
692 return TRUE;
693
694 EXIT:
695 xf86FlushInput(pInfo->fd);
696 return FALSE;
697}
698
699static MouseProtocolID
700probePs2ProtocolPnP(InputInfoPtr pInfo)
701{
702 unsigned char u;
703 MouseProtocolID ret = PROT_UNKNOWN;
704
705 xf86FlushInput(pInfo->fd);
706
707 ps2DisableDataReporting(pInfo);
708
709 if (ps2Reset(pInfo)) { /* Reset PS2 device */
710 unsigned char seq[] = { 243, 200, 243, 100, 243, 80 };
711 /* Try to identify Intelli Mouse */
712 if (ps2SendPacket(pInfo, seq, sizeof(seq))) {
713 u = ps2GetDeviceID(pInfo);
714 if (u == 0x03) {
715 /* found IntelliMouse now try IntelliExplorer */
716 unsigned char seq[] = { 243, 200, 243, 200, 243, 80 };
717 if (ps2SendPacket(pInfo,seq,sizeof(seq))) {
718 u = ps2GetDeviceID(pInfo);
719 if (u == 0x04)
720 ret = PROT_EXPPS2;
721 else
722 ret = PROT_IMPS2;
723 }
724 } else if (ps2Reset(pInfo)) /* reset again to find sane state */
725 ret = PROT_PS2;
726 }
727
728 if (ret != PROT_UNKNOWN)
729 ps2EnableDataReporting(pInfo);
730 }
731 return ret;
732}
733
734static struct ps2protos {
735 int Id;
736 MouseProtocolID protoID;
737} ps2 [] = {
738 { 0x0, PROT_PS2 },
739 { 0x3, PROT_IMPS2 },
740 { 0x4, PROT_EXPPS2 },
741 { -1 , PROT_UNKNOWN }
742};
743
744
745static MouseProtocolID
746getPs2ProtocolPnP(InputInfoPtr pInfo)
747{
748 int Id;
749 int i;
750 MouseProtocolID proto;
751 int count = 4;
752
753 xf86FlushInput(pInfo->fd);
754
755 while (--count)
756 if (ps2DisableDataReporting(pInfo))
757 break;
758
759 if (!count) {
760 proto = PROT_UNKNOWN;
761 goto EXIT;
762 }
763
764 if ((Id = ps2GetDeviceID(pInfo)) == -1) {
765 proto = PROT_UNKNOWN;
766 goto EXIT;
767 }
768
769 if (-1 == ps2EnableDataReporting(pInfo)) {
770 proto = PROT_UNKNOWN;
771 goto EXIT;
772 }
773
774 for (i = 0; ps2[i].protoID != PROT_UNKNOWN; i++) {
775 if (ps2[i].Id == Id) {
776 xf86MsgVerb(X_PROBED,2,"Found PS/2 proto ID %x\n",Id);
777 proto = ps2[i].protoID;
778 goto EXIT;
779 }
780 }
781
782 proto = PROT_UNKNOWN;
783 xf86Msg(X_ERROR,"Found unknown PS/2 proto ID %x\n",Id);
784
785 EXIT:
786 xf86FlushInput(pInfo->fd);
787 return proto;
788}
789
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette