This commit is contained in:
bubnikv 2019-03-01 15:36:01 +01:00
commit 570bc63e58
34 changed files with 2205 additions and 15279 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-D_BSD_SOURCE -D_DEFAULT_SOURCE) # To enable various useful macros and functions on Unices
remove_definitions(-D_UNICODE -DUNICODE)
@ -68,18 +70,31 @@ set(AVRDUDE_SOURCES
)
if (MSVC)
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
windows/utf8.c
windows/unistd.cpp
windows/getopt.c
)
endif()
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
set(STANDALONE_SOURCES
main-standalone.c
add_executable(avrdude-conf-gen conf-generate.cpp)
# Config file embedding
add_custom_command(
DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf > avrdude-slic3r.conf.h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_executable(avrdude-slic3r ${STANDALONE_SOURCES})
add_custom_target(gen_conf_h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
)
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
add_dependencies(avrdude gen_conf_h)
add_executable(avrdude-slic3r main-standalone.cpp)
target_link_libraries(avrdude-slic3r avrdude)
set_target_properties(avrdude-slic3r PROPERTIES EXCLUDE_FROM_ALL TRUE)
if (WIN32)
target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)

View File

@ -158,8 +158,10 @@ static int arduino_open(PROGRAMMER * pgm, char * port)
return -1;
}
if (stk500_getsync(pgm) < 0)
if (stk500_getsync(pgm) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}

View File

@ -0,0 +1,424 @@
#
# This is a basic minimal config file embedded into the avrdude-slic3r binary
# so that it can work in a standalone manner.
#
# Only the bits useful for Prusa3D devices were copied over from avrdude.conf
# If needed, more configuration can still be loaded into avrdude-slic3r
# via the -C command-line option.
#
programmer
id = "wiring";
desc = "Wiring";
type = "wiring";
connection_type = serial;
;
programmer
id = "arduino";
desc = "Arduino";
type = "arduino";
connection_type = serial;
;
programmer
id = "avr109";
desc = "Atmel AppNote AVR109 Boot Loader";
type = "butterfly";
connection_type = serial;
;
#------------------------------------------------------------
# ATmega2560
#------------------------------------------------------------
part
id = "m2560";
desc = "ATmega2560";
signature = 0x1e 0x98 0x01;
has_jtag = yes;
stk500_devcode = 0xB2;
# avr910_devcode = 0x43;
chip_erase_delay = 9000;
pagel = 0xD7;
bs2 = 0xA0;
reset = dedicated;
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
"x x x x x x x x x x x x x x x x";
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
"x x x x x x x x x x x x x x x x";
timeout = 200;
stabdelay = 100;
cmdexedelay = 25;
synchloops = 32;
bytedelay = 0;
pollindex = 3;
pollvalue = 0x53;
predelay = 1;
postdelay = 1;
pollmethod = 1;
pp_controlstack =
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02;
hventerstabdelay = 100;
progmodedelay = 0;
latchcycles = 5;
togglevtg = 1;
poweroffdelay = 15;
resetdelayms = 1;
resetdelayus = 0;
hvleavestabdelay = 15;
chiperasepulsewidth = 0;
chiperasepolltimeout = 10;
programfusepulsewidth = 0;
programfusepolltimeout = 5;
programlockpulsewidth = 0;
programlockpolltimeout = 5;
idr = 0x31;
spmcr = 0x57;
rampz = 0x3b;
allowfullpagebitstream = no;
ocdrev = 4;
memory "eeprom"
paged = no; /* leave this "no" */
page_size = 8; /* for parallel programming */
size = 4096;
min_write_delay = 9000;
max_write_delay = 9000;
readback_p1 = 0x00;
readback_p2 = 0x00;
read = " 1 0 1 0 0 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
write = " 1 1 0 0 0 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 a2 a1 a0",
" i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 0 0 0",
" x x x x x x x x";
mode = 0x41;
delay = 10;
blocksize = 8;
readsize = 256;
;
memory "flash"
paged = yes;
size = 262144;
page_size = 256;
num_pages = 1024;
min_write_delay = 4500;
max_write_delay = 4500;
readback_p1 = 0x00;
readback_p2 = 0x00;
read_lo = " 0 0 1 0 0 0 0 0",
"a15 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0",
"a15 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
loadpage_lo = " 0 1 0 0 0 0 0 0",
" x x x x x x x x",
" x a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_hi = " 0 1 0 0 1 0 0 0",
" x x x x x x x x",
" x a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0",
"a15 a14 a13 a12 a11 a10 a9 a8",
" a7 x x x x x x x",
" x x x x x x x x";
load_ext_addr = " 0 1 0 0 1 1 0 1",
" 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 0 0 a16",
" 0 0 0 0 0 0 0 0";
mode = 0x41;
delay = 10;
blocksize = 256;
readsize = 256;
;
memory "lfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
"x x x x x x x x i i i i i i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "hfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
"x x x x x x x x i i i i i i i i";
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "efuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
"x x x x x x x x x x x x x i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "lock"
size = 1;
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x x x o o o o o o";
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
"x x x x x x x x 1 1 i i i i i i";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "calibration"
size = 1;
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
"0 0 0 0 0 0 0 0 o o o o o o o o";
;
memory "signature"
size = 3;
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o";
;
;
#------------------------------------------------------------
# ATmega32u4
#------------------------------------------------------------
part
id = "m32u4";
desc = "ATmega32U4";
signature = 0x1e 0x95 0x87;
usbpid = 0x2ff4;
has_jtag = yes;
# stk500_devcode = 0xB2;
# avr910_devcode = 0x43;
chip_erase_delay = 9000;
pagel = 0xD7;
bs2 = 0xA0;
reset = dedicated;
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
"x x x x x x x x x x x x x x x x";
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
"x x x x x x x x x x x x x x x x";
timeout = 200;
stabdelay = 100;
cmdexedelay = 25;
synchloops = 32;
bytedelay = 0;
pollindex = 3;
pollvalue = 0x53;
predelay = 1;
postdelay = 1;
pollmethod = 1;
pp_controlstack =
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
hventerstabdelay = 100;
progmodedelay = 0;
latchcycles = 5;
togglevtg = 1;
poweroffdelay = 15;
resetdelayms = 1;
resetdelayus = 0;
hvleavestabdelay = 15;
chiperasepulsewidth = 0;
chiperasepolltimeout = 10;
programfusepulsewidth = 0;
programfusepolltimeout = 5;
programlockpulsewidth = 0;
programlockpolltimeout = 5;
idr = 0x31;
spmcr = 0x57;
rampz = 0x3b;
allowfullpagebitstream = no;
ocdrev = 3;
memory "eeprom"
paged = no; /* leave this "no" */
page_size = 4; /* for parallel programming */
size = 1024;
min_write_delay = 9000;
max_write_delay = 9000;
readback_p1 = 0x00;
readback_p2 = 0x00;
read = " 1 0 1 0 0 0 0 0",
" x x x x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
write = " 1 1 0 0 0 0 0 0",
" x x x x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 a2 a1 a0",
" i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x a10 a9 a8",
" a7 a6 a5 a4 a3 0 0 0",
" x x x x x x x x";
mode = 0x41;
delay = 20;
blocksize = 4;
readsize = 256;
;
memory "flash"
paged = yes;
size = 32768;
page_size = 128;
num_pages = 256;
min_write_delay = 4500;
max_write_delay = 4500;
readback_p1 = 0x00;
readback_p2 = 0x00;
read_lo = " 0 0 1 0 0 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
loadpage_lo = " 0 1 0 0 0 0 0 0",
" x x x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_hi = " 0 1 0 0 1 0 0 0",
" x x x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0",
" a15 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 x x x x x x",
" x x x x x x x x";
mode = 0x41;
delay = 6;
blocksize = 128;
readsize = 256;
;
memory "lfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
"x x x x x x x x i i i i i i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "hfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
"x x x x x x x x i i i i i i i i";
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "efuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
"x x x x x x x x x x x x i i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "lock"
size = 1;
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x x x o o o o o o";
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
"x x x x x x x x 1 1 i i i i i i";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "calibration"
size = 1;
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
"0 0 0 0 0 0 0 0 o o o o o o o o";
;
memory "signature"
size = 3;
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o";
;
;

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,6 @@ static void avrdude_oom_handler(const char *context, void *user_p)
struct AvrDude::priv
{
std::string sys_config;
std::deque<std::vector<std::string>> args;
bool cancelled = false;
int exit_code = 0;
@ -54,8 +53,6 @@ struct AvrDude::priv
std::thread avrdude_thread;
priv(std::string &&sys_config) : sys_config(sys_config) {}
void set_handlers();
void unset_handlers();
int run_one(const std::vector<std::string> &args);
@ -110,7 +107,7 @@ int AvrDude::priv::run_one(const std::vector<std::string> &args) {
message_fn(command_line.c_str(), command_line.size());
const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data(), sys_config.c_str());
const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data());
return res;
}
@ -130,7 +127,7 @@ int AvrDude::priv::run() {
// Public
AvrDude::AvrDude(std::string sys_config) : p(new priv(std::move(sys_config))) {}
AvrDude::AvrDude() : p(new priv()) {}
AvrDude::AvrDude(AvrDude &&other) : p(std::move(other.p)) {}

View File

@ -22,8 +22,7 @@ public:
typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
typedef std::function<void()> CompleteFn;
// Main c-tor, sys_config is the location of avrdude's main configuration file
AvrDude(std::string sys_config);
AvrDude();
AvrDude(AvrDude &&);
AvrDude(const AvrDude &) = delete;
AvrDude &operator=(AvrDude &&) = delete;

View File

@ -55,7 +55,7 @@ void avrdude_cancel();
#define MSG_TRACE (4) /* displayed with -vvvv, show trace commuication */
#define MSG_TRACE2 (5) /* displayed with -vvvvv */
int avrdude_main(int argc, char * argv [], const char *sys_config);
int avrdude_main(int argc, char * argv []);
#if defined(WIN32NATIVE)

View File

@ -0,0 +1,41 @@
#include <iostream>
#include <fstream>
#include <ios>
#include <iomanip>
int main(int argc, char const *argv[])
{
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " <file> <symbol name>" << std::endl;
return -1;
}
const char* filename = argv[1];
const char* symbol = argv[2];
size_t size = 0;
std::fstream file(filename);
if (!file.good()) {
std::cerr << "Cannot read file: " << filename << std::endl;
}
std::cout << "/* WARN: This file is auto-generated from `" << filename << "` */" << std::endl;
std::cout << "unsigned char " << symbol << "[] = {";
char c;
std::cout << std::hex;
std::cout.fill('0');
for (file.get(c); !file.eof(); size++, file.get(c)) {
if (size % 12 == 0) { std::cout << "\n "; }
std::cout << "0x" << std::setw(2) << (unsigned)c << ", ";
}
std::cout << "\n 0, 0\n};\n";
std::cout << std::dec;
std::cout << "size_t " << symbol << "_size = " << size << ";" << std::endl;
std::cout << "size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl;
return 0;
}

View File

@ -32,6 +32,8 @@
#include "config_gram.h"
#include "avrdude-slic3r.conf.h" // Embedded config file
char default_programmer[MAX_STR_CONST];
char default_parallel[PATH_MAX];
char default_serial[PATH_MAX];
@ -325,7 +327,7 @@ int read_config(const char * file)
FILE * f;
int r;
f = fopen(file, "r");
f = fopen_utf8(file, "r");
if (f == NULL) {
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
progname, file, strerror(errno));
@ -347,3 +349,33 @@ int read_config(const char * file)
return r;
}
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern YY_BUFFER_STATE yy_scan_bytes(char *base, size_t size);
extern void yy_delete_buffer(YY_BUFFER_STATE b);
int read_config_builtin()
{
int r;
lineno = 1;
infile = "(builtin)";
// Note: Can't use yy_scan_buffer, it's buggy (?), leads to fread from a null FILE*
// and so unfortunatelly we have to use the copying variant here
YY_BUFFER_STATE buffer = yy_scan_bytes(avrdude_slic3r_conf, avrdude_slic3r_conf_size);
if (buffer == NULL) {
avrdude_message(MSG_INFO, "%s: read_config_builtin: Failed to initialize parsing buffer\n", progname);
return -1;
}
r = yyparse();
yy_delete_buffer(buffer);
#ifdef HAVE_YYLEX_DESTROY
/* reset lexer and free any allocated memory */
yylex_destroy();
#endif
return r;
}

View File

@ -40,6 +40,9 @@
#include "avrdude.h"
#include "libavrdude.h"
#if defined(WIN32NATIVE)
#include "windows/utf8.h"
#endif
#define IHEX_MAXDATA 256
@ -102,21 +105,25 @@ static int fmt_autodetect(char * fname, unsigned section);
static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
FILE *fopen_utf8(const char *filename, const char *mode)
{
FILE *file;
// On Windows we need to convert the filename to UTF-16
#if defined(WIN32NATIVE)
static wchar_t fname_buffer[PATH_MAX];
static wchar_t mode_buffer[MAX_MODE_LEN];
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; }
if (MultiByteToWideChar(CP_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
if (MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
file = _wfopen(fname_buffer, mode_buffer);
return _wfopen(fname_buffer, mode_buffer);
#else
file = fopen(filename, mode);
return fopen(filename, mode);
#endif
}
static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
{
FILE *file = fopen_utf8(filename, mode);
if (file == NULL) {
return NULL;

View File

@ -1527,8 +1527,10 @@ static int jtagmkII_open(PROGRAMMER * pgm, char * port)
*/
jtagmkII_drain(pgm, 0);
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0)
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}
@ -1579,8 +1581,10 @@ static int jtagmkII_open_dw(PROGRAMMER * pgm, char * port)
*/
jtagmkII_drain(pgm, 0);
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0)
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}
@ -1631,8 +1635,10 @@ static int jtagmkII_open_pdi(PROGRAMMER * pgm, char * port)
*/
jtagmkII_drain(pgm, 0);
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0)
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}
@ -1684,8 +1690,10 @@ static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port)
*/
jtagmkII_drain(pgm, 0);
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0)
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}
@ -1737,8 +1745,10 @@ static int jtagmkII_dragon_open_dw(PROGRAMMER * pgm, char * port)
*/
jtagmkII_drain(pgm, 0);
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0)
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}
@ -1790,8 +1800,10 @@ static int jtagmkII_dragon_open_pdi(PROGRAMMER * pgm, char * port)
*/
jtagmkII_drain(pgm, 0);
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0)
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}
@ -3370,6 +3382,8 @@ static int jtagmkII_open32(PROGRAMMER * pgm, char * port)
status = jtagmkII_getsync(pgm, -1);
if(status < 0) return -1;
// FIXME: Error handling is bad here: memory leak in resp (?) and port not closed
// AVR32 "special"
buf[0] = CMND_SET_PARAMETER;
buf[1] = 0x2D;

View File

@ -820,6 +820,8 @@ extern "C" {
char * fmtstr(FILEFMT format);
FILE *fopen_utf8(const char *filename, const char *mode);
int fileio(int op, char * filename, FILEFMT format,
struct avrpart * p, char * memtype, int size, unsigned section);
@ -939,6 +941,7 @@ int init_config(void);
void cleanup_config(void);
int read_config(const char * file);
int read_config_builtin();
#ifdef __cplusplus
}

View File

@ -1,9 +0,0 @@
#include "avrdude.h"
static const char* SYS_CONFIG = "/etc/avrdude-slic3r.conf";
int main(int argc, char *argv[])
{
return avrdude_main(argc, argv, SYS_CONFIG);
}

View File

@ -0,0 +1,54 @@
extern "C" {
#include "avrdude.h"
}
#ifdef WIN32
#include <stdlib.h>
#include <vector>
extern "C" {
#include "windows/utf8.h"
}
struct ArgvUtf8 : std::vector<char*>
{
int argc;
ArgvUtf8(int argc_w, wchar_t *argv_w[]) : std::vector<char*>(argc_w + 1, nullptr), argc(0)
{
for (int i = 0; i < argc_w; i++) {
char *arg_utf8 = ::wstr_to_utf8(argv_w[i], -1);
if (arg_utf8 != nullptr) {
operator[](i) = arg_utf8;
argc = i + 1;
} else {
break;
}
}
}
~ArgvUtf8()
{
for (char *arg : *this) {
if (arg != nullptr) {
::free(arg);
}
}
}
};
int wmain(int argc_w, wchar_t *argv_w[])
{
ArgvUtf8 argv_utf8(argc_w, argv_w);
return ::avrdude_main(argv_utf8.argc, &argv_utf8[0]);
}
#else
int main(int argc, char *argv[])
{
return ::avrdude_main(argc, argv);
}
#endif

View File

@ -426,7 +426,7 @@ static int cleanup_main(int status)
/*
* main routine
*/
int avrdude_main(int argc, char * argv [], const char *sys_config)
int avrdude_main(int argc, char * argv [])
{
int rc; /* general return code checking */
int exitrc; /* exit code for main() */
@ -807,13 +807,15 @@ int avrdude_main(int argc, char * argv [], const char *sys_config)
"%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n"
"%sCopyright (c) 2007-2014 Joerg Wunsch\n\n",
progname, version, __DATE__, __TIME__, progbuf, progbuf);
avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
progbuf, sys_config);
// avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
// progbuf, sys_config);
rc = read_config(sys_config);
// rc = read_config(sys_config);
rc = read_config_builtin();
if (rc) {
avrdude_message(MSG_INFO, "%s: error reading system wide configuration file \"%s\"\n",
progname, sys_config);
// avrdude_message(MSG_INFO, "%s: error reading system wide configuration file \"%s\"\n",
// progname, sys_config);
avrdude_message(MSG_INFO, "%s: error reading built-in configuration file\n", progname);
return cleanup_main(1);
}

View File

@ -44,7 +44,7 @@
#include "avrdude.h"
#include "libavrdude.h"
long serial_recv_timeout = 5000; /* ms */
long serial_recv_timeout = 4000; /* ms */
#define MAX_ZERO_READS 512
struct baud_mapping {
@ -150,6 +150,68 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
return 0;
}
// Timeout read & write variants
// Additionally to the regular -1 on I/O error, they return -2 on timeout
ssize_t read_timeout(int fd, void *buf, size_t count, long timeout)
{
struct timeval tm, tm2;
fd_set rfds;
int nfds;
tm.tv_sec = timeout / 1000L;
tm.tv_usec = (timeout % 1000L) * 1000;
while (1) {
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tm2 = tm;
nfds = select(fd + 1, &rfds, NULL, NULL, &tm2);
if (nfds == 0) {
return -2;
} else if (nfds == -1) {
if (errno == EINTR || errno == EAGAIN) {
continue;
} else {
return -1;
}
} else {
return read(fd, buf, count);
}
}
}
ssize_t write_timeout(int fd, const void *buf, size_t count, long timeout)
{
struct timeval tm, tm2;
fd_set wfds;
int nfds;
tm.tv_sec = timeout / 1000L;
tm.tv_usec = (timeout % 1000L) * 1000;
while (1) {
FD_ZERO(&wfds);
FD_SET(fd, &wfds);
tm2 = tm;
nfds = select(fd + 1, NULL, &wfds, NULL, &tm2);
if (nfds == 0) {
return -2;
} else if (nfds == -1) {
if (errno == EINTR || errno == EAGAIN) {
continue;
} else {
return -1;
}
} else {
return write(fd, buf, count);
}
}
}
/*
* Given a port description of the form <host>:<port>, open a TCP
* connection to the specified destination, which is assumed to be a
@ -314,6 +376,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
int rc;
const unsigned char * p = buf;
size_t len = buflen;
unsigned zero_writes = 0;
if (!len)
return 0;
@ -341,14 +404,25 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
while (len) {
RETURN_IF_CANCEL();
rc = write(fd->ifd, p, (len > 1024) ? 1024 : len);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
progname, strerror(errno));
rc = write_timeout(fd->ifd, p, (len > 1024) ? 1024 : len, serial_recv_timeout);
if (rc == -2) {
avrdude_message(MSG_NOTICE2, "%s: ser_send(): programmer is not responding\n", progname);
return -1;
} else if (rc == -1) {
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, strerror(errno));
return -1;
} else if (rc == 0) {
zero_writes++;
if (zero_writes > MAX_ZERO_READS) {
avrdude_message(MSG_NOTICE2, "%s: ser_send(): programmer is not responding (too many zero writes)\n",
progname);
return -1;
}
} else {
zero_writes = 0;
p += rc;
len -= rc;
}
p += rc;
len -= rc;
}
return 0;
@ -357,51 +431,21 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
{
struct timeval timeout, to2;
fd_set rfds;
int nfds;
int rc;
unsigned char * p = buf;
size_t len = 0;
unsigned zero_reads = 0;
timeout.tv_sec = serial_recv_timeout / 1000L;
timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000;
to2 = timeout;
while (len < buflen) {
reselect:
RETURN_IF_CANCEL();
FD_ZERO(&rfds);
FD_SET(fd->ifd, &rfds);
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
// FIXME: The timeout has different behaviour on Linux vs other Unices
// On Linux, the timeout is modified by subtracting the time spent,
// on OS X (for example), it is not modified.
// POSIX recommends re-initializing it before selecting.
if (nfds == 0) {
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
progname);
rc = read_timeout(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, serial_recv_timeout);
if (rc == -2) {
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n", progname);
return -1;
}
else if (nfds == -1) {
if (errno == EINTR || errno == EAGAIN) {
avrdude_message(MSG_INFO, "%s: ser_recv(): programmer is not responding,reselecting\n",
progname);
goto reselect;
}
else {
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n",
progname, strerror(errno));
return -1;
}
}
rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
progname, strerror(errno));
} else if (rc == -1) {
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, strerror(errno));
return -1;
} else if (rc == 0) {
zero_reads++;
@ -445,49 +489,26 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
static int ser_drain(union filedescriptor *fd, int display)
{
struct timeval timeout;
fd_set rfds;
int nfds;
int rc;
unsigned char buf;
unsigned zero_reads = 0;
timeout.tv_sec = 0;
timeout.tv_usec = 250000;
if (display) {
avrdude_message(MSG_INFO, "drain>");
}
while (1) {
FD_ZERO(&rfds);
FD_SET(fd->ifd, &rfds);
reselect:
RETURN_IF_CANCEL();
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
if (nfds == 0) {
rc = read_timeout(fd->ifd, &buf, 1, 250); // Note: timeout needs to be kept low to not timeout in programmers
if (rc == -2) {
if (display) {
avrdude_message(MSG_INFO, "<drain\n");
}
break;
}
else if (nfds == -1) {
if (errno == EINTR) {
goto reselect;
}
else {
avrdude_message(MSG_INFO, "%s: ser_drain(): select(): %s\n",
progname, strerror(errno));
return -1;
}
}
rc = read(fd->ifd, &buf, 1);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
progname, strerror(errno));
break;
} else if (rc == -1) {
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, strerror(errno));
return -1;
} else if (rc == 0) {
zero_reads++;

View File

@ -34,16 +34,63 @@
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h> /* for isprint */
#include <errno.h> /* ENOTTY */
#include "avrdude.h"
#include "libavrdude.h"
#include "windows/utf8.h"
long serial_recv_timeout = 5000; /* ms */
#define W32SERBUFSIZE 1024
// Get last error message string in UTF-8
// Always return a valid null-terminated string
// The returned string should be freed by the caller
char* last_error_string(int wsa)
{
LPWSTR wbuffer = NULL;
(void)wsa;
DWORD wbuffer_len = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
#ifdef HAVE_LIBWS2_32
wsa ? WSAGetLastError() : GetLastError(),
#else
GetLastError(),
#endif
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&wbuffer,
0,
NULL);
if (wbuffer_len == 0) {
return NULL;
}
char *res = wstr_to_utf8(wbuffer, wbuffer_len);
LocalFree(wbuffer);
if (res == NULL) {
// If we get here, conversion to UTF-8 failed
res = strdup("(could not get error message)");
if (res == NULL) {
avrdude_oom("last_error_string(): out of memory\n");
}
}
return res;
}
struct baud_mapping {
long baud;
DWORD speed;
@ -95,6 +142,7 @@ static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
// ctmo.ReadIntervalTimeout = timeout;
// ctmo.ReadTotalTimeoutMultiplier = timeout;
ctmo.ReadTotalTimeoutConstant = timeout;
ctmo.WriteTotalTimeoutConstant = timeout;
return SetCommTimeouts(hComPort, &ctmo);
}
@ -129,7 +177,6 @@ static int
net_open(const char *port, union filedescriptor *fdp)
{
WSADATA wsaData;
LPVOID lpMsgBuf;
char *hstr, *pstr, *end;
unsigned int pnum;
@ -175,18 +222,10 @@ net_open(const char *port, union filedescriptor *fdp)
free(hstr);
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
const char *error = last_error_string(1);
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, error);
free(error);
return -1;
}
@ -196,18 +235,9 @@ net_open(const char *port, union filedescriptor *fdp)
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
const char *error = last_error_string(1);
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname);
free(error);
return -1;
}
@ -221,7 +251,6 @@ net_open(const char *port, union filedescriptor *fdp)
static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
{
LPVOID lpMsgBuf;
HANDLE hComPort=INVALID_HANDLE_VALUE;
char *newname = 0;
@ -261,19 +290,9 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hComPort == INVALID_HANDLE_VALUE) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n",
progname, port, (char*)lpMsgBuf);
LocalFree( lpMsgBuf );
const char *error = last_error_string(0);
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n", progname, port, error);
free(error);
return -1;
}
@ -346,14 +365,13 @@ static int ser_set_dtr_rts(union filedescriptor *fd, int is_on)
#ifdef HAVE_LIBWS2_32
static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
{
LPVOID lpMsgBuf;
int rc;
const unsigned char *p = buf;
size_t len = buflen;
if (fd->ifd < 0) {
avrdude_message(MSG_NOTICE, "%s: net_send(): connection not open\n", progname);
exit(1);
return -1;
}
if (!len) {
@ -382,19 +400,10 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t
while (len) {
rc = send(fd->ifd, p, (len > 1024) ? 1024 : len, 0);
if (rc < 0) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
exit(1);
const char *error = last_error_string(1);
avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, error);
free(error);
return -1;
}
p += rc;
len -= rc;
@ -423,8 +432,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
HANDLE hComPort=(HANDLE)fd->pfd;
if (hComPort == INVALID_HANDLE_VALUE) {
avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n",
progname);
avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n", progname);
return -1;
}
@ -449,18 +457,18 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
}
avrdude_message(MSG_INFO, "\n");
}
serial_w32SetTimeOut(hComPort,500);
if (!WriteFile (hComPort, buf, buflen, &written, NULL)) {
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
progname, "sorry no info avail"); // TODO
if (!WriteFile(hComPort, buf, buflen, &written, NULL)) {
const char *error = last_error_string(0);
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, error);
free(error);
return -1;
}
if (written != buflen) {
avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n",
progname);
avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n", progname);
return -1;
}
@ -471,7 +479,6 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
#ifdef HAVE_LIBWS2_32
static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
{
LPVOID lpMsgBuf;
struct timeval timeout, to2;
fd_set rfds;
int nfds;
@ -481,7 +488,7 @@ static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
if (fd->ifd < 0) {
avrdude_message(MSG_INFO, "%s: net_recv(): connection not open\n", progname);
exit(1);
return -1;
}
timeout.tv_sec = serial_recv_timeout / 1000L;
@ -504,37 +511,19 @@ reselect:
avrdude_message(MSG_NOTICE, "%s: ser_recv(): programmer is not responding, reselecting\n", progname);
goto reselect;
} else {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
exit(1);
const char *error = last_error_string(1);
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, error);
free(error);
return -1;
}
}
rc = recv(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, 0);
if (rc < 0) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
exit(1);
const char *error = last_error_string(1);
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
free(error);
return -1;
}
p += rc;
len += rc;
@ -579,37 +568,24 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
RETURN_IF_CANCEL();
HANDLE hComPort=(HANDLE)fd->pfd;
if (hComPort == INVALID_HANDLE_VALUE) {
avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n",
progname);
avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n", progname);
return -1;
}
serial_w32SetTimeOut(hComPort, serial_recv_timeout);
if (!ReadFile(hComPort, buf, buflen, &read, NULL)) {
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
progname, (char*)lpMsgBuf);
LocalFree( lpMsgBuf );
const char *error = last_error_string(0);
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
free(error);
return -1;
}
/* time out detected */
if (read == 0) {
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
progname);
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n", progname);
return -1;
}
@ -664,20 +640,9 @@ static int ser_drain(union filedescriptor *fd, int display)
readres=ReadFile(hComPort, buf, 1, &read, NULL);
if (!readres) {
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
progname, (char*)lpMsgBuf);
LocalFree( lpMsgBuf );
const char *error = last_error_string(0);
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, error);
free(error);
return -1;
}

View File

@ -669,11 +669,15 @@ static int stk500_open(PROGRAMMER * pgm, char * port)
// MIB510 init
if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0 &&
mib510_isp(pgm, 1) != 0)
mib510_isp(pgm, 1) != 0) {
serial_close(&pgm->fd);
return -1;
}
if (stk500_getsync(pgm) < 0)
if (stk500_getsync(pgm) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}

View File

@ -1695,8 +1695,10 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
stk500v2_drain(pgm, 0);
if (pgm->bitclock != 0.0) {
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) {
serial_close(&pgm->fd);
return -1;
}
}
return 0;
@ -1753,8 +1755,10 @@ static int stk600_open(PROGRAMMER * pgm, char * port)
stk500v2_drain(pgm, 0);
if (pgm->bitclock != 0.0) {
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) {
serial_close(&pgm->fd);
return -1;
}
}
return 0;

View File

@ -0,0 +1,45 @@
#include "utf8.h"
char* wstr_to_utf8(LPWSTR wstr, int len)
{
char *res = NULL;
int res_size = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
if (res_size > 0) {
// Note: WideCharToMultiByte doesn't null-terminate if real (ie. > 0) buffer length is passed
res = malloc(len != - 1 ? res_size + 1 : res_size);
if (res == NULL) { return NULL; }
if (WideCharToMultiByte(CP_UTF8, 0, wstr, len, res, res_size, NULL, NULL) == res_size) {
if (len != -1) { res[res_size] = '\0'; }
} else {
free(res);
return NULL;
}
}
return res;
}
LPWSTR utf8_to_wstr(const char *str, int len)
{
LPWSTR res = NULL;
int res_size = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
if (res_size > 0) {
// Note: MultiByteToWideChar doesn't null-terminate if real (ie. > 0) buffer length is passed
res = malloc(len != - 1 ? res_size + 1 : res_size);
if (res == NULL) { return NULL; }
if (MultiByteToWideChar(CP_UTF8, 0, str, len, res, res_size) == res_size) {
if (len != -1) { res[res_size] = L'\0'; }
} else {
free(res);
return NULL;
}
}
return res;
}

View File

@ -0,0 +1,10 @@
#ifndef SLIC3R_AVRDUDE_UTF8_H
#define SLIC3R_AVRDUDE_UTF8_H
#include <windows.h>
extern char* wstr_to_utf8(LPWSTR wstr, int len);
extern LPWSTR utf8_to_wstr(const char *str, int len);
#endif // SLIC3R_AVRDUDE_UTF8_H

View File

@ -192,8 +192,10 @@ static int wiring_open(PROGRAMMER * pgm, char * port)
/* drain any extraneous input */
stk500v2_drain(pgm, 0);
if (stk500v2_getsync(pgm) < 0)
if (stk500v2_getsync(pgm) < 0) {
serial_close(&pgm->fd);
return -1;
}
return 0;
}

View File

@ -157,8 +157,6 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
"expTimeFirst = " + expt_first_str + "\n"
"numFade = " + cnt_fade_layers + "\n"
"layerHeight = " + layerh_str + "\n"
"expTime = "+expt_str+" + resinType = generic+layerHeight = "
+layerh_str+" + printer = DWARF3\n"
"usedMaterial = " + used_material + "\n"
"numSlow = " + cnt_slow_layers + "\n"
"numFast = " + cnt_fast_layers + "\n";

View File

@ -1004,7 +1004,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason)
p->btn_prev = new wxButton(this, wxID_ANY, _(L("< &Back")));
p->btn_next = new wxButton(this, wxID_ANY, _(L("&Next >")));
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
p->btn_cancel = new wxButton(this, wxID_CANCEL);
p->btn_cancel = new wxButton(this, wxID_CANCEL, _(L("Cancel"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
p->btnsizer->AddStretchSpacer();
p->btnsizer->Add(p->btn_prev, 0, wxLEFT, BTN_SPACING);
p->btnsizer->Add(p->btn_next, 0, wxLEFT, BTN_SPACING);

View File

@ -122,7 +122,6 @@ struct FirmwareDialog::priv
// This is a shared pointer holding the background AvrDude task
// also serves as a status indication (it is set _iff_ the background task is running, otherwise it is reset).
AvrDude::Ptr avrdude;
std::string avrdude_config;
unsigned progress_tasks_done;
unsigned progress_tasks_bar;
bool user_cancelled;
@ -134,7 +133,6 @@ struct FirmwareDialog::priv
btn_flash_label_flashing(_(L("Cancel"))),
label_status_flashing(_(L("Flashing in progress. Please do not disconnect the printer!"))),
timer_pulse(q),
avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()),
progress_tasks_done(0),
progress_tasks_bar(0),
user_cancelled(false),
@ -553,7 +551,7 @@ void FirmwareDialog::priv::perform_upload()
flashing_start(hex_file.device == HexFile::DEV_MK3 ? 2 : 1);
// Init the avrdude object
AvrDude avrdude(avrdude_config);
AvrDude avrdude;
// It is ok here to use the q-pointer to the FirmwareDialog
// because the dialog ensures it doesn't exit before the background thread is done.
@ -722,7 +720,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
panel->SetSizer(vsizer);
auto *label_hex_picker = new wxStaticText(panel, wxID_ANY, _(L("Firmware image:")));
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, wxFileSelectorPromptStr,
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, wxFileSelectorPromptStr,
"Hex files (*.hex)|*.hex|All files|*.*");
auto *label_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:")));
@ -770,7 +768,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
// Experience says it needs to be 1, otherwise things won't get sized properly.
vsizer->Add(p->spoiler, 1, wxEXPAND | wxBOTTOM, SPACING);
p->btn_close = new wxButton(panel, wxID_CLOSE);
p->btn_close = new wxButton(panel, wxID_CLOSE, _(L("Close"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
p->btn_flash = new wxButton(panel, wxID_ANY, p->btn_flash_label_ready);
p->btn_flash->Disable();
auto *bsizer = new wxBoxSizer(wxHORIZONTAL);

View File

@ -896,8 +896,7 @@ void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selectio
if (needs_reset)
clear();
if (volume->is_modifier)
m_mode = Volume;
m_mode = volume->is_modifier ? Volume : Instance;
switch (m_mode)
{
@ -4918,6 +4917,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
// to remove hover on objects when the mouse goes out of this canvas
m_mouse.position = Vec2d(-1.0, -1.0);
// ensure m_mouse.left_down is reset (it may happen when switching canvas)
m_mouse.left_down = false;
m_dirty = true;
}
else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
@ -4985,12 +4986,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
// event was taken care of by the SlaSupports gizmo
}
else if (view_toolbar_contains_mouse != -1)
else if (evt.LeftDown() && (view_toolbar_contains_mouse != -1))
{
if (m_view_toolbar != nullptr)
m_view_toolbar->do_action((unsigned int)view_toolbar_contains_mouse, *this);
}
else if (toolbar_contains_mouse != -1)
else if (evt.LeftDown() && (toolbar_contains_mouse != -1))
{
m_toolbar_action_running = true;
m_mouse.set_start_position_3D_as_invalid();
@ -5188,7 +5189,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// the gizmo got the event and took some action, no need to do anything more here
m_dirty = true;
}
else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
// do not process dragging if the mouse is into any of the HUD elements
else if (evt.Dragging() && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1) && (view_toolbar_contains_mouse == -1))
{
m_mouse.dragging = true;
@ -5197,7 +5199,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (m_layers_editing.state == LayersEditing::Editing)
_perform_layer_editing_action(&evt);
}
else if (evt.LeftIsDown())
// do not process the dragging if the left mouse was set down in another canvas
else if (m_mouse.left_down && evt.LeftIsDown())
{
// if dragging over blank area with left button, rotate
#if ENABLE_MOVE_MIN_THRESHOLD

View File

@ -25,6 +25,8 @@
#include "GUI.hpp"
#include "GUI_Utils.hpp"
#include "GUI_App.hpp"
#include "GUI_ObjectSettings.hpp"
#include "GUI_ObjectList.hpp"
#include "I18N.hpp"
#include "PresetBundle.hpp"
@ -1937,7 +1939,7 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
{
return (m_state == On) && (m_model_object != nullptr) && (m_model_object != m_old_model_object) && !m_model_object->instances.empty();
return (m_state == On) && (m_model_object != m_old_model_object) && (m_model_object != nullptr) && !m_model_object->instances.empty();
//if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix))
// return false;
@ -2176,13 +2178,10 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
return false;
}
void GLGizmoSlaSupports::delete_selected_points()
void GLGizmoSlaSupports::delete_selected_points(bool force)
{
if (!m_editing_mode)
return;
for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands)) {
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands || force)) {
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
m_unsaved_changes = true;
}
@ -2243,6 +2242,35 @@ void GLGizmoSlaSupports::render_tooltip_texture() const {
#endif // not ENABLE_IMGUI
std::vector<ConfigOption*> GLGizmoSlaSupports::get_config_options(const std::vector<std::string>& keys) const
{
std::vector<ConfigOption*> out;
if (!m_model_object)
return out;
DynamicPrintConfig& object_cfg = m_model_object->config;
DynamicPrintConfig& print_cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
std::unique_ptr<DynamicPrintConfig> default_cfg = nullptr;
for (const std::string& key : keys) {
if (object_cfg.has(key))
out.push_back(object_cfg.option(key));
else
if (print_cfg.has(key))
out.push_back(print_cfg.option(key));
else { // we must get it from defaults
if (default_cfg == nullptr)
default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys));
out.push_back(default_cfg->option(key));
}
}
return out;
}
#if ENABLE_IMGUI
void GLGizmoSlaSupports::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
{
@ -2257,6 +2285,7 @@ RENDER_AGAIN:
bool force_refresh = false;
bool remove_selected = false;
bool remove_all = false;
if (m_editing_mode) {
m_imgui->text(_(L("Left mouse click - add point")));
@ -2270,7 +2299,8 @@ RENDER_AGAIN:
wxString str = ss.str();
bool old_combo_state = m_combo_box_open;
m_combo_box_open = m_imgui->combo(_(L("Head diameter")), options, str);
// The combo is commented out for now, until the feature is supported by backend.
// m_combo_box_open = m_imgui->combo(_(L("Head diameter")), options, str);
force_refresh |= (old_combo_state != m_combo_box_open);
float current_number = atof(str);
@ -2294,6 +2324,10 @@ RENDER_AGAIN:
remove_selected = m_imgui->button(_(L("Remove selected points")));
m_imgui->disabled_end();
m_imgui->disabled_begin(m_editing_mode_cache.empty());
remove_all = m_imgui->button(_(L("Remove all points")));
m_imgui->disabled_end();
m_imgui->text(" "); // vertical gap
if (m_imgui->button(_(L("Apply changes")))) {
@ -2308,13 +2342,29 @@ RENDER_AGAIN:
}
}
else { // not in editing mode:
/*ImGui::PushItemWidth(100.0f);
ImGui::PushItemWidth(100.0f);
m_imgui->text(_(L("Minimal points distance: ")));
ImGui::SameLine();
bool value_changed = ImGui::SliderFloat("", &m_minimal_point_distance, 0.f, 20.f, "%.f mm");
std::vector<ConfigOption*> opts = get_config_options({"support_points_density_relative", "support_points_minimal_distance"});
float density = static_cast<ConfigOptionInt*>(opts[0])->value;
float minimal_point_distance = static_cast<ConfigOptionFloat*>(opts[1])->value;
bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm");
if (value_changed)
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
m_imgui->text(_(L("Support points density: ")));
ImGui::SameLine();
value_changed |= ImGui::SliderFloat(" ", &m_density, 0.f, 200.f, "%.f %%");*/
if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) {
value_changed = true;
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density;
}
if (value_changed) { // Update side panel
wxGetApp().obj_settings()->UpdateAndShow(true);
wxGetApp().obj_list()->update_settings_items();
}
bool generate = m_imgui->button(_(L("Auto-generate points [A]")));
@ -2325,6 +2375,12 @@ RENDER_AGAIN:
if (m_imgui->button(_(L("Manual editing [M]"))))
switch_to_editing_mode();
m_imgui->disabled_begin(m_editing_mode_cache.empty());
remove_all = m_imgui->button(_(L("Remove all points")));
m_imgui->disabled_end();
m_imgui->text("");
m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" :
(m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" :
(m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" :
@ -2339,10 +2395,14 @@ RENDER_AGAIN:
}
m_old_editing_state = m_editing_mode;
if (remove_selected) {
if (remove_selected || remove_all) {
force_refresh = false;
m_parent.reload_scene(true);
delete_selected_points();
if (remove_all)
select_point(AllPoints);
delete_selected_points(remove_all);
if (remove_all && !m_editing_mode)
editing_mode_apply_changes();
if (first_run) {
first_run = false;
goto RENDER_AGAIN;
@ -2390,19 +2450,22 @@ void GLGizmoSlaSupports::on_set_state()
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
}
if (m_state == Off) {
if (m_old_state != Off && m_model_object) { // the gizmo was just turned Off
if (m_old_state != Off) { // the gizmo was just turned Off
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
if (m_model_object) {
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
}
}
m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; // so it is not active next time the gizmo opens
m_editing_mode_cache.clear();
}
}
m_old_state = m_state;

View File

@ -469,7 +469,7 @@ public:
virtual ~GLGizmoSlaSupports();
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
void delete_selected_points();
void delete_selected_points(bool force = false);
private:
bool on_init();
@ -507,6 +507,8 @@ private:
int m_canvas_width;
int m_canvas_height;
std::vector<ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
// Methods that do the model_object and editing cache synchronization,
// editing mode selection, etc:
enum {

View File

@ -177,33 +177,40 @@ bool GUI_App::OnInit()
if (this->plater() != nullptr)
this->obj_manipul()->update_if_dirty();
});
// On OS X the UI tends to freeze in weird ways if modal dialogs(config wizard, update notifications, ...)
// are shown before or in the same event callback with the main frame creation.
// Therefore we schedule them for later using CallAfter.
CallAfter([this]() {
try {
if (!preset_updater->config_update())
mainframe->Close();
} catch (const std::exception &ex) {
show_error(nullptr, ex.what());
// Preset updating & Configwizard are done after the above initializations,
// and after MainFrame is created & shown.
// The extra CallAfter() is needed because of Mac, where this is the only way
// to popup a modal dialog on start without screwing combo boxes.
// This is ugly but I honestly found not better way to do it.
// Neither wxShowEvent nor wxWindowCreateEvent work reliably.
static bool once = true;
if (once) {
once = false;
try {
if (!preset_updater->config_update()) {
mainframe->Close();
}
} catch (const std::exception &ex) {
show_error(nullptr, ex.what());
}
CallAfter([this] {
if (!config_wizard_startup(app_conf_exists)) {
// Only notify if there was not wizard so as not to bother too much ...
preset_updater->slic3r_update_notify();
}
preset_updater->sync(preset_bundle);
});
load_current_presets();
}
});
CallAfter([this]() {
if (!config_wizard_startup(app_conf_exists)) {
// Only notify if there was not wizard so as not to bother too much ...
preset_updater->slic3r_update_notify();
}
preset_updater->sync(preset_bundle);
load_current_presets();
});
mainframe->Show(true);
return m_initialized = true;
m_initialized = true;
return true;
}
unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)

View File

@ -418,11 +418,14 @@ void Preview::load_print()
load_print_as_sla();
}
void Preview::reload_print(bool force)
void Preview::reload_print(bool force, bool keep_volumes)
{
m_canvas->reset_volumes();
m_canvas->reset_legend_texture();
m_loaded = false;
if (!keep_volumes)
{
m_canvas->reset_volumes();
m_canvas->reset_legend_texture();
m_loaded = false;
}
if (!IsShown() && !force)
return;

View File

@ -129,7 +129,7 @@ public:
void set_drop_target(wxDropTarget* target);
void load_print();
void reload_print(bool force = false);
void reload_print(bool force = false, bool keep_volumes = false);
void refresh_print();
private:

View File

@ -1997,6 +1997,9 @@ void Plater::priv::schedule_background_process()
this->background_process_timer.Start(500, wxTIMER_ONE_SHOT);
// Notify the Canvas3D that something has changed, so it may invalidate some of the layer editing stuff.
this->view3D->get_canvas3d()->set_config(this->config);
// Reset gcode preview
this->preview->get_canvas3d()->reset_volumes();
this->preview->get_canvas3d()->reset_legend_texture();
}
void Plater::priv::update_print_volume_state()
@ -2261,7 +2264,8 @@ void Plater::priv::set_current_panel(wxPanel* panel)
else if (current_panel == preview)
{
this->q->reslice();
preview->reload_print();
// keeps current gcode preview, if any
preview->reload_print(false, true);
preview->set_canvas_as_dirty();
view_toolbar.select_item("Preview");
}

View File

@ -157,7 +157,7 @@ PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent)
btn_cancel->Disable();
btn_error = new wxButton(this, wxID_ANY, _(L("Show error message")));
btn_error->Disable();
auto *btn_close = new wxButton(this, wxID_CANCEL, _(L("Close")));
auto *btn_close = new wxButton(this, wxID_CANCEL, _(L("Close"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING);
btnsizer->Add(btn_error, 0);
btnsizer->AddStretchSpacer();