1 /*
2  * @brief Vitual communication port example
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2013
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products.  This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights.  NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers.  This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include "board.h"
33 #include <stdio.h>
34 #include <string.h>
35 #include "app_usbd_cfg.h"
36 #include "cdc_vcom.h"
37 
38 /*****************************************************************************
39  * Private types/enumerations/variables
40  ****************************************************************************/
41 
42 /*****************************************************************************
43  * Public types/enumerations/variables
44  ****************************************************************************/
45 
46 static USBD_HANDLE_T g_hUsb;
47 static uint8_t g_rxBuff[256];
48 const  USBD_API_T *g_pUsbApi;
49 
50 /*****************************************************************************
51  * Private functions
52  ****************************************************************************/
53 
54 /*****************************************************************************
55  * Public functions
56  ****************************************************************************/
57 
58 /**
59  * @brief	Handle interrupt from USB0
60  * @return	Nothing
61  */
USB_IRQHandler(void)62 void USB_IRQHandler(void)
63 {
64 	USBD_API->hw->ISR(g_hUsb);
65 }
66 
67 /* Find the address of interface descriptor for given class type. */
find_IntfDesc(const uint8_t * pDesc,uint32_t intfClass)68 USB_INTERFACE_DESCRIPTOR *find_IntfDesc(const uint8_t *pDesc, uint32_t intfClass)
69 {
70 	USB_COMMON_DESCRIPTOR *pD;
71 	USB_INTERFACE_DESCRIPTOR *pIntfDesc = 0;
72 	uint32_t next_desc_adr;
73 
74 	pD = (USB_COMMON_DESCRIPTOR *) pDesc;
75 	next_desc_adr = (uint32_t) pDesc;
76 
77 	while (pD->bLength) {
78 		/* is it interface descriptor */
79 		if (pD->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) {
80 
81 			pIntfDesc = (USB_INTERFACE_DESCRIPTOR *) pD;
82 			/* did we find the right interface descriptor */
83 			if (pIntfDesc->bInterfaceClass == intfClass) {
84 				break;
85 			}
86 		}
87 		pIntfDesc = 0;
88 		next_desc_adr = (uint32_t) pD + pD->bLength;
89 		pD = (USB_COMMON_DESCRIPTOR *) next_desc_adr;
90 	}
91 
92 	return pIntfDesc;
93 }
94 
95 /**
96  * @brief	main routine for blinky example
97  * @return	Function should not exit.
98  */
main(void)99 int main(void)
100 {
101 	USBD_API_INIT_PARAM_T usb_param;
102 	USB_CORE_DESCS_T desc;
103 	ErrorCode_t ret = LPC_OK;
104 	uint32_t prompt = 0, rdCnt = 0;
105 
106 	SystemCoreClockUpdate();
107 	/* Initialize board and chip */
108 	Board_Init();
109 
110 	/* enable clocks */
111 	Chip_USB_Init();
112 
113 	/* initialize USBD ROM API pointer. */
114 	g_pUsbApi = (const USBD_API_T *) LPC_ROM_API->pUSBD;
115 
116 	/* initialize call back structures */
117 	memset((void *) &usb_param, 0, sizeof(USBD_API_INIT_PARAM_T));
118 	usb_param.usb_reg_base = LPC_USB0_BASE;
119 	/*	WORKAROUND for artf44835 ROM driver BUG:
120 	    Code clearing STALL bits in endpoint reset routine corrupts memory area
121 	    next to the endpoint control data. For example When EP0, EP1_IN, EP1_OUT,
122 	    EP2_IN are used we need to specify 3 here. But as a workaround for this
123 	    issue specify 4. So that extra EPs control structure acts as padding buffer
124 	    to avoid data corruption. Corruption of padding memory doesn’t affect the
125 	    stack/program behaviour.
126 	 */
127 	usb_param.max_num_ep = 3 + 1;
128 	usb_param.mem_base = USB_STACK_MEM_BASE;
129 	usb_param.mem_size = USB_STACK_MEM_SIZE;
130 
131 	/* Set the USB descriptors */
132 	desc.device_desc = (uint8_t *) &USB_DeviceDescriptor[0];
133 	desc.string_desc = (uint8_t *) &USB_StringDescriptor[0];
134 	/* Note, to pass USBCV test full-speed only devices should have both
135 	   descriptor arrays point to same location and device_qualifier set to 0.
136 	 */
137 	desc.high_speed_desc = (uint8_t *) &USB_FsConfigDescriptor[0];
138 	desc.full_speed_desc = (uint8_t *) &USB_FsConfigDescriptor[0];
139 	desc.device_qualifier = 0;
140 
141 	/* USB Initialization */
142 	ret = USBD_API->hw->Init(&g_hUsb, &desc, &usb_param);
143 	if (ret == LPC_OK) {
144 
145 		/* Init VCOM interface */
146 		ret = vcom_init(g_hUsb, &desc, &usb_param);
147 		if (ret == LPC_OK) {
148 			/*  enable USB interrupts */
149 			NVIC_EnableIRQ(USB0_IRQn);
150 			/* now connect */
151 			USBD_API->hw->Connect(g_hUsb, 1);
152 		}
153 
154 	}
155 
156 	DEBUGSTR("USB CDC class based virtual Comm port example!\r\n");
157 
158 	while (1) {
159 		/* Check if host has connected and opened the VCOM port */
160 		if ((vcom_connected() != 0) && (prompt == 0)) {
161 			vcom_write("Hello World!!\r\n", 15);
162 			prompt = 1;
163 		}
164 		/* If VCOM port is opened echo whatever we receive back to host. */
165 		if (prompt) {
166 			rdCnt = vcom_bread(&g_rxBuff[0], 256);
167 			if (rdCnt) {
168 				vcom_write(&g_rxBuff[0], rdCnt);
169 			}
170 		}
171 		/* Sleep until next IRQ happens */
172 		__WFI();
173 	}
174 }
175