]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blob - fx2lib/lib/setupdat.c
Import fx2lib into fx2lafw directly.
[sigrok-firmware-fx2lafw.git] / fx2lib / lib / setupdat.c
1 /**
2  * Copyright (C) 2009 Ubixum, Inc. 
3  *
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.
8  *
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.
13  *
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  **/
18
19 //#define DEBUG_SETUPDAT
20
21 #ifdef DEBUG_SETUPDAT
22 #include <stdio.h> // NOTE this needs deleted
23 #else
24 #define printf(...)
25 #define NULL (void*)0;
26 #endif
27
28 #include <fx2regs.h>
29 #include <fx2macros.h>
30 #include <eputils.h>
31 #include <setupdat.h>
32
33
34 extern BOOL handle_vendorcommand(BYTE cmd);
35 extern BOOL handle_set_configuration(BYTE cfg);
36 extern BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc);
37 extern BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc);
38 extern BYTE handle_get_configuration();
39 extern BOOL handle_set_configuration(BYTE cfg);
40 extern void handle_reset_ep(BYTE ep);
41
42 /**
43  * Predefs for handlers
44  **/
45
46
47 //  GET_STATUS,
48 BOOL handle_get_status();
49 //  CLEAR_FEATURE,
50 BOOL handle_clear_feature();
51   // 0x02 is reserved
52 //  SET_FEATURE=0x03,
53 BOOL handle_set_feature();
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();
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
64
65 /*
66  TRM 2.2
67  Setup Token ->
68  data transfer ->
69  handshake
70 */
71
72 void handle_setupdata() {
73     //printf ( "Handle setupdat: %02x\n", SETUPDAT[1] );
74
75     switch ( SETUPDAT[1] ) {
76
77         case GET_STATUS:
78             if (!handle_get_status())
79                 STALLEP0();
80             break;
81         case CLEAR_FEATURE:
82             if (!handle_clear_feature()) {
83                 STALLEP0();
84             }
85             break;
86         case SET_FEATURE:
87             if (!handle_set_feature()) {
88                 STALLEP0();
89             }
90             break;
91         case GET_DESCRIPTOR:
92             handle_get_descriptor();
93             break;
94         case GET_CONFIGURATION:            
95             EP0BUF[0] = handle_get_configuration();
96             EP0BCH=0;
97             EP0BCL=1;
98             break;
99         case SET_CONFIGURATION:
100             // user callback
101             if( !handle_set_configuration(SETUPDAT[2])) {
102                 STALLEP0();
103             }
104             break;
105         case GET_INTERFACE:
106             {
107                 BYTE alt_ifc;
108                 if (!handle_get_interface(SETUPDAT[4],&alt_ifc)) {
109                     STALLEP0();
110                 } else {
111                  EP0BUF[0] = alt_ifc;
112                  EP0BCH=0;
113                  EP0BCL=1;
114                 }
115             }
116             break;
117         case SET_INTERFACE:
118             // user callback
119             if ( !handle_set_interface(SETUPDAT[4],SETUPDAT[2])) {
120                 STALLEP0();
121             }
122             break;
123         default:
124          if (!handle_vendorcommand(SETUPDAT[1])) {
125             printf ( "Unhandled Vendor Command: %02x\n" , SETUPDAT[1] );
126             STALLEP0();
127          }
128         
129         
130     }
131     
132     // do the handshake
133     EP0CS |= bmHSNAK;
134     
135 }
136
137 __xdata BYTE* ep_addr(BYTE ep) { // bit 8 of ep_num is the direction
138  BYTE ep_num = ep&~0x80; // mask the direction
139  switch (ep_num) {
140   case 0: return &EP0CS;
141   case 1: return ep&0x80? &EP1INCS : &EP1OUTCS;
142   case 2: return &EP2CS;
143   case 4: return &EP4CS;
144   case 6: return &EP6CS;
145   case 8: return &EP8CS;
146   default: return NULL;
147  }
148 }
149
150
151 // Get status has three request types
152 #define GS_DEVICE 0x80
153 #define GS_INTERFACE 0x81
154 #define GS_ENDPOINT 0x82
155
156
157 volatile BOOL self_powered=FALSE;
158 volatile BOOL remote_wakeup_allowed=FALSE;
159
160 BOOL handle_get_status() {
161     
162     switch ( SETUPDAT[0] ) {
163
164 //        case 0: // sometimes we get a 0 status too
165         case GS_INTERFACE: 
166             EP0BUF[0] = 0;
167             EP0BUF[1] = 0;
168             EP0BCH=0;
169             EP0BCL=2;
170             break;
171         case GS_DEVICE:
172
173             // two byte response
174             // byte 0 bit 0 = self powered bit 1 = remote wakeup
175             EP0BUF[0] = (remote_wakeup_allowed << 1) | self_powered;
176             // byte 1 = 0
177             EP0BUF[1] = 0;
178             EP0BCH = 0;
179             EP0BCL = 2;
180             break;
181         case GS_ENDPOINT:
182             {
183                 __xdata BYTE* pep=ep_addr(SETUPDAT[4]);
184                 if ( !pep ) return FALSE;
185                 // byte 0 bit 0 = stall bit
186                 EP0BUF[0] = *pep & bmEPSTALL ? 1 : 0;
187                 EP0BUF[1] = 0;
188                 EP0BCH=0;
189                 EP0BCL=2;
190             }
191             break;
192         default:
193             printf ( "Unexpected Get Status: %02x\n", SETUPDAT[0] );
194             return FALSE;
195             
196                         
197     }
198     return TRUE;
199 }
200
201
202 #define GF_DEVICE 0
203 #define GF_ENDPOINT 2
204
205 BOOL handle_clear_feature() {
206  //printf ( "Clear Feature\n" );
207  switch ( SETUPDAT[0] ) {
208    case GF_DEVICE:
209     if (SETUPDAT[2] == 1) {
210         remote_wakeup_allowed=FALSE;
211         break;
212     }
213     return FALSE;
214    case GF_ENDPOINT:
215     if (SETUPDAT[2] == 0) { // ep stall feature
216         __xdata BYTE* pep=ep_addr(SETUPDAT[4]);
217         printf ( "unstall endpoint %02X\n" , SETUPDAT[4] );
218         *pep &= ~bmEPSTALL;        
219     } else {
220         printf ( "unsupported ep feature %02x", SETUPDAT[2] );
221         return FALSE;
222     }
223
224     break;
225    default:
226     return handle_vendorcommand(SETUPDAT[1]);
227  }
228  return TRUE;
229 }
230
231 BOOL handle_set_feature() {
232  printf ( "Set Feature %02x\n", SETUPDAT[0] );
233  switch ( SETUPDAT[0] ) {
234   case GF_DEVICE:
235     if (SETUPDAT[2] == 2) break; // this is TEST_MODE and we simply need to return the handshake
236     if (SETUPDAT[2] == 1) {
237        remote_wakeup_allowed=TRUE; 
238        break;
239     }
240     return FALSE;
241   case GF_ENDPOINT:
242     if ( SETUPDAT[2] == 0 ) { // ep stall feature
243         // set TRM 2.3.2
244         // stall and endpoint
245         __xdata BYTE* pep = ep_addr(SETUPDAT[4]);
246         printf ( "Stall ep %d\n", SETUPDAT[4] );
247         if (!pep) {            
248             return FALSE;
249         }
250         
251         *pep |= bmEPSTALL;
252         // should now reset data toggles
253         // write ep+dir to TOGCTL
254         RESETTOGGLE(SETUPDAT[4]);
255         // restore stalled ep to default condition
256         // NOTE
257         //handle_reset_ep(SETUPDAT[4]);
258         
259     } else {
260         printf ( "unsupported ep feature %02x\n", SETUPDAT[2] );
261         return FALSE;
262     }  
263    break;
264    default:
265     return handle_vendorcommand(SETUPDAT[1]);
266  }
267  return TRUE;
268 }
269
270 /* these are devined in dscr.asm
271    and need to be customized then
272    linked in by the firmware manually */
273 extern __code WORD dev_dscr;
274 extern __code WORD dev_qual_dscr;
275 extern __code WORD highspd_dscr;
276 extern __code WORD fullspd_dscr;
277 extern __code WORD dev_strings;
278
279 WORD pDevConfig = (WORD)&fullspd_dscr;
280 WORD pOtherConfig = (WORD)&highspd_dscr;
281
282 void handle_hispeed(BOOL highspeed) {
283  __critical { 
284      printf ( "Hi Speed or reset Interrupt\n" );
285      if (highspeed) {
286          pDevConfig=(WORD)&highspd_dscr;
287          pOtherConfig=(WORD)&fullspd_dscr;
288      } else {
289         pDevConfig=(WORD)&fullspd_dscr;
290         pOtherConfig=(WORD)&highspd_dscr;
291      }
292  }
293 }
294
295 /**
296  * Handle:
297  *  Device Descriptor
298  *  Device Qualifier
299  *  Configuration
300  *  String
301  *  Other-Speed
302  **/
303 void handle_get_descriptor() {
304     //printf ( "Get Descriptor\n" );
305     
306     switch ( SETUPDAT[3] ) {
307         case DSCR_DEVICE_TYPE:
308             printf ( "Get Device Config\n" );
309             SUDPTRH = MSB((WORD)&dev_dscr);
310             SUDPTRL = LSB((WORD)&dev_dscr);
311             break;
312         case DSCR_CONFIG_TYPE:
313             // get the config descriptor
314             printf ( "Get Config Descriptor\n");
315             SUDPTRH = MSB(pDevConfig);
316             SUDPTRL = LSB(pDevConfig);
317             break;        
318         case DSCR_STRING_TYPE:
319             //printf ( "Get String Descriptor idx: %d\n", SETUPDAT[2] );
320             {
321                 STRING_DSCR* pStr = (STRING_DSCR*)&dev_strings;
322                 // pStr points to string 0
323                 BYTE idx = SETUPDAT[2];
324                 BYTE cur=0; // current check
325                 do {
326                     if (idx==cur++) break;
327                     //printf ( "Length of pStr: %d\n", pStr->dsc_len );
328                     //printf ( "pstr: %04x to ", pStr );
329                     pStr = (STRING_DSCR*)((BYTE*)pStr + pStr->dsc_len);
330                     //printf ( "%04x\n" , pStr );
331                     if (pStr->dsc_type != DSCR_STRING_TYPE) pStr=NULL;
332                 } while ( pStr && cur<=idx);
333                 
334                 if (pStr) {
335                     /* BYTE i;
336                     //printf ( "found str: '");
337                     for (i=0;i<pStr->dsc_len-2;++i) {
338                        printf ( i%2==0?"%c":"%02x", *((BYTE*)(&pStr->pstr)+i));
339                     } printf ( "\n"); */
340                     
341                     SUDPTRH = MSB((WORD)pStr);
342                     SUDPTRL = LSB((WORD)pStr);
343                     //SUDPTRH = MSB((WORD)&dev_strings);
344                     //SUDPTRL = LSB((WORD)&dev_strings);
345                 } else {STALLEP0();}
346                 
347             }
348             
349             break;
350         case DSCR_DEVQUAL_TYPE:
351             printf ( "Get Device Qualifier Descriptor\n");
352             // assumes this is a high speed capable device
353             SUDPTRH = MSB((WORD)&dev_qual_dscr);
354             SUDPTRL = LSB((WORD)&dev_qual_dscr);
355             break;
356         case DSCR_OTHERSPD_TYPE:
357             printf ( "Other Speed Descriptor\n");
358             SUDPTRH = MSB(pOtherConfig);
359             SUDPTRL = LSB(pOtherConfig);
360             break;
361         default:
362             printf ( "Unhandled Get Descriptor: %02x\n", SETUPDAT[3]);
363             STALLEP0();
364     }
365     
366 }
367