コード例 #1
0
ファイル: reset.c プロジェクト: AessentTechnology/aes220
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;
}
コード例 #2
0
// 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
}
コード例 #3
0
ファイル: device.c プロジェクト: diorcety/AdslSniffer
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;
}
コード例 #4
0
ファイル: app.c プロジェクト: vaesumed/libfpgalink
// 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
}
コード例 #5
0
ファイル: app.c プロジェクト: bioak/libfpgalink
// 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
}