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

📄 speakerheadset.cpp

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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.
//

#include <windows.h>
#include "SpeakerHeadset.h"

#include <wdm.h> // for READ_PORT_XXXX, WRITE_PORT_XXXX
#include <Pkfuncs.h>
#include <nkintr.h>
#include <cardserv.h>
#include <devload.h>
#include <winnls.h>

#include <storemgr.h>
#include <diskio.h>
#include <s3c2410x_ioport.h>
#include <s3c2410x_base_regs.h>
#include <bsp_base_reg_cfg.h>
#include "Devnotify.h"
#include "NotifyWindowList.h"

typedef enum 
{
    CarKitMask = 1,
    HeadsetMask = 2,
    SpeakerphoneMask = 4
} DeviceMask_t;

bool fSpeakerHeadsetInitialized;
CRITICAL_SECTION SPKDeviceLock;
const wchar_t *szHardwareRegRootKey = L"System\\State\\Hardware";

struct SpeakerHeadsetDevice 
{
    unsigned __int8 SpeakerPhoneState;
};

static unsigned __int8 CurrentDriverState = 0;
volatile SpeakerHeadsetDevice *g_SpeakerHeadsetDevice = NULL;

NotifyWindowList g_HeadsetNotificationList;
NotifyWindowList g_SpeakerPhoneNotificationList;
NotifyWindowList g_CarkitNotificationList;

// Notify the registered clients of the change in the device state.
DWORD NotifyClientsOfStateChange(unsigned __int8 changedStateMask)
{
    unsigned __int8 val = 0;

    DEBUGMSG( TRUE, (TEXT("++SPK --> NotifyClientsOfStateChange ChangedMask=%d\n"), changedStateMask) );
    if (changedStateMask & CarKitMask) {
        val = (CurrentDriverState & CarKitMask)?1:0;
        g_CarkitNotificationList.SendMessage(val);
    }

    if (changedStateMask & HeadsetMask) {
        val = (CurrentDriverState & HeadsetMask)?1:0;
        g_HeadsetNotificationList.SendMessage(val);
    }

    if (changedStateMask & SpeakerphoneMask) {
        val = (CurrentDriverState & SpeakerphoneMask)?1:0;
        g_SpeakerPhoneNotificationList.SendMessage(val);
    }
    DEBUGMSG( TRUE, (TEXT("--SPK --> NotifyClientsOfStateChange\n")) );
    return 0;
}

DWORD UpdateRegistryValues(unsigned __int8 changedValMask)
{
    HKEY hHardwareKey = NULL;
    DWORD val;  
    DWORD error = 0;

    DEBUGMSG( TRUE, (TEXT("++SPK --> UpdateRegistryValues ChangedMask=%d\n"), changedValMask) );
    if (ERROR_SUCCESS == (error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szHardwareRegRootKey, 0, 0, &hHardwareKey))) {
        if (changedValMask & CarKitMask) {
            val = CurrentDriverState & CarKitMask;
            if (ERROR_SUCCESS != RegSetValueEx(hHardwareKey, L"Car Kit", 0, REG_DWORD, (const BYTE*)&val, sizeof(DWORD))) {
                error = GetLastError();
            }
        }

        if (changedValMask & HeadsetMask) {
            val = (CurrentDriverState & HeadsetMask)?1:0;
            if (ERROR_SUCCESS != RegSetValueEx(hHardwareKey, L"Headset", 0, REG_DWORD, (const BYTE*)&val, sizeof(DWORD))) {
                error = GetLastError();
            }
        }
        
        if (changedValMask & SpeakerphoneMask) {
            val = (CurrentDriverState & SpeakerphoneMask)?1:0;
            if (ERROR_SUCCESS != RegSetValueEx(hHardwareKey, L"Speaker", 0, REG_DWORD, (const BYTE*)&val, sizeof(DWORD))) {
                error = GetLastError();
            }            
        }
        RegCloseKey(hHardwareKey);
    } else {
        error = GetLastError();
    }
    DEBUGMSG( TRUE, (TEXT("--SPK --> UpdateRegistryValues %d\n"), error) );
    return error;
}

/******************************************
This function reads the current state of the 
device and verifies with the stored state, if 
a difference is there in stored state and current
state, the device status is updated and a 
notification is sent to all the registered 
window handles. Please make sure that you take lock
as this modifies the datastructures.
**********************************************/

DWORD ProcessMaskChange()
{
    DWORD error = 0;
    unsigned __int8 deviceState = 0;
    unsigned __int8 changedMask = 0;
   
    DEBUGMSG( TRUE, (TEXT("++SPK --> ProcessMaskChange\n")) );
    // Really shouldn't happen.
    if (g_SpeakerHeadsetDevice == NULL) {
        error = ERROR_INVALID_HANDLE;
        goto Done;
    }

    // Read the current value of device state.       
    deviceState = g_SpeakerHeadsetDevice->SpeakerPhoneState;
    
    // Check if device state and driver state are different.
    if (deviceState != CurrentDriverState) {
        changedMask = deviceState ^ CurrentDriverState;
        CurrentDriverState = deviceState;
        error = NotifyClientsOfStateChange(changedMask);        
        error = UpdateRegistryValues(changedMask);
    }
Done:
    DEBUGMSG( TRUE, (TEXT("--SPK --> ProcessMaskChange Error=%d\n"), error) );
    return error;
}

/************************************************
This is just a wrapper over ProcessMaskChange but 
takes a lock. This is called from EmulServ device.
*************************************************/
void ProcessSPKMaskChange()
{
    if (fSpeakerHeadsetInitialized) {
        EnterCriticalSection(&SPKDeviceLock);
        ProcessMaskChange();
        LeaveCriticalSection(&SPKDeviceLock);    
    }
}
    

BOOL SetSpeakerPhoneMode(unsigned __int8 newSpeakerMode)
{
    BOOL success = TRUE;
    unsigned __int8 maskVal;
    
    // wparam should be 1 or 0. Any other value is taken as invalid parameter.
    if (newSpeakerMode != 1 && newSpeakerMode != 0) {
        SetLastError(ERROR_INVALID_PARAMETER);
        success = FALSE;
    } else {
        if (newSpeakerMode) {
            maskVal = SpeakerphoneMask;
        } else {
            maskVal = 0;
        }                
        // Write the value into the device.
        // Any other value written other than this mask will be taken as invalid and emulator will terminate.
        g_SpeakerHeadsetDevice->SpeakerPhoneState = maskVal;
        // Read the state from device.
        CurrentDriverState = g_SpeakerHeadsetDevice->SpeakerPhoneState;
        success = g_SpeakerPhoneNotificationList.SendMessage(newSpeakerMode);
        UpdateRegistryValues(maskVal);
    }
    return success;
}

extern "C" DWORD SPK_Init(LPCTSTR pContext, DWORD dwBusContext)
{  
    
    DWORD error = 0;

    DEBUGMSG( TRUE, (TEXT("++SPK_Init\n")) );
    InitializeCriticalSection(&SPKDeviceLock);
    // Really should not happen. But if happens then just return the same, device context.
    ASSERT(NULL == g_SpeakerHeadsetDevice);
    if (NULL != g_SpeakerHeadsetDevice) {
       goto Done;
    }

    EnterCriticalSection(&SPKDeviceLock);
    // Reset the driver state.
    CurrentDriverState = 0;
    g_HeadsetNotificationList.ResetRecordList();
    g_SpeakerPhoneNotificationList.ResetRecordList();
    g_CarkitNotificationList.ResetRecordList();
    
    // Map the virtual address to physical address.
    g_SpeakerHeadsetDevice = (volatile SpeakerHeadsetDevice*)VirtualAlloc(NULL, 0x02, MEM_RESERVE, PAGE_NOACCESS);
    if (NULL == g_SpeakerHeadsetDevice) {
        error = GetLastError();
        goto Done;
    }

    // Map the entire page. Virtual copy needs page aligned address.
    PVOID ppvSPKPhysical = (PVOID)((BSP_BASE_REG_PA_SPKHEADSET & ~0xfff) >> 8);
    if (!VirtualCopy((LPVOID)g_SpeakerHeadsetDevice, ppvSPKPhysical, 0x1000, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL)) {
        error = GetLastError();
        goto Done;
    }
    // Now go to the actual address of the device.
    g_SpeakerHeadsetDevice = (volatile SpeakerHeadsetDevice*)((size_t)g_SpeakerHeadsetDevice + (BSP_BASE_REG_PA_SPKHEADSET & 0xfff));
    // Carry out the initialization.
    error = ProcessMaskChange();

Done:
    LeaveCriticalSection(&SPKDeviceLock);
    if (error == 0) {
        fSpeakerHeadsetInitialized = true;
    }
    DEBUGMSG( TRUE, (TEXT("--SPK_Init Error=%d\n"), error) );
    return (DWORD)g_SpeakerHeadsetDevice;
}

extern "C" BOOL SPK_Deinit(DWORD hDeviceContext)
{
    BOOL success = FALSE;
    DEBUGMSG( TRUE, (TEXT("++SPK_Deinit\n")) );
    EnterCriticalSection(&SPKDeviceLock);
    // Really wondering if the mapping will be freed correctly, because i added the offset.
    if (NULL != g_SpeakerHeadsetDevice) {
        success = VirtualFree ((LPVOID)g_SpeakerHeadsetDevice, 0, MEM_RELEASE);
        g_SpeakerHeadsetDevice = NULL;
    }
    // Reset the driver state.
    CurrentDriverState = 0;
    g_HeadsetNotificationList.ResetRecordList();
    g_SpeakerPhoneNotificationList.ResetRecordList();
    g_CarkitNotificationList.ResetRecordList();    
    LeaveCriticalSection(&SPKDeviceLock);
    fSpeakerHeadsetInitialized = false;
    DeleteCriticalSection(&SPKDeviceLock);
    DEBUGMSG( TRUE, (TEXT("--SPK_Deinit\n")) );
    return success;
}

extern "C" void SPK_PowerUp(DWORD hDeviceContext) 
{
    DEBUGMSG( TRUE, (TEXT("++SPK_PowerUp\n")) );
    EnterCriticalSection(&SPKDeviceLock);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -