⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mseries.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved
Copyright (c) 1993  Logitech Inc.

Module Name:

    mseries.c

Abstract:


Environment:

    Kernel mode only.

Notes:


Revision History:

--*/

//
// Includes.
//

#include "ntddk.h"
#include "mouser.h"
#include "debug.h"
#include "cseries.h"
#include "mseries.h"

//
// Use the alloc_text pragma to specify the driver initialization routines
// (they can be paged out).
//

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,MSerSetProtocol)
#pragma alloc_text(PAGE,MSerPowerUp)
#pragma alloc_text(PAGE,MSerPowerDown)
#pragma alloc_text(PAGE,MSerDetect)
#endif // ALLOC_PRAGMA

//
// Constants.
//

#define MSER_BAUDRATE 1200
#define MAX_RESET_BUFFER 8
#define MINIMUM_RESET_TIME (200 * MS_TO_100_NS)

//
// Microsoft Plus.
//

#define MP_SYNCH_BIT          0x40

#define MP_BUTTON_LEFT        0x20
#define MP_BUTTON_RIGHT       0x10
#define MP_BUTTON_MIDDLE      0x20

#define MP_BUTTON_LEFT_SR     5
#define MP_BUTTON_RIGHT_SR    3
#define MP_BUTTON_MIDDLE_SR   3

#define MP_BUTTON_MIDDLE_MASK 0x04

#define MP_UPPER_MASKX        0x03
#define MP_UPPER_MASKY        0x0C

#define MP_UPPER_MASKX_SL     6
#define MP_UPPER_MASKY_SL     4

//
// Microsoft BallPoint.
//

#define BP_SYNCH_BIT          0x40

#define BP_BUTTON_LEFT        0x20
#define BP_BUTTON_RIGHT       0x10
#define BP_BUTTON_3           0x04
#define BP_BUTTON_4           0x08

#define BP_BUTTON_LEFT_SR     5
#define BP_BUTTON_RIGHT_SR    3
#define BP_BUTTON_3_SL        0
#define BP_BUTTON_4_SL        0

#define BP_UPPER_MASKX        0x03
#define BP_UPPER_MASKY        0x0C

#define BP_UPPER_MASKX_SL     6
#define BP_UPPER_MASKY_SL     4

#define BP_SIGN_MASKX         0x01
#define BP_SIGN_MASKY         0x02

//
// Microsoft Magellan Mouse.
//

#define Z_SYNCH_BIT          0x40
#define Z_EXTRA_BIT          0x20

#define Z_BUTTON_LEFT        0x20
#define Z_BUTTON_RIGHT       0x10
#define Z_BUTTON_MIDDLE      0x10

#define Z_BUTTON_LEFT_SR     5
#define Z_BUTTON_RIGHT_SR    3
#define Z_BUTTON_MIDDLE_SR   3

#define Z_BUTTON_MIDDLE_MASK 0x04

#define Z_UPPER_MASKX        0x03
#define Z_UPPER_MASKY        0x0C
#define Z_UPPER_MASKZ        0x0F

#define Z_LOWER_MASKZ        0x0F

#define Z_UPPER_MASKX_SL     6
#define Z_UPPER_MASKY_SL     4
#define Z_UPPER_MASKZ_SL     4

//
// Type definitions.
//

typedef struct _PROTOCOL {
    PPROTOCOL_HANDLER Handler;
    // UCHAR LineCtrl;
    SERIAL_LINE_CONTROL LineCtrl;
} PROTOCOL;

//
// This list is indexed by protocol values MSER_PROTOCOL_*.
//

static PROTOCOL Protocol[] = {
    {
    MSerHandlerMP,  // Microsoft Plus
    // ACE_7BW | ACE_1SB
    { STOP_BIT_1, NO_PARITY, 7 }
    },
    {
    MSerHandlerBP,  // BALLPOINT
    // ACE_7BW | ACE_1SB
    { STOP_BIT_1, NO_PARITY, 7 }
    },
    {
    MSerHandlerZ,   // Magellan Mouse
    // ACE_7BW | ACE_1SB
    { STOP_BIT_1, NO_PARITY, 7 }
    }
};

PPROTOCOL_HANDLER
MSerSetProtocol(
    PDEVICE_EXTENSION DeviceExtension, 
    UCHAR             NewProtocol
    )
/*++

Routine Description:

    Set the mouse protocol. This function only sets the serial port 
    line control register.

Arguments:

    Port - Pointer to the serial port.

    NewProtocol - Index into the protocol table.

Return Value:

    Pointer to the protocol handler function.

--*/
{
    ASSERT(NewProtocol < MSER_PROTOCOL_MAX);
    PAGED_CODE();

    Print(DeviceExtension, DBG_SS_TRACE, ("MSerSetProtocol called\n"));

    //
    // Set the protocol
    //
    SerialMouseSetLineCtrl(DeviceExtension, &Protocol[NewProtocol].LineCtrl);

    return Protocol[NewProtocol].Handler;
}

NTSTATUS
MSerPowerUp(
    PDEVICE_EXTENSION DeviceExtension
    )
/*++

Routine Description:

    Powers up the mouse. Just sets the RTS and DTR lines and returns.

Arguments:

    Port - Pointer to the serial port.

Return Value:

    TRUE.

--*/
{
    IO_STATUS_BLOCK     iosb;
    NTSTATUS            status;
    KEVENT              event;

    PAGED_CODE();

    Print(DeviceExtension, DBG_SS_TRACE, ("MSerPowerUp called\n"));

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Clear DTR
    //
    Print(DeviceExtension, DBG_SS_NOISE, ("Clearing DTR...\n"));
    status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_CLR_DTR,
                                    DeviceExtension->TopOfStack, 
                                    &event,
                                    &iosb
                                    );

    if (!NT_SUCCESS(status)) {
        return status;  
    }
                
    //
    // Clear RTS
    //
    Print(DeviceExtension, DBG_SS_NOISE, ("Clearing RTS...\n"));
    status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_CLR_RTS,
                                    DeviceExtension->TopOfStack, 
                                    &event,
                                    &iosb
                                    );
    if (!NT_SUCCESS(status)) {
        return status;
    }
                
    //
    // Set a timer for 200 ms
    //
    status = SerialMouseWait(DeviceExtension, -PAUSE_200_MS);
    if (!NT_SUCCESS(status)) {
        Print(DeviceExtension, DBG_SS_ERROR,
              ("Timer failed with status %x\n", status ));
        return status;      
    }

    //
    // set DTR
    //
    Print(DeviceExtension, DBG_SS_NOISE, ("Setting DTR...\n"));
    status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_SET_DTR,
                                    DeviceExtension->TopOfStack, 
                                    &event,
                                    &iosb
                                    );
    if (!NT_SUCCESS(status)) {
        return status;
    }
        
    status = SerialMouseWait(DeviceExtension, -PAUSE_200_MS);
    if (!NT_SUCCESS(status)) {
            Print(DeviceExtension, DBG_SS_ERROR,
              ("Timer failed with status %x\n", status ));
        return status;
    }                                 

    // 
    // set RTS      
    //
    Print(DeviceExtension, DBG_SS_NOISE, ("Setting RTS...\n"));
    status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_SET_RTS,
                                    DeviceExtension->TopOfStack, 
                                    &event,
                                    &iosb
                                    );

    status = SerialMouseWait(DeviceExtension, -175 * MS_TO_100_NS);
    if (!NT_SUCCESS(status)) {
        Print(DeviceExtension, DBG_SS_ERROR,
        ("Timer failed with status %x\n", status ));
        return status;
    }                                 

    return status;
}

NTSTATUS
MSerPowerDown(
    PDEVICE_EXTENSION   DeviceExtension 
    )
/*++

Routine Description:

    Powers down the mouse. Sets the RTS line to an inactive state.

Arguments:

    Port - Pointer to the serial port.

Return Value:

    TRUE.

--*/
{
    IO_STATUS_BLOCK     iosb;
    SERIAL_HANDFLOW     shf;
    KEVENT              event;
    NTSTATUS            status;
    ULONG               bits;

    PAGED_CODE();

    Print(DeviceExtension, DBG_SS_TRACE, ("MSerPowerDown called\n"));

    KeInitializeEvent(&event,
                      NotificationEvent,
                      FALSE
                      );

#if 0
    //
    // Set the handflow to default values
    //
    Print(DeviceExtension, DBG_SS_NOISE,
          ("Setting handflow to default values...\n"));
    shf.ControlHandShake = SERIAL_DTR_CONTROL;
    shf.FlowReplace = SERIAL_RTS_CONTROL;
    shf.XonLimit = 0;
    shf.XoffLimit = 0;
    status = SerialMouseIoSyncIoctlEx(IOCTL_SERIAL_SET_HANDFLOW,
                                      DeviceExtension->TopOfStack, 
                                      &event,
                                      &iosb,
                                      &shf,
                                      sizeof(SERIAL_HANDFLOW),
                                      NULL,
                                      0);
    if (!NT_SUCCESS(status)) {
        return status;
    }
#endif

    //
    // Set DTR
    //
    Print(DeviceExtension, DBG_SS_NOISE, ("Setting DTR...\n"));
    status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_SET_DTR,
                                    DeviceExtension->TopOfStack, 
                                    &event,
                                    &iosb);
    if (!NT_SUCCESS(status)) {
        return status; 
    }
        
    //
    // Clear RTS
    //
    Print(DeviceExtension, DBG_SS_NOISE, ("Clearing RTS...\n"));
    status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_CLR_RTS,
                                    DeviceExtension->TopOfStack, 
                                    &event,
                                    &iosb);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Set a timer for 200 ms
    //
    status = SerialMouseWait(DeviceExtension, -PAUSE_200_MS);
    if (!NT_SUCCESS(status)) {
        Print(DeviceExtension, DBG_SS_ERROR,
              ("Timer failed with status %x\n", status));
       return status;
    }
    
    return status;
}

#define BUFFER_SIZE 256
    
MOUSETYPE
MSerDetect(
    PDEVICE_EXTENSION DeviceExtension
    )
/*++

Routine Description:

    Detection code for pointing devices that identify themselves at 
    power on time.

Arguments:

    Port - Pointer to the serial port.

    BaudClock - The external frequency driving the serial chip.

Return Value:

    The type of mouse detected.

--*/
{
    ULONG           count = 0;
    MOUSETYPE       mouseType = NO_MOUSE;
    NTSTATUS        status;
    ULONG           i;
    CHAR            receiveBuffer[BUFFER_SIZE];

    PAGED_CODE();

    Print(DeviceExtension, DBG_SS_TRACE,
          ("MSerDetect enter\n"));

    status = SerialMouseInitializePort(DeviceExtension);
    if (!NT_SUCCESS(status)) {
        Print(DeviceExtension, DBG_SS_ERROR,
              ("Initializing the port failed (%x)\n", status));
        // return status;
    }

    status = MSerPowerDown(DeviceExtension);
    if (!NT_SUCCESS(status)) {
        Print(DeviceExtension, DBG_SS_ERROR,
              ("PowerDown failed (%x)\n", status));
        // return status;
    }

    //
    // Set the baud rate.
    //
    SerialMouseSetBaudRate(DeviceExtension, MSER_BAUDRATE);

    //
    // Set the data format so that the possible answer can be recognized.
    //
    SerialMouseSetLineCtrl(DeviceExtension,
                           &Protocol[MSER_PROTOCOL_MP].LineCtrl);

    //
    // Clean possible garbage in uart input buffer.
    //
    SerialMouseFlushReadBuffer(DeviceExtension);

    status = MSerPowerUp(DeviceExtension);
    if (!NT_SUCCESS(status)) {
        Print(DeviceExtension, DBG_SS_ERROR, ("Powerup failed (%x)\n", status));
    }
        
    //
    // Get the possible first reset character ('M' or 'B'), followed
    // by any other characters the hardware happens to send back.
    //
    // Note:  Typically, we expect to get just one character ('M' or
    //        'B'), perhaps followed by a '2' or '3' (to indicate the
    //        number of mouse buttons.  On some machines, we're
    //        getting extraneous characters before the 'M'.
    //        We get extraneous characters after the expected data if this a 
    //        true PnP comm device
    //

    ASSERT(CSER_POWER_UP >= MINIMUM_RESET_TIME);

    status = SerialMouseSetReadTimeouts(DeviceExtension, 200);

    if (NT_SUCCESS(SerialMouseReadChar(DeviceExtension,
                                       &receiveBuffer[count]))) {

        count++;
        SerialMouseSetReadTimeouts(DeviceExtension, 100);

        while (count < (BUFFER_SIZE - 1)) { 
            if (NT_SUCCESS(SerialMouseReadChar(DeviceExtension,
                                               &receiveBuffer[count]))) {
                count++;
            } else {
                break;
            }
        } 
    }

    *(receiveBuffer + count) = 0;

    Print(DeviceExtension, DBG_SS_NOISE, ("Receive buffer:\n"));
    for (i = 0; i < count; i++) {
        Print(DeviceExtension, DBG_SS_NOISE, ("\t0x%x\n", receiveBuffer[i]));
    }

    //
    //
    // Analyze the possible mouse answer.  Start at the beginning of the 
    // "good" data in the receive buffer, ignoring extraneous characters 
    // that may have come in before the 'M' or 'B'.
    //

    for (i = 0; i < count; i++) {
        if (receiveBuffer[i] == 'M') {
            if (receiveBuffer[i + 1] == '3') {
                Print(DeviceExtension, DBG_SS_INFO,
                      ("Detected MSeries 3 buttons\n"));
                mouseType = MOUSE_3B;
            }
            else if (receiveBuffer[i + 1] == 'Z') {
                Print(DeviceExtension, DBG_SS_INFO,
                      ("Detected Wheel Mouse\n"));
                mouseType = MOUSE_Z;
            }
            else {
                Print(DeviceExtension, DBG_SS_INFO,
                      ("Detected MSeries 2 buttons\n"));
                mouseType = MOUSE_2B;
            }
            break;
        } else if (receiveBuffer[i] == 'B') {
            Print(DeviceExtension, DBG_SS_INFO,
                  ("Detected Ballpoint\n"));
            mouseType = BALLPOINT;
            break;
        }
    }

    if (i >= count) {

        //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -