Menu

TryReadWrite function

Help
2009-08-04
2013-05-20
  • Kirill Bagrinovsky

    Hello
    I read source code of com0com during 3 month. And I have some questions.

    1. I see startRead and firstRead flags in TryReadWrite function. Why you use it? firstRead = true when we take first Irp from queue and it not canceled. Is it fact significant for us?

    Why we can't write something like this:

    >> dataIrpRead.data.irp.pIrp = StartCurrentIrp(pQueueRead, &pCancelRoutineRead, &firstRead);

    instead of

    >>  if (startRead) {
    >>    dataIrpRead.data.irp.pIrp = pQueueRead->pCurrent;
    >>    pCancelRoutineRead = NULL;
    >>  } else {
    >>    dataIrpRead.data.irp.pIrp = StartCurrentIrp(pQueueRead, &pCancelRoutineRead, >>&firstRead);
    >>  }

    2. Why you use so complex scheme ( TX QUEUE -> TX FIFO -> TX shift register -> Rx shift register -> Rx Fifo -> Rx Buffer -> Rx Queue)? Why not just a Tx Queue -> Rx Queue?

     
    • Vyacheslav Frolov

      1. It's not a trivial task to describe.
      2. For more true emulation of real serial port. Old versions had just a Tx Queue -> Rx Queue.

       
    • Kirill Bagrinovsky

      Vyacheslav
      Can answer me on some questions about com0com source code

      1. Function ReadFromBuffers. In start of this function we call ReadFromBuffer and then ReadFromTxBuffer. Why we pass [&pReadIoPort->readBuf] parameter to ReadFromTxBuffer? I think that readBuf is already empty when we call ReadFromTxBuffer. Isn't it?

      2. Function FdoPortQueryInformation.

      if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(FILE_STANDARD_INFORMATION))
              {
                 // <<HERE>>
                 status = STATUS_BUFFER_TOO_SMALL;
                 break;
              }

      Should we add line pIrp->IoStatus.Information = 0 on label <<HERE>>?

      3. Function FdoPortStartIrp.

        if (pIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL && pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_WAIT_ON_MASK)
          status = NoPending(pIrp, STATUS_INVALID_PARAMETER);

      If understand this place right - here you handle situation when you receive second IOCTL_SERIAL_WAIT_ON_MASK request. And you complete this request with status STATUS_INVALID_PARAMETER.

      I read MSDN and find this:
      >> An IOCTL_SERIAL_SET_WAIT_MASK request is received while a
      >> wait-on-mask request is  pending. The driver completes the
      >> pending wait-on-mask request with a status of
      >> STATUS_SUCCESS and the output wait mask is set to zero.

      4. Function FdoPortStartIrp.

      if (pIrpStack->MajorFunction == IRP_MJ_FLUSH_BUFFERS)
        status = NoPending(pIrp, STATUS_SUCCESS);

      You try to complete Irp that placed in queue. Am i correct?

      5. Function TryReadWrite. I understand why you use flag start read. But why you set pCancelRoutineRead = NULL? Is it necessary?

        if (startRead)
        {
          dataIrpRead.data.irp.pIrp = pQueueRead->pCurrent;
          pCancelRoutineRead = NULL;
        }
        else
          dataIrpRead.data.irp.pIrp = StartCurrentIrp(pQueueRead, &pCancelRoutineRead, &firstRead);

       
    • Vyacheslav Frolov

      1. ReadFromTxBuffer do writing to readBuf.
      2. Possible it's a bug.
      3. MSDN: "A status of STATUS_INVALID_PARAMETER indicates that no wait events are set, or a wait-on-mask request is already pending."
      4. Possible it's a bug.
      5. It's for compiling:

           com0com\sys\io.c(1391) : error C2220: warning treated as error - no 'object' file generated
           com0com\sys\io.c(1391) : error C4701: local variable 'pCancelRoutineRead' may be used without having been initialized

         and for debuging:

           HALT_UNLESS(pCancelRoutine);

       
    • Kirill Bagrinovsky

      Hello, Vyacheslav
      Can you write some words on my questions to help me understand your code in IO.c file, fuction TryReadWrite, section [Move shifted data from TX QUEUE to RX QUEUE while RX QUEUE is not empty]?

      ===============================================
      if (dataIrpWrite.data.irp.status == STATUS_PENDING)
        break;

      if (dataIrpWrite.data.irp.status == STATUS_SUCCESS &&
          pIrpStackWrite->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
          pIrpStackWrite->Parameters.DeviceIoControl.IoControlCode == 
          IOCTL_SERIAL_XOFF_COUNTER)
      {
              if(startWrite && firstWrite)
                status = STATUS_PENDING;
              else
                StopCurrentIrp(STATUS_PENDING, firstWrite, doneWrite, pIoPortWrite, pQueueWrite, pQueueToComplete);

              if (dataIrpWrite.data.irp.pIrp == pQueueWrite->pCurrent)
              {
                if (doneWrite)
                  StartXoffCounter(pIoPortWrite, pQueueToComplete);

                if (dataIrpWrite.data.irp.pIrp == pQueueWrite->pCurrent)
                {
                  dataIrpWrite.data.irp.pIrp = NULL;
                  break;
                }
              }
      }
      ==========================================

      1. I analyse code and see that [dataIrpWrite.data.irp.status] can have only two values STATUS_PENDING and STATUS_SUCCESS. Why you check [dataIrpWrite.data.irp.status == STATUS_SUCCESS] following code?
      >> if (dataIrpWrite.data.irp.status == STATUS_PENDING)
      >>   break;

      2. In what conditions this IF be FALSE?
      >> if (dataIrpWrite.data.irp.pIrp == pQueueWrite->pCurrent)
      I think pCurrent element always equal to dataIrpWrite.data.irp.pIrp befor read this code.

      3. Why IOCTL_SERIAL_XOFF_COUNTER request get STATUS_PENDING status after following checking?
      >> if (dataIrpWrite.data.irp.status == STATUS_PENDING)
      >>   break;

       
    • Kirill Bagrinovsky

      And one little question

      Why you always check
      >> if (IrpReadStatus == STATUS_PENDING)
      in [Move shifted data from TX QUEUE to RX QUEUE while RX QUEUE is not empty] section?

      I think that IRPs with status [not STATUS_PENDING] don't enter in [while (IrpRead)] loop in section
      [Move shifted data from TX QUEUE to RX QUEUE while RX QUEUE is not empty].

       
    • Kirill Bagrinovsky

      I understand anser on question (3).
      Processing of SERIAL_XOFF_COUNTER  consist of 2 stages

       

Log in to post a comment.