访问硬件示例 访问键盘控制器

控制一个芯片首先要知道它的地址,大多数PC上的8259键盘控制器在地址0x60和0x64上是可寻址的,这些位置有时称为端口(port),因为它们提供了进入硬件芯片的入口。

在使用DDK时,有多个宏可以读写这些端口:

READ_PORT_UCHAR ();

WRITE_PORT_UCHAR();

另外也可以使用汇编指令.

示例代码如下所示,感兴趣的话可以自己试试:

#include "ntddk.h"

#include "stdio.h" // use for _snprintf

//#include <wdm.h>

//#define RTL_STRING_CONST(x) \

//       (sizeof(L##x)-2, sizeof(L##x), L##x)

PKTIMER gTimer;

PKDPC gDPCP;

UCHAR g_key_bits = 0;

// command bytes

#define SET_LEDS       0xED

#define KEY_RESET      0xFF

 

// responses from keyboard

#define KEY_ACK        0xFA    // ack

#define KEY_AGAIN      0xFE    // send again

 

// 8042 ports

// When you read from port 60, this is called STATUS_BYTE.

// When you write to port 60, this is called COMMAND_BYTE/

// Read and write on port 64 is called DATA_BYTE.

PUCHAR KEYBOARD_PORT_60 = ( PUCHAR )0x60;

PUCHAR KEYBOARD_PORT_64 = ( PUCHAR )0x64;

 

// status register bits

#define IBUFFER_FULL   0x02

#define OBUFFER_FULL   0x01

 

// flags for keyboard LEDS

#define SCROLL_LOCK_BIT   (0x01 << 0)

#define NUMLOCK_BIT       (0x01 << 1)

#define CAPS_LOCK_BIT     (0x01 << 2)

 

ULONG WaitForKeyboard()

{

         char _t[255];

         int i = 100;   // number of times to loop

         UCHAR mychar;

         DbgPrint("waiting for keyboard to become accessible\n");

         do

         {

                   mychar = READ_PORT_UCHAR ( KEYBOARD_PORT_64 );

                   KeStallExecutionProcessor(50);

                   _snprintf(_t, 253, "WatiForKeyboard::read byte %02X from port 0x64\n", mychar);

    DbgPrint(_t);

                   if(!(mychar & IBUFFER_FULL)) break// if the flag is clear, we go ahead

         }

         while (i--);

         if(i) return TRUE;

         return FALSE;

}

 

 

// Call WaitForKeyboard before calling this function

void DrainOutputBuffer()

{

         char _t[255];

         int i = 100; // number of times to loop

         UCHAR c;

         DbgPrint("draining keyboard buffer\n");

         do

         {

                   c = READ_PORT_UCHAR(KEYBOARD_PORT_64);

                   KeStallExecutionProcessor(666);

                   _snprintf(_t, 253, "DrainOutputBuffer::read byte %02X from port 0x64\n", c);

                   DbgPrint(_t);

                   if(!(c & OBUFFER_FULL)) break; // if the flag is clear, we go ahead.

 

                   // Gobble up the byte in the output buffer.

                   c = READ_PORT_UCHAR(KEYBOARD_PORT_60);

                   _snprintf(_t, 253, "DrainOutputBuffer::read byte %02X from port 0x60\n", c);

                   DbgPrint(_t);

         }

         while (i--);

}

 

// Write a byte to the data port at 0x60

ULONG SendKeyboardCommand ( IN UCHAR theCommand)

{

         char _t[255];

         if ( TRUE == WaitForKeyboard ( ) )

         {

                   DrainOutputBuffer();

                   _snprintf(_t, 253, "SendKeyboardCommand::sending byte %02X to port 0x60\n", theCommand);

                   DbgPrint(_t);

                   WRITE_PORT_UCHAR ( KEYBOARD_PORT_60, theCommand );

                   DbgPrint("SendKeyboardCommand::sent\n");

         }

         else

         {

                   DbgPrint("SendKeyboardCommand::timeout waiting for keyboard\n");

                   return FALSE;

         }

 

         return TRUE;

}

 

void SetLEDS ( UCHAR theLEDS)

{

         // setup for setting LEDS

         if ( FALSE == SendKeyboardCommand ( 0xED ) )

         {

                   DbgPrint("SetLEDS::error sending keyboard command\n");

         }

         // send the flags for the LEDS

         if ( FALSE == SendKeyboardCommand ( theLEDS ) )

         {

                   DbgPrint("SetLEDS::error sending keyboard command\n");

         }

}

 

// called perodically

VOID timerDPC ( IN PKDPC Dpc,

                     IN PVOID DeferredContext,

                                     IN PVOID sys1,

                                     IN PVOID sys2 )

{

         // WRITE_PORT_UCHAR ( KEYBOARD_PORT_64, 0xFE );

         SetLEDS ( g_key_bits++ );

         if ( g_key_bits > 0x07 ) g_key_bits = 0;

}

 

 

// End keyboar code

 

void Example1Unload(IN PDRIVER_OBJECT pDrvobj)

{

         UNICODE_STRING usDosDevName;

         DbgPrint("Example1: Driver is being unload.\n");

 

         RtlInitUnicodeString(&usDosDevName, L"\\DosDevices\\ExampleLINK2");

         IoDeleteSymbolicLink(&usDosDevName);

         IoDeleteDevice(pDrvobj->DeviceObject);

 

         // Keyboard unload code

    KeCancelTimer ( gTimer );

         ExFreePool ( gTimer );

         ExFreePool ( gDPCP );

         // Keyboard end

}

 

NTSTATUS ExampleIrp(IN PDEVICE_OBJECT device, IN PIRP pIrp)

{

//       pDev;

//       pIrp;

         DbgPrint("An driver routine is called.\n");

         return STATUS_SUCCESS;

}

 

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDrvObj, IN PUNICODE_STRING pUsRegPath)

{

         NTSTATUS status = STATUS_UNSUCCESSFUL;

         UNICODE_STRING usDevName;

         UNICODE_STRING usDosDevName;

         PDEVICE_OBJECT pDevObj = NULL;

         unsigned int nIndex;

         LARGE_INTEGER timeout;

         DbgPrint("Example: Driver entry is called. \n");

 

         // Keyboard code start

         // WRITE_PORT_UCHAR ( 0x60, 0xED );

         // WRITE_PORT_UCHAR ( 0x60, 0x0000111b);

        

         timeout.QuadPart = -10;

        

         // These objects must be non-paged

         gTimer = ExAllocatePool ( NonPagedPool, sizeof ( KTIMER ) );

         gDPCP = ExAllocatePool ( NonPagedPool, sizeof ( KDPC ) );

        

 

         KeInitializeTimer ( gTimer );

         KeInitializeDpc ( gDPCP, timerDPC, NULL );

         if ( TRUE == KeSetTimerEx ( gTimer, timeout, 1000, gDPCP ) )

         {

                   DbgPrint("Timer was already queued .. ");

         }

 

//       usDevName = RTL_CONSTANT_STRING(L"\\Device\\Example3");

//       usDosDevName = RTL_CONSTANT_STRING(L"\\DosDevice\\Example3");

         RtlInitUnicodeString(&usDevName, L"\\Device\\Example3");

         RtlInitUnicodeString(&usDosDevName, L"\\DosDevices\\ExampleLINK2");

 

         // Create Device

         status = IoCreateDevice(pDrvObj, 0, &usDevName, FILE_DEVICE_UNKNOWN,

                   FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);

 

         if(NT_SUCCESS(status))

         {

                   for(nIndex = 0; nIndex < IRP_MJ_MAXIMUM_FUNCTION; ++nIndex)

                            pDrvObj->MajorFunction[nIndex] = ExampleIrp;

 

                   pDrvObj->DriverUnload = Example1Unload;

 

                   // ã?ä¡ä¡§Ì?¦¨¨À?À¡êä?e¤¡äê?¤?¨°°?¨®?¨¹°y®?

                   pDrvObj->DeviceObject = pDevObj;

                   status = IoCreateSymbolicLink(&usDosDevName, &usDevName);

                   if(!NT_SUCCESS(status))

                   {

                            DbgPrint("IoCreateSymbolicLink failed.\n");

                            IoDeleteDevice(pDevObj);

 

                   }

                   else

                   {

                            DbgPrint("Successed!.\n");

                   }

                  

 

         }

         else

         {

                   DbgPrint("IoCreateDevice failed\n");

         }

 

    return status;

 

}

 

 

 

    

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值