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


/* usbHcdLib.c - Implements HCD functional API */

/* Copyright 2000 Wind River Systems, Inc. */

/*
Modification history
--------------------
01e,26jan00,rcb  Change  parameter in usbHcdPipeCreate() to
		  and redefined as UINT32.
01d,29nov99,rcb  Remove obsolete function usbHcdBusReset().
		 Increase frame number fields to 32 bits.
01c,23nov99,rcb  Replace bandwidth alloc/release functions with pipe
		 create/destroy functions...generalizes approach for use
		 with OHCI HCD.
01b,07sep99,rcb  Add support for management callback param in attach.
		 Add set-bus-state API.
01a,09jun99,rcb  First.
*/

/*
DESCRIPTION

This file implements the functional interface to the HCD.
*/


/* includes */

#include "usb/usbPlatform.h"

#include "string.h"

#include "usb/usbHcdLib.h"      /* our API */


/* functions */

/***************************************************************************
*
* hrbInit - Initialize an HCD request block
*
* RETURNS: N/A
*/

LOCAL VOID hrbInit (pHRB_HEADER pHrb, pHCD_NEXUS pNexus, UINT16 function, UINT16 totalLen)
{
    memset (pHrb, 0, totalLen);

    if (pNexus != NULL)
        pHrb->handle = pNexus->handle;

    pHrb->function = function;
    pHrb->hrbLength = totalLen;
}


/***************************************************************************
*
* usbHcdAttach - Attach to the HCD
*
* Attempts to connect the caller to the HCD.  The  value is HCD-
* implementation-specific.  Returns an HCD_CLIENT_HANDLE if the HCD was
* able to initialize properly.	If  is not NULL, also returns
* number of buses managed through this nexus.
*
*  is an optional pointer to a routine which should be invoked
* if the HCD detects "management events" (e.g., remote wakeup/resume).
*  is a caller-defined parameter which will be passed to
* the  routine each time it is invoked.
*
* RETURNS: OK, or ERROR if unable to initialize HCD.
*/

STATUS usbHcdAttach (HCD_EXEC_FUNC hcdExecFunc, /* HCD's primary entry point */
                     pVOID param,   /* HCD-specific param */
                     USB_HCD_MNGMT_CALLBACK callback,   /* management callback */
                     pVOID callbackParam,   /* parameter to management callback */
                     pHCD_NEXUS pNexus, /* nexus will be initialized on return */
                     pUINT16 pBusCount)
{
    HRB_ATTACH hrb;
    STATUS s;


    /* Initialize HRB */

    hrbInit (&hrb.header, NULL, HCD_FNC_ATTACH, sizeof (hrb));

    hrb.param = param;
    hrb.mngmtCallback = callback;
    hrb.mngmtCallbackParam = callbackParam;


    /* Execute HRB */

    s = (*hcdExecFunc) ((pVOID) & hrb);


    /* Return results */

    if (pNexus != NULL) {
        pNexus->hcdExecFunc = hcdExecFunc;
        pNexus->handle = hrb.header.handle;
    }

    if (pBusCount != NULL)
        *pBusCount = hrb.busCount;

    return s;
}


/***************************************************************************
*
* usbHcdDetach - Detach from the HCD
*
* Disconnects a caller which has previously attached to an HCD.
*
* RETURNS: OK, or ERROR if unable to shutdown HCD.
*/

STATUS usbHcdDetach (pHCD_NEXUS pNexus  /* client's nexus */
    )
{
    HRB_DETACH hrb;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_DETACH, sizeof (hrb));


    /* Execute HRB */

    return (*pNexus->hcdExecFunc) ((pVOID) & hrb);
}


/***************************************************************************
*
* usbHcdSetBusState - sets bus suspend/resume state
*
* Sets the state for  no as specified in .  
* is a bit mask.  Typically, the caller will set USB_BUS_SUSPEND or
* USB_BUS_RESUME to suspend or resume the indicated bus.
*
* RETURNS: OK, or ERROR if unable to place bus in specified state
*/

STATUS usbHcdSetBusState (pHCD_NEXUS pNexus,    /* client's nexus */
                          UINT16 busNo, /* bus number */
                          UINT16 busState   /* desired bus state */
    )
{
    HRB_SET_BUS_STATE hrb;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_SET_BUS_STATE, sizeof (hrb));

    hrb.busNo = busNo;
    hrb.busState = busState;


    /* Execute HRB */

    return (*pNexus->hcdExecFunc) ((pVOID) & hrb);
}


/***************************************************************************
*
* usbHcdCurrentFrameGet - Returns current frame number for a bus
*
* Returns the current  and the frame window, 
* for the specified bus.
*
* RETURNS: OK, or ERROR if unable to retrieve current frame number.
*/

STATUS usbHcdCurrentFrameGet (pHCD_NEXUS pNexus,    /* client's nexus */
                              UINT16 busNo, /* bus number */
                              pUINT32 pFrameNo, /* current frame number */
                              pUINT32 pFrameWindow  /* size of frame window */
    )
{
    HRB_CURRENT_FRAME_GET hrb;
    STATUS s;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_CURRENT_FRAME_GET, sizeof (hrb));

    hrb.busNo = busNo;


    /* Execute HRB */

    s = (*pNexus->hcdExecFunc) ((pVOID) & hrb);


    /* return results */

    if (pFrameNo != NULL)
        *pFrameNo = hrb.frameNo;

    if (pFrameWindow != NULL)
        *pFrameWindow = hrb.frameWindow;

    return s;
}


/***************************************************************************
*
* usbHcdIrpSubmit - Submits an IRP to the HCD for execution
*
* This function passes the  to the HCD for scheduling.  The function
* returns as soon as the HCD has queued/scheduled the IRP.  The 
* must include a non-NULL  which will be invoked upon IRP
* completion.
*
* RETURNS: OK, or ERROR if unable to submit IRP for transfer.
*/

STATUS usbHcdIrpSubmit (pHCD_NEXUS pNexus,  /* client's nexus */
                        HCD_PIPE_HANDLE pipeHandle, /* pipe to which IRP is directed */
                        pUSB_IRP pIrp   /* IRP to be executed */
    )
{
    HRB_IRP_SUBMIT hrb;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_IRP_SUBMIT, sizeof (hrb));

    hrb.pipeHandle = pipeHandle;
    hrb.pIrp = pIrp;


    /* Execute HRB */

    return (*pNexus->hcdExecFunc) ((pVOID) & hrb);
}


/***************************************************************************
*
* usbHcdIrpCancel - Requests the HCD to cancel a pending IRP
*
* This function requests the HCD to cancel the specified .  If
* the IRP can be canceled before it completes execution normally, its 
* result will be set to S_usbHcdLib_IRP_CANCELED and the IRPs callback
* will be invoked.
*
* There is no guarantee that an IRP, once submitted to the HCD, can be
* canceled before it otherwise completes normally (or times out).
*
* RETURNS: OK, or ERROR if unable to cancel transfer.
*/


STATUS usbHcdIrpCancel (pHCD_NEXUS pNexus,  /* client's nexus */
                        pUSB_IRP pIrp   /* IRP to be canceled */
    )
{
    HRB_IRP_CANCEL hrb;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_IRP_CANCEL, sizeof (hrb));

    hrb.pIrp = pIrp;


    /* Execute HRB */

    return (*pNexus->hcdExecFunc) ((pVOID) & hrb);
}


/***************************************************************************
*
* usbHcdPipeCreate - create a pipe and calculate / reserve bus bandwidth
*
* The USBD calls this function to notify the HCD that it is attempting to
* create a new pipe.  The USBD passes the type of pipe in .
*
* If the pipe is an interrupt or isochronous pipe, the HCD calculates the 
* amount of time a transfer of a given number of bytes will require on the 
* bus - measured in nanoseconds (10E-9 seconds).  The formulas used here are 
* taken from Section 5.9.3 of Revision 1.1 of the USB spec.
*
* If enough bus bandwidth is available, then that amount of bandwidth will
* be reserved by the HCD.  Reserved bandwidth must later be released using 
* usbHcdPipeDestroy().
*
* , , and  should describe the characteristics
* of the pipe/transfer as USB_XFRTYPE_xxxx, USB_DIR_xxxx, and USB_SPEED_xxxx,
* repsectively.   is the size of packets to be used.
*
* For interrupt pipes,  is the total number of bytes which will 
* be sent each frame.  For isochronous pipes,  is the number of
* bytes per second.   should be 0 for control and bulk pipes.
*
* The worst-case transfer time is returned in .
*
* The HCD will return an HCD_PIPE_HANDLE in .  The USBD will use
* this HCD_PIPE_HANDLE to identify the pipe in the future.  
*
* RETURNS: OK, or ERROR if unable to reserve bandwdith.
*/

STATUS usbHcdPipeCreate (pHCD_NEXUS pNexus, /* client's nexus */
                         UINT16 busNo,  /* bus number for IRP */
                         UINT16 busAddress, /* bus address of USB device */
                         UINT16 endpoint,   /* endpoint on device */
                         UINT16 transferType,   /* transfer type */
                         UINT16 direction,  /* pipe/transfer direction */
                         UINT16 speed,  /* transfer speed */
                         UINT16 maxPacketSize,  /* packet size */
                         UINT32 bandwidth,  /* bandwidth required by pipe */
                         UINT16 interval,   /* service interval */
                         pUINT32 pTime, /* calculated packet time on return */
                         pHCD_PIPE_HANDLE pPipeHandle   /* HCD pipe handle */
    )
{
    HRB_PIPE_CREATE hrb;
    STATUS s;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_PIPE_CREATE, sizeof (hrb));

    hrb.busNo = busNo;
    hrb.busAddress = busAddress;
    hrb.endpoint = endpoint;
    hrb.transferType = transferType;
    hrb.direction = direction;
    hrb.speed = speed;
    hrb.maxPacketSize = maxPacketSize;
    hrb.bandwidth = bandwidth;
    hrb.interval = interval;


    /* Execute HRB */

    s = (*pNexus->hcdExecFunc) ((pVOID) & hrb);


    /* return results */

    if (pTime != NULL)
        *pTime = hrb.time;

    if (pPipeHandle != NULL)
        *pPipeHandle = hrb.pipeHandle;

    return s;
}


/***************************************************************************
*
* usbHcdPipeDestroy - destroys pipe and releases previously allocated bandwidth
*
* Destroys the pipe identified by  and releases any bandwidth used
* by the pipe.	
*
* RETURNS: OK, or ERROR if HCD fails to destroy pipe.
*/

STATUS usbHcdPipeDestroy (pHCD_NEXUS pNexus,    /* client's nexus */
                          HCD_PIPE_HANDLE pipeHandle    /* pipe to be destroyed */
    )
{
    HRB_PIPE_DESTROY hrb;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_PIPE_DESTROY, sizeof (hrb));
    hrb.pipeHandle = pipeHandle;


    /* Execute HRB */

    return (*pNexus->hcdExecFunc) ((pVOID) & hrb);
}


/***************************************************************************
*
* usbHcdPipeModify - modify characteristics of an existing pipe
*
* Two characteristics of a pipe, the device's USB bus address and the 
* maximum packet size, may change after a pipe is first created.  Typically,
* this will happen only with the default control pipe for a given device,
* which must be created before issuing SET_ADDRESS to the device and before
* reading the device descriptor to determine the maximum packet size supported
* by the default control endpoint.  The USBD will typically use this function
* to update either the  or the  for the indicated
* .  If either  or  is 0, then the
* corresponding pipe attribute remains unchanged.  
*
* RETURNS: OK, or ERROR if HCD fails to modify pipe
*/

STATUS usbHcdPipeModify (pHCD_NEXUS pNexus, /* client's nexus */
                         HCD_PIPE_HANDLE pipeHandle,    /* pipe to be modified */
                         UINT16 busAddress, /* new bus address or 0 */
                         UINT16 maxPacketSize   /* new max packet size or 0 */
    )
{
    HRB_PIPE_MODIFY hrb;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_PIPE_MODIFY, sizeof (hrb));
    hrb.pipeHandle = pipeHandle;
    hrb.busAddress = busAddress;
    hrb.maxPacketSize = maxPacketSize;


    /* Execute HRB */

    return (*pNexus->hcdExecFunc) ((pVOID) & hrb);
}


/***************************************************************************
*
* usbHcdSofIntervalGet - retrieves SOF interval for a bus
*
* Returns the SOF interval for  in .  The SOF 
* interval is expressed in terms of high-speed bit times, and is typically
* close to 12,000.
*
* RETURNS: OK, or ERROR if HCD failed to retrieve SOF interval
*/

STATUS usbHcdSofIntervalGet (pHCD_NEXUS pNexus, /* client's nexus */
                             UINT16 busNo,  /* bus number */
                             pUINT16 pSofInterval   /* bfr to receive SOF interval */
    )
{
    HRB_SOF_INTERVAL_GET_SET hrb;
    STATUS s;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_SOF_INTERVAL_GET, sizeof (hrb));
    hrb.busNo = busNo;


    /* Execute HRB */

    s = (*pNexus->hcdExecFunc) ((pVOID) & hrb);


    /* return results */

    if (pSofInterval != NULL)
        *pSofInterval = hrb.sofInterval;

    return s;
}


/***************************************************************************
*
* usbHcdSofIntervalSet - sets SOF interval for a bus
*
* Sets the SOF interval for  to .  
* must express the new SOF interval in terms of high-speed bit times, and
* should be in the neighborhood of 12,000.  Certain HCD implementations
* may impose narrower or wider limits on the allowable .
*
* RETURNS: OK, or ERROR if HCD failed to set SOF interval.
*/

STATUS usbHcdSofIntervalSet (pHCD_NEXUS pNexus, /* client's nexus */
                             UINT16 busNo,  /* bus number */
                             UINT16 sofInterval /* new SOF interval */
    )
{
    HRB_SOF_INTERVAL_GET_SET hrb;


    /* Initialize HRB */

    hrbInit (&hrb.header, pNexus, HCD_FNC_SOF_INTERVAL_SET, sizeof (hrb));
    hrb.busNo = busNo;
    hrb.sofInterval = sofInterval;


    /* Execute HRB */

    return (*pNexus->hcdExecFunc) ((pVOID) & hrb);
}


/* End of file. */