]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blame - fx2lib/lib/setupdat.c
fx2lib: fix SDCC warning 283
[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
040a6eae 15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
3608c106
UH
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
33extern BOOL handle_vendorcommand(BYTE cmd);
34extern BOOL handle_set_configuration(BYTE cfg);
35extern BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc);
36extern BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc);
bb3c6dfd 37extern BYTE handle_get_configuration(void);
3608c106
UH
38extern BOOL handle_set_configuration(BYTE cfg);
39extern void handle_reset_ep(BYTE ep);
40
41/**
42 * Predefs for handlers
43 **/
44
45
46// GET_STATUS,
bb3c6dfd 47BOOL handle_get_status(void);
3608c106 48// CLEAR_FEATURE,
bb3c6dfd 49BOOL handle_clear_feature(void);
3608c106
UH
50 // 0x02 is reserved
51// SET_FEATURE=0x03,
bb3c6dfd 52BOOL handle_set_feature(void);
3608c106
UH
53 // 0x04 is reserved
54// SET_ADDRESS=0x05, // this is handled by EZ-USB core unless RENUM=0
55// GET_DESCRIPTOR,
bb3c6dfd 56void handle_get_descriptor(void);
3608c106
UH
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
bb3c6dfd 71void handle_setupdata(void) {
3608c106
UH
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
156volatile BOOL self_powered=FALSE;
157volatile BOOL remote_wakeup_allowed=FALSE;
158
bb3c6dfd 159BOOL handle_get_status(void) {
3608c106
UH
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
bb3c6dfd 204BOOL handle_clear_feature(void) {
3608c106
UH
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
bb3c6dfd 230BOOL handle_set_feature(void) {
3608c106
UH
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 */
272extern __code WORD dev_dscr;
273extern __code WORD dev_qual_dscr;
274extern __code WORD highspd_dscr;
275extern __code WORD fullspd_dscr;
276extern __code WORD dev_strings;
277
278WORD pDevConfig = (WORD)&fullspd_dscr;
279WORD pOtherConfig = (WORD)&highspd_dscr;
280
281void 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 **/
bb3c6dfd 302void handle_get_descriptor(void) {
3608c106
UH
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