Note: 剖析 ACPIEC Part II – AddDevice & Create Device Object

還是把 AcpiEcAddDevice 拿出來, 基本做的就一般 Function/Filter driver要做的事!
AddDevice會由PNP Manager 傳進兩個Parameters, 一個是 本身的Driver Object 另一個是Physical Device Object
一開始會按照標準的Function Driver 一般去建立 FDO (Function Device Object), 這是透過AcpiEcCreateFdo() 來實現的

在AcpiEcCreateFdo()內就是簡單的呼叫 IoCreateDevice() 去Create該FDO, 取得FDO 之後, 將其參數初始化與建立同步物件

取得FDO後, 透過 IoAttachDeviceToDeviceStack() 把FDO掛上

NTSTATUS
AcpiEcAddDevice(
IN PDRIVER_OBJECT   DriverObject,
IN PDEVICE_OBJECT   Pdo
)

/*++

Routine Description:

This routine creates functional device objects for each AcpiEc controller in the
system and attaches them to the physical device objects for the controllers

Arguments:

DriverObject       – a pointer to the object for this driver
PDO                  – a pointer to where the FDO is placed

Return Value:

Status from device creation and initialization

–*/

{
PDEVICE_OBJECT  fdo = NULL;
PDEVICE_OBJECT  ownerDevice = NULL;
PDEVICE_OBJECT  lowerDevice = NULL;
PECDATA         EcData;
NTSTATUS        status;

PAGED_CODE();

EcPrint(EC_LOW, (“AcpiEcAddDevice: Entered with pdo %xn", Pdo));

if (Pdo == NULL) {

//
// Have we been asked to do detection on our own?
// if so just return no more devices
//

EcPrint(EC_LOW, (“AcpiEcAddDevice – asked to do detectionn"));
return STATUS_NO_MORE_ENTRIES;
}

//
// Create and initialize the new functional device object
//

status = AcpiEcCreateFdo(DriverObject, &fdo);

if (!NT_SUCCESS(status)) {

EcPrint(EC_LOW, (“AcpiEcAddDevice – error creating Fdon"));
return status;
}

//
// Layer our FDO on top of the PDO
//

lowerDevice = IoAttachDeviceToDeviceStack(fdo,Pdo);

//
// No status. Do the best we can.
//
ASSERT(lowerDevice);

EcData = fdo->DeviceExtension;
EcData->LowerDeviceObject = lowerDevice;
EcData->Pdo = Pdo;

//
// Allocate and hold an IRP for Query notifications, and miscellaneous
//
EcData->IrpSize         = IoSizeOfIrp (EcData->LowerDeviceObject->StackSize);
EcData->QueryRequest    = IoAllocateIrp (EcData->LowerDeviceObject->StackSize, FALSE);
EcData->MiscRequest     = IoAllocateIrp (EcData->LowerDeviceObject->StackSize, FALSE);

if ((!EcData->QueryRequest) || (!EcData->MiscRequest)) {
//
// NOTE: This failure case and other failure cases below should do
// cleanup of all previous allocations, etc performed in this function.
//

EcPrint(EC_ERROR, (“AcpiEcAddDevice: Couldn’t allocate Irpn"));
return STATUS_INSUFFICIENT_RESOURCES;
}

//
// Link this fdo to the list of fdo’s managed by the driver
// (Probably overkill since there will be only one FDO)
//
//
EcPrint(EC_LOW, (“AcpiEcAddDevice: linking fdo to listn"));
EcData->NextFdo = FdoList;
InterlockedExchangePointer((PVOID *) &FdoList, fdo);

//
// Get the GPE vector assigned to this device
//

status = AcpiEcGetGpeVector (EcData);
if (!NT_SUCCESS(status)) {

EcPrint(EC_LOW, (“AcpiEcAddDevice: Could not get GPE vector, status = %Lxn", status));
return status;
}

//
// Get the direct-call ACPI interfaces.
//

status = AcpiEcGetAcpiInterfaces (EcData);
if (!NT_SUCCESS(status)) {

EcPrint(EC_LOW, (“AcpiEcAddDevice: Could not get ACPI driver interfaces, status = %Lxn", status));
return status;
}

//
// Final flags
//

fdo->Flags &= ~DO_DEVICE_INITIALIZING;
fdo->Flags |= DO_POWER_PAGABLE;             // Don’t want power Irps at irql 2

return STATUS_SUCCESS;
}

 

NTSTATUS
AcpiEcCreateFdo(
IN PDRIVER_OBJECT   DriverObject,
OUT PDEVICE_OBJECT  *NewDeviceObject
)

/*++

Routine Description:

This routine will create and initialize a functional device object to
be attached to a Embedded controller PDO.

Arguments:

DriverObject – a pointer to the driver object this is created under
DeviceObject – a location to store the pointer to the new device object

Return Value:

STATUS_SUCCESS if everything was successful
reason for failure otherwise

–*/

{
UNICODE_STRING  unicodeString;
PDEVICE_OBJECT  deviceObject;
NTSTATUS        Status;
PECDATA         EcData;

PAGED_CODE();

EcPrint(EC_LOW, (“AcpiEcCreateFdo: Entryn") );

RtlInitUnicodeString(&unicodeString, L"\Device\ACPIEC");

Status = IoCreateDevice(
DriverObject,
sizeof (ECDATA),
&unicodeString,
FILE_DEVICE_UNKNOWN,    // DeviceType
0,
FALSE,
&deviceObject
);

if (Status != STATUS_SUCCESS) {
EcPrint(EC_LOW, (“AcpiEcCreateFdo: unable to create device object: %Xn", Status));
return(Status);
}

deviceObject->Flags |= DO_BUFFERED_IO;
deviceObject->StackSize = 1;

//
// Initialize EC device extension data
//

EcData = (PECDATA) deviceObject->DeviceExtension;
EcData->DeviceObject        = deviceObject;
EcData->DeviceState         = EC_DEVICE_WORKING;
EcData->QueryState          = EC_QUERY_IDLE;
EcData->IoState             = EC_IO_NONE;
EcData->IsStarted           = FALSE;
EcData->MaxBurstStall       = 50;
EcData->MaxNonBurstStall    = 10;
EcData->InterruptEnabled    = TRUE;

//
// Initialize EC global synchronization objects
//

InitializeListHead (&EcData->WorkQueue);
KeInitializeEvent (&EcData->Unload, NotificationEvent, FALSE);
KeInitializeSpinLock (&EcData->Lock);

*NewDeviceObject = deviceObject;
return STATUS_SUCCESS;

}

 

廣告

6 回應 to “Note: 剖析 ACPIEC Part II – AddDevice & Create Device Object”

  1. 版主你好,小弟目前在寫HID Driver(Driver的功用為:對OS層能跟Win8 airplane mode UI溝通,對BIOS層能跟ACPI Device溝通,進而達到OS與BIOS無線裝置狀態一至之目的。

    現階段在BIOS 端增加了一個ACPI Device,在系統Device Manager會看到一個Unknow Device,目前想法是把ACPI Driver在做的事放到HID Driver裡,來收NB鍵盤Fn Key被按下後BIOS Notify出來的訊息進而做一些運用),但看了"ACPI Driver Interface in Windows Vista"這分資料後觀念還是很薄弱,看了你po的這段code,這行"EcData = fdo->DeviceExtension;"也是看不懂,網路及書店這方面資訊有限,不知版主是否還有其它文件資料可供參考,感激不盡。

    ps:
    1. 開發環境–>Visual Studio 2012 + WDK8
    2. 實驗環境–>Windows 8 32bit

    MSN and Mail: hbo971@hotmail.com

    • Hbo971 你好, 基本上按照你的需求 是沒必要做成HID的

      如果你硬要做成HID 也是可以,

      那個BIOS 透過ACPI 弄了一個Device Node 出來是 WHQL 的需求, 不管要不要這個功能
      VISTA 以上的OS要過WHQL 必須要有一個HOTKEY DRIVER

      建議你去找一下WDK內的 WMI-ACPI 的相關範例, 比這個ACPI Driver 簡單很多
      這方面資料只能網路多找找 對岸BIOSREN 網站好像有人放出一個比較完整的範例不過也是看DDK/WDK 改的

      DeviceExtension 這行看不懂的話, 表示你沒有Windows Driver 的基礎!

      如果你真的要ACPI to HID driver, intel 有寫過一個 參考下面
      https://kunyichen.wordpress.com/2008/11/27/%e9%97%9c%e6%96%bc-acpi-driver-for-windows-os/
      該篇的link 我已經修正了

      • 版主感謝你給的方向,會想做成HID Driver是因為在微軟一分文件中建議使用KMDF的方式寫一隻HID Driver來完成這樣的功能(因為airplane mode UI有被定義在HID裡頭,可透過HID driver來跟它作互動,WMI是否能跟airplane mode UI互動這方面就不太清楚了),所以才想說利用這樣的方式來完成,我先study一下intel的source code在看有什麼想法在像你請教,感謝回覆。

      • 我看了一下 原來是win8 新功能, 看起來是一定要用HID 的型式了

        我不清楚你們的設計
        不過MS 有提供一個 USB to HID WDF Driver http://code.msdn.microsoft.com/windowshardware/Radio-Switch-Test-Driver-0eb8f876/view/Discussions#content

        Intel 那各式GPIO to HID 而且是比較繁瑣 DDK/WDM 型式
        因為沒碰Win8 所以不是很清楚你的需求

    • Hello hbo971, 我也在弄這個airplane mode driver,目前也是很頭大,因為WDM的範例跟WDF差異很大,而文件中又規定一定要用KMDF規格…
      微軟自己提供的wdf driver sample幾乎查不到關於ACPI的東西…不知道您有甚麼進展嗎?

  2. 今天突然看到上面幾位所需的功能, 應該可以透過 WDK 下的 hid\hidusbfx2 去改成 KMDF HID Mapper 要透過ACPI 就參考 Intel 那個
    不過我想上面幾位應該已經結案才是 😛
    仔細一看跟我上面提到的 Microsoft 應該是同一個範例
    看的懂 這幾隻程式的人一定可以做出 ACPI KMDF 的HID driver

    for windows 8 的 HID report 也是現成的!
    http://msdn.microsoft.com/en-us/library/windows/hardware/jj128401(v=vs.85).aspx

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

%d 位部落客按了讚: