1 /*
2 * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016,2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "usb_host_config.h"
10 #if ((defined USB_HOST_CONFIG_PHDC) && (USB_HOST_CONFIG_PHDC))
11 #include "usb_host.h"
12 #include "usb_host_phdc.h"
13 /*******************************************************************************
14 * Definitions
15 ******************************************************************************/
16
17 /*******************************************************************************
18 * Prototypes
19 ******************************************************************************/
20
21 /*!
22 * @brief phdc control pipe transfer callback.
23 *
24 * @param param callback parameter.
25 * @param transfer callback transfer.
26 * @param status transfer status.
27 */
28 static void USB_HostPhdcControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
29
30 /*!
31 * @brief phdc set and clear feature endpoint halt callback.
32 *
33 * @param param callback parameter.
34 * @param transfer callback transfer.
35 * @param status transfer status.
36 */
37 static void USB_HostPhdcSetClearFeatureEndpointHaltCallback(void *param,
38 usb_host_transfer_t *transfer,
39 usb_status_t status);
40
41 /*!
42 * @brief phdc interrupt pipe transfer callback.
43 *
44 * @param param callback parameter.
45 * @param transfer callback transfer.
46 * @param status transfer status.
47 */
48 static void USB_HostPhdcInterruptPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
49
50 /*!
51 * @brief phdc bulk in pipe transfer callback.
52 *
53 * @param param callback parameter.
54 * @param transfer callback transfer.
55 * @param status transfer status.
56 */
57 static void USB_HostPhdcBulkInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
58
59 /*!
60 * @brief phdc bulk out pipe transfer callback.
61 *
62 * @param param callback parameter.
63 * @param transfer callback transfer.
64 * @param status transfer status.
65 */
66 static void USB_HostPhdcBulkOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
67
68 /*!
69 * @brief phdc set interface callback, open pipes.
70 *
71 * @param param callback parameter.
72 * @param transfer callback transfer.
73 * @param status transfer status.
74 */
75 static void USB_HostPhdcSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
76
77 /*******************************************************************************
78 * Variables
79 ******************************************************************************/
80
81 /*! @brief meta-data message preamble signature string */
82 static char const metaDataMsgPreambleSignature[] = "PhdcQoSSignature";
83
84 /*******************************************************************************
85 * Code
86 ******************************************************************************/
87
88 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
89
USB_HostPhdcClearInHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)90 static void USB_HostPhdcClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
91 {
92 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
93
94 phdcInstance->controlTransfer = NULL;
95 /* Reduces the number of bulk transfer to 0 to expect new message preamble transfer */
96 phdcInstance->numberTransferBulkIn = 0U;
97 if (phdcInstance->inCallbackFn != NULL)
98 {
99 /* callback to application, the callback function is initialized in USB_HostPhdcRecv */
100 phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, phdcInstance->stallDataBuffer,
101 phdcInstance->stallDataLength, kStatus_USB_TransferStall);
102 }
103 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
104 }
105
USB_HostPhdcClearOutHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)106 static void USB_HostPhdcClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
107 {
108 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
109
110 phdcInstance->controlTransfer = NULL;
111 if (phdcInstance->outCallbackFn != NULL)
112 {
113 /* callback to application, callback function is initialized in USB_HostPhdcSend */
114 phdcInstance->outCallbackFn(phdcInstance->outCallbackParam, phdcInstance->stallDataBuffer,
115 phdcInstance->stallDataLength, kStatus_USB_TransferStall);
116 }
117 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
118 }
119
USB_HostPhdcClearHalt(usb_host_phdc_instance_t * phdcInstance,usb_host_transfer_t * stallTransfer,host_inner_transfer_callback_t callbackFn,uint8_t endpoint)120 static usb_status_t USB_HostPhdcClearHalt(usb_host_phdc_instance_t *phdcInstance,
121 usb_host_transfer_t *stallTransfer,
122 host_inner_transfer_callback_t callbackFn,
123 uint8_t endpoint)
124 {
125 usb_status_t status;
126 usb_host_transfer_t *transfer;
127
128 /* malloc one transfer */
129 status = USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer);
130 if (status != kStatus_USB_Success)
131 {
132 #ifdef HOST_ECHO
133 usb_echo("allocate transfer error\r\n");
134 #endif
135 return status;
136 }
137 phdcInstance->stallDataBuffer = stallTransfer->transferBuffer;
138 phdcInstance->stallDataLength = stallTransfer->transferSofar;
139 /* save the application callback function */
140 phdcInstance->controlCallbackFn = NULL;
141 phdcInstance->controlCallbackParam = NULL;
142 /* initialize transfer */
143 transfer->callbackFn = callbackFn;
144 transfer->callbackParam = phdcInstance;
145 transfer->transferBuffer = NULL;
146 transfer->transferLength = 0;
147 transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_CLEAR_FEATURE;
148 transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
149 transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT);
150 transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(endpoint);
151 transfer->setupPacket->wLength = 0;
152 status = USB_HostSendSetup(phdcInstance->hostHandle, phdcInstance->controlPipe, transfer);
153
154 if (status != kStatus_USB_Success)
155 {
156 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
157 }
158 phdcInstance->controlTransfer = transfer;
159
160 return status;
161 }
162
163 #endif
164
165 /*!
166 * @brief phdc control pipe transfer callback.
167 *
168 * @param param callback parameter.
169 * @param transfer callback transfer.
170 * @param status transfer status.
171 */
USB_HostPhdcControlPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)172 static void USB_HostPhdcControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
173 {
174 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
175 phdcInstance->controlTransfer = NULL;
176 if (kStatus_USB_Success == status)
177 {
178 if (USB_HOST_PHDC_SET_FEATURE_REQUEST == transfer->setupPacket->bRequest)
179 {
180 /* Meta-data message preamble feature is enabled */
181 phdcInstance->isMessagePreambleEnabled = 1U;
182 }
183 else if (USB_HOST_PHDC_CLEAR_FEATURE_REQUEST == transfer->setupPacket->bRequest)
184 {
185 /* Meta-data message preamble feature is disable */
186 phdcInstance->isMessagePreambleEnabled = 0U;
187 }
188 else
189 {
190 /*no action*/
191 }
192 }
193 if (NULL != phdcInstance->controlCallbackFn)
194 {
195 /* callback function is initialized in USB_HostPhdcSetInterface */
196 phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, transfer->transferBuffer,
197 transfer->transferSofar, status);
198 }
199 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
200 }
201
202 /*!
203 * @brief phdc set and clear feature endpoint halt callback for meta-data message preamble error.
204 *
205 * @param param callback parameter.
206 * @param transfer callback transfer.
207 * @param status transfer status.
208 */
USB_HostPhdcSetClearFeatureEndpointHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)209 static void USB_HostPhdcSetClearFeatureEndpointHaltCallback(void *param,
210 usb_host_transfer_t *transfer,
211 usb_status_t status)
212 {
213 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
214 phdcInstance->controlTransfer = NULL;
215 if (kStatus_USB_Success == status)
216 {
217 if ((transfer->setupPacket->bRequest == USB_REQUEST_STANDARD_SET_FEATURE) &&
218 (transfer->setupPacket->bmRequestType == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT) &&
219 (transfer->setupPacket->wValue ==
220 USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT)) &&
221 (transfer->setupPacket->wIndex ==
222 USB_SHORT_TO_LITTLE_ENDIAN(phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress)))
223 {
224 /* The host shall issue CLEAR_FEATURE ENDPOINT_HALT request to the device */
225 usb_host_process_feature_param_t featureParam;
226 featureParam.requestType = (uint8_t)kRequestEndpoint;
227 featureParam.featureSelector = USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT;
228 featureParam.interfaceOrEndpoint = phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress;
229 if (kStatus_USB_Success != USB_HostPhdcSetClearFeatureEndpointHalt(phdcInstance->hostHandle,
230 USB_REQUEST_STANDARD_CLEAR_FEATURE,
231 &featureParam, NULL, NULL))
232 {
233 #ifdef HOST_ECHO
234 usb_echo("Error for USB_HostPhdcSetClearFeatureEndpointHalt\r\n");
235 #endif
236 }
237 }
238 if ((transfer->setupPacket->bRequest == USB_REQUEST_STANDARD_CLEAR_FEATURE) &&
239 (transfer->setupPacket->bmRequestType == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT) &&
240 (transfer->setupPacket->wValue ==
241 USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT)) &&
242 (transfer->setupPacket->wIndex ==
243 USB_SHORT_TO_LITTLE_ENDIAN(phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress)))
244 {
245 /* Reduces the number of bulk transfer to 0 to expect new message preamble transfer */
246 phdcInstance->numberTransferBulkIn = 0U;
247 }
248 }
249 if (NULL != phdcInstance->controlCallbackFn)
250 {
251 /* Notify to application the status of request, callback function is initialized in USB_HostPhdcSetInterface */
252 phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, transfer->transferBuffer,
253 transfer->transferSofar, status);
254 }
255 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
256 }
257
258 /*!
259 * @brief phdc interrupt pipe transfer callback.
260 *
261 * @param param callback parameter.
262 * @param transfer callback transfer.
263 * @param status transfer status.
264 */
USB_HostPhdcInterruptPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)265 static void USB_HostPhdcInterruptPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
266 {
267 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
268
269 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
270 if (status == kStatus_USB_TransferStall)
271 {
272 if (USB_HostPhdcClearHalt(
273 phdcInstance, transfer, USB_HostPhdcClearInHaltCallback,
274 (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)phdcInstance->interruptPipe)->endpointAddress)) ==
275 kStatus_USB_Success)
276 {
277 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
278 return;
279 }
280 }
281 #endif
282 if (NULL != phdcInstance->inCallbackFn)
283 {
284 /* callback to application, the callback function is initialized in USB_HostPhdcRecv */
285 phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
286 status);
287 }
288 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
289 }
290
291 /*!
292 * @brief phdc bulk in pipe transfer callback.
293 *
294 * @param param callback parameter.
295 * @param transfer callback transfer.
296 * @param status transfer status.
297 */
USB_HostPhdcBulkInPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)298 static void USB_HostPhdcBulkInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
299 {
300 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
301 void *temp;
302 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
303 if (status == kStatus_USB_TransferStall)
304 {
305 if (USB_HostPhdcClearHalt(
306 phdcInstance, transfer, USB_HostPhdcClearInHaltCallback,
307 (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)phdcInstance->bulkInPipe)->endpointAddress)) ==
308 kStatus_USB_Success)
309 {
310 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
311 return;
312 }
313 }
314 #endif
315 if (status == kStatus_USB_Success)
316 {
317 /* The meta-data message preamble is implemented and enabled */
318 if (phdcInstance->isMessagePreambleEnabled == 1U)
319 {
320 /* The meta-data message preamble feature is enabled, then all data transfers or sets
321 of data transfers shall be preceded by a meta-data message preamble transfer. The
322 numberTransferBulkIn is initialized as zero for receiving this message preamble data,
323 then it is updated to the value of bNumTransfers field of message preamble data */
324 if (0U != phdcInstance->numberTransferBulkIn)
325 {
326 /* When numberTransferBulkIn reduces to 0, a new meta-data message preamble shall
327 be transferred */
328 phdcInstance->numberTransferBulkIn--;
329 }
330 else
331 {
332 uint8_t preambleSignatureChecking = 1U;
333 /* The received packet is meta-data message preamble */
334 temp = (void *)transfer->transferBuffer;
335 usb_host_phdc_metadata_preamble_t *metaDataMsgPreamble = (usb_host_phdc_metadata_preamble_t *)temp;
336 /* Meta-data message preamble signature checking */
337 for (uint8_t i = 0U; i < USB_HOST_PHDC_MESSAGE_PREAMBLE_SIGNATURE_SIZE; i++)
338 {
339 if (*(transfer->transferBuffer + i) != (uint8_t)metaDataMsgPreambleSignature[i])
340 {
341 preambleSignatureChecking = 0U;
342 break;
343 }
344 }
345 if (0U != preambleSignatureChecking)
346 {
347 /* Checks if the meta-data message preamble contains an invalid bmLatencyReliability value
348 or bNumTransfers value */
349 if ((0U == (metaDataMsgPreamble->bNumberTransfers)) || /* bNumTransfers shall never equal zero */
350 (metaDataMsgPreamble->bQosEncodingVersion != 0x01U) || /* Encoding version should be 0x01 */
351 ((metaDataMsgPreamble->bmLatencyReliability !=
352 0x02U) && /* Medium.Good latency, reliability bin */
353 (metaDataMsgPreamble->bmLatencyReliability !=
354 0x04U) && /* Medium.Better latency, reliability bin */
355 (metaDataMsgPreamble->bmLatencyReliability !=
356 0x08U) && /* Medium.Best latency, reliability bin */
357 (metaDataMsgPreamble->bmLatencyReliability !=
358 0x10U) && /* High.Best latency, reliability bin */
359 (metaDataMsgPreamble->bmLatencyReliability !=
360 0x20U) /* VeryHigh.Best latency, reliability bin */))
361 {
362 /* The host shall issue SET_FEATURE ENDPOINT_HALT request to the device */
363 usb_host_process_feature_param_t featureParam;
364 featureParam.requestType = (uint8_t)kRequestEndpoint;
365 featureParam.featureSelector = USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT;
366 featureParam.interfaceOrEndpoint =
367 phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress;
368 if (kStatus_USB_Success !=
369 USB_HostPhdcSetClearFeatureEndpointHalt(
370 phdcInstance->hostHandle, USB_REQUEST_STANDARD_SET_FEATURE, &featureParam, NULL, NULL))
371 {
372 #ifdef HOST_ECHO
373 usb_echo(
374 "USB_HostPhdcBulkInPipeCallback: Error for "
375 "USB_HostPhdcSetClearFeatureEndpointHalt\r\n");
376 #endif
377 }
378 }
379 else
380 {
381 /* The meta-data message preamble data is correct, update the phdc status and
382 * numberTransferBulkIn value */
383 phdcInstance->numberTransferBulkIn = metaDataMsgPreamble->bNumberTransfers;
384 }
385 }
386 }
387 }
388 }
389 if (NULL != phdcInstance->inCallbackFn)
390 {
391 /* callback to application, the callback function is initialized in USB_HostPhdcRecv */
392 phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
393 status);
394 }
395 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
396 }
397
398 /*!
399 * @brief phdc bulk out pipe transfer callback.
400 *
401 * @param param callback parameter.
402 * @param transfer callback transfer.
403 * @param status transfer status.
404 */
USB_HostPhdcBulkOutPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)405 static void USB_HostPhdcBulkOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
406 {
407 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
408
409 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
410 if (status == kStatus_USB_TransferStall)
411 {
412 if (USB_HostPhdcClearHalt(
413 phdcInstance, transfer, USB_HostPhdcClearOutHaltCallback,
414 (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)phdcInstance->bulkOutPipe)->endpointAddress)) ==
415 kStatus_USB_Success)
416 {
417 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
418 return;
419 }
420 }
421 #endif
422 if (NULL != phdcInstance->outCallbackFn)
423 {
424 /* callback to application, callback function is initialized in USB_HostPhdcSend */
425 phdcInstance->outCallbackFn(phdcInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar,
426 status);
427 }
428 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
429 }
430
431 /*!
432 * @brief phdc open interface.
433 *
434 * @param phdcInstance phdc instance pointer.
435 *
436 * @return kStatus_USB_Success or error codes.
437 */
USB_HostPhdcOpenInterface(usb_host_phdc_instance_t * phdcInstance)438 static usb_status_t USB_HostPhdcOpenInterface(usb_host_phdc_instance_t *phdcInstance)
439 {
440 usb_status_t status;
441 uint8_t epIndex = 0U;
442 usb_host_pipe_init_t pipeInit;
443 usb_descriptor_endpoint_t *epDesc = NULL;
444 usb_host_interface_t *interface;
445 if (NULL != phdcInstance->interruptPipe)
446 {
447 /* Close the PHDC interrupt pipe if it is opening */
448 status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->interruptPipe);
449
450 if (status != kStatus_USB_Success)
451 {
452 #ifdef HOST_ECHO
453 usb_echo("USB_HostPhdcOpenInterface: Error when close pipe\r\n");
454 #endif
455 }
456 phdcInstance->interruptPipe = NULL;
457 }
458
459 if (NULL != phdcInstance->bulkInPipe)
460 {
461 /* Close the PHDC bulk in pipe if it is opening */
462 status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkInPipe);
463
464 if (status != kStatus_USB_Success)
465 {
466 #ifdef HOST_ECHO
467 usb_echo("USB_HostPhdcOpenInterface: Error when close pipe\r\n");
468 #endif
469 }
470 phdcInstance->bulkInPipe = NULL;
471 }
472
473 if (NULL != phdcInstance->bulkOutPipe)
474 {
475 /* Close the PHDC bulk out pipe if it is opening */
476 status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkOutPipe);
477
478 if (status != kStatus_USB_Success)
479 {
480 #ifdef HOST_ECHO
481 usb_echo("USB_HostPhdcOpenInterface: Error when close pipe\r\n");
482 #endif
483 }
484 phdcInstance->bulkOutPipe = NULL;
485 }
486
487 /* open interface pipes */
488 interface = (usb_host_interface_t *)phdcInstance->interfaceHandle;
489 for (epIndex = 0U; epIndex < interface->epCount; ++epIndex)
490 {
491 epDesc = interface->epList[epIndex].epDesc;
492 if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
493 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
494 ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
495 {
496 /* Initialize the interrupt pipe */
497 pipeInit.devInstance = phdcInstance->deviceHandle;
498 pipeInit.pipeType = USB_ENDPOINT_INTERRUPT;
499 pipeInit.direction = USB_IN;
500 pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
501 pipeInit.interval = epDesc->bInterval;
502 pipeInit.maxPacketSize = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
503 USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
504 pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
505 USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
506 pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
507 status = USB_HostOpenPipe(phdcInstance->hostHandle, &phdcInstance->interruptPipe, &pipeInit);
508 if (status != kStatus_USB_Success)
509 {
510 #ifdef HOST_ECHO
511 usb_echo("USB_HostPhdcOpenInterface: Error when open pipe\r\n");
512 #endif
513 return kStatus_USB_Error;
514 }
515 /* save interrupt in endpoint information */
516 phdcInstance->interruptInEndpointInformation = interface->epList[epIndex];
517 }
518 else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
519 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
520 ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
521 {
522 /* Initialize bulk in pipe */
523 pipeInit.devInstance = phdcInstance->deviceHandle;
524 pipeInit.pipeType = USB_ENDPOINT_BULK;
525 pipeInit.direction = USB_IN;
526 pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
527 pipeInit.maxPacketSize = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
528 USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
529 pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
530 USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
531 pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
532 pipeInit.interval = 0U;
533 status = USB_HostOpenPipe(phdcInstance->hostHandle, &phdcInstance->bulkInPipe, &pipeInit);
534 if (status != kStatus_USB_Success)
535 {
536 #ifdef HOST_ECHO
537 usb_echo("USB_HostPhdcOpenInterface: Error when open pipe\r\n");
538 #endif
539 return kStatus_USB_Error;
540 }
541 /* save bulk in endpoint information */
542 phdcInstance->bulkInEndpointInformation = interface->epList[epIndex];
543 }
544 else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
545 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
546 ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
547 {
548 /* Initialize bulk out pipe */
549 pipeInit.devInstance = phdcInstance->deviceHandle;
550 pipeInit.pipeType = USB_ENDPOINT_BULK;
551 pipeInit.direction = USB_OUT;
552 pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
553 pipeInit.maxPacketSize = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
554 USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
555 pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
556 USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
557 pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
558 pipeInit.interval = 0U;
559 status = USB_HostOpenPipe(phdcInstance->hostHandle, &phdcInstance->bulkOutPipe, &pipeInit);
560 if (status != kStatus_USB_Success)
561 {
562 #ifdef HOST_ECHO
563 usb_echo("USB_HostPhdcOpenInterface: Error when open pipe\r\n");
564 #endif
565 return kStatus_USB_Error;
566 }
567 /* save bulk out endpoint information */
568 phdcInstance->bulkOutEndpointInformation = interface->epList[epIndex];
569 }
570 else
571 {
572 /*no action*/
573 }
574 }
575 return kStatus_USB_Success;
576 }
577
578 /*!
579 * @brief phdc set interface callback, open pipes.
580 *
581 * @param param callback parameter.
582 * @param transfer callback transfer.
583 * @param status transfer status.
584 */
USB_HostPhdcSetInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)585 static void USB_HostPhdcSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
586 {
587 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param;
588
589 phdcInstance->controlTransfer = NULL;
590 if (status == kStatus_USB_Success)
591 {
592 /* set interface is done, open the interface */
593 status = USB_HostPhdcOpenInterface(phdcInstance);
594 }
595
596 if (NULL != phdcInstance->controlCallbackFn)
597 {
598 /* Notify to application the status of set interface request, callback function is initialized in
599 * USB_HostPhdcSetInterface */
600 phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, NULL, 0U, status);
601 }
602 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
603 }
604
605 /*!
606 * @brief set interface.
607 *
608 * This function binds the interface with the phdc instance.
609 *
610 * @param classHandle the class handle.
611 * @param interfaceHandle the interface handle.
612 * @param alternateSetting the alternate setting value.
613 * @param callbackFn this callback is called after this function completes.
614 * @param callbackParam the first parameter in the callback function.
615 *
616 * @retval kStatus_USB_Success The device is initialized successfully.
617 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
618 * @retval kStatus_USB_Busy There is no idle transfer.
619 * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup.
620 * @retval kStatus_USB_Busy callback return status, there is no idle pipe.
621 * @retval kStatus_USB_TransferStall callback return status, the transfer is stall by device.
622 * @retval kStatus_USB_Error callback return status, open pipe fail, please reference to USB_HostOpenPipe.
623 */
USB_HostPhdcSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)624 usb_status_t USB_HostPhdcSetInterface(usb_host_class_handle classHandle,
625 usb_host_interface_handle interfaceHandle,
626 uint8_t alternateSetting,
627 transfer_callback_t callbackFn,
628 void *callbackParam)
629 {
630 usb_status_t status;
631 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle;
632 usb_host_transfer_t *transfer;
633
634 if (NULL == classHandle)
635 {
636 return kStatus_USB_InvalidParameter;
637 }
638
639 phdcInstance->interfaceHandle = interfaceHandle;
640
641 status = USB_HostOpenDeviceInterface(phdcInstance->deviceHandle, interfaceHandle);
642 if (status != kStatus_USB_Success)
643 {
644 return status;
645 }
646
647 /* Cancel interrupt transfers */
648 if (NULL != phdcInstance->interruptPipe)
649 {
650 status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->interruptPipe, NULL);
651 if (status != kStatus_USB_Success)
652 {
653 #ifdef HOST_ECHO
654 usb_echo("USB_HostPhdcSetInterface: Error when cancel pipe\r\n");
655 #endif
656 }
657 }
658 /* Cancel bulk in transfers */
659 if (NULL != phdcInstance->bulkInPipe)
660 {
661 status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkInPipe, NULL);
662 if (status != kStatus_USB_Success)
663 {
664 #ifdef HOST_ECHO
665 usb_echo("USB_HostPhdcSetInterface: Error when cancel pipe\r\n");
666 #endif
667 }
668 }
669 /* Cancel bulk out transfers */
670 if (NULL != phdcInstance->bulkOutPipe)
671 {
672 status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkOutPipe, NULL);
673 if (status != kStatus_USB_Success)
674 {
675 #ifdef HOST_ECHO
676 usb_echo("USB_HostPhdcSetInterface: Error when cancel pipe\r\n");
677 #endif
678 }
679 phdcInstance->bulkOutPipe = NULL;
680 }
681 if (0U == alternateSetting)
682 {
683 if (NULL != callbackFn)
684 {
685 status = USB_HostPhdcOpenInterface(phdcInstance);
686 callbackFn(callbackParam, NULL, 0U, status);
687 }
688 }
689 else
690 {
691 /* Create transfer buffer */
692 if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
693 {
694 #ifdef HOST_ECHO
695 usb_echo("USB_HostPhdcSetInterface: Error to get transfer\r\n");
696 #endif
697 return kStatus_USB_Error;
698 }
699 /* Save application callback function and parameter */
700 phdcInstance->controlCallbackFn = callbackFn;
701 phdcInstance->controlCallbackParam = callbackParam;
702 /* Initialize transfer */
703 transfer->callbackFn = USB_HostPhdcSetInterfaceCallback;
704 transfer->callbackParam = phdcInstance;
705 transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_INTERFACE;
706 transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
707 transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(
708 ((usb_host_interface_t *)phdcInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
709 transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
710 transfer->setupPacket->wLength = 0;
711 transfer->transferBuffer = NULL;
712 transfer->transferLength = 0;
713 /* Send set interface request to device */
714 status = USB_HostSendSetup(phdcInstance->hostHandle, phdcInstance->controlPipe, transfer);
715 if (status == kStatus_USB_Success)
716 {
717 phdcInstance->controlTransfer = transfer;
718 }
719 else
720 {
721 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
722 }
723 }
724 return status;
725 }
726
727 /*!
728 * @brief initialize the phdc instance.
729 *
730 * This function allocates the resource for phdc instance.
731 *
732 * @param deviceHandle the device handle.
733 * @param classHandle return class handle.
734 *
735 * @retval kStatus_USB_Success The device is initialized successfully.
736 * @retval kStatus_USB_AllocFail Allocate memory fail.
737 */
USB_HostPhdcInit(usb_host_handle deviceHandle,usb_host_class_handle * classHandle)738 usb_status_t USB_HostPhdcInit(usb_host_handle deviceHandle, usb_host_class_handle *classHandle)
739 {
740 usb_host_phdc_instance_t *phdcInstance =
741 (usb_host_phdc_instance_t *)OSA_MemoryAllocate(sizeof(usb_host_phdc_instance_t));
742 uint32_t infoValue = 0U;
743 uint32_t *temp;
744 if (NULL == phdcInstance)
745 {
746 return kStatus_USB_AllocFail;
747 }
748 /* Initialize PHDC instance */
749 phdcInstance->deviceHandle = deviceHandle;
750 phdcInstance->interfaceHandle = NULL;
751 (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &infoValue);
752 temp = (uint32_t *)infoValue;
753 phdcInstance->hostHandle = (usb_host_handle)temp;
754 (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &infoValue);
755 temp = (uint32_t *)infoValue;
756 phdcInstance->controlPipe = (usb_host_pipe_handle)temp;
757
758 *classHandle = phdcInstance;
759 return kStatus_USB_Success;
760 }
761
762 /*!
763 * @brief de-initialize the phdc instance.
764 *
765 * This function release the resource for phdc instance.
766 *
767 * @param deviceHandle the device handle.
768 * @param classHandle the class handle.
769 *
770 * @retval kStatus_USB_Success The device is de-initialized successfully.
771 */
USB_HostPhdcDeinit(usb_host_handle deviceHandle,usb_host_class_handle classHandle)772 usb_status_t USB_HostPhdcDeinit(usb_host_handle deviceHandle, usb_host_class_handle classHandle)
773 {
774 usb_status_t status;
775 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle;
776
777 if (NULL == deviceHandle)
778 {
779 return kStatus_USB_InvalidHandle;
780 }
781
782 if (NULL != classHandle)
783 {
784 if (NULL != phdcInstance->interruptPipe)
785 {
786 /* Cancel/close interrupt transfers/pipe */
787 status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->interruptPipe, NULL);
788 if (status != kStatus_USB_Success)
789 {
790 #ifdef HOST_ECHO
791 usb_echo("error when cancel pipe\r\n");
792 #endif
793 }
794 status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->interruptPipe);
795
796 if (status != kStatus_USB_Success)
797 {
798 #ifdef HOST_ECHO
799 usb_echo("USB_HostPhdcDeinit: Error when close pipe\r\n");
800 #endif
801 }
802 phdcInstance->interruptPipe = NULL;
803 }
804 if (NULL != phdcInstance->bulkInPipe)
805 {
806 /* Cancel/close bulk in transfers/pipe */
807 status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkInPipe, NULL);
808 if (status != kStatus_USB_Success)
809 {
810 #ifdef HOST_ECHO
811 usb_echo("error when cancel pipe\r\n");
812 #endif
813 }
814 status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkInPipe);
815
816 if (status != kStatus_USB_Success)
817 {
818 #ifdef HOST_ECHO
819 usb_echo("USB_HostPhdcDeinit: Error when close pipe\r\n");
820 #endif
821 }
822 phdcInstance->bulkInPipe = NULL;
823 }
824 if (NULL != phdcInstance->bulkOutPipe)
825 {
826 /* Cancel/close bulk out transfers/pipe */
827 status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkOutPipe, NULL);
828 if (status != kStatus_USB_Success)
829 {
830 #ifdef HOST_ECHO
831 usb_echo("error when cancel pipe\r\n");
832 #endif
833 }
834 status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkOutPipe);
835
836 if (status != kStatus_USB_Success)
837 {
838 #ifdef HOST_ECHO
839 usb_echo("USB_HostPhdcDeinit: Error when close pipe\r\n");
840 #endif
841 }
842 phdcInstance->bulkOutPipe = NULL;
843 }
844 if ((NULL != phdcInstance->controlPipe) && (NULL != phdcInstance->controlTransfer))
845 {
846 /* Cancel control transfers */
847 status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->controlPipe,
848 phdcInstance->controlTransfer);
849 if (status != kStatus_USB_Success)
850 {
851 #ifdef HOST_ECHO
852 usb_echo("error when cancel pipe\r\n");
853 #endif
854 }
855 }
856 /* Close device interface */
857 (void)USB_HostCloseDeviceInterface(deviceHandle, phdcInstance->interfaceHandle);
858 /* Release PHDC instance */
859 OSA_MemoryFree(phdcInstance);
860 }
861 else
862 {
863 (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
864 }
865 return kStatus_USB_Success;
866 }
867
868 /*!
869 * @brief receive data.
870 *
871 * This function implements phdc receiving data.
872 *
873 * @param classHandle the class handle.
874 * @param qos QoS of the data being received.
875 * @param buffer the buffer pointer.
876 * @param bufferLength the buffer length.
877 * @param callbackFn this callback is called after this function completes.
878 * @param callbackParam the first parameter in the callback function.
879 *
880 * @retval kStatus_USB_Success receive request successfully.
881 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
882 * @retval kStatus_USB_Busy There is no idle transfer.
883 * @retval kStatus_USB_Error pipe is not initialized.
884 * Or, send transfer fail, please reference to USB_HostRecv.
885 */
USB_HostPhdcRecv(usb_host_class_handle classHandle,uint8_t qos,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)886 usb_status_t USB_HostPhdcRecv(usb_host_class_handle classHandle,
887 uint8_t qos,
888 uint8_t *buffer,
889 uint32_t bufferLength,
890 transfer_callback_t callbackFn,
891 void *callbackParam)
892 {
893 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle;
894 usb_host_transfer_t *transfer;
895 usb_host_pipe_handle pipe;
896 usb_host_phdc_qos_descriptor_t *qosDesc = NULL;
897 void *temp;
898 if (NULL == classHandle)
899 {
900 return kStatus_USB_InvalidHandle;
901 }
902
903 if ((NULL == phdcInstance->interruptPipe) && (NULL == phdcInstance->bulkInPipe))
904 {
905 return kStatus_USB_Error;
906 }
907 /* Allocate the transfer buffer */
908 if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
909 {
910 #ifdef HOST_ECHO
911 usb_echo("error to get transfer\r\n");
912 #endif
913 return kStatus_USB_Error;
914 }
915 /* Save application callback function and parameter */
916 phdcInstance->inCallbackFn = callbackFn;
917 phdcInstance->inCallbackParam = callbackParam;
918 /* Initialize the transfer pointer */
919 transfer->transferBuffer = buffer;
920 transfer->transferLength = bufferLength;
921 transfer->callbackParam = phdcInstance;
922 /* The on can receive the data on interrupt pipe or bulk in pipe depends on the QoS value */
923 pipe = (0U != (qos & 0x01U)) ? (phdcInstance->interruptPipe) : (phdcInstance->bulkInPipe);
924 if (pipe == phdcInstance->bulkInPipe)
925 {
926 /* get bulk in QoS descriptor */
927 temp = (void *)phdcInstance->bulkInEndpointInformation.epExtension;
928 qosDesc = (usb_host_phdc_qos_descriptor_t *)temp;
929 transfer->callbackFn = USB_HostPhdcBulkInPipeCallback;
930 }
931 else
932 {
933 /* get interrupt in QoS descriptor */
934 temp = (void *)phdcInstance->interruptInEndpointInformation.epExtension;
935 qosDesc = (usb_host_phdc_qos_descriptor_t *)temp;
936 transfer->callbackFn = USB_HostPhdcInterruptPipeCallback;
937 }
938 /* Latency and reliability checking */
939 if (0U == (qos & qosDesc->bmLatencyReliability))
940 {
941 #ifdef HOST_ECHO
942 usb_echo("USB_HostPhdcRecv, ERROR: invalid QoS bin");
943 #endif
944 return kStatus_USB_Error;
945 }
946 /* The previous control transfer is pending */
947 if (NULL != phdcInstance->controlTransfer)
948 {
949 #ifdef HOST_ECHO
950 usb_echo("USB_HostPhdcRecv, ERROR: Control transfer is in progress");
951 #endif
952 return kStatus_USB_Busy;
953 }
954 if (USB_HostRecv(phdcInstance->hostHandle, pipe, transfer) != kStatus_USB_Success)
955 {
956 #ifdef HOST_ECHO
957 usb_echo("fail to USB_HostRecv\r\n");
958 #endif
959 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
960 return kStatus_USB_Error;
961 }
962
963 return kStatus_USB_Success;
964 }
965
966 /*!
967 * @brief send data.
968 *
969 * This function implements phdc sending data.
970 *
971 * @param classHandle the class handle.
972 * @param buffer the buffer pointer.
973 * @param bufferLength the buffer length.
974 * @param callbackFn this callback is called after this function completes.
975 * @param callbackParam the first parameter in the callback function.
976 *
977 * @retval kStatus_USB_Success send request successfully.
978 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
979 * @retval kStatus_USB_Busy There is no idle transfer.
980 * @retval kStatus_USB_Error pipe is not initialized.
981 * Or, send transfer fail, please reference to USB_HostSend.
982 */
USB_HostPhdcSend(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)983 usb_status_t USB_HostPhdcSend(usb_host_class_handle classHandle,
984 uint8_t *buffer,
985 uint32_t bufferLength,
986 transfer_callback_t callbackFn,
987 void *callbackParam)
988 {
989 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle;
990 usb_host_transfer_t *transfer;
991 void *temp;
992 usb_host_phdc_metadata_preamble_t *preamble;
993 usb_status_t status;
994 if (classHandle == NULL)
995 {
996 return kStatus_USB_InvalidHandle;
997 }
998
999 if (NULL == phdcInstance->bulkOutPipe)
1000 {
1001 return kStatus_USB_Error;
1002 }
1003 if (NULL != phdcInstance->controlTransfer)
1004 {
1005 status = kStatus_USB_Busy;
1006 #ifdef HOST_ECHO
1007 usb_echo("USB_HostPhdcSend, Error: control transfer is in progress");
1008 #endif
1009 return status;
1010 }
1011 /* The meta-data message preamble is implemented and enabled */
1012 if (phdcInstance->isMessagePreambleEnabled == 1U)
1013 {
1014 /* The meta-data message preamble feature is enabled, then all data transfers or sets
1015 of data transfers shall be preceded by a meta-data message preamble transfer. The
1016 numberTransferBulkOut is initialized as zero for sending this message preamble data,
1017 then it is updated to the value of bNumTransfers field of message preamble data */
1018 if (0U != phdcInstance->numberTransferBulkOut)
1019 {
1020 /* When numberTransferBulkOut reduces to 0, a new meta-data message preamble shall
1021 be transferred */
1022 phdcInstance->numberTransferBulkOut--;
1023 }
1024 else
1025 {
1026 temp = (void *)phdcInstance->bulkOutEndpointInformation.epExtension;
1027 usb_host_phdc_qos_descriptor_t *qosDesc = (usb_host_phdc_qos_descriptor_t *)temp;
1028 temp = (void *)buffer;
1029 preamble = (usb_host_phdc_metadata_preamble_t *)temp;
1030 uint8_t latencyReliability = preamble->bmLatencyReliability;
1031 /* Latency reliability validity checking */
1032 if ((latencyReliability != 0x02U) && /* Medium.Good latency, reliability bin */
1033 (latencyReliability != 0x04U) && /* Medium.Better latency, reliability bin */
1034 (latencyReliability != 0x08U) && /* Medium.Best latency, reliability bin */
1035 (latencyReliability != 0x10U) && /* High.Best latency, reliability bin */
1036 (latencyReliability != 0x20U) /* VeryHigh.Best latency, reliability bin */)
1037 {
1038 status = kStatus_USB_InvalidRequest;
1039 #ifdef HOST_ECHO
1040 usb_echo("USB_HostPhdcSend, Error: invalid LatencyReliability");
1041 #endif
1042 return status;
1043 }
1044 /* LatencyReliablity checking */
1045 if (0U == (qosDesc->bmLatencyReliability & latencyReliability))
1046 {
1047 status = kStatus_USB_Error;
1048 #ifdef HOST_ECHO
1049 usb_echo("USB_HostPhdcSend, Error: the latency reliability is not supported by Bulk OUT endpoint");
1050 #endif
1051 return status;
1052 }
1053 if (0U == preamble->bNumberTransfers)
1054 {
1055 status = kStatus_USB_Error;
1056 #ifdef HOST_ECHO
1057 usb_echo("USB_HostPhdcSend, Error: the numTransfer should never zero");
1058 #endif
1059 return status;
1060 }
1061 /* Update the number of bulk out transfer */
1062 phdcInstance->numberTransferBulkOut = preamble->bNumberTransfers;
1063 }
1064 }
1065 /* Allocate the transfer pointer */
1066 if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
1067 {
1068 #ifdef HOST_ECHO
1069 usb_echo("error to get transfer\r\n");
1070 #endif
1071 return kStatus_USB_Error;
1072 }
1073 /* Save the application callback function and parameter */
1074 phdcInstance->outCallbackFn = callbackFn;
1075 phdcInstance->outCallbackParam = callbackParam;
1076 /* Initialize the transfer pointer */
1077 transfer->transferBuffer = buffer;
1078 transfer->transferLength = bufferLength;
1079 transfer->callbackFn = USB_HostPhdcBulkOutPipeCallback;
1080 transfer->callbackParam = phdcInstance;
1081 if (USB_HostSend(phdcInstance->hostHandle, phdcInstance->bulkOutPipe, transfer) != kStatus_USB_Success)
1082 {
1083 #ifdef HOST_ECHO
1084 usb_echo("fail to USB_HostSend\r\n");
1085 #endif
1086 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
1087 return kStatus_USB_Error;
1088 }
1089 return kStatus_USB_Success;
1090 }
1091
1092 /*!
1093 * @brief phdc sends control request.
1094 *
1095 * @param classHandle the class handle.
1096 * @param request_type setup packet request.
1097 * @param callbackFn this callback is called after this function completes.
1098 * @param callbackParam the first parameter in the callback function.
1099 *
1100 * @retval kStatus_USB_Success send request successfully.
1101 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
1102 * @retval kStatus_USB_Busy There is no idle transfer.
1103 * @retval kStatus_USB_Error pipe is not initialized.
1104 * Or, send transfer fail, please reference to USB_HostSend.
1105 */
USB_HostPhdcSendControlRequest(usb_host_class_handle classHandle,uint8_t request,transfer_callback_t callbackFn,void * callbackParam)1106 usb_status_t USB_HostPhdcSendControlRequest(usb_host_class_handle classHandle,
1107 uint8_t request,
1108 transfer_callback_t callbackFn,
1109 void *callbackParam)
1110 {
1111 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle;
1112 usb_status_t status = kStatus_USB_Success;
1113 usb_host_transfer_t *transfer;
1114
1115 if (NULL == classHandle)
1116 {
1117 return kStatus_USB_InvalidHandle;
1118 }
1119
1120 if (NULL == phdcInstance->controlPipe)
1121 {
1122 return kStatus_USB_Error;
1123 }
1124
1125 if (NULL != phdcInstance->controlTransfer)
1126 {
1127 return kStatus_USB_Busy;
1128 }
1129 /* Allocate the transfer pointer */
1130 if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
1131 {
1132 #ifdef HOST_ECHO
1133 usb_echo("error to get transfer\r\n");
1134 #endif
1135 return kStatus_USB_Error;
1136 }
1137 /* Save the callback function and parameter */
1138 phdcInstance->controlCallbackFn = callbackFn;
1139 phdcInstance->controlCallbackParam = callbackParam;
1140 /* Initialize the transfer pointer */
1141 transfer->callbackFn = USB_HostPhdcControlPipeCallback;
1142 transfer->callbackParam = phdcInstance;
1143 transfer->setupPacket->bRequest = request;
1144 transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(
1145 ((usb_host_interface_t *)phdcInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
1146 switch (request)
1147 {
1148 case USB_HOST_PHDC_GET_STATUS_REQUEST:
1149 /* Initialize the PHDC get status request */
1150 transfer->setupPacket->wValue = 0U;
1151 transfer->setupPacket->bmRequestType =
1152 USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
1153 transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(2U);
1154 break;
1155 case USB_HOST_PHDC_SET_FEATURE_REQUEST:
1156 case USB_HOST_PHDC_CLEAR_FEATURE_REQUEST:
1157 /* Initialize the PHDC set/clear feature request */
1158 transfer->setupPacket->bmRequestType =
1159 USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
1160 transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(
1161 USB_HOST_PHDC_FEATURE_METADATA | (uint16_t)((uint16_t)USB_HOST_PHDC_QOS_ENCODING_VERSION << 8U));
1162 transfer->setupPacket->wLength = 0U;
1163 break;
1164 default:
1165 status = kStatus_USB_InvalidRequest;
1166 break;
1167 }
1168 if (USB_HostSendSetup(phdcInstance->hostHandle, phdcInstance->controlPipe, transfer) != kStatus_USB_Success)
1169 {
1170 #ifdef HOST_ECHO
1171 usb_echo("fail for USB_HostSendSetup\r\n");
1172 #endif
1173 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
1174 return kStatus_USB_Error;
1175 }
1176 phdcInstance->controlTransfer = transfer;
1177
1178 return status;
1179 }
1180
1181 /*!
1182 * @brief phdc set and clear feature endpoint halt request for meta-data message preamble error.
1183 *
1184 * @param classHandle the class handle.
1185 * @param request setup packet request.
1186 * @param param request parameter
1187 * @param callbackFn this callback is called after this function completes.
1188 * @param callbackParam the first parameter in the callback function.
1189 *
1190 * @retval kStatus_USB_Success send request successfully.
1191 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
1192 * @retval kStatus_USB_Busy There is no idle transfer.
1193 * @retval kStatus_USB_Error pipe is not initialized.
1194 * Or, send transfer fail, please reference to USB_HostSend.
1195 */
USB_HostPhdcSetClearFeatureEndpointHalt(usb_host_class_handle classHandle,uint8_t request,void * param,transfer_callback_t callbackFn,void * callbackParam)1196 usb_status_t USB_HostPhdcSetClearFeatureEndpointHalt(usb_host_class_handle classHandle,
1197 uint8_t request,
1198 void *param,
1199 transfer_callback_t callbackFn,
1200 void *callbackParam)
1201 {
1202 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle;
1203 usb_host_transfer_t *transfer;
1204 if (NULL == classHandle)
1205 {
1206 return kStatus_USB_InvalidHandle;
1207 }
1208
1209 if (NULL == phdcInstance->controlPipe)
1210 {
1211 return kStatus_USB_Error;
1212 }
1213
1214 if (NULL != phdcInstance->controlTransfer)
1215 {
1216 return kStatus_USB_Busy;
1217 }
1218 /* Allocate the transfer pointer */
1219 if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
1220 {
1221 #ifdef HOST_ECHO
1222 usb_echo("error to get transfer\r\n");
1223 #endif
1224 return kStatus_USB_Error;
1225 }
1226 /* Save application callback function and parameter */
1227 phdcInstance->controlCallbackFn = callbackFn;
1228 phdcInstance->controlCallbackParam = callbackParam;
1229 /* Initialize the transfer request */
1230 transfer->callbackFn = USB_HostPhdcSetClearFeatureEndpointHaltCallback;
1231 transfer->callbackParam = phdcInstance;
1232 if (kStatus_USB_Success != USB_HostRequestControl(phdcInstance->deviceHandle, request, transfer, param))
1233 {
1234 #ifdef HOST_ECHO
1235 usb_echo("fail for USB_HostRequestControl\r\n");
1236 #endif
1237 (void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
1238 return kStatus_USB_Error;
1239 }
1240 phdcInstance->controlTransfer = transfer;
1241
1242 return kStatus_USB_Success;
1243 }
1244
1245 /*!
1246 * @brief USB_HostPhdcGetEndpointInformation.
1247 * This function returns the PHDC endpoint information structure contains endpoint
1248 * descriptor and endpoint extended descriptor.
1249 *
1250 * @param classHandle the class handle.
1251 * @param pipeType pipe type.
1252 * @param direction pipe direction.
1253 *
1254 * @retval endpointReturn All input parameters are valid.
1255 * @retval NULL One or more input parameters are invalid.
1256 */
USB_HostPhdcGetEndpointInformation(usb_host_class_handle classHandle,uint8_t pipeType,uint8_t direction)1257 usb_host_ep_t *USB_HostPhdcGetEndpointInformation(usb_host_class_handle classHandle,
1258 uint8_t pipeType,
1259 uint8_t direction)
1260 {
1261 usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle;
1262 usb_host_ep_t *endpointReturn = NULL;
1263 if (NULL != classHandle)
1264 {
1265 if (pipeType == USB_ENDPOINT_BULK)
1266 {
1267 if (direction == USB_IN)
1268 {
1269 /* bulk in endpoint information */
1270 endpointReturn = (usb_host_ep_t *)&phdcInstance->bulkInEndpointInformation;
1271 }
1272 else
1273 {
1274 /* bulk out endpoint information */
1275 endpointReturn = (usb_host_ep_t *)&phdcInstance->bulkOutEndpointInformation;
1276 }
1277 }
1278 else if (pipeType == USB_ENDPOINT_INTERRUPT)
1279 {
1280 /* interrupt in endpoint information */
1281 endpointReturn = (usb_host_ep_t *)&phdcInstance->interruptInEndpointInformation;
1282 }
1283 else
1284 {
1285 /*no action*/
1286 }
1287 }
1288 return endpointReturn;
1289 }
1290 #endif
1291