Using the BIL Interface

This tutorial describes how to use the Buffer Interface Layer (BIL) to read and write shared chunks form the client driver.

The BIL is a thin layer over the LDD APIs that removes the need for the class driver to handle buffers directly. The BIL is consistent between different class drivers and reduces the buffer related understanding needed to use the USBSc LDD.

Using the BIL is optional to the class driver, but very highly recommended.

Before completing these steps you must have followed the procedure from the beginning of the tutorial set through to RDevUsbcScClient::FinalizeInterface()

  1. Open each endpoint object. Use the function RDevUsbcScClient::OpenEndpoint() for each endpoint object.
    TEndpointBuffer iEpBuf;
    const TUint KWriteEp = 1;
    
    gPort.OpenEndpoint(iEpBuf, KWriteEp);
    OpenEndpoint() fills the provided endpoint buffer (iEpBuf) for use with the given endpoint number (KWriteEp). This endpoint will be opened on the current alternate interface setting.

  2. Reading with an OUT endpoint. To read with an endpoint call TEndpointBuffer::GetBuffer() to request data from the BIL.
    r = iEpBuf.GetBuffer(scReadData, readSize, readZlp, aStatus);
    The first parameter passed to GetBuffer() can be either a pointer to the transfer buffer or the offset of the transfer data within the shared chunk. This function allows the BIL to expire any previously retrieved transfer on this endpoint so that it can be used again for new transfers. If the transfer or the LDD are not ready then aStatus is set to pending. If no transfer is available then the variable passed in the first parameter is set to NULL or 0 depending on the API. Call this function again on completion, to wait for data again. The function GetBuffer() returns:

    1. KErrCompletion if data could be retrieved without a pending request,

    2. KErrNone if an asynchronous request was queued. This function should be called again on completion,

    3. KErrEof if the end of the data in the endpoint has been reached,

    4. KErrNotSupported if the endpoint is an IN endpoint.
    If the host has changed to an alternate setting and you wish to continue reading and writing data then you must Close() all endpoints and go to step five Process the next alternate set of endpoints. Otherwise, if you have finished then go to step four Close each endpoint object.

  3. Writing with an IN endpoint. After filling a shared chunk buffer with some data call TEndpointBuffer::WriteBuffer() to write the data to endpoint hardware. WriteBuffer() transmits the provided buffer on the given endpoint asynchronously. More than one request may be outstanding at any time. This reduces the time between buffer transfers.
    r = iEpBuf.WriteBuffer(buffer, length, ETrue, aStatus);
    The first parameter passed to WriteBuffer() can be either a pointer to the transfer buffer or the offset of the transfer data within the shared chunk. If the host has changed to an alternate setting and you wish to continue reading and writing data then you must Close() all endpoints and go to step five Process the next alternate set of endpoints. Otherwise, if you have finished then go to step four Close each endpoint object.

  4. Close each endpoint object. Each endpoint object opened with OpenEndpoint() must be closed with TEndpointBuffer::Close().
    iEpBuf.Close();
    If the host has changed to an alternate setting and you wish to continue reading and writing data then you must Close() all endpoints and go to step five Process the next alternate set of endpoints. Otherwise, if you have finished data transfer then Close and Unload the Driver. If you wish to continue reading and writing data but on an alternate setting then call RDevUsbcScClient::StartNextOutAlternateSetting(). Otherwise if you have finished then Close and Unload the Driver.

  5. Process the next alternate set of endpoints. Use the function RDevUsbcScClient::StartNextOutAlternateSetting() to switch to the next set of endpoints. The alternate interfaces were initialised with SetInterface(). See Set the Interface Descriptors.
    TInt r = StartNextOutAlternateSetting(ETrue);
    Pass ETrue to the function to purge the buffers of any data unread for the previous setting. Note: All open endpoints (except EP0) must be closed before this is called.

When you have finished reading and writing Close and Unload the Driver.