mpsse, mcuhost usb protocol decoding
This commit is contained in:
parent
c5a4a6b3e5
commit
210f74dbc5
|
@ -156,6 +156,7 @@ static void ftdi_task(int itfnum) {
|
||||||
enum ftdi_mode mode = ftdi_if_get_mode(itf);
|
enum ftdi_mode mode = ftdi_if_get_mode(itf);
|
||||||
struct ftfifo_fns fifocb = fifocbs[(mode == 0) ? 0 : __builtin_ctz(mode)];
|
struct ftfifo_fns fifocb = fifocbs[(mode == 0) ? 0 : __builtin_ctz(mode)];
|
||||||
uint32_t avail;
|
uint32_t avail;
|
||||||
|
uint8_t cmdbyte;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case ftmode_uart : case ftmode_fifo : case ftmode_cpufifo:
|
case ftmode_uart : case ftmode_fifo : case ftmode_cpufifo:
|
||||||
case ftmode_asyncbb: case ftmode_syncbb:
|
case ftmode_asyncbb: case ftmode_syncbb:
|
||||||
|
@ -173,8 +174,159 @@ static void ftdi_task(int itfnum) {
|
||||||
if (avail) tud_vendor_n_write(itfnum, itf->readbuf, avail);
|
if (avail) tud_vendor_n_write(itfnum, itf->readbuf, avail);
|
||||||
} while (avail == sizeof itf->readbuf);
|
} while (avail == sizeof itf->readbuf);
|
||||||
break;
|
break;
|
||||||
case ftmode_mpsse: break; // BIG TODO
|
case ftmode_mpsse:
|
||||||
case ftmode_mcuhost: break; // BIG TODO
|
avail = 0;
|
||||||
|
|
||||||
|
switch ((cmdbyte = vnd_read_byte(itf, itfnum))) {
|
||||||
|
case ftmpsse_set_dirval_lo: // low byte of output gpio, not to low level
|
||||||
|
itf->writebuf[0] = vnd_read_byte(itf, itfnum); // val
|
||||||
|
itf->writebuf[1] = vnd_read_byte(itf, itfnum); // dir
|
||||||
|
ftdi_if_mpsse_set_dirval_lo(itf, itf->writebuf[1], itf->writebuf[0]);
|
||||||
|
break;
|
||||||
|
case ftmpsse_set_dirval_hi:
|
||||||
|
itf->writebuf[0] = vnd_read_byte(itf, itfnum); // val
|
||||||
|
itf->writebuf[1] = vnd_read_byte(itf, itfnum); // dir
|
||||||
|
ftdi_if_mpsse_set_dirval_hi(itf, itf->writebuf[1], itf->writebuf[0]);
|
||||||
|
break;
|
||||||
|
case ftmpsse_read_lo:
|
||||||
|
itf->readbuf[0] = ftdi_if_mpsse_read_lo(itf);
|
||||||
|
avail = 1;
|
||||||
|
break;
|
||||||
|
case ftmpsse_read_hi:
|
||||||
|
itf->readbuf[0] = ftdi_if_mpsse_read_hi(itf);
|
||||||
|
avail = 1;
|
||||||
|
break;
|
||||||
|
case ftmpsse_loopback_on : ftdi_if_mpsse_loopback(itf, true ); break;
|
||||||
|
case ftmpsse_loopback_off: ftdi_if_mpsse_loopback(itf, false); break;
|
||||||
|
case ftmpsse_set_clkdiv:
|
||||||
|
avail = vnd_read_byte(itf, itfnum);
|
||||||
|
avail |= (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
ftdi_if_mpsse_set_clkdiv(itf, (uint16_t)avail);
|
||||||
|
avail = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ftmpsse_flush: ftdi_if_mpsse_flush(itf); break;
|
||||||
|
case ftmpsse_wait_io_hi: ftdi_if_mpsse_wait_io(itf, true ); break;
|
||||||
|
case ftmpsse_wait_io_lo: ftdi_if_mpsse_wait_io(itf, false); break;
|
||||||
|
|
||||||
|
case ftmpsse_div5_disable: ftdi_if_mpsse_div5(itf, false); break;
|
||||||
|
case ftmpsse_div5_enable : ftdi_if_mpsse_div5(itf, true ); break;
|
||||||
|
case ftmpsse_data_3ph_en : ftdi_if_mpsse_data_3ph(itf, true ); break;
|
||||||
|
case ftmpsse_data_3ph_dis: ftdi_if_mpsse_data_3ph(itf, false); break;
|
||||||
|
case ftmpsse_clockonly_bits: ftdi_if_mpsse_clockonly(itf, vnd_read_byte(itf, itfnum)); break;
|
||||||
|
case ftmpsse_clockonly_bytes:
|
||||||
|
avail = vnd_read_byte(itf, itfnum);
|
||||||
|
avail |= (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
ftdi_if_mpsse_clockonly(itf, avail);
|
||||||
|
avail = 0;
|
||||||
|
break;
|
||||||
|
case ftmpsse_clock_wait_io_hi: ftdi_if_mpsse_clock_wait_io(itf, true ); break;
|
||||||
|
case ftmpsse_clock_wait_io_lo: ftdi_if_mpsse_clock_wait_io(itf, false); break;
|
||||||
|
case ftmpsse_clock_adapclk_enable : ftdi_if_mpsse_adaptive(itf, true ); break;
|
||||||
|
case ftmpsse_clock_adapclk_disable: ftdi_if_mpsse_adaptive(itf, false); break;
|
||||||
|
case ftmpsse_clock_bits_wait_io_hi:
|
||||||
|
avail = vnd_read_byte(itf, itfnum);
|
||||||
|
avail |= (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
ftdi_if_mpsse_clockonly_wait_io(itf, true, avail);
|
||||||
|
avail = 0;
|
||||||
|
break;
|
||||||
|
case ftmpsse_clock_bits_wait_io_lo:
|
||||||
|
avail = vnd_read_byte(itf, itfnum);
|
||||||
|
avail |= (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
ftdi_if_mpsse_clockonly_wait_io(itf, false, avail);
|
||||||
|
avail = 0;
|
||||||
|
break;
|
||||||
|
case ftmpsse_hi_is_tristate:
|
||||||
|
avail = vnd_read_byte(itf, itfnum);
|
||||||
|
avail |= (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
ftdi_if_mpsse_hi_is_tristate(itf, avail);
|
||||||
|
avail = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (!(cmdbyte & ftmpsse_specialcmd)) {
|
||||||
|
if (cmdbyte & ftmpsse_tmswrite) {
|
||||||
|
if (cmdbyte & ftmpsse_bitmode) {
|
||||||
|
itf->writebuf[0] = vnd_read_byte(itf, itfnum); // number of bits
|
||||||
|
itf->writebuf[1] = vnd_read_byte(itf, itfnum); // data bits to output
|
||||||
|
itf->readbuf[0] = ftdi_if_mpsse_tms_xfer(itf, cmdbyte, itf->writebuf[0], itf->writebuf[1]);
|
||||||
|
if (cmdbyte & tdoread) avail = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// else: fallthru to error code
|
||||||
|
} else {
|
||||||
|
if (cmdbyte & bitmode) {
|
||||||
|
itf->writebuf[0] = vnd_read_byte(itf, itfnum); // number of bits
|
||||||
|
if (cmdbyte & ftmpsse_tdiwrite)
|
||||||
|
itf->writebuf[1] = vnd_read_byte(itf, itfnum); // data bits to output
|
||||||
|
itf->readbuf[0] = ftdi_if_mpsse_xfer_bits(itf, cmdbyte, itf->writebuf[0], itf->writebuf[1]);
|
||||||
|
if (cmdbyte & tdoread) avail = 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
avail = vnd_read_byte(itf, itfnum);
|
||||||
|
avail |= (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < avail; i += 64) {
|
||||||
|
uint32_t thisbatch = avail - i;
|
||||||
|
if (thisbatch > 64) thisbatch = 64;
|
||||||
|
for (size_t j = 0; j < thisbatch; ++j)
|
||||||
|
itf->writebuf[j] = vnd_read_byte(itf, itfnum);
|
||||||
|
ftdi_if_mpsse_xfer_bytes(itf, cmdbyte, thisbatch, itf->readbuf, itf->writebuf);
|
||||||
|
tud_vendor_n_write(itfnum, itf->readbuf, thisbatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
avail = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
itf->readbuf[0] = 0xfa;
|
||||||
|
itf->readbuf[1] = cmdbyte;
|
||||||
|
avail = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avail) tud_vendor_n_write(itfnum, itf->readbuf, avail);
|
||||||
|
break;
|
||||||
|
case ftmode_mcuhost:
|
||||||
|
avail = 0;
|
||||||
|
switch ((cmdbyte = vnd_read_byte(itf, itfnum))) {
|
||||||
|
case ftmcu_flush: ftdi_if_mcu_flush(itf); break;
|
||||||
|
case ftmcu_wait_io_hi: ftdi_if_mcu_wait_io(itf, true ); break;
|
||||||
|
case ftmcu_wait_io_lo: ftdi_if_mcu_wait_io(itf, false); break;
|
||||||
|
|
||||||
|
case ftmcu_read8:
|
||||||
|
itf->readbuf[0] = ftdi_if_mcu_read8(itf, vnd_read_byte(itf, itfnum));
|
||||||
|
avail = 1;
|
||||||
|
break;
|
||||||
|
case ftmcu_read16:
|
||||||
|
avail = (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
avail |= vnd_read_byte(itf, itfnum);
|
||||||
|
itf->readbuf[0] = ftdi_if_mcu_read16(itf, (uint16_t)avail);
|
||||||
|
avail = 1;
|
||||||
|
break;
|
||||||
|
case ftmcu_write8:
|
||||||
|
itf->writebuf[0] = vnd_read_byte(itf, itfnum);
|
||||||
|
itf->writebuf[1] = vnd_read_byte(itf, itfnum);
|
||||||
|
ftdi_if_mcu_write8(itf, itf->writebuf[0], itf->writebuf[1]);
|
||||||
|
break;
|
||||||
|
case ftmcu_write16:
|
||||||
|
avail = (uint32_t)vnd_read_byte(itf, itfnum) << 8;
|
||||||
|
avail |= vnd_read_byte(itf, itfnum);
|
||||||
|
itf->writebuf[0] = vnd_read_byte(itf, itfnum);
|
||||||
|
ftdi_if_mcu_write8(itf, addr, itf->writebuf[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // send error response when command doesn't exist
|
||||||
|
itf->readbuf[0] = 0xfa;
|
||||||
|
itf->readbuf[1] = cmdbyte;
|
||||||
|
avail = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avail) tuf_vendor_n_write(itfnum, itf->readbuf, avail);
|
||||||
|
break;
|
||||||
default: // drop incoming data so that the pipes don't get clogged. can't do much else
|
default: // drop incoming data so that the pipes don't get clogged. can't do much else
|
||||||
avail = tud_vendor_n_available(itfnum);
|
avail = tud_vendor_n_available(itfnum);
|
||||||
if (avail) tud_vendor_n_read(itfnum, itf->writebuf, avail);
|
if (avail) tud_vendor_n_read(itfnum, itf->writebuf, avail);
|
||||||
|
|
|
@ -154,7 +154,9 @@ enum ftdi_mpsse_cflg {
|
||||||
ftmpsse_lsbfirst = 1<<3, // if 0, msb first
|
ftmpsse_lsbfirst = 1<<3, // if 0, msb first
|
||||||
ftmpsse_tdiwrite = 1<<4, // 1 == do perform output
|
ftmpsse_tdiwrite = 1<<4, // 1 == do perform output
|
||||||
ftmpsse_tdoread = 1<<5, // 1 == do perform input
|
ftmpsse_tdoread = 1<<5, // 1 == do perform input
|
||||||
ftmpsse_tmswrite = 1<<6 // 1 == do perform output?
|
ftmpsse_tmswrite = 1<<6, // 1 == do perform output?
|
||||||
|
|
||||||
|
ftmpsse_specialcmd = 1<<7 // see below enum if set
|
||||||
};
|
};
|
||||||
// bitmode: 1 length byte, max=7 (#bits = length+1) for separate bits
|
// bitmode: 1 length byte, max=7 (#bits = length+1) for separate bits
|
||||||
// bytemode: 2 length bytes == number of bytes that follow
|
// bytemode: 2 length bytes == number of bytes that follow
|
||||||
|
@ -314,8 +316,7 @@ void ftdi_if_mpsse_set_dirval_lo(struct ftdi_interface* itf, uint8_t dir, uint8_
|
||||||
void ftdi_if_mpsse_set_dirval_hi(struct ftdi_interface* itf, uint8_t dir, uint8_t val);
|
void ftdi_if_mpsse_set_dirval_hi(struct ftdi_interface* itf, uint8_t dir, uint8_t val);
|
||||||
uint8_t ftdi_if_mpsse_read_lo(struct ftdi_interface* itf);
|
uint8_t ftdi_if_mpsse_read_lo(struct ftdi_interface* itf);
|
||||||
uint8_t ftdi_if_mpsse_read_hi(struct ftdi_interface* itf);
|
uint8_t ftdi_if_mpsse_read_hi(struct ftdi_interface* itf);
|
||||||
void ftdi_if_mpsse_loopback_on(struct ftdi_interface* itf);
|
void ftdi_if_mpsse_loopback(struct ftdi_interface* itf, bool enable);
|
||||||
void ftdi_if_mpsse_loopback_off(struct ftdi_interface* itf);
|
|
||||||
void ftdi_if_mpsse_set_clkdiv(struct ftdi_interface* itf, uint16_t div);
|
void ftdi_if_mpsse_set_clkdiv(struct ftdi_interface* itf, uint16_t div);
|
||||||
|
|
||||||
uint8_t ftdi_if_mpsse_xfer_bits(struct ftdi_interface* itf, int flags, size_t nbits, uint8_t value);
|
uint8_t ftdi_if_mpsse_xfer_bits(struct ftdi_interface* itf, int flags, size_t nbits, uint8_t value);
|
||||||
|
|
Loading…
Reference in New Issue