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