USB Libraries Help > USB Device Libraries > USB Device Layer Library > Library Interface > e) Endpoint Management Functions > USB_DEVICE_EndpointWrite Function
MPLAB Harmony USB Stack
USB_DEVICE_EndpointWrite Function

This function requests a data write to the USB Device Endpoint. The function places a requests with Device layer, the request will get serviced as and when the data is requested by the USB Host. A handle to the request is returned in the transferHandle parameter. The termination of the request is indicated by the USB_DEVICE_EVENT_ENDPOINT_WRITE_COMPLETE event. The amount of data written and the transfer handle associated with the request is returned along with the event in length member of the pData parameter in the event handler. The transfer handle expires when event handler for the USB_DEVICE_EVENT_ENDPOINT_WRITE_COMPLETE exits. If the write request could not be accepted, the function returns an error code and transferHandle will contain the value USB_DEVICE_TRANSFER_HANDLE_INVALID

The behavior of the write request depends on the flags and size parameter. If the application intends to send more data in a request, then it should use the USB_DEVICE_TRANSFER_FLAGS_MORE_DATA_PENDING flag. If there is no more data to be sent in the request, the application must use the USB_DEVICE_TRANSFER_FLAGS_DATA_COMPLETE flag. This is explained in more detail here: 

 

  • If size is a multiple of maxPacketSize and flag is set as

USB_DEVICE_TRANSFER_FLAGS_DATA_COMPLETE, the write function will append a Zero Length Packet (ZLP) to complete the transfer. 

 

  • If size is a multiple of maxPacketSize and flag is set as

USB_DEVICE_TRANSFER_FLAGS_MORE_DATA_PENDING, the write function will not append a ZLP and hence will not complete the transfer. 

 

  • If size is greater than but not a multiple of maxPacketSize and flags is

set as USB_DEVICE_TRANSFER_FLAGS_DATA_COMPLETE, the write function complete the transfer without appending a ZLP. 

 

  • If size is greater than but not a multiple of maxPacketSize and flags is

set as USB_DEVICE_TRANSFER_FLAGS_MORE_DATA_PENDING, the write function returns an error code and sets the transferHandle parameter to USB_DEVICE_TRANSFER_HANDLE_INVALID

 

  • If size is less than maxPacketSize and flag is set as

USB_DEVICE_TRANSFER_FLAGS_DATA_COMPLETE, the write function schedules one packet. 

 

  • If size is less than maxPacketSize and flag is set as

USB_DEVICE_TRANSFER_FLAGS_MORE_DATA_PENDING, the write function returns an error code and sets the transferHandle parameter to USB_DEVICE_TRANSFER_HANDLE_INVALID.

C
USB_DEVICE_RESULT USB_DEVICE_EndpointWrite(
    USB_DEVICE_HANDLE usbDeviceHandle, 
    USB_DEVICE_TRANSFER_HANDLE * transferHandle, 
    USB_ENDPOINT_ADDRESS endpoint, 
    const void * data, 
    size_t size, 
    USB_DEVICE_TRANSFER_FLAGS flags
);
Preconditions

The USB Device should be in a configured state.

Parameters
Parameters 
Description 
instance 
Handle to the device layer.
 
transferHandle 
Pointer to a USB_DEVICE_TRANSFER_HANDLE type of variable. This variable will contain the transfer handle in case the write request was successful.
 
endpoint 
Endpoint to which the data should be written. Note that is a combination of direction and the endpoint number. Refer to the description of USB_ENDPOINT_ADDRESS for more details.
 
data 
Pointer to the data buffer that contains the data to written.
 
size 
Size of the data buffer. Refer to the description section for more details on how the size affects the transfer.
 
flags 
Flags that indicate whether the transfer should continue or end. Refer to the description for more details. 
Returns

USB_DEVICE_RESULT_OK - The write request was successful. transferHandle contains a valid transfer handle. 

USB_DEVICE_RESULT_ERROR_TRANSFER_QUEUE_FULL - Internal request queue is full. The write request could not be added. 

USB_DEVICE_RESULT_ERROR_ENDPOINT_INVALID - Endpoint is not provisioned in the system. 

USB_DEVICE_RESULT_ERROR_TRANSFER_SIZE_INVALID - The combination of the transfer size and the specified flag is invalid. 

USB_DEVICE_RESULT_ERROR_ENDPOINT_NOT_CONFIGURED - Endpoint is not enabled because device is not configured. 

USB_DEVICE_RESULT_ERROR_PARAMETER_INVALID - Device Layer handle is not valid.

Remarks

While the using the device layer with PIC32MZ USB module, the transmit buffer provided to the USB_DEVICE_EndpointWrite should be placed in coherent memory and aligned at a 16 byte boundary. This can be done by declaring the buffer using the __attribute__((coherent, aligned(16))) attribute. An example is shown here 

 

uint8_t data[256] __attribute__((coherent, aligned(16)));
Example
// Below is a set of examples showing various conditions trying to
// send data with the Write command.  
//
// This assumes that Device Layer was opened successfully.
// Assume maxPacketSize is 64.

USB_DEVICE_TRANSFER_HANDLE transferHandle;
USB_DEVICE_RESULT writeRequestHandle;
USB_DEVICE_HANDLE usbDeviceHandle;

//-------------------------------------------------------
// In this example we want to send 34 bytes only.

writeRequestResult = USB_DEVICE_EndpointWrite(usbDeviceHandle,
                        &transferHandle, data, 34, 
                        USB_DEVICE_TRANSFER_FLAGS_DATA_COMPLETE);

if(USB_DEVICE_RESULT_OK != writeRequestResult)
{
    //Do Error handling here
}

//-------------------------------------------------------
// In this example we want to send 64 bytes only.
// This will cause a ZLP to be sent.

writeRequestResult = USB_DEVICE_EndpointWrite(usbDeviceHandle,
                        &transferHandle, data, 64, 
                        USB_DEVICE_TRANSFER_FLAGS_DATA_COMPLETE);

if(USB_DEVICE_RESULT_OK != writeRequestResult)
{
    //Do Error handling here
}

//-------------------------------------------------------
// This example will return an error because size is less
// than maxPacketSize and the flag indicates that more
// data is pending.

writeRequestResult = USB_DEVICE_EndpointWrite(usbDeviceHandle,
                        &transferHandle, data, 32, 
                        USB_DEVICE_TRANSFER_FLAGS_MORE_DATA_PENDING);

//-------------------------------------------------------
// In this example we want to place a request for a 70 byte transfer.
// The 70 bytes will be sent out in a 64 byte transaction and a 6 byte
// transaction completing the transfer.

writeRequestResult = USB_DEVICE_EndpointWrite(usbDeviceHandle,
                        &transferHandle, data, 70, 
                        USB_DEVICE_TRANSFER_FLAGS_DATA_COMPLETE);

if(USB_DEVICE_RESULT_OK != writeRequestResult)
{
    //Do Error handling here
}

//-------------------------------------------------------
// This example would result in an error because the transfer size is
// not an exact multiple of the endpoint size and the
// USB_DEVICE_TRANSFER_FLAGS_MORE_DATA_PENDING flag indicate that the
// transfer should continue.

writeRequestResult = USB_DEVICE_EndpointWrite(usbDeviceHandle,
                        &transferHandle, data, 70, 
                        USB_DEVICE_TRANSFER_FLAGS_MORE_DATA_PENDING);

if(USB_DEVICE_RESULT_OK != writeRequestResult)
{
    //Do Error handling here
}

// The completion of the write request will be indicated by the 
// USB_DEVICE_EVENT_ENDPOINT_WRITE_COMPLETE event.