1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_device_config.h"
10 #include "usb.h"
11 #include "usb_device.h"
12 
13 #include "usb_device_class.h"
14 
15 #if ((defined(USB_DEVICE_CONFIG_PRINTER)) && (USB_DEVICE_CONFIG_PRINTER > 0U))
16 #include "usb_device_printer.h"
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 
26 /*******************************************************************************
27  * Variables
28  ******************************************************************************/
29 
USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE)30 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_printer_struct_t
31     s_PrinterHandle[USB_DEVICE_CONFIG_PRINTER];
32 
33 /*******************************************************************************
34  * Code
35  ******************************************************************************/
36 
37 static usb_status_t USB_DevicePrinterAllocateHandle(usb_device_printer_struct_t **printerHandle)
38 {
39     uint8_t index;
40 
41     for (index = 0; index < USB_DEVICE_CONFIG_PRINTER; ++index)
42     {
43         if (s_PrinterHandle[index].deviceHandle == NULL)
44         {
45             *printerHandle = &(s_PrinterHandle[index]);
46             return kStatus_USB_Success;
47         }
48     }
49 
50     return kStatus_USB_Busy;
51 }
52 
USB_DevicePrinterFreeHandle(usb_device_printer_struct_t * printerHandle)53 static usb_status_t USB_DevicePrinterFreeHandle(usb_device_printer_struct_t *printerHandle)
54 {
55     /* ensure that printerHandle is not NULL before calling this function */
56     printerHandle->deviceHandle    = NULL;
57     printerHandle->classConfig     = NULL;
58     printerHandle->alternate       = 0xFFu;
59     printerHandle->configuration   = 0;
60     printerHandle->interfaceNumber = 0;
61 
62     return kStatus_USB_Success;
63 }
64 
65 /*!
66  * @brief bulk IN endpoint callback function.
67  *
68  * This callback function is used to notify upper layer the transfer result of a transfer.
69  * This callback pointer is passed when the bulk IN pipe initialized.
70  *
71  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
72  * @param message         The result of the bulk IN pipe transfer.
73  * @param callbackParam   The parameter for this callback. It is same with
74  * usb_device_endpoint_callback_struct_t::callbackParam.
75  *                        In the class, the value is the printer class handle.
76  *
77  * @retval kStatus_USB_Success          The transfer is successful.
78  * @retval kStatus_USB_InvalidHandle    The device handle not be found.
79  */
USB_DevicePrinterBulkInCallback(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)80 static usb_status_t USB_DevicePrinterBulkInCallback(usb_device_handle handle,
81                                                     usb_device_endpoint_callback_message_struct_t *message,
82                                                     void *callbackParam)
83 {
84     usb_device_printer_struct_t *printerHandle = (usb_device_printer_struct_t *)callbackParam;
85     usb_status_t status                        = kStatus_USB_Error;
86 
87     if (callbackParam == NULL)
88     {
89         return kStatus_USB_InvalidHandle;
90     }
91 
92     printerHandle->bulkInBusy = 0U;
93     if ((NULL != printerHandle->classConfig) && (NULL != printerHandle->classConfig->classCallback))
94     {
95         /* Notify the application data received by calling the printer class callback.
96         ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
97         it is from the second parameter of classInit */
98         status = printerHandle->classConfig->classCallback((class_handle_t)printerHandle,
99                                                            kUSB_DevicePrinterEventSendResponse, message);
100     }
101 
102     return status;
103 }
104 
105 /*!
106  * @brief bulk OUT endpoint callback function.
107  *
108  * This callback function is used to notify upper layer the transfer result of a transfer.
109  * This callback pointer is passed when the bulk OUT pipe initialized.
110  *
111  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
112  * @param message         The result of the bulk OUT pipe transfer.
113  * @param callbackParam   The parameter for this callback. It is same with
114  * usb_device_endpoint_callback_struct_t::callbackParam.
115  *                        In the class, the value is the printer class handle.
116  *
117  * @retval kStatus_USB_Success          The transfer is successful.
118  * @retval kStatus_USB_InvalidHandle    The device handle not be found.
119  */
USB_DevicePrinterBulkOutCallback(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)120 static usb_status_t USB_DevicePrinterBulkOutCallback(usb_device_handle handle,
121                                                      usb_device_endpoint_callback_message_struct_t *message,
122                                                      void *callbackParam)
123 {
124     usb_device_printer_struct_t *printerHandle = (usb_device_printer_struct_t *)callbackParam;
125     usb_status_t status                        = kStatus_USB_Error;
126 
127     if (printerHandle == NULL)
128     {
129         return kStatus_USB_InvalidHandle;
130     }
131     printerHandle->bulkOutBusy = 0U;
132     if ((NULL != printerHandle->classConfig) && (NULL != printerHandle->classConfig->classCallback))
133     {
134         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
135         it is from the second parameter of classInit */
136         status = printerHandle->classConfig->classCallback((class_handle_t)printerHandle,
137                                                            kUSB_DevicePrinterEventRecvResponse, message);
138     }
139 
140     return status;
141 }
142 
143 /*!
144  * @brief Initialize the endpoints of the printer class.
145  *
146  * This callback function is used to initialize the endpoints of the printer class.
147  *
148  * @param printerHandle          The device printer class handle. It equals the value returned from
149  * usb_device_class_config_struct_t::classHandle.
150  *
151  * @return A USB error code or kStatus_USB_Success.
152  */
USB_DevicePrinterEndpointsInit(usb_device_printer_struct_t * printerHandle)153 static usb_status_t USB_DevicePrinterEndpointsInit(usb_device_printer_struct_t *printerHandle)
154 {
155     /* ensure that printerHandle is not NULL before calling this function */
156     usb_device_interface_list_t *configInterfaceList;
157     usb_device_interface_struct_t *interface = NULL;
158     usb_status_t status                      = kStatus_USB_Error;
159     uint8_t interfaceIndex;
160     uint8_t index;
161 
162     /* return error when configuration is invalid (0 or more than the configuration number) */
163     if ((printerHandle->configuration == 0U) ||
164         (printerHandle->configuration > printerHandle->classConfig->classInfomation->configurations))
165     {
166         return status;
167     }
168 
169     configInterfaceList =
170         &(printerHandle->classConfig->classInfomation->interfaceList[printerHandle->configuration - 1U]);
171     for (interfaceIndex = 0; interfaceIndex < configInterfaceList->count; ++interfaceIndex)
172     {
173         if (USB_DEVICE_CONFIG_PRINTER_CLASS_CODE == configInterfaceList->interfaces[interfaceIndex].classCode)
174         {
175             /* index means the alternate interface's index here */
176             for (index = 0; index < configInterfaceList->interfaces[interfaceIndex].count; ++index)
177             {
178                 if (configInterfaceList->interfaces[interfaceIndex].interface[index].alternateSetting ==
179                     printerHandle->alternate)
180                 {
181                     interface = &(configInterfaceList->interfaces[interfaceIndex].interface[index]);
182                     break;
183                 }
184             }
185             printerHandle->interfaceNumber = configInterfaceList->interfaces[interfaceIndex].interfaceNumber;
186             break;
187         }
188     }
189     if (interface == NULL)
190     {
191         return status;
192     }
193 
194     /* Keep new interface handle. */
195     printerHandle->interfaceHandle = interface;
196 
197     /* Initialize the endpoints of the new interface. */
198     /* index means the endpoint's index here */
199     for (index = 0; index < interface->endpointList.count; ++index)
200     {
201         usb_device_endpoint_init_struct_t epInitStruct;
202         usb_device_endpoint_callback_struct_t epCallback;
203         epInitStruct.zlt             = 0U;
204         epInitStruct.interval        = interface->endpointList.endpoint[index].interval;
205         epInitStruct.endpointAddress = interface->endpointList.endpoint[index].endpointAddress;
206         epInitStruct.maxPacketSize   = interface->endpointList.endpoint[index].maxPacketSize;
207         epInitStruct.transferType    = interface->endpointList.endpoint[index].transferType;
208 
209         if (((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
210              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT) == USB_IN)
211         {
212             epCallback.callbackFn               = USB_DevicePrinterBulkInCallback;
213             printerHandle->bulkInPipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
214             printerHandle->bulkInPipeStall      = 0U;
215             printerHandle->bulkInPipeDataLen    = 0U;
216         }
217         else
218         {
219             epCallback.callbackFn                = USB_DevicePrinterBulkOutCallback;
220             printerHandle->bulkOutPipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
221             printerHandle->bulkOutPipeStall      = 0U;
222             printerHandle->bulkOutPipeDataLen    = 0U;
223         }
224         epCallback.callbackParam = printerHandle;
225 
226         status = USB_DeviceInitEndpoint(printerHandle->deviceHandle, &epInitStruct, &epCallback);
227     }
228 
229     return status;
230 }
231 
232 /*!
233  * @brief De-initialize the endpoints of the printer class.
234  *
235  * This callback function is used to de-initialize the endpoints of the printer class.
236  *
237  * @param printerHandle          The device printer class handle. It equals the value returned from
238  * usb_device_class_config_struct_t::classHandle.
239  *
240  * @return A USB error code or kStatus_USB_Success.
241  */
USB_DevicePrinterEndpointsDeinit(usb_device_printer_struct_t * printerHandle)242 static usb_status_t USB_DevicePrinterEndpointsDeinit(usb_device_printer_struct_t *printerHandle)
243 {
244     /* ensure that printerHandle is not NULL before calling this function */
245     usb_status_t status = kStatus_USB_Error;
246     uint8_t index;
247 
248     /* return directly when the interfaceHandle is NULL, it means USB_DevicePrinterEndpointsInit is not called */
249     if (printerHandle->interfaceHandle == NULL)
250     {
251         return kStatus_USB_Success;
252     }
253 
254     for (index = 0; index < printerHandle->interfaceHandle->endpointList.count; ++index)
255     {
256         status = USB_DeviceDeinitEndpoint(printerHandle->deviceHandle,
257                                           printerHandle->interfaceHandle->endpointList.endpoint[index].endpointAddress);
258     }
259     printerHandle->interfaceHandle = NULL;
260 
261     return status;
262 }
263 
USB_DevicePrinterInit(uint8_t controllerId,usb_device_class_config_struct_t * config,class_handle_t * handle)264 usb_status_t USB_DevicePrinterInit(uint8_t controllerId,
265                                    usb_device_class_config_struct_t *config,
266                                    class_handle_t *handle)
267 
268 {
269     usb_device_handle deviceHandle;
270     usb_device_printer_struct_t *printerHandle = NULL;
271     usb_status_t status;
272     OSA_SR_ALLOC();
273 
274     /* get the controller's device handle */
275     status = USB_DeviceClassGetDeviceHandle(controllerId, &deviceHandle);
276     if (status != kStatus_USB_Success)
277     {
278         return status;
279     }
280     if (deviceHandle == NULL)
281     {
282         return kStatus_USB_InvalidHandle;
283     }
284 
285     /* Allocate a printer class handle. */
286     OSA_ENTER_CRITICAL();
287     status                      = USB_DevicePrinterAllocateHandle(&printerHandle);
288     printerHandle->deviceHandle = deviceHandle; /* this printer instance is used */
289     OSA_EXIT_CRITICAL();
290     if (status != kStatus_USB_Success)
291     {
292         return status;
293     }
294 
295     printerHandle->classConfig     = config;
296     printerHandle->alternate       = 0xFFU;
297     printerHandle->configuration   = 0U;
298     printerHandle->interfaceNumber = 0U;
299     printerHandle->interfaceHandle = NULL;
300 
301     *handle = (class_handle_t)printerHandle;
302 
303     return status;
304 }
305 
USB_DevicePrinterDeinit(class_handle_t handle)306 usb_status_t USB_DevicePrinterDeinit(class_handle_t handle)
307 {
308     usb_status_t status;
309     usb_device_printer_struct_t *printerHandle = (usb_device_printer_struct_t *)handle;
310 
311     if (NULL == handle)
312     {
313         return kStatus_USB_InvalidHandle;
314     }
315 
316     status = USB_DevicePrinterEndpointsDeinit(printerHandle);
317 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
318     if (kStatus_USB_Success != USB_DevicePrinterFreeHandle(printerHandle))
319     {
320         return kStatus_USB_Error;
321     }
322 #else
323     (void)USB_DevicePrinterFreeHandle(printerHandle);
324 #endif
325     return status;
326 }
327 
USB_DevicePrinterEvent(void * handle,uint32_t event,void * param)328 usb_status_t USB_DevicePrinterEvent(void *handle, uint32_t event, void *param)
329 {
330     usb_status_t status                        = kStatus_USB_Error;
331     usb_device_printer_struct_t *printerHandle = (usb_device_printer_struct_t *)handle;
332     uint16_t temp16;
333     uint8_t temp8;
334     usb_device_class_event_t eventCode = (usb_device_class_event_t)event;
335 
336     if ((handle == NULL) || (param == NULL))
337     {
338         return kStatus_USB_InvalidHandle;
339     }
340 
341     switch (eventCode)
342     {
343         case kUSB_DeviceClassEventDeviceReset:
344             /* de-initialize printer instance */
345             printerHandle->interfaceHandle = NULL;
346             printerHandle->alternate       = 0xFFU;
347             printerHandle->configuration   = 0U;
348             printerHandle->interfaceNumber = 0U;
349             printerHandle->bulkInBusy      = 0U;
350             printerHandle->bulkOutBusy     = 0U;
351             status                         = kStatus_USB_Success;
352             break;
353 
354         case kUSB_DeviceClassEventSetConfiguration:
355             temp8 = *((uint8_t *)param);
356             if (printerHandle->classConfig == NULL)
357             {
358                 break;
359             }
360             if (temp8 == printerHandle->configuration)
361             {
362                 status = kStatus_USB_Success;
363                 break;
364             }
365 
366             /* De-initialize the endpoints when current configuration is none zero. */
367             if (printerHandle->configuration != 0U)
368             {
369                 status = USB_DevicePrinterEndpointsDeinit(printerHandle);
370             }
371             /* Save new configuration. */
372             printerHandle->configuration = temp8;
373             printerHandle->alternate     = 0U;
374             printerHandle->bulkInBusy    = 0U;
375             printerHandle->bulkOutBusy   = 0U;
376 
377             /* Initialize the endpoints of the new current configuration */
378             status = USB_DevicePrinterEndpointsInit(printerHandle);
379             break;
380 
381         case kUSB_DeviceClassEventSetInterface:
382             if (printerHandle->classConfig == NULL)
383             {
384                 break;
385             }
386 
387             /* Get the new alternate setting of the interface */
388             temp16 = *((uint16_t *)param);
389             /* Get the alternate setting value */
390             temp8 = (uint8_t)(temp16 & 0xFFU);
391             /* Whether the interface belongs to the class. */
392             if (printerHandle->interfaceNumber != ((uint8_t)(temp16 >> 8U)))
393             {
394                 break;
395             }
396             /* Only handle new alternate setting. */
397             if (temp8 == printerHandle->alternate)
398             {
399                 status = kStatus_USB_Success;
400                 break;
401             }
402 
403             /* De-initialize old endpoints */
404             status                     = USB_DevicePrinterEndpointsDeinit(printerHandle);
405             printerHandle->alternate   = temp8;
406             printerHandle->bulkInBusy  = 0U;
407             printerHandle->bulkOutBusy = 0U;
408             /* Initialize new endpoints */
409             status = USB_DevicePrinterEndpointsInit(printerHandle);
410             break;
411 
412         case kUSB_DeviceClassEventSetEndpointHalt:
413             if ((printerHandle->classConfig == NULL) || (printerHandle->interfaceHandle == NULL))
414             {
415                 break;
416             }
417             /* Get the endpoint address */
418             temp8 = *((uint8_t *)param);
419             for (temp16 = 0; temp16 < printerHandle->interfaceHandle->endpointList.count; ++temp16)
420             {
421                 if (temp8 == printerHandle->interfaceHandle->endpointList.endpoint[temp16].endpointAddress)
422                 {
423                     /* Only stall the endpoint belongs to the class */
424                     if (USB_IN == ((printerHandle->interfaceHandle->endpointList.endpoint[temp16].endpointAddress &
425                                     USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
426                                    USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT))
427                     {
428                         printerHandle->bulkInPipeStall = 1U;
429                     }
430                     else
431                     {
432                         printerHandle->bulkOutPipeStall = 1U;
433                     }
434                     status = USB_DeviceStallEndpoint(printerHandle->deviceHandle, temp8);
435                     break;
436                 }
437             }
438             break;
439 
440         case kUSB_DeviceClassEventClearEndpointHalt:
441             if ((printerHandle->classConfig == NULL) || (printerHandle->interfaceHandle == NULL))
442             {
443                 break;
444             }
445             /* Get the endpoint address */
446             temp8 = *((uint8_t *)param);
447             for (temp16 = 0; temp16 < printerHandle->interfaceHandle->endpointList.count; ++temp16)
448             {
449                 if (temp8 == printerHandle->interfaceHandle->endpointList.endpoint[temp16].endpointAddress)
450                 {
451                     /* Only un-stall the endpoint belongs to the class */
452                     status = USB_DeviceUnstallEndpoint(printerHandle->deviceHandle, temp8);
453                     if (USB_IN == (((temp8)&USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
454                                    USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT))
455                     {
456                         if (0U != printerHandle->bulkInPipeStall)
457                         {
458                             printerHandle->bulkInPipeStall = 0U;
459                             if ((uint8_t *)USB_INVALID_TRANSFER_BUFFER != printerHandle->bulkInPipeDataBuffer)
460                             {
461                                 status = USB_DeviceSendRequest(
462                                     printerHandle->deviceHandle,
463                                     (printerHandle->interfaceHandle->endpointList.endpoint[temp16].endpointAddress &
464                                      USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK),
465                                     printerHandle->bulkInPipeDataBuffer, printerHandle->bulkInPipeDataLen);
466                                 if (kStatus_USB_Success != status)
467                                 {
468                                     usb_device_endpoint_callback_message_struct_t endpointCallbackMessage;
469                                     endpointCallbackMessage.buffer  = printerHandle->bulkInPipeDataBuffer;
470                                     endpointCallbackMessage.length  = printerHandle->bulkInPipeDataLen;
471                                     endpointCallbackMessage.isSetup = 0U;
472 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
473                                     if (kStatus_USB_Success !=
474                                         USB_DevicePrinterBulkInCallback(printerHandle->deviceHandle,
475                                                                         (void *)&endpointCallbackMessage, handle))
476                                     {
477                                         return kStatus_USB_Error;
478                                     }
479 #else
480                                     (void)USB_DevicePrinterBulkInCallback(printerHandle->deviceHandle,
481                                                                           (void *)&endpointCallbackMessage, handle);
482 #endif
483                                 }
484                                 printerHandle->bulkInPipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
485                                 printerHandle->bulkInPipeDataLen    = 0U;
486                             }
487                         }
488                     }
489                     else
490                     {
491                         if (printerHandle->bulkOutPipeStall == 1U)
492                         {
493                             printerHandle->bulkOutPipeStall = 0U;
494                             if ((uint8_t *)USB_INVALID_TRANSFER_BUFFER != printerHandle->bulkOutPipeDataBuffer)
495                             {
496                                 status = USB_DeviceRecvRequest(
497                                     printerHandle->deviceHandle,
498                                     (printerHandle->interfaceHandle->endpointList.endpoint[temp16].endpointAddress &
499                                      USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK),
500                                     printerHandle->bulkOutPipeDataBuffer, printerHandle->bulkOutPipeDataLen);
501                                 if (kStatus_USB_Success != status)
502                                 {
503                                     usb_device_endpoint_callback_message_struct_t endpointCallbackMessage;
504                                     endpointCallbackMessage.buffer  = printerHandle->bulkOutPipeDataBuffer;
505                                     endpointCallbackMessage.length  = printerHandle->bulkOutPipeDataLen;
506                                     endpointCallbackMessage.isSetup = 0U;
507 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
508                                     if (kStatus_USB_Success !=
509                                         USB_DevicePrinterBulkInCallback(printerHandle->deviceHandle,
510                                                                         (void *)&endpointCallbackMessage, handle))
511                                     {
512                                         return kStatus_USB_Error;
513                                     }
514 #else
515                                     (void)USB_DevicePrinterBulkInCallback(printerHandle->deviceHandle,
516                                                                           (void *)&endpointCallbackMessage, handle);
517 #endif
518                                 }
519                                 printerHandle->bulkOutPipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
520                                 printerHandle->bulkOutPipeDataLen    = 0U;
521                             }
522                         }
523                     }
524                     break;
525                 }
526             }
527             break;
528 
529         case kUSB_DeviceClassEventClassRequest:
530         {
531             /* Handle the printer class specific request. */
532             usb_device_control_request_struct_t *controlRequest = (usb_device_control_request_struct_t *)param;
533             usb_device_printer_class_request_t classRequest;
534             if ((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) !=
535                 USB_REQUEST_TYPE_RECIPIENT_INTERFACE)
536             {
537                 break;
538             }
539 
540             classRequest.interface = (uint8_t)(controlRequest->setup->wIndex >> 8);
541             if (classRequest.interface != printerHandle->interfaceNumber)
542             {
543                 break;
544             }
545 
546             classRequest.alternateSetting = (uint8_t)(controlRequest->setup->wIndex);
547             status                        = kStatus_USB_InvalidRequest;
548             switch (controlRequest->setup->bRequest)
549             {
550                 case USB_DEVICE_PRINTER_GET_DEVICE_ID:
551                     /* GET_DEVICE_ID */
552                     if (((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
553                          USB_REQUEST_TYPE_DIR_IN) &&
554                         (controlRequest->setup->wLength != 0U))
555                     {
556                         classRequest.configIndex = (uint8_t)controlRequest->setup->wValue;
557 
558                         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
559                         it is from the second parameter of classInit */
560                         status = printerHandle->classConfig->classCallback(
561                             (class_handle_t)printerHandle, kUSB_DevicePrinterEventGetDeviceId, &classRequest);
562                         controlRequest->buffer = classRequest.buffer;
563                         controlRequest->length = classRequest.length;
564                     }
565                     break;
566 
567                 case USB_DEVICE_PRINTER_GET_PORT_STATUS:
568                     /* GET_PORT_STATUS */
569                     if (((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
570                          USB_REQUEST_TYPE_DIR_IN) &&
571                         (controlRequest->setup->wLength == 1U))
572                     {
573                         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
574                         it is from the second parameter of classInit */
575                         status = printerHandle->classConfig->classCallback(
576                             (class_handle_t)printerHandle, kUSB_DevicePrinterEventGetPortStatus, &classRequest);
577                         controlRequest->buffer = classRequest.buffer;
578                         controlRequest->length = classRequest.length;
579                     }
580                     break;
581 
582                 case USB_DEVICE_PRINTER_SOFT_RESET:
583                     if (((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
584                          USB_REQUEST_TYPE_DIR_OUT) &&
585                         (controlRequest->setup->wLength == 0U))
586                     {
587                         /* reset BULK_IN/OUT endpoint and inform application */
588 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
589                         if ((kStatus_USB_Success != USB_DevicePrinterEndpointsDeinit(printerHandle)) ||
590                             (kStatus_USB_Success != USB_DevicePrinterEndpointsInit(printerHandle)))
591                         {
592                             return kStatus_USB_Error;
593                         }
594 #else
595                         (void)USB_DevicePrinterEndpointsDeinit(printerHandle);
596                         (void)USB_DevicePrinterEndpointsInit(printerHandle);
597 #endif
598                         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
599                         it is from the second parameter of classInit */
600                         status = printerHandle->classConfig->classCallback(
601                             (class_handle_t)printerHandle, kUSB_DevicePrinterEventSoftReset, &classRequest);
602                     }
603                     break;
604 
605                 default:
606                     /*no action*/
607                     break;
608             }
609             break;
610         }
611         default:
612             /*no action*/
613             break;
614     }
615 
616     return status;
617 }
618 
USB_DevicePrinterSend(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)619 usb_status_t USB_DevicePrinterSend(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
620 {
621     usb_device_printer_struct_t *printerHandle = (usb_device_printer_struct_t *)handle;
622     usb_status_t status;
623 
624     if (NULL == handle)
625     {
626         return kStatus_USB_InvalidHandle;
627     }
628 
629     if (1U == printerHandle->bulkInBusy)
630     {
631         return kStatus_USB_Busy;
632     }
633     printerHandle->bulkInBusy = 1U;
634 
635     if (0U != printerHandle->bulkInPipeStall)
636     {
637         printerHandle->bulkInPipeDataBuffer = buffer;
638         printerHandle->bulkInPipeDataLen    = length;
639         return kStatus_USB_Success;
640     }
641 
642     status = USB_DeviceSendRequest(printerHandle->deviceHandle, ep, buffer, length);
643     if (kStatus_USB_Success != status)
644     {
645         printerHandle->bulkInBusy = 0U;
646     }
647     return status;
648 }
649 
USB_DevicePrinterRecv(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)650 usb_status_t USB_DevicePrinterRecv(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
651 {
652     usb_device_printer_struct_t *printerHandle = (usb_device_printer_struct_t *)handle;
653     usb_status_t status                        = kStatus_USB_Error;
654 
655     if (NULL == handle)
656     {
657         return kStatus_USB_InvalidHandle;
658     }
659 
660     if (0U != printerHandle->bulkOutBusy)
661     {
662         return kStatus_USB_Busy;
663     }
664     printerHandle->bulkOutBusy = 1U;
665 
666     if (0U != printerHandle->bulkOutPipeStall)
667     {
668         printerHandle->bulkOutPipeDataBuffer = buffer;
669         printerHandle->bulkOutPipeDataLen    = length;
670         return kStatus_USB_Success;
671     }
672     status = USB_DeviceRecvRequest(printerHandle->deviceHandle, ep, buffer, length);
673     if (kStatus_USB_Success != status)
674     {
675         printerHandle->bulkOutBusy = 0U;
676     }
677 
678     return status;
679 }
680 #endif
681