BOOL handle_vendorcommand(BYTE cmd) { WORD addr=SETUP_VALUE(),len=SETUP_LENGTH(); switch ( cmd ) { case VC_EPSTAT: { xdata BYTE* pep= ep_addr(SETUPDAT[2]); if (pep) { EP0BUF[0] = *pep; EP0BCH=0; EP0BCL=1; return TRUE; } } break; case VC_EEPROM: { // wait for ep0 not busy switch (SETUP_TYPE) { case 0xc0: while (len) { // still have bytes to read // can't read more than 64 bytes at a time BYTE cur_read = len > 64 ? 64 : len; while (EP0CS&bmEPBUSY); // can't do this until EP0 is ready eeprom_read(0x51, addr, cur_read, EP0BUF ); EP0BCH=0; SYNCDELAY(); EP0BCL=cur_read; len -= cur_read; addr += cur_read; } break; case 0x40: while (len) { BYTE cur_write; EP0BCL = 0; // allow pc transfer in while(EP0CS & bmEPBUSY); // wait cur_write=EP0BCL; if ( !eeprom_write(0x51, addr, cur_write, EP0BUF ) ) return FALSE; addr += cur_write; len -= cur_write; } break; default: return FALSE; // bad type } printf ( "All OK\n" ); return TRUE; } break; default: { printf ( "Need to implement vendor command: %02x\n", cmd ); return FALSE; } } return FALSE; }
// Called when a vendor command is received // uint8 handleVendorCommand(uint8 cmd) { if (handleUVCCommand(cmd)) return true; if (handleCDCCommand(cmd)) return true; switch(cmd) { // Set various mode bits, or fetch status information // case CMD_MODE_STATUS: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { const __xdata uint16 param = SETUP_VALUE(); const __xdata uint8 value = SETUPDAT[4]; if ( param == FIFO_MODE ) { // Enable or disable FIFO mode fifoSetEnabled(value); } else { return false; } } else { // Get STATUS: return the diagnostic byte while ( EP0CS & bmEPBUSY ); EP0BUF[0] = 'N'; // Magic bytes (my cat's name) EP0BUF[1] = 'E'; EP0BUF[2] = 'M'; EP0BUF[3] = 'I'; EP0BUF[4] = m_diagnosticCode; // Last operation diagnostic code EP0BUF[5] = (IOA & bmBIT2) ? 0 : 1; // Flags EP0BUF[6] = 0x11; // NeroProg endpoints EP0BUF[7] = 0x26; // CommFPGA endpoints EP0BUF[8] = 0xFF; // Firmware ID MSB EP0BUF[9] = 0xFF; // Firmware ID LSB EP0BUF[10] = (uint8)(DATE>>24); // Version MSB EP0BUF[11] = (uint8)(DATE>>16); // Version EP0BUF[12] = (uint8)(DATE>>8); // Version EP0BUF[13] = (uint8)DATE; // Version LSB EP0BUF[14] = 0x00; // Reserved EP0BUF[15] = 0x00; // Reserved // Return status packet to host EP0BCH = 0; SYNCDELAY; EP0BCL = 16; } return true; // Clock data into and out of the JTAG chain. Reads from EP2OUT and writes to EP4IN. // case CMD_PROG_CLOCK_DATA: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data progShiftBegin(*((uint32 *)EP0BUF), (ProgOp)SETUPDAT[4], SETUPDAT[2]); // Init numBits & flagByte return true; // Now that numBits & flagByte are set, this operation will continue in mainLoop()... } break; // Clock an (up to) 32-bit pattern LSB-first into TMS to change JTAG TAP states // case CMD_JTAG_CLOCK_FSM: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data progClockFSM(*((uint32 *)EP0BUF), SETUPDAT[2]); // Bit pattern, transitionCount return true; } break; // Execute a number of JTAG clocks. // case CMD_JTAG_CLOCK: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { progClocks(*((uint32 *)(SETUPDAT+2))); return true; } break; // Set various mode bits, or fetch status information // case CMD_PORT_BIT_IO: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { const __xdata uint8 portNumber = SETUPDAT[2]; const __xdata uint8 bitNumber = SETUPDAT[3]; const __xdata uint8 drive = SETUPDAT[4]; const __xdata uint8 high = SETUPDAT[5]; if ( portNumber > 4 || bitNumber > 7 ) { return false; // illegal port or bit } // Get the state of the port lines: while ( EP0CS & bmEPBUSY ); EP0BUF[0] = portAccess(portNumber, (1<<bitNumber), drive, high); EP0BCH = 0; SYNCDELAY; EP0BCL = 1; return true; } break; case CMD_PORT_MAP: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { __xdata uint8 patchClass = SETUPDAT[4]; const __xdata uint8 patchPort = SETUPDAT[5]; if ( patchClass == 0x00 ) { // Patch class zero is just an anchor for the less flexible Harvard architecture // micros like the AVR; since the FX2LP has a Von Neumann architecture it can // efficiently self-modify its code, so the port mapping can be done individually, // so there's no need for an anchor to group mapping operations together. return true; } patchClass--; if ( patchClass < 4 ) { const __xdata uint8 patchBit = SETUPDAT[2]; livePatch(patchClass, 0x80 + (patchPort << 4) + patchBit); } else { livePatch( patchClass, 0x80 + (patchPort << 4) ); } return true; } break; // Command to talk to the EEPROM // case CMD_READ_WRITE_EEPROM: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { // It's an IN operation - read from prom and send to host __xdata uint16 address = SETUP_VALUE(); __xdata uint16 length = SETUP_LENGTH(); __xdata uint16 chunkSize; __xdata uint8 i; while ( length ) { while ( EP0CS & bmEPBUSY ); chunkSize = length < EP0BUF_SIZE ? length : EP0BUF_SIZE; for ( i = 0; i < chunkSize; i++ ) { EP0BUF[i] = 0x23; } promRead(SETUPDAT[4], address, chunkSize, EP0BUF); EP0BCH = 0; SYNCDELAY; EP0BCL = chunkSize; address += chunkSize; length -= chunkSize; } } else if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { // It's an OUT operation - read from host and send to prom __xdata uint16 address = SETUP_VALUE(); __xdata uint16 length = SETUP_LENGTH(); __xdata uint16 chunkSize; while ( length ) { EP0BCL = 0x00; // allow pc transfer in while ( EP0CS & bmEPBUSY ); // wait for data chunkSize = EP0BCL; promWrite(SETUPDAT[4], address, chunkSize, EP0BUF); address += chunkSize; length -= chunkSize; } } return true; } return false; // unrecognised command }
BOOL handle_vendorcommand(BYTE cmd) { if(cmd == 0x90) { // Reset reset(); // Nothing to reply EP0BCH = 0; EP0BCL = 0; EP0CS |= bmHSNAK; return TRUE; } else if(cmd == 0x91) { // Enable/Disable debug short val = SETUP_VALUE(); if(val != 0) { usb_debug_enable(); USB_DEBUG_PRINTF(6, "Debug enabled"); } else { usb_debug_disable(); } EP0BCH = 0; EP0BCL = 0; EP0CS |= bmHSNAK; return TRUE; } else if(cmd == 0x92) { // Start stream USB_DEBUG_PRINTF(6, "Start"); IOA &= ~SIG_EN; // Low // Nothing to reply EP0BCH = 0; EP0BCL = 0; EP0CS |= bmHSNAK; #ifdef SIMULATION fx2_setup_timer0(29); #else IFCONFIG |= bmIFFIFO; #endif return TRUE; } else if(cmd == 0x93) { // Stop stream USB_DEBUG_PRINTF(6, "Stop"); IOA |= SIG_EN; // High // Reset EP2 FIFORESET = bmNAKALL; SYNCDELAY(); FIFORESET = bmNAKALL | 2; SYNCDELAY(); FIFORESET = 0x00; SYNCDELAY(); // Nothing to reply EP0BCH = 0; EP0BCL = 0; EP0CS |= bmHSNAK; #ifdef SIMULATION fx2_setup_timer0(0); #else IFCONFIG &= ~bmIFFIFO; #endif return TRUE; } else if(cmd == 0x94) { // Get version USB_PRINTF(0, "AdslSniffer V0.0.1"); EP0CS |= bmHSNAK; return TRUE; } else if(cmd == 0x95) { // Get bitrate WORD size = sizeof(DWORD); DWORD *rate = (DWORD*)EP0BUF; *rate = 8832000; EP0BCH = MSB(size); EP0BCL = LSB(size); EP0CS |= bmHSNAK; return TRUE; } else if(cmd == 0x99) { // Test debug EP USB_DEBUG_PRINTF(6, "Test"); EP0BCH = 0; EP0BCL = 0; EP0CS |= bmHSNAK; return TRUE; } return FALSE; }
// Called when a vendor command is received // uint8 handleVendorCommand(uint8 cmd) { switch(cmd) { // Set various mode bits, or fetch status information // case CMD_MODE_STATUS: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { xdata uint16 wBits = SETUP_VALUE(); xdata uint16 wMask = SETUP_INDEX(); if ( wMask & MODE_FIFO ) { // Enable or disable FIFO mode fifoSetEnabled(wBits & MODE_FIFO ? true : false); } else { return false; } } else { // Get STATUS: return the diagnostic byte while ( EP0CS & bmEPBUSY ); EP0BUF[0] = 'N'; // Magic bytes (my cat's name) EP0BUF[1] = 'E'; EP0BUF[2] = 'M'; EP0BUF[3] = 'I'; EP0BUF[4] = m_diagnosticCode; // Last operation diagnostic code EP0BUF[5] = (IOA & bmBIT2) ? 0 : 1; // Flags EP0BUF[6] = 0x11; // NeroProg endpoints EP0BUF[7] = 0x26; // CommFPGA endpoints EP0BUF[8] = 0x00; // Reserved EP0BUF[9] = 0x00; // Reserved EP0BUF[10] = 0x00; // Reserved EP0BUF[11] = 0x00; // Reserved EP0BUF[12] = 0x00; // Reserved EP0BUF[13] = 0x00; // Reserved EP0BUF[14] = 0x00; // Reserved EP0BUF[15] = 0x00; // Reserved // Return status packet to host EP0BCH = 0; SYNCDELAY; EP0BCL = 16; } return true; // Clock data into and out of the JTAG chain. Reads from EP2OUT and writes to EP4IN. // case CMD_JTAG_CLOCK_DATA: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data progShiftBegin(*((uint32 *)EP0BUF), (ProgOp)SETUPDAT[4], SETUPDAT[2]); // Init numBits & flagByte return true; // Now that numBits & flagByte are set, this operation will continue in mainLoop()... } break; // Clock an (up to) 32-bit pattern LSB-first into TMS to change JTAG TAP states // case CMD_JTAG_CLOCK_FSM: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data progClockFSM(*((uint32 *)EP0BUF), SETUPDAT[2]); // Bit pattern, transitionCount return true; } break; // Execute a number of JTAG clocks. // case CMD_JTAG_CLOCK: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { progClocks(*((uint32 *)(SETUPDAT+2))); return true; } break; // Set various mode bits, or fetch status information // case CMD_PORT_IO: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { const xdata uint8 portSelect = SETUPDAT[4]; const xdata uint8 mask = SETUPDAT[5]; xdata uint8 ddrWrite = SETUPDAT[2]; xdata uint8 portWrite = SETUPDAT[3]; //usartSendString("Got: "); //usartSendByteHex(portSelect); //usartSendByteHex(mask); //usartSendByteHex(ddrWrite); //usartSendByteHex(portWrite); //usartSendByte('\r'); if ( portSelect > 4 ) { return false; // illegal port } portWrite &= mask; ddrWrite &= mask; // Get the state of the port lines: while ( EP0CS & bmEPBUSY ); EP0BUF[0] = portAccess(portSelect, mask, ddrWrite, portWrite); EP0BCH = 0; SYNCDELAY; EP0BCL = 1; return true; } break; case CMD_PORT_MAP: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { const xdata uint8 patchClass = SETUPDAT[4]; const xdata uint8 patchPort = SETUPDAT[5]; if ( patchClass < 4 ) { const xdata uint8 patchBit = SETUPDAT[2]; livePatch(patchClass, 0x80 + (patchPort << 4) + patchBit); } else { livePatch( patchClass, 0x80 + (patchPort << 4) ); } return true; } break; // Command to talk to the EEPROM // case CMD_READ_WRITE_EEPROM: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { // It's an IN operation - read from prom and send to host xdata uint16 address = SETUP_VALUE(); xdata uint16 length = SETUP_LENGTH(); xdata uint16 chunkSize; xdata uint8 i; while ( length ) { while ( EP0CS & bmEPBUSY ); chunkSize = length < EP0BUF_SIZE ? length : EP0BUF_SIZE; for ( i = 0; i < chunkSize; i++ ) { EP0BUF[i] = 0x23; } promRead(SETUPDAT[4], address, chunkSize, EP0BUF); EP0BCH = 0; SYNCDELAY; EP0BCL = chunkSize; address += chunkSize; length -= chunkSize; } } else if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { // It's an OUT operation - read from host and send to prom xdata uint16 address = SETUP_VALUE(); xdata uint16 length = SETUP_LENGTH(); xdata uint16 chunkSize; while ( length ) { EP0BCL = 0x00; // allow pc transfer in while ( EP0CS & bmEPBUSY ); // wait for data chunkSize = EP0BCL; promWrite(SETUPDAT[4], address, chunkSize, EP0BUF); address += chunkSize; length -= chunkSize; } } return true; } return false; // unrecognised command }
// Called when a vendor command is received // uint8 handleVendorCommand(uint8 cmd) { switch(cmd) { // Set various mode bits, or fetch status information // case CMD_MODE_STATUS: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { xdata uint16 wBits = SETUP_VALUE(); xdata uint16 wMask = SETUP_INDEX(); if ( wMask & MODE_JTAG ) { // When in JTAG mode, the JTAG lines are driven; tristate otherwise jtagSetEnabled(wBits & MODE_JTAG ? true : false); } } else { // Get STATUS: return the diagnostic byte while ( EP0CS & bmEPBUSY ); EP0BUF[0] = 'N'; // Magic bytes (my cat's name) EP0BUF[1] = 'E'; EP0BUF[2] = 'M'; EP0BUF[3] = 'I'; EP0BUF[4] = m_diagnosticCode; // Last operation diagnostic code EP0BUF[5] = (IOA & bmBIT2) ? 0 : 1; // Flags EP0BUF[6] = 0x11; // NeroJTAG endpoints EP0BUF[7] = 0x26; // CommFPGA endpoints EP0BUF[8] = 0x00; // Reserved EP0BUF[9] = 0x00; // Reserved EP0BUF[10] = 0x00; // Reserved EP0BUF[11] = 0x00; // Reserved EP0BUF[12] = 0x00; // Reserved EP0BUF[13] = 0x00; // Reserved EP0BUF[14] = 0x00; // Reserved EP0BUF[15] = 0x00; // Reserved // Return status packet to host EP0BCH = 0; SYNCDELAY; EP0BCL = 16; } return true; // Clock data into and out of the JTAG chain. Reads from EP2OUT and writes to EP4IN. // case CMD_JTAG_CLOCK_DATA: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data jtagShiftBegin(*((uint32 *)EP0BUF), SETUPDAT[2]); // Init numBits & flagByte return true; // Now that numBits & flagByte are set, this operation will continue in mainLoop()... } break; // Clock an (up to) 32-bit pattern LSB-first into TMS to change JTAG TAP states // case CMD_JTAG_CLOCK_FSM: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { EP0BCL = 0x00; // Allow host transfer in while ( EP0CS & bmEPBUSY ); // Wait for data jtagClockFSM(*((uint32 *)EP0BUF), SETUPDAT[2]); // Bit pattern, transitionCount return true; } break; // Execute a number of JTAG clocks. // case CMD_JTAG_CLOCK: if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { jtagClocks(*((uint32 *)(SETUPDAT+2))); return true; } break; // Set various mode bits, or fetch status information // case CMD_PORT_IO: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { const xdata uint8 portSelect = SETUPDAT[4]; const xdata uint8 mask = SETUPDAT[5]; xdata uint8 ddrWrite = SETUPDAT[2]; xdata uint8 portWrite = SETUPDAT[3]; //usartSendString("Got: "); //usartSendByteHex(portSelect); //usartSendByteHex(mask); //usartSendByteHex(ddrWrite); //usartSendByteHex(portWrite); //usartSendByte('\r'); if ( portSelect > 4 ) { return false; // illegal port } portWrite &= mask; ddrWrite &= mask; pins[portSelect] &= ~mask; // clear existing relevant bits pins[portSelect] |= portWrite; ddrs[portSelect] &= ~mask; ddrs[portSelect] |= ddrWrite; (*maskFunc[JTAG_PORT])(); // Get the state of the port D & B lines: while ( EP0CS & bmEPBUSY ); switch ( portSelect ) { case 0: OEA = ddrs[0]; IOA = pins[0]; EP0BUF[0] = IOA; break; case 2: OEC = ddrs[2]; IOC = pins[2]; EP0BUF[0] = IOC; break; case 3: OED = ddrs[3]; IOD = pins[3]; EP0BUF[0] = IOD; break; case 4: OEE = ddrs[4]; IOE = pins[4]; EP0BUF[0] = IOE; break; default: EP0BUF[0] = 0xAA; break; } EP0BCH = 0; SYNCDELAY; EP0BCL = 1; return true; } break; // Command to talk to the EEPROM // case CMD_READ_WRITE_EEPROM: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { // It's an IN operation - read from prom and send to host xdata uint16 address = SETUP_VALUE(); xdata uint16 length = SETUP_LENGTH(); xdata uint16 chunkSize; xdata uint8 i; while ( length ) { while ( EP0CS & bmEPBUSY ); chunkSize = length < EP0BUF_SIZE ? length : EP0BUF_SIZE; for ( i = 0; i < chunkSize; i++ ) { EP0BUF[i] = 0x23; } promRead(SETUPDAT[4], address, chunkSize, EP0BUF); EP0BCH = 0; SYNCDELAY; EP0BCL = chunkSize; address += chunkSize; length -= chunkSize; } } else if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { // It's an OUT operation - read from host and send to prom xdata uint16 address = SETUP_VALUE(); xdata uint16 length = SETUP_LENGTH(); xdata uint16 chunkSize; while ( length ) { EP0BCL = 0x00; // allow pc transfer in while ( EP0CS & bmEPBUSY ); // wait for data chunkSize = EP0BCL; promWrite(SETUPDAT[4], address, chunkSize, EP0BUF); address += chunkSize; length -= chunkSize; } } return true; case CMD_SELECTMAP: if ( SETUP_TYPE == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR) ) { // return the status byte and micro-controller mode while ( EP0CS & bmEPBUSY ); // can't do this until EP0 is ready EP0BUF[0] = 0xF0; EP0BUF[1] = 0x0D; EP0BUF[2] = 0x1E; EP0BCH=0; SYNCDELAY; EP0BCL=3; } else if ( SETUP_TYPE == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR) ) { smapProgBegin(MAKEDWORD(SETUP_VALUE(), SETUP_INDEX())); } return true; } return false; // unrecognised command }