Beispiel #1
0
//.-.-.-.-.-.-.-.-.-.-.-.- PathAppendSettingsSerialDeviceCategory -.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  PathAppendSettingsSerialDeviceCategory(
    DtString*  pPath,
    UInt64  DvcSerial,
    Char*  pCategory)
{
    DtStatus  Status = DT_STATUS_OK;
    DT_STRING_DECL(SettingsStr, "Settings\\");
    DT_STRING_DECL(DeviceStr, "\\Device");
        
    // Registry path starts with <\Settings\>
    Status = DtStringAppendDtString(pPath, &SettingsStr);
    if (DT_SUCCESS(Status))    
        // Convert serial to unicode string and append to path
        Status = DtStringUInt64ToDtStringAppend(pPath, 10, DvcSerial);

    if (DT_SUCCESS(Status))
    {
        Status = DtStringAppendDtString(pPath, &DeviceStr);
        if (DT_SUCCESS(Status))
        {
            if (pCategory != NULL) 
            {
                // Append category
                Status = DtStringAppendChars(pPath, "\\");
                if (DT_SUCCESS(Status))
                    Status = DtStringAppendChars(pPath, pCategory);
            }
        }
    }
    return Status;
}
Beispiel #2
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- CheckAndCreateRegistryPath -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  CheckAndCreateRegistryPath(
    WDFDRIVER  Driver,
    DtString*  pItemPath)
{
    DtStringChar*  pRegistryPath;
    DtString  RegistryPath;
    DtString  FullKeyName;
    UInt  PathLength;
    DtStatus  Status;
    Int  i;
    DT_STRING_DECL(ParamItemName, "\\Parameters");

    // Build the full path
    pRegistryPath = WdfDriverGetRegistryPath(Driver);
    PathLength = wcslen(pRegistryPath); 

    DT_STRING_INIT_CONST(RegistryPath, pRegistryPath, PathLength);

    // Allocate a new DtString buffer for the complete path inclusive a '\0' character and
    // extra '\'
    if (!DT_SUCCESS(DtStringAlloc(&FullKeyName, PathLength+
                                                  DtStringGetStringLength(&ParamItemName)+
                                                   DtStringGetStringLength(pItemPath)+2)))
        return STATUS_NO_MEMORY;

    DtStringAppendDtString(&FullKeyName, &RegistryPath);
    DtStringAppendDtString(&FullKeyName, &ParamItemName);

    if (RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer) != STATUS_SUCCESS)
        RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer);

    Status = DT_STATUS_OK;

    i = 1;
    // Get all subitems from pItemPath and check if the registry entry exist.
    // If not, create the registry entry.
    // This function is needed, because Wuindows only allows us to create one registry entry
    // at a time and not a complete path.
    while (Status == DT_STATUS_OK)
    {
        DtStringAppendChars(&FullKeyName, "\\");
        Status = DtStringAppendSubstring(&FullKeyName, pItemPath, i, '\\');
        if (DT_SUCCESS(Status))
        {
            if (RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer) 
                                                                        != STATUS_SUCCESS)
                RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer);
        }
        i++;
    }
    DtStringFree(&FullKeyName);
    return DT_STATUS_OK;    
}
Beispiel #3
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- EzUsbLoadFirmware -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  EzUsbLoadFirmware(
    DtuDeviceData*  pDvcData,
    const DtuIntelHexRecord*  pMicroCode)
{
    DtStatus  Status;
    Int  Dummy = 0;
    DtuIntelHexRecord*  pPtr = NULL;

    if (pMicroCode == NULL)
        return DT_STATUS_INVALID_PARAMETER;

    //.-.-.-.-.-.-.-.-.-.-.-.- Download firmware to internal RAM -.-.-.-.-.-.-.-.-.-.-.-.-
    //
    // Before starting the upload, stop the 8051

    Status = EzUsbResetProcessor(pDvcData, TRUE);
    if (!DT_SUCCESS(Status))
    {
        DtDbgOut(ERR, DTU, "Failed to stop the processor (Status=0x%08X)", Status);
        return Status;
    }

    pPtr = (DtuIntelHexRecord*)pMicroCode;
    while (pPtr->Type == 0)
    {
        // Send load command
        Status = DtUsbVendorRequest(&pDvcData->m_Device, NULL, EZUSB_FX2_LOAD_INTERNAL, 
                                   pPtr->Address, 0, DT_USB_HOST_TO_DEVICE, 
                                   pPtr->Data, pPtr->Length, &Dummy, MAX_USB_REQ_TIMEOUT);
        if (!DT_SUCCESS(Status))
        {
            DtDbgOut(ERR, DTU, "Failed to send load command (Status=0x%08X)", Status);
            return Status;
        }
        pPtr++;
    }
    // Restart the 8051
    if (Status == DT_STATUS_OK)
    {
        Status = EzUsbResetProcessor(pDvcData, FALSE);
        if (!DT_SUCCESS(Status))
        {
            DtDbgOut(ERR, DTU, "Failed to start the processor (Status=0x%08X)", Status);
            return Status;
        }
    }
  
    return DT_STATUS_OK;
}
Beispiel #4
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtTableGetForType -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtTableGetForType(
    const char*  pTypeName,
    Int  TypeNumber, 
    Int  SubDvc,
    Int  HwRev,
    Int  FwVer,
    Int  FwVariant,
    const char*  pTableName, 
    Int  PortIndex, 
    UInt  MaxNumEntries,
    UInt* pNumEntries,
    DtTableEntry* pTableEntry2,
    UInt OutBufSize)
{
    DtPropertyData  PropData;
    DtStatus  Status = DT_STATUS_OK;
        
    // Init property data structure
    PropData.m_TypeNumber = TypeNumber;
    PropData.m_SubDvc = SubDvc;
    PropData.m_FirmwareVariant = FwVariant;
    PropData.m_FirmwareVersion = FwVer;
    PropData.m_HardwareRevision = HwRev;
    PropData.m_TypeName = (char*)pTypeName;

    Status = DtTablesInit(&PropData);
    if (!DT_SUCCESS(Status))
        return Status;

    // Now find the table
    return DtTableGet(&PropData, pTableName, PortIndex, MaxNumEntries, pNumEntries,
                                                                pTableEntry2, OutBufSize);
}
Beispiel #5
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- EzUsbIsFirmwareLoaded -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
// Check if microcode for the EzUsb chip has been loaded
//
Bool  EzUsbIsFirmwareLoaded(DtuDeviceData* pDvcData)
{
    DtStatus  Status;
    DtString  DtStr;
    DtStringChar  DtStrBuffer[64];
    
    // Connect DtStrBuffer to DtStr
    DT_STRING_INIT(DtStr, DtStrBuffer, 64);

    // Found a uninitialised DTU-2xx device with manuf microcode
    if (pDvcData->m_DevInfo.m_ProductId == DTU2xx_MANUF)
        return TRUE;

    // For DTU-3XX devices check that the manufacturer string is "DekTec".
    if (pDvcData->m_DevInfo.m_TypeNumber>=300 && pDvcData->m_DevInfo.m_TypeNumber<400)
        return DtUsbManufNameEq(&pDvcData->m_Device, "DekTec");

    //.-.-.-.-.-.-.-.- Check for the availability of a string descriptor -.-.-.-.-.-.-.-.-
    //
    // If there is no microcode there will be no string descriptor

    Status = DtUsbQueuryString(&pDvcData->m_Device, &DtStr, 1);
    if (!DT_SUCCESS(Status))
        return FALSE;

    // Must find a string descriptor with a size >= 3
    return DtStringGetStringLength(&DtStr)>=3 ? TRUE : FALSE;
}
Beispiel #6
0
//-.-.-.-.-.-.-.-.-.-.-.-.- PathAppendSettingsSerialPortCategory -.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  PathAppendSettingsSerialPortCategory(
    DtString*  pPath,
    UInt64  DvcSerial,
    Int  Port,
    Char*  pCategory)
{
    DtStatus  Status = DT_STATUS_OK;
    DT_STRING_DECL(SettingsStr, "Settings\\");
    DT_STRING_DECL(PortStr, "\\Port");
        
    // Registry path starts with <\Settings\>
    Status = DtStringAppendDtString(pPath, &SettingsStr);
    if (DT_SUCCESS(Status))
    {
        // Convert serial to unicode string and append to path
        Status = DtStringUInt64ToDtStringAppend(pPath, 10, DvcSerial);
    }

    if (DT_SUCCESS(Status))
    {
        // Append port if provided
        if (Port >= 0)
        {
            Status = DtStringAppendDtString(pPath, &PortStr);
            if (DT_SUCCESS(Status))
            {
                // Convert Port to unicode string
                Status = DtStringUIntegerToDtStringAppend(pPath, 10, Port);
            }
        }
        
        if (DT_SUCCESS(Status))
        {
            if (pCategory != NULL) 
            {
                // Append category
                Status = DtStringAppendChars(pPath, "\\");
                if (DT_SUCCESS(Status))
                    Status = DtStringAppendChars(pPath, pCategory);
            }
        }
    }
    return Status;
}
Beispiel #7
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuDvcPowerSupplyInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
// Initializes the Altera power supply
// 
DtStatus  DtuDvcPowerSupplyInit(DtuDeviceData* pDvcData)
{
    DtStatus  Status = DT_STATUS_OK;
    UInt8  I2cBuf[8];
    Int  TypeNumber = pDvcData->m_DevInfo.m_TypeNumber;

    if (TypeNumber==215)
    {
        // Start 1V2 power supply (ALTERA core voltage)
        // NOTE: we only start the 1V2 power supply here. Other power supplies are started
        // later when we init the device hardware.
        I2cBuf[0] = DTU215_IIC_ADDR_PWR_1V2;
        I2cBuf[1] = DTU215_IIC_PWR_1V2_CTRL;
        Status = DtuI2cWrite(pDvcData, NULL, DTU215_IIC_ADDR_PWR_SUPPLY, 2, I2cBuf);
        // Sleep shortly to allow power-supply to settle
        DtSleep(200);
        if (DT_SUCCESS(Status))
            DtDbgOut(AVG, DTU, "DTU-%d power supply started", TypeNumber);
        else
            DtDbgOut(ERR, DTU, "DTU-%d power supply start ERROR. Error: %xh", TypeNumber, 
                                                                                  Status);
    }
    else if ((TypeNumber==350 || TypeNumber==351) && pDvcData->m_DevInfo.m_UsbSpeed==2)
    {
        Status = DtUsbVendorRequest(&pDvcData->m_Device, NULL, DTU_USB3_PNP_CMD,
                           DTU_PNP_CMD_DVC_POWER, DTU_DVC_POWER_ON, DT_USB_HOST_TO_DEVICE,
                           NULL, 0, NULL, MAX_USB_REQ_TIMEOUT);
        if (DT_SUCCESS(Status))
            DtSleep(100);
    }
    else if (TypeNumber==315 && pDvcData->m_DevInfo.m_UsbSpeed==2)
    {
        // DTU-315 specific: Enable LED (fade PWM mode)
        Dtu3RegWrite(pDvcData, DTU3_FX3_BLOCK_OFFSET, &FwbFx3.LedCtrl, 1);
    }
    
    return Status;
}
Beispiel #8
0
DtStatus  DtIoConfigReadFromNonVolatileStorage(
    DtDrvObject*  pSalDrvObj,
    UInt64  Serial,
    Int  PortIndex,
    Int  IoGroup,
    DtIoConfigValueDriver*  pCfgValue)
{
    DtStatus  Result;
    Int32  Value;
    Int64  BinValue;
    Char StrValue[IOCONFIG_NAME_MAX_SIZE];
    Int  ParXtraIdx;
    DtIoConfigValueDriver  IoConfig;
    Char GroupName[IOCONFIG_NAME_MAX_SIZE];

    
    // Get the IO group name
    Result = IoConfigNameGet(IoGroup, GroupName, sizeof(GroupName) );
    if (!DT_SUCCESS(Result))
        return Result;

    // Get config value
    Result = DtNonVolatileSettingsStringRead(pSalDrvObj, Serial, PortIndex,
                                    GroupName, "ConfigValue", StrValue, sizeof(StrValue));
    if (!DT_SUCCESS(Result))
        return Result;

    Result = IoConfigCodeGet(StrValue, &Value);
    if (!DT_SUCCESS(Result))
        return Result;
    IoConfig.m_Value = (Int)Value;

    // Get config subvalue
    Result = DtNonVolatileSettingsStringRead(pSalDrvObj, Serial, PortIndex,
                                 GroupName, "ConfigSubValue", StrValue, sizeof(StrValue));
    if (!DT_SUCCESS(Result))
        return Result;

    Result = IoConfigCodeGet(StrValue, &Value);
    if (!DT_SUCCESS(Result))
        return Result;
    IoConfig.m_SubValue = Value;
    
    // Read ParXtra
    for (ParXtraIdx=0; ParXtraIdx<DT_MAX_PARXTRA_COUNT; ParXtraIdx++)
    {
        Result = DtNonVolatileSettingsValueRead(pSalDrvObj, Serial, PortIndex,
                                 GroupName, (Char*)IoParXtraNames[ParXtraIdx], &BinValue);
        if (!DT_SUCCESS(Result))
            return DT_STATUS_CONFIG_ERROR;
        IoConfig.m_ParXtra[ParXtraIdx] = BinValue;
    }

    // Copy result only if succeeded
    *pCfgValue = IoConfig;

    return DT_STATUS_OK;
}
Beispiel #9
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuShBufferInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtuShBufferInit(
    DtuIoctlShBufCmdInput*  pShBufCmdInput,
    DtFileObject*  pFile,
    DtPageList*  pPageList,
    char*  pBuffer,
    Int  BufSize,
    UInt  BufType,
    DtuShBuffer*  pShBuffer)
{
    DtStatus  Status;

    if (pShBuffer->m_Initialised)
        return DT_STATUS_IN_USE;

    // Create a pagelist for the shared buffer
    Status = DtCreatePageList(pBuffer, BufSize, BufType, &pShBuffer->m_PageList);
    if (!DT_SUCCESS(Status))
        return Status;
        
    pShBuffer->m_pBuffer = pBuffer;
    if (BufType == DT_BUFTYPE_USER)
    {
        // Lock buffer into kernel memory
        Status = DtLockUserBuffer(&pShBuffer->m_PageList, pBuffer);
        if (DT_SUCCESS(Status))
            pShBuffer->m_pBuffer = pShBuffer->m_PageList.m_pVirtualKernel;
    }
    if (!DT_SUCCESS(Status))
    {
        DtDeletePageList(&pShBuffer->m_PageList);
        return Status;
    }

    pShBuffer->m_Owner = *pFile;
    pShBuffer->m_Initialised = TRUE;
    return Status;
}
Beispiel #10
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- EzUsbLoadFirmware -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  EzUsbLoadFirmwareFx3(
    DtuDeviceData*  pDvcData,
    const DtuFx3HexRecord*  pMicroCode)
{
    DtStatus  Status;
    Int  Dummy = 0;
    const DtuFx3HexRecord*  pPtr = pMicroCode;
    Bool  Cont = TRUE;

    if (pMicroCode == NULL)
        return DT_STATUS_INVALID_PARAMETER;

    DtDbgOut(MAX, DTU, "Loading firmware");
    
    while (Cont)
    {
        UInt32  Len = pPtr->Length;
        UInt32  Addr = pPtr->Address;
        UInt8*  Data = (UInt8*)(pPtr->Data);
        UInt32  NumToWrite;
        Cont = (pPtr->Length != 0);
        do
        {
            NumToWrite = Len < FX3_MAX_CHUNK_SIZE ? Len : FX3_MAX_CHUNK_SIZE;
            
            // Send load command
            Status = DtUsbVendorRequest(&pDvcData->m_Device, NULL, EZUSB_FX2_LOAD_INTERNAL, 
                                       Addr&0xFFFF, Addr>>16, DT_USB_HOST_TO_DEVICE, 
                                       Data, NumToWrite, &Dummy, MAX_USB_REQ_TIMEOUT);
            if (!DT_SUCCESS(Status))
            {
                DtDbgOut(ERR, DTU, "Failed to send load command (Status=0x%08X)", Status);
                return Status;
            }
            Len -= NumToWrite;
            Addr += NumToWrite;
            Data += NumToWrite;
        } while (Len > 0);
        pPtr++;
    }
  
    return DT_STATUS_OK;
}
Beispiel #11
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtPropertiesGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtPropertiesGet(DtPropertyData* pPropData, const char* pName, Int PortIndex,
                                      DtPropertyValue* pValue, DtPropertyValueType* pType,
                                      DtPropertyScope* pScope,
                                      Int DtapiMaj, Int DtapiMin, Int DtapiBugfix)
{
    DtStatus  Status = DT_STATUS_OK;

    // Find the property in the property tables
    const  DtProperty*  pProperty = NULL;
    Status = DtPropertiesFind(pPropData, pName, PortIndex, &pProperty, DtapiMaj,
                                                                   DtapiMin, DtapiBugfix);
    if (Status == DT_STATUS_NOT_FOUND)
    {
        Int  i;
        Int  NumAltNames = 0;
        const char* const*  pAltNames;

        // If not found, look for alternative names
        // Get the alternative names
        DtPropertiesGetAltName(pName, &NumAltNames, &pAltNames);
        // Try to get the property for the alternative name
        for (i=0; i<NumAltNames && Status==DT_STATUS_NOT_FOUND; i++)
        {
            Status = DtPropertiesFind(pPropData, pAltNames[i], PortIndex, &pProperty,
                                                         DtapiMaj, DtapiMin, DtapiBugfix);
        }
    }  
    
    // Get property details
    if (DT_SUCCESS(Status) && pProperty!=NULL)
    {
        // Copy property info
        *pValue = pProperty->m_Value;
        *pType = pProperty->m_Type;
        *pScope = pProperty->m_Scope;
        DtDbgOut(MAX, PROP, "Found property %s for %s-%d, FW %d, HW %d. "
                            "Value: 0x%08x%08x, Type:%i, Scope:%i",
                              pName, pPropData->m_TypeName, pPropData->m_TypeNumber,
                              pPropData->m_FirmwareVersion, pPropData->m_HardwareRevision,
                              (UInt32)(*pValue>>32),(UInt32)*pValue, *pType, *pScope);
    } 
Beispiel #12
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuDemodInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtuDemodInit(DtuDeviceData* pDvcData)
{
    DtStatus  Status = DT_STATUS_OK;
    const DtuDemodFirmwareStore*  pDemodFirmware = NULL;
    
    pDemodFirmware = DtuGetDemodFirmware(pDvcData->m_DevInfo.m_ProductId,
                                                  pDvcData->m_DevInfo.m_HardwareRevision);
    if (pDemodFirmware == NULL)
        return DT_STATUS_OK;
    
    Status =  DtuLoadDemodFirmware(pDvcData, pDemodFirmware);
    if (!DT_SUCCESS(Status))
    {
        DtDbgOut(ERR, DTU, "Failed to upload demodulator firmware (Status=0x%08X)", 
                                                                                  Status);
        return Status;
    }
    DtDbgOut(AVG, DTU, "Demodulator firmware uploaded successfully");
                                                                                  
    return Status;
}
Beispiel #13
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuRead -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtuRead(
    DtuDeviceData*  pDvcData,
    Int  PortIndex,
    UInt8*  pBuf,
    Int  NumToRead,
    Int*  pNumRead)

{
    DtStatus  Status = DT_STATUS_OK;
    UInt8*  pTempBuf = NULL;
    Int  TempBufWrIndex = 0;
    Int  TempBufRdIndex = 0;
    Int  NonIpPortIndex;
    DtuNonIpPort*  pNonIpPort;
    Int  BytesLeft = NumToRead;
    Int  BufIndex = 0;
    Int  NumCopy = 0;

    // Get pipe for reading data
    Int  Pipe = pDvcData->m_EzUsb.m_ReadPipe;

    // Nothing read yet
    *pNumRead = 0;

    DtDbgOut(MAX, RDWR, "Entry: pBuf=%p, NumToRead=%d", pBuf, NumToRead);

    // Check if the PortIndex is from the NonIpPort
    Status = DtuGetNonIpPortIndex(pDvcData, PortIndex, &NonIpPortIndex);
    if (!DT_SUCCESS(Status))
        return Status;
    pNonIpPort = &pDvcData->m_pNonIpPorts[NonIpPortIndex];


    // Simple checks
    if (NumToRead == 0)
        return DT_STATUS_OK;
    if (pBuf == NULL)
        return DT_STATUS_INVALID_PARAMETER;

    // Get temporary buffer
    pTempBuf = pNonIpPort->m_pTempBuf;
    TempBufWrIndex = pNonIpPort->m_TempBufWrIndex;
    TempBufRdIndex = pNonIpPort->m_TempBufRdIndex;

    DtDbgOut(MAX, RDWR, "NumToRead=%d, BytesLeft:%d, TempLoad=%d", 
                                   NumToRead, BytesLeft, TempBufWrIndex - TempBufRdIndex);

    //-.-.-.-.-.-.-.-.-.-.- First check for data already pre-fetched -.-.-.-.-.-.-.-.-.-.-
    if (TempBufRdIndex > 0)
    {
        // Determine how much we can copy from temporary buffer
        Int  NumInTempBuf = TempBufWrIndex - TempBufRdIndex;
        NumCopy = (NumInTempBuf > NumToRead) ? NumToRead : NumInTempBuf;

        // Copy from temporary buffer to user buffer
        DtMemCopyToUserBuf(&pBuf[BufIndex], &pTempBuf[TempBufRdIndex], NumCopy);

        // Update counters
        TempBufRdIndex += NumCopy;
        BytesLeft -= NumCopy;
        BufIndex += NumCopy;
        *pNumRead += NumCopy;

        DtDbgOut(MAX, RDWR, "NumCopy=%d, BytesLeft:%d, TempLoad=%d", 
                                       NumCopy, BytesLeft, TempBufWrIndex-TempBufRdIndex);
    }

    // Temporary buffer empty?
    if (TempBufRdIndex==TempBufWrIndex)
    {
        // Reset indices, so we don't need a wraparround
        TempBufRdIndex = TempBufWrIndex = 0;
    }

    //.-.-.-.-.-.-.-.-.- Directly copy multiples of DTU_BULK_TRANSFER_ALIGN -.-.-.-.-.-.-.-.-.
    while (DT_SUCCESS(Status) && BytesLeft>=DTU_BULK_TRANSFER_ALIGN)
    {
        if (BytesLeft>=DTU_BULK_PACKETSIZE)
            // Copy DTU_BULK_PACKETSIZE bytes directly
            NumCopy = DTU_BULK_PACKETSIZE;
        else if (BytesLeft%DTU_BULK_TRANSFER_ALIGN == 0)
            // Bytes left is multiple of DTU_BULK_TRANSFER_ALIGN copy it directly
            NumCopy = BytesLeft;
        else
            // Copy the rest via temporary buffer
            break;

       // Read data
#ifdef LINBUILD
        // For Linux, we have to read from a temp. buffer. We can not read from
        // the user buffer directly
        Status = DtUsbPipeRead(&pDvcData->m_Device, NULL, Pipe, pTempBuf, NumCopy,
                                                                      MAX_USB_RW_TIMEOUT);
        DtMemCopyToUserBuf(&pBuf[BufIndex], pTempBuf, NumCopy);
#else
        Status = DtUsbPipeRead(&pDvcData->m_Device, NULL, Pipe, &pBuf[BufIndex], NumCopy,
                                                                      MAX_USB_RW_TIMEOUT);
#endif

        // Update counters
        BytesLeft -= NumCopy;
        BufIndex += NumCopy;
        *pNumRead += NumCopy;

        DtDbgOut(MAX, RDWR, "NumCopy=%d, BytesLeft:%d", NumCopy, BytesLeft);
    }

    //.-.-.-.-.-.-.-.-.- Copy the remaining bytes via temporary buffer  -.-.-.-.-.-.-.-.-.
    if (DT_SUCCESS(Status) && BytesLeft>0)
    {
        Int NumToTemp;

        DT_ASSERT(TempBufRdIndex==0 && TempBufWrIndex==0);

        // Copy a multiple of DTU_BULK_TRANSFER_ALIGN
        NumToTemp = ((BytesLeft + DTU_BULK_TRANSFER_ALIGN-1)/DTU_BULK_TRANSFER_ALIGN) * 
                                                                  DTU_BULK_TRANSFER_ALIGN;
        
        // Read data for temporary buffer
        Status = DtUsbPipeRead(&pDvcData->m_Device, NULL, Pipe, pTempBuf, NumToTemp, 
                                                                      MAX_USB_RW_TIMEOUT);
   
        // Copy remaining bytes from temporary buffer to user buffer
        NumCopy = BytesLeft;
        DtMemCopyToUserBuf(&pBuf[BufIndex], pTempBuf, NumCopy);

        // Update indices and counters
        TempBufWrIndex = NumToTemp;
        TempBufRdIndex = NumCopy;
        BytesLeft -= NumCopy;
        BufIndex += NumCopy;
        *pNumRead += NumCopy;

        DtDbgOut(MAX, RDWR, "NumCopy=%d, BytesLeft:%d", NumCopy, BytesLeft);
    }


    // Save temporary buffer indices
    pNonIpPort->m_TempBufWrIndex = TempBufWrIndex;
    pNonIpPort->m_TempBufRdIndex = TempBufRdIndex;

    DtDbgOut(MAX, RDWR, "Exit: pBuf[0]: %d, BytesLeft:%d, TempLoad=%d",pBuf[0], BytesLeft,
                                                           TempBufWrIndex-TempBufRdIndex);

    return Status;
}
Beispiel #14
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuLoadDemodFirmware -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtuLoadDemodFirmware(
    DtuDeviceData*  pDvcData, 
    const DtuDemodFirmwareStore*  pDemodFirmware)
{
    DtStatus  Status = DT_STATUS_OK;
    UInt8  Buffer[2];
    Int  i, j;
    UInt DvcAddr = pDemodFirmware->m_DemodI2cAddress;
    
    DT_ASSERT(pDemodFirmware != NULL);
    
    // First do the PRE-upload register writes
    if (pDemodFirmware->m_pPreUpload != NULL)
    {
        const DtuInitRegisterStruct*  pInitRegisterData = pDemodFirmware->m_pPreUpload;

        for (i=0; i<pInitRegisterData->m_RegisterDataCount; i++)
        {
            Buffer[0] = pInitRegisterData->m_RegData[i].m_Data[0];
            Buffer[1] = pInitRegisterData->m_RegData[i].m_Data[1];
            Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer);
            if (!DT_SUCCESS(Status))
            {
                DtDbgOut(ERR, DTU, "Error writing I2C pre-upload data. (Status=0x%08X)",
                                                                                  Status);
                return Status;
            }
        }
    }

    // Upload demodulator firmware
    if (pDemodFirmware->m_pFirmware != NULL)
    {
        const Int  MAX_BYTES_TO_TRY = 60;
        UInt8  AddrHigh;
        UInt8  AddrLow;
        Int  DataCount;
        Int  BytesToTry;
        const DtuHexStruct* pFirmware = pDemodFirmware->m_pFirmware;
        UInt8* pHexData=NULL;

        // First allocate memory for temporary helper buffer
        pHexData = DtMemAllocPool(DtPoolNonPaged, 4096, DTU_TAG);
        if (pHexData == NULL)
            return DT_STATUS_OUT_OF_MEMORY;
    
        for (i=0; i<pFirmware->m_HexBlockCount; i++)
        {
            const DtuHexBlockStruct*  pHexBlock = &(pFirmware->m_HexBlock[i]);
            DataCount = pHexBlock->m_DataCount;

            BytesToTry = 0;

            while (DataCount > 0)
            {
                AddrHigh = (UInt8)((pHexBlock->m_Address +
                                                  pHexBlock->m_DataCount-DataCount) >> 8);
                AddrLow = (UInt8)(pHexBlock->m_Address +
                                                        pHexBlock->m_DataCount-DataCount);
                // Write high address
                Buffer[0] = (UInt8)pDemodFirmware->m_AddrRegH;
                Buffer[1] = AddrHigh;
                Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer);
                if (!DT_SUCCESS(Status))
                {
                    DtDbgOut(ERR, DTU, "Error writing I2C high address. (Status=0x%08X)",
                                                                                  Status);
                    DtMemFreePool(pHexData, DTU_TAG);
                    return Status;
                }

                // Write low address
                Buffer[0] = (UInt8)pDemodFirmware->m_AddrRegL;
                Buffer[1] = AddrLow;
                Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer);
                if (!DT_SUCCESS(Status))
                {
                    DtDbgOut(ERR, DTU, "Error writing I2C low address. (Status=0x%08X)",
                                                                                  Status);
                    DtMemFreePool(pHexData, DTU_TAG);
                    return Status;
                }

                // Write data
                pHexData[0] = (UInt8)pDemodFirmware->m_DataReg;
                BytesToTry = (DataCount<=MAX_BYTES_TO_TRY ? DataCount : MAX_BYTES_TO_TRY);
                for (j=0; j<BytesToTry; j++) 
                    pHexData[j + 1] = pHexBlock->m_Data[j + pHexBlock->m_DataCount - 
                                                                               DataCount];
                Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, BytesToTry+1, pHexData);
                if (!DT_SUCCESS(Status))
                {
                    DtDbgOut(ERR, DTU, "Error writing I2C data. (Status=0x%08X)", Status);
                    DtMemFreePool(pHexData, DTU_TAG);
                    return Status;
                }
                DataCount -= BytesToTry;
            }

        }
        DtMemFreePool(pHexData, DTU_TAG);
    }

    // Do the STOP-upload register writes
    if (pDemodFirmware->m_pStopUpload != NULL)
    {
        const DtuInitRegisterStruct*  pInitRegisterData = pDemodFirmware->m_pStopUpload;

        for (i=0; i<pInitRegisterData->m_RegisterDataCount; i++)
        {
            Buffer[0] = pInitRegisterData->m_RegData[i].m_Data[0];
            Buffer[1] = pInitRegisterData->m_RegData[i].m_Data[1];
            Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer);
            if (!DT_SUCCESS(Status))
            {
                DtDbgOut(ERR, DTU, "Error writing I2C stop-upload data. (Status=0x%08X)",
                                                                                  Status);
                return Status;
            }
        }
    }

    // Wait until AP is running
    if (pDemodFirmware->m_pFirmware != NULL)
    {   
        Int  TimeOut;
        Buffer[0] = (UInt8)pDemodFirmware->m_ApStatReg;
        Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 1, Buffer);
        if (!DT_SUCCESS(Status))
        {
            DtDbgOut(ERR, DTU, "Error writing I2C apstat data. (Status=0x%08X)", Status);
            return Status;
        }

        // Wait until ready
        Buffer[0] = 1;
        TimeOut = 0;
        while (Buffer[0]==1 && TimeOut<250) // Wait max. 250ms
        {
            DtSleep(10);
            TimeOut += 10;
            // Read the app status
            Status = DtuI2cRead(pDvcData, NULL, DvcAddr, 1, Buffer);
            if (!DT_SUCCESS(Status))
            {
                DtDbgOut(ERR, DTU, "Error reading I2C apstat data. (Status=0x%08X)",
                                                                                  Status);
                return Status;
            }
        }
        if (Buffer[0] == 1)
        {
            DtDbgOut(ERR, DTU, "TIMEOUT! APSTAT = %x.", (Int)(Buffer[0]));
        }
    }

    //Do the post-upload register writes
    if (pDemodFirmware->m_pPostUpload != NULL)
    {
        const DtuInitRegisterStruct*  pInitRegisterData = pDemodFirmware->m_pPostUpload;

        for (i=0; i<pInitRegisterData->m_RegisterDataCount; i++)
        {
            Buffer[0] = pInitRegisterData->m_RegData[i].m_Data[0];
            Buffer[1] = pInitRegisterData->m_RegData[i].m_Data[1];
            Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer);
            if (!DT_SUCCESS(Status))
            {
                DtDbgOut(ERR, DTU, "Error writing I2C post-upload data. (Status=0x%08X)",
                                                                                  Status);
                return Status;
            }
        }
    }
    return Status;
}
Beispiel #15
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtNonVolatileManufSettingsRead -.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
// Read a registry key from the manufacturing section, e.g. from
// ../Dta/Parameters/Settings/Manuf/2137/ForcedHardwareRevision
//
DtStatus DtNonVolatileManufSettingsRead(
    DtDrvObject* pSalDrvObj, 
    Int Type, 
    Char* pName, 
    Int64* pBinValue)
{
    DtStatus  Status = DT_STATUS_OK;

#ifdef WINBUILD

    // Windows uses the registry to store non volatile settings
    NTSTATUS  NtStatus;
    DtString  RegKeyName;
    DtString  ValueName;

    // Allocate RegKeyName buffer
    Status = DtStringAlloc(&RegKeyName, 150);
    if (DT_SUCCESS(Status))
    {
        Status = DtStringAlloc(&ValueName, 40);
        if (DT_SUCCESS(Status))
        {
            // Create registry path string
            DT_STRING_DECL(SettingsStr, "Settings\\Manuf\\");
            
            // Registry path starts with <\Settings\Manuf\>
            Status = DtStringAppendDtString(&RegKeyName, &SettingsStr);
            if (DT_SUCCESS(Status) && Type!=-1)
                // Convert type to unicode string and append to path
                Status = DtStringUIntegerToDtStringAppend(&RegKeyName, 10, (UInt)(Type));
            
            if (DT_SUCCESS(Status))
            {
                // Convert value name to DtString
                Status = DtStringAppendChars(&ValueName, pName);
                if (DT_SUCCESS(Status))
                {
                    // Read register binary value
                    NtStatus = DriverParametersKeyRead(pSalDrvObj->m_WdfDriver, 
                                                &RegKeyName, &ValueName, pBinValue, NULL);
                    
                    if (!NT_SUCCESS(NtStatus))
                    {
                        Status = DT_STATUS_FAIL;

                        // Be more specific if object name was not found
                        if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
                            Status = DT_STATUS_NOT_FOUND;
                    }
                }
            }

            // Free ValueName
            DtStringFree(&ValueName);
        }
        
        // Free RegKeyName
        DtStringFree(&RegKeyName);
    }

#else
    // Not yet implemented in Linux.
    Status = DT_STATUS_NOT_FOUND;
#endif

    return Status;
}
Beispiel #16
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- IoConfigCodesCodeGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  IoConfigCodeGet( const char*  pName, Int  *pConfigCode)
{
    DtStatus  Status = DT_STATUS_OK;
    const IoConfigCodeHashSet*  pHashSets = IoConfigCodeHashSets;
    UInt  HashSetCount = IoConfigCodesHashCount;
    
    UInt  Hash = 0;
    Int  Index;
    Bool  ConfigNameFound = FALSE;
    const IoConfigCodeHashSet*  pHashSet = NULL;
    Int  ConfigCount = 0;
    const IoConfigCode*  pConfig = NULL;

    // Special case empty string
    if (pName[0] == '\0')
    {
        *pConfigCode = -1;
        return Status;
    }

    // Determine the name hash
    Hash = DtDjb2(pName) % HashSetCount;

    // Get correct hash set (if exists)
    if (DT_SUCCESS(Status))
    {
        pHashSet = &pHashSets[Hash];
        ConfigCount = pHashSets[Hash].m_ConfigCodeCount;

        // Check if a hash set was available for this hash value
        if (pHashSet == NULL)
            Status = DT_STATUS_NOT_FOUND;
    }

    // Get correct config entry within hash set
    if (DT_SUCCESS(Status))
    {
        // Search all configs
        for (Index=0; Index<ConfigCount; Index++)
        {
            pConfig = &pHashSet->m_pConfigCodes[Index];

            // Compare name to check if we found the first occurrence
            if (DtAnsiCharArrayIsEqual(pName, pConfig->m_pName))
            {
                *pConfigCode = pConfig->m_Value;
                ConfigNameFound = TRUE;
                break;
            }
        }
        if (!ConfigNameFound)
            Status = DT_STATUS_NOT_FOUND;

    }

    if (!ConfigNameFound)
        DtDbgOut(ERR, PROP, "ConfigName %s is not found", pName);
    else
        DtDbgOut(MAX, PROP, "Found config code %d for %s", *pConfigCode, pName);

    return Status;
}
Beispiel #17
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- EzUsbInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  EzUsbInit(DtuDeviceData* pDvcData, Bool* pReEnumerate)
{
    DtStatus  Status = DT_STATUS_OK;
    const DtuIntelHexRecord*  pEzUsbFirmware = NULL;
    DtPropertyData*  pPropData = &pDvcData->m_PropData;
    Bool  IsEzUsbFwLoaded=FALSE, IsPldFwLoaded=FALSE;
    Int  FirmwareEndpoint;
    Int  ReadEndpoint;
    Int  WriteEndpoint;
    
    

    // Initialize properties
    FirmwareEndpoint = DtPropertiesGetInt(pPropData, "USB_END_POINT_FIRMWARE", -1);
    ReadEndpoint = DtPropertiesGetInt(pPropData, "USB_END_POINT_READ", -1);
    WriteEndpoint = DtPropertiesGetInt(pPropData, "USB_END_POINT_WRITE", -1);
        
    // Check if no property error occurred
    Status = DtuPropertiesReportDriverErrors(pDvcData);
    if (!DT_SUCCESS(Status))
        return Status;

    // Check if we need to load firmware. NOTE: there are two conditions to load the 
    // firmware namely:
    //   1. EzUsb firmware is not loaded yet
    //   2. PLD firmware is loaded already, which suggest a warm-reboot which we want to
    //      treat as a cold roboot => upload EzUsb firmware, but no re-enumeration
    *pReEnumerate = FALSE;

    IsEzUsbFwLoaded = EzUsbIsFirmwareLoaded(pDvcData);
    IsPldFwLoaded = FALSE;
    if (IsEzUsbFwLoaded && !(pDvcData->m_DevInfo.m_TypeNumber>=300
                                                 && pDvcData->m_DevInfo.m_TypeNumber<400))
        IsPldFwLoaded = DtuPldIsFirmwareLoaded(pDvcData);
    if (!IsEzUsbFwLoaded || IsPldFwLoaded)
    {
        if (IsPldFwLoaded)
            DtDbgOut(MIN, DTU, "PLD FW is already loaded => warm reboot");
        else
            DtDbgOut(MIN, DTU, "No EzUsb firmware loaded => cold reboot");

        if (pDvcData->m_DevInfo.m_TypeNumber>=300 && pDvcData->m_DevInfo.m_TypeNumber<400)
        {
            // Lookup firmware
            const DtuFx3HexRecord*  pFx3Firmware = Dtu3GetFx3Firmware(
                                                pDvcData->m_DevInfo.m_TypeNumber,
                                                -1,
                                                pDvcData->m_DevInfo.m_HardwareRevision);
            if (pFx3Firmware == NULL)
                DtDbgOut(ERR, DTU, "FX3 firmware not found for Typenumber: %d,"
                                                                     " HardwareRev: 0x%X",
                                                  pDvcData->m_DevInfo.m_TypeNumber,
                                                  pDvcData->m_DevInfo.m_HardwareRevision);

            if (!DtUsbManufNameEq(&pDvcData->m_Device, "Cypress"))
            {
                DtDbgOut(ERR, DTU, "DTU-3XX vid/pid found but wrong manufacturer string");
                return DT_STATUS_FAIL;
            }
            if (pDvcData->m_DevInfo.m_ProductId == DTU3_PID_UNIT_EEPROM)
                pDvcData->m_BootState = DTU_BOOTSTATE_FACTORY_COLD;
            else
                pDvcData->m_BootState = DTU_BOOTSTATE_COLD;

            //TODOTM: verify product string is "DTU-351"

            // Upload firmware for EzUsb chip
            Status = EzUsbLoadFirmwareFx3(pDvcData, pFx3Firmware);
            if (!DT_SUCCESS(Status))
            {
                DtDbgOut(ERR, DTU, "Failed to upload FX3 firmware (Status=0x%08X)", Status);
                return Status;
            }
            DtDbgOut(ERR, DTU, "FX3 firmware uploaded");
        } else {
            // Lookup firmware
            pEzUsbFirmware = DtuGetEzUsbFirmware(pDvcData->m_DevInfo.m_ProductId,
                                                  -1,
                                                  pDvcData->m_DevInfo.m_HardwareRevision);
            if (pEzUsbFirmware == NULL)
            {
                DtDbgOut(ERR, DTU, "No EzUsb firmware available for DTU-%d", 
                                                            pDvcData->m_DevInfo.m_TypeNumber);
                return DT_STATUS_FAIL;
            }

            // Upload firmware for EzUsb chip
            Status = EzUsbLoadFirmware(pDvcData, pEzUsbFirmware);
            if (!DT_SUCCESS(Status))
            {
                DtDbgOut(ERR, DTU, "Failed to upload FX2 firmware (Status=0x%08X)", Status);
                return Status;
            }
        }

        *pReEnumerate = !IsPldFwLoaded;   // Device will reenumerate, if cold reboot
        if (!IsPldFwLoaded)
            return DT_STATUS_OK;  // In case of cold reboot we are done (will reenumerate)
    }

    // Convert endpoint to pipe numbers
    if (FirmwareEndpoint != -1)
    {
        // Convert endpoint to pipe number
        pDvcData->m_EzUsb.m_FirmwarePipe = DtUsbGetBulkPipeNumber(&pDvcData->m_Device,
                                                 DT_USB_HOST_TO_DEVICE, FirmwareEndpoint);
        DT_ASSERT(pDvcData->m_EzUsb.m_FirmwarePipe != -1);
    }
    
    if (ReadEndpoint != -1)
    {
        // Convert endpoint to pipe number
        pDvcData->m_EzUsb.m_ReadPipe = DtUsbGetBulkPipeNumber(&pDvcData->m_Device,
                                 DT_USB_DEVICE_TO_HOST, ReadEndpoint);
        DT_ASSERT(pDvcData->m_EzUsb.m_ReadPipe != -1);
    }
    
    if (WriteEndpoint != -1)
    {
        // Convert endpoint to pipe number
        pDvcData->m_EzUsb.m_WritePipe = DtUsbGetBulkPipeNumber(&pDvcData->m_Device,
                                DT_USB_HOST_TO_DEVICE, WriteEndpoint);
        DT_ASSERT(pDvcData->m_EzUsb.m_WritePipe != -1);
    }

    return Status;
}
Beispiel #18
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtDpcSchedule -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtDpcSchedule(DtDpc* pDpc, DtDpcArgs* pArgs)
{
    DtStatus  Result = DT_STATUS_OK;
    Int  OldState;
    Bool  DoRun = FALSE;
    Bool  DoQueue = FALSE;

    DT_ASSERT(pDpc->m_SchedulingEnabled);

    // Try to set running from idle state
    OldState = DtAtomicCompareExchange((Int*)&pDpc->m_State, 0, DPC_STATE_BIT_RUNNING);
    if (OldState == 0)
        // Successfully running
        DoRun = TRUE;
    else if (pDpc->m_QueueIfRunning)
    {
        // Try to set Queuing
        OldState = DtAtomicCompareExchange((Int*)&pDpc->m_State, DPC_STATE_BIT_RUNNING,
                                             DPC_STATE_BIT_RUNNING|DPC_STATE_BIT_QUEUING);
        if (OldState == DPC_STATE_BIT_RUNNING)
            // Successfully set to queuing
            DoQueue = TRUE;
        // Not running anymore?
        // Try to set running again to be sure a full execution of the worker is pending
        // after the call the DtDpcSchedule... 
        else if ((OldState&DPC_STATE_BIT_RUNNING) == 0)
        {
            // Retry to set running from idle state
            OldState = DtAtomicCompareExchange((Int*)&pDpc->m_State, 0, 
                                                                   DPC_STATE_BIT_RUNNING);
            if (OldState == 0)
                // Successfully set to running
                DoRun = TRUE;
            else
                Result = DT_STATUS_IN_USE;
        } else
            Result = DT_STATUS_IN_USE;
    }

    if (!DT_SUCCESS(Result))
        return Result;

    // Queue DPC?
    if (DoQueue)
    {
        // Copy arguments
        pDpc->m_QueuedArgs = *pArgs;

        // Set to queued (running|queuing|queued)
        OldState = DtAtomicCompareExchange((Int*)&pDpc->m_State,
                        DPC_STATE_BIT_RUNNING|DPC_STATE_BIT_QUEUING,
                        DPC_STATE_BIT_RUNNING|DPC_STATE_BIT_QUEUING|DPC_STATE_BIT_QUEUED);
        // Check if we failed because we were not running anymore
        if (OldState == DPC_STATE_BIT_QUEUING)
        {
            // Choose running slot --> try to set from queuing to running instead of
            // queued
            OldState = DtAtomicCompareExchange((Int*)&pDpc->m_State,
                                            DPC_STATE_BIT_QUEUING, DPC_STATE_BIT_RUNNING);
            if (OldState == DPC_STATE_BIT_QUEUING)
                DoRun = TRUE;
            else {
                Result = DT_STATUS_IN_USE;
                // Can not happen?
                DT_ASSERT(FALSE);
            }
        }
    }

    // Start initial DPC?
    if (DoRun)
    {
        pDpc->m_Args = *pArgs;

#ifdef WINBUILD
        KeInsertQueueDpc(&pDpc->m_Kdpc, NULL, NULL);
#else
        tasklet_schedule(&pDpc->m_Tasklet);
#endif

        // Running flag is already set...
    }

    return Result;
}
Beispiel #19
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaGenlockInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtaGenlockInit(DtaDeviceData* pDvcData)
{
    DtStatus  Status = DT_STATUS_OK;

    // Initialize properties    
    DtPropertyData*  pPropData = &pDvcData->m_PropData;

    // Assume genlock is not supported
    pDvcData->m_Genlock.m_IsSupported = FALSE;
    pDvcData->m_Genlock.m_OpModeIntSrc = GENLOCK_OPMODE_INTSRC_UNDEF;

    pDvcData->m_Genlock.m_GenlArch = DtPropertiesGetInt(pPropData, "GENLOCK_ARCH", -1);
    // Do we have a valid architecture
    if (pDvcData->m_Genlock.m_GenlArch > 0)
        pDvcData->m_Genlock.m_IsSupported = TRUE;
    
    pDvcData->m_Genlock.m_AsyncPortIndex = DtPropertiesGetInt(pPropData, 
                                                                "GENLOCK_ASYNC_PORT", -1);
           
    if (pDvcData->m_Genlock.m_AsyncPortIndex > 0)
        pDvcData->m_Genlock.m_AsyncPortIndex--;     // Convert to port-index
    else
        pDvcData->m_Genlock.m_AsyncPortIndex = -1;  // No async port

    // Get internal genref port
    pDvcData->m_Genlock.m_IntGenrefPortIndex = DtPropertiesGetInt(pPropData, 
                                                           "GENLOCK_INT_GENREF_PORT", -1);
    if (pDvcData->m_Genlock.m_IntGenrefPortIndex > 0)
        pDvcData->m_Genlock.m_IntGenrefPortIndex--;     // Convert to port-index
    else
        pDvcData->m_Genlock.m_IntGenrefPortIndex = -1;  // No internal genref port

    // Get slave genref port
    pDvcData->m_Genlock.m_SlaveGenrefPortIndex = DtPropertiesGetInt(pPropData, 
                                                         "GENLOCK_SLAVE_GENREF_PORT", -1);
    if (pDvcData->m_Genlock.m_SlaveGenrefPortIndex > 0)
        pDvcData->m_Genlock.m_SlaveGenrefPortIndex--;     // Convert to port-index
    else
        pDvcData->m_Genlock.m_SlaveGenrefPortIndex = -1;  // No slave genref port

    // Get the port group mask
    pDvcData->m_Genlock.m_PortGroup = DtPropertiesGetUInt32(pPropData, 
                                                                "GENLOCK_PORT_GROUP", -1);

    // Init to 'safe' default values
    pDvcData->m_Genlock.m_FracMode = DTA_GENLOCK_FRACMODE_NA;
    pDvcData->m_Genlock.m_RefPortIndex = pDvcData->m_Genlock.m_IntGenrefPortIndex;
    pDvcData->m_Genlock.m_RefVidStd = DT_VIDSTD_625I50;
    pDvcData->m_Genlock.m_OutVidStd = pDvcData->m_Genlock.m_RefVidStd;
    pDvcData->m_Genlock.m_RefLineDurationNs = pDvcData->m_Genlock.m_OutLineDurationNs = 1; 
    pDvcData->m_Genlock.m_InDelayNs = 0;
    pDvcData->m_Genlock.m_LineOffset = 0;
    pDvcData->m_Genlock.m_TofAlignOffsetNs = 0;

    if (pDvcData->m_Genlock.m_GenlArch == GENLOCK_ARCH_2152 || 
                                  pDvcData->m_Genlock.m_GenlArch == GENLOCK_ARCH_2154)
    {
        UInt16  Offset = -1;
        Offset = DtPropertiesGetUInt16(&pDvcData->m_PropData, "REGISTERS_GENL", -1);
        if (Offset == (UInt16)-1)
        {
            DtDbgOut(ERR, GENL, "Failed to get genlock register offset property");
            return DT_STATUS_FAIL;
        }
        pDvcData->m_Genlock.m_pGenlRegs = (UInt8*)pDvcData->m_DtaRegs.m_pKernel + Offset;
    }
    else
        pDvcData->m_Genlock.m_pGenlRegs = NULL;
        
    if (pDvcData->m_Genlock.m_GenlArch == GENLOCK_ARCH_2152)
    {
       Status = DtaLmh1982Init(pDvcData, &pDvcData->m_Genlock.m_Lmh1982);
        if (!DT_SUCCESS(Status))
            DtDbgOut(ERR, GENL, "Failed to init LMH-1982 module");
    }
    else if (pDvcData->m_Genlock.m_GenlArch == GENLOCK_ARCH_2154)
    {
        // Must have an operational mode
        Int  OpMode = DtPropertiesGetInt(pPropData, "GENLOCK_OPMODE_INTSRC", -1);
        if (OpMode!=GENLOCK_OPMODE_INTSRC_FREE_RUN && OpMode!=GENLOCK_OPMODE_INTSRC_AFD)
        {
            DtDbgOut(ERR, GENL, "Invalid value (%d) for 'GENLOCK_OPMODE_INTSRC' property",
                                                                                  OpMode);
            return DT_STATUS_FAIL;
        }
        pDvcData->m_Genlock.m_OpModeIntSrc = OpMode;
        pDvcData->m_Genlock.m_VcxoValue = -1;
        pDvcData->m_Genlock.m_pVcxoOwner = NULL;

        Status = DtaLmh1983Init(pDvcData, &pDvcData->m_Genlock.m_Lmh1983);
        if (!DT_SUCCESS(Status))
            DtDbgOut(ERR, GENL, "Failed to init LMH-1983 module");
    }

    // 145/2145/2144 architecture
    if (pDvcData->m_Genlock.m_GenlArch==GENLOCK_ARCH_2144 || 
                                         pDvcData->m_Genlock.m_GenlArch==GENLOCK_ARCH_145)
        Status = DtaFpgaGenlockInit(pDvcData, &pDvcData->m_Genlock.m_FpgaGenlock);
    
    return Status;
}
Beispiel #20
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaEnDecIoctl -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtaEnDecIoctl(
    DtaDeviceData*  pDvcData,
    DtFileObject*  pFile,
    DtIoctlObject*  pIoctl,
    Bool  PowerDownPending)
{
    DtStatus  Status = DT_STATUS_OK;
    char*  pCmdStr;             // Mnemonic string for Command
    UInt  InReqSize = 0;        // Required length of input buffer
    UInt  OutReqSize = 0;       // Required length of output buffer
    Int  NonIpPortIndex;        // Index in the nonip port struct
    DtaNonIpPort*  pNonIpPort = NULL;
    DtaIoctlEnDecCmdInput*  pEnDecCmdInput = 
                                           (DtaIoctlEnDecCmdInput*)pIoctl->m_pInputBuffer;
    DtaIoctlEnDecCmdOutput*  pEnDecCmdOutput =
                                         (DtaIoctlEnDecCmdOutput*)pIoctl->m_pOutputBuffer;
    
    // Default require at least the size of the header preceding the data
    InReqSize = OFFSETOF(DtaIoctlEnDecCmdInput, m_Data);
    OutReqSize = OFFSETOF(DtaIoctlEnDecCmdOutput, m_Data);

    // Check if we can read m_Cmd / m_PortIndex
    if (pIoctl->m_InputBufferSize < InReqSize)
        return DT_STATUS_INVALID_PARAMETER;

    // Validate port index
    pNonIpPort = NULL;  // Assume a board level request
    if (!DT_SUCCESS(DtaGetNonIpPortIndex(pDvcData, pEnDecCmdInput->m_PortIndex,
                                                                        &NonIpPortIndex)))
         return DT_STATUS_INVALID_PARAMETER;
    pNonIpPort = &pDvcData->m_pNonIpPorts[NonIpPortIndex];

    if (!pNonIpPort->m_CapAvEnc)
        return DT_STATUS_NOT_SUPPORTED;
    
    // Determine final required output/input sizes
    switch (pEnDecCmdInput->m_Cmd)
    {
    case DTA_ENDEC_CMD_EXCLUSIVE_ACCESS:
        pCmdStr = "DTA_ENDEC_CMD_EXCLUSIVE_ACCESS";
        InReqSize += sizeof(DtaIoctlNonIpCmdExclusiveAccessInput);
        OutReqSize = 0;
        break;
        
    case DTA_ENDEC_CMD_GET_SOURCE_PORT:
        pCmdStr = "DTA_ENDEC_CMD_GET_SOURCE_PORT";
        InReqSize = 0;
        OutReqSize += sizeof(DtaIoctEnDecCmdGetSourcePortOutput);
        break;

    case DTA_ENDEC_CMD_SET_SOURCE_PORT:
        pCmdStr = "DTA_ENDEC_CMD_SET_SOURCE_PORT";
        InReqSize += sizeof(DtaIoctEnDecCmdSetSourcePortInput);
        OutReqSize = 0;
        break;
        
    case DTA_ENDEC_CMD_GET_VIDSTD:
        pCmdStr = "DTA_ENDEC_CMD_GET_VIDSTD";
        InReqSize = 0;
        OutReqSize += sizeof(DtaIoctEnDecCmdGetVidStdOutput);
        break;

    case DTA_ENDEC_CMD_SET_VIDSTD:
        pCmdStr = "DTA_ENDEC_CMD_SET_VIDSTD";
        InReqSize += sizeof(DtaIoctEnDecCmdSetVidStdInput);
        OutReqSize = 0;
        break;

    default:
        pCmdStr = "??UNKNOWN ENDEC_CMD CODE??";
        Status = DT_STATUS_NOT_SUPPORTED;
    }

    if (DT_SUCCESS(Status))
    {
        // Check buffer sizes
        if (pIoctl->m_InputBufferSize < InReqSize)
        {
            DtDbgOut(ERR, D7PRO, "%s: INPUT BUFFER TOO SMALL Size=%d Req=%d", pCmdStr,
                                                    pIoctl->m_InputBufferSize, InReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }
        if (pIoctl->m_OutputBufferSize < OutReqSize)
        {
            DtDbgOut(ERR, D7PRO, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pCmdStr, 
                                                  pIoctl->m_OutputBufferSize, OutReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }

        DtDbgOut(MAX, D7PRO, "%s: In=%d (Rq=%d), Out=%d (Rq=%d)", pCmdStr,
            pIoctl->m_InputBufferSize, InReqSize, pIoctl->m_OutputBufferSize, OutReqSize);
    }

    // The bytes written will be updated if needed. Set the default value here.
    pIoctl->m_OutputBufferBytesWritten = OutReqSize;

    if (DT_SUCCESS(Status))
    {
        switch (pEnDecCmdInput->m_Cmd)
        {
        case DTA_ENDEC_CMD_EXCLUSIVE_ACCESS:
            Status = DtaEnDecExclusiveAccess(pNonIpPort, pFile,
                                          pEnDecCmdInput->m_Data.m_ExclusiveAccess.m_Cmd);
            break;

        case DTA_ENDEC_CMD_GET_SOURCE_PORT:
            Status = DtaEnDecGetSourcePort(pNonIpPort,
                                    &pEnDecCmdOutput->m_Data.m_GetSourcePort.m_PortIndex);
            break;

        case DTA_ENDEC_CMD_SET_SOURCE_PORT:
            Status = DtaEnDecSetSourcePort(pNonIpPort,
                                      pEnDecCmdInput->m_Data.m_SetSourcePort.m_PortIndex);
            break;

        case DTA_ENDEC_CMD_GET_VIDSTD:
            Status = DtaEnDecGetVidStd(pNonIpPort,
                                           &pEnDecCmdOutput->m_Data.m_GetVidStd.m_VidStd);
            break;

        case DTA_ENDEC_CMD_SET_VIDSTD:
            Status = DtaEnDecSetVidStd(pNonIpPort,
                                             pEnDecCmdInput->m_Data.m_SetVidStd.m_VidStd);
            break;
        }
    }

    // If we failed, no data has to be copied to user space
    if (!DT_SUCCESS(Status))
    {
        pIoctl->m_OutputBufferBytesWritten = 0;
        if (Status == DT_STATUS_NOT_SUPPORTED)
            DtDbgOut(MIN, D7PRO, "EnDecCmd=0x%x: NOT SUPPORTED", pEnDecCmdInput->m_Cmd);
        else if (Status == DT_STATUS_IO_PENDING)
            DtDbgOut(MAX, D7PRO, "%s: ERROR %xh", pCmdStr, Status); // NOT A REAL ERROR
        else
            DtDbgOut(MIN, D7PRO, "%s: ERROR %xh", pCmdStr, Status);
    }

    return Status;
}
Beispiel #21
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuShBufferIoctl -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtuShBufferIoctl(
    DtuDeviceData*  pDvcData, 
    DtFileObject*  pFile, 
    DtIoctlObject*  pIoctl)
{
    DtStatus  Status = DT_STATUS_OK;
    char*  pIoctlStr;           // Mnemonic string for Command
    UInt  InReqSize = 0;        // Required length of input buffer
    UInt  OutReqSize = 0;       // Required length of output buffer
    Int  Index;
    DtuShBuffer*  pShBuffer = NULL;
    DtuIoctlShBufCmdInput*  pShBufCmdInput = 
                                           (DtuIoctlShBufCmdInput*)pIoctl->m_pInputBuffer;
    
    InReqSize = OFFSETOF(DtuIoctlShBufCmdInput, m_Data);
    
    
    // Check if we can read m_Cmd
    if (pIoctl->m_InputBufferSize < OFFSETOF(DtuIoctlShBufCmdInput, m_Data))
        return DT_STATUS_INVALID_PARAMETER;

    switch (pShBufCmdInput->m_Cmd)
    {
    case DTU_SH_BUF_CMD_INIT:
        pIoctlStr = "DTU_SH_BUF_CMD_INIT";
        InReqSize += sizeof(DtuIoctlShBufCmdInitInput);
        // We expect an output buffer size, but will be checked later
        OutReqSize = 0;
        break;

    case DTU_SH_BUF_CMD_CLOSE:
        pIoctlStr = "DTU_HP_BUF_CMD_CLOSE";
        // We expect no output buffer
        OutReqSize = 0;
        break;

    default:
        pIoctlStr = "??UNKNOWN VPDCMD CODE??";
        Status = DT_STATUS_NOT_SUPPORTED;
    }

    if (DT_SUCCESS(Status))
    {
        // Check buffer sizes
        if (pIoctl->m_InputBufferSize < InReqSize)
        {
            DtDbgOut(ERR, SHBUF, "%s: INPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, 
                                                        pIoctl->m_InputBufferSize, InReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }
        if (pIoctl->m_OutputBufferSize < OutReqSize)
        {
            DtDbgOut(ERR, SHBUF, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, 
                                                      pIoctl->m_OutputBufferSize, OutReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }

        DtDbgOut(MAX, SHBUF, "%s: In=%d (Rq=%d), Out=%d (Rq=%d)", pIoctlStr,
                pIoctl->m_InputBufferSize, InReqSize, pIoctl->m_OutputBufferSize, OutReqSize);
    }

    if (pShBufCmdInput->m_BufferIndex != 0)
    {
        DtDbgOut(ERR, SHBUF, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, 
                                                      pIoctl->m_OutputBufferSize, OutReqSize);
        return DT_STATUS_INVALID_PARAMETER;
    }
    
    // The bytes written will be updated if needed. Set the default value here.
    pIoctl->m_OutputBufferBytesWritten = OutReqSize;

    // Lookup the shared buffer structure
    // Check if the PortIndex is from the NonIpPort
    Status = DtuGetNonIpPortIndex(pDvcData, pShBufCmdInput->m_PortIndex, &Index);
    if (!DT_SUCCESS(Status))
        return DT_STATUS_NOT_FOUND;
    pShBuffer = &pDvcData->m_pNonIpPorts[Index].m_SharedBuffer;

    if (DT_SUCCESS(Status))
    {
        switch (pShBufCmdInput->m_Cmd)
        {
        case DTU_SH_BUF_CMD_INIT:
            {
                char*  pBuffer;
                UInt  Size;
                DtPageList*  pPageList = NULL;
#if defined(WINBUILD)
                DtPageList  PageList;
                PMDL  pMdl;
                NTSTATUS  NtStatus;
                // Retrieve MDL and virtual buffer from request object
                NtStatus = WdfRequestRetrieveOutputWdmMdl(pIoctl->m_WdfRequest, &pMdl);
                if (NtStatus != STATUS_SUCCESS)
                {
                    DtDbgOut(ERR, SHBUF, "WdfRequestRetrieveOutputWdmMdl error: %08x", 
                                                                                NtStatus);
                    Status = DT_STATUS_OUT_OF_RESOURCES;
                }
                if (DT_SUCCESS(Status))
                {
                    pBuffer = MmGetMdlVirtualAddress(pMdl);
                    if (pBuffer == NULL)
                    {
                        DtDbgOut(ERR, SHBUF, "DTU_SH_BUF_CMD_INIT: DT_STATUS_OUT_OF_MEMORY");
                        Status = DT_STATUS_OUT_OF_MEMORY;
                    }
                    Size = MmGetMdlByteCount(pMdl);

                    // Build pagelist object for user space buffer
                    pPageList = &PageList;
                    pPageList->m_BufType = DT_BUFTYPE_USER;
                    pPageList->m_OwnedByOs = TRUE;
                    pPageList->m_pMdl = pMdl;
                    pPageList->m_pVirtualKernel = NULL;
                }
#else // LINBUILD
                Size = (UInt)pShBufCmdInput->m_Data.m_Init.m_BufferSize;
#if defined(LIN32)
                pBuffer = (char*)(UInt32)pShBufCmdInput->m_Data.m_Init.m_BufferAddr;
#else
                pBuffer = (char*)(UInt64)pShBufCmdInput->m_Data.m_Init.m_BufferAddr;
#endif
#endif
                if (DT_SUCCESS(Status))
                {
                    Status = DtuShBufferInit(pShBufCmdInput, pFile, pPageList, pBuffer, 
                                                        Size, DT_BUFTYPE_USER, pShBuffer);
                    if (!DT_SUCCESS(Status))
                        DtDbgOut(ERR, SHBUF, "DtuShBufferInit failed");
                }
            }
            break;
        case DTU_SH_BUF_CMD_CLOSE:
            if (pDvcData->m_pNonIpPorts!=NULL && 
                                   pDvcData->m_pNonIpPorts[0].m_State==DTU3_STATE_READ351)
            {
                pDvcData->m_pNonIpPorts[0].m_NextState = DTU3_STATE_DET_VIDSTD;
                DtEventSet(&pDvcData->m_pNonIpPorts[0].m_StateChanged);
                DtEventWait(&pDvcData->m_pNonIpPorts[0].m_StateChangeCmpl, -1);
            }
            else  if (pDvcData->m_pNonIpPorts!=NULL && 
                                  pDvcData->m_pNonIpPorts[0].m_State==DTU3_STATE_WRITE315)
            {
                pDvcData->m_pNonIpPorts[0].m_NextState = DTU3_STATE_IDLE;
                DtEventSet(&pDvcData->m_pNonIpPorts[0].m_StateChanged);
                DtEventWait(&pDvcData->m_pNonIpPorts[0].m_StateChangeCmpl, -1);
            }
            Status = DtuShBufferClose(pShBuffer);
            break;
        default:
            Status = DT_STATUS_NOT_SUPPORTED;
        }
    }

    // If we failed, no data has te be copied to user space
    if (!DT_SUCCESS(Status))
    {
        pIoctl->m_OutputBufferBytesWritten = 0;
        if (Status == DT_STATUS_NOT_SUPPORTED)
            DtDbgOut(MIN, SHBUF, "ShBufCmd=0x%x: NOT SUPPORTED", pShBufCmdInput->m_Cmd);
    }
    return Status;
}
Beispiel #22
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DriverParametersKeyWrite -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
NTSTATUS  DriverParametersKeyWrite(
    WDFDRIVER  Driver,
    DtString*  pKeyName,
    DtString*  pValueName,
    Int64  BinValue,
    DtString*  pStrValue)
{
    NTSTATUS  NtStatus;
    WDFKEY  ParametersKey;
    WDFKEY  Key = NULL;
    WDFSTRING WdfString;
    
    DT_ASSERT(KeGetCurrentIrql()<=PASSIVE_LEVEL);
   
    // Check if the registry path already exists. If not, create the registry path.
    if (!DT_SUCCESS(CheckAndCreateRegistryPath(Driver, pKeyName)))
        return STATUS_UNSUCCESSFUL;
       
    // Open the drivers parameters key (under services)
    NtStatus = WdfDriverOpenParametersRegistryKey(Driver, KEY_WRITE,
                                                WDF_NO_OBJECT_ATTRIBUTES, &ParametersKey);
    if (!NT_SUCCESS(NtStatus))
    {
        DtDbgOut(ERR, SAL, "WdfDriverOpenParametersRegistryKey failed. Error: 0x%x", 
                                                                                NtStatus);
        return NtStatus;
    }

    // Open the key (including part of path)
    NtStatus = WdfRegistryOpenKey(ParametersKey, pKeyName, KEY_WRITE, 
                                                          WDF_NO_OBJECT_ATTRIBUTES, &Key);
    if (!NT_SUCCESS(NtStatus))
        DtDbgOut(ERR, SAL, "WdfRegistryOpenKey failed. Error: 0x%x", NtStatus);

    if (NT_SUCCESS(NtStatus))
    {

        // Write string or binary value
        if (pStrValue != NULL)
        {
            // Set string attributes with the key as parent object, so that the string 
            // object is freed when the key object is destroyed. If we donot do this the
            // string object is freed when the driver unloads, meaning that the each call 
            // to DriverParametersKeyWrite result in an increase of memory usage, only 
            // to be freed on the unload.
            WDF_OBJECT_ATTRIBUTES  WdfStringAttr;
            WDF_OBJECT_ATTRIBUTES_INIT(&WdfStringAttr);
            WdfStringAttr.ParentObject = Key;
            NtStatus = WdfStringCreate(pStrValue, &WdfStringAttr, &WdfString);

            if (NT_SUCCESS(NtStatus))
                NtStatus = WdfRegistryAssignString(Key, pValueName, WdfString);
        }
        else
            NtStatus = WdfRegistryAssignValue(Key, pValueName, REG_QWORD, sizeof(Int64),
                                                                               &BinValue);
        if (!NT_SUCCESS(NtStatus))
            DtDbgOut(ERR, SAL, "WdfRegistryAssignValue failed. Error: 0x%x", NtStatus);
    }
    
    if (Key != NULL)
        WdfRegistryClose(Key);
    WdfRegistryClose(ParametersKey);
    return NtStatus;
}
Beispiel #23
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtNonVolatileSettingsWrite -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtNonVolatileSettingsWrite(
    DtDrvObject*  pDrvObj,
    UInt64  DvcSerial,
    Int  Port,
    Char*  pCategory,
    Char*  pName,
    Int64  BinValue,
    Char*  pStrValue)
{
    DtStatus  Status = DT_STATUS_OK;

#ifdef WINBUILD

    // Windows uses the registry to store non volatile settings
    NTSTATUS  NtStatus;
    DtString  RegKeyName;
    DtString  ValueName;
    
    // Allocate RegKeyName buffer
    Status = DtStringAlloc(&RegKeyName, 150);
    if (DT_SUCCESS(Status))
    {
        Status = DtStringAlloc(&ValueName, 50);
        if (DT_SUCCESS(Status))
        {
            // Create registry path string
            Status = PathAppendSettingsSerialPortCategory(&RegKeyName, DvcSerial, Port, 
                                                                               pCategory);
            if (DT_SUCCESS(Status))
            {
                // Convert value name to DtString
                Status = DtStringAppendChars(&ValueName, pName);
                if (DT_SUCCESS(Status))
                {
                    if (pStrValue!=NULL)
                    {
                        DtString  StrValue;
                        Status = DtStringAlloc(&StrValue, 50);
                        if (DT_SUCCESS(Status))
                        {
                            // Convert value to DtString
                            Status = DtStringAppendChars(&StrValue, pStrValue);
                            if (DT_SUCCESS(Status))
                            {
                                // Write register string value
                                NtStatus = DriverParametersKeyWrite(pDrvObj->m_WdfDriver, 
                                                  &RegKeyName, &ValueName, -1, &StrValue);
                            }
                            // Free ValueName
                            DtStringFree(&StrValue);
                        }
                    }
                    else
                    {
                        // Write register binary value
                        NtStatus = DriverParametersKeyWrite(pDrvObj->m_WdfDriver, 
                                                 &RegKeyName, &ValueName, BinValue, NULL);
                    }

                    if (!NT_SUCCESS(NtStatus))
                        Status = DT_STATUS_FAIL;
                }
            }

            // Free ValueName
            DtStringFree(&ValueName);
        }

        // Free RegKeyName
        DtStringFree(&RegKeyName);
    }

#else

    // Linux can use config files, but they should not be read / write from a kernel
    // module --> http://www.linuxjournal.com/article/8110
    // Maybe use hotplug event in user space to have helper application to perform
    // driver load and do the initial settings. Helper application can be DtapiService
    // or a simple script.

    Status = DT_STATUS_OK;

#endif

    return Status;
}
Beispiel #24
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuWrite -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtuWrite(
    DtuDeviceData*  pDvcData,
    Int  PortIndex,
    UInt8*  pBuf,
    Int  NumToWrite)
{
    DtStatus  Status = DT_STATUS_OK;
    UInt8*  pTempBuf = NULL;
    Int  TempBufWrIndex = 0;
    Int  TempBufRdIndex = 0;
    Int  NonIpPortIndex;
    DtuNonIpPort*  pNonIpPort;
    Int  BytesLeft = NumToWrite;
    Int  BufIndex = 0;
    Int  NumCopy = 0;

    // Get pipe for writing data
    Int  Pipe = pDvcData->m_EzUsb.m_WritePipe;

    DtDbgOut(MAX, RDWR, "Entry: pBuf=%p, NumToWrite=%d", pBuf, NumToWrite);

    // Check if the PortIndex is from the NonIpPort
    Status = DtuGetNonIpPortIndex(pDvcData, PortIndex, &NonIpPortIndex);
    if (!DT_SUCCESS(Status))
        return Status;
    pNonIpPort = &pDvcData->m_pNonIpPorts[NonIpPortIndex];


    // Simple checks
    if (NumToWrite == 0)
        return DT_STATUS_OK;
    if (pBuf == NULL)
        return DT_STATUS_INVALID_PARAMETER;

    // Get temporary buffer
    pTempBuf = pNonIpPort->m_pTempBuf;
    TempBufWrIndex = pNonIpPort->m_TempBufWrIndex;
    TempBufRdIndex = pNonIpPort->m_TempBufRdIndex;

    DT_ASSERT(TempBufRdIndex==0);

    DtDbgOut(MAX, RDWR, "NumToWrite=%d, BytesLeft:%d, TempLoad=%d", 
                                                 NumToWrite, BytesLeft, TempBufWrIndex );

    //-.-.-.-.-.-.-.-.-.-.-.-.- Check for minimum transfer size -.-.-.-.-.-.-.-.-.-.-.-.-.

    // First transfer data from internal buffer
    if (TempBufWrIndex>0 && (TempBufWrIndex+NumToWrite)>=DTU_BULK_TRANSFER_ALIGN)
    {
        // Determine maximum to copy in TempBuf such that TempBuf is full or
        // filled with a multiple of DTU_BULK_TRANSFER_ALIGN bytes
        if ((TempBufWrIndex + NumToWrite) >= DTU_BULK_PACKETSIZE)
            NumCopy = DTU_BULK_PACKETSIZE - TempBufWrIndex;
        else
            NumCopy = NumToWrite - (TempBufWrIndex+NumToWrite)%DTU_BULK_TRANSFER_ALIGN;
        
        DtMemCopyFromUserBuf(&pTempBuf[TempBufWrIndex], &pBuf[BufIndex], NumCopy);

        DtDbgOut(MAX, RDWR, "NumCopy=%d, BytesLeft:%d, TempLoad=%d", 
                                                      NumCopy, BytesLeft, TempBufWrIndex);

        // Write data
        Status = DtUsbPipeWrite(&pDvcData->m_Device, NULL, Pipe, pTempBuf,
                                              TempBufWrIndex+NumCopy, MAX_USB_RW_TIMEOUT);
        // Temporary buffer is empty now
        TempBufWrIndex = 0;   
        TempBufRdIndex = 0;

        // Update counters
        BytesLeft -= NumCopy;
        BufIndex += NumCopy;
    }

    //-.-.-.-.-.-.-.-.-.-.-.-.- Directly copy multiples of 1024 -.-.-.-.-.-.-.-.-.-.-.-.-.
    while (DT_SUCCESS(Status) && BytesLeft>=DTU_BULK_TRANSFER_ALIGN)
    {
        if (BytesLeft>DTU_BULK_PACKETSIZE)
            NumCopy = DTU_BULK_PACKETSIZE;
        else 
            NumCopy = BytesLeft - (BytesLeft%DTU_BULK_TRANSFER_ALIGN);
    

        DtDbgOut(MAX, RDWR, "NumCopy=%d, BytesLeft:%d, TempLoad=%d", 
                                                      NumCopy, BytesLeft, TempBufWrIndex);
        // Write data
#ifdef LINBUILD
        // For Linux, we have to write to a temp. buffer. We can not write to
        // the user buffer directly
        DtMemCopyFromUserBuf(pTempBuf, &pBuf[BufIndex], NumCopy);
        Status = DtUsbPipeWrite(&pDvcData->m_Device, NULL, Pipe, pTempBuf, NumCopy,
                                                                      MAX_USB_RW_TIMEOUT);
#else
        Status = DtUsbPipeWrite(&pDvcData->m_Device, NULL, Pipe, &pBuf[BufIndex], NumCopy,
                                                                      MAX_USB_RW_TIMEOUT);
#endif
    
        BytesLeft -= NumCopy;
        BufIndex += NumCopy;
    }

    //-.-.-.-.-.-.-.-.-.-.- Copy remaining data to temporary buffer -.-.-.-.-.-.-.-.-.-.-.
    if (DT_SUCCESS(Status) && BytesLeft > 0 )
    {
        NumCopy = BytesLeft;
        DtDbgOut(MAX, RDWR, "NumCopy=%d, BytesLeft:%d, TempLoad=%d", 
                                                      NumCopy, BytesLeft, TempBufWrIndex);
        DtMemCopyFromUserBuf(&pTempBuf[TempBufWrIndex], &pBuf[BufIndex], NumCopy);

        // Update index and counters
        TempBufWrIndex += NumCopy;
        BytesLeft -= NumCopy;
        BufIndex += NumCopy;
    }

    // Save temporary buffer indices
    pNonIpPort->m_TempBufWrIndex = TempBufWrIndex;
    pNonIpPort->m_TempBufRdIndex = TempBufRdIndex;

    DtDbgOut(MAX, RDWR, "Exit: BytesLeft:%d, TempLoad=%d",  BytesLeft, TempBufWrIndex);

    return Status;
}
Beispiel #25
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DriverParametersSubKeyDelete -.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
NTSTATUS  DriverParametersSubKeyDelete(
    WDFDRIVER  Driver,
    DtString*  pKeyName)
{
    NTSTATUS  NtStatus = STATUS_SUCCESS;
    DtStringChar*  pRegistryPath;
    DtString  RegistryPath;
    DtString  FullKeyName;
    UInt  PathLength;
    HANDLE  hKey;
    OBJECT_ATTRIBUTES  ObjectAttributes;
    KEY_BASIC_INFORMATION*  pKeyInfo;
    ULONG  Size;
    ULONG  ResultSize;
    Int  Index;
    
    DT_STRING_DECL(ParamItemName, "\\Parameters\\");

    DT_ASSERT(KeGetCurrentIrql()<=PASSIVE_LEVEL);

    // Build the full path
    pRegistryPath = WdfDriverGetRegistryPath(Driver);
    PathLength = wcslen(pRegistryPath); 

    DT_STRING_INIT_CONST(RegistryPath, pRegistryPath, PathLength);

    // Allocate struct for key information result
    Size = sizeof(KEY_BASIC_INFORMATION)+100;
    pKeyInfo = DtMemAllocPool(DtPoolNonPaged, Size, SAL_TAG);
    if (pKeyInfo == NULL)
        return STATUS_NO_MEMORY;

    // Allocate a new DtString buffer for the complete path inclusive a '\0' character
    // and extra '\\'
    if (!DT_SUCCESS(DtStringAlloc(&FullKeyName, PathLength+
                                                  DtStringGetStringLength(&ParamItemName)+
                                                  DtStringGetStringLength(pKeyName)+
                                                  100+1+1)))
    {
        DtMemFreePool(pKeyInfo, SAL_TAG);
        return STATUS_NO_MEMORY;
    }

    DtStringAppendDtString(&FullKeyName, &RegistryPath);
    DtStringAppendDtString(&FullKeyName, &ParamItemName);
    DtStringAppendDtString(&FullKeyName, pKeyName);

    // Initialize key to open
    InitializeObjectAttributes(&ObjectAttributes, &FullKeyName, OBJ_KERNEL_HANDLE, NULL,
                                                                                    NULL);
    
    NtStatus = ZwOpenKey(&hKey, KEY_ENUMERATE_SUB_KEYS , &ObjectAttributes);
    
    if (NT_SUCCESS(NtStatus)) 
    {
        Index = 0;
        NtStatus = STATUS_SUCCESS;
        // Enumerate all keys
        while (NtStatus != STATUS_NO_MORE_ENTRIES)
        {
            NtStatus = ZwEnumerateKey(hKey, Index, KeyBasicInformation, pKeyInfo, Size,
                                                                             &ResultSize);
            if (NT_SUCCESS(NtStatus))
            {
                DtString SubKey;

                // Build key to delete
                pKeyInfo->Name[pKeyInfo->NameLength/2] = L'\0';
                DT_STRING_INIT_CONST(SubKey, pKeyInfo->Name, ((USHORT)pKeyInfo->NameLength/2));

                DtStringClear(&FullKeyName);
                DtStringAppendDtString(&FullKeyName, pKeyName);
                DtStringAppendChars(&FullKeyName, "\\");
                DtStringAppendDtString(&FullKeyName, &SubKey);
                
                DtDbgOut(MAX, SAL, "Delete SubKey %S.", FullKeyName.Buffer);
                NtStatus = DriverParametersKeyDelete(Driver, &FullKeyName);
                if (!NT_SUCCESS(NtStatus))
                    DtDbgOut(ERR, SAL, "Error deleting SubKey %S. Error: %x", 
                                                            FullKeyName.Buffer, NtStatus);
            }
            // In case deletion failed, skip this entry
            if (!NT_SUCCESS(NtStatus)) 
                Index++;
        }
        NtStatus = ZwDeleteKey(hKey);
        ZwClose(hKey);
    }
    DtMemFreePool(pKeyInfo, SAL_TAG);
    DtStringFree(&FullKeyName);
    return NtStatus;
}
Beispiel #26
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtTableGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtTableGet(
    DtPropertyData*  pPropData,
    const char*  pTableName,
    Int  PortIndex,
    UInt  MaxNumEntries,
    UInt*  pNumEntries,
    DtTableEntry*  pTableEntry2,
    UInt OutBufSize)
{
    DtStatus  Status = DT_STATUS_OK;
    const DtTableStore*  pStore = (DtTableStore*)pPropData->m_pTableStore;
    Int  HwRevision = pPropData->m_HardwareRevision;
    Int  FwVariant = pPropData->m_FirmwareVariant;

    Bool  TableNameFound = FALSE;
    Int  FindCount = 0;
    UInt  Index;
    DtTableLink*  pTableLinkFound = NULL;

    // For devices with no 'EC' VPD resource and no registry key which forces the
    // hardware revision, treat the hardware revision as 0
    if (HwRevision < 0)
        HwRevision = 0;
    
    *pNumEntries = 0;
    if (pPropData->m_pTableStore == NULL)
    {
        DtDbgOut(ERR, TABLE, "There are no tables defined at all for DTX-%d", 
                                                                 pPropData->m_TypeNumber);
        return DT_STATUS_NOT_FOUND;
    }

    // If the property is not found for a specific fw-variant try a second time
    // without specifying a specific fw-variant
    for (FindCount=0; FindCount<2 && pTableLinkFound==NULL; FindCount++)
    {
        if (FindCount == 1)
            FwVariant = -1;

        TableNameFound = FALSE;

        // Search all tables
        for (Index=0; Index<pStore->m_TableLinkCount; Index++)
        {
            const DtTableLink*  pTableLink = &pStore->m_pTableLink[Index];

            // Check if the table name was already found. If so, we stop if
            // name <> NULL.
            if (TableNameFound)
            {
                // When the table name was found earlier, only accept entries without
                // a name. We just stop when (another) named entry is found.
                if (pTableLink->m_pName != NULL)
                    break;
            } else {
                // Compare name to check if we found the first occurrence
                if (DtAnsiCharArrayIsEqual(pTableName, pTableLink->m_pName))
                    TableNameFound = TRUE;
            }

            if (TableNameFound)
            {
                // Check port number and firmware variant
                if (PortIndex==pTableLink->m_PortIndex
                                                    && FwVariant==pTableLink->m_FwVariant)
                {
                    // Check minimal firmware version
                    if (pPropData->m_FirmwareVersion >= pTableLink->m_MinFw)
                    {
                        // Check minimal hardware version
                        if (HwRevision >= pTableLink->m_MinHw)
                        {
                            pTableLinkFound = (DtTableLink*)pTableLink;

                            // We can stop here since the parser has ordened each
                            // property by minimal firmware version/hardware version.
                            // This means the first hit is the best one
                            break;
                        }
                    }
                }
            }
        }
    }

    if (!TableNameFound)
    {   
        DtDbgOut(ERR, TABLE, "Table %s is not found at all for DTX-%d",
                                                        pTableName, pStore->m_TypeNumber);
        Status = DT_STATUS_NOT_FOUND;
    }
        
    // Check if the table was found
    if (pTableLinkFound == NULL)
    {
        Status = DT_STATUS_NOT_FOUND;
        DtDbgOut(ERR, TABLE, "Failed to get table %s for DTX-%d:%d, FW %d, HW %d port %i", 
                                                  pTableName,
                                                  pPropData->m_TypeNumber,
                                                  pPropData->m_SubDvc,
                                                  pPropData->m_FirmwareVersion,
                                                  pPropData->m_HardwareRevision,
                                                  PortIndex);
    }
    
    if (DT_SUCCESS(Status) && pTableLinkFound!=NULL)
    {
        DtDbgOut(MAX, TABLE, "Found table %s for DTX-%d:%d, FW %d, HW %d. #EL:%i #MAX:%i" ,
                                                  pTableName,
                                                  pPropData->m_TypeNumber,
                                                  pPropData->m_SubDvc,
                                                  pPropData->m_FirmwareVersion,
                                                  pPropData->m_HardwareRevision,
                                                  pTableLinkFound->m_TableEntryCount,
                                                  MaxNumEntries);
        *pNumEntries =  pTableLinkFound->m_TableEntryCount;
        
        // Check if enough space for the table
        if (MaxNumEntries < pTableLinkFound->m_TableEntryCount)
        {
            if (MaxNumEntries != 0)
                DtDbgOut(ERR, TABLE, "Max. number of entries to small. Needed:%i, "
                       "Space for:%i", pTableLinkFound->m_TableEntryCount, MaxNumEntries);
        }
        else if (OutBufSize < pTableLinkFound->m_TableEntryCount * sizeof(DtTableEntry)) {
            DtDbgOut(ERR, TABLE, "Buffer smaller than indicated by MaxNumEntries");
            Status = DT_STATUS_INVALID_PARAMETER;
        } else {
            // Copy table
            DtMemCopy(pTableEntry2, (void*)pTableLinkFound->m_pTableEntries, 
                             pTableLinkFound->m_TableEntryCount * sizeof(DtTableEntry));
        }
    } 
    return Status;
}
Beispiel #27
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaNonIpTxIoctl -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtaNonIpTxIoctl(
    DtaDeviceData*  pDvcData,
    DtFileObject*  pFile,
    DtIoctlObject*  pIoctl)
{
    DtStatus  Status = DT_STATUS_OK;
    char*  pCmdStr;             // Mnemonic string for Command
    UInt  InReqSize = 0;        // Required length of input buffer
    UInt  OutReqSize = 0;       // Required length of output buffer
    Int  NonIpPortIndex;        // Index in the nonip port struct
    DtaIoctlNonIpTxCmdInput* pNonIpTxCmdInput = 
                                         (DtaIoctlNonIpTxCmdInput*)pIoctl->m_pInputBuffer;
    DtaIoctlNonIpTxCmdOutput* pNonIpTxCmdOutput =
                                       (DtaIoctlNonIpTxCmdOutput*)pIoctl->m_pOutputBuffer;
    
    // Default require at least the size of the header preceding the data
    InReqSize = OFFSETOF(DtaIoctlNonIpTxCmdInput, m_Data);
    OutReqSize = OFFSETOF(DtaIoctlNonIpTxCmdOutput, m_Data);

    // Check if we can read m_Cmd / m_PortIndex
    if (pIoctl->m_InputBufferSize < InReqSize)
        return DT_STATUS_INVALID_PARAMETER;

    // Validate port index
    if (!DT_SUCCESS(DtaGetNonIpPortIndex(pDvcData, pNonIpTxCmdInput->m_PortIndex,
                                                                        &NonIpPortIndex)))
        return DT_STATUS_INVALID_PARAMETER;
    
    // Determine final required output/input sizes
    switch (pNonIpTxCmdInput->m_Cmd)
    {
    case DTA_NONIP_TX_CMD_GET_FLAGS:
        pCmdStr = "DTA_NONIP_TX_CMD_GET_FLAGS";
        OutReqSize += sizeof(DtaIoctlNonIpTxCmdGetFlagsOutput);
        // We expect no additional data in the input buffer
        InReqSize += 0;
        break;

    case DTA_NONIP_TX_CMD_CLEAR_FLAGS:
        pCmdStr = "DTA_NONIP_TX_CMD_CLEAR_FLAGS";
        InReqSize += sizeof(DtaIoctlNonIpTxCmdClearFlagsInput);
        // We expect no output buffer at all
        OutReqSize = 0;
        break;

    case DTA_NONIP_TX_CMD_SET_FAILSAFE_CFG:
        pCmdStr = "DTA_NONIP_TX_CMD_SET_FAILSAFE_CFG";
        InReqSize += sizeof(DtaIoctlNonIpTxCmdSetFailsafeCfgInput);
        // We expect no output buffer at all
        OutReqSize = 0;
        break;

    case DTA_NONIP_TX_CMD_SET_FAILSAFE_ALIVE:
        pCmdStr = "DTA_NONIP_TX_CMD_SET_FAILSAFE_ALIVE";
        // We expect no additional data in the input buffer
        InReqSize += 0;
        // We expect no output buffer at all
        OutReqSize = 0;
        break;
    
    case DTA_NONIP_TX_CMD_GET_FAILSAFE_INFO:
        pCmdStr = "DTA_NONIP_TX_CMD_GET_FAILSAFE_INFO";
        OutReqSize += sizeof(DtaIoctlNonIpTxCmdGetFailsafeInfoOutput);
        // We expect no additional data in the input buffer
        InReqSize += 0;
        break;

    default:
        pCmdStr = "??UNKNOWN VPDCMD CODE??";
        Status = DT_STATUS_NOT_SUPPORTED;
    }

    if (DT_SUCCESS(Status))
    {
        // Check buffer sizes
        if (pIoctl->m_InputBufferSize < InReqSize)
        {
            DtDbgOut(ERR, NONIP, "%s: INPUT BUFFER TOO SMALL Size=%d Req=%d", pCmdStr, 
                                                    pIoctl->m_InputBufferSize, InReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }
        if (pIoctl->m_OutputBufferSize < OutReqSize)
        {
            DtDbgOut(ERR, NONIP, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pCmdStr, 
                                                  pIoctl->m_OutputBufferSize, OutReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }

        DtDbgOut(MAX, NONIP, "%s: In=%d (Rq=%d), Out=%d (Rq=%d)", pCmdStr,
                pIoctl->m_InputBufferSize, InReqSize, pIoctl->m_OutputBufferSize, OutReqSize);
    }
    
    // The bytes written will be updated if needed. Set the default value here.
    pIoctl->m_OutputBufferBytesWritten = OutReqSize;

    if (DT_SUCCESS(Status))
    {
        // Execute cmd
        switch (pNonIpTxCmdInput->m_Cmd)
        {
        case DTA_NONIP_TX_CMD_GET_FLAGS:
            Status = DtaNonIpTxGetFlags(&pDvcData->m_pNonIpPorts[NonIpPortIndex],
                                         &pNonIpTxCmdOutput->m_Data.m_GetFlags.m_Status,
                                         &pNonIpTxCmdOutput->m_Data.m_GetFlags.m_Latched);
            break;

        case DTA_NONIP_TX_CMD_CLEAR_FLAGS:
            Status = DtaNonIpTxClearFlags(&pDvcData->m_pNonIpPorts[NonIpPortIndex],
                                    pNonIpTxCmdInput->m_Data.m_ClearFlags.m_FlagsToClear);
            break;

        case DTA_NONIP_TX_CMD_SET_FAILSAFE_CFG:
            Status = DtaNonIpTxSetFailsafeCfg(&pDvcData->m_pNonIpPorts[NonIpPortIndex],
                                     pNonIpTxCmdInput->m_Data.m_SetFailsafeCfg.m_Enable,
                                     pNonIpTxCmdInput->m_Data.m_SetFailsafeCfg.m_Timeout);
            break;

        case DTA_NONIP_TX_CMD_SET_FAILSAFE_ALIVE:
            Status = DtaNonIpTxSetFailsafeAlive(&pDvcData->m_pNonIpPorts[NonIpPortIndex]);
            break;
        
        case DTA_NONIP_TX_CMD_GET_FAILSAFE_INFO:
            Status = DtaNonIpTxGetFailsafeInfo(&pDvcData->m_pNonIpPorts[NonIpPortIndex],
                                   &pNonIpTxCmdOutput->m_Data.m_GetFailsafeInfo.m_Enable,
                                   &pNonIpTxCmdOutput->m_Data.m_GetFailsafeInfo.m_Timeout,
                                   &pNonIpTxCmdOutput->m_Data.m_GetFailsafeInfo.m_Alive);
            break;

        default:
            Status = DT_STATUS_NOT_SUPPORTED;
        }
    }

    // If we failed, no data has te be copied to user space
    if (!DT_SUCCESS(Status))
    {
        pIoctl->m_OutputBufferBytesWritten = 0;
        if (Status == DT_STATUS_NOT_SUPPORTED)
            DtDbgOut(MIN, NONIP, "NonIpTxCmd=0x%x: NOT SUPPORTED", 
                                                                 pNonIpTxCmdInput->m_Cmd);
        else 
            DtDbgOut(MIN, NONIP, "%s: ERROR %xh", pCmdStr, Status);
    }

    return Status;
}
Beispiel #28
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtPropertiesFind -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtPropertiesFind(DtPropertyData* pPropData, const char* pName, Int PortIndex,
               const DtProperty** ppProperty, Int DtapiMaj, Int DtapiMin, Int DtapiBugfix)
{
    DtStatus  Status = DT_STATUS_OK;
    const DtPropertyStore*  pStore = (DtPropertyStore*)pPropData->m_pPropertyStore;
    const DtPropertyHashSet*  pHashSets = (DtPropertyHashSet*)pStore->m_pPropertyHashSets;
    UInt  HashSetCount = pStore->m_PropertyHashSetCount;
    Int  FwVersion = pPropData->m_FirmwareVersion;
    Int  HwRevision = pPropData->m_HardwareRevision;
    Int  FwVariant = pPropData->m_FirmwareVariant;


    UInt  Hash = 0;
    Int  Index;
    Int  FindCount = 0;
    Bool  PropertyNameFound = FALSE;
    const DtPropertyHashSet*  pHashSet = NULL;
    Int  PropertyCount = 0;
    *ppProperty = NULL;

    // For devices with no 'EC' VPD resource and no registry key which forces the
    // hardware revision, treat the hardware revision as 0
    if (HwRevision < 0)
        HwRevision = 0;

    // Determine the name hash
    Hash = DtDjb2(pName) % HashSetCount;

    // Get correct hash set (if it exists)
    if (DT_SUCCESS(Status))
    {
        pHashSet = &pHashSets[Hash];
        PropertyCount = pHashSets[Hash].m_PropertyCount;

        // Check if a hash set was available for this hash value
        if (pHashSet == NULL)
            Status = DT_STATUS_NOT_FOUND;
    }

    if (DT_SUCCESS(Status))
    {

        // If the property is not found for a specific fw-variant try a second time
        // without specifying a specific fw-variant
        for (FindCount=0; FindCount<2 && *ppProperty==NULL; FindCount++)
        {
            if (FindCount == 1)
                FwVariant = -1;
            
            // Get correct property entry within hash set
            PropertyNameFound = FALSE;
            
            // Search all properties
            for (Index=0; Index<PropertyCount; Index++)
            {
                const DtProperty*  pProp = &pHashSet->m_pProperties[Index];

                // Check the property name was already found
                if (PropertyNameFound)
                {
                    // When the property name was found earlier, only accept entries 
                    // without a name. We just stop when (another) named entry is found.
                    if (pProp->m_pName != NULL)
                          break;
                } else {
                    // Compare name to check if we found the first occurrence
                    if (DtAnsiCharArrayIsEqual(pName, pProp->m_pName))
                        PropertyNameFound = TRUE;
                }

                if (PropertyNameFound)
                {
                    // Check port number and firmware variant
                    if (PortIndex==pProp->m_PortIndex && FwVariant==pProp->m_FwVariant)
                    {
                        // Check minimal firmware version and hardware version
                        if (FwVersion>=pProp->m_MinFw && HwRevision>=pProp->m_MinHw &&
                                        (pProp->m_MaxHw==-1 || HwRevision<pProp->m_MaxHw))
                        {
                            Bool  DtapiVerOk = FALSE;
                            // -1 means the request came from the driver
                            if (DtapiMaj==-1 && DtapiMin==-1 && DtapiBugfix==-1)
                                DtapiVerOk = TRUE;
                            else if (DtapiMaj > pProp->m_MinDtapiMaj)
                                DtapiVerOk = TRUE;
                            else if (DtapiMaj==pProp->m_MinDtapiMaj)
                            {
                                if (DtapiMin > pProp->m_MinDtapiMin)
                                    DtapiVerOk = TRUE;
                                else if (DtapiMin==pProp->m_MinDtapiMin
                                                  && DtapiBugfix>= pProp->m_MinDtapiBugfix)
                                    DtapiVerOk = TRUE;
                            }
                            // Check minimal DTAPI version
                            if (DtapiVerOk)
                            {
                                *ppProperty = pProp;
                                // We can stop here since the parser has ordered each
                                // property by minimal firmware version/hardware version.
                                // This means the first hit is the best one...
                                break;
                            }
                        }
                    }
                }
            }
        }

        if (!PropertyNameFound)
        {   
            if (DtAnsiCharArrayStartsWith(pName, "CAP_"))
                DtDbgOut(AVG, PROP, "PropertyName(Capability) %s is not found at all for"
                         " %s-%d", pName, pPropData->m_TypeName, pPropData->m_TypeNumber);
            else
                DtDbgOut(MIN, PROP, "PropertyName %s is not found at all for %s-%d",
                                   pName, pPropData->m_TypeName, pPropData->m_TypeNumber);
        }
            
        // Check if the property was found
        if (*ppProperty == NULL)
        {
            Status = DT_STATUS_NOT_FOUND;
            DtDbgOut(AVG, PROP, "Failed to find property %s for %s-%d, FW %d, HW %d"
                     "VAR %d", pName, pPropData->m_TypeName, pPropData->m_TypeNumber,
                             pPropData->m_FirmwareVersion, pPropData->m_HardwareRevision,
                             pPropData->m_FirmwareVariant);
        }
    }

    return Status;
}
Beispiel #29
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuEventsGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
// Return a pending event. This functions blocks if no events are pending.
//
DtStatus  DtuEventsGet(
    DtuDeviceData*  pDvcData,
    DtFileObject*  pFile, 
    UInt*  pEventType, 
    UInt*  pValue1,
    UInt*  pValue2,
    Bool  Wait)
{
    DtStatus  Result = DT_STATUS_OK;
    DtuEvents*  pDtuEvents;

    if (pFile==NULL || pEventType==NULL || pValue1==NULL || pValue2==NULL)
        return DT_STATUS_INVALID_PARAMETER;

    // Get corresponding events object
    pDtuEvents = DtuEventsGetEventsObject(pDvcData, pFile);
    if (pDtuEvents == NULL)
        Result = DT_STATUS_NOT_FOUND;

    if (DT_SUCCESS(Result))
    {
        DtEventReset(&pDtuEvents->m_PendingEvent);

        if (Wait && pDtuEvents->m_NumPendingEvents==0 && !pDtuEvents->m_CancelInProgress) 
        {
            DtDbgOut(MAX, EVENTS, "Waiting for event");
        
            // Wait for event to be triggered
            DtEventWait(&pDtuEvents->m_PendingEvent, -1);
        }

        // The next request will be rejected by the IoCtl function, so we can reset
        // the Cancel state here.
        if (pDtuEvents->m_CancelInProgress)
            Result = DT_STATUS_CANCELLED;
        pDtuEvents->m_CancelInProgress = FALSE;

        DtSpinLockAcquire(&pDtuEvents->m_Lock);
        
        // Return pending events
        if (pDtuEvents->m_NumPendingEvents != 0)
        {  
            *pEventType = pDtuEvents->m_PendingEvents[0].m_EventType;
            *pValue1 = pDtuEvents->m_PendingEvents[0].m_EventValue1;
            *pValue2 =  pDtuEvents->m_PendingEvents[0].m_EventValue2;
            DtDbgOut(MAX, EVENTS, "Event #%d. Type: %d, Value1: %d, Value2: %d", 
                         pDtuEvents->m_NumPendingEvents, *pEventType, *pValue1, *pValue2);
            pDtuEvents->m_NumPendingEvents--;

            if (pDtuEvents->m_NumPendingEvents != 0)
            {   
                // Remove the old event
                DtMemMove(&pDtuEvents->m_PendingEvents[0],
                                       &pDtuEvents->m_PendingEvents[1],
                                       sizeof(DtuEvent) * pDtuEvents->m_NumPendingEvents);
            }
        } else {
            *pEventType = 0;
            *pValue1 = 0;
            *pValue2 = 0;
            if (Result == DT_STATUS_OK)
                Result = DT_STATUS_REQUEUE; // No pending events
            DtDbgOut(MAX, EVENTS, "Event #%d. No event", pDtuEvents->m_NumPendingEvents);
        }
    
        DtSpinLockRelease(&pDtuEvents->m_Lock);

        // Decrement refcount
        DtuEventsUnrefEventsObject(pDvcData, pDtuEvents);
    }
    
    return Result;
}
Beispiel #30
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtNonVolatileSettingsDelete -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtNonVolatileSettingsDelete(
    DtDrvObject*  pDrvObj,
    UInt64  DvcSerial,
    UInt  NumPorts)
{
    DtStatus  Status = DT_STATUS_OK;

#ifdef WINBUILD

    NTSTATUS  NtStatus;
    DtString  RegKeyName;
    Int  i;

    // Allocate RegKeyName buffer
    Status = DtStringAlloc(&RegKeyName, 150);
    if (!DT_SUCCESS(Status))
        return Status;
    
    // Remove all port settings
    for (i = 0; i < (Int)NumPorts; i++)
    {
        Status = DtStringClear(&RegKeyName);
        if (!DT_SUCCESS(Status))
        {
            DtStringFree(&RegKeyName);
            return Status;
        }
            
        Status = PathAppendSettingsSerialPortCategory(&RegKeyName, DvcSerial, i, NULL);
        if (!DT_SUCCESS(Status))
        {
            DtStringFree(&RegKeyName);
            return Status;
        }

        // First delete all subitems of PortX (=Categories)
        NtStatus = DriverParametersSubKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName);
    
        // Delete registry item: PortX
        NtStatus = DriverParametersKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName);
    }

    // Remove the device settings
    Status = DtStringClear(&RegKeyName);
    if (!DT_SUCCESS(Status))
    {
        DtStringFree(&RegKeyName);
        return Status;
    }

    Status = PathAppendSettingsSerialDeviceCategory(&RegKeyName, DvcSerial, NULL);
    if (!DT_SUCCESS(Status))
    {
        DtStringFree(&RegKeyName);
        return Status;
    }

    // First delete all subitems of device(=Categories)
    NtStatus = DriverParametersSubKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName);

    // Delete registry item: Device
    NtStatus = DriverParametersKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName);


    // Now remove the serial number
    Status = DtStringClear(&RegKeyName);
    if (!DT_SUCCESS(Status))
    {
        DtStringFree(&RegKeyName);
        return Status;
    }

    // Create path without port number
    Status = PathAppendSettingsSerialPortCategory(&RegKeyName, DvcSerial, -1, NULL);
    if (!DT_SUCCESS(Status))
    {
        DtStringFree(&RegKeyName);
        return Status;
    }
        
    // Delete registry item: serial number
    NtStatus = DriverParametersKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName);
    if (!NT_SUCCESS(NtStatus))
    {
        DtStringFree(&RegKeyName);
        return DT_STATUS_FAIL;
    }
    DtStringFree(&RegKeyName);
#else
    // Not yet implemented in Linux.
    Status = DT_STATUS_OK;
#endif

    return Status;
}