]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blame - fx2lib/lib/setupdat.c
Import fx2lib into fx2lafw directly.
[sigrok-firmware-fx2lafw.git] / fx2lib / lib / setupdat.c
CommitLineData
3608c106
UH
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
34extern BOOL handle_vendorcommand(BYTE cmd);
35extern BOOL handle_set_configuration(BYTE cfg);
36extern BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc);
37extern BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc);
38extern BYTE handle_get_configuration();
39extern BOOL handle_set_configuration(BYTE cfg);
40extern void handle_reset_ep(BYTE ep);
41
42/**
43 * Predefs for handlers
44 **/
45
46
47// GET_STATUS,
48BOOL handle_get_status();
49// CLEAR_FEATURE,
50BOOL handle_clear_feature();
51 // 0x02 is reserved
52// SET_FEATURE=0x03,
53BOOL handle_set_feature();
54 // 0x04 is reserved
55// SET_ADDRESS=0x05, // this is handled by EZ-USB core unless RENUM=0
56// GET_DESCRIPTOR,
57void 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
72void 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
157volatile BOOL self_powered=FALSE;
158volatile BOOL remote_wakeup_allowed=FALSE;
159
160BOOL 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
205BOOL 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
231BOOL 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 */
273extern __code WORD dev_dscr;
274extern __code WORD dev_qual_dscr;
275extern __code WORD highspd_dscr;
276extern __code WORD fullspd_dscr;
277extern __code WORD dev_strings;
278
279WORD pDevConfig = (WORD)&fullspd_dscr;
280WORD pOtherConfig = (WORD)&highspd_dscr;
281
282void 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 **/
303void 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