1 /*
2  * Copyright (c) 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_PRINTER) && (USB_HOST_CONFIG_PRINTER))
11 #include "usb_host.h"
12 #include "usb_host_printer.h"
13 
14 /*******************************************************************************
15  * API
16  ******************************************************************************/
17 
18 /*!
19  * @brief printer in pipe transfer callback.
20  *
21  * @param param       callback parameter.
22  * @param transfer    callback transfer.
23  * @param status      transfer status.
24  */
25 static void USB_HostPrinterInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
26 
27 /*!
28  * @brief printer out pipe transfer callback.
29  *
30  * @param param       callback parameter.
31  * @param transfer    callback transfer.
32  * @param status      transfer status.
33  */
34 static void USB_HostPrinterOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
35 
36 /*!
37  * @brief printer control pipe transfer callback.
38  *
39  * @param param       callback parameter.
40  * @param transfer    callback transfer.
41  * @param status      transfer status.
42  */
43 static void USB_HostPrinterControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
44 
45 /*!
46  * @brief printer open interface. It is called when set interface request success or open alternate setting 0 interface.
47  *
48  * @param printerInstance     printer instance pointer.
49  *
50  * @return kStatus_USB_Success or error codes.
51  */
52 static usb_status_t USB_HostPrinterOpenInterface(usb_host_printer_instance_t *printerInstance);
53 
54 /*!
55  * @brief printer set interface callback, open pipes.
56  *
57  * @param param       callback parameter.
58  * @param transfer    callback transfer.
59  * @param status      transfer status.
60  */
61 static void USB_HostPrinterSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
62 
63 /*!
64  * @brief printer send control transfer common code.
65  *
66  * @param classHandle    the class handle.
67  * @param requestType    setup packet request type.
68  * @param request        setup packet request value.
69  * @param wvalue         setup packet wValue.
70  * @param windex         setup packet wIndex.
71  * @param wlength        setup packet wlength value.
72  * @param data           data buffer pointer
73  * @param callbackFn     this callback is called after this function completes.
74  * @param callbackParam  the first parameter in the callback function.
75  *
76  * @return An error code or kStatus_USB_Success.
77  */
78 static usb_status_t USB_HostPrinterControl(usb_host_printer_instance_t *printerInstance,
79                                            uint8_t requestType,
80                                            uint8_t request,
81                                            uint16_t wvalue,
82                                            uint16_t windex,
83                                            uint16_t wlength,
84                                            uint8_t *data,
85                                            transfer_callback_t callbackFn,
86                                            void *callbackParam);
87 
88 /*******************************************************************************
89  * Definitions
90  ******************************************************************************/
91 /*******************************************************************************
92  * Prototypes
93  ******************************************************************************/
94 /*******************************************************************************
95  * Variables
96  ******************************************************************************/
97 /*******************************************************************************
98  * Code
99  ******************************************************************************/
100 
101 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
USB_HostPrinterClearInHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)102 static void USB_HostPrinterClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
103 {
104     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
105 
106     if (printerInstance->inCallbackFn != NULL)
107     {
108         /* callback to application, callback function is initialized in USB_HostPrinterRecv */
109         printerInstance->inCallbackFn(printerInstance->outCallbackParam, printerInstance->stallDataBuffer,
110                                       printerInstance->stallDataLength, kStatus_USB_TransferStall);
111     }
112     (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
113 }
114 
USB_HostPrinterClearOutHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)115 static void USB_HostPrinterClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
116 {
117     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
118 
119     if (printerInstance->outCallbackFn != NULL)
120     {
121         /* callback to application, callback function is initialized in USB_HostPrinterSend */
122         printerInstance->outCallbackFn(printerInstance->outCallbackParam, printerInstance->stallDataBuffer,
123                                        printerInstance->stallDataLength, kStatus_USB_TransferStall);
124     }
125     (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
126 }
127 
USB_HostPrinterClearHalt(usb_host_printer_instance_t * printerInstance,usb_host_transfer_t * stallTransfer,host_inner_transfer_callback_t callbackFn,uint8_t endpoint)128 static usb_status_t USB_HostPrinterClearHalt(usb_host_printer_instance_t *printerInstance,
129                                              usb_host_transfer_t *stallTransfer,
130                                              host_inner_transfer_callback_t callbackFn,
131                                              uint8_t endpoint)
132 {
133     usb_status_t status;
134     usb_host_transfer_t *transfer;
135 
136     /* malloc one transfer */
137     status = USB_HostMallocTransfer(printerInstance->hostHandle, &transfer);
138     if (status != kStatus_USB_Success)
139     {
140 #ifdef HOST_ECHO
141         usb_echo("allocate transfer error\r\n");
142 #endif
143         return status;
144     }
145     printerInstance->stallDataBuffer = stallTransfer->transferBuffer;
146     printerInstance->stallDataLength = stallTransfer->transferSofar;
147     /* save the application callback function */
148     printerInstance->controlCallbackFn    = NULL;
149     printerInstance->controlCallbackParam = NULL;
150     /* initialize transfer */
151     transfer->callbackFn                 = callbackFn;
152     transfer->callbackParam              = printerInstance;
153     transfer->transferBuffer             = NULL;
154     transfer->transferLength             = 0;
155     transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_CLEAR_FEATURE;
156     transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
157     transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT);
158     transfer->setupPacket->wIndex  = USB_SHORT_TO_LITTLE_ENDIAN(endpoint);
159     transfer->setupPacket->wLength = 0;
160     status = USB_HostSendSetup(printerInstance->hostHandle, printerInstance->controlPipe, transfer);
161 
162     if (status != kStatus_USB_Success)
163     {
164         (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
165     }
166     printerInstance->controlTransfer = transfer;
167 
168     return status;
169 }
170 #endif
171 
USB_HostPrinterInPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)172 static void USB_HostPrinterInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
173 {
174     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
175 
176 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
177     if (status == kStatus_USB_TransferStall)
178     {
179         if (USB_HostPrinterClearHalt(
180                 printerInstance, transfer, USB_HostPrinterClearInHaltCallback,
181                 (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)printerInstance->inPipe)->endpointAddress)) ==
182             kStatus_USB_Success)
183         {
184             (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
185             return;
186         }
187     }
188 #endif
189 
190     if (printerInstance->inCallbackFn != NULL)
191     {
192         /* callback to application, callback function is initialized in USB_HostPrinterRecv */
193         printerInstance->inCallbackFn(printerInstance->inCallbackParam, transfer->transferBuffer,
194                                       transfer->transferSofar, status);
195     }
196     (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
197 }
198 
USB_HostPrinterOutPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)199 static void USB_HostPrinterOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
200 {
201     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
202 
203 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
204     if (status == kStatus_USB_TransferStall)
205     {
206         if (USB_HostPrinterClearHalt(
207                 printerInstance, transfer, USB_HostPrinterClearOutHaltCallback,
208                 (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)printerInstance->outPipe)->endpointAddress)) ==
209             kStatus_USB_Success)
210         {
211             (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
212             return;
213         }
214     }
215 #endif
216     if (printerInstance->outCallbackFn != NULL)
217     {
218         /* callback to application, callback function is initialized in USB_HostPrinterSend */
219         printerInstance->outCallbackFn(printerInstance->outCallbackParam, transfer->transferBuffer,
220                                        transfer->transferSofar, status);
221     }
222     (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
223 }
224 
USB_HostPrinterControlPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)225 static void USB_HostPrinterControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
226 {
227     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
228 
229     printerInstance->controlTransfer = NULL;
230     if (printerInstance->controlCallbackFn != NULL)
231     {
232         /* callback to application, callback to application, callback function is initialized in the
233         USB_HostPrinterControl,
234         USB_HostPrinterSetInterface or USB_HostHubClassRequestCommon, but is the same function */
235         printerInstance->controlCallbackFn(printerInstance->controlCallbackParam, transfer->transferBuffer,
236                                            transfer->transferSofar, status);
237     }
238     (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
239 }
240 
USB_HostPrinterOpenInterface(usb_host_printer_instance_t * printerInstance)241 static usb_status_t USB_HostPrinterOpenInterface(usb_host_printer_instance_t *printerInstance)
242 {
243     usb_status_t status;
244     uint8_t epIndex = 0;
245     usb_host_pipe_init_t pipeInit;
246     usb_descriptor_endpoint_t *epDesc = NULL;
247     usb_host_interface_t *interfacePointer;
248 
249     if (printerInstance->inPipe != NULL)
250     {
251         status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->inPipe);
252 
253         if (status != kStatus_USB_Success)
254         {
255 #ifdef HOST_ECHO
256             usb_echo("error when close pipe\r\n");
257 #endif
258         }
259         printerInstance->inPipe = NULL;
260     }
261     if (printerInstance->outPipe != NULL) /* close interrupt out pipe if it is open */
262     {
263         status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->outPipe);
264 
265         if (status != kStatus_USB_Success)
266         {
267 #ifdef HOST_ECHO
268             usb_echo("error when close pipe\r\n");
269 #endif
270         }
271         printerInstance->outPipe = NULL;
272     }
273 
274     /* open interface pipes */
275     interfacePointer = (usb_host_interface_t *)printerInstance->interfaceHandle;
276     for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex)
277     {
278         epDesc = interfacePointer->epList[epIndex].epDesc;
279         if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
280              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
281             ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
282         {
283             pipeInit.devInstance     = printerInstance->deviceHandle;
284             pipeInit.pipeType        = USB_ENDPOINT_BULK;
285             pipeInit.direction       = USB_IN;
286             pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
287             pipeInit.interval        = epDesc->bInterval;
288             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
289                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
290             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
291                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
292             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
293 
294             printerInstance->inPacketSize = pipeInit.maxPacketSize;
295 
296             status = USB_HostOpenPipe(printerInstance->hostHandle, &printerInstance->inPipe, &pipeInit);
297             if (status != kStatus_USB_Success)
298             {
299 #ifdef HOST_ECHO
300                 usb_echo("USB_HostPrinterSetInterface fail to open pipe\r\n");
301 #endif
302                 return kStatus_USB_Error;
303             }
304         }
305         else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
306                   USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
307                  ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
308         {
309             pipeInit.devInstance     = printerInstance->deviceHandle;
310             pipeInit.pipeType        = USB_ENDPOINT_BULK;
311             pipeInit.direction       = USB_OUT;
312             pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
313             pipeInit.interval        = epDesc->bInterval;
314             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
315                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
316             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
317                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
318             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
319 
320             printerInstance->outPacketSize = pipeInit.maxPacketSize;
321 
322             status = USB_HostOpenPipe(printerInstance->hostHandle, &printerInstance->outPipe, &pipeInit);
323             if (status != kStatus_USB_Success)
324             {
325 #ifdef HOST_ECHO
326                 usb_echo("USB_HostPrinterSetInterface fail to open pipe\r\n");
327 #endif
328                 return kStatus_USB_Error;
329             }
330         }
331         else
332         {
333         }
334     }
335 
336     return kStatus_USB_Success;
337 }
338 
USB_HostPrinterSetInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)339 static void USB_HostPrinterSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
340 {
341     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
342 
343     printerInstance->controlTransfer = NULL;
344     if (status == kStatus_USB_Success)
345     {
346         status = USB_HostPrinterOpenInterface(printerInstance); /* printer open interface */
347     }
348 
349     if (printerInstance->controlCallbackFn != NULL)
350     {
351         /* callback to application, callback to application, callback function is initialized in the
352         USB_HostPrinterControl,
353         USB_HostPrinterSetInterface or USB_HostHubClassRequestCommon, but is the same function */
354         printerInstance->controlCallbackFn(printerInstance->controlCallbackParam, NULL, 0, status);
355     }
356     (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
357 }
358 
USB_HostPrinterInit(usb_device_handle deviceHandle,usb_host_class_handle * classHandle)359 usb_status_t USB_HostPrinterInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
360 {
361     uint32_t infoValue = 0U;
362     uint32_t *temp;
363     /* malloc printer class instance */
364     usb_host_printer_instance_t *printerInstance =
365         (usb_host_printer_instance_t *)OSA_MemoryAllocate(sizeof(usb_host_printer_instance_t));
366 
367     if (printerInstance == NULL)
368     {
369         return kStatus_USB_AllocFail;
370     }
371 
372     /* initialize printer instance */
373     printerInstance->deviceHandle    = deviceHandle;
374     printerInstance->interfaceHandle = NULL;
375 
376     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &infoValue);
377     temp                        = (uint32_t *)infoValue;
378     printerInstance->hostHandle = (usb_host_handle)temp;
379     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &infoValue);
380     temp                         = (uint32_t *)infoValue;
381     printerInstance->controlPipe = (usb_host_pipe_handle)temp;
382 
383     *classHandle = printerInstance;
384     return kStatus_USB_Success;
385 }
386 
USB_HostPrinterSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)387 usb_status_t USB_HostPrinterSetInterface(usb_host_class_handle classHandle,
388                                          usb_host_interface_handle interfaceHandle,
389                                          uint8_t alternateSetting,
390                                          transfer_callback_t callbackFn,
391                                          void *callbackParam)
392 {
393     usb_status_t status;
394     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
395     usb_host_transfer_t *transfer;
396 
397     if (classHandle == NULL)
398     {
399         return kStatus_USB_InvalidParameter;
400     }
401 
402     /* notify host driver the interface is open */
403     status = USB_HostOpenDeviceInterface(printerInstance->deviceHandle, interfaceHandle);
404     if (status != kStatus_USB_Success)
405     {
406         return status;
407     }
408     printerInstance->interfaceHandle = interfaceHandle;
409 
410     /* cancel transfers */
411     if (printerInstance->inPipe != NULL)
412     {
413         status = USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->inPipe, NULL);
414 
415         if (status != kStatus_USB_Success)
416         {
417 #ifdef HOST_ECHO
418             usb_echo("error when cancel pipe\r\n");
419 #endif
420         }
421     }
422     if (printerInstance->outPipe != NULL)
423     {
424         status = USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->outPipe, NULL);
425 
426         if (status != kStatus_USB_Success)
427         {
428 #ifdef HOST_ECHO
429             usb_echo("error when cancel pipe\r\n");
430 #endif
431         }
432     }
433 
434     if (alternateSetting == 0U) /* open interface directly */
435     {
436         if (callbackFn != NULL)
437         {
438             status = USB_HostPrinterOpenInterface(printerInstance);
439             callbackFn(callbackParam, NULL, 0, status);
440         }
441     }
442     else /* send setup transfer */
443     {
444         /* malloc one transfer */
445         if (USB_HostMallocTransfer(printerInstance->hostHandle, &transfer) != kStatus_USB_Success)
446         {
447 #ifdef HOST_ECHO
448             usb_echo("error to get transfer\r\n");
449 #endif
450             return kStatus_USB_Error;
451         }
452 
453         /* save the application callback function */
454         printerInstance->controlCallbackFn    = callbackFn;
455         printerInstance->controlCallbackParam = callbackParam;
456         /* initialize transfer */
457         transfer->callbackFn                 = USB_HostPrinterSetInterfaceCallback;
458         transfer->callbackParam              = printerInstance;
459         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
460         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
461         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
462             ((usb_host_interface_t *)printerInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
463         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
464         transfer->setupPacket->wLength = 0;
465         transfer->transferBuffer       = NULL;
466         transfer->transferLength       = 0;
467         status = USB_HostSendSetup(printerInstance->hostHandle, printerInstance->controlPipe, transfer);
468 
469         if (status == kStatus_USB_Success)
470         {
471             printerInstance->controlTransfer = transfer;
472         }
473         else
474         {
475             (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
476         }
477     }
478 
479     return status;
480 }
481 
USB_HostPrinterDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)482 usb_status_t USB_HostPrinterDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
483 {
484     usb_status_t status;
485     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
486 
487     if (deviceHandle == NULL)
488     {
489         return kStatus_USB_InvalidHandle;
490     }
491 
492     if (classHandle != NULL) /* class instance has initialized */
493     {
494         if (printerInstance->inPipe != NULL)
495         {
496             status =
497                 USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->inPipe, NULL); /* cancel pipe */
498             if (status != kStatus_USB_Success)
499             {
500 #ifdef HOST_ECHO
501                 usb_echo("error when cancel pipe\r\n");
502 #endif
503             }
504             status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->inPipe); /* close pipe */
505 
506             if (status != kStatus_USB_Success)
507             {
508 #ifdef HOST_ECHO
509                 usb_echo("error when close pipe\r\n");
510 #endif
511             }
512             printerInstance->inPipe = NULL;
513         }
514         if (printerInstance->outPipe != NULL)
515         {
516             status =
517                 USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->outPipe, NULL); /* cancel pipe */
518             if (status != kStatus_USB_Success)
519             {
520 #ifdef HOST_ECHO
521                 usb_echo("error when cancel pipe\r\n");
522 #endif
523             }
524             status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->outPipe); /* close pipe */
525 
526             if (status != kStatus_USB_Success)
527             {
528 #ifdef HOST_ECHO
529                 usb_echo("error when close pipe\r\n");
530 #endif
531             }
532             printerInstance->outPipe = NULL;
533         }
534         if ((printerInstance->controlPipe != NULL) &&
535             (printerInstance->controlTransfer !=
536              NULL)) /* cancel control transfer if there is on-going control transfer */
537         {
538             status = USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->controlPipe,
539                                             printerInstance->controlTransfer);
540             if (status != kStatus_USB_Success)
541             {
542 #ifdef HOST_ECHO
543                 usb_echo("error when cancel pipe\r\n");
544 #endif
545             }
546         }
547         (void)USB_HostCloseDeviceInterface(
548             deviceHandle, printerInstance->interfaceHandle); /* notify host driver the interface is closed */
549         OSA_MemoryFree(printerInstance);
550     }
551     else
552     {
553         (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
554     }
555 
556     return kStatus_USB_Success;
557 }
558 
USB_HostPrinterRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)559 usb_status_t USB_HostPrinterRecv(usb_host_class_handle classHandle,
560                                  uint8_t *buffer,
561                                  uint32_t bufferLength,
562                                  transfer_callback_t callbackFn,
563                                  void *callbackParam)
564 {
565     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
566     usb_host_transfer_t *transfer;
567 
568     if (classHandle == NULL)
569     {
570         return kStatus_USB_InvalidHandle;
571     }
572 
573     if (printerInstance->inPipe == NULL)
574     {
575         return kStatus_USB_Error;
576     }
577 
578     /* malloc one transfer */
579     if (USB_HostMallocTransfer(printerInstance->hostHandle, &transfer) != kStatus_USB_Success)
580     {
581 #ifdef HOST_ECHO
582         usb_echo("error to get transfer\r\n");
583 #endif
584         return kStatus_USB_Busy;
585     }
586     /* save the application callback function */
587     printerInstance->inCallbackFn    = callbackFn;
588     printerInstance->inCallbackParam = callbackParam;
589     /* initialize transfer */
590     transfer->transferBuffer = buffer;
591     transfer->transferLength = bufferLength;
592     transfer->callbackFn     = USB_HostPrinterInPipeCallback;
593     transfer->callbackParam  = printerInstance;
594 
595     /* call host driver api */
596     if (USB_HostRecv(printerInstance->hostHandle, printerInstance->inPipe, transfer) != kStatus_USB_Success)
597     {
598 #ifdef HOST_ECHO
599         usb_echo("fail to USB_HostRecv\r\n");
600 #endif
601         (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
602         return kStatus_USB_Error;
603     }
604 
605     return kStatus_USB_Success;
606 }
607 
USB_HostPrinterGetPacketsize(usb_host_class_handle classHandle,uint8_t pipeType,uint8_t direction)608 uint16_t USB_HostPrinterGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
609 {
610     usb_host_printer_instance_t *phdcInstance = (usb_host_printer_instance_t *)classHandle;
611     if (classHandle == NULL)
612     {
613         return 0;
614     }
615 
616     if (pipeType == USB_ENDPOINT_INTERRUPT)
617     {
618         if (direction == USB_IN)
619         {
620             return phdcInstance->inPacketSize;
621         }
622         else
623         {
624             return phdcInstance->outPacketSize;
625         }
626     }
627 
628     return 0;
629 }
630 
USB_HostPrinterSend(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)631 usb_status_t USB_HostPrinterSend(usb_host_class_handle classHandle,
632                                  uint8_t *buffer,
633                                  uint32_t bufferLength,
634                                  transfer_callback_t callbackFn,
635                                  void *callbackParam)
636 {
637     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
638     usb_host_transfer_t *transfer;
639 
640     if (classHandle == NULL)
641     {
642         return kStatus_USB_InvalidHandle;
643     }
644 
645     if (printerInstance->outPipe == NULL)
646     {
647         return kStatus_USB_Error;
648     }
649 
650     /* malloc one transfer */
651     if (USB_HostMallocTransfer(printerInstance->hostHandle, &transfer) != kStatus_USB_Success)
652     {
653 #ifdef HOST_ECHO
654         usb_echo("error to get transfer\r\n");
655 #endif
656         return kStatus_USB_Error;
657     }
658     /* save the application callback function */
659     printerInstance->outCallbackFn    = callbackFn;
660     printerInstance->outCallbackParam = callbackParam;
661     /* initialize transfer */
662     transfer->transferBuffer = buffer;
663     transfer->transferLength = bufferLength;
664     transfer->callbackFn     = USB_HostPrinterOutPipeCallback;
665     transfer->callbackParam  = printerInstance;
666 
667     /* call host driver api */
668     if (USB_HostSend(printerInstance->hostHandle, printerInstance->outPipe, transfer) != kStatus_USB_Success)
669     {
670 #ifdef HOST_ECHO
671         usb_echo("fail to USB_HostSend\r\n");
672 #endif
673         (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
674         return kStatus_USB_Error;
675     }
676 
677     return kStatus_USB_Success;
678 }
679 
USB_HostPrinterControl(usb_host_printer_instance_t * printerInstance,uint8_t requestType,uint8_t request,uint16_t wvalue,uint16_t windex,uint16_t wlength,uint8_t * data,transfer_callback_t callbackFn,void * callbackParam)680 static usb_status_t USB_HostPrinterControl(usb_host_printer_instance_t *printerInstance,
681                                            uint8_t requestType,
682                                            uint8_t request,
683                                            uint16_t wvalue,
684                                            uint16_t windex,
685                                            uint16_t wlength,
686                                            uint8_t *data,
687                                            transfer_callback_t callbackFn,
688                                            void *callbackParam)
689 {
690     usb_host_transfer_t *transfer;
691 
692     if (printerInstance == NULL)
693     {
694         return kStatus_USB_InvalidHandle;
695     }
696 
697     if (USB_HostMallocTransfer(printerInstance->hostHandle, &transfer) != kStatus_USB_Success)
698     {
699 #ifdef HOST_ECHO
700         usb_echo("error to get transfer\r\n");
701 #endif
702         return kStatus_USB_Busy;
703     }
704     /* save the application callback function */
705     printerInstance->controlCallbackFn    = callbackFn;
706     printerInstance->controlCallbackParam = callbackParam;
707     /* initialize transfer */
708     transfer->transferBuffer             = data;
709     transfer->transferLength             = wlength;
710     transfer->callbackFn                 = USB_HostPrinterControlPipeCallback;
711     transfer->callbackParam              = printerInstance;
712     transfer->setupPacket->bmRequestType = requestType;
713     transfer->setupPacket->bRequest      = request;
714     transfer->setupPacket->wValue        = USB_SHORT_TO_LITTLE_ENDIAN(wvalue);
715     transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(windex);
716     transfer->setupPacket->wLength       = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
717 
718     /* call host driver api */
719     if (USB_HostSendSetup(printerInstance->hostHandle, printerInstance->controlPipe, transfer) != kStatus_USB_Success)
720     {
721 #ifdef HOST_ECHO
722         usb_echo("fail for USB_HostSendSetup\r\n");
723 #endif
724         (void)USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
725         return kStatus_USB_Error;
726     }
727     printerInstance->controlTransfer = transfer;
728 
729     return kStatus_USB_Success;
730 }
731 
USB_HostPrinterGetDeviceId(usb_host_class_handle classHandle,uint8_t interfaceIndex,uint8_t alternateSetting,uint8_t * buffer,uint32_t length,transfer_callback_t callbackFn,void * callbackParam)732 usb_status_t USB_HostPrinterGetDeviceId(usb_host_class_handle classHandle,
733                                         uint8_t interfaceIndex,
734                                         uint8_t alternateSetting,
735                                         uint8_t *buffer,
736                                         uint32_t length,
737                                         transfer_callback_t callbackFn,
738                                         void *callbackParam)
739 {
740     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
741     uint32_t infoValue                           = 0U;
742 
743     (void)USB_HostHelperGetPeripheralInformation(printerInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceConfigIndex,
744                                                  &infoValue);
745 
746     return USB_HostPrinterControl(
747         printerInstance, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
748         USB_HOST_PRINTER_GET_DEVICE_ID, (uint16_t)infoValue,
749         (uint16_t)((uint16_t)((uint16_t)interfaceIndex << 8U) | alternateSetting), (uint16_t)length, buffer, callbackFn,
750         callbackParam);
751 }
752 
USB_HostPrinterGetPortStatus(usb_host_class_handle classHandle,uint8_t * portStatus,transfer_callback_t callbackFn,void * callbackParam)753 usb_status_t USB_HostPrinterGetPortStatus(usb_host_class_handle classHandle,
754                                           uint8_t *portStatus,
755                                           transfer_callback_t callbackFn,
756                                           void *callbackParam)
757 {
758     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
759 
760     return USB_HostPrinterControl(
761         printerInstance, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
762         USB_HOST_PRINTER_GET_PORT_STATUS, 0,
763         (uint16_t)(((usb_host_interface_t *)printerInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber), 1,
764         portStatus, callbackFn, callbackParam);
765 }
766 
USB_HostPrinterSoftReset(usb_host_class_handle classHandle,transfer_callback_t callbackFn,void * callbackParam)767 usb_status_t USB_HostPrinterSoftReset(usb_host_class_handle classHandle,
768                                       transfer_callback_t callbackFn,
769                                       void *callbackParam)
770 {
771     usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
772 
773     return USB_HostPrinterControl(
774         printerInstance, USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
775         USB_HOST_PRINTER_SOFT_RESET, 0,
776         (uint16_t)(((usb_host_interface_t *)printerInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber), 0,
777         NULL, callbackFn, callbackParam);
778 }
779 
780 #endif /* USB_HOST_CONFIG_PRINTER */
781