www.pudn.com > camera.rar > qcibus.cpp
// // Copyright (c) Microsoft Corporation. All rights reserved. // // // Use of this sample source code is subject to the terms of the Microsoft // license agreement under which you licensed this sample source code. If // you did not accept the terms of the license agreement, you are not // authorized to use this sample source code. For the terms of the license, // please see the license agreement between you and Microsoft or, if applicable, // see the LICENSE.RTF on your install media or the root of your tools installation. // THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES. // // // (C) Copyright 2006 Marvell International Ltd. // All Rights Reserved // // // Routines to Bus Support the QCIbus // #include#include #include #include #include "qci.h" #include "qci_private.h" #ifdef DEBUG DBGPARAM dpCurSettings = { _T("QCIBUS"), { _T("Errors"), _T("Warnings"), _T("Init"), _T("Function"), _T("Ioctl"), _T("Device"), _T("Activity"), _T(""), _T(""),_T(""),_T(""),_T(""), _T(""),_T(""),_T(""),_T("") }, MASK_ERROR | MASK_WARN | MASK_INIT }; #endif SensorFolder::SensorFolder(LPCTSTR lpBusName,LPCTSTR lpTemplateRegPath,DWORD dwBusType, DWORD BusNumber,PCI_SLOT_NUMBER SlotNumber,HANDLE hParent) : DeviceFolder(lpBusName,lpTemplateRegPath,dwBusType,BusNumber,SlotNumber.u.bits.DeviceNumber,SlotNumber.u.bits.FunctionNumber, hParent) { } SensorFolder::~SensorFolder() { } // PCI Power Handling; BOOL SensorFolder::SetPowerState(CEDEVICE_POWER_STATE newPowerState) { return TRUE; } //-------------------------------------PCI Bus Driver ------------------------------------------------------- QciBus::QciBus(LPCTSTR lpActiveRegPath) : DefaultBusDriver(lpActiveRegPath), m_DeviceKey(lpActiveRegPath) { DEBUGMSG(ZONE_ENUM| ZONE_INIT,(TEXT("QciBus::QciBus (ActivateRegPath=%s)\r\n"),lpActiveRegPath)); // Get DEVLOAD_DEVKEY_VALNAME name m_lpActiveRegPath = NULL; HANDLE hThisDevice = GetDeviceHandleFromContext(lpActiveRegPath); if(hThisDevice != NULL) { DEVMGR_DEVICE_INFORMATION di; memset(&di, 0, sizeof(di)); di.dwSize = sizeof(di); if(GetDeviceInformationByDeviceHandle(hThisDevice, &di)) { DWORD dwKeyLen = wcslen(di.szDeviceKey) + 1; m_lpActiveRegPath = new TCHAR [dwKeyLen]; if ( m_lpActiveRegPath) { wcscpy(m_lpActiveRegPath, di.szDeviceKey); } LPCWSTR pszName = wcschr(di.szBusName, L'\\'); if(pszName != NULL) { pszName++; if(*pszName != 0) { dwKeyLen = wcslen(pszName) + 1; m_lpBusName = new TCHAR[dwKeyLen]; if (m_lpBusName) { wcscpy(m_lpBusName, pszName); } } } } } m_lpStrInitParam = NULL; m_dwNumOfInitParam =0 ; m_dwDeviceIndex = 0; } QciBus::~QciBus() { if (m_lpStrInitParam ) delete [] m_lpStrInitParam ; if (m_lpActiveRegPath) delete [] m_lpActiveRegPath; } #define BUSNAMEUNKNOWN TEXT("UnknownBus") BOOL QciBus::Init() { BOOL bReturn = FALSE; if (!QCIInitAll()) return FALSE; // Initialize InitParam if ( m_lpActiveRegPath==NULL || !m_DeviceKey.IsKeyOpened()) { DEBUGMSG(ZONE_ENUM|ZONE_ERROR,(TEXT("QciBus!Init RegOpenKeyEx() return FALSE!!!\r\n"))); return FALSE; } if (m_lpStrInitParam == NULL ) { DWORD dwKeyLen=0; DWORD dwType; // BC. It is BC with RegEnum We may want remove this later // What this key contain multi-string that indicate the reigstry has such name will copy into active registry if (m_DeviceKey.RegQueryValueEx(DEVLOAD_REPARMS_VALNAME, &dwType,NULL,&dwKeyLen) && dwType== REG_MULTI_SZ && dwKeyLen!=0 ) { dwKeyLen = (dwKeyLen + sizeof(TCHAR) -1 ) / sizeof(TCHAR); m_lpStrInitParam = new TCHAR [ dwKeyLen ]; if (m_lpStrInitParam) { if (m_DeviceKey.GetRegValue(DEVLOAD_REPARMS_VALNAME,(LPBYTE)m_lpStrInitParam,dwKeyLen * sizeof(TCHAR))) { DWORD dwUnitCount= dwKeyLen; for (LPTSTR lpCurPos = m_lpStrInitParam; m_dwNumOfInitParam< MAX_INITPARAM && dwUnitCount!=0 && *lpCurPos!=0 ; m_dwNumOfInitParam++) { m_lpInitParamArray[m_dwNumOfInitParam] = lpCurPos; while (*lpCurPos!=0 && dwUnitCount!=0 ) { lpCurPos++; dwUnitCount --; } if (dwUnitCount) { lpCurPos ++; dwUnitCount --; } else break; } } } } } // Scan And Enum All the driver in registry. if ( GetDeviceHandle()!=NULL && m_DeviceKey.IsKeyOpened()) { DWORD dwKeyLen=0; if (!m_DeviceKey.GetRegValue(DEVLOAD_INTERFACETYPE_VALNAME,(PUCHAR) &m_dwBusType,sizeof(m_dwBusType))) { // No interface type defined m_dwBusType=InterfaceTypeUndefined; }; if (!m_DeviceKey.GetRegValue(DEVLOAD_BUSNUMBER_VALNAME , (LPBYTE)&m_dwBusNumber,sizeof(m_dwBusNumber))) m_dwBusNumber=0; if ( AssignChildDriver() ) return TRUE; }; DEBUGMSG(ZONE_ENUM|ZONE_ERROR,(TEXT("QciBus!Init return FALSE!!!\r\n"))); return FALSE; }; BOOL QciBus::PostInit() { BOOL bReturn = FALSE; if ( GetDeviceHandle()!=NULL && m_DeviceKey.IsKeyOpened()) { bReturn=ActiveAllChildDriver(); }; return bReturn; } DWORD QciBus::GetBusNamePrefix(__out_ecount(dwSizeInUnit) LPTSTR lpReturnBusName,DWORD dwSizeInUnit) { if (m_lpBusName && lpReturnBusName && dwSizeInUnit) { DWORD dwCopyUnit = min(_tcslen(m_lpBusName) +1 , dwSizeInUnit); _tcsncpy(lpReturnBusName,m_lpBusName,dwCopyUnit); lpReturnBusName[dwCopyUnit-1]=0; return dwCopyUnit; } else return DefaultBusDriver::GetBusNamePrefix(lpReturnBusName,dwSizeInUnit); } BOOL QciBus::AssignChildDriver() { DWORD NumSubKeys; DWORD MaxSubKeyLen; DWORD MaxClassLen; DWORD NumValues; DWORD MaxValueNameLen; DWORD MaxValueLen; // Get info on Template Key BOOL bSuccess = m_DeviceKey.RegQueryInfoKey( NULL, // class name buffer (lpszClass) NULL, // ptr to length of class name buffer (lpcchClass) NULL, // reserved &NumSubKeys, // ptr to number of sub-keys (lpcSubKeys) &MaxSubKeyLen, // ptr to longest subkey name length (lpcchMaxSubKeyLen) &MaxClassLen, // ptr to longest class string length (lpcchMaxClassLen) &NumValues, // ptr to number of value entries (lpcValues) &MaxValueNameLen, // ptr to longest value name length (lpcchMaxValueNameLen) &MaxValueLen, // ptr to longest value data length (lpcbMaxValueData) NULL, // ptr to security descriptor length NULL); // ptr to last write time if (!bSuccess) { DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (TEXT("QciBus::RegCopyKey RegQueryInfoKey returned fails.\r\n"))); return FALSE; } // Recurse for each sub-key for (DWORD Key = 0; Key < NumSubKeys; Key++) { // Get TKey sub-key according to Key WCHAR ValName[DEVKEY_LEN]; DWORD ValLen = sizeof(ValName) / sizeof(WCHAR); if (! m_DeviceKey.RegEnumKeyEx( Key, ValName, &ValLen, NULL, NULL, NULL, NULL)){ DEBUGMSG(ZONE_ENUM, (TEXT("QciBus::RegCopyKey RegEnumKeyEx(%d) returned Error\r\n"), ValName)); break; } else { // Open sub-key under TKey CRegistryEdit TSubKey(m_DeviceKey.GetHKey(),ValName); if (!TSubKey.IsKeyOpened()) { DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (TEXT("QciBus::RegCopyKey RegOpenKeyEx(%s) returned Error\r\n"), ValName)); continue; } else { // Get Bus Info. DDKPCIINFO dpi; dpi.cbSize = sizeof (DDKPCIINFO); dpi.dwDeviceNumber = (DWORD)-1; dpi.dwFunctionNumber = (DWORD)-1; if (TSubKey.GetPciInfo(&dpi)!=ERROR_SUCCESS || dpi.dwDeviceNumber == (DWORD)-1 || dpi.dwFunctionNumber == (DWORD)-1) { dpi.dwDeviceNumber = m_dwDeviceIndex++; dpi.dwFunctionNumber = 0; } DWORD dwBusNumber = (DWORD)0; // We Create Foler for this driver. TCHAR lpChildPath[DEVKEY_LEN]; _tcsncpy(lpChildPath,m_lpActiveRegPath,DEVKEY_LEN-1); lpChildPath[DEVKEY_LEN-2] = 0; DWORD dwLen=_tcslen(lpChildPath); lpChildPath[dwLen]=_T('\\'); dwLen++; lpChildPath[dwLen]=0; _tcsncat(lpChildPath,ValName,DEVKEY_LEN-1-dwLen); lpChildPath[DEVKEY_LEN-1]=0; PCI_SLOT_NUMBER SlotNumber; SlotNumber.u.bits.DeviceNumber= dpi.dwDeviceNumber; SlotNumber.u.bits.FunctionNumber = dpi.dwFunctionNumber; SensorFolder * nDevice = new SensorFolder (m_lpBusName!=NULL?m_lpBusName:BUSNAMEUNKNOWN, lpChildPath,m_dwBusType,dwBusNumber,SlotNumber,GetDeviceHandle()); if (nDevice) InsertChild(nDevice); } } } return TRUE; } #define MAX_TEMP_BUFFER_SIZE 0x200 BOOL QciBus::ActiveAllChildDriver() { TakeReadLock(); SensorFolder * pCurDevice = (SensorFolder *)GetDeviceList (); while (pCurDevice) { DEBUGMSG(ZONE_ENUM,(TEXT("QciBus: Activate Child: Template reg path is %s\r\n"),pCurDevice->GetRegPath())); // Create Initial Active Registry. for (DWORD dwIndex=0; dwIndex< m_dwNumOfInitParam; dwIndex++) { BYTE tempBuffer[ MAX_TEMP_BUFFER_SIZE] ; DWORD dwSize=MAX_TEMP_BUFFER_SIZE; DWORD dwType; if (m_DeviceKey.IsKeyOpened() && m_DeviceKey.RegQueryValueEx(m_lpInitParamArray[dwIndex],&dwType, tempBuffer,&dwSize) ) { REGINI Reg; Reg.lpszVal = m_lpInitParamArray[dwIndex]; Reg.dwType = dwType; Reg.dwLen = dwSize; Reg.pData = tempBuffer; pCurDevice->AddInitReg(1, &Reg); DEBUGMSG(ZONE_ENUM,(TEXT("QciBus: Activate Child add %s to %s ActivePath\r\n"),m_lpInitParamArray[dwIndex],pCurDevice->GetRegPath())); } } pCurDevice =(SensorFolder *) pCurDevice->GetNextDeviceFolder(); } // Activate Device DWORD dwCurOrder = 0; while (dwCurOrder != MAXDWORD) { DEBUGMSG(ZONE_ENUM,(TEXT("QciBus: Activate Child LoaderDriver at order %d \r\n"),dwCurOrder)); DWORD dwNextOrder = MAXDWORD; pCurDevice = (SensorFolder *)GetDeviceList (); while (pCurDevice) { DWORD dwDeviceLoadOrder = pCurDevice->GetLoadOrder(); if ( dwDeviceLoadOrder == dwCurOrder) { SetLastError(0); BOOL rv = pCurDevice->LoadDevice(); } else if (dwDeviceLoadOrder> dwCurOrder && dwDeviceLoadOrder < dwNextOrder) dwNextOrder = dwDeviceLoadOrder; pCurDevice = (SensorFolder *)pCurDevice->GetNextDeviceFolder(); } dwCurOrder = dwNextOrder; } LeaveReadLock(); return TRUE; } BOOL QciBus::FastIOControl(DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut,DeviceFolder **ppDeviceFolder ) { BOOL rc = TRUE; switch (dwCode) { case IOCTL_QCI_SET_INTERFACE: if (pBufIn == NULL || dwLenIn < sizeof(qci_interface_t)) goto err; __try { //qci_set_interface((qci_interface_t*)pBufIn); QCISetInterface((qci_interface_t*)pBufIn); } __except( EXCEPTION_EXECUTE_HANDLER ) { goto err; } break; case IOCTL_QCI_CLOCK_ENABLE: { if (pBufIn == NULL || dwLenIn < sizeof(BOOL)) goto err; __try { QCIClockEnable(*(BOOL*)pBufIn); } __except( EXCEPTION_EXECUTE_HANDLER ) { goto err; } break; } case IOCTL_QCI_ENABLE: QCIEnable(); break; case IOCTL_QCI_SET_MASTER_TIMING: if (pBufIn == NULL || dwLenIn < sizeof(qci_master_timing_t)) goto err; __try { QCISetMasterTiming((qci_master_timing_t*)pBufIn); } __except( EXCEPTION_EXECUTE_HANDLER ) { goto err; } break; case IOCTL_QCI_SET_IMAGE_FORMAT: { if (pBufIn == NULL || dwLenIn < sizeof(int) * 2) goto err; int* in_format = (int*)pBufIn; int* out_format = in_format + 1; __try { QCISetImageFormat(*in_format, *out_format); } __except( EXCEPTION_EXECUTE_HANDLER ) { goto err; } } break; case IOCTL_QCI_START_CAPTURE: { int still_skips; __try { still_skips = *(int*)pBufIn; } __except( EXCEPTION_EXECUTE_HANDLER ) { goto err; } QCICaptureStart(still_skips); break; } case IOCTL_QCI_STOP_CAPTURE: QCICaptureStop(); break; case IOCTL_QCI_SET_CAPTURE_CALLBACK: { if (pBufIn == NULL || dwLenIn < sizeof(callback_data_t)) goto err; callback_data_t* callback_data = (callback_data_t*)pBufIn; __try { QCIAddCallBack(callback_data); } __except( EXCEPTION_EXECUTE_HANDLER ) { goto err; } } break; case IOCTL_QCI_NOTIFY_FORMAT: { if (pBufIn == NULL || dwLenIn < sizeof(format_t)) goto err; format_t* format = (format_t*) pBufIn; QCIDMAPrepareFormat(format); } case IOCTL_QCI_SET_FRAME_FORMAT: { if (pBufIn == NULL || dwLenIn < sizeof(format_t)) goto err; format_t* format = (format_t*) pBufIn; QCIDMASetFrameFormat(format); } break; case IOCTL_QCI_SET_IMAGE_PROC_CFG: __try { QCIImageProcCfg((qci_image_proc_cfg_t*)pBufIn); } __except( EXCEPTION_EXECUTE_HANDLER ) { goto err; } break; default: return DefaultBusDriver::FastIOControl(dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut, ppDeviceFolder); break; } return rc; err: DEBUGMSG(ZONE_IOCTL,(L"QciBus: IOCTL 0x%x failed for invalid parameter\r\n",dwCode)); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } extern "C" void QCI_Deinit (DWORD dwData) { DefaultBusDriver * pBusDriver = (DefaultBusDriver*) dwData; if (pBusDriver != NULL) delete pBusDriver; } extern "C" BOOL QCI_PowerUp(DWORD dwData) { //power_on(); QCIPowerOn(); return TRUE; } extern "C" BOOL QCI_PowerDown(DWORD dwData) { return TRUE; } #define FASTBUSACCESS_TAG 0xDEFBa51e typedef struct __FASTBUSACCESSHANDLE { DWORD dwHandleTag; DefaultBusDriver * pBusDriver; DeviceFolder * pDeviceFolder; } FASTBUSACCESSHANDLE, *PFASTBUSACCESSHANDLE ; extern "C" HANDLE QCI_Open( HANDLE pHead, // @parm Handle returned by COM_Init. DWORD AccessCode, // @parm access code. DWORD ShareMode // @parm share mode - Not used in this driver. ) { DefaultBusDriver * pBusDriver = (DefaultBusDriver * )pHead; if (pBusDriver && pBusDriver->Open(AccessCode,ShareMode)) { PFASTBUSACCESSHANDLE pFastAccessHandle = new FASTBUSACCESSHANDLE; if (pFastAccessHandle) { pFastAccessHandle->dwHandleTag = FASTBUSACCESS_TAG; pFastAccessHandle->pBusDriver = pBusDriver; pFastAccessHandle->pDeviceFolder = NULL ; return (HANDLE)pFastAccessHandle; } else pBusDriver->Close(); } return NULL; } extern "C" BOOL QCI_Close(HANDLE pOpenHead) { PFASTBUSACCESSHANDLE pFastAccessHandle = (PFASTBUSACCESSHANDLE) pOpenHead ; if (pFastAccessHandle && pFastAccessHandle->dwHandleTag ==FASTBUSACCESS_TAG ) { pFastAccessHandle->pBusDriver->Close(); delete pFastAccessHandle ; } return FALSE; } extern "C" BOOL QCI_IOControl(HANDLE pOpenHead, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) { PFASTBUSACCESSHANDLE pFastAccessHandle = (PFASTBUSACCESSHANDLE) pOpenHead ; if (pFastAccessHandle && pFastAccessHandle->dwHandleTag ==FASTBUSACCESS_TAG ) return pFastAccessHandle->pBusDriver->FastIOControl(dwCode,pBufIn,dwLenIn,pBufOut,dwLenOut,pdwActualOut, &(pFastAccessHandle->pDeviceFolder)); return FALSE; } // // driver entry point. // extern "C" DWORD QCI_Init(DWORD key) { QciBus * pQCI = new QciBus((LPCTSTR)key); if (pQCI) { if (pQCI->Init()) return (DWORD)pQCI; else delete pQCI; } return NULL; } extern "C" BOOL WINAPI DllEntry(HINSTANCE DllInstance, INT Reason, LPVOID Reserved) { switch(Reason) { case DLL_PROCESS_ATTACH: DEBUGREGISTER(DllInstance); DEBUGMSG(ZONE_INIT,(TEXT("QciBus.DLL DLL_PROCESS_ATTACH\r\n"))); DisableThreadLibraryCalls((HMODULE) DllInstance); break; case DLL_PROCESS_DETACH: DEBUGMSG(ZONE_INIT,(TEXT("QciBus.DLL DLL_PROCESS_DETACH\r\n"))); break; }; return TRUE; }