?? device.c
字號:
/* File: device.c * * Purpose: WinCE device manager * * Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. *///// This module contains these functions:// FS_RegisterDevice// RegisterDeviceEx// DoFreeFSD// DoFreeDevice// WaitForFSDs// NotifyFSDs// IsValidDevice// FS_DeregisterDevice// FS_ActivateDevice// FindActiveByHandle// FS_DeactivateDevice// GetFSD// FormatDeviceName// LoadFSDThread// FS_LoadFSD// FS_LoadFSDEx// FS_CeResyncFilesys// FS_PowerAllDevices// FS_GetDeviceByIndex// FS_CreateDeviceHandle// FS_DevCloseFileHandle// FS_DevReadFile// FS_DevWriteFile// FS_DevSetFilePointer// FS_DevDeviceIoControl// FS_DevGetFileSize// FS_DevGetFileInformation// FS_DevFlushFileBuffers// FS_DevGetFileTime// FS_DevSetFileTime// FS_DevSetEndOfFile// FS_DevProcNotify// FS_CloseAllDeviceHandles// WinMain//#include <device.h>#include <devload.h>#include <devloadp.h>#include <cardserv.h>#include <console.h>#ifdef TARGET_NT#include <devemul.h>#include "proxy.h"#endif#ifdef INSTRUM_DEV#include <instrumd.h>#else#define ENTER_INSTRUM#define EXIT_INSTRUM_INIT#define EXIT_INSTRUM_DEINIT#define EXIT_INSTRUM_POWERDOWN#define EXIT_INSTRUM_POWERUP#define EXIT_INSTRUM_OPEN#define EXIT_INSTRUM_CLOSE#define EXIT_INSTRUM_READ#define EXIT_INSTRUM_WRITE#define EXIT_INSTRUM_SEEK#define EXIT_INSTRUM_IOCONTROL#endif // INSTRUM_DEV/* Device driver implementation */// @doc EXTERNAL OSDEVICE KERNEL// @module device.c - device driver support | Device driver support functions.// @topic WinCE Device Drivers | There are two types of device drivers. The// first type are specialized drivers. These are keyboard, mouse/touch screen,// and display drivers. These drivers have specialized interfaces. The other// type of driver is the stream based device driver model. Drivers following the// stream based model will need to export several functions and be initialized// before they can be used. They can be accessed through standard file APIs such// as OpenFile. The driver dll must export a set of entrypoints of the form// ttt_api, where ttt is the device id passed in lpszType to RegisterDevice, and// api is a required or optional API. The APIs required are: Init, Deinit, Open,// Close, Read, Write, Seek, and IOCtl.// Drivers which need interrupts can use kernel exported interrupt support // routines. To understand the interrupt model and functions please look at// <l Interrupt Support.Kernel Interrupt Support>// @xref <f RegisterDevice> <f DeregisterDevice> // <l Interrupt Support.Kernel Interrupt Support>// notes on handling of unloading of dlls while threads are in those dlls:// 1> routines which take the device critical section before calling into a dll do not need to// adjust the reference count since the deregister call takes the critical section// 2> routines which do not take the device critical section do the following:// a> check if the device is still valid [ if (fsodev->lpDev) ]// b> if so, increment the reference count, so dodec = 1, make call, decrement the reference count,// set dodec = 0// c> we assume we will not fault in the interlockedDecrement, since once we've succeeded in the// increment, we know we won't fault on the decrement since nobody will be LocalFree'ing the device// d> if we fault inside the actual function call, we'll do the decrement due to the dodec flag// 3> We signal an event when we put someone on the DyingDevs list. We can just poll from that point onwards// since (1) it's a rare case and (2) it's cheaper than always doing a SetEvent if you decrement the// reference count to 0.CRITICAL_SECTION g_devcs;LIST_ENTRY g_DevChain;LIST_ENTRY g_DyingDevs;fsopendev_t *g_lpOpenDevs;fsopendev_t *g_lpDyingOpens;HANDLE g_hDevApiHandle, g_hDevFileApiHandle, g_hCleanEvt, g_hCleanDoneEvt;fsd_t *g_lpFSDChain;//// Devload.c and pcmcia.c //typedef DWORD (*SYSTEMPOWER)(DWORD);extern SYSTEMPOWER pfnSystemPower;extern void DevloadInit(void);extern void DevloadPostInit(void);extern BOOL I_DeactivateDevice(HANDLE hDevice, LPWSTR ActivePath);extern HANDLE StartOneDriver(LPTSTR RegPath, LPTSTR PnpId, DWORD LoadOrder, DWORD ClientInfo, CARD_SOCKET_HANDLE hSock);#ifndef TARGET_NTconst PFNVOID FDevApiMethods[] = { (PFNVOID)FS_DevProcNotify, (PFNVOID)0, (PFNVOID)FS_RegisterDevice, (PFNVOID)FS_DeregisterDevice, (PFNVOID)FS_CloseAllDeviceHandles, (PFNVOID)FS_CreateDeviceHandle, (PFNVOID)FS_LoadFSD, (PFNVOID)FS_ActivateDevice, (PFNVOID)FS_DeactivateDevice, (PFNVOID)FS_LoadFSDEx, (PFNVOID)FS_GetDeviceByIndex, (PFNVOID)FS_CeResyncFilesys,};#define NUM_FDEV_APIS (sizeof(FDevApiMethods)/sizeof(FDevApiMethods[0]))const DWORD FDevApiSigs[NUM_FDEV_APIS] = { FNSIG3(DW, DW, DW), // ProcNotify FNSIG0(), FNSIG4(PTR, DW, PTR, DW), // RegisterDevice FNSIG1(DW), // DeregisterDevice FNSIG0(), // CloseAllDeviceHandles FNSIG4(PTR, DW, DW, DW), // CreateDeviceHandle FNSIG2(PTR, PTR), // LoadFSD FNSIG2(PTR, DW), // ActivateDevice FNSIG1(DW), // DeactivateDevice FNSIG3(PTR, PTR, DW), //LoadFSDEx FNSIG2(DW, PTR), // GetDeviceByIndex FNSIG1(DW), // CeResyncFilesys};const PFNVOID DevFileApiMethods[] = { (PFNVOID)FS_DevCloseFileHandle, (PFNVOID)0, (PFNVOID)FS_DevReadFile, (PFNVOID)FS_DevWriteFile, (PFNVOID)FS_DevGetFileSize, (PFNVOID)FS_DevSetFilePointer, (PFNVOID)FS_DevGetFileInformationByHandle, (PFNVOID)FS_DevFlushFileBuffers, (PFNVOID)FS_DevGetFileTime, (PFNVOID)FS_DevSetFileTime, (PFNVOID)FS_DevSetEndOfFile, (PFNVOID)FS_DevDeviceIoControl,};#define NUM_FAPIS (sizeof(DevFileApiMethods)/sizeof(DevFileApiMethods[0]))const DWORD DevFileApiSigs[NUM_FAPIS] = { FNSIG1(DW), // CloseFileHandle FNSIG0(), FNSIG5(DW,PTR,DW,PTR,PTR), // ReadFile FNSIG5(DW,PTR,DW,PTR,PTR), // WriteFile FNSIG2(DW,PTR), // GetFileSize FNSIG4(DW,DW,PTR,DW), // SetFilePointer FNSIG2(DW,PTR), // GetFileInformationByHandle FNSIG1(DW), // FlushFileBuffers FNSIG4(DW,PTR,PTR,PTR), // GetFileTime FNSIG4(DW,PTR,PTR,PTR), // SetFileTime FNSIG1(DW), // SetEndOfFile, FNSIG8(DW, DW, PTR, DW, PTR, DW, PTR, PTR), // DeviceIoControl};#endif // TARGET_NTPFNVOID FS_GetProcAddr(LPCWSTR type, LPCWSTR lpszName, HINSTANCE hInst) { WCHAR fullname[32]; memcpy(fullname,type,3*sizeof(WCHAR)); fullname[3] = L'_'; wcscpy(&fullname[4],lpszName); return (PFNVOID)GetProcAddress(hInst,fullname);}// @func HANDLE | RegisterDevice | Register a new device// @parm LPCWSTR | lpszType | device id (SER, PAR, AUD, etc) - must be 3 characters long// @parm DWORD | dwIndex | index between 0 and 9, ie: COM2 would be 2// @parm LPCWSTR | lpszLib | dll containing driver code// @parm DWORD | dwInfo | instance information// @rdesc Returns a handle to a device, or 0 for failure. This handle should// only be passed to DeregisterDevice.// @comm For stream based devices, the drivers will be .dll or .drv files.// Each driver is initialized by// a call to the RegisterDevice API (performed by the server process).// The lpszLib parameter is what will be to open the device. The// lpszType is a three character string which is used to identify the // function entry points in the DLL, so that multiple devices can exist// in one DLL. The lpszLib is the name of the DLL which contains the// entry points. Finally, dwInfo is passed in to the init routine. So,// if there were two serial ports on a device, and comm.dll was the DLL// implementing the serial driver, it would be likely that there would be// the following init calls:<nl>// <tab>h1 = RegisterDevice(L"COM", 1, L"comm.dll",0x3f8);<nl>// <tab>h2 = RegisterDevice(L"COM", 2, L"comm.dll",0x378);<nl>// Most likely, the server process will read this information out of a// table or registry in order to initialize all devices at startup time.// @xref <f DeregisterDevice> <l Overview.WinCE Device Drivers>//HANDLEFS_RegisterDevice( LPCWSTR lpszType, DWORD dwIndex, LPCWSTR lpszLib, DWORD dwInfo ){ return RegisterDeviceEx( lpszType, dwIndex, lpszLib, dwInfo, MAX_LOAD_ORDER+1 );}HANDLERegisterDeviceEx( LPCWSTR lpszType, DWORD dwIndex, LPCWSTR lpszLib, DWORD dwInfo, DWORD dwLoadOrder ){ HANDLE hDev = 0; fsdev_t *lpdev = 0, *lpTrav; DWORD retval = 0; DEBUGMSG(ZONE_DYING, (TEXT("DEVICE: About to wait on CleanDoneEvt.\r\n"))); // Need to wait for any filesystem devices to finish getting deregistered // before we go ahead and register them again. This gets around problems // with storage card naming. retval = WaitForSingleObject(g_hCleanDoneEvt, 5000); DEBUGMSG(ZONE_DYING, (TEXT("DEVICE: Got CleanDoneEvt.\r\n"))); ASSERT(retval != WAIT_TIMEOUT); retval = ERROR_SUCCESS; // Initialize for success if (dwIndex > 9) { retval = ERROR_INVALID_PARAMETER; goto errret; } if (!(lpdev = LocalAlloc(LPTR,sizeof(fsdev_t)))) { retval = ERROR_OUTOFMEMORY; goto errret; } __try { memset(lpdev, 0, sizeof(fsdev_t)); memcpy(lpdev->type,lpszType,sizeof(lpdev->type)); lpdev->index = dwIndex; if (!(lpdev->hLib = LoadDriver(lpszLib))) { retval = ERROR_FILE_NOT_FOUND; } else { if (!(lpdev->fnInit = (pInitFn)FS_GetProcAddr(lpdev->type,L"Init",lpdev->hLib)) || !(lpdev->fnDeinit = (pDeinitFn)FS_GetProcAddr(lpdev->type,L"Deinit",lpdev->hLib)) || !(lpdev->fnOpen = (pOpenFn)FS_GetProcAddr(lpdev->type,L"Open",lpdev->hLib)) || !(lpdev->fnClose = (pCloseFn)FS_GetProcAddr(lpdev->type,L"Close",lpdev->hLib)) || !(lpdev->fnRead = (pReadFn)FS_GetProcAddr(lpdev->type,L"Read",lpdev->hLib)) || !(lpdev->fnWrite = (pWriteFn)FS_GetProcAddr(lpdev->type,L"Write",lpdev->hLib)) || !(lpdev->fnSeek = (pSeekFn)FS_GetProcAddr(lpdev->type,L"Seek",lpdev->hLib)) || !(lpdev->fnControl = (pControlFn)FS_GetProcAddr(lpdev->type,L"IOControl",lpdev->hLib))) { retval = ERROR_INVALID_FUNCTION; } else { // Got all the required functions. Now let's get the optional ones lpdev->fnPowerup = (pPowerupFn)FS_GetProcAddr(lpdev->type,L"PowerUp",lpdev->hLib); lpdev->fnPowerdn = (pPowerupFn)FS_GetProcAddr(lpdev->type,L"PowerDown",lpdev->hLib); } } } __except (EXCEPTION_EXECUTE_HANDLER) { retval = ERROR_INVALID_PARAMETER; } if (retval) { goto errret; } // Now enter the critical section to look for it in the device list EnterCriticalSection (&g_devcs); __try { // // check for uniqueness // for (lpTrav = (fsdev_t *)g_DevChain.Flink; lpTrav != (fsdev_t *)&g_DevChain; lpTrav = (fsdev_t *)(lpTrav->list.Flink)) { if (!memcmp(lpTrav->type,lpdev->type,sizeof(lpdev->type)) && (lpTrav->index == lpdev->index)) { retval = ERROR_DEVICE_IN_USE; break; } } } __except (EXCEPTION_EXECUTE_HANDLER) { retval = ERROR_INVALID_PARAMETER; } LeaveCriticalSection(&g_devcs); if (retval) { goto errret; } __try { ENTER_INSTRUM { lpdev->dwData = lpdev->fnInit(dwInfo); } EXIT_INSTRUM_INIT; if (!(lpdev->dwData)) { retval = ERROR_OPEN_FAILED; } else { // Sucess lpdev->PwrOn = TRUE; lpdev->dwLoadOrder = dwLoadOrder; } } __except (EXCEPTION_EXECUTE_HANDLER) { retval = ERROR_INVALID_PARAMETER; } if (retval) { goto errret; } EnterCriticalSection(&g_devcs); __try { // // Insert according to LoadOrder // for (lpTrav = (fsdev_t *)g_DevChain.Flink; lpTrav != (fsdev_t *)&g_DevChain; lpTrav = (fsdev_t *)(lpTrav->list.Flink)) { if (lpTrav->dwLoadOrder >= dwLoadOrder) { InsertHeadList((PLIST_ENTRY)lpTrav, (PLIST_ENTRY)lpdev); break; } } if (lpTrav == (fsdev_t *)&g_DevChain) { // insert at the end InsertTailList(&g_DevChain, (PLIST_ENTRY)lpdev); } hDev = (HANDLE)lpdev; } __except (EXCEPTION_EXECUTE_HANDLER) { retval = ERROR_INVALID_PARAMETER; } LeaveCriticalSection(&g_devcs);errret: #ifdef DEBUG if (ZONE_ACTIVE) { if (hDev != NULL) { DEBUGMSG(ZONE_ACTIVE, (TEXT("DEVICE: Name Load Order\r\n"))); // // Display the list of devices in ascending load order. // EnterCriticalSection(&g_devcs); for (lpTrav = (fsdev_t *)g_DevChain.Flink; lpTrav != (fsdev_t *)&g_DevChain; lpTrav = (fsdev_t *)(lpTrav->list.Flink)) { DEBUGMSG(ZONE_ACTIVE, (TEXT("DEVICE: %c%c%c%d: %d\r\n"), lpTrav->type[0], lpTrav->type[1], lpTrav->type[2], lpTrav->index, lpTrav->dwLoadOrder)); } LeaveCriticalSection(&g_devcs); } }#endif // If we failed then let's clean up the module and data if (retval) { SetLastError (retval); if (lpdev) { if (lpdev->hLib) { FreeLibrary(lpdev->hLib); } LocalFree (lpdev); } } return hDev;}void DoFreeFSD(pfsd_t pfsd){ pfsd_t pfsd1; if (pfsd->cFSDDevices <= 0) { FreeLibrary(pfsd->hFSDLib); if (pfsd == g_lpFSDChain) { g_lpFSDChain = pfsd->next; LocalFree(pfsd); return; } else { pfsd1 = g_lpFSDChain; while (pfsd1) { if (pfsd1->next == pfsd) { pfsd1->next = pfsd->next; LocalFree(pfsd); return; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -