remove a bash-ism from a Makefile
[fx2lib.git] / lib / setupdat.c
blob002b4f7ba43f16b814494663aa829c7333485075
1 /**
2 * Copyright (C) 2009 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 <eputils.h>
31 #include <setupdat.h>
34 extern BOOL handle_get_descriptor(void);
35 extern BOOL handle_vendorcommand(BYTE cmd);
36 extern BOOL handle_set_configuration(BYTE cfg);
37 extern BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc);
38 extern BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc);
39 extern BYTE handle_get_configuration(void);
40 extern void handle_reset_ep(BYTE ep);
42 /**
43 * Predefs for handlers
44 **/
47 // GET_STATUS,
48 BOOL handle_get_status(void);
49 // CLEAR_FEATURE,
50 BOOL handle_clear_feature(void);
51 // 0x02 is reserved
52 // SET_FEATURE=0x03,
53 BOOL handle_set_feature(void);
54 // 0x04 is reserved
55 // SET_ADDRESS=0x05, // this is handled by EZ-USB core unless RENUM=0
56 // GET_DESCRIPTOR,
57 void _handle_get_descriptor(void);
58 // SET_DESCRIPTOR,
59 // GET_CONFIGURATION, // handled by callback
60 // SET_CONFIGURATION, // handled by callback
61 // GET_INTERFACE, // handled by callback
62 // SET_INTERFACE, // handled by callback
63 // SYNC_FRAME // not yet implemented
66 TRM 2.2
67 Setup Token ->
68 data transfer ->
69 handshake
72 void handle_setupdata(void) {
73 //printf ( "Handle setupdat: %02x\n", SETUPDAT[1] );
75 switch ( SETUPDAT[1] ) {
77 case GET_STATUS:
78 if (!handle_get_status())
79 STALLEP0();
80 break;
81 case CLEAR_FEATURE:
82 if (!handle_clear_feature()) {
83 STALLEP0();
85 break;
86 case SET_FEATURE:
87 if (!handle_set_feature()) {
88 STALLEP0();
90 break;
91 case GET_DESCRIPTOR:
92 if (!handle_get_descriptor())
93 _handle_get_descriptor();
94 break;
95 case GET_CONFIGURATION:
96 EP0BUF[0] = handle_get_configuration();
97 EP0BCH=0;
98 EP0BCL=1;
99 break;
100 case SET_CONFIGURATION:
101 // user callback
102 if( !handle_set_configuration(SETUPDAT[2])) {
103 STALLEP0();
105 break;
106 case GET_INTERFACE:
108 BYTE alt_ifc;
109 if (!handle_get_interface(SETUPDAT[4],&alt_ifc)) {
110 STALLEP0();
111 } else {
112 EP0BUF[0] = alt_ifc;
113 EP0BCH=0;
114 EP0BCL=1;
117 break;
118 case SET_INTERFACE:
119 // user callback
120 if ( !handle_set_interface(SETUPDAT[4],SETUPDAT[2])) {
121 STALLEP0();
123 break;
124 default:
125 if (!handle_vendorcommand(SETUPDAT[1])) {
126 printf ( "Unhandled Vendor Command: %02x\n" , SETUPDAT[1] );
127 STALLEP0();
133 // do the handshake
134 EP0CS |= bmHSNAK;
138 __xdata BYTE* ep_addr(BYTE ep) { // bit 8 of ep_num is the direction
139 BYTE ep_num = ep&~0x80; // mask the direction
140 switch (ep_num) {
141 case 0: return &EP0CS;
142 case 1: return ep&0x80? &EP1INCS : &EP1OUTCS;
143 case 2: return &EP2CS;
144 case 4: return &EP4CS;
145 case 6: return &EP6CS;
146 case 8: return &EP8CS;
147 default: return NULL;
152 // Get status has three request types
153 #define GS_DEVICE 0x80
154 #define GS_INTERFACE 0x81
155 #define GS_ENDPOINT 0x82
158 volatile BOOL self_powered=FALSE;
159 volatile BOOL remote_wakeup_allowed=FALSE;
161 BOOL handle_get_status(void) {
163 switch ( SETUPDAT[0] ) {
165 // case 0: // sometimes we get a 0 status too
166 case GS_INTERFACE:
167 EP0BUF[0] = 0;
168 EP0BUF[1] = 0;
169 EP0BCH=0;
170 EP0BCL=2;
171 break;
172 case GS_DEVICE:
174 // two byte response
175 // byte 0 bit 0 = self powered bit 1 = remote wakeup
176 EP0BUF[0] = (remote_wakeup_allowed << 1) | self_powered;
177 // byte 1 = 0
178 EP0BUF[1] = 0;
179 EP0BCH = 0;
180 EP0BCL = 2;
181 break;
182 case GS_ENDPOINT:
184 __xdata BYTE* pep=ep_addr(SETUPDAT[4]);
185 if ( !pep ) return FALSE;
186 // byte 0 bit 0 = stall bit
187 EP0BUF[0] = *pep & bmEPSTALL ? 1 : 0;
188 EP0BUF[1] = 0;
189 EP0BCH=0;
190 EP0BCL=2;
192 break;
193 default:
194 printf ( "Unexpected Get Status: %02x\n", SETUPDAT[0] );
195 return FALSE;
199 return TRUE;
203 #define GF_DEVICE 0
204 #define GF_ENDPOINT 2
206 BOOL handle_clear_feature(void) {
207 //printf ( "Clear Feature\n" );
208 switch ( SETUPDAT[0] ) {
209 case GF_DEVICE:
210 if (SETUPDAT[2] == 1) {
211 remote_wakeup_allowed=FALSE;
212 break;
215 if (SETUPDAT[2] == 6) // debug feature
216 break;
217 return FALSE;
218 case GF_ENDPOINT:
219 if (SETUPDAT[2] == 0) { // ep stall feature
220 __xdata BYTE* pep=ep_addr(SETUPDAT[4]);
221 printf ( "unstall endpoint %02X\n" , SETUPDAT[4] );
222 *pep &= ~bmEPSTALL;
223 RESETTOGGLE(SETUPDAT[4]);
224 } else {
225 printf ( "unsupported ep feature %02x", SETUPDAT[2] );
226 return FALSE;
229 break;
230 default:
231 return handle_vendorcommand(SETUPDAT[1]);
233 return TRUE;
236 BOOL handle_set_feature(void) {
237 printf ( "Set Feature %02x\n", SETUPDAT[0] );
238 switch ( SETUPDAT[0] ) {
239 case GF_DEVICE:
240 if (SETUPDAT[2] == 2) break; // this is TEST_MODE and we simply need to return the handshake
241 if (SETUPDAT[2] == 1) {
242 remote_wakeup_allowed=TRUE;
243 break;
245 if (SETUPDAT[2] == 6) // debug feature
246 break;
247 return FALSE;
248 case GF_ENDPOINT:
249 if ( SETUPDAT[2] == 0 ) { // ep stall feature
250 // set TRM 2.3.2
251 // stall and endpoint
252 __xdata BYTE* pep = ep_addr(SETUPDAT[4]);
253 printf ( "Stall ep %d\n", SETUPDAT[4] );
254 if (!pep) {
255 return FALSE;
258 *pep |= bmEPSTALL;
259 // should now reset data toggles
260 // write ep+dir to TOGCTL
261 RESETTOGGLE(SETUPDAT[4]);
262 // restore stalled ep to default condition
263 // NOTE
264 //handle_reset_ep(SETUPDAT[4]);
266 } else {
267 printf ( "unsupported ep feature %02x\n", SETUPDAT[2] );
268 return FALSE;
270 break;
271 default:
272 return handle_vendorcommand(SETUPDAT[1]);
274 return TRUE;
277 /* these are devined in dscr.asm
278 and need to be customized then
279 linked in by the firmware manually */
280 extern __code WORD dev_dscr;
281 extern __code WORD dev_qual_dscr;
282 extern __code WORD highspd_dscr;
283 extern __code WORD fullspd_dscr;
284 extern __code WORD dev_strings;
286 WORD pDevConfig = (WORD)&fullspd_dscr;
287 WORD pOtherConfig = (WORD)&highspd_dscr;
289 void handle_hispeed(BOOL highspeed) {
290 __critical {
291 printf ( "Hi Speed or reset Interrupt\n" );
292 if (highspeed) {
293 pDevConfig=(WORD)&highspd_dscr;
294 pOtherConfig=(WORD)&fullspd_dscr;
295 } else {
296 pDevConfig=(WORD)&fullspd_dscr;
297 pOtherConfig=(WORD)&highspd_dscr;
303 * Handle:
304 * Device Descriptor
305 * Device Qualifier
306 * Configuration
307 * String
308 * Other-Speed
310 void _handle_get_descriptor(void) {
311 //printf ( "Get Descriptor\n" );
313 switch ( SETUPDAT[3] ) {
314 case DSCR_DEVICE_TYPE:
315 printf ( "Get Device Config\n" );
316 SUDPTRH = MSB((WORD)&dev_dscr);
317 SUDPTRL = LSB((WORD)&dev_dscr);
318 break;
319 case DSCR_CONFIG_TYPE:
320 // get the config descriptor
321 printf ( "Get Config Descriptor\n");
322 SUDPTRH = MSB(pDevConfig);
323 SUDPTRL = LSB(pDevConfig);
324 break;
325 case DSCR_STRING_TYPE:
326 //printf ( "Get String Descriptor idx: %d\n", SETUPDAT[2] );
328 STRING_DSCR* pStr = (STRING_DSCR*)&dev_strings;
329 // pStr points to string 0
330 BYTE idx = SETUPDAT[2];
331 BYTE cur=0; // current check
332 do {
333 if (idx==cur++) break;
334 //printf ( "Length of pStr: %d\n", pStr->dsc_len );
335 //printf ( "pstr: %04x to ", pStr );
336 pStr = (STRING_DSCR*)((BYTE*)pStr + pStr->dsc_len);
337 //printf ( "%04x\n" , pStr );
338 if (pStr->dsc_type != DSCR_STRING_TYPE) pStr=NULL;
339 } while ( pStr && cur<=idx);
341 if (pStr) {
342 /* BYTE i;
343 //printf ( "found str: '");
344 for (i=0;i<pStr->dsc_len-2;++i) {
345 printf ( i%2==0?"%c":"%02x", *((BYTE*)(&pStr->pstr)+i));
346 } printf ( "\n"); */
348 SUDPTRH = MSB((WORD)pStr);
349 SUDPTRL = LSB((WORD)pStr);
350 //SUDPTRH = MSB((WORD)&dev_strings);
351 //SUDPTRL = LSB((WORD)&dev_strings);
352 } else {STALLEP0();}
356 break;
357 case DSCR_DEVQUAL_TYPE:
358 printf ( "Get Device Qualifier Descriptor\n");
359 // assumes this is a high speed capable device
360 SUDPTRH = MSB((WORD)&dev_qual_dscr);
361 SUDPTRL = LSB((WORD)&dev_qual_dscr);
362 break;
363 case DSCR_OTHERSPD_TYPE:
364 printf ( "Other Speed Descriptor\n");
365 SUDPTRH = MSB(pOtherConfig);
366 SUDPTRL = LSB(pOtherConfig);
367 break;
368 default:
369 printf ( "Unhandled Get Descriptor: %02x\n", SETUPDAT[3]);
370 STALLEP0();