Beispiel #1
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 #2
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 #3
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;
}