📄 c-hoststack.html
字号:
<dl class="margin"><dd><p class="Body"><a name="85524"></a>You must decide when to attach HCDs to the USBD and when to detach them (if ever). Typically, USBD clients, such as USB class drivers, are not responsible for attaching HCDs to the USBD.</p><dd><p class="Body"><a name="85525"></a>When an HCD is attached to the USBD, the caller passes the HCD's <i class="term">execution entry point</i> (of the form <b class="symbol_UC">HCD_EXEC_FUNC</b>) and an HCD-defined parameter (the HCD attachment parameter) to the <b class="routine">usbdHcdAttach( )</b> routine. The USBD in turn invokes the HCD's execution entry point with an <b class="symbol_UC">HCD_FNC_ATTACH</b> service request, passing it the same HCD attachment parameter provided by the caller. Use of this HCD-defined parameter can vary; however, both HCDs provided by Wind River use the parameter in the same way. For the UHCI and OHCI HCDs provided by Wind River, the HCD attachment parameter is a pointer to a structure of type <b class="symbol_UC">PCI_CFG_HEADER</b> (defined in <b class="file">pciConstants.h</b>). The structure has been initialized with the PCI configuration header for a UHCI or OCHI host controller. The HCD uses the information in this structure to locate and manage the specified host controller.</p><dd><p class="Body"><a name="85526"></a>Typically, the caller obtains the PCI configuration header for the desired host controller by calling the <b class="routine">usbPciClassFind( )</b> and <b class="routine">usbPciConfigHeaderGet( )</b> routines in <b class="library">usbPciLib</b> (that is, in various <b class="library">stubUsb</b><i class="textVariable">Arch</i><b class="library">PciLib.c</b> files). If more than one UHCI or OHCI host controller is to be attached to the USBD, these routines should be used repeatedly to obtain the <b class="symbol_UC">PCI_CFG_HEADER</b> for each host controller, and <b class="routine">usbdHcdAttach( )</b> should be invoked once for each host controller so identified.</p><dd><p class="Body"><a name="85527"></a>The following code fragment demonstrates how to attach a UHCI host controller to the USBD:</p></dl><dl class="margin"><dd><font color="0000a0"><pre class="Code"><a name="85528"></a> UINT8 busNo; UINT8 deviceNo; UINT8 funcNo; PCI_CFG_HEADER pciCfgHdr; /* PCI_CFG_HEADER defined in pciConstants.h */ GENERIC_HANDLE uhciAttachToken; /* GENERIC_HANDLE defined in usbHandleLib.h */ /* Locate the first (0th) UHCI controller. UHCI_CLASS, etc., are defined * in usbUhci.h. The functions usbPciClassFind() and * usbPciConfigHeaderGet() are exported by usbPciLib. */ if (!usbPciClassFind (UHCI_CLASS, UHCI_SUBCLASS, UHCI_PGMIF, 0, &busNo, &deviceNo, &funcNo)) { /* No UHCI controller was found. */ return ERROR; } usbPciConfigHeaderGet (busNo, deviceNo, funcNo, &pciCfgHdr); /* Attach the UHCI HCD to the USBD. The function usbHcdUhciExec() is * exported by usbHcdUhciLib. */ if (usbdHcdAttach (usbHcdUhciExec, &pciCfgHdr, &uhciAttachToken) != OK) { /* USBD failed to attach to UHCI HCD. */ return ERROR; } /* Attachment is complete. */</pre></font></dl><dl class="margin"><dd><p class="Body"><a name="85529"></a>Detaching an HCD from the USBD is even simpler, as demonstrated in the following code fragment:</p></dl><dl class="margin"><dd><font color="0000a0"><pre class="Code"><a name="85530"></a> /* Detach the UHCI HCD from the HCD. */ usbdHcdDetach (uhciAttachToken); /* Detach is complete! */</pre></font></dl></dl><dl class="margin"><dd><p class="table"><table border="0" cellpadding="2" cellspacing="0"><tr valign="top"><td colspan=1 rowspan=1></td><td><hr></td></tr><tr valign="top"><td><img border="0" alt="*" src="icons/caution.gif"> </td><td colspan=1 rowspan=1><div class="CalloutCell"><a name="85535"></a><b class="symbol_UC"><font face="Helvetica, sans-serif" size="-1" class="sans">CAUTION: </font></b>While the USBD and Wind River HCDs are designed to support the dynamic attachment and detachment of HCDs, certain Wind River BSPs may not support the disconnection of the USB HCD from the underlying PCI interrupt vector, which is essential to the detaching process. If the vector is subsequently re-enabled, the system may attempt to execute a stale interrupt service routine and will fault.</div></td></tr><tr valign="top"><td colspan=1 rowspan=1></td><td colspan=1 rowspan=1><hr></td></tr><tr valign="middle"><td colspan="20"></td></tr></table></p></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H4"><i><a name="85541"></a>Order of Initialization</i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="85542"></a>The <b class="routine">usbdInitialize( )</b> routine must be called before all other USBD functions, including <b class="routine">usbdHcdAttach( )</b>. However, it is not necessary that all USBD clients call <b class="routine">usbdInitialize( )</b> before one or more HCDs have been attached to the USBD. The following two scenarios for initialization sequences are both acceptable:</p></dl></dl><dl class="margin"><dd><font face="Helvetica, sans-serif" size="-1" class="sans"><h5 class="HU"><i><a name="85543"></a>Scenario #1: Traditional "boot time" initialization</i></h5></font><dl class="margin"><dl class="margin"><dd><p class="Indent"><a name="85544"></a></p></dl></dl><dl class="margin"><dd><ol class="List"><li value="1"><a name="85545"></a>Boot code calls <b class="routine">usbdInitialize( )</b>.</li></ol><dd><ol class="List"><li value="2"><a name="85546"></a>Boot code calls <b class="routine">usbPciClassFind( )</b> to locate a USB host controller.</li></ol><dd><ol class="List"><li value="3"><a name="85547"></a>Boot code calls <b class="routine">usbPciConfigHeaderGet( )</b> to read the host controller's configuration header.</li></ol><dd><ol class="List"><li value="4"><a name="85548"></a>Boot code calls <b class="routine">usbdHcdAttach( )</b> to attach the HCD for the identified host controller.</li></ol><dd><ol class="List"><li value="5"><a name="85549"></a>Boot code calls the USB class driver initialization entry point.</li></ol><dd><ol class="List"><li value="6"><a name="85550"></a>The USB class driver calls <b class="routine">usbdInitialize( )</b>.</li></ol><dl class="margin"><dd><p class="Indent"><a name="85551"></a></p></dl></dl><dd><font face="Helvetica, sans-serif" size="-1" class="sans"><h5 class="HU"><i><a name="85552"></a>Scenario #2: "Hotswap"-driven initialization</i></h5></font><dl class="margin"><dd><ol class="List"><li value="1"><a name="85553"></a>Boot code calls the USB class driver initialization entry point.</li></ol><dd><ol class="List"><li value="2"><a name="85554"></a>The USB class driver calls <b class="routine">usbdInitialize( )</b>.</li></ol><dl class="margin"><dd><p class="Indent"><a name="85555"></a></p></dl><dd><ol class="List"><li value="3"><a name="85556"></a>Hotswap code identifies the presence or insertion of the USB host controller.</li></ol><dd><ol class="List"><li value="4"><a name="85557"></a>Hotswap code calls <b class="routine">usbdInitialize( )</b>.</li></ol><dd><ol class="List"><li value="5"><a name="85558"></a>Hotswap code calls <b class="routine">usbPciConfigHeaderGet( )</b> to read the host controller's configuration header.</li></ol><dd><ol class="List"><li value="6"><a name="85559"></a>Hotswap code calls <b class="routine">usbdHcdAttach( )</b> to attach the HCD for the identified host controller.</li></ol><dl class="margin"><dd><p class="Indent"><a name="85560"></a></p></dl></dl><dl class="margin"><dd><p class="Body"><a name="85561"></a>Similarly, calls to <b class="routine">usbdHcdDetach( ) </b>can be made at any time to detach HCDs from the USBD. Outstanding requests to an HCD that is being detached are canceled, and detachment proceeds.</p><dd><p class="Body"><a name="85562"></a>To understand why these different scenarios work correctly, it is necessary to recognize that hot-plugging of USB devices can occur at any time. So, both the USBD and its clients must be written (using the "dynamic attachment" functions described in <a href="c-hostStack.html#85595"><i class="title">Dynamic Attachment Registration</i></a>) to recognize the appearance and disappearance of USB devices at run-time. It is for this reason that the appearance and disappearance of host controllers can also be handled flexibly. When a new host controller is attached to the system, the USBD automatically identifies the devices connected to it and notifies interested clients. Likewise, when a host controller is removed from the system, the USBD automatically notifies interested clients that the devices attached to that host controller have disappeared. The key point here is that USBD clients, such as USB class drivers, never assume that a particular device is present when the client is first initialized, and these drivers are always ready to accept devices connected to the system at other times.</p></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H4"><i><a name="85566"></a>Bus Tasks</i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="85567"></a>For each host controller attached to the USBD, the USBD spawns a <i class="term">bus task</i> responsible for monitoring bus events, such as the attachment and removal of devices. These tasks are normally "dormant"--that is, consuming no CPU time--and they typically wake up only when a USB hub reports a change on one of its ports.</p><dd><p class="Body"><a name="85568"></a>Each USBD bus task has the VxWorks task name <b class="task">tUsbdBus</b>.</p><dd><p class="Body"><a name="85569"></a>It is also possible, though not mandated by the design of the USBD, for the HCD itself to create tasks that monitor host controller events. For example, both the UHCI and OHCI HCDs provided by Wind River create such tasks. In the case of the Wind River UHCI module, <b class="library">usbHcdUhciLib</b>, the background task wakes up periodically to poll the status of the UHCI root hub and to check for timed-out I/O request packets (IRPs). In the case of the Wind River OHCI module, <b class="library">usbHcdOhciLib</b>, the background task wakes up periodically to check for timed-out IRPs only (OHCI root hub changes are reported by an interrupt).</p></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H4"><i><a name="85570"></a>Registering Client Modules</i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="85571"></a>Client modules that intend to make use of the USBD to communicate with USB devices must, in addition to calling <b class="routine">usbdInitialize( )</b>, register with the USBD by calling <b class="routine">usbdClientRegister( )</b>. When a client registers with the USBD, the USBD allocates per-client data structures that are later used to track all requests made by that client. During client registration, the USBD also creates a <i class="term">callback task</i> for each registered client (see <a href="c-hostStack.html#85584"><i class="title">Client Callback Tasks</i></a>). After successfully registering a new client, the USBD returns a handle, <b class="symbol_UC">USBD_CLIENT_HANDLE</b>, that must be used by that client when making subsequent calls to the USBD.</p><dd><p class="Body"><a name="85575"></a>When a client no longer intends to use the USBD, it must call <b class="routine">usbdClientUnregister( )</b> in order to release its per-client data and callback task. Any outstanding USB requests made by the client are canceled at that time.</p><dd><p class="Body"><a name="85581"></a>The following code fragment demonstrates the registration and unregistration of a USBD client:</p></dl><dl class="margin"><dd><font color="0000a0"><pre class="Code"><a name="85582"></a> USBD_CLIENT_HANDLE usbdClientHandle; /* Register a client named "USBD_TEST" with the USBD. */ if (usbdClientRegister ("USBD_TEST", &usbdClientHandle) != OK) { /* Attempt to register a new client failed. */ return ERROR; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -