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; 
}