Problem reading data from serial driver at kernel level

Hi,
I have a Kmdf driver that talks to the serial driver (using WDFTARGET mechanism). I have a timer object which expires every 1ms and sends a read request to the serial port driver. I am able to test this out as well and every 1ms i am getting periodic call-back after the request is completed and the status of the request is 0x00.

The problem is that the data that I get through the reads are garbage or to be more accurate are in Extended ASCII form (128- 256). I used winDBG to get to the bottom of this everything looks fine. The input buffer value i am getting is garbage on the request completion routine and this is the problem, but the size of the data received matches with the data that is sent by the transmitter.

Is this a problem with some symbols or I am using a serial to USB port converter on one end a serial port on the other, could this be resulting in getting garbage values as input? The baud rates r the same on the both ends, that i have verified.

Any pointers in this regard will be really helpful.

Regards,
Thor

Instead of using a timer object to send a read, why not always send a read and let the serial port driver give you the data back when it is ready?

What type of data are you expecting? Only ascii? otherwise 128-256 are valid values for a byte? Is it garbage only when you try to treat the buffer as something you want to print in the debugger?

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@rediffmail.com
Sent: Monday, January 07, 2008 10:18 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Problem reading data from serial driver at kernel level

Hi,
I have a Kmdf driver that talks to the serial driver (using WDFTARGET mechanism). I have a timer object which expires every 1ms and sends a read request to the serial port driver. I am able to test this out as well and every 1ms i am getting periodic call-back after the request is completed and the status of the request is 0x00.

The problem is that the data that I get through the reads are garbage or to be more accurate are in Extended ASCII form (128- 256). I used winDBG to get to the bottom of this everything looks fine. The input buffer value i am getting is garbage on the request completion routine and this is the problem, but the size of the data received matches with the data that is sent by the transmitter.

Is this a problem with some symbols or I am using a serial to USB port converter on one end a serial port on the other, could this be resulting in getting garbage values as input? The baud rates r the same on the both ends, that i have verified.

Any pointers in this regard will be really helpful.

Regards,
Thor


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hi Doron,
The external device is sending data at the rate of 1ms and that is y i have the timer object send request every 1ms. The data i am expecting is in ascii (like 0x01234567) but i am getting 0x7f7f7f7f7f in the memory location that is y the debug prints r printing garbage. But the size of the data is matching the data i am sending.

Well the same thing happens with the write mechanism as well. When i send a write request it is printing garbage on the other end, but when i print the buffer that was sent from the request completion routine, it is printing the correct data that i put into the buffer. So i am kind of confused and trying to figure out where is the disconnect.

Thanks.

xxxxx@rediffmail.com wrote:

The external device is sending data at the rate of 1ms and that is y i have the timer object send request every 1ms. The data i am expecting is in ascii (like 0x01234567)

That’s not ASCII.

but i am getting 0x7f7f7f7f7f in the memory location that is y the debug prints r printing garbage. But the size of the data is matching the data i am sending.

Remember that debug prints in WinDbg take a significant amount of time,
especially if you have a two-machine setup. You cannot do real time
processing at the submillisecond level if you are sending debug messages
externally.

Well the same thing happens with the write mechanism as well. When i send a write request it is printing garbage on the other end, but when i print the buffer that was sent from the request completion routine, it is printing the correct data that i put into the buffer. So i am kind of confused and trying to figure out where is the disconnect.

I doubt that we can help without some code samples.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

If you always have a read pending (or multiple reads pending at once), it reall doesn’t matter how often the other side is sending data, you will be notified of its arrival when it shows up. remember that by default the timer freq is 10ms (unless you change the timer resolution), so a 1ms period will not be realized.

Please post the code which formats the request and the completion routine which processes the data.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@rediffmail.com
Sent: Tuesday, January 08, 2008 9:48 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Problem reading data from serial driver at kernel level

Hi Doron,
The external device is sending data at the rate of 1ms and that is y i have the timer object send request every 1ms. The data i am expecting is in ascii (like 0x01234567) but i am getting 0x7f7f7f7f7f in the memory location that is y the debug prints r printing garbage. But the size of the data is matching the data i am sending.

Well the same thing happens with the write mechanism as well. When i send a write request it is printing garbage on the other end, but when i print the buffer that was sent from the request completion routine, it is printing the correct data that i put into the buffer. So i am kind of confused and trying to figure out where is the disconnect.

Thanks.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thanks Doron.
As of now i am sending that 0x12345 from hyperterminal and it sends the data in ASCII. Below is the code for the Timer create section:

NTSTATUS createTimerHandle(IN WDFDEVICE* pDevice)
{
NTSTATUS result=STATUS_SUCCESS;
WDF_OBJECT_ATTRIBUTES timerAttrib,targetAttrib;
WDF_TIMER_CONFIG timerConf;
PDEVICE_EXTENSION devExtension;
WDF_IO_TARGET_OPEN_PARAMS ioTargetParams;
DECLARE_CONST_UNICODE_STRING(serialPortName,SERIAL_PORT_NAME);

PAGED_CODE();
#ifdef DEBUG
KdPrint((“Creating IO Target and assoc Timer handle here!\n”));
#endif
devExtension = testDevGetData(*pDevice);

WDF_OBJECT_ATTRIBUTES_INIT(&targetAttrib);
result = WdfIoTargetCreate(*pDevice,
&targetAttrib,
&devExtension->ioTarget);
if (!NT_SUCCESS(result))
{
#ifdef DEBUG
KdPrint((“Error Creating the Target \n”));
#endif
return result;
}
WDF_IO_TARGET_OPEN_PARAMS_INIT_CREATE_BY_NAME( &ioTargetParams,
(PUNICODE_STRING)&serialPortName,
STANDARD_RIGHTS_ALL);
ioTargetParams.EvtIoTargetRemoveComplete = RemoteIoTargetClosed;

result = WdfIoTargetOpen(devExtension->ioTarget,&ioTargetParams);

if (!NT_SUCCESS(result))
{
#ifdef DEBUG
KdPrint((“Error Creating the Target \n”));
#endif
WdfIoTargetClose(devExtension->ioTarget);
return result;
}

WDF_TIMER_CONFIG_INIT_PERIODIC( &timerConf,
wakeUpFunctionCb,
PERIODIC_TIMER_VALUE);

WDF_OBJECT_ATTRIBUTES_INIT(&timerAttrib);
timerAttrib.ParentObject = devExtension->ioTarget;

result = WdfTimerCreate(
&timerConf,
&timerAttrib,
&devExtension->timerHandle);

if (!NT_SUCCESS(result))
{
#ifdef DEBUG
KdPrint((“Error Creating Time obj.Exit Now!0x%x\n”,result));
#endif
WdfObjectDelete(devExtension->ioTarget);
return result;
}

WdfTimerStart(devExtension->timerHandle,WDF_REL_TIMEOUT_IN_SEC(5));
}

The WakeupfunctionCb is called upon expiration of the timer and as of now the timer is set at 5 seconds instead of 1ms, but that i will test when the seconds metric is seen to work correctly.

VOID wakeUpFunctionCb(IN WDFTIMER Timer)
{

PDEVICE_EXTENSION devExtension;
WDFIOTARGET ioTargetDev;
WDFDEVICE device;

ioTargetDev = WdfTimerGetParentObject(Timer);
device = WdfIoTargetGetDevice(ioTargetDev);

devExtension = testDevGetData(device);

if (devExtension->size == 0)
{
WdfTimerStop(Timer,FALSE);
WdfObjectDelete(devExtension->ioTarget);
}
else
{
createReadReq(devExtension);
}
}

CreateReadReq: creates a request for read

NTSTATUS
createReadReq(PVOID inContext)
{
NTSTATUS result = STATUS_SUCCESS;
PDEVICE_EXTENSION context;
WDF_OBJECT_ATTRIBUTES reqAttrib,memAttrib;
int i=0;

// This initializes the custom context required for the device
context = (PDEVICE_EXTENSION)inContext;

WDF_OBJECT_ATTRIBUTES_INIT(&reqAttrib);
reqAttrib.ParentObject = context->ioTarget;

result = WdfRequestCreate(&reqAttrib,context->ioTarget,&context->readRequest);

WDF_OBJECT_ATTRIBUTES_INIT(&memAttrib);
memAttrib.ParentObject = context->readRequest;

result = WdfMemoryCreate(&memAttrib,
NonPagedPool,
‘daer’,
sizeof(readBuffer),
&context->readReqMem,
NULL);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Creating Memory for READ\n”));
return result;
}
result = WdfIoTargetFormatRequestForRead(context->ioTarget,
context->readRequest,
context->readReqMem,
NULL,
NULL);

if (!NT_SUCCESS(result))
{
KdPrint((“Error Formating READ Request\n”));
return result;
}
WdfRequestSetCompletionRoutine(context->readRequest,
&RemoteIoTargetRead,
inContext);

if ( WdfRequestSend(context->readRequest,
context->ioTarget,
WDF_NO_SEND_OPTIONS) == FALSE) {
result = WdfRequestGetStatus(context->readRequest);
KdPrint((“Error Sending Write Request 0x%x\n”,result));
return result;
}
return result;
}

As of now i just have debug prints in the code for the Call-back function upon Read Request complete, but it is given below.

VOID RemoteIoTargetRead(IN WDFREQUEST Request,
IN WDFIOTARGET Target,
IN PWDF_REQUEST_COMPLETION_PARAMS Params,
IN WDFCONTEXT Context)
{
PVOID buff=NULL;
PDEVICE_EXTENSION cbStruct = (PDEVICE_EXTENSION)Context;

DbgBreakPoint();
if (Target == cbStruct->ioTarget)
{
KdPrint((“From COM PORT obviously \n”));
}
buff = WdfMemoryGetBuffer(Params->Parameters.Read.Buffer,NULL);

KdPrint((“The type of Call-back is 0x%x \n”,Params->Type));
KdPrint((“The data obtained is %s \n”,buff));
KdPrint((“The Length of data is %d \n”,Params->Parameters.Read.Length));
KdPrint((“The status of the request is 0x%x \n”,Params->IoStatus.Information));

}

I guess now you geVOID RemoteIoTargetRead(IN WDFREQUEST Request,
IN WDFIOTARGET Target,
IN PWDF_REQUEST_COMPLETION_PARAMS Params,
IN WDFCONTEXT Context)
{
PVOID buff=NULL;
PDEVICE_EXTENSION cbStruct = (PDEVICE_EXTENSION)Context;

DbgBreakPoint();
if (Target == cbStruct->ioTarget)
{
KdPrint((“From COM PORT obviously \n”));
}
buff = WdfMemoryGetBuffer(Params->Parameters.Read.Buffer,NULL);

KdPrint((“The type of Call-back is 0x%x \n”,Params->Type));
KdPrint((“The data obtained is %s \n”,buff));
KdPrint((“The Length of data is %d \n”,Params->Parameters.Read.Length));
KdPrint((“The status of the request is 0x%x \n”,Params->IoStatus.Information));

}
I hope that you can get an idea on the what i am trying to do now and hopefully shoVOID RemoteIoTargetRead(IN WDFREQUEST Request,
IN WDFIOTARGET Target,
IN PWDF_REQUEST_COMPLETION_PARAMS Params,
IN WDFCONTEXT Context)
{
PVOID buff=NULL;
PDEVICE_EXTENSION cbStruct = (PDEVICE_EXTENSION)Context;

DbgBreakPoint();
if (Target == cbStruct->ioTarget)
{
KdPrint((“From COM PORT obviously \n”));
}
buff = WdfMemoryGetBuffer(Params->Parameters.Read.Buffer,NULL);

KdPrint((“The type of Call-back is 0x%x \n”,Params->Type));
KdPrint((“The data obtained is %s \n”,buff));
KdPrint((“The Length of data is %d \n”,Params->Parameters.Read.Length));
KdPrint((“The status of the request is 0x%x \n”,Params->IoStatus.Information));

}
I hope that the code gives a better idea on what i am trying to achieve and make things clearer?

thanks again.
Thor

I have posted Code samples here on previous reply. I have tried debugging, but i still am not able to get any meaningful data from the serial driver. Any pointers on what could be the problem?

Thanks for your inputs.

Reg,
Thor

Muer Thor wrote:

I have posted Code samples here on previous reply. I have tried
debugging, but i still am not able to get any meaningful data from
the serial driver. Any pointers on what could be the problem?

Stop using timers to read from the serial driver like Doron said. Just issue reads to it continuously, the serial driver will complete them when any data comes (1ms or not).

hi Chris,
I understand that, but I will have to read periodically and not just once. So instead of timer object, i tried creating a kernel thread and that sends read requests every 10 seconds or so. But I am still having the same problem, that the data is corrupt. It will be helpful if i can figure out why there is this weirdness and could this be due to repeated reads using timer?? It cannot be as i tried it through the kernel thread and i am getting the same output?

You are not understanding what I am suggesting you do. Instead of dedicating a timer or a thread to do the read, you just always have a read request pending. That means that you send it once when you start reading (right after you open and configure the com port) and then in the read request’s completion routine, you reformat the request and resend it. This way you do not use a timer, you do not burn a thread and you are not sending it every x ms, rather you are always reading from the com port and the serial driver will complete the request when the data arrives.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@rediffmail.com
Sent: Wednesday, January 09, 2008 2:34 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Problem reading data from serial driver at kernel level

hi Chris,
I understand that, but I will have to read periodically and not just once. So instead of timer object, i tried creating a kernel thread and that sends read requests every 10 seconds or so. But I am still having the same problem, that the data is corrupt. It will be helpful if i can figure out why there is this weirdness and could this be due to repeated reads using timer?? It cannot be as i tried it through the kernel thread and i am getting the same output?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thanks Doron.
It is clear now, I will reuse the request from the Completion routine. I will try this out and hopefully this should change outcome. I will get back to you on this one and confirm if this works out or not.

Reg,
Thor

Hi,
I had made the indicated modifications. I am now allocating memory from preallocated pool and then reusing the request in the call-back functions. There is one improvement that the Write to the serial port works correctly. But the Read from the serial port is still returning me garbage data. I am attaching the code below.

This function creates request related stuff and also allocates memory.
NTSTATUS createMemHandle(IN WDFDEVICE* pDevice)
{
NTSTATUS result=STATUS_SUCCESS;
PDEVICE_EXTENSION devExtension;
WDF_OBJECT_ATTRIBUTES reqAttrib,memAttrib;
WDF_REQUEST_SEND_OPTIONS sendOptions;
int i=0;

PAGED_CODE();
devExtension = testDevGetData(*pDevice);
devExtension->pReadBuff = NULL;
devExtension->pWriteBuff = NULL;

//#ifdef SEND_READ_REQ

WDF_OBJECT_ATTRIBUTES_INIT(&reqAttrib);
reqAttrib.ParentObject = devExtension->ioTarget;

result = WdfRequestCreate(&reqAttrib,devExtension->ioTarget,&devExtension->readRequest);

devExtension->pReadBuff = ExAllocatePoolWithTag(NonPagedPool,
sizeof(readBuffer),
‘0meM’);

if (devExtension->pReadBuff == NULL)
{
KdPrint((“Error Creating Memory for Read from ExAlloc\n”));
return result;
}

WDF_OBJECT_ATTRIBUTES_INIT(&memAttrib);
memAttrib.ParentObject = devExtension->readRequest;

result = WdfMemoryCreatePreallocated( &memAttrib,
devExtension->pReadBuff,
sizeof(readBuffer),
&devExtension->readReqMem);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Creating Memory for Read 0x%x\n”,result));
return result;
}

result = WdfIoTargetFormatRequestForRead(devExtension->ioTarget,
devExtension->readRequest,
devExtension->readReqMem,
NULL,
NULL);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Formating Read Request 0x%x\n”,result));
return result;
}

WdfRequestSetCompletionRoutine(devExtension->readRequest,
&RemoteIoTargetRead,
devExtension);

if ( WdfRequestSend(devExtension->readRequest,
devExtension->ioTarget,
WDF_NO_SEND_OPTIONS) == FALSE) {
result = WdfRequestGetStatus(devExtension->readRequest);
KdPrint((“Error Sending Read Request 0x%x\n”,result));
return result;
}
KdPrint((“Sent Read Request\n”));
return result;
//#endif

#ifdef SEND_WRITE_REQ

WDF_OBJECT_ATTRIBUTES_INIT(&reqAttrib);
reqAttrib.ParentObject = devExtension->ioTarget;

result = WdfRequestCreate(&reqAttrib,devExtension->ioTarget,&devExtension->writeRequest);

devExtension->pWriteBuff = ExAllocatePoolWithTag(NonPagedPool,
sizeof(writeBuffer),
‘1meM’);

if (devExtension->pWriteBuff == NULL)
{
KdPrint((“Error Creating Memory for Write from ExAlloc\n”));
return result;
}

WDF_OBJECT_ATTRIBUTES_INIT(&memAttrib);
memAttrib.ParentObject = devExtension->writeRequest;

result = WdfMemoryCreatePreallocated( &memAttrib,
devExtension->pWriteBuff,
sizeof(writeBuffer),
&devExtension->writeReqMem);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Creating Memory for Write 0x%x\n”,result));
return result;
}
result = RtlStringCchCopyA(devExtension->pWriteBuff,18,“This is Test Data”);
if (!NT_SUCCESS(result))
{
KdPrint((“Error copying string into the buffer\n”));
return result;
}
KdPrint((“The string in buffer is %s \n”,devExtension->pWriteBuff));
result = WdfIoTargetFormatRequestForWrite(devExtension->ioTarget,
devExtension->writeRequest,
devExtension->writeReqMem,
NULL,
NULL);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Formating Write Request 0x%x\n”,result));
return result;
}

WdfRequestSetCompletionRoutine(devExtension->writeRequest,
&RemoteIoTargetWrite,
devExtension);

if ( WdfRequestSend(devExtension->writeRequest,
devExtension->ioTarget,
WDF_NO_SEND_OPTIONS) == FALSE) {
result = WdfRequestGetStatus(devExtension->writeRequest);
KdPrint((“Error Sending Write Request 0x%x\n”,result));
return result;
}
KdPrint((“Sent Write Request\n”));
return result;
#endif
}

As per the above code, the Write request produces correct output at the other end.

This is the call-back function that is getting invoked everytime the Serial port has enough data.
There is also an another issue that the Serial driver is calling this function not when it reaches the size of the buffer I allocate. For ex: in this case, i have the size of readBuffer as 25 characters and the Serial driver calls this call-back when it receives 32 characters.

VOID RemoteIoTargetRead(IN WDFREQUEST Request,
IN WDFIOTARGET Target,
IN PWDF_REQUEST_COMPLETION_PARAMS Params,
IN WDFCONTEXT Context)
{
NTSTATUS result = STATUS_SUCCESS;
PVOID buff=NULL;
PDEVICE_EXTENSION devExtension = (PDEVICE_EXTENSION)Context;
WDFMEMORY outMemory = NULL;
WDF_REQUEST_REUSE_PARAMS reuseParam;

#ifdef DEBUG
DbgBreakPoint();
#endif
if (Target != devExtension->ioTarget)
{
KdPrint((“NOT From COM PORT going to end\n”));
goto end;
}

buff = WdfMemoryGetBuffer(Params->Parameters.Read.Buffer,NULL);

if (buff != NULL)
{
KdPrint((“The data obtained is %s \n”,buff));
KdPrint((“The Length of data is %d \n”,Params->Parameters.Read.Length));
}
if (!NT_SUCCESS(Params->IoStatus.Status))
{
KdPrint((“The status of the request is 0x%x \n”,Params->IoStatus.Information));
}

WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParam,
WDF_REQUEST_REUSE_NO_FLAGS,
STATUS_SUCCESS);

result = WdfRequestReuse(Request,&reuseParam);
if (!NT_SUCCESS(result))
{
KdPrint((“Request REUSE failure 0x%x \n”,result));
}

result = WdfMemoryAssignBuffer( devExtension->readReqMem,
devExtension->pReadBuff,
sizeof(readBuffer));

if (!NT_SUCCESS(result))
{
KdPrint((“Assign Buffer failure 0x%x \n”,result));
}
result = WdfIoTargetFormatRequestForRead( Target,
Request,
devExtension->readReqMem,
NULL,
NULL);
if (!NT_SUCCESS(result))
{
KdPrint((“Request FORMAT failure 0x%x \n”,result));
}

WdfRequestSetCompletionRoutine(Request,
RemoteIoTargetRead,
devExtension);

if ( WdfRequestSend(Request,
Target,
WDF_NO_SEND_OPTIONS) == FALSE)
{
result = WdfRequestGetStatus(Request);
KdPrint((“Error Sending Write Request 0x%x\n”,result));
}
end:
KdPrint((“Read Request complete\n”));
}

It will be helpful if i could get any assistance in this regard…!

reg,
Thor

3 things that stand out to me w/out diving deep

  1. do not pass WDFDEVICE*, you can just pass the WDFDEVICE by value
  2. You do not need to allocate the pool and then create a WDFMEMORY to wrap it. Just create the WDFMEMORY via WdfMemoryCreate and specify the size
  3. You do not need to reassign the buffer to the WDFMEMORY in your read completion routine

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@rediffmail.com
Sent: Friday, January 11, 2008 1:25 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Problem reading data from serial driver at kernel level

Hi,
I had made the indicated modifications. I am now allocating memory from preallocated pool and then reusing the request in the call-back functions. There is one improvement that the Write to the serial port works correctly. But the Read from the serial port is still returning me garbage data. I am attaching the code below.

This function creates request related stuff and also allocates memory.
NTSTATUS createMemHandle(IN WDFDEVICE* pDevice)
{
NTSTATUS result=STATUS_SUCCESS;
PDEVICE_EXTENSION devExtension;
WDF_OBJECT_ATTRIBUTES reqAttrib,memAttrib;
WDF_REQUEST_SEND_OPTIONS sendOptions;
int i=0;

PAGED_CODE();
devExtension = testDevGetData(*pDevice);
devExtension->pReadBuff = NULL;
devExtension->pWriteBuff = NULL;

//#ifdef SEND_READ_REQ

WDF_OBJECT_ATTRIBUTES_INIT(&reqAttrib);
reqAttrib.ParentObject = devExtension->ioTarget;

result = WdfRequestCreate(&reqAttrib,devExtension->ioTarget,&devExtension->readRequest);

devExtension->pReadBuff = ExAllocatePoolWithTag(NonPagedPool,
sizeof(readBuffer),
‘0meM’);

if (devExtension->pReadBuff == NULL)
{
KdPrint((“Error Creating Memory for Read from ExAlloc\n”));
return result;
}

WDF_OBJECT_ATTRIBUTES_INIT(&memAttrib);
memAttrib.ParentObject = devExtension->readRequest;

result = WdfMemoryCreatePreallocated( &memAttrib,
devExtension->pReadBuff,
sizeof(readBuffer),
&devExtension->readReqMem);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Creating Memory for Read 0x%x\n”,result));
return result;
}

result = WdfIoTargetFormatRequestForRead(devExtension->ioTarget,
devExtension->readRequest,
devExtension->readReqMem,
NULL,
NULL);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Formating Read Request 0x%x\n”,result));
return result;
}

WdfRequestSetCompletionRoutine(devExtension->readRequest,
&RemoteIoTargetRead,
devExtension);

if ( WdfRequestSend(devExtension->readRequest,
devExtension->ioTarget,
WDF_NO_SEND_OPTIONS) == FALSE) {
result = WdfRequestGetStatus(devExtension->readRequest);
KdPrint((“Error Sending Read Request 0x%x\n”,result));
return result;
}
KdPrint((“Sent Read Request\n”));
return result;
//#endif

#ifdef SEND_WRITE_REQ

WDF_OBJECT_ATTRIBUTES_INIT(&reqAttrib);
reqAttrib.ParentObject = devExtension->ioTarget;

result = WdfRequestCreate(&reqAttrib,devExtension->ioTarget,&devExtension->writeRequest);

devExtension->pWriteBuff = ExAllocatePoolWithTag(NonPagedPool,
sizeof(writeBuffer),
‘1meM’);

if (devExtension->pWriteBuff == NULL)
{
KdPrint((“Error Creating Memory for Write from ExAlloc\n”));
return result;
}

WDF_OBJECT_ATTRIBUTES_INIT(&memAttrib);
memAttrib.ParentObject = devExtension->writeRequest;

result = WdfMemoryCreatePreallocated( &memAttrib,
devExtension->pWriteBuff,
sizeof(writeBuffer),
&devExtension->writeReqMem);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Creating Memory for Write 0x%x\n”,result));
return result;
}
result = RtlStringCchCopyA(devExtension->pWriteBuff,18,“This is Test Data”);
if (!NT_SUCCESS(result))
{
KdPrint((“Error copying string into the buffer\n”));
return result;
}
KdPrint((“The string in buffer is %s \n”,devExtension->pWriteBuff));
result = WdfIoTargetFormatRequestForWrite(devExtension->ioTarget,
devExtension->writeRequest,
devExtension->writeReqMem,
NULL,
NULL);
if (!NT_SUCCESS(result))
{
KdPrint((“Error Formating Write Request 0x%x\n”,result));
return result;
}

WdfRequestSetCompletionRoutine(devExtension->writeRequest,
&RemoteIoTargetWrite,
devExtension);

if ( WdfRequestSend(devExtension->writeRequest,
devExtension->ioTarget,
WDF_NO_SEND_OPTIONS) == FALSE) {
result = WdfRequestGetStatus(devExtension->writeRequest);
KdPrint((“Error Sending Write Request 0x%x\n”,result));
return result;
}
KdPrint((“Sent Write Request\n”));
return result;
#endif
}

As per the above code, the Write request produces correct output at the other end.

This is the call-back function that is getting invoked everytime the Serial port has enough data.
There is also an another issue that the Serial driver is calling this function not when it reaches the size of the buffer I allocate. For ex: in this case, i have the size of readBuffer as 25 characters and the Serial driver calls this call-back when it receives 32 characters.

VOID RemoteIoTargetRead(IN WDFREQUEST Request,
IN WDFIOTARGET Target,
IN PWDF_REQUEST_COMPLETION_PARAMS Params,
IN WDFCONTEXT Context)
{
NTSTATUS result = STATUS_SUCCESS;
PVOID buff=NULL;
PDEVICE_EXTENSION devExtension = (PDEVICE_EXTENSION)Context;
WDFMEMORY outMemory = NULL;
WDF_REQUEST_REUSE_PARAMS reuseParam;

#ifdef DEBUG
DbgBreakPoint();
#endif
if (Target != devExtension->ioTarget)
{
KdPrint((“NOT From COM PORT going to end\n”));
goto end;
}

buff = WdfMemoryGetBuffer(Params->Parameters.Read.Buffer,NULL);

if (buff != NULL)
{
KdPrint((“The data obtained is %s \n”,buff));
KdPrint((“The Length of data is %d \n”,Params->Parameters.Read.Length));
}
if (!NT_SUCCESS(Params->IoStatus.Status))
{
KdPrint((“The status of the request is 0x%x \n”,Params->IoStatus.Information));
}

WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParam,
WDF_REQUEST_REUSE_NO_FLAGS,
STATUS_SUCCESS);

result = WdfRequestReuse(Request,&reuseParam);
if (!NT_SUCCESS(result))
{
KdPrint((“Request REUSE failure 0x%x \n”,result));
}

result = WdfMemoryAssignBuffer( devExtension->readReqMem,
devExtension->pReadBuff,
sizeof(readBuffer));

if (!NT_SUCCESS(result))
{
KdPrint((“Assign Buffer failure 0x%x \n”,result));
}
result = WdfIoTargetFormatRequestForRead( Target,
Request,
devExtension->readReqMem,
NULL,
NULL);
if (!NT_SUCCESS(result))
{
KdPrint((“Request FORMAT failure 0x%x \n”,result));
}

WdfRequestSetCompletionRoutine(Request,
RemoteIoTargetRead,
devExtension);

if ( WdfRequestSend(Request,
Target,
WDF_NO_SEND_OPTIONS) == FALSE)
{
result = WdfRequestGetStatus(Request);
KdPrint((“Error Sending Write Request 0x%x\n”,result));
}
end:
KdPrint((“Read Request complete\n”));
}

It will be helpful if i could get any assistance in this regard…!

reg,
Thor


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hi Doron,
Thanks for the reply.
I am making the modifications as you had suggested. My question is reassigning the buffer is causing the output the data as shown?

I am getting data that is like the one shown below from the debugger output:
00000064 304.50735474 The type of Call-back is 0x3
00000065 304.50741577 The data obtained is  
00000066 304.50741577 The Length of data is 25
00000067 304.50750732 Sent Read Request
00000068 304.50750732 Read Request complete

Thanks,
Thor.

Hi
I have made the modifications and tested it out. I am getting the call-back exactly when the character size of 25 (my buffer size) is reached. But the data i am getting is garbage. This is my last hurdle if i get through this i am home free (i guess!).

Any idea on what could be the cause on the data not being stored properly?

Thanks,
Thor

If I had to throw out a guess, I’d guess that you were trying to read
the data at the wrong baud rate, or parity, or whatever.

Serial ports are pretty reliable (as is the serial driver) when
configured properly.

xxxxx@rediffmail.com wrote:

Hi
I have made the modifications and tested it out. I am getting the call-back exactly when the character size of 25 (my buffer size) is reached. But the data i am getting is garbage. This is my last hurdle if i get through this i am home free (i guess!).

Any idea on what could be the cause on the data not being stored properly?

Thanks,
Thor


Ray
(If you want to reply to me off list, please remove “spamblock.” from my
email address)

Hi Ray,
Thanks for ur reply.
I had checked the communication mechanisms. But the Write call succeeds and this could be possible only when the baud rate and the parity rates are correct. i stepped through using debugger and the memory location pointed to by the buffer has 7F7F in its location and that is what is being displayed on the screen.

I am not sure on this.

Reg,
Thor

Can you show again how you are dumping your data so that you can determine it is garbage? Are you dumping it byte by byte?

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@rediffmail.com
Sent: Friday, January 11, 2008 3:22 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Problem reading data from serial driver at kernel level

Hi
I have made the modifications and tested it out. I am getting the call-back exactly when the character size of 25 (my buffer size) is reached. But the data i am getting is garbage. This is my last hurdle if i get through this i am home free (i guess!).

Any idea on what could be the cause on the data not being stored properly?

Thanks,
Thor


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

xxxxx@rediffmail.com wrote:


This is the call-back function that is getting invoked everytime the Serial port has enough data.
There is also an another issue that the Serial driver is calling this function not when it reaches the size of the buffer I allocate. For ex: in this case, i have the size of readBuffer as 25 characters and the Serial driver calls this call-back when it receives 32 characters.

buff = WdfMemoryGetBuffer(Params->Parameters.Read.Buffer,NULL);

if (buff != NULL)
{
KdPrint((“The data obtained is %s \n”,buff));
KdPrint((“The Length of data is %d \n”,Params->Parameters.Read.Length));
}

I believe you will find that Params->Parameters.Read.Length contains the
size of your buffer, NOT the amount of data actually returned. The
amount of data actually read is in Params->IoStatus.Information.

if (!NT_SUCCESS(Params->IoStatus.Status))
{
KdPrint((“The status of the request is 0x%x \n”,Params->IoStatus.Information));
}

I assume you really wanted to print IoStatus.Status here, not
IoStatus.Information.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Please show the debugger logs which show that the pointer is the one in the irp (!wdfmemory [WDFMEMORY] will tell you what the pointer is for the WDFMEMORY used to format the read) and how you dumped it

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@rediffmail.com
Sent: Friday, January 11, 2008 3:57 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Problem reading data from serial driver at kernel level

Hi Ray,
Thanks for ur reply.
I had checked the communication mechanisms. But the Write call succeeds and this could be possible only when the baud rate and the parity rates are correct. i stepped through using debugger and the memory location pointed to by the buffer has 7F7F in its location and that is what is being displayed on the screen.

I am not sure on this.

Reg,
Thor


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer