1 |
2 |
ZTEX |
/*%
|
2 |
|
|
ZTEX Firmware Kit for EZ-USB FX3 Microcontrollers
|
3 |
|
|
Copyright (C) 2009-2017 ZTEX GmbH.
|
4 |
|
|
http://www.ztex.de
|
5 |
|
|
|
6 |
|
|
This Source Code Form is subject to the terms of the Mozilla Public
|
7 |
|
|
License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
8 |
|
|
You can obtain one at http://mozilla.org/MPL/2.0/.
|
9 |
|
|
|
10 |
|
|
Alternatively, the contents of this file may be used under the terms
|
11 |
|
|
of the GNU General Public License Version 3, as described below:
|
12 |
|
|
|
13 |
|
|
This program is free software; you can redistribute it and/or modify
|
14 |
|
|
it under the terms of the GNU General Public License version 3 as
|
15 |
|
|
published by the Free Software Foundation.
|
16 |
|
|
|
17 |
|
|
This program is distributed in the hope that it will be useful, but
|
18 |
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
20 |
|
|
General Public License for more details.
|
21 |
|
|
|
22 |
|
|
You should have received a copy of the GNU General Public License
|
23 |
|
|
along with this program; if not, see http://www.gnu.org/licenses/.
|
24 |
|
|
%*/
|
25 |
|
|
/*
|
26 |
|
|
Implementation of the Endpoint 0 functionality.
|
27 |
|
|
*/
|
28 |
|
|
|
29 |
|
|
/*
|
30 |
|
|
return values of ztex_vendor_func:
|
31 |
|
|
|
32 |
|
|
1..254: RTOS or API error (see cyu3error.h)
|
33 |
|
|
255 : other error
|
34 |
|
|
*/
|
35 |
|
|
uint8_t vendor_req_last = 0; // last vendor request + 1
|
36 |
|
|
uint8_t vendor_cmd_last = 0; // last vendor command + 1
|
37 |
|
|
uint8_t vendor_req_idx[ZTEX_VENDOR_REQ_MAX]; // indexes of vendor requests
|
38 |
|
|
uint8_t vendor_cmd_idx[ZTEX_VENDOR_CMD_MAX]; // indexes of vendor commands
|
39 |
|
|
ztex_vendor_func vendor_req[ZTEX_VENDOR_REQ_MAX]; // indexes of vendor requests
|
40 |
|
|
ztex_vendor_func vendor_cmd[ZTEX_VENDOR_CMD_MAX]; // indexes of vendor commands
|
41 |
|
|
|
42 |
|
|
void (*ztex_disable_flash_boot)() = 0; // this is board specific and called to disable boot from flash
|
43 |
|
|
|
44 |
|
|
uint8_t ztex_register_vendor_req(uint8_t idx, ztex_vendor_func f) {
|
45 |
|
|
uint8_t i=0;
|
46 |
|
|
while ( (i<vendor_req_last) && (vendor_req_idx[i]!=idx) ) i++;
|
47 |
|
|
ZTEX_ASSERT_RET((i<ZTEX_VENDOR_REQ_MAX));
|
48 |
|
|
vendor_req_idx[i]=idx;
|
49 |
|
|
vendor_req[i]=f;
|
50 |
|
|
if (i==vendor_req_last) vendor_req_last++;
|
51 |
|
|
return 0;
|
52 |
|
|
}
|
53 |
|
|
|
54 |
|
|
uint8_t ztex_register_vendor_cmd(uint8_t idx, ztex_vendor_func f) {
|
55 |
|
|
uint8_t i=0;
|
56 |
|
|
while ( (i<vendor_cmd_last) && (vendor_cmd_idx[i]!=idx) ) i++;
|
57 |
|
|
ZTEX_ASSERT_RET(i<ZTEX_VENDOR_CMD_MAX);
|
58 |
|
|
vendor_cmd_idx[i]=idx;
|
59 |
|
|
vendor_cmd[i]=f;
|
60 |
|
|
if (i==vendor_cmd_last) vendor_cmd_last++;
|
61 |
|
|
return 0;
|
62 |
|
|
}
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
uint8_t ztex_send_string_descriptor (char* str) {
|
66 |
|
|
uint8_t l = 1;
|
67 |
|
|
if ( str == NULL ) {
|
68 |
|
|
ztex_ep0buf[0]=4;
|
69 |
|
|
ztex_ep0buf[2]=0;
|
70 |
|
|
ztex_ep0buf[3]=0;
|
71 |
|
|
} else {
|
72 |
|
|
l = strlen(str);
|
73 |
|
|
ztex_ep0buf[0]=l*2+2;
|
74 |
|
|
for ( uint8_t i = 0; i<l; i++ ) {
|
75 |
|
|
ztex_ep0buf[i*2+2] = str[i];
|
76 |
|
|
ztex_ep0buf[i*2+3] = 0;
|
77 |
|
|
}
|
78 |
|
|
}
|
79 |
|
|
ztex_ep0buf[1]=CY_U3P_USB_STRING_DESCR;
|
80 |
|
|
return CyU3PUsbSendEP0Data(l*2+2, ztex_ep0buf);
|
81 |
|
|
}
|
82 |
|
|
|
83 |
|
|
#define SEND_DESCR(d) ZTEX_REC(status=CyU3PUsbSendEP0Data (((uint8_t *)d)[0], (uint8_t *)d));
|
84 |
|
|
CyBool_t ztex_ep0_handler ( uint32_t setupdat0, uint32_t setupdat1)
|
85 |
|
|
{
|
86 |
|
|
// Decode the fields from the setup request.
|
87 |
|
|
uint8_t bRequestType = (setupdat0 & CY_U3P_USB_REQUEST_TYPE_MASK);
|
88 |
|
|
uint8_t bType = (bRequestType & CY_U3P_USB_TYPE_MASK);
|
89 |
|
|
uint8_t bTarget = (bRequestType & CY_U3P_USB_TARGET_MASK);
|
90 |
|
|
uint8_t bRequest = ((setupdat0 & CY_U3P_USB_REQUEST_MASK) >> CY_U3P_USB_REQUEST_POS);
|
91 |
|
|
uint16_t wValue = ((setupdat0 & CY_U3P_USB_VALUE_MASK) >> CY_U3P_USB_VALUE_POS);
|
92 |
|
|
uint16_t wIndex = ((setupdat1 & CY_U3P_USB_INDEX_MASK) >> CY_U3P_USB_INDEX_POS);
|
93 |
|
|
uint16_t wLength = ((setupdat1 & CY_U3P_USB_LENGTH_MASK) >> CY_U3P_USB_LENGTH_POS);
|
94 |
|
|
uint8_t isHandled = 0;
|
95 |
|
|
uint8_t status = 0;
|
96 |
|
|
|
97 |
|
|
// handle strings
|
98 |
|
|
if ( bRequest==6 && (wValue>>8)==3 ) {
|
99 |
|
|
switch (wValue & 255) {
|
100 |
|
|
case 1:
|
101 |
|
|
ZTEX_REC(status = ztex_send_string_descriptor((char *)ztex_manufacturer_string));
|
102 |
|
|
break;
|
103 |
|
|
case 2:
|
104 |
|
|
ZTEX_REC(status = ztex_send_string_descriptor((char *)ztex_product_string));
|
105 |
|
|
break;
|
106 |
|
|
case 3:
|
107 |
|
|
ZTEX_REC(status = ztex_send_string_descriptor((char *)ztex_sn_string));
|
108 |
|
|
break;
|
109 |
|
|
default:
|
110 |
|
|
// 4..12 descriptions for interfaces 0..7
|
111 |
|
|
ZTEX_REC(status = ztex_send_string_descriptor( (((wValue & 255) >= 4) && ((wValue & 255) < 12)) ? ztex_interface_string[(wValue & 255)-4] : NULL) );
|
112 |
|
|
break;
|
113 |
|
|
}
|
114 |
|
|
isHandled = 1;
|
115 |
|
|
}
|
116 |
|
|
else if (bType == CY_U3P_USB_STANDARD_RQT) {
|
117 |
|
|
|
118 |
|
|
if ( (bTarget == CY_U3P_USB_TARGET_INTF) && ((bRequest == CY_U3P_USB_SC_SET_FEATURE) || (bRequest == CY_U3P_USB_SC_CLEAR_FEATURE)) && (wValue==0) ) {
|
119 |
|
|
if ( ztex_usb_is_connected )
|
120 |
|
|
CyU3PUsbAckSetup();
|
121 |
|
|
else
|
122 |
|
|
CyU3PUsbStall(0, CyTrue, CyFalse);
|
123 |
|
|
isHandled = 1;
|
124 |
|
|
}
|
125 |
|
|
|
126 |
|
|
/* Clear stall requests for endpoint is always passed to the setup callback.
|
127 |
|
|
* It's handled by ztex_ep_cleanup_handler */
|
128 |
|
|
if ( (bTarget == CY_U3P_USB_TARGET_ENDPT) && (bRequest == CY_U3P_USB_SC_CLEAR_FEATURE) && (wValue == CY_U3P_USBX_FS_EP_HALT))
|
129 |
|
|
{
|
130 |
|
|
if ( ztex_usb_is_connected )
|
131 |
|
|
{
|
132 |
|
|
ztex_ep_cleanup_handler(wIndex);
|
133 |
|
|
CyU3PUsbStall (wIndex, CyFalse, CyTrue);
|
134 |
|
|
CyU3PUsbAckSetup ();
|
135 |
|
|
isHandled = CyTrue;
|
136 |
|
|
}
|
137 |
|
|
}
|
138 |
|
|
|
139 |
|
|
}
|
140 |
|
|
// Handle vendor requests.
|
141 |
|
|
else if (bRequestType == 0xc0 ) {
|
142 |
|
|
isHandled = 0;
|
143 |
|
|
|
144 |
|
|
switch (bRequest)
|
145 |
|
|
{
|
146 |
|
|
case 0x22: // send ZTEX descriptor
|
147 |
|
|
SEND_DESCR(ztex_descriptor);
|
148 |
|
|
isHandled = 1;
|
149 |
|
|
break;
|
150 |
|
|
|
151 |
|
|
default:
|
152 |
|
|
for ( int i=0; i<vendor_req_last; i++ ) {
|
153 |
|
|
if ( bRequest==vendor_req_idx[i] ) {
|
154 |
|
|
status = (vendor_req[i])(wValue, wIndex, wLength);
|
155 |
|
|
isHandled = 1;
|
156 |
|
|
}
|
157 |
|
|
}
|
158 |
|
|
// unknown request
|
159 |
|
|
break;
|
160 |
|
|
}
|
161 |
|
|
}
|
162 |
|
|
// Handle vendor command
|
163 |
|
|
else if (bRequestType == 0x40 ) {
|
164 |
|
|
isHandled = 0;
|
165 |
|
|
switch (bRequest)
|
166 |
|
|
{
|
167 |
|
|
case 0xA1: // system reset
|
168 |
|
|
if ( (wValue == 0) && (ztex_disable_flash_boot != 0) ) ztex_disable_flash_boot();
|
169 |
|
|
CyU3PDeviceReset(CyFalse);
|
170 |
|
|
isHandled = 1;
|
171 |
|
|
break;
|
172 |
|
|
default:
|
173 |
|
|
for ( int i=0; i<vendor_cmd_last; i++ ) {
|
174 |
|
|
if ( bRequest==vendor_cmd_idx[i] ) {
|
175 |
|
|
status = (vendor_cmd[i])(wValue, wIndex, wLength);
|
176 |
|
|
isHandled = 1;
|
177 |
|
|
}
|
178 |
|
|
}
|
179 |
|
|
// unknown request
|
180 |
|
|
break;
|
181 |
|
|
}
|
182 |
|
|
}
|
183 |
|
|
return isHandled && (status == 0);
|
184 |
|
|
}
|