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

📄 hid.cpp

📁 Intel PXA270 Wince5.0 BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.

Module Name:  

hid.cpp

Abstract:  
    USB Human Interface Device (HID) class driver sample.

Functions:

Notes: 

--*/


#define RETAIL_ZONE_HID	0

// There are four warnings that I like from Warning level 4.  Since we build
// at warning level 3, I'm setting these four down to level 3 so I still get
// them.
// C4100 unrefrenced formal parameter
// C4101 unrefrenced local variable
// C4705 statement has no effect
// C4706 assignment in conditional
#pragma warning (3 : 4101 4705 4706)


#include <windows.h>
#include <windev.h>
#include <nkintr.h>
#include <usbdi.h>

#include "dinputce.h"
#include "keybd.hpp"
#include "hid.hpp"
#include "parse.hpp"


// The total configuration descriptor is of variable length.  We'll first
// try the most likely length and then go back and redo it if that wasn't
// enough.
// Leave room for One configuration, one interfaces, one endpoints and a
// HID descriptor.  That should minimize retries.	
const UINT gcAssumedConfigurationDescriptorLength =
sizeof(USB_CONFIGURATION_DESCRIPTOR) +
sizeof(USB_INTERFACE_DESCRIPTOR) +
sizeof(USB_ENDPOINT_DESCRIPTOR) + sizeof(HID_DESCRIPTOR);




CHid *gpobHid;


/*++
*******************************************************************************

    Hid Class Static Member Functions

*******************************************************************************
--*/


ULONG CALLBACK
CHid::HidThreadStub(
                   PVOID   context)
{
    CHid* pHid = (CHid*)context;
    return (pHid->HidThread());
}   



/*++
*******************************************************************************

    Hid Class Member Functions

*******************************************************************************
--*/



CHid::CHid()
{
    UINT device;

    InitializeCriticalSection(&m_csDeviceLock);

    m_bClosing = FALSE;

    m_curMaxNumDevices = gcInitialMaxNumDevices;
    m_ppDevices = new SHidDevice*[gcInitialMaxNumDevices];

    for (device = 0; device < gcInitialMaxNumDevices; device++)
        m_ppDevices[device] = NULL;

    m_hEvent = NULL;
    m_hThread = NULL;
    m_curDevices = 0;
    m_lpUsbFuncs = NULL;

    // can't fail a constructor so activate this device in the Initialize method.
}

CHid::~CHid()
{
    UINT device;
    DWORD   dwWaitReturn;

    DeactivateDevice(m_hOSDevice);  // inform the OS that we're going away

    for (device = 0; device < m_curMaxNumDevices; device++) {
        if (m_ppDevices[device] != NULL)
            m_ppDevices[device]->bValid = FALSE;
    }
    // Now, when the thread wakes up it'll go through and remove all the
    // devices.

    m_bClosing = TRUE;
    // Wake up the connection thread again and give it time to die.
    if (m_hEvent != NULL) {
        SetEvent(m_hEvent);
        if (m_hThread != NULL) {
            dwWaitReturn = WaitForSingleObject(m_hThread, 10000);
            if (dwWaitReturn != WAIT_OBJECT_0) {
                DEBUGMSG(ZONE_ERROR,(TEXT("!Timed out waiting for HID thread\r\n")));
                TerminateThread(m_hThread, DWORD(-1));
            }
            m_hThread = NULL;
        }
        CloseHandle(m_hEvent);
        m_hEvent = NULL;
    }

    DeleteCriticalSection(&m_csDeviceLock);
    delete[] m_ppDevices;
}   


BOOL
CHid::Initialize(LPCUSB_FUNCS  lpUsbFuncs)
{
    WCHAR const *key = TEXT("Drivers\\USB\\LoadClients\\Default\\Default\\3\\Generic_Sample_Hid_Class_Driver");

    m_hOSDevice = ActivateDevice(key, 0);
    if (m_hOSDevice == NULL) {
       DEBUGMSG(ZONE_ERROR,
                (TEXT("HID: Error on ActivateDevice(%s)\r\n"), key));
       return (FALSE);
    }

    m_lpUsbFuncs = lpUsbFuncs;

    m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (m_hEvent == NULL) {
        DEBUGMSG(ZONE_ERROR,
                 (TEXT("HID: Error on CreateEvent for connect event\r\n")));
        return (FALSE);
    }

    m_hThread = CreateThread(0, 0, HidThreadStub, this, 0, NULL);
    if (m_hThread == NULL) {
        DEBUGMSG(ZONE_ERROR,
                 (TEXT("HID: Error on CreateThread\r\n")));
        
        return (FALSE);
    }

    return (TRUE);
}   

static inline DWORD MakeID (UINT idx)
{
   static UINT ctr = 0;

   ++ctr;
   return (LOBYTE(ctr) << 8) | LOBYTE(idx+1);
}


SHidDevice *
CHid::HidNewDevice(USB_HANDLE hDevice,           // USB handle to the device
                   LPCUSB_INTERFACE lpInterface, // Pointer to the interface we are using
                   UCHAR bMaxPacketSize0)        // Max size of transfers on EP0
{
    UINT device;
    BOOL bFoundSlot = FALSE;
    SHidDevice *pstHidDevice;
    PHID_DESCRIPTOR pHd;
    LPCUSB_ENDPOINT_DESCRIPTOR pEd;

    DEBUGMSG(ZONE_ATTACH || ZONE_FUNCTION,(TEXT("HidNewDevice, hDevice = 0x%X, MaxPacketSize0: %u\r\n"),hDevice,bMaxPacketSize0));
    DEBUGMSG(ZONE_ATTACH,(TEXT("Interface: IFNum: %u, NumEP: %u, Class: 0x%X, SubClass: 0x%X, Protocol: 0x%X\r\n"),
                          lpInterface->Descriptor.bInterfaceNumber, lpInterface->Descriptor.bNumEndpoints,
                          lpInterface->Descriptor.bInterfaceClass,lpInterface->Descriptor.bInterfaceSubClass,
                          lpInterface->Descriptor.bInterfaceProtocol));

    for (device = 0; device < m_curMaxNumDevices; device++) {
        if (m_ppDevices[device] == NULL) {
            bFoundSlot = TRUE;
            break;
        }
    }

    if (!bFoundSlot) {
        UINT oldNumDevices;
        SHidDevice **ppOldDevices;

        // We've got more devices than we bargained for.  Grow the device array
        oldNumDevices = m_curMaxNumDevices;
        ppOldDevices = m_ppDevices;
        m_curMaxNumDevices += gcInitialMaxNumDevices;
        DEBUGMSG(ZONE_WARNING, 
                 (TEXT("HID: Growing the device array from %d to %d\r\n"),
                  oldNumDevices, m_curMaxNumDevices));
        m_ppDevices = new SHidDevice*[m_curMaxNumDevices];

        // First copy over the old devices
        for (device = 0; device < oldNumDevices; device++) {
            m_ppDevices[device] = ppOldDevices[device];
        }

        // Now NULL out the new spaces
        for (/* already set */; device < m_curMaxNumDevices; device++) {
            m_ppDevices[device] = NULL; 
        }

        // Now delete the old space used.
        delete[] ppOldDevices;

        // Finally, we can be sure (having just allocated the space) that 
        // this spot is free.
        device = oldNumDevices;
    }

    pstHidDevice = new SHidDevice;
    if (pstHidDevice == NULL) {
        DEBUGMSG(ZONE_ERROR, (TEXT("Error out of memory\r\n")));
        goto Error;
    }

    memset(pstHidDevice,0,sizeof(SHidDevice));

    // Device initialization
    pstHidDevice->hDevice = hDevice;
    pstHidDevice->configStatus = gcConfigStatusNewDevice;
    pstHidDevice->signalStatus = gcSignalStatusNone;
    pstHidDevice->dwRepeatDeadline = INFINITE;
    pstHidDevice->intrBufferSize = 0;
    pstHidDevice->bValid = TRUE;

    InitializeCriticalSection(&pstHidDevice->csLock);

    pstHidDevice->bMaxPacketSize = bMaxPacketSize0;
    
    // HID devices should have a control endpoint (EP0) and an interrupt endpoint
    if (lpInterface->lpEndpoints == NULL) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::HidNewDevice - missing endpoint descriptors\r\n")));
        goto Error;
    }
    pEd = &lpInterface->lpEndpoints[0].Descriptor;

    // HCD should guarantee this
    ASSERT (pEd->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);

    // Make sure endpoint is right type
    if ((pEd->bmAttributes & USB_ENDPOINT_TYPE_MASK) != USB_ENDPOINT_TYPE_INTERRUPT ) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::HidNewDevice - 1st endpoint not interrupt (attr %u)\r\n"),
                             pEd->bmAttributes & USB_ENDPOINT_TYPE_MASK));
        goto Error;
    }

    // Regarding bSendToInterface.  The original HID spec said that the Hid
    // descriptor would come after the interface and endpoint descriptors.
    // It also said that class specific commands should be sent to the endpoint.
    // The next spec said that the HID descriptor would come after the interface
    // descriptor (not at the end) and that commands should be sent to the
    // interface, not to the endpoint.  So, I'm assuming that if I find the
    // Hid descriptor after the interface, the device is following the new spec
    // and I should send commands to the interface.  Otherwise, I'll send them
    // to the endpoint, as stated in the old spec.
    pHd = (PHID_DESCRIPTOR) lpInterface->lpvExtended;

    if (pHd == NULL) {
        pHd = (PHID_DESCRIPTOR) lpInterface->lpEndpoints->lpvExtended;
        if (pHd == NULL) {
            DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::HidNewDevice - missing HID descriptor\r\n")));
#ifdef OHCI_DESC_BUG_WORKAROUND
            // But wait, there is a bug in the OHCI driver descriptor parsing logic where 
            // class specific descriptors are not indicated if they follow the EP descriptors.
            // This code should be removed when we ship the fix to OHCI in SP2.
            if (! GetConfigDesc(pstHidDevice,gcAssumedConfigurationDescriptorLength)) {
                goto Error;
            }
            pstHidDevice->dwId = MakeID(device);
            m_ppDevices[device] = pstHidDevice;
            m_curDevices++;
            return (pstHidDevice);
#else
            goto Error;
#endif
        }
        else {
            pstHidDevice->endptOrIntrNum = pEd->bEndpointAddress;
            pstHidDevice->bSendToInterface = FALSE;
        }
    }
    else {
        pstHidDevice->endptOrIntrNum = lpInterface->Descriptor.bInterfaceNumber;
        pstHidDevice->bSendToInterface = TRUE;
    }

    DEBUGMSG(ZONE_ATTACH,(TEXT("HID Descriptor:  bLength: %u, bcdHID: 0x%X, bCountryCode: 0x%X\r\n"),pHd->bLength, pHd->bcdHID, pHd->bCountryCode));
    DEBUGMSG(ZONE_ATTACH,(TEXT("                 bNumDescriptors: %u, bClassDescriptorType: 0x%X, wDescriptorLength: %u\r\n"),
                          pHd->bNumDescriptors,pHd->bClassDescriptorType,pHd->wDescriptorLength));

    pstHidDevice->wReportDescriptorLength = pHd->wDescriptorLength;

    // Open interrupt pipe
    pstHidDevice->hIntrPipe = m_lpUsbFuncs->lpOpenPipe(hDevice,pEd);
    if (pstHidDevice->hIntrPipe == NULL) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::HidNewDevice - Error %u opening interrupt pipe for device\r\n"),GetLastError()));
        goto Error;
    }
    pstHidDevice->dwId = MakeID(device);
    m_ppDevices[device] = pstHidDevice;
    m_curDevices++;

    DEBUGMSG(ZONE_CONFIG,(TEXT("HID: Dev 0x%X state: GettingReport\r\n"),pstHidDevice));

    if (! GetReport(pstHidDevice)) {
        goto Error;
    }
    return (pstHidDevice);

    Error:
    RETAILMSG(1,(TEXT("!CHid::HidNewDevice - Error setting up new HID device\r\n")));
    if (pstHidDevice) {
        if (pstHidDevice->hIntrPipe)
            m_lpUsbFuncs->lpClosePipe(pstHidDevice->hIntrPipe);
        delete pstHidDevice;
    }
    return NULL;
}

BOOL
CHid::HidCloseDevice(
                    SHidDevice *pHidDevice)
{
    DEBUGMSG(ZONE_ATTACH || ZONE_FUNCTION,
             (TEXT("HidCloseDevice, pHidDevice = 0x%X\r\n"), pHidDevice));

    ASSERT(m_curDevices);
    m_curDevices--;

    if (pHidDevice->hIntrPipe) {
        m_lpUsbFuncs->lpClosePipe(pHidDevice->hIntrPipe);
        pHidDevice->hIntrPipe = NULL;
    }

    // To keep this thread safe without using critical sections,
    // mark him as invalid and let the main thread handle it.
    pHidDevice->bValid = FALSE;
    SetEvent(m_hEvent);
    return (TRUE); 

⌨️ 快捷键说明

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