Data Transfer across Memory Boundaries

This document describes how to read from and write to user-side memory from a kernel thread context or a user thread.

When a driver reads or writes data from or to a user-side program, the data must be copied between user address space and Kernel address space. The Kernel provides a number of APIs that allow this to be done safely. The API to use depends on whether the request is serviced in a user thread context, or in a Kernel thread context.

From kernel space

To read and write data to the user space from a kernel thread context, use Kernel APIs such as Kern::ThreadDesRead(), Kern::ThreadRawRead(), Kern::ThreadDesWrite(), and Kern::ThreadRawWrite(). The data can be handled as descriptors or as raw memory.

The Kernel also provides other APIs to safely read the information about a descriptor in another thread's address space. Kern::ThreadGetDesInfo() returns the length, maximum length, and a pointer to the descriptor's buffer. The length and maximum length can also be obtained specifically by using Kern::ThreadGetDesLength() and Kern::ThreadGetDesMaxLength().

TInt DExDriverLogicalChannel::DoControl(TInt aFunction, TAny* a1, TAny* /*a2*/)
    {
    ...
    // To read the buffer descriptors from user space
    r=Kern::ThreadDesRead(iClient,a1,iTxBuffer,0,0);
    ...
    // To write the buffer descriptors to user space
    r=Kern::ThreadDesWrite(iClient,(TDes8*)a1,iRxBuffer,0);
    ...
    }
// Read the descriptor maximum length from the user thread (iClient)  
// using the kernel API Kern::ThreadGetDesMaxLength(). This API 
// gets the maximum length of a descriptor in another thread's 
// address space. Kern::ThreadGetDesInfo() can also be used to 
// get length, maximum length and pointer to the descriptor's 
// buffer.
//
iCount=Kern::ThreadGetDesMaxLength(iClient,aData);

From user space

When executing a read or write operation in the context of a user thread, use the following APIs:

Kernel APIs are also available to do copy operations using descriptors:

Kern::InfoCopy() can be used to copy a descriptor safely in a way that enables forward and backward compatibility. It is typically used for copying capability packages.

void DExDriverLogicalDevice::GetCaps(TDes8& aCaps) const
    {
    // device capabilities are packaged to a buffer
    TPckgBuf<RExDriver::TUartCaps> caps;
    caps().iVersion=iVersion;
    // Copy the device capabilities to the user thread using the 
    // Kernel API
    Kern::InfoCopy(aCaps,caps);
    }