Annotation of ntddk/src/input/sermouse/cseries.c, revision 1.1.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.