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

📄 datatransfer.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                }               

                _buffer_size = packet_count * packet_size;
                _urb_size = GET_ISO_URB_SIZE(packet_count);
            }
            break;
        case UsbdPipeTypeBulk:
            {
                if(_p_current_config->getUsbSpeed()==1) //high speed
                {
                  packet_size = 512;  
                  if(_media_type == 1)  //audio, the reason is with low-rate transfer,we can't wait for long time to play
                  {
                      packet_count = 2;
                  }
                  else
                  {
                      //MS:Maximum Transfer Sizes for Bulk and Interrupt Pipes is 256,000 bytes. 
                      packet_count = 320;                      
                  }                    
                }
                else  //full speed
                {                	
                     packet_size = 64; 
                     packet_count = 4;
                }
                _buffer_size = packet_count * packet_size;
                _urb_size = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
		        _is_bulk = 1;
            }
            break;
    }
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS DataTransfer::start()
{   
    initializeTransfer();

    NTSTATUS status = STATUS_SUCCESS;
    DWORD i;
    for(i = 0; i < _buffers_need; i++)
    {

        PBUFFER_ENTRY p_buffer = allocateBuffer();
        if(p_buffer)
        {
            p_buffer->buffer_id = i;
            sendBuffer(p_buffer);
        }
        else
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }

        if(!NT_SUCCESS(status))
        {
            break;
        }
    }


    if(_buffer_count)
    {
        //We have some outstanding buffers, start the buffer parsing thread
        status = startThread();
    }
    
    return status;
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID DataTransfer::stop()
{
    if(!_stop_thread)
    {
        _stop_thread = TRUE;

        if(_p_thread_object)
        {
        
            //Release the completion thread if it is waiting on buffers
            _buffer_complete_queue.cancelWaits();
        
            //Wait for the buffer complete thread to exit
            KeWaitForSingleObject(
                _p_thread_object,
                Executive,
                KernelMode,
                TRUE,
                NULL);
        
            _p_thread_object = NULL;
        }

        //Abort any outstanding requests
        _p_usb->UsbAbortPipe(_pipe, _interface);

        //Wait for all outstanding buffers to complete and remove them from the 
        // buffer complete queue.
        while(_buffer_count)
        {
            PBUFFER_ENTRY p_buffer = _buffer_complete_queue.getBuffer();
        
            while(p_buffer)
            {
                freeBuffer(p_buffer);
                p_buffer = _buffer_complete_queue.getBuffer();
            }
        
            if(_buffer_count && !p_buffer)
            {
                _buffer_complete_queue.waitForBuffers(500);
                p_buffer = _buffer_complete_queue.getBuffer();
            }
        }
        // need to store the flag
        _digital_stream = 0;
	    _is_bulk = 0;
    }

}

/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS DataTransfer::sendBuffer(PBUFFER_ENTRY p_buffer)
{
    //Initialize our completion context
    p_buffer->p_data_transfer = this;
    p_buffer->read_context.pIrp = p_buffer->p_irp;
    p_buffer->read_context.pUrb = p_buffer->p_urb;
    p_buffer->read_context.pCompletion = (USBCOMPLETION)static_BufferComplete;
    p_buffer->read_context.UserContext = p_buffer;
    
    p_buffer->bytes_completed = 0;
    //Start a data transfer
    NTSTATUS status =  _p_usb->UsbAsyncIo(
        _pipe,
        _interface,
        p_buffer->p_buffer,
        _buffer_size,
        NULL,
        &(p_buffer->read_context)); 
    if(NT_SUCCESS(status))
    {
        return STATUS_SUCCESS;
    }
    //We have a failure.  Free the buffer. (Should we wait and retry if this fails?)
    KdPrint(("Error sending buffer to USB bus driver.  status = %x\n", status));

    //If we failed, the completion routine may not get called, so we need to avoid
    // losing the buffer.  Add the buffer to the complete queue.
    _buffer_complete_queue.addBuffer(p_buffer);

    // call datatransfer stop() to stop all operations 
    // This is the only way to recover from race condition.
    // once there is a problem with USB transfer, either it could be surprise removal or 
    // pipe broke issue. once the transfer is not ok, then in the present case the p_buffer is
    // added to complete queue, and data transfer thread inner while loop sees the buffer always
    // with bytes_completed as zero, and that too this thread runs at HIGH_PRIORITY-3 level, 
    // nobody else gets priority than the while loop. To avoid this race condition, we need to 
    // stop the complete operation as if top layer sent stop() command.

    // stop data transfer which will avoid double while loop of scheduling new IRP's
    // other wise system will be in these while loops forever because of its High Priority
    // If we decrease the priority, Movie maker fails to record the good video. So the data 
    // transfer thread has to run at high priority.
    //stop();
	return STATUS_UNSUCCESSFUL;
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID DataTransfer::static_BufferComplete(PBUFFER_ENTRY            p_context,
                                         NTSTATUS                 status, 
                                         ULONG                    transfer_size,
                                         PVOID                    p_read_context)
{
    if(p_context)
    {
        DataTransfer* p_this = p_context->p_data_transfer;

        if((status == STATUS_SUCCESS) && (transfer_size > 0))
        {
            p_context->bytes_completed = transfer_size;

            if( p_this->_digital_stream)
            {
                p_this->_polaris_engine_fail_count = 0;
            }
        }
        else
        {
        //    KdPrint(("DataTransfer::static_BufferComplete is failed, type = %x,transfer_size = %d\n",p_this->getType(),transfer_size));
            p_context->bytes_completed = 0;

            if( p_this->_digital_stream)
            {
                p_this->_polaris_engine_fail_count++;
            }
        }

        //if the buffer was not on the complete queue already, add it there.

        //Put the buffer in the buffer complete queue
        p_this->_buffer_complete_queue.addBuffer(p_context);
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID DataTransfer::static_ThreadFunction(DataTransfer* p_this)
{
    p_this->parseBufferThread();
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID DataTransfer::parseBufferThread()
{
    PBUFFER_ENTRY p_buffer_entry = NULL;
    ULONG fail_counter = 0;
    BOOL bUnrecoverableError = FALSE;
    NTSTATUS status=STATUS_UNSUCCESSFUL;

    // Initialize the variables for digital path
    if(_digital_stream)
    {
        _polaris_engine_fail_count=0;
        _ts_Data.Initialize(_p_usb_firmware);
    }

    KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY-3 );

    while(!_stop_thread)
    {
        p_buffer_entry = _buffer_complete_queue.getBuffer();
        while(p_buffer_entry)
        {
            if(_stop_thread)
            {
                break;
            }

            if(p_buffer_entry->bytes_completed != 0)
            {
              fail_counter = 0;
              if(_is_bulk)//bulk
              {
                   if( _digital_stream)
               {
                         _ts_Data.submitDataBuffer(
                                          p_buffer_entry->p_buffer,
                                         _buffer_size);
                    }
                    else
                    {
                        if (_media_type == 1)  //Audio without HANC
                        {
                            _data_parser.submitDataBuffer(
                                               p_buffer_entry->p_buffer,
                                              _buffer_size,1);
                        }
                        else   // other cases
                        {
                             _data_parser.submitDataBuffer(
                                          p_buffer_entry->p_buffer,
                                         _buffer_size,0);
                        }
                     }  
                    
               
               }
               else  //iso
               {

                        struct _URB_ISOCH_TRANSFER	*pIso = 
                        (struct _URB_ISOCH_TRANSFER *)p_buffer_entry->p_urb;

                    for (ULONG i = 0; i < pIso->NumberOfPackets; i++)
                    {
                        if (pIso->IsoPacket[i].Length)
                        {
                            if( _digital_stream)
                            {
                                // Digital path working
                                _ts_Data.submitDataBuffer(
                                 p_buffer_entry->p_buffer + pIso->IsoPacket[i].Offset,
                                 pIso->IsoPacket[i].Length);
                            }
                            else
                            {
                                // Analog path working
                                if (_media_type == 1)  // Audio without HANC
                                {
                                    _data_parser.submitDataBuffer(
                                        p_buffer_entry->p_buffer + pIso->IsoPacket[i].Offset,
                                        pIso->IsoPacket[i].Length,1);
                                }
                                else
                                {
                                     _data_parser.submitDataBuffer(
                                        p_buffer_entry->p_buffer + pIso->IsoPacket[i].Offset,
                                        pIso->IsoPacket[i].Length,0);
                                }
                            }
                        }
                    }
                }
            }		
            else
            {
                fail_counter++;
                if(fail_counter == 50)
                {

⌨️ 快捷键说明

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