From 21f04520c3d915ae1f1a7fefa62122435f689391 Mon Sep 17 00:00:00 2001 From: Ngo Hung Cuong Date: Sat, 12 Aug 2023 16:25:26 +0700 Subject: [PATCH] Add support USB ISP 3.0, ISP v2 Renew, MCU Pro --- src/CMakeLists.txt | 6 + src/avrdude.conf.in | 36 ++ src/ispv2renew.c | 851 +++++++++++++++++++++++++++++++++++++++ src/ispv2renew.h | 15 + src/mcupro.c | 851 +++++++++++++++++++++++++++++++++++++++ src/mcupro.h | 15 + src/pgm_type.c | 6 + src/usbisp3.c | 959 ++++++++++++++++++++++++++++++++++++++++++++ src/usbisp3.h | 15 + 9 files changed, 2754 insertions(+) create mode 100644 src/ispv2renew.c create mode 100644 src/ispv2renew.h create mode 100644 src/mcupro.c create mode 100644 src/mcupro.h create mode 100644 src/usbisp3.c create mode 100644 src/usbisp3.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d75a0457..568172a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -168,6 +168,8 @@ add_library(libavrdude freebsd_ppi.h ft245r.c ft245r.h + ispv2renew.h + ispv2renew.c jtagmkI.c jtagmkI.h jtagmkI_private.h @@ -184,6 +186,8 @@ add_library(libavrdude linuxspi.h linux_ppdev.h lists.c + mcupro.h + mcupro.c micronucleus.c micronucleus.h par.c @@ -231,6 +235,8 @@ add_library(libavrdude urclock_private.h usbasp.c usbasp.h + usbisp3.h + usbisp3.c usbdevs.h usb_hidapi.c usb_libusb.c diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 43dbe767..55541b5e 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -2482,6 +2482,42 @@ programmer connection_type = usb; ; +#------------------------------------------------------------ +# usbisp3 +#------------------------------------------------------------ + +programmer + id = "usbisp3"; + desc = "USB ISP 3.0 by Ngo Hung Cuong"; + type = "usbisp3"; + prog_modes = PM_ISP; + connection_type = usb; +; + +#------------------------------------------------------------ +# ispv2renew +#------------------------------------------------------------ + +programmer + id = "ispv2renew"; + desc = "ISP v2 Renew by Ngo Hung Cuong"; + type = "ispv2renew"; + prog_modes = PM_ISP; + connection_type = usb; +; + +#------------------------------------------------------------ +# mcupro +#------------------------------------------------------------ + +programmer + id = "mcupro"; + desc = "MCU Pro by Ngo Hung Cuong"; + type = "mcupro"; + prog_modes = PM_ISP; + connection_type = usb; +; + #------------------------------------------------------------ # flip1 #------------------------------------------------------------ diff --git a/src/ispv2renew.c b/src/ispv2renew.c new file mode 100644 index 00000000..6cf6d239 --- /dev/null +++ b/src/ispv2renew.c @@ -0,0 +1,851 @@ +#include "ac_cfg.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "libavrdude.h" + +#include "ispv2renew.h" + +#include + +const char ispv2renew_desc[] = "ISP v2 Renew by Ngo Hung Cuong"; + +// libusb support +static usb_dev_handle* hUsb; +static uint8_t buff[64 * 1024]; +static uint32_t connected = 0; + +static uint32_t KT_LibUSB_OpenVidPid(uint32_t vid, uint32_t pid); +static void KT_LibUSB_Close(void); +static uint32_t KT_LibUSB_Read(uint8_t ep, uint8_t* p_data, uint32_t length); +static uint32_t KT_LibUSB_Write(uint8_t ep, uint8_t* p_data, uint32_t length); + +// ispv2renew +static char szFirmwareVer[] = "ISP v2 Renew b230421"; + +static uint32_t usbisp3_spi_exch(const PROGRAMMER* pgm, const uint8_t* pu8Send, uint8_t* pu8Recv, int u8Length) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x24; + u8Buff[1] = u8Length; + memmove(&u8Buff[4], pu8Send, u8Length); + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) + { + return -1; + } + if (!KT_LibUSB_Read(0x81, u8Buff, 64)) + { + return -1; + } + memmove(pu8Recv, u8Buff, u8Length); + + return 0; +} + +static uint32_t usbisp3_avr_setup(const PROGRAMMER* pgm, uint8_t u8Speed, uint8_t u8Type, uint8_t u8Time) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x10; + u8Buff[1] = u8Type; + u8Buff[2] = u8Speed; + u8Buff[3] = u8Time; + + return KT_LibUSB_Write(0x01, u8Buff, 64); +} + +static uint32_t usbisp3_avr_exit(const PROGRAMMER* pgm, uint8_t u8RstType, uint8_t u8RstVal) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x11; + u8Buff[1] = u8RstType; + u8Buff[2] = u8RstVal; + + return KT_LibUSB_Write(0x01, u8Buff, 64); +} + +static int usbisp3_initialize(const PROGRAMMER* pgm, const AVRPART* p) +{ + uint8_t i; + + for (i = 0; i < 8; ++i) { + if (!usbisp3_avr_setup(pgm, i, 1, 0)) + { + usbisp3_avr_exit(pgm, 0, 0); + return -1; + } + + if (pgm->program_enable(pgm, p) == 0x00) + { + return 0; + } + } + + return -1; +} + +static void usbisp3_display(const PROGRAMMER* pgm, const char* p) +{ + + return; +} + +static void usbisp3_enable(PROGRAMMER* pgm, const AVRPART* p) +{ + + return; +} + +static void usbisp3_disable(const PROGRAMMER* pgm) +{ + + usbisp3_avr_exit(pgm, 0, 0); +} + +static void usbisp3_powerdown(const PROGRAMMER* pgm) +{ + + pgm->disable(pgm); +} + +static int usbisp3_program_enable(const PROGRAMMER* pgm, const AVRPART* p) +{ + uint8_t cmd[4]; + uint8_t res[4]; + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) + { + pmsg_error("program enable instruction not defined for part %s\n", p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); + + pgm->cmd(pgm, cmd, res); + + { + int i; + msg_debug("program_enable(): sending command. Resp = "); + + for (i = 0; i < 4; i++) + { + msg_debug("%02x ", res[i]); + } + msg_debug("\n"); + } + + // check for sync character + if (res[2] != cmd[1]) + return -2; + + return 0; +} + +static int usbisp3_chip_erase(const PROGRAMMER* pgm, const AVRPART* p) +{ + + unsigned char cmd[4]; + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) + { + pmsg_error("chip erase instruction not defined for part %s\n", p->desc); + return -1; + } + + pgm->pgm_led(pgm, ON); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return 0; +} + +static int usbisp3_open(PROGRAMMER* pgm, const char* port) +{ + uint8_t u8Buff[64]; + + if (KT_LibUSB_OpenVidPid(0x1986, 0x0023)) + { + u8Buff[0] = 0x00; + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) + { + pmsg_error("USB IO: FAILED\n"); + return -1; + } + if (!KT_LibUSB_Read(0x81, u8Buff, 64)) { + pmsg_error("USB IO: FAILED\n"); + return -1; + } + if (strcmpi((char*)u8Buff, szFirmwareVer)) + { + pmsg_error("Wrong firmware version\n"); + KT_LibUSB_Close(); + return -1; + } + + return 0; + } + + return -1; +} + +static void usbisp3_close(PROGRAMMER* pgm) +{ + + KT_LibUSB_Close(); +} + +static int usbisp3_cmd(const PROGRAMMER* pgm, const unsigned char* cmd, + unsigned char* res) +{ + + return pgm->spi(pgm, cmd, res, 4); +} + +static uint32_t usbisp3_spi_exch_n(const PROGRAMMER* pgm, uint32_t u32Length, uint8_t* pu8Send, uint8_t* pu8Recv) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x03; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (0); + u8Buff[4] = (0); + + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + if (!KT_LibUSB_Write(0x01, pu8Send, u32Length)) { + return 0; + } + + u8Buff[0] = 0x25; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (0); + u8Buff[4] = (0); + + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + u8Buff[0] = 0x04; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (u32Length >> 16); + u8Buff[4] = (u32Length >> 24); + + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + return KT_LibUSB_Read(0x81, pu8Recv, u32Length); +} + +static uint32_t usbisp3_avr_read_flash(const PROGRAMMER* pgm, uint16_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[8 * 1024]; + u16Length >>= 1; + u16Address >>= 1; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + + for (i = 0; i < u16Length; ++i) { + *p = 0x20; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + *p = 0x28; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + ++u16Address; + } + + if (usbisp3_spi_exch_n(pgm, u16Length * 8, u8SendBuff, u8SendBuff)) { + p = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = u8SendBuff[i * 8 + 3]; + ++p; + *p = u8SendBuff[i * 8 + 7]; + ++p; + } + return 1; + } + else { + return 0; + } +} + +static uint32_t usbisp3_avr_read_eeprom(const PROGRAMMER* pgm, uint16_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[8 * 1024]; + + uint32_t i; + uint8_t* p; + p = u8SendBuff; + + for (i = 0; i < u16Length; ++i) { + *p = 0xA0; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + ++u16Address; + } + + if (usbisp3_spi_exch_n(pgm, u16Length * 4, u8SendBuff, u8SendBuff)) { + p = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = u8SendBuff[i * 4 + 3]; + ++p; + } + return 1; + } + else { + return 0; + } +} + +static uint32_t usbisp3_avr_write_flash(const PROGRAMMER* pgm, uint32_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[1024]; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + uint8_t* pS; + pS = pu8Data; + uint16_t u16TmpAddress; + uint16_t u16Pos = 0; + uint8_t u8Poll; + + if (u16Length < 16) { + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < (u16Length / 2); ++i) { + *p = 0x40; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + *p = 0x48; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + ++u16TmpAddress; + } + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, u16Length * 4)) { + return 0; + } + + u8SendBuff[0] = 0x4c; + u8SendBuff[1] = (u16Address >> 9); + u8SendBuff[2] = (u16Address >> 1); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + if (u16Pos % 2) { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x28; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x20; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + } + else { + Sleep(10); + return 1; + } + } + else { + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < (u16Length / 2); ++i) { + *p = 0x40; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + *p = 0x48; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + ++u16TmpAddress; + } + if (!usbisp3_spi_exch_n(pgm, u16Length * 4, u8SendBuff, u8SendBuff)) { + return 0; + } + + u8SendBuff[0] = 0x4c; + u8SendBuff[1] = (u16Address >> 9); + u8SendBuff[2] = (u16Address >> 1); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + + if (u16Pos % 2) { + + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x28; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x20; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + } + else { + Sleep(10); + return 1; + } + } + + return 0; +} + +static uint32_t usbisp3_avr_write_eeprom(const PROGRAMMER* pgm, uint32_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[1024]; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + uint8_t* pS; + pS = pu8Data; + uint16_t u16TmpAddress; + uint16_t u16Pos = 0; + uint8_t u8Poll; + + if (u16Length != 0x01) { + + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = 0xC1; + ++p; + *p = (i >> 8); + ++p; + *p = (i); + ++p; + *p = *pS; + ++pS; + ++p; + } + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, u16Length * 4)) { + return 0; + } + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0xA0; + u8SendBuff[1] = ((u16Address + u16Pos) >> 8); + u8SendBuff[2] = (u16Address + u16Pos); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + Sleep(10); + return 1; + } + } + else { + u8SendBuff[0] = 0xC0; + u8SendBuff[1] = (u16Address >> 8); + u8SendBuff[2] = (u16Address); + u8SendBuff[3] = pu8Data[0]; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0xA0; + u8SendBuff[1] = (u16Address >> 8); + u8SendBuff[2] = (u16Address); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[0]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + + return 0; +} + +static int usbisp3_paged_write(const PROGRAMMER* pgm, const AVRPART* p, const AVRMEM* mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) +{ + if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)) + { + return -1; + } + + if (strcmp(mem->desc, "flash") == 0) + { + OPCODE* readop = 0, * lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + uint8_t data = 0, cmd[64], res[64]; + + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr / 2); + pgm->cmd(pgm, cmd, res); + } + + if (usbisp3_avr_write_flash(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + } + + if (usbisp3_avr_write_eeprom(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + + return -1; +} + +static int usbisp3_paged_load(const PROGRAMMER* pgm, const AVRPART* p, const AVRMEM* mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) +{ + + // only supporting flash & eeprom page reads + if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)) + { + return -1; + } + + if (strcmp(mem->desc, "flash") == 0) + { + OPCODE* readop = 0, * lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + uint8_t data = 0, cmd[64], res[64]; + + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr / 2); + pgm->cmd(pgm, cmd, res); + } + + if (usbisp3_avr_read_flash(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + } + + if (usbisp3_avr_read_eeprom(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + + return -1; +} + +static int usbisp3_parseextparams(const PROGRAMMER* pgm, const LISTID extparms) +{ + + return 0; +} + +void ispv2renew_initpgm(PROGRAMMER* pgm) +{ + pgm->initialize = usbisp3_initialize; + pgm->display = usbisp3_display; + pgm->enable = usbisp3_enable; + pgm->disable = usbisp3_disable; + pgm->powerdown = usbisp3_powerdown; + pgm->program_enable = usbisp3_program_enable; + pgm->chip_erase = usbisp3_chip_erase; + pgm->open = usbisp3_open; + pgm->close = usbisp3_close; + pgm->spi = usbisp3_spi_exch; + + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + pgm->cmd = usbisp3_cmd; + pgm->paged_write = usbisp3_paged_write; + pgm->paged_load = usbisp3_paged_load; + + pgm->parseextparams = usbisp3_parseextparams; + + strncpy(pgm->type, "ispv2renew", sizeof(pgm->type)); +} + +uint32_t KT_LibUSB_OpenVidPid(uint32_t vid, uint32_t pid) +{ + connected = 0; + usb_init(); /* initialize the library */ + usb_find_busses(); /* find all busses */ + usb_find_devices(); /* find all connected devices */ + + struct usb_bus* bus; + struct usb_device* dev; + for (bus = usb_get_busses(); bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (dev->descriptor.idVendor == vid + && dev->descriptor.idProduct == pid) + { + hUsb = usb_open(dev); //Opens a USB device + break; + } + } + } + if (!hUsb) + { + return 0; + } + if (usb_set_configuration(hUsb, 1) < 0) // Sets the Active configuration of the device + { + usb_close(hUsb); + return 0; + } + + if (usb_claim_interface(hUsb, 0) < 0) //claims the interface with the Operating System + { + //Closes a device opened since the claim interface is failed. + usb_close(hUsb); + return 0; + } + + connected = 1; + return 1; +} + +void KT_LibUSB_Close(void) +{ + + if (connected) + { + connected = 0; + usb_release_interface(hUsb, 0); + usb_close(hUsb); + } +} + +uint32_t KT_LibUSB_Read(uint8_t ep, uint8_t* p_data, uint32_t length) +{ + + if (usb_bulk_read(hUsb, ep | 0x80, (char*)buff, length, 5000) != length) { + return 0; + } + memmove(p_data, buff, length); + + return 1; +} + +uint32_t KT_LibUSB_Write(uint8_t ep, uint8_t* p_data, uint32_t length) +{ + memmove(buff, p_data, length); + if (usb_bulk_write(hUsb, ep, (char*)buff, length, 5000) < 0) { + return 0; + } + + return 1; +} diff --git a/src/ispv2renew.h b/src/ispv2renew.h new file mode 100644 index 00000000..f6b1bcec --- /dev/null +++ b/src/ispv2renew.h @@ -0,0 +1,15 @@ +#ifndef ISPV2RENEW_H_ +#define ISPV2RENEW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + extern const char ispv2renew_desc[]; + void ispv2renew_initpgm(PROGRAMMER* pgm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/mcupro.c b/src/mcupro.c new file mode 100644 index 00000000..0325eb3e --- /dev/null +++ b/src/mcupro.c @@ -0,0 +1,851 @@ +#include "ac_cfg.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "libavrdude.h" + +#include "mcupro.h" + +#include + +const char mcupro_desc[] = "MCU Pro by Ngo Hung Cuong"; + +// libusb support +static usb_dev_handle* hUsb; +static uint8_t buff[64 * 1024]; +static uint32_t connected = 0; + +static uint32_t KT_LibUSB_OpenVidPid(uint32_t vid, uint32_t pid); +static void KT_LibUSB_Close(void); +static uint32_t KT_LibUSB_Read(uint8_t ep, uint8_t* p_data, uint32_t length); +static uint32_t KT_LibUSB_Write(uint8_t ep, uint8_t* p_data, uint32_t length); + +// ispv2renew +static char szFirmwareVer[] = "MCU PRO b221223"; + +static uint32_t usbisp3_spi_exch(const PROGRAMMER* pgm, const uint8_t* pu8Send, uint8_t* pu8Recv, int u8Length) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x24; + u8Buff[1] = u8Length; + memmove(&u8Buff[4], pu8Send, u8Length); + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) + { + return -1; + } + if (!KT_LibUSB_Read(0x81, u8Buff, 64)) + { + return -1; + } + memmove(pu8Recv, u8Buff, u8Length); + + return 0; +} + +static uint32_t usbisp3_avr_setup(const PROGRAMMER* pgm, uint8_t u8Speed, uint8_t u8Type, uint8_t u8Time) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x10; + u8Buff[1] = u8Type; + u8Buff[2] = u8Speed; + u8Buff[3] = u8Time; + + return KT_LibUSB_Write(0x01, u8Buff, 64); +} + +static uint32_t usbisp3_avr_exit(const PROGRAMMER* pgm, uint8_t u8RstType, uint8_t u8RstVal) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x11; + u8Buff[1] = u8RstType; + u8Buff[2] = u8RstVal; + + return KT_LibUSB_Write(0x01, u8Buff, 64); +} + +static int usbisp3_initialize(const PROGRAMMER* pgm, const AVRPART* p) +{ + uint8_t i; + + for (i = 0; i < 8; ++i) { + if (!usbisp3_avr_setup(pgm, i, 1, 0)) + { + usbisp3_avr_exit(pgm, 0, 0); + return -1; + } + + if (pgm->program_enable(pgm, p) == 0x00) + { + return 0; + } + } + + return -1; +} + +static void usbisp3_display(const PROGRAMMER* pgm, const char* p) +{ + + return; +} + +static void usbisp3_enable(PROGRAMMER* pgm, const AVRPART* p) +{ + + return; +} + +static void usbisp3_disable(const PROGRAMMER* pgm) +{ + + usbisp3_avr_exit(pgm, 0, 0); +} + +static void usbisp3_powerdown(const PROGRAMMER* pgm) +{ + + pgm->disable(pgm); +} + +static int usbisp3_program_enable(const PROGRAMMER* pgm, const AVRPART* p) +{ + uint8_t cmd[4]; + uint8_t res[4]; + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) + { + pmsg_error("program enable instruction not defined for part %s\n", p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); + + pgm->cmd(pgm, cmd, res); + + { + int i; + msg_debug("program_enable(): sending command. Resp = "); + + for (i = 0; i < 4; i++) + { + msg_debug("%02x ", res[i]); + } + msg_debug("\n"); + } + + // check for sync character + if (res[2] != cmd[1]) + return -2; + + return 0; +} + +static int usbisp3_chip_erase(const PROGRAMMER* pgm, const AVRPART* p) +{ + + unsigned char cmd[4]; + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) + { + pmsg_error("chip erase instruction not defined for part %s\n", p->desc); + return -1; + } + + pgm->pgm_led(pgm, ON); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return 0; +} + +static int usbisp3_open(PROGRAMMER* pgm, const char* port) +{ + uint8_t u8Buff[64]; + + if (KT_LibUSB_OpenVidPid(0x4348, 0x0005)) + { + u8Buff[0] = 0x00; + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) + { + pmsg_error("USB IO: FAILED\n"); + return -1; + } + if (!KT_LibUSB_Read(0x81, u8Buff, 64)) { + pmsg_error("USB IO: FAILED\n"); + return -1; + } + if (strcmpi((char*)u8Buff, szFirmwareVer)) + { + pmsg_error("Wrong firmware version\n"); + KT_LibUSB_Close(); + return -1; + } + + return 0; + } + + return -1; +} + +static void usbisp3_close(PROGRAMMER* pgm) +{ + + KT_LibUSB_Close(); +} + +static int usbisp3_cmd(const PROGRAMMER* pgm, const unsigned char* cmd, + unsigned char* res) +{ + + return pgm->spi(pgm, cmd, res, 4); +} + +static uint32_t usbisp3_spi_exch_n(const PROGRAMMER* pgm, uint32_t u32Length, uint8_t* pu8Send, uint8_t* pu8Recv) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x03; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (0); + u8Buff[4] = (0); + + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + if (!KT_LibUSB_Write(0x01, pu8Send, u32Length)) { + return 0; + } + + u8Buff[0] = 0x25; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (0); + u8Buff[4] = (0); + + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + u8Buff[0] = 0x04; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (u32Length >> 16); + u8Buff[4] = (u32Length >> 24); + + if (!KT_LibUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + return KT_LibUSB_Read(0x81, pu8Recv, u32Length); +} + +static uint32_t usbisp3_avr_read_flash(const PROGRAMMER* pgm, uint16_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[8 * 1024]; + u16Length >>= 1; + u16Address >>= 1; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + + for (i = 0; i < u16Length; ++i) { + *p = 0x20; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + *p = 0x28; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + ++u16Address; + } + + if (usbisp3_spi_exch_n(pgm, u16Length * 8, u8SendBuff, u8SendBuff)) { + p = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = u8SendBuff[i * 8 + 3]; + ++p; + *p = u8SendBuff[i * 8 + 7]; + ++p; + } + return 1; + } + else { + return 0; + } +} + +static uint32_t usbisp3_avr_read_eeprom(const PROGRAMMER* pgm, uint16_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[8 * 1024]; + + uint32_t i; + uint8_t* p; + p = u8SendBuff; + + for (i = 0; i < u16Length; ++i) { + *p = 0xA0; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + ++u16Address; + } + + if (usbisp3_spi_exch_n(pgm, u16Length * 4, u8SendBuff, u8SendBuff)) { + p = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = u8SendBuff[i * 4 + 3]; + ++p; + } + return 1; + } + else { + return 0; + } +} + +static uint32_t usbisp3_avr_write_flash(const PROGRAMMER* pgm, uint32_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[1024]; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + uint8_t* pS; + pS = pu8Data; + uint16_t u16TmpAddress; + uint16_t u16Pos = 0; + uint8_t u8Poll; + + if (u16Length < 16) { + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < (u16Length / 2); ++i) { + *p = 0x40; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + *p = 0x48; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + ++u16TmpAddress; + } + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, u16Length * 4)) { + return 0; + } + + u8SendBuff[0] = 0x4c; + u8SendBuff[1] = (u16Address >> 9); + u8SendBuff[2] = (u16Address >> 1); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + if (u16Pos % 2) { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x28; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x20; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + } + else { + Sleep(10); + return 1; + } + } + else { + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < (u16Length / 2); ++i) { + *p = 0x40; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + *p = 0x48; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + ++u16TmpAddress; + } + if (!usbisp3_spi_exch_n(pgm, u16Length * 4, u8SendBuff, u8SendBuff)) { + return 0; + } + + u8SendBuff[0] = 0x4c; + u8SendBuff[1] = (u16Address >> 9); + u8SendBuff[2] = (u16Address >> 1); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + + if (u16Pos % 2) { + + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x28; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x20; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + } + else { + Sleep(10); + return 1; + } + } + + return 0; +} + +static uint32_t usbisp3_avr_write_eeprom(const PROGRAMMER* pgm, uint32_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[1024]; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + uint8_t* pS; + pS = pu8Data; + uint16_t u16TmpAddress; + uint16_t u16Pos = 0; + uint8_t u8Poll; + + if (u16Length != 0x01) { + + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = 0xC1; + ++p; + *p = (i >> 8); + ++p; + *p = (i); + ++p; + *p = *pS; + ++pS; + ++p; + } + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, u16Length * 4)) { + return 0; + } + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0xA0; + u8SendBuff[1] = ((u16Address + u16Pos) >> 8); + u8SendBuff[2] = (u16Address + u16Pos); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + Sleep(10); + return 1; + } + } + else { + u8SendBuff[0] = 0xC0; + u8SendBuff[1] = (u16Address >> 8); + u8SendBuff[2] = (u16Address); + u8SendBuff[3] = pu8Data[0]; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0xA0; + u8SendBuff[1] = (u16Address >> 8); + u8SendBuff[2] = (u16Address); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[0]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + + return 0; +} + +static int usbisp3_paged_write(const PROGRAMMER* pgm, const AVRPART* p, const AVRMEM* mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) +{ + if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)) + { + return -1; + } + + if (strcmp(mem->desc, "flash") == 0) + { + OPCODE* readop = 0, * lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + uint8_t data = 0, cmd[64], res[64]; + + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr / 2); + pgm->cmd(pgm, cmd, res); + } + + if (usbisp3_avr_write_flash(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + } + + if (usbisp3_avr_write_eeprom(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + + return -1; +} + +static int usbisp3_paged_load(const PROGRAMMER* pgm, const AVRPART* p, const AVRMEM* mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) +{ + + // only supporting flash & eeprom page reads + if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)) + { + return -1; + } + + if (strcmp(mem->desc, "flash") == 0) + { + OPCODE* readop = 0, * lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + uint8_t data = 0, cmd[64], res[64]; + + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr / 2); + pgm->cmd(pgm, cmd, res); + } + + if (usbisp3_avr_read_flash(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + } + + if (usbisp3_avr_read_eeprom(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + + return -1; +} + +static int usbisp3_parseextparams(const PROGRAMMER* pgm, const LISTID extparms) +{ + + return 0; +} + +void mcupro_initpgm(PROGRAMMER* pgm) +{ + pgm->initialize = usbisp3_initialize; + pgm->display = usbisp3_display; + pgm->enable = usbisp3_enable; + pgm->disable = usbisp3_disable; + pgm->powerdown = usbisp3_powerdown; + pgm->program_enable = usbisp3_program_enable; + pgm->chip_erase = usbisp3_chip_erase; + pgm->open = usbisp3_open; + pgm->close = usbisp3_close; + pgm->spi = usbisp3_spi_exch; + + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + pgm->cmd = usbisp3_cmd; + pgm->paged_write = usbisp3_paged_write; + pgm->paged_load = usbisp3_paged_load; + + pgm->parseextparams = usbisp3_parseextparams; + + strncpy(pgm->type, "mcupro", sizeof(pgm->type)); +} + +uint32_t KT_LibUSB_OpenVidPid(uint32_t vid, uint32_t pid) +{ + connected = 0; + usb_init(); /* initialize the library */ + usb_find_busses(); /* find all busses */ + usb_find_devices(); /* find all connected devices */ + + struct usb_bus* bus; + struct usb_device* dev; + for (bus = usb_get_busses(); bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (dev->descriptor.idVendor == vid + && dev->descriptor.idProduct == pid) + { + hUsb = usb_open(dev); //Opens a USB device + break; + } + } + } + if (!hUsb) + { + return 0; + } + if (usb_set_configuration(hUsb, 1) < 0) // Sets the Active configuration of the device + { + usb_close(hUsb); + return 0; + } + + if (usb_claim_interface(hUsb, 0) < 0) //claims the interface with the Operating System + { + //Closes a device opened since the claim interface is failed. + usb_close(hUsb); + return 0; + } + + connected = 1; + return 1; +} + +void KT_LibUSB_Close(void) +{ + + if (connected) + { + connected = 0; + usb_release_interface(hUsb, 0); + usb_close(hUsb); + } +} + +uint32_t KT_LibUSB_Read(uint8_t ep, uint8_t* p_data, uint32_t length) +{ + + if (usb_bulk_read(hUsb, ep | 0x80, (char*)buff, length, 5000) != length) { + return 0; + } + memmove(p_data, buff, length); + + return 1; +} + +uint32_t KT_LibUSB_Write(uint8_t ep, uint8_t* p_data, uint32_t length) +{ + memmove(buff, p_data, length); + if (usb_bulk_write(hUsb, ep, (char*)buff, length, 5000) < 0) { + return 0; + } + + return 1; +} diff --git a/src/mcupro.h b/src/mcupro.h new file mode 100644 index 00000000..a96d3a15 --- /dev/null +++ b/src/mcupro.h @@ -0,0 +1,15 @@ +#ifndef MCUPRO_H_ +#define MCUPRO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + extern const char mcupro_desc[]; + void mcupro_initpgm(PROGRAMMER* pgm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/pgm_type.c b/src/pgm_type.c index 91400fea..a421051d 100644 --- a/src/pgm_type.c +++ b/src/pgm_type.c @@ -36,11 +36,13 @@ #include "flip1.h" #include "flip2.h" #include "ft245r.h" +#include "ispv2renew.h" #include "jtagmkI.h" #include "jtagmkII.h" #include "jtag3.h" #include "linuxgpio.h" #include "linuxspi.h" +#include "mcupro.h" #include "micronucleus.h" #include "par.h" #include "pickit2.h" @@ -53,6 +55,7 @@ #include "teensy.h" #include "urclock.h" #include "usbasp.h" +#include "usbisp3.h" #include "usbtiny.h" #include "wiring.h" #include "xbee.h" @@ -75,6 +78,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th {"flip1", flip1_initpgm, flip1_desc}, // "flip1" {"flip2", flip2_initpgm, flip2_desc}, // "flip2" {"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, // "ftdi_syncbb" + {"ispv2renew", ispv2renew_initpgm, ispv2renew_desc}, // "ispv2renew" {"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, // "JTAGMKI" {"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, // "JTAGMKII" {"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, // "JTAGMKII_AVR32" @@ -90,6 +94,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th {"jtagice3_tpi", jtag3_tpi_initpgm, jtag3_tpi_desc}, // "JTAGICE3_TPI" {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio" {"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI + {"mcupro", mcupro_initpgm, mcupro_desc}, // "mcupro" {"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0" {"par", par_initpgm, par_desc}, // "PPI" {"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2" @@ -106,6 +111,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th {"teensy", teensy_initpgm, teensy_desc}, // "teensy" {"urclock", urclock_initpgm, urclock_desc}, // "Urclock" {"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp" + {"usbisp3", usbisp3_initpgm, usbisp3_desc}, // "usbisp3" {"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny" {"wiring", wiring_initpgm, wiring_desc}, // "Wiring" {"xbee", xbee_initpgm, xbee_desc}, // "XBee" diff --git a/src/usbisp3.c b/src/usbisp3.c new file mode 100644 index 00000000..5b39a753 --- /dev/null +++ b/src/usbisp3.c @@ -0,0 +1,959 @@ +#include "ac_cfg.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "libavrdude.h" + +#include "usbisp3.h" + +#include "winusb.h" + +const char usbisp3_desc[] = "USB ISP 3.0 by Ngo Hung Cuong"; + +// winusb support +static WINUSB_INTERFACE_HANDLE hWinUsb; +static uint8_t buff[64 * 1024]; +static OVERLAPPED ov; +static HANDLE hUsb; +static uint32_t connected = 0; + +static uint32_t KT_WinUSB_OpenVidPid(uint32_t vid, uint32_t pid); +static void KT_WinUSB_Close(void); +static uint32_t KT_WinUSB_Read(uint8_t ep, uint8_t* p_data, uint32_t length); +static uint32_t KT_WinUSB_Write(uint8_t ep, uint8_t* p_data, uint32_t length); + +// usbisp3 +static char szFirmwareVer[] = "USB ISP 3.0 version 230726"; +static char szSerialVer[] = "ICVN.VN-230722"; + +static uint32_t usbisp3_spi_exch(const PROGRAMMER* pgm, const uint8_t* pu8Send, uint8_t* pu8Recv, int u8Length) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x24; + u8Buff[1] = u8Length; + memmove(&u8Buff[4], pu8Send, u8Length); + if (!KT_WinUSB_Write(0x01, u8Buff, 64)) + { + return -1; + } + if (!KT_WinUSB_Read(0x81, u8Buff, 64)) + { + return -1; + } + memmove(pu8Recv, u8Buff, u8Length); + + return 0; +} + +static uint32_t usbisp3_avr_setup(const PROGRAMMER* pgm, uint8_t u8Speed, uint8_t u8Type, uint8_t u8Time) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x10; + u8Buff[1] = u8Type; + u8Buff[2] = u8Speed; + u8Buff[3] = u8Time; + + return KT_WinUSB_Write(0x01, u8Buff, 64); +} + +static uint32_t usbisp3_avr_exit(const PROGRAMMER* pgm, uint8_t u8RstType, uint8_t u8RstVal) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x11; + u8Buff[1] = u8RstType; + u8Buff[2] = u8RstVal; + + return KT_WinUSB_Write(0x01, u8Buff, 64); +} + +static int usbisp3_initialize(const PROGRAMMER* pgm, const AVRPART* p) +{ + uint8_t i; + + for (i = 0; i < 8; ++i) { + if (!usbisp3_avr_setup(pgm, i, 1, 0)) + { + usbisp3_avr_exit(pgm, 0, 0); + return -1; + } + + if (pgm->program_enable(pgm, p) == 0x00) + { + return 0; + } + } + + return -1; +} + +static void usbisp3_display(const PROGRAMMER* pgm, const char* p) +{ + + return; +} + +static void usbisp3_enable(PROGRAMMER* pgm, const AVRPART* p) +{ + + return; +} + +static void usbisp3_disable(const PROGRAMMER* pgm) +{ + + usbisp3_avr_exit(pgm, 0, 0); +} + +static void usbisp3_powerdown(const PROGRAMMER* pgm) +{ + + pgm->disable(pgm); +} + +static int usbisp3_program_enable(const PROGRAMMER* pgm, const AVRPART* p) +{ + uint8_t cmd[4]; + uint8_t res[4]; + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) + { + pmsg_error("program enable instruction not defined for part %s\n", p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); + + pgm->cmd(pgm, cmd, res); + + { + int i; + msg_debug("program_enable(): sending command. Resp = "); + + for (i = 0; i < 4; i++) + { + msg_debug("%02x ", res[i]); + } + msg_debug("\n"); + } + + // check for sync character + if (res[2] != cmd[1]) + return -2; + + return 0; +} + +static int usbisp3_chip_erase(const PROGRAMMER* pgm, const AVRPART* p) +{ + + unsigned char cmd[4]; + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) + { + pmsg_error("chip erase instruction not defined for part %s\n", p->desc); + return -1; + } + + pgm->pgm_led(pgm, ON); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + return 0; +} + +static int usbisp3_open(PROGRAMMER* pgm, const char* port) +{ + uint8_t u8Buff[64]; + + if (KT_WinUSB_OpenVidPid(0x03eb, 0xc8b4)) + { + uint8_t ser[100]; + char szSer[100]; + uint32_t len; + + if (WinUsb_GetDescriptor(hWinUsb, USB_STRING_DESCRIPTOR_TYPE, 3, 3, ser, 100, (PULONG)&len)) + { + if (len > 64) + { + KT_WinUSB_Close(); + return -1; + } + if (len != ser[0]) + { + KT_WinUSB_Close(); + return -1; + } + uint32_t i; + for (i = 0; i < (len / 2 - 1); ++i) + { + szSer[i] = ser[2 + i * 2]; + } + szSer[i] = 0; + if (strcmpi(szSer, szSerialVer)) + { + pmsg_error("Wrong firmware version\n"); + KT_WinUSB_Close(); + return -1; + } + u8Buff[0] = 0x00; + if (!KT_WinUSB_Write(0x01, u8Buff, 64)) + { + pmsg_error("USB IO: FAILED\n"); + return -1; + } + if (!KT_WinUSB_Read(0x81, u8Buff, 64)) { + pmsg_error("USB IO: FAILED\n"); + return -1; + } + if (strcmpi((char *)u8Buff, szFirmwareVer)) + { + pmsg_error("Wrong firmware version\n"); + KT_WinUSB_Close(); + return -1; + } + + return 0; + } + else + { + KT_WinUSB_Close(); + return -1; + } + + return -1; + } + + return -1; +} + +static void usbisp3_close(PROGRAMMER* pgm) +{ + + KT_WinUSB_Close(); +} + +static int usbisp3_cmd(const PROGRAMMER* pgm, const unsigned char* cmd, + unsigned char* res) +{ + + return pgm->spi(pgm, cmd, res, 4); +} + +static uint32_t usbisp3_spi_exch_n(const PROGRAMMER* pgm, uint32_t u32Length, uint8_t* pu8Send, uint8_t* pu8Recv) +{ + uint8_t u8Buff[64]; + + u8Buff[0] = 0x03; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (0); + u8Buff[4] = (0); + + if (!KT_WinUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + if (!KT_WinUSB_Write(0x01, pu8Send, u32Length)) { + return 0; + } + + u8Buff[0] = 0x25; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (0); + u8Buff[4] = (0); + + if (!KT_WinUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + u8Buff[0] = 0x04; + u8Buff[1] = (u32Length); + u8Buff[2] = (u32Length >> 8); + u8Buff[3] = (u32Length >> 16); + u8Buff[4] = (u32Length >> 24); + + if (!KT_WinUSB_Write(0x01, u8Buff, 64)) { + return 0; + } + + return KT_WinUSB_Read(0x81, pu8Recv, u32Length); +} + +static uint32_t usbisp3_avr_read_flash(const PROGRAMMER* pgm, uint16_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[8 * 1024]; + u16Length >>= 1; + u16Address >>= 1; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + + for (i = 0; i < u16Length; ++i) { + *p = 0x20; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + *p = 0x28; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + ++u16Address; + } + + if (usbisp3_spi_exch_n(pgm, u16Length * 8, u8SendBuff, u8SendBuff)) { + p = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = u8SendBuff[i * 8 + 3]; + ++p; + *p = u8SendBuff[i * 8 + 7]; + ++p; + } + return 1; + } + else { + return 0; + } +} + +static uint32_t usbisp3_avr_read_eeprom(const PROGRAMMER* pgm, uint16_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[8 * 1024]; + + uint32_t i; + uint8_t* p; + p = u8SendBuff; + + for (i = 0; i < u16Length; ++i) { + *p = 0xA0; + ++p; + *p = (u16Address >> 8); + ++p; + *p = (u16Address); + ++p; + *p = 0x00; + ++p; + + ++u16Address; + } + + if (usbisp3_spi_exch_n(pgm, u16Length * 4, u8SendBuff, u8SendBuff)) { + p = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = u8SendBuff[i * 4 + 3]; + ++p; + } + return 1; + } + else { + return 0; + } +} + +static uint32_t usbisp3_avr_write_flash(const PROGRAMMER* pgm, uint32_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[1024]; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + uint8_t* pS; + pS = pu8Data; + uint16_t u16TmpAddress; + uint16_t u16Pos = 0; + uint8_t u8Poll; + + if (u16Length < 16) { + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < (u16Length / 2); ++i) { + *p = 0x40; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + *p = 0x48; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + ++u16TmpAddress; + } + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, u16Length * 4)) { + return 0; + } + + u8SendBuff[0] = 0x4c; + u8SendBuff[1] = (u16Address >> 9); + u8SendBuff[2] = (u16Address >> 1); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + if (u16Pos % 2) { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x28; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x20; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + } + else { + Sleep(10); + return 1; + } + } + else { + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < (u16Length / 2); ++i) { + *p = 0x40; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + *p = 0x48; + ++p; + *p = (u16TmpAddress >> 8); + ++p; + *p = (u16TmpAddress); + ++p; + *p = *pS; + ++pS; + ++p; + + ++u16TmpAddress; + } + if (!usbisp3_spi_exch_n(pgm, u16Length * 4, u8SendBuff, u8SendBuff)) { + return 0; + } + + u8SendBuff[0] = 0x4c; + u8SendBuff[1] = (u16Address >> 9); + u8SendBuff[2] = (u16Address >> 1); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + + if (u16Pos % 2) { + + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x28; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + u16TmpAddress = u16Address + u16Pos; + u16TmpAddress >>= 1; + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0x20; + u8SendBuff[1] = (u16TmpAddress >> 8); + u8SendBuff[2] = (u16TmpAddress); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + } + else { + Sleep(10); + return 1; + } + } + + return 0; +} + +static uint32_t usbisp3_avr_write_eeprom(const PROGRAMMER* pgm, uint32_t u16Address, uint16_t u16Length, uint8_t* pu8Data) +{ + uint8_t u8SendBuff[1024]; + uint32_t i; + uint8_t* p; + p = u8SendBuff; + uint8_t* pS; + pS = pu8Data; + uint16_t u16TmpAddress; + uint16_t u16Pos = 0; + uint8_t u8Poll; + + if (u16Length != 0x01) { + + u16TmpAddress = 0; + p = u8SendBuff; + pS = pu8Data; + for (i = 0; i < u16Length; ++i) { + *p = 0xC1; + ++p; + *p = (i >> 8); + ++p; + *p = (i); + ++p; + *p = *pS; + ++pS; + ++p; + } + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, u16Length * 4)) { + return 0; + } + for (i = 0; i < u16Length; ++i) { + if (pu8Data[i] != 0xff) { + u16Pos = i; + break; + } + } + if (u16Pos != u16Length) { + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0xA0; + u8SendBuff[1] = ((u16Address + u16Pos) >> 8); + u8SendBuff[2] = (u16Address + u16Pos); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[u16Pos]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + else { + Sleep(10); + return 1; + } + } + else { + u8SendBuff[0] = 0xC0; + u8SendBuff[1] = (u16Address >> 8); + u8SendBuff[2] = (u16Address); + u8SendBuff[3] = pu8Data[0]; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + u8Poll = 0; + for (i = 0; i < 1000; ++i) { + u8SendBuff[0] = 0xA0; + u8SendBuff[1] = (u16Address >> 8); + u8SendBuff[2] = (u16Address); + u8SendBuff[3] = 0x00; + if (!usbisp3_spi_exch(pgm, u8SendBuff, u8SendBuff, 4)) { + return 0; + } + if (u8SendBuff[3] == pu8Data[0]) { + u8Poll = 1; + break; + } + } + if (u8Poll) { + return 1; + } + else { + return 0; + } + } + + return 0; +} + +static int usbisp3_paged_write(const PROGRAMMER* pgm, const AVRPART* p, const AVRMEM* mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) +{ + if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)) + { + return -1; + } + + if (strcmp(mem->desc, "flash") == 0) + { + OPCODE* readop = 0, * lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + uint8_t data = 0, cmd[64], res[64]; + + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr / 2); + pgm->cmd(pgm, cmd, res); + } + + if (usbisp3_avr_write_flash(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + } + + if (usbisp3_avr_write_eeprom(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + + return -1; +} + +static int usbisp3_paged_load(const PROGRAMMER* pgm, const AVRPART* p, const AVRMEM* mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) +{ + + // only supporting flash & eeprom page reads + if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)) + { + return -1; + } + + if (strcmp(mem->desc, "flash") == 0) + { + OPCODE* readop = 0, * lext = mem->op[AVR_OP_LOAD_EXT_ADDR]; + uint8_t data = 0, cmd[64], res[64]; + + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr / 2); + pgm->cmd(pgm, cmd, res); + } + + if (usbisp3_avr_read_flash(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + } + + if (usbisp3_avr_read_eeprom(pgm, addr, n_bytes, &mem->buf[addr])) + { + return 0; + } + else + { + return -1; + } + + return -1; +} + +static int usbisp3_parseextparams(const PROGRAMMER* pgm, const LISTID extparms) +{ + + return 0; +} + +void usbisp3_initpgm(PROGRAMMER* pgm) +{ + pgm->initialize = usbisp3_initialize; + pgm->display = usbisp3_display; + pgm->enable = usbisp3_enable; + pgm->disable = usbisp3_disable; + pgm->powerdown = usbisp3_powerdown; + pgm->program_enable = usbisp3_program_enable; + pgm->chip_erase = usbisp3_chip_erase; + pgm->open = usbisp3_open; + pgm->close = usbisp3_close; + pgm->spi = usbisp3_spi_exch; + + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + pgm->cmd = usbisp3_cmd; + pgm->paged_write = usbisp3_paged_write; + pgm->paged_load = usbisp3_paged_load; + + pgm->parseextparams = usbisp3_parseextparams; + + strncpy(pgm->type, "usbisp3", sizeof(pgm->type)); +} + +uint32_t KT_WinUSB_OpenVidPid(uint32_t vid, uint32_t pid) +{ + connected = 0; + HANDLE hDevInfoSet; + + GUID hidGuid = { 0xdee824ef, 0x729b, 0x4a0e, 0x9c, 0x14, 0xb7, 0x11, 0x7d, 0x33, 0xa8, 0x17 }; + + hDevInfoSet = SetupDiGetClassDevsA(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (!hDevInfoSet) { + return 0; + } + DWORD dwRes; + DWORD dwStatus; + DWORD dwInterfaceIndex = 0; + SP_DEVICE_INTERFACE_DATA devInterfaceData; + SP_DEVICE_INTERFACE_DETAIL_DATA detail; + devInterfaceData.cbSize = sizeof(devInterfaceData); + char* pBuff; + SP_DEVINFO_DATA devInfoData; + DWORD dwRegType, dwRegSize; + DWORD dwFound = 0; + while (1) { + dwRes = SetupDiEnumDeviceInterfaces(hDevInfoSet, NULL, &hidGuid, dwInterfaceIndex, &devInterfaceData); + if (dwRes) { + dwStatus = GetLastError(); + } + else { + return 0; + } + + if (dwStatus == ERROR_NO_MORE_ITEMS) { + return 0; + } + + devInfoData.cbSize = sizeof(devInfoData); + SetupDiEnumDeviceInfo(hDevInfoSet, dwInterfaceIndex, &devInfoData); + + SetupDiGetDeviceRegistryPropertyA(hDevInfoSet, &devInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize); + + pBuff = (char*)malloc(dwRegSize); + if (!pBuff) { + return 0; + } + + SetupDiGetDeviceRegistryPropertyA(hDevInfoSet, &devInfoData, SPDRP_HARDWAREID, &dwRegType, (unsigned char*)pBuff, dwRegSize, NULL); + + char szVid[100]; + char szPid[100]; + char* p; + wsprintfA(szPid, "pid_%04x", pid); + wsprintfA(szVid, "vid_%04x&", vid); + lstrcatA(szVid, szPid); + DWORD dwLen, dwJ; + dwLen = lstrlenA(pBuff); + for (dwJ = 0; dwJ < dwLen; ++dwJ) { + if (pBuff[dwJ] >= 'A' && pBuff[dwJ] <= 'Z') + pBuff[dwJ] += 0x20; + } + p = strstr(pBuff, szVid); + if (p) { + dwFound = 1; + break; + } + ++dwInterfaceIndex; + } + + if (dwFound) { + } + else { + return 0; + } + + memset(&detail, 0, sizeof(detail)); + detail.cbSize = sizeof(detail); + DWORD dwSize = 0; + SetupDiGetDeviceInterfaceDetail(hDevInfoSet, &devInterfaceData, NULL, 0, &dwSize, NULL); + PSP_DEVICE_INTERFACE_DETAIL_DATA ktNew; + ktNew = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(dwSize); + if (!ktNew) { + return 0; + } + ktNew->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + SetupDiGetDeviceInterfaceDetail(hDevInfoSet, &devInterfaceData, ktNew, dwSize, NULL, NULL); + + hUsb = CreateFile(ktNew->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (!hUsb) { + return 0; + } + if (!WinUsb_Initialize(hUsb, &hWinUsb)) { + return 0; + } + + connected = 1; + return 1; +} + +void KT_WinUSB_Close(void) +{ + + if (connected) + { + connected = 0; + CloseHandle(hUsb); + WinUsb_Free(hWinUsb); + } +} + +uint32_t KT_WinUSB_Read(uint8_t ep, uint8_t* p_data, uint32_t length) +{ + DWORD len; + + ov.hEvent = CreateEventA(NULL, TRUE, FALSE, "KT_WinUsb"); + if (ov.hEvent == NULL) + { + return 0; + } + DWORD dwTimeOut = 5000; + + WinUsb_SetPipePolicy(hWinUsb, 0x81, PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &dwTimeOut); + + WinUsb_ReadPipe(hWinUsb, ep | 0x80, buff, length, &len, &ov); + DWORD dwTrans; + + WinUsb_GetOverlappedResult(hWinUsb, &ov, &dwTrans, TRUE); + if (dwTrans != length) { + CloseHandle(ov.hEvent); + return 0; + } + + memmove(p_data, buff, length); + CloseHandle(ov.hEvent); + return 1; +} + +uint32_t KT_WinUSB_Write(uint8_t ep, uint8_t* p_data, uint32_t length) +{ + DWORD len; + + memmove(buff, p_data, length); + + return WinUsb_WritePipe(hWinUsb, ep, buff, length, &len, NULL); +} diff --git a/src/usbisp3.h b/src/usbisp3.h new file mode 100644 index 00000000..1d54d750 --- /dev/null +++ b/src/usbisp3.h @@ -0,0 +1,15 @@ +#ifndef USBISP3_H_ +#define USBISP3_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + extern const char usbisp3_desc[]; + void usbisp3_initpgm(PROGRAMMER* pgm); + +#ifdef __cplusplus +} +#endif + +#endif