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

📄 device.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 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_NT
const 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_NT

PFNVOID 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>
//

HANDLE
FS_RegisterDevice(
    LPCWSTR lpszType,
    DWORD   dwIndex,
    LPCWSTR lpszLib,
    DWORD   dwInfo
    )
{
    return RegisterDeviceEx(
                lpszType,
                dwIndex,
                lpszLib,
                dwInfo,
                MAX_LOAD_ORDER+1
                );
}

HANDLE
RegisterDeviceEx(
    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 + -