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 Changeparameter 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. */