Add support USB ISP 3.0, ISP v2 Renew, MCU Pro
This commit is contained in:
parent
73383e7169
commit
21f04520c3
|
@ -168,6 +168,8 @@ add_library(libavrdude
|
||||||
freebsd_ppi.h
|
freebsd_ppi.h
|
||||||
ft245r.c
|
ft245r.c
|
||||||
ft245r.h
|
ft245r.h
|
||||||
|
ispv2renew.h
|
||||||
|
ispv2renew.c
|
||||||
jtagmkI.c
|
jtagmkI.c
|
||||||
jtagmkI.h
|
jtagmkI.h
|
||||||
jtagmkI_private.h
|
jtagmkI_private.h
|
||||||
|
@ -184,6 +186,8 @@ add_library(libavrdude
|
||||||
linuxspi.h
|
linuxspi.h
|
||||||
linux_ppdev.h
|
linux_ppdev.h
|
||||||
lists.c
|
lists.c
|
||||||
|
mcupro.h
|
||||||
|
mcupro.c
|
||||||
micronucleus.c
|
micronucleus.c
|
||||||
micronucleus.h
|
micronucleus.h
|
||||||
par.c
|
par.c
|
||||||
|
@ -231,6 +235,8 @@ add_library(libavrdude
|
||||||
urclock_private.h
|
urclock_private.h
|
||||||
usbasp.c
|
usbasp.c
|
||||||
usbasp.h
|
usbasp.h
|
||||||
|
usbisp3.h
|
||||||
|
usbisp3.c
|
||||||
usbdevs.h
|
usbdevs.h
|
||||||
usb_hidapi.c
|
usb_hidapi.c
|
||||||
usb_libusb.c
|
usb_libusb.c
|
||||||
|
|
|
@ -2482,6 +2482,42 @@ programmer
|
||||||
connection_type = usb;
|
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
|
# flip1
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,851 @@
|
||||||
|
#include "ac_cfg.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <Setupapi.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "avrdude.h"
|
||||||
|
#include "libavrdude.h"
|
||||||
|
|
||||||
|
#include "ispv2renew.h"
|
||||||
|
|
||||||
|
#include <lusb0_usb.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,851 @@
|
||||||
|
#include "ac_cfg.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <Setupapi.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "avrdude.h"
|
||||||
|
#include "libavrdude.h"
|
||||||
|
|
||||||
|
#include "mcupro.h"
|
||||||
|
|
||||||
|
#include <lusb0_usb.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -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
|
|
@ -36,11 +36,13 @@
|
||||||
#include "flip1.h"
|
#include "flip1.h"
|
||||||
#include "flip2.h"
|
#include "flip2.h"
|
||||||
#include "ft245r.h"
|
#include "ft245r.h"
|
||||||
|
#include "ispv2renew.h"
|
||||||
#include "jtagmkI.h"
|
#include "jtagmkI.h"
|
||||||
#include "jtagmkII.h"
|
#include "jtagmkII.h"
|
||||||
#include "jtag3.h"
|
#include "jtag3.h"
|
||||||
#include "linuxgpio.h"
|
#include "linuxgpio.h"
|
||||||
#include "linuxspi.h"
|
#include "linuxspi.h"
|
||||||
|
#include "mcupro.h"
|
||||||
#include "micronucleus.h"
|
#include "micronucleus.h"
|
||||||
#include "par.h"
|
#include "par.h"
|
||||||
#include "pickit2.h"
|
#include "pickit2.h"
|
||||||
|
@ -53,6 +55,7 @@
|
||||||
#include "teensy.h"
|
#include "teensy.h"
|
||||||
#include "urclock.h"
|
#include "urclock.h"
|
||||||
#include "usbasp.h"
|
#include "usbasp.h"
|
||||||
|
#include "usbisp3.h"
|
||||||
#include "usbtiny.h"
|
#include "usbtiny.h"
|
||||||
#include "wiring.h"
|
#include "wiring.h"
|
||||||
#include "xbee.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"
|
{"flip1", flip1_initpgm, flip1_desc}, // "flip1"
|
||||||
{"flip2", flip2_initpgm, flip2_desc}, // "flip2"
|
{"flip2", flip2_initpgm, flip2_desc}, // "flip2"
|
||||||
{"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, // "ftdi_syncbb"
|
{"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, // "ftdi_syncbb"
|
||||||
|
{"ispv2renew", ispv2renew_initpgm, ispv2renew_desc}, // "ispv2renew"
|
||||||
{"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, // "JTAGMKI"
|
{"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, // "JTAGMKI"
|
||||||
{"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, // "JTAGMKII"
|
{"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, // "JTAGMKII"
|
||||||
{"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, // "JTAGMKII_AVR32"
|
{"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"
|
{"jtagice3_tpi", jtag3_tpi_initpgm, jtag3_tpi_desc}, // "JTAGICE3_TPI"
|
||||||
{"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio"
|
{"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio"
|
||||||
{"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI
|
{"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI
|
||||||
|
{"mcupro", mcupro_initpgm, mcupro_desc}, // "mcupro"
|
||||||
{"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0"
|
{"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0"
|
||||||
{"par", par_initpgm, par_desc}, // "PPI"
|
{"par", par_initpgm, par_desc}, // "PPI"
|
||||||
{"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2"
|
{"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"
|
{"teensy", teensy_initpgm, teensy_desc}, // "teensy"
|
||||||
{"urclock", urclock_initpgm, urclock_desc}, // "Urclock"
|
{"urclock", urclock_initpgm, urclock_desc}, // "Urclock"
|
||||||
{"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp"
|
{"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp"
|
||||||
|
{"usbisp3", usbisp3_initpgm, usbisp3_desc}, // "usbisp3"
|
||||||
{"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny"
|
{"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny"
|
||||||
{"wiring", wiring_initpgm, wiring_desc}, // "Wiring"
|
{"wiring", wiring_initpgm, wiring_desc}, // "Wiring"
|
||||||
{"xbee", xbee_initpgm, xbee_desc}, // "XBee"
|
{"xbee", xbee_initpgm, xbee_desc}, // "XBee"
|
||||||
|
|
|
@ -0,0 +1,959 @@
|
||||||
|
#include "ac_cfg.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <Setupapi.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
|
@ -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
|
Loading…
Reference in New Issue