X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=fx2lib%2Flib%2Fsetupdat.c;fp=fx2lib%2Flib%2Fsetupdat.c;h=f4c217a2c3ab64c77e52d21f842959159c21e981;hb=3608c1063d17c56c038434eba5a6b11f26e530b5;hp=0000000000000000000000000000000000000000;hpb=8b13135e5fd175911ad9d8283b17fc97fe0c7709;p=sigrok-firmware-fx2lafw.git diff --git a/fx2lib/lib/setupdat.c b/fx2lib/lib/setupdat.c new file mode 100644 index 00000000..f4c217a2 --- /dev/null +++ b/fx2lib/lib/setupdat.c @@ -0,0 +1,367 @@ +/** + * Copyright (C) 2009 Ubixum, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + **/ + +//#define DEBUG_SETUPDAT + +#ifdef DEBUG_SETUPDAT +#include // NOTE this needs deleted +#else +#define printf(...) +#define NULL (void*)0; +#endif + +#include +#include +#include +#include + + +extern BOOL handle_vendorcommand(BYTE cmd); +extern BOOL handle_set_configuration(BYTE cfg); +extern BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc); +extern BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc); +extern BYTE handle_get_configuration(); +extern BOOL handle_set_configuration(BYTE cfg); +extern void handle_reset_ep(BYTE ep); + +/** + * Predefs for handlers + **/ + + +// GET_STATUS, +BOOL handle_get_status(); +// CLEAR_FEATURE, +BOOL handle_clear_feature(); + // 0x02 is reserved +// SET_FEATURE=0x03, +BOOL handle_set_feature(); + // 0x04 is reserved +// SET_ADDRESS=0x05, // this is handled by EZ-USB core unless RENUM=0 +// GET_DESCRIPTOR, +void handle_get_descriptor(); +// SET_DESCRIPTOR, +// GET_CONFIGURATION, // handled by callback +// SET_CONFIGURATION, // handled by callback +// GET_INTERFACE, // handled by callback +// SET_INTERFACE, // handled by callback +// SYNC_FRAME // not yet implemented + +/* + TRM 2.2 + Setup Token -> + data transfer -> + handshake +*/ + +void handle_setupdata() { + //printf ( "Handle setupdat: %02x\n", SETUPDAT[1] ); + + switch ( SETUPDAT[1] ) { + + case GET_STATUS: + if (!handle_get_status()) + STALLEP0(); + break; + case CLEAR_FEATURE: + if (!handle_clear_feature()) { + STALLEP0(); + } + break; + case SET_FEATURE: + if (!handle_set_feature()) { + STALLEP0(); + } + break; + case GET_DESCRIPTOR: + handle_get_descriptor(); + break; + case GET_CONFIGURATION: + EP0BUF[0] = handle_get_configuration(); + EP0BCH=0; + EP0BCL=1; + break; + case SET_CONFIGURATION: + // user callback + if( !handle_set_configuration(SETUPDAT[2])) { + STALLEP0(); + } + break; + case GET_INTERFACE: + { + BYTE alt_ifc; + if (!handle_get_interface(SETUPDAT[4],&alt_ifc)) { + STALLEP0(); + } else { + EP0BUF[0] = alt_ifc; + EP0BCH=0; + EP0BCL=1; + } + } + break; + case SET_INTERFACE: + // user callback + if ( !handle_set_interface(SETUPDAT[4],SETUPDAT[2])) { + STALLEP0(); + } + break; + default: + if (!handle_vendorcommand(SETUPDAT[1])) { + printf ( "Unhandled Vendor Command: %02x\n" , SETUPDAT[1] ); + STALLEP0(); + } + + + } + + // do the handshake + EP0CS |= bmHSNAK; + +} + +__xdata BYTE* ep_addr(BYTE ep) { // bit 8 of ep_num is the direction + BYTE ep_num = ep&~0x80; // mask the direction + switch (ep_num) { + case 0: return &EP0CS; + case 1: return ep&0x80? &EP1INCS : &EP1OUTCS; + case 2: return &EP2CS; + case 4: return &EP4CS; + case 6: return &EP6CS; + case 8: return &EP8CS; + default: return NULL; + } +} + + +// Get status has three request types +#define GS_DEVICE 0x80 +#define GS_INTERFACE 0x81 +#define GS_ENDPOINT 0x82 + + +volatile BOOL self_powered=FALSE; +volatile BOOL remote_wakeup_allowed=FALSE; + +BOOL handle_get_status() { + + switch ( SETUPDAT[0] ) { + +// case 0: // sometimes we get a 0 status too + case GS_INTERFACE: + EP0BUF[0] = 0; + EP0BUF[1] = 0; + EP0BCH=0; + EP0BCL=2; + break; + case GS_DEVICE: + + // two byte response + // byte 0 bit 0 = self powered bit 1 = remote wakeup + EP0BUF[0] = (remote_wakeup_allowed << 1) | self_powered; + // byte 1 = 0 + EP0BUF[1] = 0; + EP0BCH = 0; + EP0BCL = 2; + break; + case GS_ENDPOINT: + { + __xdata BYTE* pep=ep_addr(SETUPDAT[4]); + if ( !pep ) return FALSE; + // byte 0 bit 0 = stall bit + EP0BUF[0] = *pep & bmEPSTALL ? 1 : 0; + EP0BUF[1] = 0; + EP0BCH=0; + EP0BCL=2; + } + break; + default: + printf ( "Unexpected Get Status: %02x\n", SETUPDAT[0] ); + return FALSE; + + + } + return TRUE; +} + + +#define GF_DEVICE 0 +#define GF_ENDPOINT 2 + +BOOL handle_clear_feature() { + //printf ( "Clear Feature\n" ); + switch ( SETUPDAT[0] ) { + case GF_DEVICE: + if (SETUPDAT[2] == 1) { + remote_wakeup_allowed=FALSE; + break; + } + return FALSE; + case GF_ENDPOINT: + if (SETUPDAT[2] == 0) { // ep stall feature + __xdata BYTE* pep=ep_addr(SETUPDAT[4]); + printf ( "unstall endpoint %02X\n" , SETUPDAT[4] ); + *pep &= ~bmEPSTALL; + } else { + printf ( "unsupported ep feature %02x", SETUPDAT[2] ); + return FALSE; + } + + break; + default: + return handle_vendorcommand(SETUPDAT[1]); + } + return TRUE; +} + +BOOL handle_set_feature() { + printf ( "Set Feature %02x\n", SETUPDAT[0] ); + switch ( SETUPDAT[0] ) { + case GF_DEVICE: + if (SETUPDAT[2] == 2) break; // this is TEST_MODE and we simply need to return the handshake + if (SETUPDAT[2] == 1) { + remote_wakeup_allowed=TRUE; + break; + } + return FALSE; + case GF_ENDPOINT: + if ( SETUPDAT[2] == 0 ) { // ep stall feature + // set TRM 2.3.2 + // stall and endpoint + __xdata BYTE* pep = ep_addr(SETUPDAT[4]); + printf ( "Stall ep %d\n", SETUPDAT[4] ); + if (!pep) { + return FALSE; + } + + *pep |= bmEPSTALL; + // should now reset data toggles + // write ep+dir to TOGCTL + RESETTOGGLE(SETUPDAT[4]); + // restore stalled ep to default condition + // NOTE + //handle_reset_ep(SETUPDAT[4]); + + } else { + printf ( "unsupported ep feature %02x\n", SETUPDAT[2] ); + return FALSE; + } + break; + default: + return handle_vendorcommand(SETUPDAT[1]); + } + return TRUE; +} + +/* these are devined in dscr.asm + and need to be customized then + linked in by the firmware manually */ +extern __code WORD dev_dscr; +extern __code WORD dev_qual_dscr; +extern __code WORD highspd_dscr; +extern __code WORD fullspd_dscr; +extern __code WORD dev_strings; + +WORD pDevConfig = (WORD)&fullspd_dscr; +WORD pOtherConfig = (WORD)&highspd_dscr; + +void handle_hispeed(BOOL highspeed) { + __critical { + printf ( "Hi Speed or reset Interrupt\n" ); + if (highspeed) { + pDevConfig=(WORD)&highspd_dscr; + pOtherConfig=(WORD)&fullspd_dscr; + } else { + pDevConfig=(WORD)&fullspd_dscr; + pOtherConfig=(WORD)&highspd_dscr; + } + } +} + +/** + * Handle: + * Device Descriptor + * Device Qualifier + * Configuration + * String + * Other-Speed + **/ +void handle_get_descriptor() { + //printf ( "Get Descriptor\n" ); + + switch ( SETUPDAT[3] ) { + case DSCR_DEVICE_TYPE: + printf ( "Get Device Config\n" ); + SUDPTRH = MSB((WORD)&dev_dscr); + SUDPTRL = LSB((WORD)&dev_dscr); + break; + case DSCR_CONFIG_TYPE: + // get the config descriptor + printf ( "Get Config Descriptor\n"); + SUDPTRH = MSB(pDevConfig); + SUDPTRL = LSB(pDevConfig); + break; + case DSCR_STRING_TYPE: + //printf ( "Get String Descriptor idx: %d\n", SETUPDAT[2] ); + { + STRING_DSCR* pStr = (STRING_DSCR*)&dev_strings; + // pStr points to string 0 + BYTE idx = SETUPDAT[2]; + BYTE cur=0; // current check + do { + if (idx==cur++) break; + //printf ( "Length of pStr: %d\n", pStr->dsc_len ); + //printf ( "pstr: %04x to ", pStr ); + pStr = (STRING_DSCR*)((BYTE*)pStr + pStr->dsc_len); + //printf ( "%04x\n" , pStr ); + if (pStr->dsc_type != DSCR_STRING_TYPE) pStr=NULL; + } while ( pStr && cur<=idx); + + if (pStr) { + /* BYTE i; + //printf ( "found str: '"); + for (i=0;idsc_len-2;++i) { + printf ( i%2==0?"%c":"%02x", *((BYTE*)(&pStr->pstr)+i)); + } printf ( "\n"); */ + + SUDPTRH = MSB((WORD)pStr); + SUDPTRL = LSB((WORD)pStr); + //SUDPTRH = MSB((WORD)&dev_strings); + //SUDPTRL = LSB((WORD)&dev_strings); + } else {STALLEP0();} + + } + + break; + case DSCR_DEVQUAL_TYPE: + printf ( "Get Device Qualifier Descriptor\n"); + // assumes this is a high speed capable device + SUDPTRH = MSB((WORD)&dev_qual_dscr); + SUDPTRL = LSB((WORD)&dev_qual_dscr); + break; + case DSCR_OTHERSPD_TYPE: + printf ( "Other Speed Descriptor\n"); + SUDPTRH = MSB(pOtherConfig); + SUDPTRL = LSB(pOtherConfig); + break; + default: + printf ( "Unhandled Get Descriptor: %02x\n", SETUPDAT[3]); + STALLEP0(); + } + +} +