|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 Microsoft Corporation ! 4: Copyright (c) 1993 Logitech Inc. ! 5: ! 6: Module Name: ! 7: ! 8: mseries.c ! 9: ! 10: Abstract: ! 11: ! 12: ! 13: Environment: ! 14: ! 15: Kernel mode only. ! 16: ! 17: Notes: ! 18: ! 19: ! 20: Revision History: ! 21: ! 22: --*/ ! 23: ! 24: // ! 25: // Includes. ! 26: // ! 27: ! 28: #include "ntddk.h" ! 29: #include "uart.h" ! 30: #include "sermouse.h" ! 31: #include "debug.h" ! 32: #include "cseries.h" ! 33: #include "mseries.h" ! 34: ! 35: // ! 36: // Use the alloc_text pragma to specify the driver initialization routines ! 37: // (they can be paged out). ! 38: // ! 39: ! 40: #ifdef ALLOC_PRAGMA ! 41: #pragma alloc_text(init,MSerSetProtocol) ! 42: #pragma alloc_text(init,MSerPowerUp) ! 43: #pragma alloc_text(init,MSerPowerDown) ! 44: #pragma alloc_text(init,MSerReset) ! 45: #pragma alloc_text(init,MSerDetect) ! 46: #endif // ALLOC_PRAGMA ! 47: ! 48: // ! 49: // Constants. ! 50: // ! 51: ! 52: #define MSER_BAUDRATE 1200 ! 53: #define MAX_RESET_BUFFER 8 ! 54: #define MINIMUM_RESET_TIME 200 ! 55: ! 56: // ! 57: // Microsoft Plus. ! 58: // ! 59: ! 60: #define MP_SYNCH_BIT 0x40 ! 61: ! 62: #define MP_BUTTON_LEFT 0x20 ! 63: #define MP_BUTTON_RIGHT 0x10 ! 64: #define MP_BUTTON_MIDDLE 0x20 ! 65: ! 66: #define MP_BUTTON_LEFT_SR 5 ! 67: #define MP_BUTTON_RIGHT_SR 3 ! 68: #define MP_BUTTON_MIDDLE_SR 3 ! 69: ! 70: #define MP_BUTTON_MIDDLE_MASK 0x04 ! 71: ! 72: #define MP_UPPER_MASKX 0x03 ! 73: #define MP_UPPER_MASKY 0x0C ! 74: ! 75: #define MP_UPPER_MASKX_SL 6 ! 76: #define MP_UPPER_MASKY_SL 4 ! 77: ! 78: // ! 79: // Microsoft BallPoint. ! 80: // ! 81: ! 82: #define BP_SYNCH_BIT 0x40 ! 83: ! 84: #define BP_BUTTON_LEFT 0x20 ! 85: #define BP_BUTTON_RIGHT 0x10 ! 86: #define BP_BUTTON_3 0x04 ! 87: #define BP_BUTTON_4 0x08 ! 88: ! 89: #define BP_BUTTON_LEFT_SR 5 ! 90: #define BP_BUTTON_RIGHT_SR 3 ! 91: #define BP_BUTTON_3_SL 0 ! 92: #define BP_BUTTON_4_SL 0 ! 93: ! 94: #define BP_UPPER_MASKX 0x03 ! 95: #define BP_UPPER_MASKY 0x0C ! 96: ! 97: #define BP_UPPER_MASKX_SL 6 ! 98: #define BP_UPPER_MASKY_SL 4 ! 99: ! 100: #define BP_SIGN_MASKX 0x01 ! 101: #define BP_SIGN_MASKY 0x02 ! 102: ! 103: // ! 104: // Type definitions. ! 105: // ! 106: ! 107: typedef struct _PROTOCOL { ! 108: PPROTOCOL_HANDLER Handler; ! 109: UCHAR LineCtrl; ! 110: } PROTOCOL; ! 111: ! 112: // ! 113: // This list is indexed by protocol values MSER_PROTOCOL_*. ! 114: // ! 115: ! 116: static PROTOCOL Protocol[] = { ! 117: { ! 118: MSerHandlerMP, // Microsoft Plus ! 119: ACE_7BW | ACE_1SB ! 120: }, ! 121: { ! 122: MSerHandlerBP, // BALLPOINT ! 123: ACE_7BW | ACE_1SB ! 124: } ! 125: }; ! 126: ! 127: PPROTOCOL_HANDLER ! 128: MSerSetProtocol( ! 129: PUCHAR Port, ! 130: UCHAR NewProtocol ! 131: ) ! 132: /*++ ! 133: ! 134: Routine Description: ! 135: ! 136: Set the mouse protocol. This function only sets the serial port ! 137: line control register. ! 138: ! 139: Arguments: ! 140: ! 141: Port - Pointer to the serial port. ! 142: ! 143: NewProtocol - Index into the protocol table. ! 144: ! 145: Return Value: ! 146: ! 147: Pointer to the protocol handler function. ! 148: ! 149: --*/ ! 150: { ! 151: ASSERT(NewProtocol < MSER_PROTOCOL_MAX); ! 152: ! 153: // ! 154: // Set the protocol ! 155: // ! 156: ! 157: UARTSetLineCtrl(Port, Protocol[NewProtocol].LineCtrl); ! 158: ! 159: return Protocol[NewProtocol].Handler; ! 160: } ! 161: ! 162: BOOLEAN ! 163: MSerPowerUp( ! 164: PUCHAR Port ! 165: ) ! 166: /*++ ! 167: ! 168: Routine Description: ! 169: ! 170: Powers up the mouse. Just sets the RTS and DTR lines and returns. ! 171: ! 172: Arguments: ! 173: ! 174: Port - Pointer to the serial port. ! 175: ! 176: Return Value: ! 177: ! 178: TRUE. ! 179: ! 180: --*/ ! 181: { ! 182: ! 183: // ! 184: // Turn RTS on to power the mouse up (DTR should already be on, ! 185: // but make extra sure). ! 186: // ! 187: ! 188: UARTSetModemCtrl(Port, ACE_DTR | ACE_RTS); ! 189: ! 190: // ! 191: // Wait 10 ms. The power-up response byte(s) should take at least ! 192: // this long to get transmitted. ! 193: // ! 194: ! 195: KeStallExecutionProcessor(10 * MS_TO_MICROSECONDS); ! 196: ! 197: return TRUE; ! 198: } ! 199: ! 200: BOOLEAN ! 201: MSerPowerDown( ! 202: PUCHAR Port ! 203: ) ! 204: /*++ ! 205: ! 206: Routine Description: ! 207: ! 208: Powers down the mouse. Sets the RTS line to an inactive state. ! 209: ! 210: Arguments: ! 211: ! 212: Port - Pointer to the serial port. ! 213: ! 214: Return Value: ! 215: ! 216: TRUE. ! 217: ! 218: --*/ ! 219: { ! 220: UCHAR lineCtrl = UARTGetModemCtrl(Port); ! 221: ! 222: SerMouPrint(( ! 223: 2, ! 224: "SERMOUSE-MSerPowerDown: The intial line control is: %#X\n", ! 225: lineCtrl & 0xFF ! 226: )); ! 227: ! 228: UARTSetModemCtrl(Port, (UCHAR)(lineCtrl & (~ACE_RTS | ACE_DTR))); ! 229: ! 230: // ! 231: // Keep RTS low for at least 150 ms, in order to correctly power ! 232: // down older Microsoft serial mice. Wait even longer to avoid ! 233: // sending some Logitech CSeries mice into the floating point world... ! 234: // ! 235: ! 236: ASSERT(CSER_POWER_DOWN >= 150); ! 237: ! 238: KeStallExecutionProcessor(CSER_POWER_DOWN * MS_TO_MICROSECONDS); ! 239: ! 240: return TRUE; ! 241: } ! 242: ! 243: BOOLEAN ! 244: MSerReset( ! 245: PUCHAR Port ! 246: ) ! 247: /*++ ! 248: ! 249: Routine Description: ! 250: ! 251: Reset the serial mouse. ! 252: ! 253: Arguments: ! 254: ! 255: Port - Pointer to the serial port. ! 256: ! 257: Return Value: ! 258: ! 259: TRUE. ! 260: ! 261: --*/ ! 262: { ! 263: ! 264: // ! 265: // Remove mouse power if necessary. ! 266: // ! 267: ! 268: MSerPowerDown(Port); ! 269: ! 270: // ! 271: // Clean possible garbage in uart input buffer. ! 272: // ! 273: ! 274: UARTFlushReadBuffer(Port); ! 275: ! 276: // ! 277: // Power up the mouse (reset). ! 278: // ! 279: ! 280: MSerPowerUp(Port); ! 281: ! 282: return TRUE; ! 283: } ! 284: ! 285: MOUSETYPE ! 286: MSerDetect( ! 287: PUCHAR Port, ! 288: ULONG BaudClock ! 289: ) ! 290: /*++ ! 291: ! 292: Routine Description: ! 293: ! 294: Detection code for pointing devices that identify themselves at ! 295: power on time. ! 296: ! 297: Arguments: ! 298: ! 299: Port - Pointer to the serial port. ! 300: ! 301: BaudClock - The external frequency driving the serial chip. ! 302: ! 303: Return Value: ! 304: ! 305: The type of mouse detected. ! 306: ! 307: --*/ ! 308: { ! 309: ULONG count = 0; ! 310: MOUSETYPE mouseType; ! 311: CHAR receiveBuffer[MAX_RESET_BUFFER]; ! 312: ULONG i; ! 313: ! 314: // ! 315: // Set the debug output to the main display to avoid timing problems. ! 316: // ! 317: ! 318: SerMouSetDebugOutput(DBG_COLOR); ! 319: ! 320: // ! 321: // Set the baud rate. ! 322: // ! 323: ! 324: UARTSetBaudRate(Port, MSER_BAUDRATE, BaudClock); ! 325: ! 326: // ! 327: // Set the data format so that the possible answer can be recognized. ! 328: // ! 329: ! 330: UARTSetLineCtrl(Port, Protocol[MSER_PROTOCOL_MP].LineCtrl); ! 331: ! 332: // ! 333: // Apply the reset to the mouse. ! 334: // ! 335: ! 336: MSerReset(Port); ! 337: ! 338: // ! 339: // Get the possible first reset character ('M' or 'B'), followed ! 340: // by any other characters the hardware happens to send back. ! 341: // ! 342: // Note: Typically, we expect to get just one character ('M' or ! 343: // 'B'), perhaps followed by a '2' or '3' (to indicate the ! 344: // number of mouse buttons. On some machines, we're ! 345: // getting extraneous characters before the 'M'. Sometimes ! 346: // we get extraneous characters after the expected data, as ! 347: // well. They either get read in here, or get flushed ! 348: // when SerMouEnableInterrupts executes. ! 349: // ! 350: ! 351: ASSERT(CSER_POWER_UP >= MINIMUM_RESET_TIME); ! 352: ! 353: if (UARTReadChar(Port, &receiveBuffer[count], CSER_POWER_UP)) { ! 354: count++; ! 355: while (count < (MAX_RESET_BUFFER - 1)) { ! 356: if (UARTReadChar(Port, &receiveBuffer[count], 100)) { ! 357: count++; ! 358: } else { ! 359: break; ! 360: } ! 361: } ! 362: } ! 363: ! 364: *(receiveBuffer + count) = 0; ! 365: ! 366: SerMouPrint((2, "SERMOUSE-Receive buffer:\n")); ! 367: for (i = 0; i < count; i++) { ! 368: SerMouPrint((2, "\t0x%x\n", receiveBuffer[i])); ! 369: } ! 370: SerMouPrint((2, "\n")); ! 371: ! 372: // ! 373: // Redirect the output to the serial port. ! 374: // ! 375: ! 376: SerMouSetDebugOutput(DBG_SERIAL); ! 377: ! 378: // ! 379: // ! 380: // Analyze the possible mouse answer. Start at the beginning of the ! 381: // "good" data in the receive buffer, ignoring extraneous characters ! 382: // that may have come in before the 'M' or 'B'. ! 383: // ! 384: ! 385: for (i = 0; i < count; i++) { ! 386: if (receiveBuffer[i] == 'M') { ! 387: if (receiveBuffer[i + 1] == '3') { ! 388: SerMouPrint((2, "SERMOUSE-Detected MSeries 3 buttons\n")); ! 389: mouseType = MOUSE_3B; ! 390: } ! 391: else { ! 392: SerMouPrint((2, "SERMOUSE-Detected MSeries 2 buttons\n")); ! 393: mouseType = MOUSE_2B; ! 394: } ! 395: break; ! 396: } else if (receiveBuffer[i] == 'B') { ! 397: SerMouPrint((2, "SERMOUSE-Detected Ballpoint\n")); ! 398: mouseType = BALLPOINT; ! 399: break; ! 400: } ! 401: } ! 402: ! 403: if (i >= count) { ! 404: ! 405: // ! 406: // Special case: If another device is connected (CSeries, for ! 407: // example) and this device sends a character (movement), the ! 408: // minimum power up time might not be respected. Take ! 409: // care of this unlikely case. ! 410: // ! 411: ! 412: if (count != 0) { ! 413: KeStallExecutionProcessor(CSER_POWER_UP * MS_TO_MICROSECONDS); ! 414: } ! 415: ! 416: SerMouPrint((1, "SERMOUSE-No MSeries detected\n")); ! 417: mouseType = NO_MOUSE; ! 418: } ! 419: ! 420: return mouseType; ! 421: } ! 422: ! 423: ! 424: BOOLEAN ! 425: MSerHandlerMP( ! 426: IN PMOUSE_INPUT_DATA CurrentInput, ! 427: IN PHANDLER_DATA HandlerData, ! 428: IN UCHAR Value, ! 429: IN UCHAR LineState ! 430: ) ! 431: ! 432: /*++ ! 433: ! 434: Routine Description: ! 435: ! 436: This is the protocol handler routine for the Microsoft Plus protocol. ! 437: ! 438: Arguments: ! 439: ! 440: CurrentInput - Pointer to the report packet. ! 441: ! 442: HandlerData - Instance specific static data for the handler. ! 443: ! 444: Value - The input buffer value. ! 445: ! 446: LineState - The serial port line state. ! 447: ! 448: Return Value: ! 449: ! 450: Returns TRUE if the handler has a complete report ready. ! 451: ! 452: --*/ ! 453: ! 454: { ! 455: BOOLEAN retval = FALSE; ! 456: ULONG middleButton; ! 457: ! 458: SerMouPrint((2, "SERMOUSE-MP protocol handler: enter\n")); ! 459: ! 460: ! 461: if ((Value & MP_SYNCH_BIT) && (HandlerData->State != STATE0)) { ! 462: if ((HandlerData->State != STATE3)) { ! 463: ! 464: // ! 465: // We definitely have a synchronization problem (likely a data ! 466: // overrun). ! 467: // ! 468: ! 469: HandlerData->Error++; ! 470: } ! 471: else if ((HandlerData->PreviousButtons & MOUSE_BUTTON_3) != 0) { ! 472: ! 473: // ! 474: // We didn't receive the expected fourth byte. Missed it? ! 475: // Reset button 3 to zero. ! 476: // ! 477: ! 478: HandlerData->PreviousButtons ^= MOUSE_BUTTON_3; ! 479: HandlerData->Error++; ! 480: } ! 481: ! 482: SerMouPrint(( ! 483: 1, ! 484: "SERMOUSE-Synch error. State: %u\n", HandlerData->State ! 485: )); ! 486: ! 487: HandlerData->State = STATE0; ! 488: } ! 489: else if (!(Value & MP_SYNCH_BIT) && (HandlerData->State == STATE0)) { ! 490: HandlerData->Error++; ! 491: SerMouPrint(( ! 492: 1, ! 493: "SERMOUSE-Synch error. State: %u\n", HandlerData->State ! 494: )); ! 495: goto LExit; ! 496: } ! 497: ! 498: // ! 499: // Check for a line state error. ! 500: // ! 501: ! 502: if (LineState & ACE_LERR) { ! 503: ! 504: // ! 505: // Reset the handler state. ! 506: // ! 507: ! 508: HandlerData->State = STATE0; ! 509: HandlerData->Error++; ! 510: SerMouPrint((1, "SERMOUSE-Line status error: %#x\n", LineState)); ! 511: } ! 512: else { ! 513: ! 514: // ! 515: // Set the untranslated value. ! 516: // ! 517: ! 518: HandlerData->Raw[HandlerData->State] = Value; ! 519: SerMouPrint((3, "SERMOUSE-State%u\n", HandlerData->State)); ! 520: ! 521: switch (HandlerData->State) { ! 522: case STATE0: ! 523: case STATE1: ! 524: HandlerData->State++; ! 525: break; ! 526: case STATE2: ! 527: HandlerData->State++; ! 528: ! 529: // ! 530: // Build the report. ! 531: // ! 532: ! 533: CurrentInput->RawButtons = ! 534: (HandlerData->Raw[0] & MP_BUTTON_LEFT) >> MP_BUTTON_LEFT_SR; ! 535: CurrentInput->RawButtons |= ! 536: (HandlerData->Raw[0] & MP_BUTTON_RIGHT) >> MP_BUTTON_RIGHT_SR; ! 537: CurrentInput->RawButtons |= ! 538: HandlerData->PreviousButtons & MOUSE_BUTTON_3; ! 539: ! 540: CurrentInput->LastX = ! 541: (SCHAR)(HandlerData->Raw[1] | ! 542: ((HandlerData->Raw[0] & MP_UPPER_MASKX) << MP_UPPER_MASKX_SL)); ! 543: CurrentInput->LastY = ! 544: (SCHAR)(HandlerData->Raw[2] | ! 545: ((HandlerData->Raw[0] & MP_UPPER_MASKY) << MP_UPPER_MASKY_SL)); ! 546: ! 547: retval = TRUE; ! 548: ! 549: break; ! 550: ! 551: case STATE3: ! 552: HandlerData->State = STATE0; ! 553: middleButton = ! 554: (HandlerData->Raw[STATE3] & MP_BUTTON_MIDDLE) >> MP_BUTTON_MIDDLE_SR; ! 555: ! 556: // ! 557: // Send a report only if the middle button state changed. ! 558: // ! 559: ! 560: if (middleButton ^ (HandlerData->PreviousButtons & MOUSE_BUTTON_3)) { ! 561: ! 562: // ! 563: // Toggle the state of the middle button. ! 564: // ! 565: ! 566: CurrentInput->RawButtons ^= MP_BUTTON_MIDDLE_MASK; ! 567: CurrentInput->LastX = 0; ! 568: CurrentInput->LastY = 0; ! 569: ! 570: // ! 571: // Send the report one more time. ! 572: // ! 573: ! 574: retval = TRUE; ! 575: } ! 576: ! 577: break; ! 578: ! 579: default: ! 580: SerMouPrint(( ! 581: 0, ! 582: "SERMOUSE-MP Handler failure: incorrect state value.\n" ! 583: )); ! 584: ASSERT(FALSE); ! 585: } ! 586: } ! 587: ! 588: LExit: ! 589: SerMouPrint((2, "SERMOUSE-MP protocol handler: exit\n")); ! 590: ! 591: return retval; ! 592: ! 593: } ! 594: ! 595: BOOLEAN ! 596: MSerHandlerBP( ! 597: IN PMOUSE_INPUT_DATA CurrentInput, ! 598: IN PHANDLER_DATA HandlerData, ! 599: IN UCHAR Value, ! 600: IN UCHAR LineState ! 601: ) ! 602: ! 603: /*++ ! 604: ! 605: Routine Description: ! 606: ! 607: This is the protocol handler routine for the Microsoft Ballpoint protocol. ! 608: ! 609: Arguments: ! 610: ! 611: CurrentInput - Pointer to the report packet. ! 612: ! 613: HandlerData - Instance specific static data for the handler. ! 614: ! 615: Value - The input buffer value. ! 616: ! 617: LineState - The serial port line state. ! 618: ! 619: Return Value: ! 620: ! 621: Returns TRUE if the handler has a complete report ready. ! 622: ! 623: --*/ ! 624: ! 625: { ! 626: BOOLEAN retval = FALSE; ! 627: ! 628: SerMouPrint((2, "SERMOUSE-BP protocol handler: enter\n")); ! 629: ! 630: // ! 631: // Check for synchronization errors. ! 632: // ! 633: ! 634: if ((Value & BP_SYNCH_BIT) && (HandlerData->State != STATE0)) { ! 635: HandlerData->Error++; ! 636: SerMouPrint(( ! 637: 1, ! 638: "SERMOUSE-Synch error. State: %u\n", HandlerData->State ! 639: )); ! 640: HandlerData->State = STATE0; ! 641: } ! 642: else if (!(Value & BP_SYNCH_BIT) && (HandlerData->State == STATE0)) { ! 643: HandlerData->Error++; ! 644: SerMouPrint(( ! 645: 1, ! 646: "SERMOUSE-Synch error. State: %u\n", HandlerData->State ! 647: )); ! 648: goto LExit; ! 649: } ! 650: ! 651: // ! 652: // Check for a line state error. ! 653: // ! 654: ! 655: if (LineState & ACE_LERR) { ! 656: ! 657: // ! 658: // Reset the handler state. ! 659: // ! 660: ! 661: HandlerData->State = STATE0; ! 662: HandlerData->Error++; ! 663: SerMouPrint((1, "SERMOUSE-Line status error: %#x\n", LineState)); ! 664: } ! 665: else { ! 666: ! 667: // ! 668: // Set the untranslated value. ! 669: // ! 670: ! 671: HandlerData->Raw[HandlerData->State] = Value; ! 672: ! 673: SerMouPrint((3, "SERMOUSE-State%u\n", HandlerData->State)); ! 674: ! 675: switch (HandlerData->State) { ! 676: ! 677: case STATE0: ! 678: case STATE1: ! 679: case STATE2: ! 680: HandlerData->State++; ! 681: break; ! 682: ! 683: case STATE3: ! 684: HandlerData->State = STATE0; ! 685: ! 686: // ! 687: // Build the report. ! 688: // ! 689: ! 690: CurrentInput->RawButtons = ! 691: (HandlerData->Raw[0] & BP_BUTTON_LEFT) >> BP_BUTTON_LEFT_SR; ! 692: CurrentInput->RawButtons |= ! 693: (HandlerData->Raw[0] & BP_BUTTON_RIGHT) >> BP_BUTTON_RIGHT_SR; ! 694: ! 695: #if 0 ! 696: CurrentInput->Buttons |= ! 697: (HandlerData->Raw[3] & BP_BUTTON_3) << BP_BUTTON_3_SL; ! 698: CurrentInput->Buttons |= ! 699: (HandlerData->Raw[3] & BP_BUTTON_4) << BP_BUTTON_4_SL; ! 700: #endif ! 701: CurrentInput->LastX = HandlerData->Raw[3] & BP_SIGN_MASKX ? ! 702: (LONG)(HandlerData->Raw[1] | (ULONG)(-1 & ~0xFF) | ! 703: ((HandlerData->Raw[0] & BP_UPPER_MASKX) << BP_UPPER_MASKX_SL)): ! 704: (LONG)(HandlerData->Raw[1] | ! 705: ((HandlerData->Raw[0] & BP_UPPER_MASKX) << BP_UPPER_MASKX_SL)); ! 706: ! 707: CurrentInput->LastY = HandlerData->Raw[3] & BP_SIGN_MASKY ? ! 708: (LONG)(HandlerData->Raw[2] | (ULONG)(-1 & ~0xFF) | ! 709: ((HandlerData->Raw[0] & BP_UPPER_MASKY) << BP_UPPER_MASKY_SL)): ! 710: (LONG)(HandlerData->Raw[2] | ! 711: ((HandlerData->Raw[0] & BP_UPPER_MASKY) << BP_UPPER_MASKY_SL)); ! 712: ! 713: retval = TRUE; ! 714: ! 715: break; ! 716: ! 717: default: ! 718: SerMouPrint(( ! 719: 0, ! 720: "SERMOUSE-BP Handler failure: incorrect state value.\n" ! 721: )); ! 722: ASSERT(FALSE); ! 723: } ! 724: } ! 725: ! 726: LExit: ! 727: SerMouPrint((2, "SERMOUSE-BP protocol handler: exit\n")); ! 728: ! 729: return retval; ! 730: ! 731: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.