void serprog_handle_command(unsigned char command) { static uint8_t i; /* Loop */ static uint8_t l; /* Length */ static uint32_t slen; /* SPIOP write len */ static uint32_t rlen; /* SPIOP read len */ static uint32_t freq_req; LED0=0; switch(command) { case S_CMD_NOP: usb_putc(S_ACK); break; case S_CMD_Q_IFACE: usb_putc(S_ACK); /* little endian multibyte value to complete to 16bit */ usb_putc(S_IFACE_VERSION); usb_putc(0); break; case S_CMD_Q_CMDMAP: usb_putc(S_ACK); /* little endian */ usb_putu32(S_CMD_MAP); for(i = 0; i < 32 - sizeof(uint32_t); i++) usb_putc(0); break; case S_CMD_Q_PGMNAME: usb_putc(S_ACK); l = 0; while(S_PGM_NAME[l]) { usb_putc(S_PGM_NAME[l]); l ++; } for(i = l; i < 16; i++) usb_putc(0); break; case S_CMD_Q_SERBUF: usb_putc(S_ACK); /* Pretend to be 64K (0xffff) */ usb_putc(0xff); usb_putc(0xff); break; case S_CMD_Q_BUSTYPE: // TODO: LPC / FWH IO support via PP-Mode usb_putc(S_ACK); usb_putc(S_SUPPORTED_BUS); break; case S_CMD_Q_CHIPSIZE: break; case S_CMD_Q_OPBUF: // TODO: opbuf function 0 break; case S_CMD_Q_WRNMAXLEN: break; case S_CMD_R_BYTE: break; case S_CMD_R_NBYTES: break; case S_CMD_O_INIT: break; case S_CMD_O_WRITEB: // TODO: opbuf function 1 break; case S_CMD_O_WRITEN: // TODO: opbuf function 2 break; case S_CMD_O_DELAY: // TODO: opbuf function 3 break; case S_CMD_O_EXEC: // TODO: opbuf function 4 break; case S_CMD_SYNCNOP: usb_putc(S_NAK); usb_putc(S_ACK); break; case S_CMD_Q_RDNMAXLEN: // TODO break; case S_CMD_S_BUSTYPE: /* We do not have multiplexed bus interfaces, * so simply ack on supported types, no setup needed. */ if((usb_getc() | S_SUPPORTED_BUS) == S_SUPPORTED_BUS) usb_putc(S_ACK); else usb_putc(S_NAK); break; case S_CMD_O_SPIOP: slen = usb_getu24(); rlen = usb_getu24(); select_chip(); /* TODO: handle errors with S_NAK */ if(slen) spi_bulk_write(slen); usb_putc(S_ACK); if(rlen) spi_bulk_read(rlen); unselect_chip(); break; case S_CMD_S_SPI_FREQ: freq_req = usb_getu32(); if(freq_req == 0) usb_putc(S_NAK); else { usb_putc(S_ACK); usb_putu32(spi_conf(freq_req)); } break; default: break; // TODO: Debug malformed command } LED0=1; }
void handle_command(unsigned char command) { static uint8_t i; /* Loop */ static uint8_t l; /* Length */ static uint32_t slen; /* SPIOP write length */ static uint32_t rlen; /* SPIOP read length */ static uint32_t freq_req; /* Requested SPI clock */ LED_BUSY(); switch(command) { case S_CMD_NOP: { usbcdc_putc(S_ACK); break; } case S_CMD_Q_IFACE: { // TODO: use usbcdc_write for better efficiency usbcdc_putc(S_ACK); /* little endian multibyte value to complete to 16bit */ usbcdc_putc(S_IFACE_VERSION); usbcdc_putc(0); break; } case S_CMD_Q_CMDMAP: { // TODO: use usbcdc_write for better efficiency usbcdc_putc(S_ACK); /* little endian */ usbcdc_putu32(S_CMD_MAP); for(i = 0; i < 32 - sizeof(uint32_t); i++) { usbcdc_putc(0); } break; } case S_CMD_Q_PGMNAME: { // TODO: use usbcdc_write for better efficiency usbcdc_putc(S_ACK); l = 0; while(S_PGM_NAME[l]) { usbcdc_putc(S_PGM_NAME[l]); l ++; } for(i = l; i < 16; i++) { usbcdc_putc(0); } break; } case S_CMD_Q_SERBUF: { // TODO: use usbcdc_write for better efficiency usbcdc_putc(S_ACK); /* Pretend to be 64K (0xffff) */ usbcdc_putc(0xff); usbcdc_putc(0xff); break; } case S_CMD_Q_BUSTYPE: { // TODO: use usbcdc_write for better efficiency // TODO: LPC / FWH IO support via PP-Mode usbcdc_putc(S_ACK); usbcdc_putc(S_SUPPORTED_BUS); break; } case S_CMD_Q_CHIPSIZE: { break; } case S_CMD_Q_OPBUF: { // TODO: opbuf function 0 break; } case S_CMD_Q_WRNMAXLEN: { break; } case S_CMD_R_BYTE: { break; } case S_CMD_R_NBYTES: { break; } case S_CMD_O_INIT: { break; } case S_CMD_O_WRITEB: { // TODO: opbuf function 1 break; } case S_CMD_O_WRITEN: { // TODO: opbuf function 2 break; } case S_CMD_O_DELAY: { // TODO: opbuf function 3 break; } case S_CMD_O_EXEC: { // TODO: opbuf function 4 break; } case S_CMD_SYNCNOP: { // TODO: use usbcdc_write for better efficiency usbcdc_putc(S_NAK); usbcdc_putc(S_ACK); break; } case S_CMD_Q_RDNMAXLEN: { // TODO break; } case S_CMD_S_BUSTYPE: { /* We do not have multiplexed bus interfaces, * so simply ack on supported types, no setup needed. */ if((usbcdc_getc() | S_SUPPORTED_BUS) == S_SUPPORTED_BUS) { usbcdc_putc(S_ACK); } else { usbcdc_putc(S_NAK); } break; } case S_CMD_O_SPIOP: { slen = usbcdc_getu24(); rlen = usbcdc_getu24(); SPI_SELECT(); /* TODO: handle errors with S_NAK */ if(slen) { spi_bulk_write(slen); } usbcdc_putc(S_ACK); // TODO: S_ACK early for better performance (so while DMA is working, programmer can receive next command)? if(rlen) { spi_bulk_read(rlen); // TODO: buffer? } SPI_UNSELECT(); break; } case S_CMD_S_SPI_FREQ: { freq_req = usbcdc_getu32(); if(freq_req == 0) { usbcdc_putc(S_NAK); } else { usbcdc_putc(S_ACK); usbcdc_putu32(spi_setup(freq_req)); } break; } case S_CMD_S_PIN_STATE: { // TODO: OE break; } default: { break; // TODO: notify protocol failure malformed command } } LED_IDLE(); }