Annotation of ntddk/src/input/sermouse/cseries.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1993  Microsoft Corporation
        !             4: Copyright (c) 1993  Logitech Inc.
        !             5: 
        !             6: Module Name:
        !             7: 
        !             8:     cseries.c
        !             9: 
        !            10: Abstract:
        !            11: 
        !            12: Environment:
        !            13: 
        !            14:     Kernel mode only.
        !            15: 
        !            16: Notes:
        !            17: 
        !            18: Revision History:
        !            19: 
        !            20: --*/
        !            21: 
        !            22: //
        !            23: // Includes.
        !            24: //
        !            25: 
        !            26: #include "ntddk.h"
        !            27: #include "sermouse.h"
        !            28: #include "cseries.h"
        !            29: #include "debug.h"
        !            30: 
        !            31: //
        !            32: // Use the alloc_text pragma to specify the driver initialization routines
        !            33: // (they can be paged out).
        !            34: //
        !            35: 
        !            36: #ifdef ALLOC_PRAGMA
        !            37: #pragma alloc_text(init,CSerPowerUp)
        !            38: #pragma alloc_text(init,CSerSetReportRate)
        !            39: #pragma alloc_text(init,CSerSetBaudRate)
        !            40: #pragma alloc_text(init,CSerSetProtocol)
        !            41: #pragma alloc_text(init,CSerDetect)
        !            42: #endif // ALLOC_PRAGMA
        !            43: 
        !            44: //
        !            45: // Constants.
        !            46: //
        !            47: 
        !            48: //
        !            49: // The status command sent to the mouse.
        !            50: //
        !            51: 
        !            52: #define CSER_STATUS_COMMAND 's'
        !            53: 
        !            54: //
        !            55: // Status report from a CSeries mouse.
        !            56: //
        !            57: 
        !            58: #define CSER_STATUS 0x4F
        !            59: 
        !            60: //
        !            61: // Timeout value for the status returned by a CSeries mouse.
        !            62: //
        !            63: 
        !            64: #define CSER_STATUS_DELAY 50
        !            65: 
        !            66: //
        !            67: // Time (in milliseconds) needed by the mouse to adapt to a new baud rate.
        !            68: //
        !            69: 
        !            70: #define CSER_BAUDRATE_DELAY 2
        !            71: 
        !            72: //
        !            73: // Default baud rate and report rate.
        !            74: //
        !            75: 
        !            76: #define CSER_DEFAULT_BAUDRATE   1200
        !            77: #define CSER_DEFAULT_REPORTRATE 150
        !            78: 
        !            79: //
        !            80: // Button/status definitions.
        !            81: //
        !            82: 
        !            83: #define CSER_SYNCH_BIT     0x80
        !            84: 
        !            85: #define CSER_BUTTON_LEFT   0x04
        !            86: #define CSER_BUTTON_RIGHT  0x01
        !            87: #define CSER_BUTTON_MIDDLE 0x02
        !            88: 
        !            89: #define CSER_BUTTON_LEFT_SR   2
        !            90: #define CSER_BUTTON_RIGHT_SL  1
        !            91: #define CSER_BUTTON_MIDDLE_SL 1
        !            92: 
        !            93: #define SIGN_X 0x10
        !            94: #define SIGN_Y 0x08
        !            95: 
        !            96: //
        !            97: // Macros.
        !            98: //
        !            99: 
        !           100: #define sizeofel(x) (sizeof(x)/sizeof(*x))
        !           101: 
        !           102: //
        !           103: // Type definitions.
        !           104: //
        !           105: 
        !           106: typedef struct _REPORT_RATE {
        !           107:     CHAR Command;
        !           108:     UCHAR ReportRate;
        !           109: } REPORT_RATE;
        !           110: 
        !           111: typedef struct _PROTOCOL {
        !           112:     CHAR Command;
        !           113:     UCHAR LineCtrl;
        !           114:     PPROTOCOL_HANDLER Handler;
        !           115: } PROTOCOL;
        !           116: 
        !           117: typedef struct _CSER_BAUDRATE {
        !           118:     CHAR *Command;
        !           119:     ULONG BaudRate;
        !           120: } CSER_BAUDRATE;
        !           121: 
        !           122: //
        !           123: // Globals.
        !           124: //
        !           125: 
        !           126: //
        !           127: //  The baud rate at which we try to detect a mouse.
        !           128: //
        !           129: 
        !           130: static ULONG BaudRateDetect[] = { 1200, 2400, 4800, 9600 };
        !           131: 
        !           132: //
        !           133: // This list is indexed by protocol values PROTOCOL_*.
        !           134: //
        !           135: 
        !           136: PROTOCOL Protocol[] = {
        !           137:     {'S',
        !           138:     ACE_8BW | ACE_PEN | ACE_1SB,
        !           139:     CSerHandlerMM
        !           140:     },
        !           141:     {'T',
        !           142:     ACE_8BW | ACE_1SB,
        !           143:     NULL
        !           144:     },
        !           145:     {'U',
        !           146:     ACE_8BW | ACE_1SB,
        !           147:     NULL
        !           148:     },
        !           149:     {'V',
        !           150:     ACE_7BW | ACE_1SB,
        !           151:     NULL
        !           152:     },
        !           153:     {'B',
        !           154:     ACE_7BW | ACE_PEN | ACE_EPS | ACE_1SB,
        !           155:     NULL
        !           156:     },
        !           157:     {'A',
        !           158:     ACE_7BW | ACE_PEN | ACE_EPS | ACE_1SB,
        !           159:     NULL
        !           160:     }
        !           161: };
        !           162: 
        !           163: static REPORT_RATE ReportRateTable[] = {
        !           164:         {'D', 0 },
        !           165:         {'J', 10},
        !           166:         {'K', 20},
        !           167:         {'L', 35},
        !           168:         {'R', 50},
        !           169:         {'M', 70},
        !           170:         {'Q', 100},
        !           171:         {'N', 150},
        !           172:         {'O', 151}      // Continuous
        !           173: };
        !           174: static CSER_BAUDRATE CserBaudRateTable[] = {
        !           175:     { "*n", 1200 },
        !           176:     { "*o", 2400 },
        !           177:     { "*p", 4800 },
        !           178:     { "*q", 9600 }
        !           179: };
        !           180: 
        !           181: 
        !           182: BOOLEAN
        !           183: CSerPowerUp(
        !           184:     PUCHAR Port
        !           185:     )
        !           186: /*++
        !           187: 
        !           188: Routine Description:
        !           189: 
        !           190:     Powers up the mouse by making the RTS and DTR active.
        !           191: 
        !           192: Arguments:
        !           193: 
        !           194:     Port - Pointer to the serial port.
        !           195: 
        !           196: Return Value:
        !           197: 
        !           198:     TRUE.
        !           199: 
        !           200: --*/
        !           201: {
        !           202:     UCHAR lineCtrl;
        !           203:     SerMouPrint((2, "SERMOUSE-PowerUp: Enter\n"));
        !           204: 
        !           205:     //
        !           206:     // Set both RTS and DTR lines to an active state.
        !           207:     //
        !           208: 
        !           209:     lineCtrl = UARTSetModemCtrl(Port, ACE_DTR | ACE_RTS);
        !           210:     SerMouPrint((1, "SERMOUSE-Initial line control: %#x\n", lineCtrl));
        !           211: 
        !           212:     //
        !           213:     // If the lines are high, the power is on for at least 500 ms due to the
        !           214:     // MSeries detection.
        !           215:     //
        !           216: 
        !           217:     if ((lineCtrl & (ACE_DTR | ACE_RTS)) != (ACE_DTR | ACE_RTS)) {
        !           218:         SerMouPrint((1, "SERMOUSE-Powering up\n"));
        !           219: 
        !           220:         //
        !           221:         // Wait CSER_POWER_UP milliseconds for the mouse to power up 
        !           222:         // correctly.
        !           223:         //
        !           224: 
        !           225:         KeStallExecutionProcessor(CSER_POWER_UP * MS_TO_MICROSECONDS);
        !           226:     }
        !           227: 
        !           228:     SerMouPrint((2, "SERMOUSE-PowerUp: Exit\n"));
        !           229: 
        !           230:     return TRUE;
        !           231: }
        !           232: 
        !           233: 
        !           234: VOID
        !           235: CSerSetReportRate(
        !           236:     PUCHAR Port,
        !           237:     UCHAR ReportRate
        !           238:     )
        !           239: /*++
        !           240: 
        !           241: Routine Description:
        !           242: 
        !           243:     Set the mouse report rate. This can range from 0 (prompt mode) to 
        !           244:     continuous report rate.
        !           245: 
        !           246: Arguments:
        !           247: 
        !           248:     Port - Pointer to serial port.
        !           249: 
        !           250:     ReportRate - The desired report rate.
        !           251: 
        !           252: Return Value:
        !           253: 
        !           254:     None.
        !           255: 
        !           256: --*/
        !           257: {
        !           258:     LONG count;
        !           259: 
        !           260:     SerMouPrint((2, "SERMOUSE-CSerSetReportRate: Enter\n"));
        !           261: 
        !           262:     for (count = sizeofel(ReportRateTable) - 1; count >= 0; count--) {
        !           263: 
        !           264:         //
        !           265:         // Get the character to send from the table.
        !           266:         //
        !           267: 
        !           268:         if (ReportRate >= ReportRateTable[count].ReportRate) {
        !           269: 
        !           270:             //
        !           271:             // Set the baud rate.
        !           272:             //
        !           273: 
        !           274:             SerMouPrint((
        !           275:                 3, 
        !           276:                 "SERMOUSE-New ReportRate: %u\n", ReportRateTable[count].ReportRate
        !           277:                 ));
        !           278: 
        !           279:             UARTWriteChar(Port, ReportRateTable[count].Command);
        !           280:             break;
        !           281:         }
        !           282:     }
        !           283:     SerMouPrint((2, "SERMOUSE-CSerSetReportRate: Exit\n"));
        !           284: 
        !           285:     return;
        !           286: }
        !           287: 
        !           288: 
        !           289: VOID
        !           290: CSerSetBaudRate(
        !           291:     PUCHAR Port,
        !           292:     ULONG BaudRate,
        !           293:     ULONG BaudClock
        !           294:     )
        !           295: /*++
        !           296: 
        !           297: Routine Description:
        !           298: 
        !           299:     Set the new mouse baud rate. This will change the serial port baud rate.
        !           300: 
        !           301: Arguments:
        !           302: 
        !           303:     Port - Pointer to the serial port.
        !           304: 
        !           305:     BaudRate - Desired baud rate.
        !           306: 
        !           307:     BaudClock - The external frequency driving the serial chip.
        !           308: 
        !           309: Return Value:
        !           310: 
        !           311:     None.
        !           312: 
        !           313: --*/
        !           314: {
        !           315:     LONG count;
        !           316: 
        !           317:     SerMouPrint((2, "SERMOUSE-CSerSetBaudRate: Enter\n"));
        !           318: 
        !           319:     //
        !           320:     // Before we mess with the baud rate, put the mouse in prompt mode.
        !           321:     //
        !           322: 
        !           323:     CSerSetReportRate(Port, 0);
        !           324: 
        !           325:     for (count = sizeofel(CserBaudRateTable) - 1; count >= 0; count--) {
        !           326:         if (BaudRate >= CserBaudRateTable[count].BaudRate) {
        !           327: 
        !           328:             //
        !           329:             // Set the baud rate.
        !           330:             //
        !           331: 
        !           332:             UARTWriteString(Port, CserBaudRateTable[count].Command);
        !           333:             while(!UARTIsTransmitEmpty(Port)) /* Do nothing */;
        !           334:             UARTSetBaudRate(Port, CserBaudRateTable[count].BaudRate, BaudClock);
        !           335: 
        !           336:             //
        !           337:             // Delay to allow the UART and the mouse to synchronize 
        !           338:             // correctly.  
        !           339:             //
        !           340: 
        !           341:             KeStallExecutionProcessor(CSER_BAUDRATE_DELAY * MS_TO_MICROSECONDS);
        !           342:             break;
        !           343:         }
        !           344:     }
        !           345: 
        !           346:     SerMouPrint((2, "SERMOUSE-CSerSetBaudRate: Exit\n"));
        !           347: 
        !           348:     return;
        !           349: }
        !           350: 
        !           351: 
        !           352: PPROTOCOL_HANDLER
        !           353: CSerSetProtocol(
        !           354:     PUCHAR Port,
        !           355:     UCHAR NewProtocol
        !           356:     )
        !           357: /*++
        !           358: 
        !           359: Routine Description:
        !           360: 
        !           361:     Change the mouse protocol.
        !           362: 
        !           363:     Note: Not all the protocols are implemented in this driver.
        !           364: 
        !           365: Arguments:
        !           366: 
        !           367:     Port - Pointer to the serial port.
        !           368: 
        !           369: 
        !           370: Return Value:
        !           371: 
        !           372:     Address of the protocol handler function. See the interrupt service 
        !           373:     routine.
        !           374: 
        !           375: --*/
        !           376: {
        !           377:     SerMouPrint((2, "SERMOUSE-CSerSetProtocol: Enter\n"));
        !           378: 
        !           379:     ASSERT(NewProtocol < CSER_PROTOCOL_MAX);
        !           380: 
        !           381:     //
        !           382:     // Set the protocol.
        !           383:     //
        !           384: 
        !           385:     UARTWriteChar(Port, Protocol[NewProtocol].Command);
        !           386:     UARTSetLineCtrl(Port, Protocol[NewProtocol].LineCtrl);
        !           387:     SerMouPrint((2, "SERMOUSE-NewProtocol: %u\n", NewProtocol & 0xFF));
        !           388: 
        !           389: 
        !           390:     SerMouPrint((2, "SERMOUSE-CSerSetProtocol: Exit\n"));
        !           391: 
        !           392:     return Protocol[NewProtocol].Handler;
        !           393: }
        !           394: 
        !           395: 
        !           396: BOOLEAN
        !           397: CSerDetect(
        !           398:     PUCHAR Port,
        !           399:     ULONG BaudClock
        !           400:     )
        !           401: /*++
        !           402: 
        !           403: Routine Description:
        !           404: 
        !           405:     Detection of a CSeries type mouse. The main steps are:
        !           406: 
        !           407:     - Power up the mouse.
        !           408:     - Cycle through the available baud rates and try to get an answer 
        !           409:       from the mouse.
        !           410: 
        !           411:     At the end of the routine, a default baud rate and report rate are set.
        !           412: 
        !           413: Arguments:
        !           414: 
        !           415:     Port - Pointer to the serial port.
        !           416: 
        !           417:     BaudClock - The external frequency driving the serial chip.
        !           418: 
        !           419: Return Value:
        !           420: 
        !           421:     TRUE if a CSeries type mouse is detected, otherwise FALSE.
        !           422: 
        !           423: --*/
        !           424: {
        !           425:     UCHAR status;
        !           426:     ULONG count;
        !           427:     BOOLEAN detected = FALSE;
        !           428: 
        !           429:     SerMouSetDebugOutput(DBG_COLOR);
        !           430:     SerMouPrint((2, "SERMOUSE-CSerDetect: Start\n"));
        !           431: 
        !           432:     //
        !           433:     // Power up the mouse if necessary.
        !           434:     //
        !           435: 
        !           436:     CSerPowerUp(Port);
        !           437: 
        !           438:     //
        !           439:     // Set the line control register to a format that the mouse can
        !           440:     // understand (see below: the line is set after the report rate).
        !           441:     //
        !           442: 
        !           443:     UARTSetLineCtrl(Port, Protocol[CSER_PROTOCOL_MM].LineCtrl);
        !           444: 
        !           445:     //
        !           446:     // Cycle through the different baud rates to detect the mouse.
        !           447:     //
        !           448: 
        !           449:     for (count = 0; count < sizeofel(BaudRateDetect); count++) {
        !           450: 
        !           451:         UARTSetBaudRate(Port, BaudRateDetect[count], BaudClock);
        !           452: 
        !           453:         //
        !           454:         // Put the mouse in prompt mode.
        !           455:         //
        !           456: 
        !           457:         CSerSetReportRate(Port, 0);
        !           458: 
        !           459:         //
        !           460:         // Set the MM protocol. This way we get the mouse to talk to us in a
        !           461:         // specific format. This avoids receiving errors from the line 
        !           462:         // register.
        !           463:         //
        !           464: 
        !           465:         CSerSetProtocol(Port, CSER_PROTOCOL_MM);
        !           466: 
        !           467:         //
        !           468:         // Try to get the status byte.
        !           469:         //
        !           470: 
        !           471:         UARTWriteChar(Port, CSER_STATUS_COMMAND);
        !           472: 
        !           473:         while (!UARTIsTransmitEmpty(Port)) {
        !           474:             // Nothing
        !           475:         }
        !           476: 
        !           477:         //
        !           478:         // In case something is already there...
        !           479:         //
        !           480: 
        !           481:         UARTFlushReadBuffer(Port);
        !           482: 
        !           483:         //
        !           484:         // Read back the status character.
        !           485:         //
        !           486:         if (UARTReadChar(Port, &status, CSER_STATUS_DELAY) &&
        !           487:                 (status ==  CSER_STATUS)) {
        !           488:             detected = TRUE;
        !           489:             SerMouPrint((
        !           490:                 1,
        !           491:                 "SERMOUSE-Detected mouse at %u bauds\n",
        !           492:                 BaudRateDetect[count]
        !           493:                 ));
        !           494:             break;
        !           495:         }
        !           496:     }
        !           497: 
        !           498:     //
        !           499:     // Put the mouse back in a default mode. The protocol is already set.
        !           500:     //
        !           501: 
        !           502:     CSerSetBaudRate(Port, CSER_DEFAULT_BAUDRATE, BaudClock);
        !           503:     CSerSetReportRate(Port, CSER_DEFAULT_REPORTRATE);
        !           504: 
        !           505:     SerMouPrint((3, "SERMOUSE-Detected: %s\n", detected ? "TRUE" : "FALSE"));
        !           506:     SerMouPrint((3, "SERMOUSE-Status byte: %#x\n", status));
        !           507:     SerMouPrint((2, "SERMOUSE-CSerDetect: End\n"));
        !           508: 
        !           509:     SerMouSetDebugOutput(DBG_SERIAL);
        !           510: 
        !           511:     return detected;
        !           512: }
        !           513: 
        !           514: 
        !           515: BOOLEAN
        !           516: CSerHandlerMM(
        !           517:     IN PMOUSE_INPUT_DATA CurrentInput,
        !           518:     IN PHANDLER_DATA HandlerData,
        !           519:     IN UCHAR Value,
        !           520:     IN UCHAR LineState)
        !           521: 
        !           522: /*++
        !           523: 
        !           524: Routine Description:
        !           525: 
        !           526:     This is the protocol handler routine for the MM protocol.
        !           527: 
        !           528: Arguments:
        !           529: 
        !           530:     CurrentInput - Pointer to the report packet.
        !           531: 
        !           532:     Value - The input buffer value.
        !           533: 
        !           534:     LineState - The serial port line state.
        !           535: 
        !           536: Return Value:
        !           537: 
        !           538:     Returns TRUE if the handler has a completed report.
        !           539: 
        !           540: --*/
        !           541: 
        !           542: {
        !           543: 
        !           544:     BOOLEAN retval = FALSE;
        !           545: 
        !           546:     SerMouPrint((2, "SERMOUSE-MMHandler: enter\n"));
        !           547: 
        !           548:     if ((Value & CSER_SYNCH_BIT) && (HandlerData->State != STATE0)) {
        !           549:         HandlerData->Error++;
        !           550:         SerMouPrint((
        !           551:             1,
        !           552:             "SERMOUSE-Synch error. State: %u\n", HandlerData->State
        !           553:             ));
        !           554:         HandlerData->State = STATE0;
        !           555:     }
        !           556:     else if (!(Value & CSER_SYNCH_BIT) && (HandlerData->State == STATE0)) {
        !           557:         HandlerData->Error++;
        !           558:         SerMouPrint((
        !           559:             1,
        !           560:             "SERMOUSE-Synch error. State: %u\n", HandlerData->State
        !           561:             ));
        !           562:         goto LExit;
        !           563:     }
        !           564: 
        !           565:     //
        !           566:     // Check for a line state error.
        !           567:     //
        !           568: 
        !           569:     if (LineState & ACE_LERR) {
        !           570: 
        !           571:         //
        !           572:         // Reset the handler state.
        !           573:         //
        !           574: 
        !           575:         HandlerData->State = STATE0;
        !           576:         HandlerData->Error++;
        !           577:         SerMouPrint((1, "SERMOUSE-Line status error: %#x\n", LineState));
        !           578:     }
        !           579:     else {
        !           580:         SerMouPrint((2, "SERMOUSE-State%u\n", HandlerData->State));
        !           581:         HandlerData->Raw[HandlerData->State] = Value;
        !           582: 
        !           583:         switch (HandlerData->State) {
        !           584:         case STATE0:
        !           585:         case STATE1:
        !           586:             HandlerData->State++;
        !           587:             break;
        !           588:         case STATE2:
        !           589:             HandlerData->State = STATE0;
        !           590: 
        !           591:             //
        !           592:             // Buttons formatting.
        !           593:             //
        !           594: 
        !           595:             CurrentInput->RawButtons =
        !           596:                 (HandlerData->Raw[STATE0] & CSER_BUTTON_LEFT) >> CSER_BUTTON_LEFT_SR;
        !           597:             CurrentInput->RawButtons |=
        !           598:                 (HandlerData->Raw[STATE0] & CSER_BUTTON_RIGHT) << CSER_BUTTON_RIGHT_SL;
        !           599:             CurrentInput->RawButtons |=
        !           600:                 (HandlerData->Raw[STATE0] & CSER_BUTTON_MIDDLE) << CSER_BUTTON_MIDDLE_SL;
        !           601: 
        !           602:             //
        !           603:             // Displacement formatting.
        !           604:             //
        !           605: 
        !           606:             CurrentInput->LastX = (HandlerData->Raw[STATE0] & SIGN_X) ?
        !           607:                 HandlerData->Raw[STATE1] :
        !           608:                 -(LONG)HandlerData->Raw[STATE1];
        !           609: 
        !           610:             //
        !           611:             // Note: The Y displacement is positive to the south.
        !           612:             //
        !           613: 
        !           614:             CurrentInput->LastY = (HandlerData->Raw[STATE0] & SIGN_Y) ?
        !           615:                 -(LONG)HandlerData->Raw[STATE2] :
        !           616:                 HandlerData->Raw[STATE2];
        !           617: 
        !           618:             SerMouPrint((1, "SERMOUSE-Displacement X: %ld\n", CurrentInput->LastX));
        !           619:             SerMouPrint((1, "SERMOUSE-Displacement Y: %ld\n", CurrentInput->LastY));
        !           620:             SerMouPrint((1, "SERMOUSE-Raw Buttons: %0lx\n", CurrentInput->RawButtons));
        !           621: 
        !           622:             //
        !           623:             // The report is complete. Tell the interrupt handler to send it.
        !           624:             //
        !           625: 
        !           626:             retval = TRUE;
        !           627: 
        !           628:             break;
        !           629: 
        !           630:         default:
        !           631:             SerMouPrint((
        !           632:                 0,
        !           633:                 "SERMOUSE-MM Handler failure: incorrect state value.\n"
        !           634:                 ));
        !           635:             ASSERT(FALSE);
        !           636:         }
        !           637: 
        !           638:     }
        !           639: 
        !           640: LExit:
        !           641:     SerMouPrint((2, "SERMOUSE-MMHandler: exit\n"));
        !           642: 
        !           643:     return retval;
        !           644: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.