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

📄 jsthid.cpp

📁 ce5下测试游戏手柄/摇杆的驱动程序和测试代码以及一个笔记. 硬件是S3C2440. 对写CE的USB HID驱动的同志有帮助.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//extern "C" 
BOOL
DllEntry(
    HANDLE hDllHandle,
    DWORD dwReason, 
    LPVOID lpReserved
    )
{
    RETAILMSG( 1, (TEXT(">DllEntry--joystick\r\n")));
    
    UNREFERENCED_PARAMETER(lpReserved);
    
    switch (dwReason) {
        case DLL_PROCESS_ATTACH:
            DEBUGREGISTER((HINSTANCE)hDllHandle);

            DEBUGMSG(ZONE_INIT, (_T("%s: Attach\r\n"), pszFname));
            DisableThreadLibraryCalls((HMODULE) hDllHandle);
            break;
            
        case DLL_PROCESS_DETACH:
            DEBUGMSG(ZONE_INIT, (_T("%s: Detach\r\n"), pszFname));
            break;
            
        default:
            break;
    }
    
    return TRUE;
}


// Get interrupt reports from the device. Thread exits when the device has
// been removed or the close event has been signaled.
static
DWORD
WINAPI
KeyboardThreadProc(
    LPVOID lpParameter
    )
{
//    RETAILMSG( 1, (TEXT(">KeyboardThreadProc--joystick\r\n")));

    PHID_KBD pHidKbd = (PHID_KBD) lpParameter;
    
    PREFAST_DEBUGCHK(pHidKbd != NULL);
    DEBUGCHK(pHidKbd->hevClosing != NULL); // Needed to signal exit

    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
    
    const DWORD cbMaxHidPacket = pHidKbd->hidpCaps.InputReportByteLength;
    pHidKbd->pbInputBuffer = NULL;
	pHidKbd->pbInputBuffer = (PCHAR) LocalAlloc(LMEM_FIXED, cbMaxHidPacket);

    if (pHidKbd->pbInputBuffer == NULL) {        
        RETAILMSG( 1, (TEXT("LocalAlloc error:%d--joystick\r\n"), GetLastError()));
		goto EXIT;
    }

    while (TRUE) {  
        ValidateHidKbd(pHidKbd);

        DEBUGCHK(g_dwAutoRepeatInitialDelay >= KBD_AUTO_REPEAT_INITIAL_DELAY_MIN);
        DEBUGCHK(g_dwAutoRepeatInitialDelay <= KBD_AUTO_REPEAT_INITIAL_DELAY_MAX);
        DEBUGCHK(!g_dwAutoRepeatKeysPerSec || 
                 g_dwAutoRepeatKeysPerSec   >= KBD_AUTO_REPEAT_KEYS_PER_SEC_MIN);
        DEBUGCHK(g_dwAutoRepeatKeysPerSec   <= KBD_AUTO_REPEAT_KEYS_PER_SEC_MAX);

        // 0 keys per second => auto repeat disabled.
        if (g_dwAutoRepeatKeysPerSec == 0) {
            pHidKbd->ARState = AR_WAIT_FOR_ANY;
        }

        DWORD dwTimeout;

        // Set our timeout according to the current autorepeat state.
        if (pHidKbd->ARState == AR_WAIT_FOR_ANY) {
            dwTimeout = INFINITE;
        }
        else if (pHidKbd->ARState == AR_INITIAL_DELAY) {
            dwTimeout = g_dwAutoRepeatInitialDelay;
        }
        else {
            DEBUGCHK(pHidKbd->ARState == AR_AUTOREPEATING);
            DEBUGCHK(g_dwAutoRepeatKeysPerSec != 0); // Special case above
            dwTimeout = 1000 / g_dwAutoRepeatKeysPerSec;
        }

        DWORD cbHidPacket;

        // Get an interrupt report from the device.
        DWORD dwErr = pHidKbd->pHidFuncs->lpGetInterruptReport(
            pHidKbd->hDevice,
            pHidKbd->pbInputBuffer,
            cbMaxHidPacket,
            &cbHidPacket,
            pHidKbd->hevClosing,
            dwTimeout);

        if (dwErr == ERROR_TIMEOUT) {
            // Perform autorepeat
            DEBUGCHK(pHidKbd->ARState != AR_WAIT_FOR_ANY);
            DWORD cKeysSent = SendKeyboardUsages(pHidKbd->puapMakeUsages, 
                pHidKbd->dwMaxUsages, HidP_Keyboard_Make, &pHidKbd->KeyStateFlags);
            DEBUGCHK(cKeysSent != 0);
            pHidKbd->ARState = AR_AUTOREPEATING;
			RETAILMSG(1, (_T("InterruptReport ERROR_TIMEOUT--jsthid\r\n")));
        }
        else if (dwErr != ERROR_SUCCESS) {
            if ( (dwErr != ERROR_DEVICE_REMOVED) && (dwErr != ERROR_CANCELLED) ) {
                //DEBUGMSG(ZONE_ERROR, 
                //    (_T("%s: GetInterruptReport returned unexpected error %u\r\n"),
                //    pszFname, dwErr));
                RETAILMSG(1, 
                    (_T("GetInterruptReport returned unexpected error %u\r\n"),
                    dwErr));
            }

            // Exit thread
            break;
        }
        else {
            DEBUGCHK(cbHidPacket <= cbMaxHidPacket);
            ProcessKeyboardReport(pHidKbd, pHidKbd->pbInputBuffer, cbHidPacket);
        }
    }

EXIT:
    if (pHidKbd->pbInputBuffer != NULL) 
		LocalFree(pHidKbd->pbInputBuffer);

    RETAILMSG(1, (_T("Exiting thread\r\n")));
    
    return 0;
}


// Entry point for the HID driver. Initializes the structures for this 
// keyboard and starts the thread that will receive interrupt reports.
//extern "C"
BOOL
HIDDeviceAttach(
    HID_HANDLE                 hDevice, 
    PCHID_FUNCS                pHidFuncs,
    const HID_DRIVER_SETTINGS *pDriverSettings,
    PHIDP_PREPARSED_DATA       phidpPreparsedData,
    PVOID                     *ppvNotifyParameter,
    DWORD                      dwUnused
    )
{
	RETAILMSG( 1, (TEXT(">HIDDeviceAttach--joystick\r\n")));	
	
    BOOL fRet = FALSE;
    size_t cbUsages;
    PHID_KBD pHidKbd;
    const TCHAR * const pszClientKey = CLIENT_REGKEY_SZ;

    DEBUGCHK(hDevice != NULL);
    DEBUGCHK(pHidFuncs != NULL);
    DEBUGCHK(phidpPreparsedData != NULL);
    DEBUGCHK(ppvNotifyParameter != NULL);

    // Allocate this keyboard's data structure and fill it.
    pHidKbd = (PHID_KBD) LocalAlloc(LPTR, sizeof(HID_KBD));
    if (pHidKbd == NULL) {
		RETAILMSG(1, (_T("LocalAlloc error:%d\r\n"), GetLastError()));
        goto EXIT;
    }

    pHidKbd->dwSig				= HID_KBD_SIG;
    pHidKbd->hDevice			= hDevice;
    pHidKbd->pHidFuncs			= pHidFuncs;
    pHidKbd->phidpPreparsedData = phidpPreparsedData;
    HidP_GetCaps(pHidKbd->phidpPreparsedData, &pHidKbd->hidpCaps);
    pHidKbd->KeyStateFlags		= 0;
    pHidKbd->ARState			= AR_WAIT_FOR_ANY;

	// Allocate enough space for output reports.
    pHidKbd->cbOutputBuffer = pHidKbd->hidpCaps.OutputReportByteLength;
    pHidKbd->pbOutputBuffer = (PCHAR) LocalAlloc(0, pHidKbd->cbOutputBuffer);
    if (pHidKbd->pbOutputBuffer == NULL) {
        //DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
        RETAILMSG(1, (_T("LocalAlloc error--joystick:%d\r\n"), GetLastError()));
		goto EXIT;
    }
    
    pHidKbd->hevClosing = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (pHidKbd->hevClosing == NULL) {
        //DEBUGMSG(ZONE_ERROR, (_T("%s: Error creating event: %d\r\n"),
		RETAILMSG(1, (_T("Error creating event--joystick: %d\r\n"),
            GetLastError()));
        goto EXIT;
    }
    
    // Get the total number of usages that can be returned in an input packet.
    pHidKbd->dwMaxUsages = HidP_MaxUsageListLength(HidP_Input, 0, phidpPreparsedData);
    if (pHidKbd->dwMaxUsages == 0) {
        //DEBUGMSG(ZONE_WARNING, (_T("%s: This collection does not have any ")
		RETAILMSG(1, (_T("This collection does not have any ")
            _T("understood usages and will be ignored--joystick\r\n")));
        goto EXIT;
    }
    
    cbUsages = pHidKbd->dwMaxUsages * sizeof(USAGE_AND_PAGE);

    if (AllocateUsageLists(pHidKbd, cbUsages) == FALSE) {
		RETAILMSG(1, (_T("AllocateUsageLists failed--joystick\r\n")));
        goto EXIT;
    }

    FlashLEDs(pHidKbd);
	
    // Create the thread that will receive reports from this device
    pHidKbd->hThread = CreateThread(NULL, 0, KeyboardThreadProc, pHidKbd, 0, NULL);
    if (pHidKbd->hThread == NULL) {
		RETAILMSG(1, (_T("Failed creating keyboard thread--joystick\r\n")));
        goto EXIT;
    }
#ifdef DEBUG
    pHidKbd->fhThreadInited = TRUE;
#endif

    // Create the KBD device
    pHidKbd->hOSDevice = ActivateDevice(pszClientKey, (DWORD) pHidKbd);
    if (pHidKbd->hOSDevice == NULL) {
        RETAILMSG(1, (_T("Error on ActivateDevice(%s)\r\n"), pszClientKey));
        goto EXIT;
    }
#ifdef DEBUG
    pHidKbd->fhOSDeviceInited = TRUE;
#endif

    *ppvNotifyParameter = pHidKbd;
    ValidateHidKbd(pHidKbd);
    fRet = TRUE;

EXIT:
    if ((fRet == FALSE) && (pHidKbd != NULL)) {
        // Initialization failed. Clean up any resources that did allocate.
        RETAILMSG(1, (_T("Initialization failed--joystick\r\n")));
		FreeHidKbd(pHidKbd);
    }
	else
		RETAILMSG(1, (_T("Initialization succeed--joystick\r\n")));
    return fRet;
}
#ifdef DEBUG
// Match function with typedef.
static LPHID_CLIENT_ATTACH g_pfnDeviceAttach = HIDDeviceAttach;
#endif


// Entry point for the HID driver to give us notifications.
//extern "C" 
BOOL 
WINAPI
HIDDeviceNotifications(
    DWORD  dwMsg,
    WPARAM wParam, // Message parameter
    PVOID  pvNotifyParameter
    )
{
	RETAILMSG( 1, (TEXT(">HIDDeviceNotifications--joystick\r\n")));
	
    BOOL fRet = FALSE;
    PHID_KBD pHidKbd = (PHID_KBD) pvNotifyParameter;

    UNREFERENCED_PARAMETER(wParam);

    if (VALID_HID_KBD(pHidKbd) == FALSE) {
        //DEBUGMSG(ZONE_ERROR, (_T("%s: Received invalid structure pointer\r\n"), pszFname));
        RETAILMSG( 1, (TEXT("Received invalid structure pointer--joystick\r\n")));
		goto EXIT;
    }

    ValidateHidKbd(pHidKbd);
    
    switch(dwMsg) {
        case HID_CLOSE_DEVICE:
            // Free all of our resources.
            WaitForSingleObject(pHidKbd->hThread, INFINITE);
            CloseHandle(pHidKbd->hThread);
            pHidKbd->hThread = NULL;
            
            // Key up all keys that are still down.
            SendKeyboardUsages(pHidKbd->puapPrevUsages, pHidKbd->dwMaxUsages,
                HidP_Keyboard_Break, &pHidKbd->KeyStateFlags);

            DeactivateDevice(pHidKbd->hOSDevice);

            // Wait for KBD_Deinit to complete so we can free our context.
            WaitForSingleObject(pHidKbd->hevClosing, INFINITE);
            FreeHidKbd(pHidKbd);

            fRet = TRUE;
            break;

        default:
            DEBUGMSG(ZONE_ERROR, (_T("%s: Unhandled message %u\r\n"), pszFname));
            break;
    };

EXIT:
    return fRet;
}
#ifdef DEBUG
// Match function with typedef.
static LPHID_CLIENT_NOTIFICATIONS g_pfnDeviceNotifications = HIDDeviceNotifications;
#endif


// Flashes the keyboard's LEDs.
static
BOOL
FlashLEDs(
    PHID_KBD pHidKbd
    )
{
	RETAILMSG( 1, (TEXT(">FlashLEDs--joystick\r\n")));

    DEBUGCHK(pHidKbd != NULL);

    // Turn on all LEDs.
    SetLEDs(pHidKbd, ~0);

    // Turn off all LEDs.
    SetLEDs(pHidKbd, 0);

    return TRUE;
}


// Allocate the usage lists for this keyboard. The lists are allocated in 
// a single block and then divided up.
static
BOOL
AllocateUsageLists(
    PHID_KBD pHidKbd,
    size_t cbUsages
    )
{
    RETAILMSG( 1, (TEXT(">AllocateUsageLists--joystick\r\n")));

    BOOL fRet = FALSE;
    size_t cbTotal;
    PBYTE pbStart;
    DWORD dwIdx;
    PUSAGE_AND_PAGE *rgppUsageAndPage[] = {
        &pHidKbd->puapPrevUsages,
        &pHidKbd->puapCurrUsages,
        &pHidKbd->puapBreakUsages,
        &pHidKbd->puapMakeUsages,
        &pHidKbd->puapOldMakeUsages
    };
    
    DEBUGCHK(pHidKbd != NULL);
	DEBUGCHK(cbUsages > 0);

    // Allocate a block of memory for all the usage lists
	cbTotal = cbUsages * dim(rgppUsageAndPage);
    pbStart = (PBYTE) LocalAlloc(LPTR, cbTotal);
    
    if (pbStart == NULL) {
       //DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
       RETAILMSG( 1, (TEXT("LocalAlloc error:%d--joystick\r\n"),GetLastError()));
	   goto EXIT;
    }

    // Divide the block.
    for (dwIdx = 0; dwIdx < dim(rgppUsageAndPage); ++dwIdx) {
        *rgppUsageAndPage[dwIdx] = (PUSAGE_AND_PAGE) (pbStart + (cbUsages * dwIdx));
    }

    fRet = TRUE;

EXIT:
    return fRet;
}


// Free the memory used by pHidKbd
void
FreeHidKbd(
    PHID_KBD pHidKbd
    )
{
    PREFAST_DEBUGCHK(pHidKbd != NULL);

    // Close thread if it has been created.
    if (pHidKbd->hThread != NULL) {
        DEBUGCHK(pHidKbd->hevClosing != NULL);
        SetEvent(pHidKbd->hevClosing);
        WaitForSingleObject(pHidKbd->hThread, INFINITE);

⌨️ 快捷键说明

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