usbTargLib.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:68k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* usbTargLib.c - USB Target Library */
  2. /* Copyright 2000 Wind River Systems, Inc. */
  3. /*
  4. Modification history
  5. --------------------
  6. 01d,12apr00,wef  Fixed uninitialized variable warning: direction2 in usbTargPipeCreate
  7. 01c,23nov99,rcb  Change #include ../xxx references to lower case.
  8. 01b,24sep99,rcb  Change packet count calculation in usbTargErpCallback()
  9.  to handle case where a single 0-length packet is transferred.
  10. 01a,05aug99,rcb  First.
  11. */
  12. /*
  13. DESCRIPTION
  14. This module implements the hardware-independent USB target API.
  15. usbTargLib can manage one or more USB TCDs (Target Controller Drivers).
  16. usbTargLib provides hardware-independent target services and management
  17. while the USB TCDs provide the hardware-dependent USB interface.
  18. usbTargLib must be initialized by calling usbTargInitialize(). Before
  19. operation can begin, at least one TCD must be attached to usbTargLib
  20. by calling usbTargTcdAttach(). In response to a successful TCD
  21. attachment, usbTargLib returns a USB_TARG_CHANNEL handle to the caller.
  22. This handle must be used in all subsequent calls to usbTargLib to
  23. identify a given target channel.
  24. USB devices (targets) almost never initiate activity on the USB (the
  25. exception being RESUME signalling).  So, as part of the call to 
  26. usbTargTcdAttach(), the caller must provide a pointer to a 
  27. USB_TARG_CALLBACK_TABLE structure.  This table contains a collection of
  28. callback function pointers initialized by the caller prior to invoking
  29. the usbTargTcdAttach() function.  Through these callbacks, usbTargLib
  30. notifies the calling application of various USB events and requests from
  31. the host.  The calling application is not required to provide callback
  32. functions for all possible events.  The callback pointers for which
  33. the calling application has no interest should be NULL.
  34. usbTargLib automatically establishes the default control pipe for
  35. each attached target channel and monitors all control pipe requests.
  36. If the calling application provides a non-NULL callback for the
  37. corresponding request, usbTargLib invokes the function.  If the callback
  38. function chooses to handle the control pipe request itself, then it
  39. returns OK, and usbTargLib generally performs no further automatic
  40. processing.  If the callback instead returns FALSE, then usbTargLib
  41. handles the control pipe request automatically using a default behavior.
  42. Generally, requests through the control pipe will result in the need for
  43. the target to establish one or more additional pipes to the host.  Each
  44. pipe is assigned to a particular endpoint on the device.  The calling
  45. application then submits USB_ERPs (endpoint request packets) which cause
  46. data transfers to be performed on specific pipes.
  47. */
  48. /* includes */
  49. #include "usb/usbPlatform.h" /* platform defintions */
  50. #include "string.h"
  51. #include "usb/ossLib.h"  /* o/s services */
  52. #include "usb/usb.h" /* general USB definitions */
  53. #include "usb/usbListLib.h" /* linked list functions */
  54. #include "usb/usbHandleLib.h" /* handle functions */
  55. #include "usb/target/usbTcdLib.h" /* interface to USB TCD */
  56. #include "usb/target/usbTargLib.h" /* our API */
  57. /* defines */
  58. #define TARG_VERSION 0x0001     /* TARG version in BCD */
  59. #define TARG_MFG "Wind River Systems, Inc."  /* TARG Mfg */
  60. #define TARG_TCD_SIG ((UINT32) 0xaaaa00cd)
  61. #define TARG_PIPE_SIG ((UINT32) 0xaaaa000e)
  62. /* Constants used by resetDataToggle(). */
  63. #define ANY_CONFIGURATION 0xffff
  64. #define ANY_INTERFACE 0xffff
  65. #define ANY_ENDPOINT 0xffff
  66. #define NO_CONFIGURATION 0xfffe
  67. #define NO_INTERFACE 0xfffe
  68. #define NO_ENDPOINT 0xfffe
  69. /* typedefs */
  70. /* TARG_TCD */
  71. typedef struct targ_tcd
  72.     {
  73.     LINK tcdLink; /* linked list of TCDs */
  74.     USB_TARG_CHANNEL targChannel; /* handle allocated for channel */
  75.     UINT16 deviceAddress; /* current device address */
  76.     pUSB_TARG_CALLBACK_TABLE pCallbacks;/* table of application callbacks */
  77.     pVOID callbackParam; /* caller-defined callback param */
  78.     TCD_NEXUS tcdNexus;  /* our TCD "nexus" */
  79.     UINT16 speed; /* target speed: USB_SPEED_xxxx */
  80.     UINT16 numEndpoints; /* number of endpoints */
  81.     pUSB_TARG_ENDPOINT_INFO pEndpoints; /* ptr to array of endpoints */
  82.     LIST_HEAD pipes; /* list of pipes on this target */
  83.     USB_TARG_PIPE controlPipe; /* Pipe opened for control channel */
  84.     USB_ERP setupErp; /* ERP to receive control pipe setup */
  85.     UINT8 setupBfr [sizeof (USB_SETUP)]; /* bfr for control SETUP packet */
  86.     BOOL setupErpPending; /* TRUE when ERP is pending */
  87.     USB_ERP dataErp; /* ERP to send/receive control data */
  88.     UINT8 dataBfr [USB_MAX_DESCR_LEN]; /* bfr for control IN/OUT packet */
  89.     BOOL dataErpPending; /* TRUE when ERP is pending */
  90.     USB_ERP statusErp; /* ERP to manage status phase packet */
  91.     BOOL statusErpPending; /* TRUE when ERP is pending */
  92.     } TARG_TCD, *pTARG_TCD;
  93. /* TARG_PIPE */
  94. typedef struct targ_pipe
  95.     {
  96.     LINK pipeLink; /* linked list of pipes */
  97.     USB_TARG_PIPE pipeHandle; /* handle allocated for pipe */
  98.     pTARG_TCD pTcd; /* TCD for this pipe */
  99.     UINT16 configuration; /* configuration associated with pipe */
  100.     UINT16 interface; /* interface associated with pipe */
  101.     pUSB_TARG_ENDPOINT_INFO pEndpoint; /* ptr to TCD endpoint info */
  102.     pUSB_TARG_ENDPOINT_INFO pEndpoint2; /* 2nd endpoint for ctrl pipes */
  103.     UINT16 dataToggle; /* current DATA0/DATA1 state */
  104.     LIST_HEAD erps; /* list of outstanding ERPs */
  105.     pUSB_ERP erpBeingDeleted; /* ptr to ERP with cancel pending */
  106.     BOOL erpDeleted; /* TRUE when ERP canceled */
  107.     } TARG_PIPE, *pTARG_PIPE;
  108. /* locals */
  109. LOCAL UINT16 initCount = 0; /* init count nesting */
  110. LOCAL BOOL ossInitialized; /* TRUE when ossLib initialized */
  111. LOCAL BOOL handleInitialized; /* TRUE when usbHandleLib initialized */
  112. LOCAL MUTEX_HANDLE targMutex; /* guards data structures */
  113. LOCAL LIST_HEAD tcdList; /* list of attached TCDs */
  114. /* forward declarations */
  115. LOCAL VOID setupErpCallback (pVOID p);
  116. LOCAL VOID responseErpCallback (pVOID p);
  117. LOCAL VOID statusErpCallback (pVOID p);
  118. /* functions */
  119. /***************************************************************************
  120. *
  121. * cancelErp - Cancel an IRP and wait for the ERP callback
  122. *
  123. * RETURNS: OK or S_usbTargLib_xxxx if couldn't cancel ERP
  124. */
  125. LOCAL int cancelErp
  126.     (
  127.     pTARG_PIPE pPipe,
  128.     pUSB_ERP pErp
  129.     )
  130.     {
  131.     /* Mark ERP being canceled */
  132.     pPipe->erpBeingDeleted = pErp;
  133.     pPipe->erpDeleted = FALSE;
  134.     /* Try to cancel ERP */
  135.     if (usbTcdErpCancel (&pPipe->pTcd->tcdNexus, pErp) != OK)
  136. return S_usbTargLib_CANNOT_CANCEL;
  137.     while (!pPipe->erpDeleted)
  138. OSS_THREAD_SLEEP (1);
  139.     return OK;
  140.     }
  141. /***************************************************************************
  142. *
  143. * mngmtFunc - Invokes target applications mngmtFunc callback.
  144. *
  145. * If there is no mngmtFunc, returns OK.
  146. *
  147. * RETURNS: return code (OK, ERROR) from mngmtFunc.
  148. */
  149. LOCAL STATUS mngmtFunc
  150.     (
  151.     pTARG_TCD pTcd,
  152.     UINT16 mngmtCode
  153.     )
  154.     {
  155.     if (pTcd->pCallbacks->mngmtFunc == NULL)
  156. return OK;
  157.     return (*pTcd->pCallbacks->mngmtFunc)
  158. (pTcd->callbackParam, pTcd->targChannel, mngmtCode);
  159.     }
  160. /***************************************************************************
  161. *
  162. * destroyPipe - Shuts down a pipe and releases its resources
  163. *
  164. * RETURNS: N/A
  165. */
  166. LOCAL VOID destroyPipe
  167.     (
  168.     pTARG_PIPE pPipe
  169.     )
  170.     {
  171.     pUSB_ERP pErp;
  172.     if (pPipe != NULL)
  173. {
  174. /* Unlink the pipe */
  175. usbListUnlink (&pPipe->pipeLink);
  176. /* Cancel outstanding ERPs */
  177. while ((pErp = usbListFirst (&pPipe->erps)) != NULL)
  178.     cancelErp (pPipe, pErp);
  179. /* Release endpoint(s) assigned to pipe. */
  180. if (pPipe->pEndpoint != NULL)
  181.     usbTcdEndpointRelease (&pPipe->pTcd->tcdNexus, 
  182. pPipe->pEndpoint->endpointId);
  183. if (pPipe->pEndpoint2 != NULL)
  184.     usbTcdEndpointRelease (&pPipe->pTcd->tcdNexus,
  185. pPipe->pEndpoint2->endpointId);
  186. /* release handle */
  187. usbHandleDestroy (pPipe->pipeHandle);
  188. OSS_FREE (pPipe);
  189. }
  190.     }
  191. /***************************************************************************
  192. *
  193. * destroyTcd - Shuts down a target channel and releases its resources
  194. *
  195. * RETURNS: N/A
  196. */
  197. LOCAL VOID destroyTcd
  198.     (
  199.     pTARG_TCD pTcd
  200.     )
  201.     {
  202.     pTARG_PIPE pPipe;
  203.     if (pTcd != NULL)
  204. {
  205. /* Unlink TCD */
  206. usbListUnlink (&pTcd->tcdLink);
  207. /* Notify target application that the channel is going down. */
  208. mngmtFunc (pTcd, TCD_MNGMT_DETACH);
  209. /* Destroy outstanding pipes */
  210. while ((pPipe = usbListFirst (&pTcd->pipes)) != NULL)
  211.     destroyPipe (pPipe);
  212. /* Detach TCD */
  213. usbTcdDetach (&pTcd->tcdNexus);
  214. /* release handle */
  215. if (pTcd->targChannel != NULL)
  216.     usbHandleDestroy (pTcd->targChannel);
  217. ossFree (pTcd);
  218. }
  219.     }
  220. /***************************************************************************
  221. *
  222. * validateTarg - validate a target channel and the state of usbTargLib
  223. *
  224. * If <ppTcd> is not NULL, then validate the <targChannel> parameter.
  225. * Also checks to make sure usbTargLib has been properly initialized.
  226. *
  227. * RETURNS: OK or ERROR if unable to validate target channel
  228. *
  229. * ERRNO:
  230. *   S_usbTargLib_NOT_INITIALIZED
  231. *   S_usbTargLib_BAD_HANDLE
  232. */
  233. LOCAL int validateTarg
  234.     (
  235.     USB_TARG_CHANNEL targChannel,
  236.     pTARG_TCD *ppTcd
  237.     )
  238.     {
  239.     if (initCount == 0)
  240. return ossStatus (S_usbTargLib_NOT_INITIALIZED);
  241.     if (ppTcd != NULL)
  242. {
  243. if (usbHandleValidate (targChannel, TARG_TCD_SIG, (pVOID *) ppTcd) != OK)
  244.     return ossStatus (S_usbTargLib_BAD_HANDLE);
  245. }
  246.     return OK;
  247.     }
  248. /***************************************************************************
  249. *
  250. * validatePipe - validates a pipe handle
  251. *
  252. * RETURNS: OK or ERROR if unable to validate pipe handle
  253. *
  254. * ERRNO:
  255. *   S_usbTargLib_BAD_HANDLE
  256. */
  257. LOCAL STATUS validatePipe
  258.     (
  259.     USB_TARG_PIPE pipeHandle,
  260.     pTARG_PIPE *ppPipe
  261.     )
  262.     {
  263.     if (usbHandleValidate (pipeHandle, TARG_PIPE_SIG, (pVOID *) ppPipe) != OK)
  264. return ossStatus (S_usbTargLib_BAD_HANDLE);
  265.     return OK;
  266.     }
  267. /***************************************************************************
  268. *
  269. * findEndpointById - Return pUSB_TARG_ENDPOINT_INFO for endpointId
  270. *
  271. * RETURNS: pointer to USB_TARG_ENDPOINT_INFO or NULL if invalid endpointId
  272. */
  273. LOCAL pUSB_TARG_ENDPOINT_INFO findEndpointById
  274.     (
  275.     pTARG_TCD pTcd,
  276.     UINT16 endpointId
  277.     )
  278.     {
  279.     pUSB_TARG_ENDPOINT_INFO pEndpoint;
  280.     UINT16 i;
  281.     for (i = 0; i < pTcd->numEndpoints; i++)
  282. if ((pEndpoint = &pTcd->pEndpoints [i])->endpointId == endpointId)
  283.     return pEndpoint;
  284.     return NULL;
  285.     }
  286. /***************************************************************************
  287. *
  288. * validateEndpoint - checks if an endpointId can be used as requested
  289. *
  290. * Checks if <endpointId> is a valid endpoint ID and if the endpoint it
  291. * indicates supports the <transferType> and <direction>.  If the endpoint
  292. * is valid and supports the requested transfer type/direction, then
  293. * returns a pointer to the USB_TARG_ENDPOINT_INFO structure for the
  294. * endpoint.
  295. *
  296. * RETURNS: OK, or ERROR if unable to validate endpoint
  297. *
  298. * ERRNO:
  299. *   S_usbTargLib_BAD_PARAM
  300. *   S_usbTargLib_ENDPOINT_IN_USE
  301. */
  302. LOCAL STATUS validateEndpoint
  303.     (
  304.     pTARG_TCD pTcd,
  305.     UINT16 endpointId,
  306.     UINT16 transferType,
  307.     UINT16 direction,
  308.     pUSB_TARG_ENDPOINT_INFO *ppEndpoint
  309.     )
  310.     {
  311.     pUSB_TARG_ENDPOINT_INFO pEndpoint;
  312.     /* Check if endpoint number is valid */
  313.     if ((pEndpoint = findEndpointById (pTcd, endpointId)) == NULL)
  314. return ossStatus (S_usbTargLib_BAD_PARAM);
  315.     /* See if the endpointId is in use. */
  316.     if ((pEndpoint->flags & TCD_ENDPOINT_IN_USE) != 0)
  317. return ossStatus (S_usbTargLib_ENDPOINT_IN_USE);
  318.     /* See if the endpoint supports the direction */
  319.     if (direction == USB_DIR_IN)
  320. {
  321. if ((pEndpoint->flags & TCD_ENDPOINT_IN_OK) == 0)
  322.     return ossStatus (S_usbTargLib_BAD_PARAM);
  323. }
  324.     else if (direction == USB_DIR_OUT)
  325. {
  326. if ((pEndpoint->flags & TCD_ENDPOINT_OUT_OK) == 0)
  327.     return ossStatus (S_usbTargLib_BAD_PARAM);
  328. }
  329.     else
  330. return ossStatus (S_usbTargLib_BAD_PARAM);
  331.     
  332.     /* See if the endpoint supports the request transfer type */
  333.     
  334.     if (transferType == USB_XFRTYPE_CONTROL)
  335. {
  336. if ((pEndpoint->flags & TCD_ENDPOINT_CTRL_OK) == 0)
  337.     return ossStatus (S_usbTargLib_BAD_PARAM);
  338. }
  339.     else if (transferType == USB_XFRTYPE_BULK)
  340. {
  341. if ((pEndpoint->flags & TCD_ENDPOINT_BULK_OK) == 0)
  342.     return ossStatus (S_usbTargLib_BAD_PARAM);
  343. }
  344.     else if (transferType == USB_XFRTYPE_INTERRUPT)
  345. {
  346. if ((pEndpoint->flags & TCD_ENDPOINT_INT_OK) == 0)
  347.     return ossStatus (S_usbTargLib_BAD_PARAM);
  348. }
  349.     else if (transferType == USB_XFRTYPE_ISOCH)
  350. {
  351. if ((pEndpoint->flags & TCD_ENDPOINT_ISOCH_OK) == 0)
  352.     return ossStatus (S_usbTargLib_BAD_PARAM);
  353. }
  354.     else
  355. return ossStatus (S_usbTargLib_BAD_PARAM);
  356.     *ppEndpoint = pEndpoint;
  357.     return OK;
  358.     }
  359. /***************************************************************************
  360. *
  361. * resetDataToggle - reset data toggle on affected pipes
  362. *
  363. * This function is called when a "configuration event" is detected
  364. * for a given node.  This function searches all pipes associated with
  365. * the node for any that might be affected by the configuration event
  366. * and resets their data toggles to DATA0.
  367. *
  368. * RETURNS: N/A
  369. */
  370. LOCAL VOID resetDataToggle
  371.     (
  372.     pTARG_TCD pTcd,
  373.     UINT16 configuration,
  374.     UINT16 interface,
  375.     UINT16 endpoint
  376.     )
  377.     {
  378.     pTARG_PIPE pPipe;
  379.     pPipe = usbListFirst (&pTcd->pipes);
  380.     while (pPipe != NULL)
  381. {
  382. if (configuration == ANY_CONFIGURATION ||
  383.     configuration == pPipe->configuration)
  384.     {
  385.     if (interface == ANY_INTERFACE ||
  386. interface == pPipe->interface)
  387. {
  388. if (endpoint == ANY_ENDPOINT ||
  389.     endpoint == pPipe->pEndpoint->endpointNum)
  390.     {
  391.     /* Reset our DATA0/DATA1 indicator. */
  392.     pPipe->dataToggle = USB_DATA0;
  393.     /* Notify the TCD to reset any TCD/hardware indicators */
  394.     usbTcdEndpointStateSet (&pTcd->tcdNexus,
  395. pPipe->pEndpoint->endpointId, TCD_ENDPOINT_DATA0);
  396.     if (pPipe->pEndpoint2 != NULL)
  397. usbTcdEndpointStateSet (&pTcd->tcdNexus,
  398.     pPipe->pEndpoint2->endpointId, TCD_ENDPOINT_DATA0);
  399.     }
  400. }
  401.     }
  402. pPipe = usbListNext (&pPipe->pipeLink);
  403. }
  404.     }
  405. /***************************************************************************
  406. *
  407. * initErp - initializes ERP based on arguments passed by caller, then submits it
  408. *
  409. * RETURNS: OK, or ERROR if unable to initialize/submit ERP
  410. */
  411. LOCAL STATUS initErp
  412.     (
  413.     pTARG_TCD pTcd,
  414.     pBOOL erpInUse,
  415.     pUSB_ERP pErp,
  416.     ERP_CALLBACK callback,
  417.     UINT16 dataToggle,
  418.     UINT8 pid,
  419.     pUINT8 pBfr,
  420.     UINT16 bfrLen
  421.     )
  422.     {
  423.     /* Check if the ERP is already in use. */
  424.     if (*erpInUse)
  425. return ERROR;
  426.     *erpInUse = TRUE;
  427.     /* Initialize ERP */
  428.     memset (pErp, 0, sizeof (*pErp));
  429.     pErp->userPtr = pTcd;
  430.     pErp->erpLen = sizeof (*pErp);
  431.     pErp->userCallback = callback;
  432.     pErp->dataToggle = dataToggle;
  433.     pErp->bfrCount = 1;
  434.     pErp->bfrList [0].pid = pid;
  435.     pErp->bfrList [0].pBfr = pBfr;
  436.     pErp->bfrList [0].bfrLen = bfrLen;
  437.     /* Submit the ERP. */
  438.     return usbTargTransfer (pTcd->controlPipe, pErp);
  439.     }
  440. /***************************************************************************
  441. *
  442. * initSetupErp - Initialize ERP to listen for control pipe requests
  443. *
  444. * RETURNS: OK, or ERROR if unable to initialize control ERP.
  445. */
  446. LOCAL STATUS initSetupErp
  447.     (
  448.     pTARG_TCD pTcd
  449.     )
  450.     {
  451.     /* Initialize the Setup phase ERP */
  452.     return initErp (pTcd, &pTcd->setupErpPending, &pTcd->setupErp, 
  453. setupErpCallback, USB_DATA0, USB_PID_SETUP, 
  454. pTcd->setupBfr, sizeof (pTcd->setupBfr));
  455.     }
  456. /***************************************************************************
  457. *
  458. * initDataErpForResponse - Initialize ERP to send a control pipe response
  459. *
  460. * TARGET.dataBfr must already contain the data to be send to the host of
  461. * length <bfrLen>.
  462. *
  463. * RETURNS: OK, or ERROR if unable to initialize/submit ERP
  464. */
  465. LOCAL STATUS initDataErpForResponse
  466.     (
  467.     pTARG_TCD pTcd,
  468.     UINT16 bfrLen
  469.     )
  470.     {
  471.     /* Initialize the Data phase ERP */
  472.     return initErp (pTcd, &pTcd->dataErpPending, &pTcd->dataErp, 
  473. responseErpCallback, USB_DATA1, USB_PID_IN, pTcd->dataBfr, bfrLen);
  474.     }
  475. /***************************************************************************
  476. *
  477. * initStatusErp - Initialize ERP to send/rcv status phase packet
  478. *
  479. * <pid> must specify the direction of the status phase packet as USB_PID_IN
  480. * (from the device to the host) or USB_PID_OUT (from host to device).
  481. *
  482. * RETURNS: OK, or ERROR if unable to initialize/submit ERP
  483. */
  484. LOCAL STATUS initStatusErp
  485.     (
  486.     pTARG_TCD pTcd,
  487.     UINT8 pid
  488.     )
  489.     {
  490.     /* Initialize the Status phase ERP */
  491.     return initErp (pTcd, &pTcd->statusErpPending, &pTcd->statusErp, 
  492. statusErpCallback, USB_DATA1, pid, NULL, 0);
  493.     }
  494. /***************************************************************************
  495. *
  496. * requestClearFeature - processes a CLEAR_FEATURE setup packet
  497. *
  498. * RETURNS: OK if setup packet valid, else ERROR if invalid
  499. */
  500. LOCAL STATUS requestClearFeature
  501.     (
  502.     pTARG_TCD pTcd,
  503.     pUSB_SETUP pSetup
  504.     )
  505.     {
  506.     UINT16 feature = FROM_LITTLEW (pSetup->value);
  507.     UINT16 index = FROM_LITTLEW (pSetup->index);
  508.     /* A CLEAR_FEATURE request may be configuration event.  Therefore, we
  509.      * need to set the data toggle to DATA0 for any pipes which reference
  510.      * this interface.
  511.      */
  512.     if (pSetup->requestType == (USB_RT_STANDARD | USB_RT_ENDPOINT) &&
  513. feature == USB_FSEL_DEV_ENDPOINT_HALT)
  514. {
  515. resetDataToggle (pTcd, ANY_CONFIGURATION, ANY_ENDPOINT, index);
  516. }
  517.     /* The request itself isn't supported unless the target application
  518.      * has provided a featureSet handler.
  519.      */
  520.     if (pTcd->pCallbacks->featureClear == NULL)
  521. return ERROR;
  522.     if ((*pTcd->pCallbacks->featureClear)
  523. (pTcd->callbackParam, pTcd->targChannel, 
  524. pSetup->requestType, feature, index) != OK)
  525. return ERROR;
  526.     /* Request terminates with status phase. */
  527.     return initStatusErp (pTcd, USB_PID_IN);
  528.     }
  529. /***************************************************************************
  530. *
  531. * requestSetFeature - processes a SET_FEATURE setup packet
  532. *
  533. * RETURNS: OK if setup packet valid, else ERROR if invalid
  534. */
  535. LOCAL STATUS requestSetFeature
  536.     (
  537.     pTARG_TCD pTcd,
  538.     pUSB_SETUP pSetup
  539.     )
  540.     {
  541.     UINT16 feature = FROM_LITTLEW (pSetup->value);
  542.     UINT16 index = FROM_LITTLEW (pSetup->index);
  543.     /* This request isn't supported unless the target application
  544.      * has provided a featureSet handler.
  545.      */
  546.     if (pTcd->pCallbacks->featureSet == NULL)
  547. return ERROR;
  548.     if ((*pTcd->pCallbacks->featureSet)
  549. (pTcd->callbackParam, pTcd->targChannel, 
  550. pSetup->requestType, feature, index) != OK)
  551. return ERROR;
  552.     /* Request terminates with status phase. */
  553.     return initStatusErp (pTcd, USB_PID_IN);
  554.     }
  555. /***************************************************************************
  556. *
  557. * requestGetConfiguration - processes a GET_CONFIGURATION setup packet
  558. *
  559. * RETURNS: OK if setup packet valid, else ERROR if invalid
  560. */
  561. LOCAL STATUS requestGetConfiguration
  562.     (
  563.     pTARG_TCD pTcd,
  564.     pUSB_SETUP pSetup
  565.     )
  566.     {
  567.     /* This request isn't supported unless the target application has
  568.      * provided a configurationGet handler.
  569.      */
  570.     if (pTcd->pCallbacks->configurationGet == NULL)
  571. return ERROR;
  572.     /* Get the interface setting from the target application. */
  573.     if ((*pTcd->pCallbacks->configurationGet)
  574. (pTcd->callbackParam, pTcd->targChannel, 
  575. (pUINT8) pTcd->dataBfr) != OK)
  576. return ERROR;
  577.     /* Transmit the interface setting back to the host */
  578.     return initDataErpForResponse (pTcd, sizeof (UINT8));
  579.     }
  580. /***************************************************************************
  581. *
  582. * requestSetConfiguration - processes a SET_CONFIGURATION setup packet
  583. *
  584. * RETURNS: OK if setup packet valid, else ERROR if invalid
  585. */
  586. LOCAL STATUS requestSetConfiguration
  587.     (
  588.     pTARG_TCD pTcd,
  589.     pUSB_SETUP pSetup
  590.     )
  591.     {
  592.     UINT8 configuration = LSB (FROM_LITTLEW (pSetup->value));
  593.     /* A SET_CONFIGURATION request is a configuration event.  Therefore, we
  594.      * need to set the data toggle to DATA0 for any pipes which reference
  595.      * this interface.
  596.      */
  597.     resetDataToggle (pTcd, configuration, ANY_INTERFACE, ANY_ENDPOINT);
  598.     /* The request itself isn't supported unless the target application
  599.      * has provided an interfaceSet handler.
  600.      */
  601.     if (pTcd->pCallbacks->configurationSet == NULL)
  602. return ERROR;
  603.     if ((*pTcd->pCallbacks->configurationSet)
  604. (pTcd->callbackParam, pTcd->targChannel, configuration) != OK)
  605. return ERROR;
  606.     /* Request terminates with status phase. */
  607.     return initStatusErp (pTcd, USB_PID_IN);
  608.     }
  609. /***************************************************************************
  610. *
  611. * requestGetDescriptor - processes a GET_DESCRIPTOR setup packet
  612. *
  613. * RETURNS: OK if setup packet valid, else ERROR if invalid
  614. */
  615. LOCAL STATUS requestGetDescriptor
  616.     (
  617.     pTARG_TCD pTcd,
  618.     pUSB_SETUP pSetup
  619.     )
  620.     {
  621.     UINT8 descriptorType = MSB (FROM_LITTLEW (pSetup->value));
  622.     UINT8 descriptorIndex = LSB (FROM_LITTLEW (pSetup->value));
  623.     UINT16 languageId = FROM_LITTLEW (pSetup->index);
  624.     UINT16 length = FROM_LITTLEW (pSetup->length);
  625.     UINT16 actLen;
  626.     /* This request isn't supported unless the target application has
  627.      * provided a descriptorGet handler.
  628.      */
  629.     if (pTcd->pCallbacks->descriptorGet == NULL)
  630. return ERROR;
  631.     /* Get the descriptor from the target application. */
  632.     if ((*pTcd->pCallbacks->descriptorGet)
  633. (pTcd->callbackParam, pTcd->targChannel, 
  634. pSetup->requestType, descriptorType, descriptorIndex,
  635. languageId, min (length, sizeof (pTcd->dataBfr)), pTcd->dataBfr, 
  636. &actLen) != OK)
  637. {
  638. return ERROR;
  639. }
  640.     /* Transmit the descriptor back to the host */
  641.     return initDataErpForResponse (pTcd, actLen);
  642.     }
  643. /***************************************************************************
  644. *
  645. * requestSetDescriptor - processes a SET_DESCRIPTOR setup packet
  646. *
  647. * RETURNS: OK if setup packet valid, else ERROR if invalid
  648. */
  649. LOCAL STATUS requestSetDescriptor
  650.     (
  651.     pTARG_TCD pTcd,
  652.     pUSB_SETUP pSetup
  653.     )
  654.     {
  655.     UINT8 descriptorType = MSB (FROM_LITTLEW (pSetup->value));
  656.     UINT8 descriptorIndex = LSB (FROM_LITTLEW (pSetup->value));
  657.     UINT16 languageId = FROM_LITTLEW (pSetup->index);
  658.     UINT16 length = FROM_LITTLEW (pSetup->length);
  659.     /* This request isn't supported unless the target application has
  660.      * provided a descriptorSet handler.
  661.      */
  662.     if (pTcd->pCallbacks->descriptorSet == NULL)
  663. return ERROR;
  664.     /* Let the target application process the SET_DESCRIPTOR request. */
  665.     return (*pTcd->pCallbacks->descriptorSet)
  666. (pTcd->callbackParam, pTcd->targChannel, 
  667. pSetup->requestType, descriptorType, descriptorIndex,
  668. languageId, length);
  669.     }
  670. /***************************************************************************
  671. *
  672. * requestGetInterface - processes a GET_INTERFACE setup packet
  673. *
  674. * RETURNS: OK if setup packet valid, else ERROR if invalid
  675. */
  676. LOCAL STATUS requestGetInterface
  677.     (
  678.     pTARG_TCD pTcd,
  679.     pUSB_SETUP pSetup
  680.     )
  681.     {
  682.     UINT16 interface = FROM_LITTLEW (pSetup->index);
  683.     /* This request isn't supported unless the target application has
  684.      * provided an interfaceGet handler.
  685.      */
  686.     if (pTcd->pCallbacks->interfaceGet == NULL)
  687. return ERROR;
  688.     /* Get the interface setting from the target application. */
  689.     if ((*pTcd->pCallbacks->interfaceGet)
  690. (pTcd->callbackParam, pTcd->targChannel, 
  691. interface, (pUINT8) pTcd->dataBfr) != OK)
  692. return ERROR;
  693.     /* Transmit the interface setting back to the host */
  694.     return initDataErpForResponse (pTcd, sizeof (UINT8));
  695.     }
  696. /***************************************************************************
  697. *
  698. * requestSetInterface - processes a SET_INTERFACE setup packet
  699. *
  700. * RETURNS: OK if setup packet valid, else ERROR if invalid
  701. */
  702. LOCAL STATUS requestSetInterface
  703.     (
  704.     pTARG_TCD pTcd,
  705.     pUSB_SETUP pSetup
  706.     )
  707.     {
  708.     UINT16 interfaceIndex = FROM_LITTLEW (pSetup->index);
  709.     UINT8 alternateSetting = LSB (FROM_LITTLEW (pSetup->value));
  710.     /* A SET_INTERFACE request is a configuration event.  Therefore, we
  711.      * need to set the data toggle to DATA0 for any pipes which reference
  712.      * this interface.
  713.      */
  714.     resetDataToggle (pTcd, ANY_CONFIGURATION, interfaceIndex, ANY_ENDPOINT);
  715.     /* The request itself isn't supported unless the target application
  716.      * has provided an interfaceSet handler.
  717.      */
  718.     if (pTcd->pCallbacks->interfaceSet == NULL)
  719. return ERROR;
  720.     if ((*pTcd->pCallbacks->interfaceSet)
  721. (pTcd->callbackParam, pTcd->targChannel,
  722. interfaceIndex, alternateSetting) != OK)
  723. return ERROR;
  724.     /* Request terminates with status phase. */
  725.     return initStatusErp (pTcd, USB_PID_IN);
  726.     }
  727. /***************************************************************************
  728. *
  729. * requestGetStatus - processes a GET_STATUS setup packet
  730. *
  731. * RETURNS: OK if setup packet valid, else ERROR if invalid
  732. */
  733. LOCAL STATUS requestGetStatus
  734.     (
  735.     pTARG_TCD pTcd,
  736.     pUSB_SETUP pSetup
  737.     )
  738.     {
  739.     UINT16 index = FROM_LITTLEW (pSetup->index);
  740.     UINT16 length = FROM_LITTLEW (pSetup->length);
  741.     UINT16 actLen;
  742.     /* This request isn't supported unless the target application has
  743.      * provided a statusGet handler.
  744.      */
  745.     if (pTcd->pCallbacks->statusGet == NULL)
  746. return ERROR;
  747.     if ((*pTcd->pCallbacks->statusGet)
  748. (pTcd->callbackParam, pTcd->targChannel,
  749. pSetup->requestType, index, 
  750. min (length, sizeof (pTcd->dataBfr)), pTcd->dataBfr, 
  751. &actLen) != OK)
  752. {
  753. return ERROR;
  754. }
  755.     /* Transmit the descriptor back to the host */
  756.     return initDataErpForResponse (pTcd, actLen);
  757.     }
  758. /***************************************************************************
  759. *
  760. * requestSetAddress - processes a SET_ADDRESS setup packet
  761. *
  762. * RETURNS: OK if setup packet valid, else ERROR if invalid
  763. */
  764. LOCAL STATUS requestSetAddress
  765.     (
  766.     pTARG_TCD pTcd,
  767.     pUSB_SETUP pSetup
  768.     )
  769.     {
  770.     UINT16 deviceAddress = FROM_LITTLEW (pSetup->value);
  771.     /* If the target application has provided a SetAddress callback,
  772.      * then invoke it now.
  773.      */
  774.     if (pTcd->pCallbacks->addressSet != NULL)
  775. (*pTcd->pCallbacks->addressSet)
  776.     (pTcd->callbackParam, pTcd->targChannel, deviceAddress);
  777.     /* The new address goes into effect after the Status phase, if any. */
  778.     pTcd->deviceAddress = deviceAddress;
  779.     usbTcdAddressSet (&pTcd->tcdNexus, pTcd->deviceAddress);
  780.     return initStatusErp (pTcd, USB_PID_IN);
  781.     }
  782. /***************************************************************************
  783. *
  784. * requestGetSynchFrame - processes a GET_SYNCH_FRAME setup packet
  785. *
  786. * RETURNS: OK if setup packet valid, else ERROR if invalid
  787. */
  788. LOCAL STATUS requestGetSynchFrame
  789.     (
  790.     pTARG_TCD pTcd,
  791.     pUSB_SETUP pSetup
  792.     )
  793.     {
  794.     UINT16 endpoint = FROM_LITTLEW (pSetup->index);
  795.     /* This request isn't supported unless the target application has
  796.      * provided a synchFrameGet handler.
  797.      */
  798.     if (pTcd->pCallbacks->synchFrameGet == NULL)
  799. return ERROR;
  800.     /* Get the synch frame from the target application. */
  801.     if ((*pTcd->pCallbacks->synchFrameGet)
  802. (pTcd->callbackParam, pTcd->targChannel, 
  803. endpoint, (pUINT16) pTcd->dataBfr) != OK)
  804. return ERROR;
  805.     /* Transmit the synch frame back to the host */
  806.     return initDataErpForResponse (pTcd, sizeof (UINT16));
  807.     }
  808. /***************************************************************************
  809. *
  810. * requestVendorSpecific - processes a "vendor specific" setup packet
  811. *
  812. * RETURNS: OK if setup packet valid, else ERROR if invalid
  813. */
  814. LOCAL STATUS requestVendorSpecific
  815.     (
  816.     pTARG_TCD pTcd,
  817.     pUSB_SETUP pSetup
  818.     )
  819.     {
  820.     /* This request isn't supported unless the target application has
  821.      * provided a vendorSpecific handler.
  822.      */
  823.     if (pTcd->pCallbacks->vendorSpecific == NULL)
  824. return ERROR;
  825.     return (*pTcd->pCallbacks->vendorSpecific) 
  826. (pTcd->callbackParam, pTcd->targChannel, 
  827. pSetup->requestType, pSetup->request, FROM_LITTLEW (pSetup->value),
  828. FROM_LITTLEW (pSetup->index), FROM_LITTLEW (pSetup->length));
  829.     }
  830. /***************************************************************************
  831. *
  832. * parseSetupPacket - parse/execute a control pipe request
  833. *
  834. * The TARGET.setupBfr should contain a setup packet.  Validate it.  If
  835. * valid, parse and execute it.
  836. *
  837. * RETURNS: OK if setup packet valid, else ERROR if invalid
  838. */
  839. LOCAL STATUS parseSetupPacket
  840.     (
  841.     pTARG_TCD pTcd
  842.     )
  843.     {
  844.     pUSB_SETUP pSetup;
  845.     /* Validate the setup packet */
  846.     if (pTcd->setupErp.bfrList [0].actLen != sizeof (USB_SETUP))
  847. return ERROR;
  848.     pSetup = (pUSB_SETUP) pTcd->setupBfr;
  849.     /* Execute based on the type of request. */
  850.     if ((pSetup->requestType & USB_RT_CATEGORY_MASK) == USB_RT_STANDARD)
  851. {
  852. switch (pSetup->request)
  853.     {
  854.     case USB_REQ_CLEAR_FEATURE:
  855. return requestClearFeature (pTcd, pSetup);
  856.     case USB_REQ_SET_FEATURE:
  857. return requestSetFeature (pTcd, pSetup);
  858.     case USB_REQ_GET_CONFIGURATION:
  859. return requestGetConfiguration (pTcd, pSetup);
  860.     case USB_REQ_SET_CONFIGURATION:
  861. return requestSetConfiguration (pTcd, pSetup);
  862.     case USB_REQ_GET_DESCRIPTOR:
  863. return requestGetDescriptor (pTcd, pSetup);
  864.     case USB_REQ_SET_DESCRIPTOR:
  865. return requestSetDescriptor (pTcd, pSetup);
  866.     case USB_REQ_GET_INTERFACE:
  867. return requestGetInterface (pTcd, pSetup);
  868.     case USB_REQ_SET_INTERFACE:
  869. return requestSetInterface (pTcd, pSetup);
  870.     case USB_REQ_GET_STATUS:
  871. return requestGetStatus (pTcd, pSetup);
  872.     case USB_REQ_SET_ADDRESS:
  873. return requestSetAddress (pTcd, pSetup);
  874.     case USB_REQ_GET_SYNCH_FRAME:
  875. return requestGetSynchFrame (pTcd, pSetup);
  876.     default:
  877. break;
  878.     }
  879. }
  880.     return requestVendorSpecific (pTcd, pSetup);
  881.     }
  882. /***************************************************************************
  883. *
  884. * setupErpCallback - invoked when Setup ERP completes
  885. *
  886. * This function receives control when a Setup ERP completes.  Examines the
  887. * reason for completion, possibly invoking additional control request
  888. * handling.
  889. *
  890. * RETURNS: N/A
  891. */
  892. LOCAL VOID setupErpCallback
  893.     (
  894.     pVOID p     /* ptr to ERP */
  895.     )
  896.     {
  897.     pUSB_ERP pErp = (pUSB_ERP) p;
  898.     pTARG_TCD pTcd = (pTARG_TCD) pErp->userPtr;
  899.     pTcd->setupErpPending = FALSE;
  900.     /* Completion of a setup ERP, whether successful or not, implies that
  901.      * any previous control pipe request must be terminated. */
  902.     if (pTcd->dataErpPending)
  903. cancelErp ((pTARG_PIPE) pTcd->dataErp.targPtr, &pTcd->dataErp);
  904.     if (pTcd->statusErpPending)
  905. cancelErp ((pTARG_PIPE) pTcd->dataErp.targPtr, &pTcd->statusErp);
  906.     /* Was the ERP successful? */
  907.     if (pErp->result == OK)
  908. {
  909. /* The ERP was successful.  Parse the setup packet. */
  910. if (parseSetupPacket (pTcd) == OK)
  911.     {
  912.     /* The packet can be parsed successfully.  Other code will
  913.      * take care of resubmitting the Setup ERP, so we do nothing.
  914.      */
  915.     return;
  916.     }
  917. else
  918.     {
  919.     /* We cannot process the indicated command.  Stall the
  920.      * control pipe.
  921.      */
  922.     usbTargPipeStatusSet (pTcd->targChannel, pTcd->controlPipe,
  923. TCD_ENDPOINT_STALL);
  924.     }
  925. }
  926.     /* Re-submit the ERP unless it was canceled - which indicates that
  927.      * the pipe is probably being torn down.
  928.      */
  929.     if (pErp->result != S_usbTcdLib_ERP_CANCELED)
  930. initSetupErp (pTcd);
  931.     }
  932. /***************************************************************************
  933. *
  934. * responseErpCallback - invoked when control pipe response ERP completes
  935. *
  936. * This function receives control after the data IN phase of a control pipe
  937. * request has completed.
  938. *
  939. * RETURNS: N/A
  940. */
  941. LOCAL VOID responseErpCallback
  942.     (
  943.     pVOID p     /* ptr to ERP */
  944.     )
  945.     {
  946.     pUSB_ERP pErp = (pUSB_ERP) p;
  947.     pTARG_TCD pTcd = (pTARG_TCD) pErp->userPtr;
  948.     pTcd->dataErpPending = FALSE;
  949.     /* If the ERP was successful, then we prepare the status phase.  The
  950.      * status phase is always in the oppposite direction to the data phase.
  951.      * Since this callback handles only "responses" (from device to host),
  952.      * then the status phase will always be an OUT (from host to device).
  953.      *
  954.      * If the data phase failed for some reason other than being canceled,
  955.      * then we resubmit the Setup phase ERP to ensure that the target
  956.      * continues to be responsive on the control pipe.
  957.      */
  958.     if (pErp->result == OK)
  959. {
  960. initStatusErp (pTcd, USB_PID_OUT);
  961. return;
  962. }
  963.     if (pErp->result != S_usbTcdLib_ERP_CANCELED)
  964. initSetupErp (pTcd);
  965.     }
  966. /***************************************************************************
  967. *
  968. * statusErpCallback - invoked when control pipe status packet completes
  969. *
  970. * This function receives control after the status phase of a control pipe
  971. * request has completed.
  972. *
  973. * RETURNS: N/A
  974. */
  975. LOCAL VOID statusErpCallback
  976.     (
  977.     pVOID p     /* ptr to ERP */
  978.     )
  979.     {
  980.     pUSB_ERP pErp = (pUSB_ERP) p;
  981.     pTARG_TCD pTcd = (pTARG_TCD) pErp->userPtr;
  982.     pTcd->statusErpPending = FALSE;
  983.     /* Re-submit the Setup ERP. */
  984.     if (pErp->result != S_usbTcdLib_ERP_CANCELED)
  985. initSetupErp (pTcd);
  986.     }
  987. /***************************************************************************
  988. *
  989. * usbTargManagementCallback - invoked when TCD detects management event
  990. *
  991. * This function is invoked by a TCD when the TCD detects a "management"
  992. * event on a target channel.  Examples of management events include
  993. * bus resets, detection of a new or lost connection, etc.
  994. *
  995. * RETURNS: N/A
  996. */
  997. LOCAL VOID usbTargManagementCallback
  998.     (
  999.     pVOID mngmtCallbackParam,     /* caller-defined param */
  1000.     TCD_HANDLE handle,     /* channel */
  1001.     UINT16 mngmtCode     /* management code */
  1002.     )
  1003.     {
  1004.     pTARG_TCD pTcd = (pTARG_TCD) mngmtCallbackParam;
  1005.     switch (mngmtCode)
  1006. {
  1007. case TCD_MNGMT_VBUS_LOST:
  1008. case TCD_MNGMT_BUS_RESET:
  1009.     /* Reset the device configuration to the power-on state. */
  1010.     pTcd->deviceAddress = 0;
  1011.     /* code falls through into following case */
  1012. case TCD_MNGMT_VBUS_DETECT:
  1013. case TCD_MNGMT_SUSPEND:
  1014. case TCD_MNGMT_RESUME:
  1015.     /* reflect the management event to the target application */
  1016.     mngmtFunc (pTcd, mngmtCode);
  1017.     break;
  1018. }
  1019.     }
  1020. /***************************************************************************
  1021. *
  1022. * usbTargErpCallback - invoked when ERP completes
  1023. *
  1024. * The TCD invokes this callback when an ERP completes. This gives us the
  1025. * opportunity to monitor ERP execution.  We reflect the callback to the
  1026. * calling application after we finish our processing.
  1027. *
  1028. * NOTE: By convention, the targPtr field of the ERP has been initialized
  1029. * to point to the TARG_PIPE for this ERP.
  1030. *
  1031. * RETURNS: N/A
  1032. */
  1033. LOCAL VOID usbTargErpCallback
  1034.     (
  1035.     pVOID p     /* ptr to ERP */
  1036.     )
  1037.     {
  1038.     pUSB_ERP pErp = (pUSB_ERP) p;
  1039.     pTARG_PIPE pPipe = (pTARG_PIPE) pErp->targPtr;
  1040.     UINT16 packets;
  1041.     UINT16 i;
  1042.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1043.     /* Unlink the ERP */
  1044.     usbListUnlink (&pErp->targLink);
  1045.     /* Check if this ERP is being deleted.  If so, let the foreground
  1046.      * thread know the callback has been invoked.
  1047.      */
  1048.     if (pErp == pPipe->erpBeingDeleted)
  1049. pPipe->erpDeleted = TRUE;
  1050.     /* Update data toggle for pipe.  Control and isochronous transfers
  1051.      * always begin with DATA0, which is set at pipe initialization -
  1052.      * so we don't change it here.  Bulk and interrupt pipes alternate
  1053.      * between DATA0 and DATA1, and we need to keep a running track of
  1054.      * the state across ERPs.
  1055.      */
  1056.     if (pErp->transferType == USB_XFRTYPE_INTERRUPT ||
  1057. pErp->transferType == USB_XFRTYPE_BULK)
  1058. {
  1059. /* Calculate the number of packets exchanged to determine the
  1060.  * next data toggle value.  If the count of packets is odd, then
  1061.  * the data toggle needs to switch.
  1062.  *
  1063.  * NOTE: If the ERP is successful, then at least one packet MUST
  1064.  * have been transferred.  However, it may have been a 0-length
  1065.  * packet.  This case is handled after the following "for" loop.
  1066.  */
  1067. packets = 0;
  1068. for (i = 0; i < pErp->bfrCount; i++)
  1069.     {
  1070.     packets += 
  1071. (pErp->bfrList [i].actLen + pPipe->pEndpoint->maxPacketSize - 1) /
  1072. pPipe->pEndpoint->maxPacketSize;
  1073.     }
  1074. if (pErp->result == OK)
  1075.     packets = max (packets, 1);
  1076. if ((packets & 1) != 0)
  1077.     pPipe->dataToggle = (pPipe->dataToggle == USB_DATA0) ?
  1078. USB_DATA1 : USB_DATA0;
  1079. }
  1080.     /* Invoke the user's callback routine */
  1081.     if (pErp->userCallback != NULL)
  1082. (*pErp->userCallback) (pErp);
  1083.     OSS_MUTEX_RELEASE (targMutex);
  1084.     }
  1085. /***************************************************************************
  1086. *
  1087. * usbTargVersionGet - Retrieve usbTargLib version
  1088. *
  1089. * This function returns the usbTargLib version.  If <pVersion> is not NULL, the 
  1090. * usbTargLib returns its version in BCD in <pVersion>. For example, version 
  1091. * "1.02" would be coded as 01h in the high byte and 02h in the low byte.
  1092. *
  1093. * If <pMfg> is not NULL it must point to a buffer of at least USBT_NAME_LEN 
  1094. * bytes in length in which the USBD will store the NULL terminated name of
  1095. * the usbTargLib manufacturer (e.g., "Wind River Systems" + ).
  1096. *
  1097. * RETURNS: OK
  1098. */
  1099.  
  1100. STATUS usbTargVersionGet
  1101.     (
  1102.     pUINT16 pVersion, /* usbTargLib version */
  1103.     pCHAR pMfg /* usbTargLib manufacturer */
  1104.     )
  1105.     {
  1106.     /* return version info */
  1107.     if (pVersion != NULL)
  1108. *pVersion = TARG_VERSION;
  1109.     if (pMfg != NULL)
  1110. strncpy (pMfg, TARG_MFG, USBT_NAME_LEN);
  1111.     return OK;
  1112.     }
  1113. /***************************************************************************
  1114. *
  1115. * doShutdown - shut down usbTargLib
  1116. *
  1117. * RETURNS: N/A
  1118. */
  1119. LOCAL VOID doShutdown (void)
  1120.     {
  1121.     pTARG_TCD pTcd;
  1122.     /* Shut down all target channels */
  1123.     while ((pTcd = usbListFirst (&tcdList)) != NULL)
  1124. destroyTcd (pTcd);
  1125.     /* Release other resources. */
  1126.     if (targMutex != NULL)
  1127. {
  1128. OSS_MUTEX_DESTROY (targMutex);
  1129. targMutex = NULL;
  1130. }
  1131.     /* Shut down handle library */
  1132.     if (handleInitialized)
  1133. {
  1134. usbHandleShutdown ();
  1135. handleInitialized = FALSE;
  1136. }
  1137.     /* Shut down ossLib */
  1138.     if (ossInitialized)
  1139. {
  1140. ossShutdown ();
  1141. ossInitialized = FALSE;
  1142. }
  1143.     }
  1144. /***************************************************************************
  1145. *
  1146. * usbTargInitialize - Initializes usbTargLib
  1147. *
  1148. * usbTargInitialize() must be called at least once prior to calling other
  1149. * usbTargLib functions except for usbTargVersionGet(). usbTargLib maintains
  1150. * an internal initialization count, so calls to usbTargInitialize() may be 
  1151. * nested.  
  1152. *
  1153. * RETURNS: OK, or ERROR if unable to initialize usbTargLib.
  1154. *
  1155. * ERRNO:
  1156. *   S_usbTargLib_OUT_OF_RESOURCES
  1157. *   S_usbTargLib_GENERAL_FAULT;
  1158. */
  1159. STATUS usbTargInitialize (void)
  1160.     {
  1161.     int status = OK;
  1162.     if (initCount == 0)
  1163. {
  1164. /* Initialize local data */
  1165. memset (&tcdList, 0, sizeof (tcdList));
  1166. ossInitialized = FALSE;
  1167. handleInitialized = FALSE;
  1168. /* Initialize ossLib */
  1169. if (ossInitialize () != OK)
  1170.     status = S_usbTargLib_GENERAL_FAULT;
  1171. else
  1172.     {
  1173.     ossInitialized = TRUE;
  1174.     /* Intialize usbHandleLib */
  1175.     if (usbHandleInitialize (0) != OK)
  1176. status = S_usbTargLib_GENERAL_FAULT;
  1177.     else
  1178. {
  1179. handleInitialized = TRUE;
  1180. if (OSS_MUTEX_CREATE (&targMutex) != OK)
  1181.     status = S_usbTargLib_OUT_OF_RESOURCES;
  1182. }
  1183.     }
  1184. }
  1185.     if (status == OK)
  1186. initCount++;
  1187.     else
  1188. doShutdown ();
  1189.     return ossStatus (status);
  1190.     }
  1191. /***************************************************************************
  1192. *
  1193. * usbTargShutdown - Shuts down usbTargLib
  1194. *
  1195. * usbTargShutdown() should be called once for every successful call to
  1196. * usbTargInitialize(). usbTargShutdown() closes any open target channels
  1197. * and releases resources allocated by the usbTargLib.
  1198. *
  1199. * RETURNS: OK, or ERROR if unable to shut down usbTargLib.
  1200. *
  1201. * ERRNO:
  1202. *   S_usbTargLib_NOT_INITIALIZED
  1203. */
  1204. STATUS usbTargShutdown (void)
  1205.     {
  1206.     /* Are we initialized? */
  1207.     if (initCount == 0)
  1208. return ossStatus (S_usbTargLib_NOT_INITIALIZED);
  1209.     if (--initCount == 0)
  1210. doShutdown ();
  1211.     return OK;
  1212.     }
  1213. /***************************************************************************
  1214. *
  1215. * usbTargTcdAttach - Attaches and initializes a USB target controller driver
  1216. *
  1217. * This function attaches a USB TCD (Target Controller Driver) to usbTargLib.
  1218. * A TCD needs to be attached to usbTargLib before any other USB operations
  1219. * may be performed on the target channel it manages.
  1220. *
  1221. * <tcdExecFunc> is the primary entry point of the TCD being attached and
  1222. * <tcdParam> is a TCD-defined parameter which is passed to the TCD's attach
  1223. * function.  Generally, the <tcdParam> is points to a TCD-defined structure
  1224. * which identifies the characteristics of the target controller hardware
  1225. * (i.e., base I/O address, IRQ channel, etc.). Each call to usbTargTcdAttach()
  1226. * enables one and only one target channel.
  1227. *
  1228. * <pCallbacks> points to a USB_TARG_CALLBACK_TABLE structure in which the
  1229. * caller has stored the addresses of callbacks for events in which it is
  1230. * interested in being notified.  <callbackParam> is a caller-defined parameter 
  1231. * which is passed to each callback function when the callbacks are invoked by
  1232. * usbTargLib.
  1233. *
  1234. * <pTargChannel> points to a USB_TARG_CHANNEL variable allocated by the caller
  1235. * which receives a handle to the target channel created by this call to
  1236. * usbTargTcdAttach().
  1237. *
  1238. * <pNumEndpoints> and <ppEndpoints> receive the count of target endpoints and
  1239. * a pointer to an array of USB_TARG_ENDPOINT_INFO structures, respectively.
  1240. * The caller can use this information to assign endpoints to pipes.
  1241. *
  1242. * RETURNS: OK, or ERROR if unable to attach/initialize TCD.
  1243. *
  1244. * ERRNO:
  1245. *   S_usbTargLib_BAD_PARAM
  1246. *   S_usbTargLib_OUT_OF_MEMORY
  1247. *   S_usbTargLib_OUT_OF_RESOURCES
  1248. *   S_usbTargLib_TCD_FAULT
  1249. *   S_usbTargLib_APP_FAULT
  1250. */
  1251. STATUS usbTargTcdAttach
  1252.     (
  1253.     USB_TCD_EXEC_FUNC tcdExecFunc, /* TCD entry point */
  1254.     pVOID tcdParam, /* TCD parameter */
  1255.     pUSB_TARG_CALLBACK_TABLE pCallbacks,/* caller-supplied callbacks */
  1256.     pVOID callbackParam, /* caller-defined callback param */
  1257.     pUSB_TARG_CHANNEL pTargChannel, /* handle to target on return */
  1258.     pUINT16 pNumEndpoints, /* bfr to receive nbr of endpoints */
  1259.     pUSB_TARG_ENDPOINT_INFO *ppEndpoints/* bfr to rcv ptr to endpt array */
  1260.     )
  1261.     {
  1262.     pTARG_TCD pTcd;
  1263.     int status;
  1264.     /* Validate parameters */
  1265.     if (tcdExecFunc == NULL || pCallbacks == NULL || pTargChannel == NULL ||
  1266. pNumEndpoints == NULL || ppEndpoints == NULL)
  1267. return ossStatus (S_usbTargLib_BAD_PARAM);
  1268.     if ((status = validateTarg (NULL, NULL)) != OK)
  1269. return status;
  1270.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1271.     /* Allocate a TARG_TCD to manage this channel */
  1272.     if ((pTcd = OSS_CALLOC (sizeof (*pTcd))) == NULL)
  1273. status = S_usbTargLib_OUT_OF_MEMORY;
  1274.     if (status == OK)
  1275. {
  1276. /* Initialize TCD */
  1277. pTcd->pCallbacks = pCallbacks;
  1278. pTcd->callbackParam = callbackParam;
  1279. if (usbHandleCreate (TARG_TCD_SIG, pTcd, &pTcd->targChannel) != OK)
  1280.     status = S_usbTargLib_OUT_OF_RESOURCES;
  1281. }
  1282.     if (status == OK)
  1283. {
  1284. /* Try to initialize the TCD */
  1285. if (usbTcdAttach (tcdExecFunc, tcdParam, &pTcd->tcdNexus,
  1286.     usbTargManagementCallback, pTcd, &pTcd->speed, 
  1287.     &pTcd->numEndpoints, &pTcd->pEndpoints) != OK)
  1288.     {
  1289.     status = S_usbTargLib_TCD_FAULT;
  1290.     }
  1291. else
  1292.     {
  1293.     /* Make sure the target exposed at least two endpoints, aka, the
  1294.      * OUT and IN endpoints we need for the default control chanenl. */
  1295.     if (pTcd->numEndpoints < 2 || pTcd->pEndpoints == NULL)
  1296. status = S_usbTargLib_TCD_FAULT;
  1297.     }
  1298. }
  1299.     if (status == OK)
  1300. {
  1301. /* Create a default control channel for this target.
  1302.  *
  1303.  * NOTE: By convention, the target always places the endpoints which
  1304.  * are best suited for the default control channel at the beginning
  1305.  * of the endpoint array, with the USB_DIR_OUT (host->device) endpoint
  1306.  * first, followed by the USB_DIR_IN endpoint.
  1307.  */
  1308. if ((status = usbTargPipeCreate (pTcd->targChannel, 
  1309.     pTcd->pEndpoints [0].endpointId, pTcd->pEndpoints [1].endpointId,
  1310.     USB_ENDPOINT_DEFAULT_CONTROL, NO_CONFIGURATION, NO_INTERFACE, 
  1311.     USB_XFRTYPE_CONTROL, USB_DIR_INOUT, &pTcd->controlPipe)) == OK)
  1312.     {
  1313.     /* Start listening for requests on the default control pipe. */
  1314.     status = initSetupErp (pTcd);     
  1315.     }
  1316. }
  1317.     if (status == OK)
  1318. {
  1319. /* Link the TCD to the list of managed TCDs. */
  1320. usbListLink (&tcdList, pTcd, &pTcd->tcdLink, LINK_TAIL);
  1321. *pTargChannel = pTcd->targChannel;
  1322. *pNumEndpoints = pTcd->numEndpoints;
  1323. *ppEndpoints = pTcd->pEndpoints;
  1324. }
  1325.     if (status == OK)
  1326. {
  1327. /* Invoke the target application's mngmtFunc to notify it that 
  1328.  * the attach is complete. 
  1329.  */
  1330. if (mngmtFunc (pTcd, TCD_MNGMT_ATTACH) != OK)
  1331.     status = S_usbTargLib_APP_FAULT;
  1332. }
  1333.     /* If we failed to initialized, clean up the TCD. */
  1334.     if (status != OK)
  1335. destroyTcd (pTcd);
  1336.     OSS_MUTEX_RELEASE (targMutex);
  1337.     return ossStatus (status);
  1338.     }
  1339. /***************************************************************************
  1340. *
  1341. * usbTargTcdDetach - Detaches a USB target controller driver
  1342. *
  1343. * This function detaches a USB TCD which was previously attached to the
  1344. * usbTargLib by calling usbTargTcdAttach().  <targChannel> is the handle
  1345. * of the target channel originally returned by usbTargTcdAttach().
  1346. *
  1347. * The usbTargLib automatically terminates any pending transactions on the
  1348. * target channel being detached and releases all internal usbTargLib
  1349. * resources allocated on behalf of the channel.  Once a target channel
  1350. * has been detached by calling this function, the <targChannel> is no
  1351. * longer valid.
  1352. *
  1353. * RETURNS: OK, or ERROR if unable to detach TCD.
  1354. */
  1355. STATUS usbTargTcdDetach
  1356.     (
  1357.     USB_TARG_CHANNEL targChannel /* target to detach */
  1358.     )
  1359.     {
  1360.     pTARG_TCD pTcd;
  1361.     STATUS status;
  1362.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1363.     /* Validate parameters */
  1364.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  1365. {
  1366. /* Destroy target channel */
  1367. destroyTcd (pTcd);
  1368. }
  1369.     OSS_MUTEX_RELEASE (targMutex);
  1370.     return status;
  1371.     }
  1372. /***************************************************************************
  1373. *
  1374. * usbTargEndpointInfoGet - Retrieves endpoint information for channel
  1375. *
  1376. * This function retrieves the number of endpoints on <targChannel> and
  1377. * returns a pointer to the base of the USB_TARG_ENDPOINT_INFO array.
  1378. *
  1379. * RETURNS: OK, or ERROR if unable to return target endpoint information
  1380. */
  1381. STATUS usbTargEndpointInfoGet
  1382.     (
  1383.     USB_TARG_CHANNEL targChannel, /* target channel */
  1384.     pUINT16 pNumEndpoints, /* receives nbr of endpoints */
  1385.     pUSB_TARG_ENDPOINT_INFO *ppEndpoints/* receives ptr to array */
  1386.     )
  1387.     {
  1388.     pTARG_TCD pTcd;
  1389.     STATUS status;
  1390.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1391.     /* Validate parameters */
  1392.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  1393. {
  1394. if (pNumEndpoints != NULL)
  1395.     *pNumEndpoints = pTcd->numEndpoints;
  1396. if (ppEndpoints != NULL)
  1397.     *ppEndpoints = pTcd->pEndpoints;
  1398. }
  1399.     
  1400.     OSS_MUTEX_RELEASE (targMutex);
  1401.     return ossStatus (status);
  1402.     }
  1403. /***************************************************************************
  1404. *
  1405. * usbTargEnable - Enables target channel onto USB
  1406. *
  1407. * After attaching a TCD to usbTargLib and performing any other application-
  1408. * specific initialization that might be necessary, this function should be
  1409. * called to enable a target channel.  The USB target controlled by the TCD
  1410. * will not appear as a device on the USB until this function has been called.
  1411. *
  1412. * RETURNS: OK, or ERROR if unable to enable target channel.
  1413. *
  1414. * ERRNO:
  1415. *   S_usbTargLib_TCD_FAULT
  1416. */
  1417. STATUS usbTargEnable
  1418.     (
  1419.     USB_TARG_CHANNEL targChannel /* target to enable */
  1420.     )
  1421.     {
  1422.     pTARG_TCD pTcd;
  1423.     STATUS status;
  1424.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1425.     /* Validate parameters */
  1426.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  1427. {
  1428. /* Enable target channel */
  1429. if (usbTcdEnable (&pTcd->tcdNexus) != OK)
  1430.     status = S_usbTargLib_TCD_FAULT;
  1431. }
  1432.     OSS_MUTEX_RELEASE (targMutex);
  1433.     return status;
  1434.     }
  1435. /***************************************************************************
  1436. *
  1437. * usbTargDisable - Disables a target channel
  1438. *
  1439. * This function is the counterpart to the usbTargEnable() function.  This
  1440. * function disables the indicated target channel.
  1441. *
  1442. * RETURNS: OK, or ERROR if unable to disable the target channel.
  1443. *
  1444. * ERRNO:
  1445. *   S_usbTargLib_TCD_FAULT
  1446. */
  1447. STATUS usbTargDisable
  1448.     (
  1449.     USB_TARG_CHANNEL targChannel /* target to disable */
  1450.     )
  1451.     {
  1452.     pTARG_TCD pTcd;
  1453.     STATUS status;
  1454.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1455.     /* Validate parameters */
  1456.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  1457. {
  1458. /* Enable target channel */
  1459. if (usbTcdDisable (&pTcd->tcdNexus) != OK)
  1460.     status = S_usbTargLib_TCD_FAULT;
  1461. }
  1462.     OSS_MUTEX_RELEASE (targMutex);
  1463.     return status;
  1464.     }
  1465. /***************************************************************************
  1466. *
  1467. * usbTargPipeCreate - Creates a pipe for communication on an endpoint
  1468. *
  1469. * This function creates a pipe attached to a specific target endpoint.
  1470. * <endpointId> is the TCD-assigned ID of the target endpoint to be used
  1471. * for this pipe and <endpointNum> is the device endpoint number to which
  1472. * the endpoint will respond.  Some TCDs allow the flexible assignment of
  1473. * endpoints to specific endpoint numbers while others do not.  The
  1474. * endpointNumMask field in the USB_TARG_ENDPOINT_INFO structure is a bit
  1475. * mask that reveals which endpoint numbers are supported by a given
  1476. * endpoint.  (e.g., If bit 0 is '1', then the corresponding endpoint can
  1477. * be assigned to endpoint #0, and so forth).
  1478. *
  1479. * By convention, each of the endpoints exposed by the TCD is unidirectional.
  1480. * Control pipes are bidirectional, and therefore logically occupy two
  1481. * endpoints, one IN endpoint and one OUT endpoint, both with the same
  1482. * endpointNum. When creating a control pipe, the caller must specify the
  1483. * second endpoint Id in <endpointId2>. In this case, <endpointId> must
  1484. * specify the OUT endpoint, and <endpointId2> must specify the IN endpoint.
  1485. * <endpointId2> should be 0 for other types of pipes.
  1486. *
  1487. * <configuration> and <interface> specify the device configuration and
  1488. * interface with which the endpoint (and pipe) is associated.  The 
  1489. * usbTargLib uses these values to reset pipes as appropriate when
  1490. * USB "configuration events" are detected.  (In response to a USB
  1491. * configuration event, the data toggle for a given endpoint is always
  1492. * reset to DATA0.)
  1493. *
  1494. * <transferType> specifies the type of transfers to be performed as
  1495. * USB_XFRTYPE_xxxx.  <direction> specifies the direction of the pipe as
  1496. * USB_DIR_xxxx.  Control pipes specify direction as USB_DIR_INOUT.
  1497. *
  1498. * The caller must be aware that not all endpoints are capable of all types
  1499. * of transfers.  Prior to assigning an endpoint for a particular purpose,
  1500. * the caller should interrogate the USB_TARG_ENDPOINT_INFO structure for
  1501. * the endpoint to ensure that it supports the indicated type of transfer.
  1502. *
  1503. * RETURNS: OK, or ERROR if unable to create pipe
  1504. *
  1505. * ERRNO:
  1506. *   S_usbTargLib_BAD_PARAM
  1507. *   S_usbTargLib_ENDPOINT_IN_USE
  1508. *   S_usbTargLib_OUT_OF_MEMORY
  1509. *   S_usbTargLib_OUT_OF_RESOURCES
  1510. *   S_usbTargLib_TCD_FAULT
  1511. */
  1512. STATUS usbTargPipeCreate
  1513.     (
  1514.     USB_TARG_CHANNEL targChannel, /* target channel */
  1515.     UINT16 endpointId, /* endpoint ID to use for pipe */
  1516.     UINT16 endpointId2,  /* needed for control pipes only */
  1517.     UINT16 endpointNum,  /* endpoint number to assign */
  1518.     UINT16 configuration, /* associated configuration */
  1519.     UINT16 interface, /* associated interface */
  1520.     UINT16 transferType, /* USB_XFRTYPE_xxxx */
  1521.     UINT16 direction, /* USB_DIR_xxxx */
  1522.     pUSB_TARG_PIPE pPipeHandle /* returned pipe handle */
  1523.     )
  1524.     {
  1525.     pTARG_TCD pTcd;
  1526.     pUSB_TARG_ENDPOINT_INFO pEndpoint = NULL;
  1527.     pUSB_TARG_ENDPOINT_INFO pEndpoint2 = NULL;
  1528.     pTARG_PIPE pPipe = NULL;
  1529.     UINT16 direction2 = NULL;
  1530.     STATUS status;
  1531.     UINT16 i;
  1532.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1533.     /* Validate parameters */
  1534.     if (pPipeHandle == NULL)
  1535. status = S_usbTargLib_BAD_PARAM;
  1536.     else
  1537. status = validateTarg (targChannel, &pTcd);
  1538.     if (transferType == USB_XFRTYPE_CONTROL)
  1539. {
  1540. /* Must validate both endpoints.  pEndpointId must be OUT endpoint
  1541.  * and pEndpointId2 must be IN endpoint.
  1542.  */
  1543. direction = USB_DIR_OUT;
  1544. direction2 = USB_DIR_IN;
  1545. if ((status = validateEndpoint (pTcd, endpointId, USB_XFRTYPE_CONTROL,
  1546.     direction, &pEndpoint)) == OK)
  1547.     {
  1548.     status = validateEndpoint (pTcd, endpointId2, USB_XFRTYPE_CONTROL,
  1549. direction2, &pEndpoint2);
  1550.     }
  1551. }
  1552.     else
  1553. {
  1554. /* Validate only the first endpointId. */
  1555. status = validateEndpoint (pTcd, endpointId, transferType,
  1556.     direction, &pEndpoint);
  1557. }
  1558.     if (status == OK)
  1559. {
  1560. /* See if the requested endpoint number is valid */
  1561. if (endpointNum > USB_MAX_ENDPOINT_NUM)
  1562.     status = S_usbTargLib_BAD_PARAM;
  1563. }
  1564.     if (status == OK)
  1565. {
  1566. /* See if the endpointNum is in use (for the same direction) */
  1567. for (i = 0; i < pTcd->numEndpoints; i++)
  1568.     {
  1569.     if ((pTcd->pEndpoints [i].flags & TCD_ENDPOINT_IN_USE) != 0 &&
  1570. pTcd->pEndpoints [i].direction == direction &&
  1571. pTcd->pEndpoints [i].endpointNum == endpointNum)
  1572. {
  1573. status = S_usbTargLib_ENDPOINT_IN_USE;
  1574. break;
  1575. }
  1576.     }
  1577. }
  1578.     if (status == OK)
  1579. {
  1580. /* All of the parameters check out OK. Create a pipe to manage
  1581.  * this endpoint. */
  1582. if ((pPipe = OSS_CALLOC (sizeof (*pPipe))) == NULL)
  1583.     status = S_usbTargLib_OUT_OF_MEMORY;
  1584. else
  1585.     {
  1586.     /* Initialize pipe */
  1587.     pPipe->pTcd = pTcd;
  1588.     pPipe->configuration = configuration;
  1589.     pPipe->interface = interface;
  1590.     pPipe->dataToggle = USB_DATA0;
  1591.     if (usbHandleCreate (TARG_PIPE_SIG, pPipe, &pPipe->pipeHandle) != OK)
  1592. status = S_usbTargLib_OUT_OF_RESOURCES;
  1593.     }
  1594. }
  1595.     if (status == OK)
  1596. {
  1597. /* Ask the TCD to assign endpointId to the pipe. */
  1598. if (usbTcdEndpointAssign (&pTcd->tcdNexus, endpointId, endpointNum,
  1599.     configuration, interface, transferType, direction) != OK)
  1600.     status = S_usbTargLib_TCD_FAULT;
  1601. else
  1602.     pPipe->pEndpoint = pEndpoint;
  1603. }
  1604.     if (status == OK && pEndpoint2 != NULL)
  1605. {
  1606. /* Ask the TCD to assign endpointId2 to the pipe. */
  1607. if (usbTcdEndpointAssign (&pTcd->tcdNexus, endpointId2, endpointNum,
  1608.     configuration, interface, transferType, direction2) != OK)
  1609.     status = S_usbTargLib_TCD_FAULT;
  1610. else
  1611.     pPipe->pEndpoint2 = pEndpoint2;
  1612. }
  1613.     /* If we failed to create the pipe, release any partially created pipe.
  1614.      * Otherwise, link the pipe to the list of pipes on this target channel. */
  1615.     if (status != OK)
  1616. destroyPipe (pPipe);
  1617.     else
  1618. {
  1619. usbListLink (&pTcd->pipes, pPipe, &pPipe->pipeLink, LINK_TAIL);
  1620. *pPipeHandle = pPipe->pipeHandle;
  1621. }
  1622.     OSS_MUTEX_RELEASE (targMutex);
  1623.     return ossStatus (status);
  1624.     }
  1625. /***************************************************************************
  1626. *
  1627. * usbTargPipeDestroy - Destroys an endpoint pipe
  1628. *
  1629. * This function tears down a pipe previously created by calling
  1630. * usbTargPipeCreate(). Any pending transfers on the pipe are canceled
  1631. * and all resources allocated to the pipe are released.
  1632. *
  1633. * RETURNS: OK, or ERROR if unable to destroy pipe.
  1634. */
  1635. STATUS usbTargPipeDestroy
  1636.     (
  1637.     USB_TARG_PIPE pipeHandle /* pipe to be destroyed */
  1638.     )
  1639.     {
  1640.     pTARG_PIPE pPipe;
  1641.     STATUS status;
  1642.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1643.     /* Validate parameters */
  1644.     if ((status = validatePipe (pipeHandle, &pPipe)) == OK)
  1645. {
  1646. /* Destroy pipe */
  1647. destroyPipe (pPipe);
  1648. }
  1649.     OSS_MUTEX_RELEASE (targMutex);
  1650.     return status;
  1651.     }
  1652. /***************************************************************************
  1653. *
  1654. * usbTargTransfer - Submits a USB_ERP for transfer through a pipe
  1655. *
  1656. * A client uses this function to initiate an transfer on the pipe indicated 
  1657. * by <pipeHandle>.  The transfer is described by an ERP, or endpoint request 
  1658. * packet, which must be allocated and initialized by the caller prior to 
  1659. * invoking usbdTargTransfer().
  1660. *
  1661. * The USB_ERP structure is defined in usb.h as:
  1662. *
  1663. * .CS
  1664. * typedef struct usb_bfr_list
  1665. *     {
  1666. *     UINT16 pid;
  1667. *     pUINT8 pBfr;
  1668. *     UINT32 bfrLen;
  1669. *     UINT32 actLen;
  1670. *     } USB_BFR_LIST;
  1671. *
  1672. * typedef struct usb_erp
  1673. *     {
  1674. *     LINK targLink;     // used by usbTargLib
  1675. *     pVOID targPtr;     // used by usbTargLib
  1676. *     LINK tcdLink;     // used by TCD
  1677. *     pVOID tcdPtr;     // used by TCD
  1678. *     pVOID userPtr;
  1679. *     UINT16 erpLen;     
  1680. *     int result;     // returned by usbTargLib/TCD
  1681. *     ERP_CALLBACK targCallback;    // used by usbTargLib
  1682. *     ERP_CALLBACK userCallback;
  1683. *     UINT16 endpointId;     // filled in by usbTargLib
  1684. *     UINT16 transferType;     // filled in by usbTargLib
  1685. *     UINT16 dataToggle;     // filled in by usbTargLib
  1686. *     UINT16 bfrCount;     
  1687. *     USB_BFR_LIST bfrList [1];
  1688. *     } USB_ERP, *pUSB_ERP;
  1689. * .CE
  1690. *
  1691. * The length of the USB_ERP structure must be stored in <erpLen> and varies 
  1692. * depending on the number of <bfrList> elements allocated at the end of the 
  1693. * structure.  By default, the default structure contains a single <bfrList>
  1694. * element, but clients may allocate a longer structure to accommodate a larger 
  1695. * number of <bfrList> elements.  
  1696. *
  1697. * <endpointId> and <transferType> are filled in automatically 
  1698. * by the usbTargLib using values recorded when the pipe was created.  
  1699. *
  1700. * <dataToggle> is filled in automatically except for control pipes.  For these
  1701. * pipes, the caller is required to store the next data toggle as USB_DATA0
  1702. * or USB_DATA1.  The Setup packet is always a DATA0.  The first packet of the
  1703. * data phase is always DATA1, with data packets alternating thereafter, and 
  1704. * the Status phase packet is always DATA1.  When using the functions
  1705. * usbTargLibResponseSend() and usbTargLibPayloadRcv(), usbTargLib handles the
  1706. * <dataToggle> value automatically.
  1707. *
  1708. * <bfrList> is an array of buffer descriptors which describe data buffers to 
  1709. * be associated with this ERP. If more than the one <bfrList> element is 
  1710. * required then the caller must allocate the ERP by calculating the size as 
  1711. *
  1712. * .CS
  1713. * erpLen = sizeof (USB_ERP) + (sizeof (USB_BFR_DESCR) * (bfrCount - 1))
  1714. * .CE
  1715. *
  1716. * <pid> specifies the packet type to use for the indicated buffer and is
  1717. * specified as USB_PID_xxxx.  Note that packet types are specified from the
  1718. * perspective of the host.  For example, USB_PID_IN indicates a transfer from
  1719. * the device (target) to the host.
  1720. *
  1721. * The ERP <userCallback> routine must point to a client-supplied ERP_CALLBACK
  1722. * routine.  The usbdTargTransfer() function returns as soon as the ERP has been
  1723. * successfully enqueued.  If there is a failure in delivering the ERP to the
  1724. * TCD, then usbdTargTransfer() returns an error.  The actual result of the ERP
  1725. * should be checked after the <userCallback> routine has been invoked.
  1726. *
  1727. * RETURNS: OK, or ERROR if unable to submit USB_ERP for execution
  1728. *
  1729. * ERRNO:
  1730. *   S_usbTargLib_BAD_PARAM
  1731. *   S_usbTargLib_TCD_FAULT
  1732. */
  1733. STATUS usbTargTransfer
  1734.     (
  1735.     USB_TARG_PIPE pipeHandle, /* pipe for transfer */
  1736.     pUSB_ERP pErp /* ERP describing transfer */
  1737.     )
  1738.     {
  1739.     pTARG_PIPE pPipe;
  1740.     STATUS status;
  1741.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1742.     /* Validate parameters */
  1743.     if (pErp == NULL)
  1744. status = S_usbTargLib_BAD_PARAM;
  1745.     else if ((status = validatePipe (pipeHandle, &pPipe)) == OK)
  1746. {
  1747. /* Fill in fields in ERP. */
  1748. pErp->targPtr = pPipe;
  1749. pErp->targCallback = usbTargErpCallback;
  1750. pErp->transferType = pPipe->pEndpoint->transferType;
  1751. /* If this is a control pipe and with a direction of USB_PID_IN,
  1752.  * then use the second endpoint for the pipe.
  1753.  */
  1754. if (pErp->transferType == USB_XFRTYPE_CONTROL &&
  1755.     pErp->bfrList [0].pid == USB_PID_IN)
  1756.     pErp->endpointId = pPipe->pEndpoint2->endpointId;
  1757. else
  1758.     pErp->endpointId = pPipe->pEndpoint->endpointId;
  1759. /* The caller must specify DATA0/DATA1 for control pipes */
  1760. if (pErp->transferType != USB_XFRTYPE_CONTROL)
  1761.     pErp->dataToggle = pPipe->dataToggle;
  1762. usbListLink (&pPipe->erps, pErp, &pErp->targLink, LINK_HEAD);
  1763. /* Submit ERP to TCD */
  1764. if (usbTcdErpSubmit (&pPipe->pTcd->tcdNexus, pErp) != OK)
  1765.     {
  1766.     status = S_usbTargLib_TCD_FAULT;
  1767.     usbListUnlink (&pErp->targLink);
  1768.     }
  1769. }
  1770.     OSS_MUTEX_RELEASE (targMutex);
  1771.     return ossStatus (status);
  1772.     }
  1773. /***************************************************************************
  1774. *
  1775. * usbTargTransferAbort - Cancels a previously submitted USB_ERP
  1776. *
  1777. * This function aborts an ERP which was previously submitted through
  1778. * a call to usbdTargTransfer().  
  1779. *
  1780. * RETURNS: OK, or ERROR if unable to cancel USB_ERP
  1781. *
  1782. * ERRNO:
  1783. *   S_usbTargLib_BAD_PARAM
  1784. */
  1785. STATUS usbTargTransferAbort
  1786.     (
  1787.     USB_TARG_PIPE pipeHandle, /* pipe for transfer to abort */
  1788.     pUSB_ERP pErp /* ERP to be aborted */
  1789.     )
  1790.     {
  1791.     pTARG_PIPE pPipe;
  1792.     STATUS status;
  1793.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1794.     /* Validate parameters */
  1795.     if (pErp == NULL)
  1796. status = S_usbTargLib_BAD_PARAM;
  1797.     else if ((status = validatePipe (pipeHandle, &pPipe)) == OK)
  1798. {
  1799. /* cancel the ERP */
  1800. status = cancelErp (pPipe, pErp);
  1801. }
  1802.     OSS_MUTEX_RELEASE (targMutex);
  1803.     return ossStatus (status);
  1804.     }
  1805. /***************************************************************************
  1806. *
  1807. * usbTargControlResponseSend - Sends a response on the control pipe
  1808. *
  1809. * usbTargLib automatically creates a pipe to manage communication on the
  1810. * default control endpoint (#0) defined by the USB.  Certain application
  1811. * callbacks (e.g., the USB_TARG_VENDOR_SPECIFIC callback) may need to
  1812. * formulate a response and send it to the host.  This function allows a
  1813. * caller to respond to a host control pipe request.
  1814. *
  1815. * There are two kinds of responses, those that involve a data phase and
  1816. * those that do not.  This function may be used to handle both types.  If
  1817. * a data phase is required, the caller passes a non-NULL <pBfr> for the 
  1818. * usbTargTransfer() function.  The usbTargControlResponseSend() function
  1819. * sends the data described by the USB_ERP and then automatically
  1820. * accepts the "status phase" transfer sent the by the host to acknowledge
  1821. * the transfer.  If there is no data phase, the <pBfr> parameter should be
  1822. * NULL, in which case usbTargLib generates just the Status phase
  1823. * automatically.
  1824. *
  1825. * The contents of the <pBfr> passed by the caller are copied into a 
  1826. * private usbTargLib buffer.  <bfrLen> must not exceed USB_MAX_DESCR_LEN.
  1827. *
  1828. * This function returns as soon as the transfer is enqueued.  
  1829. *
  1830. * RETURNS: OK, or ERROR if unable to submit response to host.
  1831. *
  1832. * ERRNO:
  1833. *   S_usbTargLib_GENERAL_FAULT
  1834. *   S_usbTargLib_BAD_PARAM
  1835. */
  1836. STATUS usbTargControlResponseSend
  1837.     (
  1838.     USB_TARG_CHANNEL targChannel, /* target channel */
  1839.     UINT16 bfrLen, /* length of response, or 0 */
  1840.     pUINT8 pBfr  /* ptr to bfr or NULL */
  1841.     )
  1842.     {
  1843.     pTARG_TCD pTcd;
  1844.     STATUS status;
  1845.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1846.     /* Validate parameters */
  1847.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  1848. {
  1849. /* If <pErp> is NULL, then just do a Status packet.  Otherwise,
  1850.  * submit the caller's ERP. 
  1851.  */
  1852. if (pBfr == NULL)
  1853.     {
  1854.     if (initStatusErp (pTcd, USB_PID_IN) != OK)
  1855. status = S_usbTargLib_GENERAL_FAULT;
  1856.     }
  1857. else
  1858.     {
  1859.     /* Transfer the caller's data. */
  1860.     if (bfrLen > sizeof (pTcd->dataBfr))
  1861. status = S_usbTargLib_BAD_PARAM;
  1862.     else
  1863. {
  1864. memcpy (pTcd->dataBfr, pBfr, bfrLen);
  1865. if (initDataErpForResponse (pTcd, bfrLen) != OK)
  1866.     status = S_usbTargLib_GENERAL_FAULT;
  1867. }
  1868.     }
  1869. }
  1870.     
  1871.     OSS_MUTEX_RELEASE (targMutex);
  1872.     return ossStatus (status);
  1873.     }
  1874. /***************************************************************************
  1875. *
  1876. * usbTargControlPayloadRcv - Receives data on the default control pipe
  1877. *
  1878. * usbTargLib automatically creates a pipe to manage communication on the
  1879. * default control pipe (#0) defined by the USB.  Certain application
  1880. * callbacks (e.g., USB_TARG_VENDOR_SPECIFIC or USB_TARG_DESCRIPTOR_SET)
  1881. * may need to receive additional data on the control OUT endpoint in order
  1882. * to complete processing of the control pipe request.  This function allows
  1883. * a caller to receive data on a control pipe.
  1884. *
  1885. * The <pErp> parameter must point to an ERP which will receive the
  1886. * additional data. 
  1887. *
  1888. * This function returns as soon as the USB_ERP is enqueued.  Completion of
  1889. * the USB_ERP is indicated when the ERP's callback is invoked. After the
  1890. * ERP completes, the application should terminate the USB request by
  1891. * invoking the usbTargControlResponseSend() function with a NULL <pBfr>
  1892. * parameter.  This will direct usbTargLib to generate a Status IN phase,
  1893. * signalling the end of the transaction.
  1894. *
  1895. * NOTE: The caller must ensure that the ERP remains valid until the ERP
  1896. * userCallback has been invoked - signalling completion of the ERP.
  1897. *
  1898. * RETURNS: OK, or ERROR if unable to submit ERP to receive additional data
  1899. */
  1900. STATUS usbTargControlPayloadRcv
  1901.     (
  1902.     USB_TARG_CHANNEL targChannel,
  1903.     pUSB_ERP pErp
  1904.     )
  1905.     {
  1906.     pTARG_TCD pTcd;
  1907.     STATUS status;
  1908.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1909.     /* Validate parameters */
  1910.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  1911. {
  1912. status = usbTargTransfer (pTcd->controlPipe, pErp);
  1913. }
  1914.     
  1915.     OSS_MUTEX_RELEASE (targMutex);
  1916.     return ossStatus (status);
  1917.     }
  1918. /***************************************************************************
  1919. *
  1920. * usbTargPipeStatusSet - sets pipe stalled/unstalled status
  1921. *
  1922. * If the target application detects an error while servicing a pipe,
  1923. * including the default control pipe, it may choose to stall the endpoint(s)
  1924. * associated with that pipe.  This function allows the caller to set the
  1925. * state of a pipe as "stalled" or "un-stalled".
  1926. *
  1927. * <pipeHandle> should be the handle of a pipe to be stalled.  A NULL
  1928. * <pipeHandle> indicates the default control pipe.  <state> indicates the
  1929. * endpoint state as TCD_ENDPOINT_STALL/UNSTALL/DATA0.  
  1930. *
  1931. * Note that the default control pipe will automatically "un-stall" upon 
  1932. * receipt of a new Setup packet.
  1933. *
  1934. * RETURNS: OK, or ERROR if unable to set indicated state
  1935. *
  1936. * ERRNO:
  1937. *   S_usbTargLib_TCD_FAULT
  1938. */
  1939. STATUS usbTargPipeStatusSet
  1940.     (
  1941.     USB_TARG_CHANNEL targChannel,
  1942.     USB_TARG_PIPE pipeHandle,
  1943.     UINT16 state
  1944.     )
  1945.     {
  1946.     pTARG_TCD pTcd;
  1947.     pTARG_PIPE pPipe;
  1948.     STATUS status;
  1949.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1950.     /* Validate parameters */
  1951.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  1952. {
  1953. /* Validate pipe */
  1954. if (pipeHandle == NULL)
  1955.     pipeHandle = pTcd->controlPipe;
  1956. status = validatePipe (pipeHandle, &pPipe);
  1957. }
  1958.     if (status == OK)
  1959. {
  1960. /* Stall endpoint(s) associated with pipe. */
  1961. if (pPipe->pEndpoint != NULL)
  1962.     if (usbTcdEndpointStateSet (&pTcd->tcdNexus, 
  1963. pPipe->pEndpoint->endpointId, state) != OK)
  1964. status = S_usbTargLib_TCD_FAULT;
  1965. if (status == OK &&
  1966.     pPipe->pEndpoint2 != NULL)
  1967.     if (usbTcdEndpointStateSet (&pTcd->tcdNexus,
  1968. pPipe->pEndpoint2->endpointId, state) != OK)
  1969. status = S_usbTargLib_TCD_FAULT;
  1970. }
  1971.     
  1972.     OSS_MUTEX_RELEASE (targMutex);
  1973.     return ossStatus (status);
  1974.     }
  1975. /***************************************************************************
  1976. *
  1977. * usbTargCurrentFrameGet - Retrieves the current USB frame number
  1978. *
  1979. * It is sometimes necessary for callers to retrieve the current USB frame 
  1980. * number.  This function allows a caller to retrieve the current USB frame 
  1981. * number for the bus to which <targChannel> is connected.  Upon return, the 
  1982. * current frame number is stored in <pFrameNo>.
  1983. *
  1984. * RETURNS: OK, or ERROR if unable to retrieve USB frame number
  1985. *
  1986. * ERRNO:
  1987. *   S_usbTargLib_TCD_FAULT
  1988. */
  1989. STATUS usbTargCurrentFrameGet
  1990.     (
  1991.     USB_TARG_CHANNEL targChannel, /* target channel */
  1992.     pUINT16 pFrameNo /* current frame number */
  1993.     )
  1994.     {
  1995.     pTARG_TCD pTcd;
  1996.     STATUS status;
  1997.     
  1998.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  1999.     /* Validate parameters */
  2000.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  2001. {
  2002. /* Get current frame number from TCD */
  2003. if (usbTcdCurrentFrameGet (&pTcd->tcdNexus, pFrameNo) != OK)
  2004.     status = S_usbTargLib_TCD_FAULT;
  2005. }
  2006.     OSS_MUTEX_RELEASE (targMutex);
  2007.     return ossStatus (status);
  2008.     }
  2009. /***************************************************************************
  2010. *
  2011. * usbTargSignalResume - Drives RESUME signalling on USB
  2012. *
  2013. * If a USB is in the SUSPENDed state, it is possible for a device (target)
  2014. * to request the bus to wake up (called remote wakeup).  This function allows
  2015. * the caller to drive USB resume signalling.  The function will return after
  2016. * resume signalling has completed.
  2017. *
  2018. * There is no guarantee that a host will honor RESUME signalling.  Therefore,
  2019. * the caller should make no assumptions about the state of the USB after
  2020. * calling this function.  Instead, the "management callback" for this 
  2021. * target channel will be invoked if the USB changes state in response to the
  2022. * RESUME signalling.
  2023. *
  2024. * RETURNS: OK, or ERROR if unable to drive RESUME signalling
  2025. *
  2026. * ERRNO:
  2027. *   S_usbTargLib_TCD_FAULT
  2028. */
  2029. STATUS usbTargSignalResume
  2030.     (
  2031.     USB_TARG_CHANNEL targChannel /* target channel */
  2032.     )
  2033.     {
  2034.     pTARG_TCD pTcd;
  2035.     STATUS status;
  2036.     OSS_MUTEX_TAKE (targMutex, OSS_BLOCK);
  2037.     /* Validate parameters */
  2038.     if ((status = validateTarg (targChannel, &pTcd)) == OK)
  2039. {
  2040. /* Have TCD drive resume signalling */
  2041. if (usbTcdSignalResume (&pTcd->tcdNexus) != OK)
  2042.     status = S_usbTargLib_TCD_FAULT;
  2043. }
  2044.     OSS_MUTEX_RELEASE (targMutex);
  2045.     return ossStatus (status);
  2046.     }
  2047. /* End of file. */