📄 usbdlib.c
字号:
* each endpoint in its configuration descriptors. The client will typically * read these descriptors using the USBD Configuration Functions and then * parse the descriptors to retrieve the appropriate maximum payload value.* * <bandwidth> specifies the bandwidth required for this pipe. For control* and bulk pipes, this parameter should be 0. For interrupt pipes, this* parameter should express the number of bytes per frame to be transferred.* for isochronous pipes, this parameter should express the number of bytes* per second to be transferred.** <serviceInterval> specifies the maximum latency for the pipe in * milliseconds. So, if a pipe needs to be serviced, for example, at least * every 20 milliseconds, then the <serviceInterval> value should be 20. The * <serviceInterval> parameter is required only for interrupt pipes. For * other types of pipes, <serviceInterval> should be 0.** If the USBD succeeds in creating the pipe it returns a pipe handle in * <pPipeHandle>. The client must use the pipe handle to identify the pipe * in subsequent calls to the USBD Transfer Functions. If there is * insufficient bus bandwidth available to create the pipe (as might happen * for an isochronous or interrupt pipe), then the USBD will return an error * and a NULL handle in <pPipeHandle>.** RETURNS: OK, or ERROR if pipe could not be create*/STATUS usbdPipeCreate (USBD_CLIENT_HANDLE clientHandle, /* Client handle */ USBD_NODE_ID nodeId, /* Node Id of device/hub */ UINT16 endpoint, /* Endpoint number */ UINT16 configuration, /* config w/which pipe associated */ UINT16 interface, /* interface w/which pipe associated */ UINT16 transferType, /* Type of transfer: control, bulk... */ UINT16 direction, /* Specifies IN or OUT endpoint */ UINT16 maxPayload, /* Maximum data payload per packet */ UINT32 bandwidth, /* Bandwidth required for pipe */ UINT16 serviceInterval, /* Required service interval */ pUSBD_PIPE_HANDLE pPipeHandle /* pipe handle returned by USBD */ ){ URB_PIPE_CREATE urb; STATUS s; /* Initalize URB */ urbInit (&urb.header, clientHandle, USBD_FNC_PIPE_CREATE, NULL, NULL, sizeof (urb)); urb.nodeId = nodeId; urb.endpoint = endpoint; urb.configuration = configuration; urb.interface = interface; urb.transferType = transferType; urb.direction = direction; urb.maxPayload = maxPayload; urb.bandwidth = bandwidth; urb.serviceInterval = serviceInterval; /* Execute URB */ s = urbExecBlock (&urb.header); /* Return result */ if (pPipeHandle != NULL) *pPipeHandle = urb.pipeHandle; return s;}/***************************************************************************** usbdPipeDestroy - Destroys a USB data transfer pipe** This function destroys a pipe previous created by calling usbdPipeCreate(). * The caller must pass the <pipeHandle> originally returned by usbdPipeCreate().** If there are any outstanding transfer requests for the pipe, the USBD will * abort those transfers prior to destroying the pipe. ** RETURNS: OK, or ERROR if unable to destroy pipe.*/STATUS usbdPipeDestroy (USBD_CLIENT_HANDLE clientHandle, /* Client handle */ USBD_PIPE_HANDLE pipeHandle /* pipe handle */ ){ URB_PIPE_DESTROY urb; /* Initalize URB */ urbInit (&urb.header, clientHandle, USBD_FNC_PIPE_DESTROY, NULL, NULL, sizeof (urb)); urb.pipeHandle = pipeHandle; /* Execute URB */ return urbExecBlock (&urb.header);}/***************************************************************************** usbdTransfer - Initiates a transfer on a USB pipe** A client uses this function to initiate an transfer on the pipe indicated * by <pipeHandle>. The transfer is described by an IRP, or I/O request * packet, which must be allocated and initialized by the caller prior to * invoking usbdTransfer().** The USB_IRP structure is defined in usb.h as:** .CS* typedef struct usb_bfr_list* {* UINT16 pid;* pUINT8 pBfr;* UINT16 bfrLen;* UINT16 actLen;* } USB_BFR_LIST;** typedef struct usb_irp* {* LINK usbdLink; // used by USBD* pVOID usbdPtr; // used by USBD* LINK hcdLink; // used by HCD* pVOID hcdPtr; // used by HCD* pVOID userPtr;* UINT16 irpLen;* int result; // returned by USBD/HCD* IRP_CALLBACK usbdCallback; // used by USBD* IRP_CALLBACK userCallback;* UINT16 dataToggle; // filled in by USBD* UINT16 flags; * UINT32 timeout; // defaults to 5 seconds if zero* UINT16 startFrame;* UINT16 transferLen;* UINT16 dataBlockSize;* UINT16 bfrCount;* USB_BFR_LIST bfrList [1];* } USB_IRP, *pUSB_IRP;* .CE** The length of the USB_IRP structure must be stored in <irpLen> and varies * depending on the number of <bfrList> elements allocated at the end of the * structure. By default, the default structure contains a single <bfrList>* element, but clients may allocate a longer structure to accommodate a larger * number of <bfrList> elements. ** <flags> define additional transfer options. The currently defined flags are:** .IP "USB_FLAG_SHORT_OK"* Treats receive (IN) data underrun as OK.* .IP "USB_FLAG_SHORT_FAIL"* Treats receive (IN) data underrun as error.* .IP "USB_FLAG_ISO_ASAP"* Start an isochronous transfer immediately.** When the USB is transferring data from a device to the host the data may * "underrun". That is, the device may transmit less data than anticipated by * the host. This may or may not indicate an error condition depending on the * design of the device. For many devices, the underrun is completely normal * and indicates the end of data stream from the device. For other devices, * the underrun indicates a transfer failure. By default, the USBD and * underlying USB HCD (Host Controller Driver) treat underrun as the end-of-data * indicator and do not declare an error. If the USB_FLAG_SHORT_FAIL flag is * set, then the USBD/HCD will instead treat underrun as an error condition.** For isochronous transfers the USB_FLAG_ISO_ASAP specifies that the * isochronous transfer should begin as soon as possible. If USB_FLAG_ISO_ASAP* is not specified, then <startFrame> must specify the starting frame number * for the transfer. The usbdCurrentFrameGet() function allows a client to* retrieve the current frame number and a value called the frame scheduling * window for the underlying USB host controller. The frame window specifies * the maximum number of frames into the future (relative to the current frame * number) which may be specified by <startFrame>. <startFrame> should be * specified only for isochronous transfers.** <dataBlockSize> may also be specified for isochronous transfers. If non-0,* the <dataBlockSize> defines the granularity of isochronous data being sent.* When the underlying Host Controller Driver (HCD) breaks up the transfer into* individual frames, it will ensure that the amount of data transferred in * each frame is a multiple of this value. ** <timeout> specifies the IRP timeout in milliseconds. If the caller passes* a value of zero, then the USBD sets a default timeout of USB_TIMEOUT_DEFAULT.* If no timeout is desired, then <timeout> should be set to USB_TIMEOUT_NONE.* Timeouts apply only to control and bulk transfers. Isochronous and* interrupt transfers do not time out.** <bfrList> is an array of buffer descriptors which describe data buffers to * be associated with this IRP. If more than the one <bfrList> element is * required then the caller must allocate the IRP by calculating the size as ** .CS* irpLen = sizeof (USB_IRP) + (sizeof (USB_BFR_DESCR) * (bfrCount - 1))* .CE** <transferLen> must be the total length of data to be transferred. In other * words, transferLen is the sum of all <bfrLen> entries in the <bfrList>.** <pid> specifies the packet type to use for the indicated buffer and is* specified as USB_PID_xxxx.** The IRP <userCallback> routine must point to a client-supplied IRP_CALLBACK* routine. The usbdTransfer() function returns as soon as the IRP has been* successfully enqueued. If there is a failure in delivering the IRP to the* HCD, then usbdTransfer() returns an error. The actual result of the IRP* should be checked after the <userCallback> routine has been invoked.** RETURNS: OK, or ERROR if unable to submit IRP for transfer.*/STATUS usbdTransfer (USBD_CLIENT_HANDLE clientHandle, /* Client handle */ USBD_PIPE_HANDLE pipeHandle, /* Pipe handle */ pUSB_IRP pIrp /* ptr to I/O request packet */ ){ URB_TRANSFER urb; /* Initalize URB */ urbInit (&urb.header, clientHandle, USBD_FNC_TRANSFER, NULL, NULL, sizeof (urb)); urb.pipeHandle = pipeHandle; urb.pIrp = pIrp; /* Execute URB */ return urbExecBlock (&urb.header);}/***************************************************************************** usbdTransferAbort - Aborts a transfer** This function aborts an IRP which was previously submitted through* a call to usbdTransfer(). ** RETURNS: OK, or ERROR if unable to abort transfer.*/STATUS usbdTransferAbort (USBD_CLIENT_HANDLE clientHandle, /* Client handle */ USBD_PIPE_HANDLE pipeHandle, /* Pipe handle */ pUSB_IRP pIrp /* ptr to I/O to abort */ ){ URB_TRANSFER urb; /* Initalize URB */ urbInit (&urb.header, clientHandle, USBD_FNC_TRANSFER_ABORT, NULL, NULL, sizeof (urb)); urb.pipeHandle = pipeHandle; urb.pIrp = pIrp; /* Execute URB */ return urbExecBlock (&urb.header);}/***************************************************************************** usbdSynchFrameGet - Returns a device's isochronous synch. frame** It is sometimes necessary for clients to re-synchronize with devices when * the two are exchanging data isochronously. This function allows a client* to query a reference frame number maintained by the device. Please refer * to the USB Specification for more detail.** <nodeId> specifies the node to query and <endpoint> specifies the endpoint * on that device. Upon return the device抯 frame number for the specified * endpoint is returned in <pFrameNo>.** RETURNS: OK, or ERROR if unable to retrieve synch. frame.*/STATUS usbdSynchFrameGet (USBD_CLIENT_HANDLE clientHandle, /* Client Handle */ USBD_NODE_ID nodeId, /* Node Id of device/hub */ UINT16 endpoint, /* Endpoint to be queried */ pUINT16 pFrameNo /* Frame number returned by device */ ){ URB_SYNCH_FRAME_GET urb; STATUS s; /* Initalize URB */ urbInit (&urb.header, clientHandle, USBD_FNC_SYNCH_FRAME_GET, NULL, NULL, sizeof (urb)); urb.nodeId = nodeId; urb.endpoint = endpoint; /* Execute URB */ s = urbExecBlock (&urb.header); /* Return result */ if (pFrameNo != NULL) *pFrameNo = urb.frameNo; return s;}/***************************************************************************** usbdCurrentFrameGet - Returns the current frame number for a USB** It is sometimes necessary for clients to retrieve the current USB frame * number for a specified host controller. This function allows a client to * retrieve the current USB frame number for the host controller to which* <nodeId> is connected. Upon return, the current frame number is stored * in <pFrameNo>.** If <pFrameWindow> is not NULL, the USBD will also return the maximum frame * scheduling window for the indicated USB host controller. The frame * scheduling window is essentially the number of unique frame numbers * tracked by the USB host controller. Most USB host controllers maintain an * internal frame count which is a 10- or 11-bit number, allowing them to * track typically 1024 or 2048 unique frames. When starting an isochronous * transfer, a client may wish to specify that the transfer will begin in a * specific USB frame. For the given USB host controller, the starting frame * number can be no more than <frameWindow> frames from the current <frameNo>.** Note: The USBD is capable of simultaneously managing multiple USB host * controllers, each of which operates independently. Therefore, it is * important that the client specify the correct <nodeId> when retrieving the * current frame number. Typically, a client will be interested in the * current frame number for the host controller to which a specific device is * attached.** RETURNS: OK, or ERROR if unable to retrieve current frame number.*/STATUS usbdCurrentFrameGet (USBD_CLIENT_HANDLE clientHandle, /* Client handle */ USBD_NODE_ID nodeId, /* Node Id of node on desired USB */ pUINT32 pFrameNo, /* bfr to receive current frame no. */ pUINT32 pFrameWindow /* bfr to receive frame window */ ){ URB_CURRENT_FRAME_GET urb; STATUS s; /* Initalize URB */ urbInit (&urb.header, clientHandle, USBD_FNC_CURRENT_FRAME_GET, NULL, NULL, sizeof (urb)); urb.nodeId = nodeId; /* Execute URB */ s = urbExecBlock (&urb.header); /* Return result */ if (pFrameNo != NULL) *pFrameNo = urb.frameNo; if (pFrameWindow != NULL) *pFrameWindow = urb.frameWindow; return s;}/***************************************************************************** usbdSofMasterTake - Takes SOF master ownership** A client which is performing isochronous transfers may need to adjust* the USB frame time by a small amount in order to syn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -