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?
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?
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);
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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;
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;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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].
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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?
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.
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);
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);
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;
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].
I understand anser on question (3).
Processing of SERIAL_XOFF_COUNTER consist of 2 stages