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

📄 cudaldongle.cpp

📁 reference about wireless design which is helpful to everyone
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include <Cudal.h>
#include "UsbIoPipe.h"


// Initialize the shared enumeration mutex
HANDLE CudalDongle::m_hMutexEnum = 0;


/// Default GUID (used when passing *pGuid = NULL to EnumDongles and CreateDongle)
/// { 0x92b5d269, 0xf794, 0x49d9, {0x8d, 0x29, 0xcc, 0x3d, 0xee, 0x8b, 0xa, 0x1} }
static const GUID DEFAULT_GUID = { 0x92b5d269, 0xf794, 0x49d9, {0x8d, 0x29, 0xcc, 0x3d, 0xee, 0x8b, 0xa, 0x1} };
 




/** \brief	Protected constructor (to prevent user instantiation)
 *
 * The constructor initializes the CudalDongle object by storing the parameters, and creates a named
 * mutex from the manufacturer, product and serial number string descriptors. If it finds that the mutex
 * already exists, the \ref m_dongleUsed parameter will be set, and \ref CudalDongle::CreateDongle() will
 * immediately destroy it.
 *
 * \note The constructor should only be called by \ref CudalDongle::CreateDongle().
 *
 * \param[in]		*pDongleInfo
 *      The same CUDAL_DONGLE_INFO pointer that was passed to \ref CudalDongle::CreateDongle()
 * \param[in]		*pUsbIo
 *      The USBIO object created by \ref CudalDongle::CreateDongle()
 */
CudalDongle::CudalDongle(CUDAL_DONGLE_INFO *pDongleInfo, CUsbIo *pUsbIo) {

    // Store the constructor parameters
    memcpy(&m_dongleInfo, pDongleInfo, sizeof(CUDAL_DONGLE_INFO));
    m_pUsbIo = pUsbIo;

    // Create the mutex name, which uniquely identifies each physical dongle
	char pMutexName[MAX_PATH * 4];
	sprintf(pMutexName, "CUDAL_MUTEX_DONGLE SN=%s,P=%s,M=%s", pDongleInfo->pSerialNumber, pDongleInfo->pManufacturer, pDongleInfo->pProduct);
    
    // Limit the number of characters in the name to MAX_PATH (CreateMutex() limitation)
    pMutexName[MAX_PATH - 1] = '\0';

    // Check whether any other CebalDongle object in any process is linked to the same physical dongle
	m_hMutexDongle = CreateMutex(NULL, TRUE, pMutexName);	
	m_dongleUsed = (m_hMutexDongle == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS);

} // CudalDongle




/** \brief  Destroys the dongle object, and makes the dongle hardware available for other applications
 *
 * Delete all associated \ref CudalPipe objects before destroying the dongle.
 *
 * \note The destructor must be called in order to release system resources and make the dongle hardware
 * available for other applications. If this is not done properly, the dongle hardware will be 
 * unavailable until the process that created the \ref CudalDongle object has been terminated.
 * 
 * \sa CudalDongle::CreateDongle
 */
/*virtual*/ CudalDongle::~CudalDongle() {
    if (m_pUsbIo) delete m_pUsbIo;
	if (m_hMutexDongle) CloseHandle(m_hMutexDongle);
} // ~CudalDongle




/** \brief  Enters data into the supplied CUDAL_DONGLE_INFO struct
 *
 * This function is used during enumeration and when creating dongle and pipe objects.
 *
 * \param[out]		*pDongleInfo
 *      The CUDAL_DONGLE_INFO structure to be filled in
 * \param[in]		*pUsbIo
 *		A pointer to the USBIO object to gather the information from
 * 
 * \return
 *		\c TRUE if successful, otherwise \c FALSE, indicating a USB communication error
 * 
 * \sa CudalDongle::EnumDongles, CudalDongle::CreateDongle, CudalDongle::CreatePipe
 */
/*static*/ BOOL CudalDongle::CreateDongleInfo(CUDAL_DONGLE_INFO *pDongleInfo, CUsbIo *pUsbIo) {
    BYTE pBuffer[256];
    DWORD length;
    int result;

    // 1. Get the ID and version numbers from the device descriptor
    USB_DEVICE_DESCRIPTOR deviceDesc;
    result = pUsbIo->GetDeviceDescriptor(&deviceDesc);
    pDongleInfo->vendorId = deviceDesc.idVendor;
    pDongleInfo->productId = deviceDesc.idProduct;
    pDongleInfo->productVersion = deviceDesc.bcdDevice;

    // 2. Get the manufacturer name
    USB_STRING_DESCRIPTOR *pStringDesc = (USB_STRING_DESCRIPTOR*) pBuffer;
    result |= pUsbIo->GetStringDescriptor(pStringDesc, length = 256, deviceDesc.iManufacturer);
    length = WideCharToMultiByte(CP_ACP, 0, pStringDesc->bString, (pStringDesc->bLength - 2) / 2, pDongleInfo->pManufacturer, 128, NULL, NULL);
	pDongleInfo->pManufacturer[length] = '\0';

    // 3. Get the product name
    result |= pUsbIo->GetStringDescriptor(pStringDesc, length = 256, deviceDesc.iProduct);
    length = WideCharToMultiByte(CP_ACP, 0, pStringDesc->bString, (pStringDesc->bLength - 2) / 2, pDongleInfo->pProduct, 128, NULL, NULL);
	pDongleInfo->pProduct[length] = '\0';

    // 4. Get the serial number
    result |= pUsbIo->GetStringDescriptor(pStringDesc, length = 256, deviceDesc.iSerialNumber);
    length = WideCharToMultiByte(CP_ACP, 0, pStringDesc->bString, (pStringDesc->bLength - 2) / 2, pDongleInfo->pSerialNumber, 128, NULL, NULL);
	pDongleInfo->pSerialNumber[length] = '\0';

    return (result == USBIO_ERR_SUCCESS);

} // CreateDongleInfo




/** \brief	Enumerates available USB dongles
 *
 * This function populates a table of \ref CUDAL_DONGLE_INFO structures, which contain ID information
 * about the USB dongles currently connected to the computer. One of these structures is then passed on
 * to \ref CudalDongle::CreateDongle() in order to create a \ref CudalDongle object.
 *
 * \note The information contained in the \ref CUDAL_DONGLE_INFO structure should uniquely identify each
 * physical USB dongle. The device must provide manufacturer, product and serial number string
 * descriptors, which, put together, must form a unique text string. If two dongles have identical 
 * string descriptors, the CUDAL library will only be able to access one of them (first found).
 *
 * \param[out]		*pDongleInfo
 *      Pointer to a caller-provided table of \ref CUDAL_DONGLE_INFO structures
 * \param[in]		maxCount
 *      Number of entries in the \ref CUDAL_DONGLE_INFO table, \c *pDongleInfo
 * \param[in]		*pGuid
 *      A pointer to the \c GUID that matches the VID/PID for the desired device(s). If this parameter 
 *      is \c NULL, a default GUID will be used.
 *
 * \return
 *		The number of valid entries in \c *pDongleInfo
 * 
 * \sa CudalDongle::CreateDongle
 */
/*static*/ int CudalDongle::EnumDongles(CUDAL_DONGLE_INFO *pDongleInfo, int maxCount, const GUID *pGuid) {
    HDEVINFO hDevInfo;
    CUsbIo usbIo;
    int count = 0;
    int result;
    
    // Use the default GUID if none was specified
    if (!pGuid) pGuid = &DEFAULT_GUID;

    // Start by wiping out the dongle info table
    memset(pDongleInfo, 0x00, sizeof(CUDAL_DONGLE_INFO) * maxCount);

	// Open/create the mutex used to make EnumDongles() and CreateDongle() safe (EnumDongles() is always
    // called first, so it's safe to do it here only)
    if (!m_hMutexEnum) {
	    m_hMutexEnum = CreateMutex(NULL, FALSE, "CUDAL_MUTEX_ENUM");
        if (!m_hMutexEnum) return 0;
    }

    // Enter the critical section
	result = WaitForSingleObject(m_hMutexEnum, 500);
	if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) {
		
        // Create a list of attached dongles
		if (hDevInfo = CUsbIo::CreateDeviceList(pGuid)) {                
			
            // Traverse through the list and gather information about each
            for (int n = 0; n < maxCount; n++) {
                if (usbIo.Open(n, hDevInfo, pGuid) == USBIO_ERR_SUCCESS) {
                    if (CreateDongleInfo(&pDongleInfo[count], &usbIo)) count++;
                    usbIo.Close();
                }
            }

			// Delete the dongle list
			CUsbIo::DestroyDeviceList(hDevInfo);
		}

        // Release the enumeration mutex
		ReleaseMutex(m_hMutexEnum);
	}

    // Return the number of valid CUDAL_DONGLE_INFO entries
    return count;

} // EnumDongles




/** \brief	Creates a dongle object
 *
 * This function creates a \ref CudalDongle object based on one of the \ref CUDAL_DONGLE_INFO structures
 * provided by the \ref CudalDongle::EnumDongles() function. The object is returned by pointer, which 
 * \b must be deleted when the object is no longer to be used.
 *
 * \note There can only be one \ref CudalDongle object for each physical USB dongle. This is ensured by 
 * creating a named mutex, based on the information found in the \ref CUDAL_DONGLE_INFO structure. If the
 * mutex cannot be created, the dongle is already in use, and \ref CudalDongle::CreateDongle() will
 * abort, and return \c NULL.
 *
 * \param[out]		*pDongleInfo
 *      A pointer to the \ref CUDAL_DONGLE_INFO structure representing the physical dongle
 * \param[in]		configurationIndex
 *      A zero-based index for the device configuration to be set. If a value of -1 is used, the set
 *      configuration request will not be sent.
 * \param[in]		*pGuid
 *      The same \c GUID that was passed to \ref CudalDongle::EnumDongles()
 *
 * \return
 *		A pointer to the created \ref CudalDongle object, or \c NULL if the operation failed (e.g. the
 *      device was removed after enumeration, or is already in use)
 * 
 * \sa CudalDongle::EnumDongles, CudalDongle::~CudalDongle, CudalDongle::CreatePipe
 */
/*static*/ CudalDongle* CudalDongle::CreateDongle(CUDAL_DONGLE_INFO *pDongleInfo, BYTE configurationIndex, const GUID *pGuid) {
    CudalDongle *pDongle = NULL;
    CUDAL_DONGLE_INFO currentInfo;
    HDEVINFO hDevInfo;
    CUsbIo *pUsbIo = new CUsbIo();
    int result;
    
    // Use the default GUID if none was specified
    if (!pGuid) pGuid = &DEFAULT_GUID;

    // Enter the critical section
	result = WaitForSingleObject(m_hMutexEnum, 500);
	if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) {
		
        // Create a list of attached dongles
		if (hDevInfo = CUsbIo::CreateDeviceList(pGuid)) {                
			
            // Traverse through the list and try to find a match
            int n = 0;
                
            // If the device could be opened...
            while (pUsbIo->Open(n++, hDevInfo, pGuid) == USBIO_ERR_SUCCESS) {

                // Compare the dongle information
                memset(&currentInfo, 0x00, sizeof(CUDAL_DONGLE_INFO));
                if (CreateDongleInfo(&currentInfo, pUsbIo)) {

                    // Create the dongle object when we have a match, and then break out of the loop
                    if (memcmp(&currentInfo, pDongleInfo, sizeof(CUDAL_DONGLE_INFO)) == 0) {
                        pDongle = new CudalDongle(pDongleInfo, pUsbIo);
                        pDongle->m_pUsbIo = pUsbIo;
                        pDongle->m_pGuid = pGuid;
                        break;
                    }
                }
                pUsbIo->Close();
            }

			// Delete the dongle list
			CUsbIo::DestroyDeviceList(hDevInfo);
		}

        // Release the enumeration mutex
		ReleaseMutex(m_hMutexEnum);
	}

    // Clean up if no dongle object was created
    if (!pDongle) delete pUsbIo;
    
    // Don't return anything if the dongle is already in use
    if (pDongle && pDongle->IsDongleUsed()) {
        delete pDongle;
        pDongle = NULL;
    }

    // Configure the device
    if (pDongle && (configurationIndex != (BYTE) -1)) pDongle->SetConfiguration(configurationIndex);

    return pDongle;

⌨️ 快捷键说明

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