www.pudn.com > vxworks_usb.rar > usbQueueLib.c


/* usbQueueLib.c - O/S-independent queue functions */

/* Copyright 2000 Wind River Systems, Inc. */
/*
Modification history
--------------------
01a,07jun99,rcb  First.
*/

/*
DESCRIPTION

This file contains a generic implementation of O/S-independent queue
functions which are built on top of the the ossLib library's mutex
and semaphore functions.

The caller creates a queue of depth "n" by calling usbQueueCreate() and
receives a QUEUE_HANDLE in response.  The QUEUE_HANDLE must be used in
all subsequent calls to usbQueuePut(), usbQueueGet(), and usbQueueDestroy().

Each entry on a queue is described by a USB_QUEUE structure which contains
, , and  fields.  The values of these fields are
completely arbitrary and may be used in any way desired by the calling
application.
*/

/* includes */

#include "usb/usbPlatform.h"

#include "string.h"

#include "usb/ossLib.h"
#include "usb/usbQueueLib.h"    /* our API */


/* typedefs */

/* Internal queue control structure. */

typedef struct usb_queue
{
    UINT16 max;                 /* Number of USB_MESSAGE entries allocated */
    /* in messages array */
    UINT16 in;                  /* Index of the next available message slot */
    UINT16 out;                 /* Index to the next message to be retrieved */
    SEM_HANDLE inUse;           /* Count of messages currently in queue */
    SEM_HANDLE empty;           /* Count of empty message slots in queue */
    MUTEX_HANDLE mutex;         /* The handle of the mutex we use to gain */
    /* temporary control of the OSS_QUEUE struct */
    USB_MESSAGE messages[1];    /* Pointer to memory allocated for msg queue */
}
USB_QUEUE, *pUSB_QUEUE;


/* functions */

/***************************************************************************
*
* usbQueueCreate - Creates a O/S-independent queue structure
*
* This function creates a queue which can accomodate a number of 
* USB_MESSAGE entries according to the  parameter.  Returns the
* max = depth;


    /* Allocate queue control resources. */

    if (OSS_SEM_CREATE (depth, 0, &pQueue->inUse) != OK ||
        OSS_SEM_CREATE (depth, depth, &pQueue->empty) != OK ||
        OSS_MUTEX_CREATE (&pQueue->mutex) != OK) {
        usbQueueDestroy ((QUEUE_HANDLE) pQueue);
        return ossStatus (S_usbQueueLib_OUT_OF_RESOURCES);
    }

    *pQueueHandle = (QUEUE_HANDLE) pQueue;
    return OK;
}


/***************************************************************************
*
* usbQueueDestroy - Destroys a queue
*
* This function destroys a queue created by calling usbQueueCreate().
*
* RETURNS: OK or ERROR.
*
* ERRNO:
*  S_usbQueueLib_BAD_HANDLE
*/

STATUS usbQueueDestroy (QUEUE_HANDLE queueHandle    /* Hnadle of queue to destroy */
    )
{
    pUSB_QUEUE pQueue = (pUSB_QUEUE) queueHandle;


    /* Qualify the queue handle. */

    if (pQueue == NULL)
        return ossStatus (S_usbQueueLib_BAD_HANDLE);


    /* Release resources and memory associated with the queue. */

    if (pQueue->inUse)
        OSS_SEM_DESTROY (pQueue->inUse);

    if (pQueue->empty)
        OSS_SEM_DESTROY (pQueue->empty);

    if (pQueue->mutex)
        OSS_SEM_DESTROY (pQueue->mutex);

    OSS_FREE (pQueue);

    return OK;
}


/***************************************************************************
*
* usbQueuePut - Puts a message onto a queue
*
* Places the specified , , and  onto .
* This function will only block if the specified queue is full.  If the 
* queue is full,  specifies the blocking behavior.  OSS_BLOCK
* blocks indefinitely.	OSS_DONT_BLOCK does not block and returns an error
* if the queue is full.  Other values of  are interpreted as
* a count of milliseconds to block before declaring a failure.
*
* RETURNS: OK or ERROR
*
* ERRNO:
*  S_usbQueueLib_BAD_HANDLE
*  S_usbQueueLib_Q_NOT_AVAILABLE
*/

STATUS usbQueuePut (QUEUE_HANDLE queueHandle,   /* queue handle */
                    UINT16 msg, /* app-specific message */
                    UINT16 wParam,  /* app-specific parameter */
                    UINT32 lParam,  /* app-specific parameter */
                    UINT32 blockFlag    /* specifies blocking action */
    )
{
    pUSB_QUEUE pQueue = (pUSB_QUEUE) queueHandle;


    /* Qualify the queue handle. */

    if (pQueue == NULL)
        return ossStatus (S_usbQueueLib_BAD_HANDLE);


    /* Wait for space to become available in the queue */

    if ((OSS_SEM_TAKE (pQueue->empty, blockFlag)) != OK) {
        return ossStatus (S_usbQueueLib_Q_NOT_AVAILABLE);
    } else {

        /* Take the queue mutex before attempting to update the queue. */

        if ((OSS_MUTEX_TAKE (pQueue->mutex, OSS_BLOCK)) != OK) {
            return ossStatus (S_usbQueueLib_Q_NOT_AVAILABLE);
        } else {

            /* Add an entry to the queue. */

            pQueue->messages[pQueue->in].msg = msg;
            pQueue->messages[pQueue->in].wParam = wParam;
            pQueue->messages[pQueue->in].lParam = lParam;

            if (++pQueue->in == pQueue->max)
                pQueue->in = 0;

            OSS_SEM_GIVE (pQueue->inUse);

            OSS_MUTEX_RELEASE (pQueue->mutex);
        }
    }

    return OK;
}


/***************************************************************************
*
* usbQueueGet - Retrieves a message from a queue
*
* Retrieves a message from the specified  and stores it in
* .  If the queue is empty,  specifies the blocking
* behavior.  OSS_BLOCK blocks indefinitely.  OSS_DONT_BLOCK does not block
* and returns an error immediately if the queue is empty.  Other values of
*  are interpreted as a count of milliseconds to block before
* declaring a failure.
*
* RETURNS: OK or ERROR
* 
* ERRNO:
*  S_usbQueueLib_BAD_HANDLE
*  S_usbQueueLib_Q_NOT_AVAILABLE
*/

STATUS usbQueueGet (QUEUE_HANDLE queueHandle,   /* queue handle */
                    pUSB_MESSAGE pMsg,  /* USB_MESSAGE to receive msg */
                    UINT32 blockFlag    /* specifies blocking action */
    )
{
    pUSB_QUEUE pQueue = (pUSB_QUEUE) queueHandle;


    /* Qualify the queue handle and msg parameters. */

    if (pQueue == NULL)
        return ossStatus (S_usbQueueLib_BAD_HANDLE);

    if (pMsg == NULL)
        return ossStatus (S_usbQueueLib_BAD_PARAMETER);


    /* Wait for a message to arrive in the queue before proceeding */

    if ((OSS_SEM_TAKE (pQueue->inUse, blockFlag)) != OK) {
        return ossStatus (S_usbQueueLib_Q_NOT_AVAILABLE);
    } else {

        /* Take the queue mutex before attempting to update the queue. */

        if ((OSS_MUTEX_TAKE (pQueue->mutex, OSS_BLOCK)) != OK) {
            return ossStatus (S_usbQueueLib_Q_NOT_AVAILABLE);
        } else {

            /* Take an entry off the queue. */

            memcpy (pMsg, &pQueue->messages[pQueue->out], sizeof (USB_MESSAGE));

            if (++pQueue->out == pQueue->max)
                pQueue->out = 0;

            OSS_SEM_GIVE (pQueue->empty);

            OSS_MUTEX_RELEASE (pQueue->mutex);
        }
    }

    return OK;
}


/* End of file */