initial lib file import
[fx2lib.git] / lib / setupdat.c
blob7835d766c06973365464499bc466e3d7a305c760
1 /**
2 * Copyright (C) 2008 Ubixum, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 **/
19 #define DEBUG_SETUPDAT
21 #ifdef DEBUG_SETUPDAT
22 #include <stdio.h> // NOTE this needs deleted
23 #else
24 #define printf(...)
25 #define NULL (void*)0;
26 #endif
28 #include <fx2regs.h>
29 #include <fx2macros.h>
30 #include <setupdat.h>
33 extern BOOL handle_vendorcommand(BYTE cmd);
34 extern BOOL handle_set_configuration(BYTE cfg);
35 extern BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc);
36 extern BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc);
37 extern BYTE handle_get_configuration();
38 extern BOOL handle_set_configuration(BYTE cfg);
39 extern void handle_reset_ep(BYTE ep);
41 /**
42 * Predefs for handlers
43 **/
46 // GET_STATUS,
47 BOOL handle_get_status();
48 // CLEAR_FEATURE,
49 BOOL handle_clear_feature();
50 // 0x02 is reserved
51 // SET_FEATURE=0x03,
52 BOOL handle_set_feature();
53 // 0x04 is reserved
54 // SET_ADDRESS=0x05, // this is handled by EZ-USB core unless RENUM=0
55 // GET_DESCRIPTOR,
56 void handle_get_descriptor();
57 // SET_DESCRIPTOR,
58 // GET_CONFIGURATION, // handled by callback
59 // SET_CONFIGURATION, // handled by callback
60 // GET_INTERFACE, // handled by callback
61 // SET_INTERFACE, // handled by callback
62 // SYNC_FRAME // not yet implemented
65 TRM 2.2
66 Setup Token ->
67 data transfer ->
68 handshake
71 void handle_setupdata() {
72 //printf ( "Handle setupdat: %02x\n", SETUPDAT[1] );
74 switch ( SETUPDAT[1] ) {
76 case GET_STATUS:
77 if (!handle_get_status())
78 STALLEP0();
79 break;
80 case CLEAR_FEATURE:
81 if (!handle_clear_feature()) {
82 STALLEP0();
84 break;
85 case SET_FEATURE:
86 if (!handle_set_feature()) {
87 STALLEP0();
89 break;
90 case GET_DESCRIPTOR:
91 handle_get_descriptor();
92 break;
93 case GET_CONFIGURATION:
94 EP0BUF[0] = handle_get_configuration();
95 EP0BCH=0;
96 EP0BCL=1;
97 break;
98 case SET_CONFIGURATION:
99 // user callback
100 if( !handle_set_configuration(SETUPDAT[2])) {
101 STALLEP0();
103 break;
104 case GET_INTERFACE:
106 BYTE alt_ifc;
107 if (!handle_get_interface(SETUPDAT[4],&alt_ifc)) {
108 STALLEP0();
109 } else {
110 EP0BUF[0] = alt_ifc;
111 EP0BCH=0;
112 EP0BCL=1;
115 break;
116 case SET_INTERFACE:
117 // user callback
118 if ( !handle_set_interface(SETUPDAT[4],SETUPDAT[2])) {
119 STALLEP0();
121 break;
122 default:
123 if (!handle_vendorcommand(SETUPDAT[1])) {
124 printf ( "Unhandled Vendor Command: %02x\n" , SETUPDAT[1] );
125 STALLEP0();
131 // do the handshake
132 EP0CS |= bmHSNAK;
136 xdata BYTE* ep_addr(BYTE ep) { // bit 8 of ep_num is the direction
137 BYTE ep_num = ep&~0x80; // mask the direction
138 switch (ep_num) {
139 case 0: return &EP0CS;
140 case 1: return ep&0x80? &EP1INCS : &EP1OUTCS;
141 case 2: return &EP2CS;
142 case 4: return &EP4CS;
143 case 6: return &EP6CS;
144 case 8: return &EP8CS;
145 default: return NULL;
150 // Get status has three request types
151 #define GS_DEVICE 0x80
152 #define GS_INTERFACE 0x81
153 #define GS_ENDPOINT 0x82
156 BOOL handle_get_status() {
158 switch ( SETUPDAT[0] ) {
160 case GS_INTERFACE: // NOTE this falls through only because GS_DEVICE is returning 0
161 // in all cases right now. If Device changes, make this always
162 // return two 0 bytes.
163 case GS_DEVICE:
165 // two byte response
166 // byte 0 bit 0 = self powered bit 1 = remote wakeup
167 EP0BUF[0] = 0; // currently lib supports neither
168 // byte 1 = 0
169 EP0BUF[1] = 0;
170 EP0BCH = 0;
171 EP0BCL = 2;
172 break;
173 case GS_ENDPOINT:
175 xdata BYTE* pep=ep_addr(SETUPDAT[4]);
176 if ( !pep ) return FALSE;
177 // byte 0 bit 0 = stall bit
178 EP0BUF[0] = *pep & bmEPSTALL ? 1 : 0;
179 EP0BUF[1] = 0;
180 EP0BCH=0;
181 EP0BCL=2;
183 break;
184 default:
185 printf ( "Unexpected Get Status: %02x\n", SETUPDAT[0] );
186 return FALSE;
190 return TRUE;
194 #define GF_DEVICE 0
195 #define GF_ENDPOINT 2
197 BOOL handle_clear_feature() {
198 //printf ( "Clear Feature\n" );
199 switch ( SETUPDAT[0] ) {
200 case GF_DEVICE:
201 printf ( "(Clear) Remote Wakeup not supported.\n" );
202 STALLEP0(); // not currently supporting remote wakeup
203 break;
204 case GF_ENDPOINT:
205 if (SETUPDAT[2] == 0) { // ep stall feature
206 xdata BYTE* pep=ep_addr(SETUPDAT[4]);
207 printf ( "unstall endpoint %02X\n" , SETUPDAT[4] );
208 *pep &= ~bmEPSTALL;
209 } else {
210 printf ( "unsupported ep feature %02x", SETUPDAT[2] );
211 STALLEP0(); // unsupported feature
213 break;
214 default:
215 return handle_vendorcommand(SETUPDAT[1]);
217 return TRUE;
220 BOOL handle_set_feature() {
221 printf ( "Set Feature %02x\n", SETUPDAT[0] );
222 switch ( SETUPDAT[0] ) {
223 case GF_DEVICE:
224 if (SETUPDAT[2] == 2) break; // this is TEST_MODE and we simply need to return the handshake
225 printf ( "(Set) Remote Wakeup not supported.\n" );
226 return FALSE;// everything else (remote wakeup) not currently supported
227 case GF_ENDPOINT:
228 if ( SETUPDAT[2] == 0 ) { // ep stall feature
229 // set TRM 2.3.2
230 // stall and endpoint
231 xdata BYTE* pep = ep_addr(SETUPDAT[4]);
232 printf ( "Stall ep %d\n", SETUPDAT[4] );
233 if (!pep) {
234 return FALSE;
237 *pep |= bmEPSTALL;
238 // should now reset data toggles
239 // write ep+dir to TOGCTL
240 RESETTOGGLE(SETUPDAT[4]);
241 // restore stalled ep to default condition
242 // NOTE
243 //handle_reset_ep(SETUPDAT[4]);
245 } else {
246 printf ( "unsupported ep feature %02x\n", SETUPDAT[2] );
247 return FALSE;
249 break;
250 default:
251 return handle_vendorcommand(SETUPDAT[1]);
253 return TRUE;
256 /* these are devined in dscr.asm
257 and need to be customized then
258 linked in by the firmware manually */
259 extern code WORD dev_dscr;
260 extern code WORD dev_qual_dscr;
261 extern code WORD highspd_dscr;
262 extern code WORD fullspd_dscr;
263 extern code WORD dev_strings;
265 WORD pDevConfig = (WORD)&fullspd_dscr;
266 WORD pOtherConfig = (WORD)&highspd_dscr;
268 void handle_hispeed() __critical {
269 printf ( "Hi Speed Interrupt\n" );
270 pDevConfig=(WORD)&highspd_dscr;
271 pOtherConfig=(WORD)&fullspd_dscr;
275 * Handle:
276 * Device Descriptor
277 * Device Qualifier
278 * Configuration
279 * String
280 * Other-Speed
282 void handle_get_descriptor() {
283 //printf ( "Get Descriptor\n" );
285 switch ( SETUPDAT[3] ) {
286 case DSCR_DEVICE_TYPE:
287 printf ( "Get Device Config\n" );
288 SUDPTRH = MSB((WORD)&dev_dscr);
289 SUDPTRL = LSB((WORD)&dev_dscr);
290 break;
291 case DSCR_CONFIG_TYPE:
292 // get the config descriptor
293 printf ( "Get Config Descriptor\n");
294 SUDPTRH = MSB(pDevConfig);
295 SUDPTRL = LSB(pDevConfig);
296 break;
297 case DSCR_STRING_TYPE:
298 //printf ( "Get String Descriptor idx: %d\n", SETUPDAT[2] );
300 STRING_DSCR* pStr = (STRING_DSCR*)&dev_strings;
301 // pStr points to string 0
302 BYTE idx = SETUPDAT[2];
303 BYTE cur=0; // current check
304 do {
305 if (idx==cur++) break;
306 //printf ( "Length of pStr: %d\n", pStr->dsc_len );
307 //printf ( "pstr: %04x to ", pStr );
308 pStr = (STRING_DSCR*)((BYTE*)pStr + pStr->dsc_len);
309 //printf ( "%04x\n" , pStr );
310 if (pStr->dsc_type != DSCR_STRING_TYPE) pStr=NULL;
311 } while ( pStr && cur<=idx);
313 if (pStr) {
314 /* BYTE i;
315 //printf ( "found str: '");
316 for (i=0;i<pStr->dsc_len-2;++i) {
317 printf ( i%2==0?"%c":"%02x", *((BYTE*)(&pStr->pstr)+i));
318 } printf ( "\n"); */
320 SUDPTRH = MSB((WORD)pStr);
321 SUDPTRL = LSB((WORD)pStr);
322 //SUDPTRH = MSB((WORD)&dev_strings);
323 //SUDPTRL = LSB((WORD)&dev_strings);
324 } else {STALLEP0();}
328 break;
329 case DSCR_DEVQUAL_TYPE:
330 printf ( "Get Device Qualifier Descriptor\n");
331 // assumes this is a high speed capable device
332 SUDPTRH = MSB((WORD)&dev_qual_dscr);
333 SUDPTRL = LSB((WORD)&dev_qual_dscr);
334 break;
335 default:
336 printf ( "Unhandled Get Descriptor: %02x\n", SETUPDAT[3]);
337 STALLEP0();