Ejemplo n.º 1
0
DRV_USART_BAUD_SET_RESULT DRV_USART_BaudSet(DRV_HANDLE handle, uint32_t baud)
{
    DRV_USART_OBJ * hDriver;
    DRV_USART_CLIENT_OBJ * client;
    USART_MODULE_ID plibID;

    /* Validate the handle */
    client = _DRV_USART_DriverHandleValidate(handle);

    if(client == NULL)
    {
        /* Driver handle is not valid. Return error */
        SYS_DEBUG(0, "Invalid client handle");
        return DRV_USART_BAUD_SET_ERROR;
    }

    hDriver = (DRV_USART_OBJ*)client->hDriver;
    plibID = hDriver->moduleId;

    if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
    {
        /* Set the baud rate */
        PLIB_USART_BaudRateSet(plibID, hDriver->brgClock, baud);
    }
    else
    {
        /* The mutex timed out */
        SYS_DEBUG(0, "Hardware instance mutex time out in DRV_USART_BaudSet() function");
        return(DRV_USART_BAUD_SET_ERROR);
    }

    /* Return success */
    return(DRV_USART_BAUD_SET_SUCCESS);
}
Ejemplo n.º 2
0
void NET_PRES_SKT_Close(NET_PRES_SKT_HANDLE_T handle, NET_PRES_SKT_ERROR_T* error)
{
    if (handle <= 0 || handle > NET_PRES_NUM_SOCKETS)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_INVALID_SOCKET;
        }
        return;
    }
    handle--;
    if (!sNetPresSockets[handle].inUse)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_INVALID_SOCKET;
        }
        return;
    }
    
    if ((sNetPresSockets[handle].socketType & NET_PRES_SKT_ENCRYPTED) == NET_PRES_SKT_ENCRYPTED)
    {
        NET_PRES_EncProviderConnectionClose fp = sNetPresSockets[handle].provObject->fpClose;
        if (fp != NULL)
        {
            (*fp)(sNetPresSockets[handle].providerData);
        }
    }
    NET_PRES_TransClose fpc = sNetPresSockets[handle].transObject->fpClose;
    if (fpc == NULL)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_OP_NOT_SUPPORTED;
        }
        return;
    }
    (*fpc)(sNetPresSockets[handle].transHandle);
    if (OSAL_MUTEX_Lock(&sNetPresData.presMutex, OSAL_WAIT_FOREVER) != OSAL_RESULT_TRUE)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_UNKNOWN_ERROR;
        }
        return;
    }
    memset(&sNetPresSockets[handle], 0, sizeof(NET_PRES_SocketData));
    if (OSAL_MUTEX_Unlock(&sNetPresData.presMutex) != OSAL_RESULT_TRUE)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_UNKNOWN_ERROR;
        }
        return;
    }
    if (error != NULL)
    {
        *error = NET_PRES_SKT_OK;
    } 
}
Ejemplo n.º 3
0
void NET_PRES_Tasks(SYS_MODULE_OBJ obj)
{
    uint8_t x;
    for (x = 0; x < NET_PRES_NUM_SOCKETS; x++)
    {
        if (sNetPresSockets[x].inUse && ((sNetPresSockets[x].socketType & NET_PRES_SKT_ENCRYPTED) == NET_PRES_SKT_ENCRYPTED))
        {
            // Check the state of the socket and then pump it if necessary.
            switch (sNetPresSockets[x].status)
            {
                case NET_PRES_ENC_SS_WAITING_TO_START_NEGOTIATION:
                {
                    // First thing is to check if the connection is connected.
                    if (!sNetPresSockets[x].transObject->fpIsConnected(sNetPresSockets[x].transHandle))
                    {
                        break;
                    }
                    // Next check to see if the provider has been initialized
                    if (OSAL_MUTEX_Lock(&sNetPresData.presMutex, OSAL_WAIT_FOREVER) != OSAL_RESULT_TRUE)
                    {
                        continue;
                    }
                    if (!(*sNetPresSockets[x].provObject->fpIsInited)())
                    {
                        if (!(*sNetPresSockets[x].provObject->fpInit)(sNetPresSockets[x].transObject))
                        {
                            sNetPresSockets[x].status = NET_PRES_ENC_SS_FAILED;
                            if (OSAL_MUTEX_Unlock(&sNetPresData.presMutex) != OSAL_RESULT_TRUE)
                            {
                                continue;
                            }
                            continue;
                        }
                    }
                    if (OSAL_MUTEX_Unlock(&sNetPresData.presMutex) != OSAL_RESULT_TRUE)
                    {
                        continue;
                    }
                    if (!(*sNetPresSockets[x].provObject->fpOpen)(sNetPresSockets[x].transHandle, &sNetPresSockets[x].providerData))
                    {
                        sNetPresSockets[x].status = NET_PRES_ENC_SS_FAILED;
                        continue;                       
                    }
                    //Intentional fall through to the next state
                }
                case NET_PRES_ENC_SS_CLIENT_NEGOTIATING:
                case NET_PRES_ENC_SS_SERVER_NEGOTIATING:
                    sNetPresSockets[x].status = (*sNetPresSockets[x].provObject->fpConnect)(sNetPresSockets[x].providerData);
                    break;
                default:
                    break;
            }
        }
    }
}
Ejemplo n.º 4
0
DRV_USART_LINE_CONTROL_SET_RESULT DRV_USART_LineControlSet
(
    DRV_HANDLE handle,
    DRV_USART_LINE_CONTROL lineControlMode
)
{
    DRV_USART_OBJ * hDriver;
    DRV_USART_CLIENT_OBJ * client;
    USART_MODULE_ID plibID;

    /* Validate the driver handle */
    client = _DRV_USART_DriverHandleValidate(handle);

    if(client == NULL)
    {
        /* Driver handle is not valid. Return error */

        SYS_DEBUG(0, "Invalid driver handle");
        return DRV_USART_LINE_CONTROL_SET_ERROR;
    }

    hDriver = (DRV_USART_OBJ*)client->hDriver;
    plibID = hDriver->moduleId;

    if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
    {
        /* Set the Line Control Mode */
        PLIB_USART_LineControlModeSelect(plibID, lineControlMode);
    }
    else
    {
        SYS_DEBUG(0, "Hardware Instance Mutex time out in DRV_USART_LineControlSet() function");
        return DRV_USART_LINE_CONTROL_SET_ERROR;
    }

    /* Return success */
    return(DRV_USART_LINE_CONTROL_SET_SUCCESS);
}
Ejemplo n.º 5
0
USB_DEVICE_CDC_RESULT USB_DEVICE_CDC_SerialStateNotificationSend 
(
    USB_DEVICE_CDC_INDEX iCDC ,
    USB_DEVICE_CDC_TRANSFER_HANDLE * transferHandle ,
    USB_CDC_SERIAL_STATE * notificationData 
)
{
    unsigned int cnt;
    USB_DEVICE_IRP * irp;
    USB_DEVICE_CDC_ENDPOINT * endpoint;
    USB_DEVICE_CDC_INSTANCE * thisCDCDevice;
    OSAL_RESULT osalError;
    USB_ERROR irpError;
    OSAL_CRITSECT_DATA_TYPE IntState;

    *transferHandle = USB_DEVICE_CDC_TRANSFER_HANDLE_INVALID;

    /* Check the validity of the function driver index */
    
    if (  iCDC >= USB_DEVICE_CDC_INSTANCES_NUMBER  )
    {
        /* Invalid CDC index */
        SYS_ASSERT(false, "Invalid CDC Device Index");
        return USB_DEVICE_CDC_RESULT_ERROR_INSTANCE_INVALID;
    }

    thisCDCDevice = &gUSBDeviceCDCInstance[iCDC];
    endpoint = &thisCDCDevice->notificationInterface.endpoint[USB_DEVICE_CDC_ENDPOINT_TX];

    if(!(endpoint->isConfigured))
    {
        /* This means that the endpoint is not configured yet */
        SYS_ASSERT(false, "Endpoint not configured");
        return (USB_DEVICE_CDC_RESULT_ERROR_INSTANCE_NOT_CONFIGURED);
    }

    if(thisCDCDevice->currentQSizeSerialStateNotification >=
            thisCDCDevice->queueSizeSerialStateNotification)
    {
        SYS_ASSERT(false, "Serial State Notification Send Queue is full");
        return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_QUEUE_FULL);
    }

    /*Obtain mutex to get access to a shared resource, check return value*/
    osalError = OSAL_MUTEX_Lock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP, OSAL_WAIT_FOREVER);
    if(osalError != OSAL_RESULT_TRUE)
    {
      /*Do not proceed lock was not obtained, or error occurred, let user know about error*/
      return (USB_DEVICE_CDC_RESULT_ERROR);
    }

    /* Loop and find a free IRP in the Q */
    for ( cnt = 0; cnt < USB_DEVICE_CDC_QUEUE_DEPTH_COMBINED; cnt ++ )
    {
        if(gUSBDeviceCDCIRP[cnt].status < (USB_DEVICE_IRP_STATUS)USB_DEVICE_IRP_FLAG_DATA_PENDING)
        {
            /* This means the IRP is free */

            irp = &gUSBDeviceCDCIRP[cnt];
            irp->data = notificationData;
            irp->size = sizeof(USB_CDC_SERIAL_STATE);
            irp->userData = (uintptr_t) iCDC;
            irp->callback = _USB_DEVICE_CDC_SerialStateSendIRPCallback;
            irp->flags = USB_DEVICE_IRP_FLAG_DATA_COMPLETE;
            /* Prevent other tasks pre-empting this sequence of code */ 
            IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
            /* Update Serial State Notification Queue Size */ 
            thisCDCDevice->currentQSizeSerialStateNotification ++;
            OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
            
            *transferHandle = (USB_DEVICE_CDC_TRANSFER_HANDLE) irp;
            irpError = USB_DEVICE_IRPSubmit(thisCDCDevice->deviceHandle, endpoint->address, irp);
            
            /* If IRP Submit function returned any error, then invalidate the
               Transfer handle.  */
            if (irpError != USB_ERROR_NONE )
            {
                /* Prevent other tasks pre-empting this sequence of code */ 
                IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
                /* Update Serial State Notification Queue Size */ 
                thisCDCDevice->currentQSizeSerialStateNotification --;
                OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
                
                *transferHandle = USB_DEVICE_CDC_TRANSFER_HANDLE_INVALID;
            }

            /*Release mutex, done with shared resource*/
            osalError = OSAL_MUTEX_Unlock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP);
            if(osalError != OSAL_RESULT_TRUE)
            {
                /*Do not proceed unlock was not complete, or error occurred, let user know about error*/
                return (USB_DEVICE_CDC_RESULT_ERROR);
            }
            
            return(irpError);
        }
    }
    
    /*Release mutex, done with shared resource*/
    osalError = OSAL_MUTEX_Unlock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP);
    if(osalError != OSAL_RESULT_TRUE)
    {
        /*Do not proceed unlock was not complete, or error occurred, let user know about error*/
        return (USB_DEVICE_CDC_RESULT_ERROR);
    }
    /* If here means we could not find a spare IRP */
    return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_QUEUE_FULL);
}
Ejemplo n.º 6
0
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
)
{
    int count = 0;
    USB_DEVICE_OBJ* devClientHandle;
    USB_ERROR irpSubmitError;
    SYS_MODULE_INDEX deviceInstanceNumber;
    USB_DEVICE_Q_SIZE_ENDPOINT* thisEndpointQueueSize;
    USB_DEVICE_IRP * irp = gUSBDeviceEndpointIRP;
    OSAL_RESULT osalError;
    *transferHandle = USB_DEVICE_TRANSFER_HANDLE_INVALID;


    /* Validate the handle */
    devClientHandle = _USB_DEVICE_ClientHandleValidate(usbDeviceHandle);
    if (devClientHandle == NULL)
    {
        SYS_DEBUG(0, "USB Device Layer: Invalid Client Handle");
        return(USB_DEVICE_RESULT_ERROR_DEVICE_HANDLE_INVALID);
    }

    /* Get Device Instance Number */
    deviceInstanceNumber = devClientHandle->usbDevLayerIndex;

    /* Get Handle to the Endpoint Queue Size structure */
    thisEndpointQueueSize  = &qSizeEndpoint[deviceInstanceNumber];

    /* Make sure that we are with in the queue size for this instance */
    if(thisEndpointQueueSize->qSizeCurrentEpWrite >= thisEndpointQueueSize->qSizeMaxEpWrite)
    {
        SYS_DEBUG(0, "Write Queue is full");
        return(USB_DEVICE_RESULT_ERROR_TRANSFER_QUEUE_FULL);
    }

    /*Obtain mutex to get access to a shared resource, check return value*/
    osalError = OSAL_MUTEX_Lock(&(devClientHandle->mutexEndpointIRP), OSAL_WAIT_FOREVER);
    if(osalError != OSAL_RESULT_TRUE)
    {
      /*Do not proceed lock was not obtained, or error occurred, let user know about error*/
      return (USB_DEVICE_RESULT_ERROR);
    }

    /* Check if the if there is free slot available in queue */
    for(count = 0; count < (USB_DEVICE_ENDPOINT_QUEUE_DEPTH_COMBINED) ; count ++ )
    {
        /* Search for a free IRP */
        if(irp->status <= USB_DEVICE_IRP_STATUS_COMPLETED_SHORT)
        {
            /* We found the IRP. Populate and submit */
            irp->data = (void *)data;
            irp->size = size;
            irp->flags = flags;
            irp->callback = &_USB_DEVICE_EndpointWriteCallBack;
            irp->userData = (uintptr_t)devClientHandle;
            (* transferHandle) = ( USB_DEVICE_TRANSFER_HANDLE )irp;
            (thisEndpointQueueSize->qSizeCurrentEpWrite)++;
            irpSubmitError = USB_DEVICE_IRPSubmit( devClientHandle, endpoint, irp);

            /*Release mutex, done with shared resource*/
            osalError = OSAL_MUTEX_Unlock(&(devClientHandle->mutexEndpointIRP));
            if(osalError != OSAL_RESULT_TRUE)
            {
                /*Do not proceed lock was not obtained, or error occurred, let user know about error*/
                return (USB_DEVICE_RESULT_ERROR);
            }
            return(irpSubmitError);
        }
        irp ++;
    }
    
    /* We could not find a spare IRP */
    SYS_DEBUG(0, "USB Device Endpoint Write: Transfer queue is full");
    return USB_DEVICE_RESULT_ERROR_TRANSFER_QUEUE_FULL;
}
void DRV_USART_BufferAddRead
(
    DRV_HANDLE hClient,
    DRV_USART_BUFFER_HANDLE * bufferHandle,
    void * destination,
    size_t nBytes
)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    bool interruptWasEnabled = false;
    DRV_USART_BUFFER_OBJ * bufferObj = NULL;
    DRV_USART_BUFFER_OBJ * iterator;
    unsigned int i;

    /* This function adds a buffer to the read queue */

    /* We first check the arguments and initialize the
       buffer handle */

    if(bufferHandle == NULL)
    {
        return;
    }

    *bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID;

    clientObj = _DRV_USART_DriverHandleValidate(hClient);

    if(clientObj == NULL)
    {
        SYS_ASSERT(false, "Invalid driver handle");
        return;
    }

    if((nBytes == 0) || (NULL == destination))
    {
        /* We either got an invalid client handle,
           invalid destination pointer or 0 bytes to
           transfer */

        SYS_ASSERT(false, "Invalid parameters");
        return;
    }

    hDriver = clientObj->hDriver;

    if(hDriver->queueSizeCurrentRead >= hDriver->queueSizeRead)
    {
        /* This means the queue is full. We cannot add
         * this request */

        //SYS_ASSERT(false, "Receive Queue is full");
        return;
    }

    /* We will allow buffers to be added in the interrupt
     * context of this USART driver. But we must make
     * sure that if we are in interrupt, then we should
     * not modify mutexes. */

    if(hDriver->interruptNestingCount == 0)
    {
        /* Grab a mutex. This is okay because we are not in an
         * interrupt context */

        if(OSAL_MUTEX_Lock(&(hDriver->mutexDriverInstance), OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
        {
            /* We will disable interrupts so that the queue
             * status does not get updated asynchronously.
             * This code will always execute. */

            interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource);
        }
        else
        {
            /* The mutex acquisition timed out. Return with an
             * invalid handle. This code will not execute
             * if there is no RTOS. */
            return;
        }
    }

    /* Search the buffer pool for a free buffer object */
    for(i = 0 ; i < DRV_USART_QUEUE_DEPTH_COMBINED; i ++)
    {
        if(!gDrvUSARTBufferObj[i].inUse)
        {
            /* This means this object is free.
             * Configure the object and then
             * break */
            bufferObj = &gDrvUSARTBufferObj[i];
            bufferObj->size     = nBytes;
            bufferObj->inUse    = true;
            bufferObj->buffer   = (uint8_t*)destination;
            bufferObj->hClient  = clientObj;
            bufferObj->next     = NULL;
            bufferObj->previous = NULL;
            bufferObj->nCurrentBytes = 0;
            bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD);

            /* Assign a handle to this buffer. The buffer handle must be unique.
             * To do this, we construct the buffer handle out of the
             * gDrvUSARTTokenCount and allocated buffer index. Note that
             * gDrvUSARTTokenCount is incremented and wrapped around when the
             * value reaches OxFFFF. We do avoid a case where the token value
             * becomes 0xFFFF and the buffer index also becomes 0xFFFF */

            bufferObj->bufferHandle = _DRV_USART_MAKE_HANDLE(gDrvUSARTTokenCount, i);
            *bufferHandle = bufferObj->bufferHandle;

            /* Update the token number. */
            _DRV_USART_UPDATE_BUFFER_TOKEN(gDrvUSARTTokenCount);
            break;
        }
    }

    if(i == DRV_USART_QUEUE_DEPTH_COMBINED)
    {
        /* This means we could not find a buffer. This
           will happen if the the DRV_USART_QUEUE_DEPTH_COMBINED
           parameter is configured to be less */

        SYS_ASSERT(false, "Insufficient Combined Queue Depth");

        /* Enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
        }

        if(hDriver->interruptNestingCount == 0)
        {
            /* Release mutex */
            OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
        }

        return;
    }

    /* Increment the current queue size*/
    hDriver->queueSizeCurrentRead ++;

    /* Check if the queue is empty */
    if(hDriver->queueRead == NULL)
    {
        /* This is the first buffer in the
           queue */

        hDriver->queueRead = bufferObj;

        /* This is the first item in the queue. Enable
           RX interrupt. */

        _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);

    }
    else
    {
        /* This means the read queue is not empty. We must add
           the buffer object to the end of the queue */

        iterator = hDriver->queueRead;
        while(iterator->next != NULL)
        {
            /* Get the next buffer object */
            iterator = iterator->next;
        }

        /* At this point, iterator will point to the
           last object in the queue. We add the buffer
           object to the linked list. Note that we
           need to set up the previous pointer as well
           because buffer should be deleted when the
           client closes the driver */

        iterator->next = bufferObj;
        bufferObj->previous = iterator;

        /* We are done. Restore the interrupt enable status
           and return. */

        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
        }

    }
    if(hDriver->interruptNestingCount == 0)
    {
        /* Release mutex */
        OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
    }
    return;
}
Ejemplo n.º 8
0
size_t DRV_USART_Read(const DRV_HANDLE hClient, void * destination, size_t nBytes)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    USART_MODULE_ID plibID;
    DRV_USART_BUFFER_OBJ * iterator, * bufferObj;
    size_t count = 0;
    uint8_t * data;
    bool status;

    /* Validate the driver handle */

    clientObj = _DRV_USART_DriverHandleValidate(hClient);
    if(clientObj == NULL)
    {
        SYS_DEBUG(0, "Invalid driver handle");
        return 0;
    }

    hDriver = (DRV_USART_OBJ *)clientObj->hDriver;
    plibID = hDriver->moduleId;

    if(!(clientObj->ioIntent & DRV_IO_INTENT_READ))
    {
        /* This client did not open the driver for
           reading */
        SYS_DEBUG(0, "Driver not opened for read");
        return 0;
    }

    if((destination == NULL) || (nBytes == 0))
    {
        /* We have a NULL pointer or dont have
           any data to write. */

        SYS_DEBUG(0, "NULL data pointer or no data to write");
        return 0;
    }

    data = (uint8_t *)destination;

    /* Grab he hardware instance mutex */

    if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
    {
        if(!(clientObj->ioIntent & DRV_IO_INTENT_NONBLOCKING))
        {
            /* This is a blocking implementation. We populate the client buffer
               object and add it to the queue. We then wait till the buffer is
               completely processed. */

            /* Because we are modifying the queue, we should disable the
               interrupt */

            status = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource);

            /* Get the queue head */

            iterator = hDriver->queueRead;

            /* If the queue is not empty, get to the end of the queue */

            if(iterator != NULL)
            {
                while(iterator->next != NULL)
                {
                    iterator = iterator->next;
                }
            }

            /* We should be at the end of the queue now. Populate the client
               buffer object */

            bufferObj = &clientObj->bufferObject;
            bufferObj->buffer = destination;
            bufferObj->nCurrentBytes = 0;
            bufferObj->size = nBytes;
            bufferObj->inUse = true;
            bufferObj->hClient = clientObj;
            bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_READ_WRITE);

            /* Add this object to the queue and enable the RX interrupt */

            bufferObj->previous = iterator;
            bufferObj->next = NULL;

            /* If we are not at the start of the queue, then update the next
               pointer of the last object else set the queue head to point to
               this object */

            if(hDriver->queueRead == NULL)
            {
                hDriver->queueRead = bufferObj;
            }
            else
            {
                iterator->next = bufferObj;
                bufferObj->previous = iterator;
            }

            /* Now enable the interrupt and release the mutex so that the system
               can proceed */

            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
            OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
                            "Unable to unlock hardware instance mutex");
            
            /* If we are in a bare metal configuration, then wait till the
               buffer is processed. If we are in RTOS configuration then pend on
               the client semaphore. */

            if(OSAL_SEM_Pend(clientObj->semReadDone, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
            {
                /* This is the implementation of the blocking behavior. In a
                   RTOS configuration, if the code reaches here, it means then
                   that buffer has been processed. */ 
                
                while(bufferObj->inUse);
                if(bufferObj->nCurrentBytes != nBytes) 
                {
                    /* This means this buffer was terminated because of an
                       error. */
                    
                    return(DRV_USART_READ_ERROR);
                }
                     
                count = nBytes;
            }
        }
        else if(clientObj->ioIntent & DRV_IO_INTENT_NONBLOCKING)
        {
            /* This is a non blocking implementation*/

            if(hDriver->queueRead != NULL)
            {
                /* This means queue is not empty. We cannot read
                   data now. */
                count = 0;
            }
            else
            {

                while((PLIB_USART_ReceiverDataIsAvailable(plibID)) &&
                        (count < nBytes))
                {
                    /* This is not a blocking implementation. We read
                       the hardware till the FIFO is empty. */

                    data[count] = PLIB_USART_ReceiverByteReceive(plibID);
                    count ++;

                    /* We need to check for errors. Store the error
                       in the client error field. */

                    clientObj->error = PLIB_USART_ErrorsGet(plibID);

                    if(clientObj->error != DRV_USART_ERROR_NONE)
                    {
                        /* This means we have an error. Release the mutex and
                           exit */
                        OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
                                "Unable to unlock hardware instance mutex");
                        return(DRV_USART_READ_ERROR);
                    }
                }
            }
        }
    }
    else
    {
        /* Timed out while waiting for read mutex.
         * We simply return 0 */
        count = 0;
    }

    return(count);
}
Ejemplo n.º 9
0
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
)
{
    int count = 0;
    USB_DEVICE_OBJ* devClientHandle;
    USB_ERROR irpSubmitError;
    SYS_MODULE_INDEX deviceInstanceNumber;
    USB_DEVICE_Q_SIZE_ENDPOINT* thisEndpointQueueSize;
    USB_DEVICE_IRP * irp ;
    OSAL_RESULT osalError;
    *transferHandle = USB_DEVICE_TRANSFER_HANDLE_INVALID;
    OSAL_CRITSECT_DATA_TYPE IntState;


    /* Validate the handle */
    devClientHandle = _USB_DEVICE_ClientHandleValidate(usbDeviceHandle);
    if (devClientHandle == NULL)
    {
        SYS_DEBUG(0, "USB Device Layer: Invalid Client Handle");
        return(USB_DEVICE_RESULT_ERROR_DEVICE_HANDLE_INVALID);
    }

    /* Get Device Instance Number */
    deviceInstanceNumber = devClientHandle->usbDevLayerIndex;

    /* Get Handle to the Endpoint Queue Size structure */
    thisEndpointQueueSize  = &qSizeEndpoint[deviceInstanceNumber];

    /* Make sure that we are with in the queue size for this instance */
    if(thisEndpointQueueSize->qSizeCurrentEpWrite >= thisEndpointQueueSize->qSizeMaxEpWrite)
    {
        SYS_DEBUG(0, "Write Queue is full");
        return(USB_DEVICE_RESULT_ERROR_TRANSFER_QUEUE_FULL);
    }

    /*Obtain mutex to get access to a shared resource, check return value*/
    osalError = OSAL_MUTEX_Lock(&(devClientHandle->mutexEndpointIRP), OSAL_WAIT_FOREVER);
    if(osalError != OSAL_RESULT_TRUE)
    {
      /*Do not proceed lock was not obtained, or error occurred, let user know about error*/
      return (USB_DEVICE_RESULT_ERROR);
    }

    /* Check if the if there is free slot available in queue */
    for(count = 0; count < (USB_DEVICE_ENDPOINT_QUEUE_DEPTH_COMBINED) ; count ++ )
    {
        if(gUSBDeviceEndpointIRP[count].status <
                (USB_DEVICE_IRP_STATUS)USB_DEVICE_IRP_FLAG_DATA_PENDING)
        {
            /* This means the IRP is free. Configure the IRP
             * update the current queue size and then submit */
            irp = &gUSBDeviceEndpointIRP[count]; 
            irp->data = (void *)data;
            irp->size = size;
            irp->flags = flags;
            irp->callback = &_USB_DEVICE_EndpointWriteCallBack;
            irp->userData = (uintptr_t)devClientHandle;
            (* transferHandle) = ( USB_DEVICE_TRANSFER_HANDLE )irp;
            
            /* Prevent other tasks pre-empting this sequence of code */ 
            IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
            (thisEndpointQueueSize->qSizeCurrentEpWrite)++;
            OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
            
            irpSubmitError = USB_DEVICE_IRPSubmit( devClientHandle, endpoint, irp);
            
            /* If IRP Submit function returned any error, then invalidate the
               Transfer handle.  */
            if (irpSubmitError != USB_ERROR_NONE )
            {
                /* Prevent other tasks pre-empting this sequence of code */ 
                IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
                /* Update the read queue size */ 
                (thisEndpointQueueSize->qSizeCurrentEpWrite)--;
                OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
                *transferHandle = USB_DEVICE_TRANSFER_HANDLE_INVALID;
            }
            
            /*Release mutex, done with shared resource*/
            osalError = OSAL_MUTEX_Unlock(&(devClientHandle->mutexEndpointIRP));
            if(osalError != OSAL_RESULT_TRUE)
            {
                /*Do not proceed lock was not obtained, or error occurred, let user know about error*/
                return (USB_DEVICE_RESULT_ERROR);
            }
            return(irpSubmitError);
        }
    }
    
    /*Release mutex, done with shared resource*/
    osalError = OSAL_MUTEX_Unlock(&(devClientHandle->mutexEndpointIRP));
    if(osalError != OSAL_RESULT_TRUE)
    {
        /*Do not proceed, unlock was not completed, or error occurred, let user know about error*/
        return (USB_DEVICE_RESULT_ERROR);
    }
    /* We could not find a spare IRP */
    SYS_DEBUG(0, "USB Device Endpoint Write: Transfer queue is full");
    return USB_DEVICE_RESULT_ERROR_TRANSFER_QUEUE_FULL;
}
Ejemplo n.º 10
0
void _DRV_USART_BufferQueueTxTasks(DRV_USART_OBJ * hDriver)
{
    /* Start by getting the buffer at the head of queue. */

    DRV_USART_BUFFER_OBJ * bufferObj;
    DRV_USART_CLIENT_OBJ * client;
    USART_MODULE_ID plibID;
    bool status;

    bufferObj = hDriver->queueWrite;
    plibID = hDriver->moduleId;

    /* If this driver is configured for polled mode in an RTOS, the tasks
       routine would be called from another thread. We need to get the driver
       instance mutex before updating the queue. If the driver is configured for
       interrupt mode, then _DRV_USART_TAKE_MUTEX will compile to true */

    if(DRV_USART_INTERRUPT_MODE == false)
    {
        if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER))
        {
            /* We were able to take the mutex */
        }
        else
        {
            /* The mutex acquisition timed out. Return with an
               invalid handle. This code will not execute
               if there is no RTOS. */
            return;
        }
    }

    if(bufferObj != NULL)
    {
        /* This means the queue is not empty. Check if this buffer is done */
        if(bufferObj->nCurrentBytes >= bufferObj->size)
        {
            /* This means the buffer is completed. If there
               is a callback registered with client, then
               call it */

            client = (DRV_USART_CLIENT_OBJ *)bufferObj->hClient;
            if((client->eventHandler != NULL) && (bufferObj->flags & DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD))
            {
                /* Before calling the event handler, the interrupt nesting
                   counter is incremented. This will allow driver routine that
                   are called from the event handler to know the interrupt
                   nesting level. Events are only generated for buffers that
                   were submitted using the buffer add routine */

                hDriver->interruptNestingCount ++;

                client->eventHandler(DRV_USART_BUFFER_EVENT_COMPLETE,
                        (DRV_USART_BUFFER_HANDLE)bufferObj,
                        client->context);

                /* Decrement the nesting count */
                hDriver->interruptNestingCount -- ;
            }
           
            /* Get the next buffer in the queue and deallocate
             * this buffer */
           
            hDriver->queueWrite = bufferObj->next;
            bufferObj->inUse = false;
            hDriver->queueSizeCurrentWrite --;
           
            if(bufferObj->flags & DRV_USART_BUFFER_OBJ_FLAG_READ_WRITE)
            {
                /* This means we should post the semaphore */
                OSAL_ASSERT(_DRV_USART_SEM_POST(client->semWriteDone) == OSAL_RESULT_TRUE,
                        "Unable to post write buffer queue empty semaphore");

            }
        }
    }

    /* Check if the queue is still not empty and process
       the buffer */

    if(hDriver->queueWrite != NULL)
    {
        bufferObj = hDriver->queueWrite;

        /* Fill up the FIFO with data till the FIFO is full
           and we have data to send */
        while((!PLIB_USART_TransmitterBufferIsFull(plibID))
                && (bufferObj->nCurrentBytes < bufferObj->size ))
        {
            PLIB_USART_TransmitterByteSend(plibID, bufferObj->buffer[bufferObj->nCurrentBytes]);
            bufferObj->nCurrentBytes ++;
        }
    }
    else 
    {
        /* If the queue is empty, then disable the TX interrupt */
        status = _DRV_USART_InterruptSourceDisable(hDriver->txInterruptSource);
    }
    
    /* Release the mutex */
    OSAL_ASSERT(_DRV_USART_RELEASE_MUTEX(hDriver->mutexDriverInstance),
                            "Unable to release Hardware Instance Mutex");
  
}
Ejemplo n.º 11
0
uint32_t wdrv_mutex_acquire(OSAL_MUTEX_HANDLE_TYPE *mutex_ptr, uint32_t tick_count)
{
    OSAL_MUTEX_Lock(mutex_ptr, OSAL_WAIT_FOREVER);
    return 0;
}
Ejemplo n.º 12
0
NET_PRES_SKT_HANDLE_T NET_PRES_SKT_Open(NET_PRES_INDEX index, NET_PRES_SKT_T socketType, NET_PRES_SKT_ADDR_T addrType, NET_PRES_SKT_PORT_T port, NET_PRES_ADDRESS * addr, NET_PRES_SKT_ERROR_T* error)
{
    NET_PRES_TransOpen fpTransOpen = NULL;
    NET_PRES_EncProviderOpen fpProvOpen= NULL;
    NET_PRES_TransportObject * transObject;
    NET_PRES_EncProviderObject * provObject;

    // Check to see if we have a valid index
    if (index >= sNetPresData.numLayers)
    {
        *error = NET_PRES_SKT_OP_INVALID_INDEX;
        return NET_PRES_INVALID_SOCKET;
    }

    // Check to see if the operation is supported
    if ((socketType & (NET_PRES_SKT_CLIENT | NET_PRES_SKT_STREAM)) ==  (NET_PRES_SKT_CLIENT | NET_PRES_SKT_STREAM))
    {
        transObject = &(sNetPresData.transObjectSC[index]);
        provObject = &(sNetPresData.encProvObjectSC[index]);
        fpProvOpen = sNetPresData.encProvObjectSC[index].fpOpen;
        fpTransOpen = sNetPresData.transObjectSC[index].fpOpen;
    }
    else if ((socketType & (NET_PRES_SKT_SERVER | NET_PRES_SKT_STREAM)) ==  (NET_PRES_SKT_SERVER | NET_PRES_SKT_STREAM))
    {
        transObject = &(sNetPresData.transObjectSS[index]);
        provObject = &(sNetPresData.encProvObjectSS[index]);
        fpProvOpen = sNetPresData.encProvObjectSS[index].fpOpen;
        fpTransOpen = sNetPresData.transObjectSS[index].fpOpen;
    }
    else if ((socketType & (NET_PRES_SKT_CLIENT | NET_PRES_SKT_DATAGRAM)) ==  (NET_PRES_SKT_CLIENT | NET_PRES_SKT_DATAGRAM))
    {
        transObject = &(sNetPresData.transObjectDC[index]);
        provObject = &(sNetPresData.encProvObjectDC[index]);
        fpProvOpen = sNetPresData.encProvObjectDC[index].fpOpen;
        fpTransOpen = sNetPresData.transObjectDC[index].fpOpen;
    }
    else if ((socketType & (NET_PRES_SKT_SERVER | NET_PRES_SKT_DATAGRAM)) ==  (NET_PRES_SKT_SERVER | NET_PRES_SKT_DATAGRAM))
    {
        transObject = &(sNetPresData.transObjectDS[index]);
        provObject = &(sNetPresData.encProvObjectDS[index]);
        fpProvOpen = sNetPresData.encProvObjectDS[index].fpOpen;
        fpTransOpen = sNetPresData.transObjectDS[index].fpOpen;
    }
    if (fpTransOpen == NULL)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_OP_NOT_SUPPORTED;
        }
        return NET_PRES_INVALID_SOCKET;        
    }
    bool encrypted = (socketType & NET_PRES_SKT_ENCRYPTED) == NET_PRES_SKT_ENCRYPTED;
    
    if (encrypted)
    {
        if (fpProvOpen == NULL)
        {
            if (error != NULL)
            {
                *error = NET_PRES_SKT_OP_NOT_SUPPORTED;
            }
            return NET_PRES_INVALID_SOCKET;                    
        }
    }
    
    // The inputs have been validated
    if (OSAL_MUTEX_Lock(&sNetPresData.presMutex, OSAL_WAIT_FOREVER) != OSAL_RESULT_TRUE)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_UNKNOWN_ERROR;
        }
        return NET_PRES_INVALID_SOCKET;
    }
    
    // Search for a free socket
    uint8_t sockIndex;
    for (sockIndex = 0 ; sockIndex < NET_PRES_NUM_SOCKETS; sockIndex++)
    {
        if (sNetPresSockets[sockIndex].inUse)
        {
            continue;
        }
        sNetPresSockets[sockIndex].inUse = true;
        // the socket has been soft locked so no longer need the mutex.
        if (OSAL_MUTEX_Unlock(&sNetPresData.presMutex) != OSAL_RESULT_TRUE)
        {
            sNetPresSockets[sockIndex].inUse = false;
            if (error != NULL)
            {
                *error = NET_PRES_SKT_UNKNOWN_ERROR;
            }
            return NET_PRES_INVALID_SOCKET;        
        }
        sNetPresSockets[sockIndex].transHandle = (*fpTransOpen)(addrType, port, addr);
        if (sNetPresSockets[sockIndex].transHandle == NET_PRES_INVALID_SOCKET)
        {
            sNetPresSockets[sockIndex].inUse = false;
            if (error != NULL)
            {
                *error = NET_PRES_SKT_UNKNOWN_ERROR;
            }
            return NET_PRES_INVALID_SOCKET;            
        }
        sNetPresSockets[sockIndex].transObject = transObject;
        sNetPresSockets[sockIndex].provObject = provObject;
        sNetPresSockets[sockIndex].socketType = socketType;
        if (error != NULL)
        {
            *error = NET_PRES_SKT_OK;
        }
        if (encrypted)
        {
            sNetPresSockets[sockIndex].status = NET_PRES_ENC_SS_WAITING_TO_START_NEGOTIATION;
        }
        return sockIndex+1; // avoid returning 0 on success.        
    }
    if (OSAL_MUTEX_Unlock(&sNetPresData.presMutex) != OSAL_RESULT_TRUE)
    {
        if (error != NULL)
        {
            *error = NET_PRES_SKT_UNKNOWN_ERROR;
        }
        return NET_PRES_INVALID_SOCKET;        
    }
    if (error != NULL)
    {
        *error = NET_PRES_SKT_OP_OUT_OF_HANDLES;
    }
    return NET_PRES_INVALID_SOCKET;   
}
Ejemplo n.º 13
0
bool _DRV_USART_ClientBufferQueueObjectsRemove(DRV_USART_CLIENT_OBJ * clientObj)
{
    DRV_USART_OBJ * dObj = clientObj->hDriver;
    bool interruptWasEnabled = false;
    DRV_USART_BUFFER_OBJ * iterator = NULL;

    if(OSAL_MUTEX_Lock(dObj->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
    {
        /* Disable the transmit interrupt */
        interruptWasEnabled = _DRV_USART_InterruptSourceDisable(dObj->txInterruptSource);
        iterator = dObj->queueWrite;
        while(iterator != NULL)
        {
            if(clientObj == (DRV_USART_CLIENT_OBJ *)iterator->hClient)
            {
                /* That means this buffer object is owned
                   by this client. This buffer object should
                   be removed. The following code removes
                   the object from a doubly linked list queue. */

                iterator->inUse = false;
                if(iterator->previous != NULL)
                {
                    iterator->previous->next = iterator->next;
                }
                if(iterator->next != NULL)
                {
                    iterator->next->previous = iterator->previous;
                }
            }
            iterator = iterator->next;
        }

        /* Re-enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(dObj->txInterruptSource);
        }

        /* Now check the receive buffer queue. Start by disabling the 
           receive interrupt */

        interruptWasEnabled = _DRV_USART_InterruptSourceDisable(dObj->rxInterruptSource);
        iterator = dObj->queueRead;
        while(iterator != NULL)
        {
            if(clientObj == (DRV_USART_CLIENT_OBJ *)iterator->hClient)
            {
                /* That means this buffer object is owned
                   by this client. This buffer object should
                   be removed. The following code removed
                   the object from a doubly linked list queue. */

                iterator->inUse = false;
                if(iterator->previous != NULL)
                {
                    iterator->previous->next = iterator->next;
                }
                if(iterator->next != NULL)
                {
                    iterator->next->previous = iterator->previous;
                }
            }
            iterator = iterator->next;
        }
        
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(dObj->rxInterruptSource);
        }
        
        /* Unlock the mutex */

        OSAL_ASSERT((OSAL_MUTEX_Unlock(dObj->mutexDriverInstance)),
                "Unable to unlock Driver instance mutex");
    }
    else
    {
        /* The case where the mutex lock timed out and the
           client buffer objects could not be removed from
           the driver queue, the close function should fail. */

        return false;
    }

    return true;

} 
Ejemplo n.º 14
0
DRV_HANDLE DRV_USART_Open 
(
    const SYS_MODULE_INDEX drvIndex,
    const DRV_IO_INTENT ioIntent
)
{
    DRV_USART_CLIENT_OBJ *clientObj;
    DRV_USART_OBJ *dObj;
    unsigned int iClient;

    if (drvIndex >= DRV_USART_INSTANCES_NUMBER)
    {
        /* Invalid driver index */
        SYS_DEBUG(0, "Invalid Driver Instance");
        return (DRV_HANDLE_INVALID);
    }

    dObj = &gDrvUSARTObj[drvIndex];
    
    if((dObj->status != SYS_STATUS_READY) || (dObj->inUse == false)) 
    {
        /* The USART module should be ready */

        SYS_DEBUG(0, "Was the driver initialized?");
        return DRV_HANDLE_INVALID;
    }

    if(dObj->isExclusive)
    {
        /* This means the another client has opened the driver in exclusive
           mode. The driver cannot be opened again */

        SYS_DEBUG(0, "Driver already opened exclusively"); 
        return ( DRV_HANDLE_INVALID ) ;
    }

    if((dObj->nClients > 0) && (ioIntent & DRV_IO_INTENT_EXCLUSIVE))
    {
        /* This means the driver was already opened and another driver was 
           trying to open it exclusively.  We cannot give exclusive access in 
           this case */

        SYS_DEBUG(0, "Driver already opened. Cannot be opened exclusively");
        return(DRV_HANDLE_INVALID);
    }

    /* Grab client object mutex here */

    if(OSAL_MUTEX_Lock(gDrvUSARTCommonDataObj.mutexClientObjects, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
    {
        /* Enter here only if the lock was obtained (appplicable in 
           RTOS only). If the mutex lock fails due to time out then
           this code does not get executed */

        for(iClient = 0; iClient != DRV_USART_CLIENTS_NUMBER; iClient ++)
        {
            if(!gDrvUSARTClientObj[iClient].inUse)
            {
                /* This means we have a free client object to use */
                clientObj = &gDrvUSARTClientObj[iClient];
                clientObj->inUse        = true;
                
                /* We have found a client object. Release the mutex */

                OSAL_ASSERT((OSAL_MUTEX_Unlock(gDrvUSARTCommonDataObj.mutexClientObjects)),
                        "Unable to unlock clients objects routine mutex");
                
                clientObj->hDriver      = dObj;

                /* In a case where the driver is configured for polled
                   and bare metal operation, it will not suppot blocking operation */
                
                clientObj->ioIntent     = (ioIntent | _DRV_USART_ALWAYS_NON_BLOCKING);
                clientObj->eventHandler = NULL;
                clientObj->context      = NULL;
                clientObj->error        = DRV_USART_ERROR_NONE;

                if(ioIntent & DRV_IO_INTENT_EXCLUSIVE)
                {
                    /* Set the driver exclusive flag */
                    dObj->isExclusive = true;
                }

                dObj->nClients ++;

                /* Create the semaphores */
                OSAL_ASSERT(((OSAL_SEM_Create(&(clientObj->semReadDone), OSAL_SEM_TYPE_COUNTING, 1, 0)) == OSAL_RESULT_TRUE),
                        "Unable to create client read done semaphore");
                OSAL_ASSERT(((OSAL_SEM_Create(&(clientObj->semWriteDone), OSAL_SEM_TYPE_COUNTING, 1, 0)) == OSAL_RESULT_TRUE),
                        "Unable to create client write done semaphore");

                /* Update the client status */
                clientObj->status = DRV_USART_CLIENT_STATUS_READY;
                return ((DRV_HANDLE) clientObj );
            }
        }

        /* Could not find a client object. Release the mutex and 
           return with an invalid handle. */
        OSAL_ASSERT((OSAL_MUTEX_Unlock(gDrvUSARTCommonDataObj.mutexClientObjects)),
                    "Unable to unlock clients objects routine mutex");
    }

    /* If we have reached here, it means either we could not find a spare
       client object or the mutex timed out in a RTOS environment. */
    
    return DRV_HANDLE_INVALID;
} 
Ejemplo n.º 15
0
USB_DEVICE_CDC_RESULT USB_DEVICE_CDC_Read 
(
    USB_DEVICE_CDC_INDEX iCDC ,
    USB_DEVICE_CDC_TRANSFER_HANDLE * transferHandle ,
    void * data , size_t size
)
{
    unsigned int cnt;
    unsigned int remainder;
    USB_DEVICE_IRP * irp;
    USB_DEVICE_CDC_ENDPOINT * endpoint;
    USB_DEVICE_CDC_INSTANCE * thisCDCDevice;
    OSAL_RESULT osalError;
    USB_ERROR irpError;
    OSAL_CRITSECT_DATA_TYPE IntState;

    /* Check the validity of the function driver index */
    
    if (  iCDC >= USB_DEVICE_CDC_INSTANCES_NUMBER  )
    {
        /* Invalid CDC index */
        SYS_ASSERT(false, "Invalid CDC Device Index");
        return USB_DEVICE_CDC_RESULT_ERROR_INSTANCE_INVALID;
    }

    thisCDCDevice = &gUSBDeviceCDCInstance[iCDC];
    endpoint = &thisCDCDevice->dataInterface.endpoint[USB_DEVICE_CDC_ENDPOINT_RX];
    *transferHandle = USB_DEVICE_CDC_TRANSFER_HANDLE_INVALID;

    /* Check if the endpoint is configured */
    if(!(endpoint->isConfigured))
    {
        /* This means that the endpoint is not configured yet */
        SYS_ASSERT(false, "Endpoint not configured");
        return (USB_DEVICE_CDC_RESULT_ERROR_INSTANCE_NOT_CONFIGURED);
    }

    /* For read the size should be a multiple of endpoint size*/
    remainder = size % endpoint->maxPacketSize;

    if((size == 0) || (remainder != 0))
    {
        /* Size is not valid */
        SYS_ASSERT(false, "Invalid size in IRP read");
        return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_SIZE_INVALID);
    }

    /* Make sure that we are with in the queue size for this instance */
    if(thisCDCDevice->currentQSizeRead >= thisCDCDevice->queueSizeRead)
    {
        SYS_ASSERT(false, "Read Queue is full");
        return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_QUEUE_FULL);
    }

    /*Obtain mutex to get access to a shared resource, check return value*/
    osalError = OSAL_MUTEX_Lock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP, OSAL_WAIT_FOREVER);
    if(osalError != OSAL_RESULT_TRUE)
    {
      /*Do not proceed lock was not obtained, or error occurred, let user know about error*/
      return (USB_DEVICE_CDC_RESULT_ERROR);
    }

    /* Loop and find a free IRP in the Q */
    for ( cnt = 0; cnt < USB_DEVICE_CDC_QUEUE_DEPTH_COMBINED; cnt ++ )
    {
        if(gUSBDeviceCDCIRP[cnt].status <
                (USB_DEVICE_IRP_STATUS)USB_DEVICE_IRP_FLAG_DATA_PENDING)
        {
            /* This means the IRP is free. Configure the IRP
             * update the current queue size and then submit */

            irp = &gUSBDeviceCDCIRP[cnt];
            irp->data = data;
            irp->size = size;
            irp->userData = (uintptr_t) iCDC;
            irp->callback = _USB_DEVICE_CDC_ReadIRPCallback;
            
            /* Prevent other tasks pre-empting this sequence of code */ 
            IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
            /* Update the read queue size */ 
            thisCDCDevice->currentQSizeRead++;
            OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
            
            *transferHandle = (USB_DEVICE_CDC_TRANSFER_HANDLE)irp;
            irpError = USB_DEVICE_IRPSubmit(thisCDCDevice->deviceHandle,
                    endpoint->address, irp);

            /* If IRP Submit function returned any error, then invalidate the
               Transfer handle.  */
            if (irpError != USB_ERROR_NONE )
            {
                /* Prevent other tasks pre-empting this sequence of code */ 
                IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
                /* Update the read queue size */ 
                thisCDCDevice->currentQSizeRead--;
                OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
                *transferHandle = USB_DEVICE_CDC_TRANSFER_HANDLE_INVALID;
            }
            
            /*Release mutex, done with shared resource*/
            osalError = OSAL_MUTEX_Unlock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP);
            if(osalError != OSAL_RESULT_TRUE)
            {
                /*Do not proceed unlock was not complete, or error occurred, let user know about error*/
                return (USB_DEVICE_CDC_RESULT_ERROR);
            }
            
            return(irpError);
        }
    }
    
    /*Release mutex, done with shared resource*/
    osalError = OSAL_MUTEX_Unlock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP);
    if(osalError != OSAL_RESULT_TRUE)
    {
        /*Do not proceed unlock was not complete, or error occurred, let user know about error*/
        return (USB_DEVICE_CDC_RESULT_ERROR);
    }
    /* If here means we could not find a spare IRP */
    return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_QUEUE_FULL);
}
Ejemplo n.º 16
0
void DRV_USART_BufferAddWrite
(
    DRV_HANDLE hClient,
    DRV_USART_BUFFER_HANDLE * bufferHandle, 
    void * source,
    size_t nBytes
)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    bool interruptWasEnabled = false;
    DRV_USART_BUFFER_OBJ * bufferObj, * iterator;
    unsigned int i;

    /* This function adds a buffer to the write queue */

    /* We first check the arguments and initialize the 
       buffer handle */ 

    if(bufferHandle != NULL)
    {
        *bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID;
    }

    /* Validate the driver handle */
    clientObj = _DRV_USART_DriverHandleValidate(hClient);
    if(clientObj == NULL)
    {
        SYS_DEBUG(0, "Invalid Driver Handle");
        return;
    }

    if((nBytes == 0) || (NULL == source) || (bufferHandle == NULL))
    {
        /* We either got an invalid client handle,
           invalid source pointer or 0 bytes to
           transfer */

        SYS_DEBUG(0, "Invalid parameters");
        return;
    }

    hDriver = clientObj->hDriver;

    if(hDriver->queueSizeCurrentWrite >= hDriver->queueSizeWrite)
    {
        /* This means the queue is full. We cannot add
           this request */

        SYS_DEBUG(0, "Transmit Queue is full");
        return;
    }

    /* We will allow buffers to be added in the interrupt
       context of this USART driver. But we must make 
       sure that if we are in interrupt, then we should 
       not modify mutexes. */

    if(hDriver->interruptNestingCount == 0)
    {
        /* Grab a mutex. This is okay because we are not in an
           interrupt context */

        if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
        {
            /* We will disable interrupts so that the queue
               status does not get updated asynchronously. 
               This code will always execute. */

            interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->txInterruptSource);
        }
        else
        {
            /* The mutex acquisition timed out. Return with an 
               invalid handle. This code will not execute
               if there is no RTOS. */
            return;
        }
    }

    /* Search the buffer pool for a free buffer object */
    for(i = 0 ; i < DRV_USART_QUEUE_DEPTH_COMBINED; i ++)
    {
        if(!gDrvUSARTBufferObj[i].inUse)
        {
            /* This means this object is free. 
             * Configure the object and then
             * break */
            bufferObj = &gDrvUSARTBufferObj[i];
            bufferObj->size     = nBytes;
            bufferObj->inUse    = true;
            bufferObj->buffer   = (uint8_t*)source;
            bufferObj->hClient  = clientObj;
            bufferObj->nCurrentBytes = 0;
            bufferObj->next = NULL;
            bufferObj->previous = NULL;
            bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD);

            /* Assign a handle to this buffer */
            *bufferHandle = (DRV_USART_BUFFER_HANDLE)bufferObj;
            break;
        }
    }

    if(i == DRV_USART_QUEUE_DEPTH_COMBINED)
    {
        /* This means we could not find a buffer. This
           will happen if the the DRV_USART_QUEUE_DEPTH_COMBINED
           parameter is configured to be less */

        SYS_DEBUG(0, "Insufficient Combined Queue Depth");

        /* Enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->txInterruptSource);
        }

        /* Release mutex */
        OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
                "Unable to unlock buffer add write mutex");
        
        return;
    }

    /* Increment the current queue size*/
    hDriver->queueSizeCurrentWrite ++;

    /* Check if the queue is empty */
    if(hDriver->queueWrite == NULL)
    {
        /* This is the first buffer in the
           queue */

        hDriver->queueWrite = bufferObj;
        
        /* Enabling the interrupt here will cause the task
           routine to start processing this buffer. If this
           function is being called in an ISR, then this
           statement will not have any effect. */

        _DRV_USART_InterruptSourceEnable(hDriver->txInterruptSource);
    }
    else
    {
        /* This means the write queue is not empty. We must add
         * the buffer object to the end of the queue */

        iterator = hDriver->queueWrite;
        while(iterator->next != NULL)
        {
            /* Get the next buffer object */
            iterator = iterator->next;
        }

        /* At this point, iterator will point to the
           last object in the queue. We add the buffer
           object to the linked list. Note that we
           need to set up the previous pointer as well
           because buffer should be deleted when the 
           client closes the driver */

        iterator->next = bufferObj;
        bufferObj->previous = iterator;

        /* We are done. Restore the interrupt enable status
           and return. */

        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->txInterruptSource);
        }

    }
    
    /* Release mutex */
    OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
            "Unable to unlock buffer add write mutex");
    return;
}
Ejemplo n.º 17
0
USB_DEVICE_CDC_RESULT USB_DEVICE_CDC_Write 
(
    USB_DEVICE_CDC_INDEX iCDC ,
    USB_DEVICE_CDC_TRANSFER_HANDLE * transferHandle ,
    const void * data , size_t size ,
    USB_DEVICE_CDC_TRANSFER_FLAGS flags 
)
{
    unsigned int cnt;
    unsigned int remainder;
    USB_DEVICE_IRP * irp;
    USB_DEVICE_IRP_FLAG irpFlag = 0;
    USB_DEVICE_CDC_INSTANCE * thisCDCDevice;
    USB_DEVICE_CDC_ENDPOINT * endpoint;
    OSAL_RESULT osalError;
    USB_ERROR irpError; 
    OSAL_CRITSECT_DATA_TYPE IntState;

    /* Check the validity of the function driver index */
    
    if (  iCDC >= USB_DEVICE_CDC_INSTANCES_NUMBER  )
    {
        /* Invalid CDC index */
        SYS_ASSERT(false, "Invalid CDC Device Index");
        return USB_DEVICE_CDC_RESULT_ERROR_INSTANCE_INVALID;
    }

    /* Initialize the transfer handle, get the instance object
     * and the transmit endpoint */

    * transferHandle = USB_DEVICE_CDC_TRANSFER_HANDLE_INVALID;
    thisCDCDevice = &gUSBDeviceCDCInstance[iCDC];
    endpoint = &thisCDCDevice->dataInterface.endpoint[USB_DEVICE_CDC_ENDPOINT_TX];

    if(!(endpoint->isConfigured))
    {
        /* This means that the endpoint is not configured yet */
        SYS_ASSERT(false, "Endpoint not configured");
        return (USB_DEVICE_CDC_RESULT_ERROR_INSTANCE_NOT_CONFIGURED);
    }

    if(size == 0) 
    {
        /* Size cannot be zero */
        return (USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_SIZE_INVALID);
    }

    /* Check the flag */

    if(flags & USB_DEVICE_CDC_TRANSFER_FLAGS_MORE_DATA_PENDING)
    {
        if(size < endpoint->maxPacketSize)
        {
            /* For a data pending flag, we must atleast get max packet
             * size worth data */

            return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_SIZE_INVALID);
        }

        remainder = size % endpoint->maxPacketSize;
        
        if(remainder != 0)
        {
            size -= remainder;
        }

        irpFlag = USB_DEVICE_IRP_FLAG_DATA_PENDING;
    }
    else if(flags & USB_DEVICE_CDC_TRANSFER_FLAGS_DATA_COMPLETE)
    {
        irpFlag = USB_DEVICE_IRP_FLAG_DATA_COMPLETE;
    }

    if(thisCDCDevice->currentQSizeWrite >= thisCDCDevice->queueSizeWrite)
    {
        SYS_ASSERT(false, "Write Queue is full");
        return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_QUEUE_FULL);
    }

    /*Obtain mutex to get access to a shared resource, check return value*/
    osalError = OSAL_MUTEX_Lock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP, OSAL_WAIT_FOREVER);
    if(osalError != OSAL_RESULT_TRUE)
    {
      /*Do not proceed lock was not obtained, or error occurred, let user know about error*/
      return (USB_DEVICE_CDC_RESULT_ERROR);
    }

    /* loop and find a free IRP in the Q */
    for ( cnt = 0; cnt < USB_DEVICE_CDC_QUEUE_DEPTH_COMBINED; cnt ++ )
    {
        if(gUSBDeviceCDCIRP[cnt].status <
                (USB_DEVICE_IRP_STATUS)USB_DEVICE_IRP_FLAG_DATA_PENDING)
        {
            /* This means the IRP is free */

            irp         = &gUSBDeviceCDCIRP[cnt];
            irp->data   = (void *)data;
            irp->size   = size;

            irp->userData   = (uintptr_t) iCDC;
            irp->callback   = _USB_DEVICE_CDC_WriteIRPCallback;
            irp->flags      = irpFlag;

            /* Prevent other tasks pre-empting this sequence of code */ 
            IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
            /* Update the Write queue size */ 
            thisCDCDevice->currentQSizeWrite++;
            OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
            
            *transferHandle = (USB_DEVICE_CDC_TRANSFER_HANDLE)irp;

            irpError = USB_DEVICE_IRPSubmit(thisCDCDevice->deviceHandle,
                    endpoint->address, irp);

            /* If IRP Submit function returned any error, then invalidate the
               Transfer handle.  */
            if (irpError != USB_ERROR_NONE )
            {
                /* Prevent other tasks pre-empting this sequence of code */ 
                IntState = OSAL_CRIT_Enter(OSAL_CRIT_TYPE_HIGH);
                /* Update the Write queue size */ 
                thisCDCDevice->currentQSizeWrite--;
                OSAL_CRIT_Leave(OSAL_CRIT_TYPE_HIGH, IntState);
                *transferHandle = USB_DEVICE_CDC_TRANSFER_HANDLE_INVALID;
            }
            /*Release mutex, done with shared resource*/
            osalError = OSAL_MUTEX_Unlock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP);
            if(osalError != OSAL_RESULT_TRUE)
            {
                /*Do not proceed unlock was not complete, or error occurred, let user know about error*/
                return (USB_DEVICE_CDC_RESULT_ERROR);
            }

            return(irpError);
        }
    }
    
    /*Release mutex, done with shared resource*/
    osalError = OSAL_MUTEX_Unlock(&gUSBDeviceCdcCommonDataObj.mutexCDCIRP);
    if(osalError != OSAL_RESULT_TRUE)
    {
        /*Do not proceed unlock was not complete, or error occurred, let user know about error*/
        return (USB_DEVICE_CDC_RESULT_ERROR);
    }
    /* If here means we could not find a spare IRP */
    return(USB_DEVICE_CDC_RESULT_ERROR_TRANSFER_QUEUE_FULL);
}
void DRV_USART_BufferAddRead
(
    DRV_HANDLE hClient,
    DRV_USART_BUFFER_HANDLE * bufferHandle,
    void * destination,
    size_t nBytes
)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    bool interruptWasEnabled=false;
    DRV_USART_BUFFER_OBJ * bufferObj, * iterator;
    DRV_USART_BUFFER_OBJECT_INDEX usartBufIndex;

    /* This function adds a buffer to the read queue */

    /* We first check the arguments and initialize the
       buffer handle */

    if(bufferHandle == NULL)
    {
        return;
    }

    *bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID;

    clientObj = _DRV_USART_DriverHandleValidate(hClient);

    if(clientObj == NULL)
    {
        SYS_ASSERT(false, "Invalid driver handle");
        return;
    }

    if((nBytes == 0) || (NULL == destination))
    {
        /* We either got an invalid client handle,
           invalid destination pointer or 0 bytes to
           transfer */

        SYS_DEBUG(0, "Invalid parameters");
        return;
    }

    hDriver = clientObj->hDriver;

    if(hDriver->queueSizeCurrentRead >= hDriver->queueSizeRead)
    {
        /* This means the queue is full. We cannot add
         * this request */

        SYS_DEBUG(0, "Receive Queue is full");
        return;
    }

    /* We will allow buffers to be added in the interrupt
     * context of this USART driver. But we must make
     * sure that if we are in interrupt, then we should
     * not modify mutexes. */

    if(hDriver->interruptNestingCount == 0)
    {
        /* Grab a mutex. This is okay because we are not in an
         * interrupt context */

        if(OSAL_MUTEX_Lock(&(hDriver->mutexDriverInstance), OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
        {
            /* We will disable interrupts so that the queue
             * status does not get updated asynchronously.
             * This code will always execute. */
            if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
            {
                interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->dmaInterruptReceive);
            }
            else
            {
                interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource);
            }

        }
        else
        {
            /* The mutex acquisition timed out. Return with an
             * invalid handle. This code will not execute
             * if there is no RTOS. */
            return;
        }
    }

    usartBufIndex = _DRV_USART_QueueObjectIndexGet();
    if (usartBufIndex != DRV_USART_BUFFER_OBJECT_INDEX_INVALID)
    {
        bufferObj = &gDrvUSARTBufferObj[usartBufIndex];

        bufferObj->bufferHandle = _DRV_USART_DMA_MAKE_HANDLE(gDrvUSARTDMATokenCount, usartBufIndex);
        *bufferHandle = bufferObj->bufferHandle;

        _DRV_USART_DMA_UPDATE_BUFFER_TOKEN(gDrvUSARTDMATokenCount);

        bufferObj->size     = nBytes;
        bufferObj->inUse    = true;
        bufferObj->buffer   = (uint8_t*)destination;
        bufferObj->hClient  = clientObj;
        bufferObj->next     = NULL;
        bufferObj->previous = NULL;
        bufferObj->nCurrentBytes = 0;
        bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD);
    }
    else
    {
        /* This means we could not find a buffer. This
           will happen if the the DRV_USART_QUEUE_DEPTH_COMBINED
           parameter is configured to be less */

        SYS_ASSERT(false, "Insufficient Combined Queue Depth");

        /* Enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
            {
                _DRV_USART_InterruptSourceEnable(hDriver->dmaInterruptReceive);
            }
            else
            {
                _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
            }
        }
        /* Release mutex */
        OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));

        return;
    }

    /* Increment the current queue size*/
    hDriver->queueSizeCurrentRead ++;

    /* Check if the queue is empty */
    if(hDriver->queueRead == NULL)
    {
        /* This is the first buffer in the queue */
        hDriver->queueRead = bufferObj;

        /* This is the first item in the queue. Enable RX interrupt. */
        if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
        {
            /* Since this is the first buffer in the queue Add it immediately
              to DMA for processing */
            size_t srcSize, cellSize;
            srcSize = 1;
            cellSize = 1;
            SYS_DMA_ChannelTransferAdd(hDriver->dmaChannelHandleRead,
                                       PLIB_USART_ReceiverAddressGet(hDriver->moduleId),
                                       srcSize,bufferObj->buffer, bufferObj->size,
                                       cellSize);
            _SYS_DMA_ChannelForceStart(hDriver->dmaChannelHandleRead);
            _DRV_USART_InterruptSourceEnable(hDriver->dmaInterruptReceive);
        }
        else
        {
            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
        }
    }
    else
    {
        /* This means the read queue is not empty. We must add
           the buffer object to the end of the queue */

        iterator = hDriver->queueRead;
        while(iterator->next != NULL)
        {
            /* Get the next buffer object */
            iterator = iterator->next;
        }

        /* At this point, iterator will point to the
           last object in the queue. We add the buffer
           object to the linked list. Note that we
           need to set up the previous pointer as well
           because buffer should be deleted when the
           client closes the driver */

        iterator->next = bufferObj;
        bufferObj->previous = iterator;

        /* We are done. Restore the interrupt enable status
           and return. */
        if(interruptWasEnabled)
        {
            if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
            {
                /* There is already a buffer under processing in the queue.
                   This buffer will be added to DMA for processing immediately
                   after the processing of the buffer prior to this buffer completes.
                   (This functionality is implemented in _DRV_USART_BufferQueueRxTasks)*/
                _SYS_DMA_ChannelForceStart(hDriver->dmaChannelHandleRead);
                _DRV_USART_InterruptSourceEnable(hDriver->dmaInterruptReceive);
            }
            else
            {
                _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
            }
        }
    }

    /* Release mutex */
    OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
    return;
}
Ejemplo n.º 19
0
uint32_t WDRV_MutexLock(OSAL_MUTEX_HANDLE_TYPE *mutex_ptr, uint32_t tick_count)
{
    OSAL_MUTEX_Lock(mutex_ptr, OSAL_WAIT_FOREVER);
    return 0;
}
Ejemplo n.º 20
0
void _DRV_USART_BufferQueueRxTasks(DRV_USART_OBJ * hDriver)
{
    DRV_USART_BUFFER_OBJ * bufferObj;
    DRV_USART_CLIENT_OBJ * client;
    USART_MODULE_ID plibID;
    bool status;

    bufferObj = hDriver->queueWrite;
    plibID = hDriver->moduleId;

    /* If this driver is configured for polled mode in an RTOS, the tasks
       routine would be called from another thread. We need to get the driver
       instance mutex before updating the queue. If the driver is configured for
       interrupt mode, then _DRV_USART_TAKE_MUTEX will compile to true */

    if(DRV_USART_INTERRUPT_MODE == false)
    {
        if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
        {
            /* We were able to take the mutex */
        }
        else
        {
            /* The mutex acquisition timed out. Return with an
               invalid handle. This code will not execute
               if there is no RTOS. */
            return;
        }
    }

    /* In this function, the driver checks if there are any buffers in queue. If
       so the buffer is serviced. A buffer that is serviced completely is
       removed from the queue. Start by getting the buffer at the head of the
       queue */

    bufferObj = hDriver->queueRead;

    if(bufferObj != NULL)
    {
        /* The USART driver is configured to generate an interrupt when the FIFO
           is not empty. Additionally the queue is not empty. Which means there
           is work to done in this routine. Read data from the FIFO till either
           the FIFO is empty or till we have read the requested number of bytes.
           */

        while((PLIB_USART_ReceiverDataIsAvailable(plibID))
                && (bufferObj->nCurrentBytes < bufferObj->size ))
        {
            bufferObj->buffer[bufferObj->nCurrentBytes] = PLIB_USART_ReceiverByteReceive(plibID);
            bufferObj->nCurrentBytes ++;
        }

        /* Check if this buffer is done */

        if(bufferObj->nCurrentBytes >= bufferObj->size)
        {
            /* This means the buffer is completed. If there
               is a callback registered with client, then
               call it */

            client = (DRV_USART_CLIENT_OBJ *)bufferObj->hClient;
            if((client->eventHandler != NULL) && (bufferObj->flags & DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD))
            {
                /* Call the event handler. We additionally increment the 
                   interrupt nesting count which lets the driver functions
                   that are called from the event handler know that an
                   interrupt context is active. 
                   */

                hDriver->interruptNestingCount ++;

                client->eventHandler(DRV_USART_BUFFER_EVENT_COMPLETE,
                        (DRV_USART_BUFFER_HANDLE)bufferObj,
                        client->context);

                hDriver->interruptNestingCount --;
            }

            /* Get the next buffer in the queue and deallocate
               this buffer */
            
            hDriver->queueRead = bufferObj->next;
            bufferObj->inUse = false;
            hDriver->queueSizeCurrentRead --;

            if(bufferObj->flags & DRV_USART_BUFFER_OBJ_FLAG_READ_WRITE)
            {
                /* This means we should post the semaphore */
                OSAL_ASSERT(_DRV_USART_SEM_POST(client->semReadDone) == OSAL_RESULT_TRUE,
                        "Unable to post write buffer queue empty semaphore");

            }
        }
    }

    if(hDriver->queueRead == NULL)
    {
        /* The queue is empty. We can disable the interrupt */
        status = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource);
    }

    /* Release the mutex */

    OSAL_ASSERT(_DRV_USART_RELEASE_MUTEX(hDriver->mutexDriverInstance),
                        "Unable to release Hardware Instance Mutex");
}