From 49fcd8a96e29db8ef7ed3a91197d4d18f8079f5b Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 8 Aug 2022 16:52:09 +0100 Subject: [PATCH] Implement -c */[sSA] (syntax-correct dump of programmer structure) --- src/avrpart.c | 2 +- src/config.c | 7 ++- src/config.h | 2 + src/config_gram.y | 3 +- src/developer_opts.c | 93 +++++++++++++++++++++++++++--- src/developer_opts_private.h | 16 ++++++ src/lexer.l | 15 +++-- src/libavrdude.h | 63 +++++++++++++------- src/main.c | 20 ++++--- src/pgm.c | 2 +- src/pgm_type.c | 108 +++++++++++++++++++---------------- src/pindefs.c | 45 ++++++++++++++- 12 files changed, 281 insertions(+), 95 deletions(-) diff --git a/src/avrpart.c b/src/avrpart.c index 970dfde8..c4a2bd8b 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -672,7 +672,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, AVRPART * avr_new_part(void) { AVRPART * p; - char *nulp = cache_string(""); + const char *nulp = cache_string(""); p = (AVRPART *)malloc(sizeof(AVRPART)); if (p == NULL) { diff --git a/src/config.c b/src/config.c index 4308407e..34745daf 100644 --- a/src/config.c +++ b/src/config.c @@ -366,7 +366,7 @@ int read_config(const char * file) // Linear-search cache for a few often-referenced strings -char *cache_string(const char *file) { +const char *cache_string(const char *file) { static char **fnames; static int n=0; @@ -394,3 +394,8 @@ char *cache_string(const char *file) { return fnames[n++]; } + +// Captures comments during parsing +int capture_comment_char(int c) { + return c; +} diff --git a/src/config.h b/src/config.h index a7d2563d..1ebd2f70 100644 --- a/src/config.h +++ b/src/config.h @@ -101,6 +101,8 @@ void pyytext(void); char * dup_string(const char * str); +int capture_comment_char(int c); + #ifdef __cplusplus } #endif diff --git a/src/config_gram.y b/src/config_gram.y index 552832ec..c3554dcc 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -1397,7 +1397,8 @@ yesno : mem_specs : mem_spec TKN_SEMI | mem_alias TKN_SEMI | - mem_specs mem_spec TKN_SEMI + mem_specs mem_spec TKN_SEMI | + /* empty */ ; diff --git a/src/developer_opts.c b/src/developer_opts.c index 8d8c183c..bd59e940 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -613,8 +613,8 @@ void dev_output_part_defs(char *partdesc) { if((flags = strchr(partdesc, '/'))) *flags++ = 0; - if(!flags && !strcmp(partdesc, "*")) // Treat -p * as if it was -p */* - flags = "*"; + if(!flags && !strcmp(partdesc, "*")) // Treat -p * as if it was -p */s + flags = "s"; if(!*flags || !strchr("cdoASsrw*t", *flags)) { dev_info("%s: flags for developer option -p / not recognised\n", progname); @@ -640,7 +640,7 @@ void dev_output_part_defs(char *partdesc) { " $ avrdude -p m328*/st | grep chip_erase_delay\n" " avrdude -p*/r | sort\n" "Notes:\n" - " -p * is the same as -p */*\n" + " -p * is the same as -p */s\n" " This help message is printed using any unrecognised flag, eg, -p/h\n" " Leaving no space after -p can be an OK substitute for quoting in shells\n" " /s, /S and /A outputs are designed to be used as input in avrdude.conf\n" @@ -935,19 +935,37 @@ static void dev_pgm_raw(PROGRAMMER *pgm) { dp.id = NULL; dp.parent_id = NULL; dp.initpgm = NULL; + dp.usbpid = NULL; + dp.usbdev = NULL; + dp.usbsn = NULL; + dp.usbvendor = NULL; + dp.usbproduct = NULL; + dp.hvupdi_support = NULL; // Only dump contents of PROGRAMMER struct up to and excluding the fd component dev_raw_dump((char *) &dp, offsetof(PROGRAMMER, fd), id, "pgm", 0); } -static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { - if(!tsv) { - int firstid = 1; +static const char *connstr(conntype_t conntype) { + switch(conntype) { + case CONNTYPE_PARALLEL: return "parallel"; + case CONNTYPE_SERIAL: return "serial"; + case CONNTYPE_USB: return "usb"; + case CONNTYPE_SPI: return "spi"; + default: return ""; + } +} +static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { + char *id = ldata(lfirst(pgm->id)); + LNODEID ln; + int firstid; + + if(!tsv) { dev_info("#------------------------------------------------------------\n"); dev_info("# "); - for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) { + for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) { if(!firstid) dev_info("/"); firstid = 0; @@ -961,6 +979,67 @@ static void dev_pgm_strct(PROGRAMMER *pgm, bool tsv, PROGRAMMER *base) { dev_info("\nprogrammer\n"); } + if(tsv) + dev_info(".prog\t%s\tid\t", id); + else + dev_info(" %-19s = ", "id"); + for(firstid=1, ln=lfirst(pgm->id); ln; ln=lnext(ln)) { + if(!firstid) + dev_info(", "); + firstid = 0; + dev_info("\"%s\"", ldata(ln)); + } + dev_info(tsv? "\n": ";\n"); + + _if_pgmout(strcmp, "\"%s\"", desc); + _pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm)); + _pgmout_fmt("connection_type", "%s", connstr(pgm->conntype)); + _if_pgmout(intcmp, "%d", baudrate); + + _if_pgmout(intcmp, "0x%04x", usbvid); + + if(pgm->usbpid && lfirst(pgm->usbpid)) { + if(tsv) + dev_info(".prog\t%s\tusbpid\t", id); + else + dev_info(" %-19s = ", "usbpid"); + for(firstid=1, ln=lfirst(pgm->usbpid); ln; ln=lnext(ln)) { + if(!firstid) + dev_info(", "); + firstid = 0; + dev_info("0x%04x", *(unsigned int *) ldata(ln)); + } + dev_info(tsv? "\n": ";\n"); + } + + _if_pgmout(strcmp, "\"%s\"", usbdev); + _if_pgmout(strcmp, "\"%s\"", usbsn); + _if_pgmout(strcmp, "\"%s\"", usbvendor); + _if_pgmout(strcmp, "\"%s\"", usbproduct); + + for(int i=0; ipin+i); + if(str && *str) + _pgmout_fmt(avr_pin_lcname(i), "%s", str); + if(str) + free(str); + } + + if(pgm->hvupdi_support && lfirst(pgm->hvupdi_support)) { + if(tsv) + dev_info(".prog\t%s\thvupdu_support\t", id); + else + dev_info(" %-19s = ", "hvupdi_support"); + for(firstid=1, ln=lfirst(pgm->hvupdi_support); ln; ln=lnext(ln)) { + if(!firstid) + dev_info(", "); + firstid = 0; + dev_info("%d", *(unsigned int *) ldata(ln)); + } + dev_info(tsv? "\n": ";\n"); + } + + if(!tsv) dev_info(";\n"); } diff --git a/src/developer_opts_private.h b/src/developer_opts_private.h index 5a208199..e6be1ee9 100644 --- a/src/developer_opts_private.h +++ b/src/developer_opts_private.h @@ -51,6 +51,22 @@ static int dev_message(int msglvl, const char *fmt, ...); #define dev_notice(...) dev_message(DEV_NOTICE, __VA_ARGS__) #define dev_notice2(...) dev_message(DEV_NOTICE2, __VA_ARGS__) +#define _pgmout(fmt, component) \ + dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component)) + +#define _pgmout_fmt(name, fmt, what) \ + dev_part_strct_entry(tsv, ".prog", id, NULL, name, dev_sprintf(fmt, what)) + +#define _if_pgmout(cmp, fmt, component) do { \ + if(!base || cmp(base->component, pgm->component)) \ + dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component)); \ +} while(0) + +#define _if_pgmout_str(cmp, result, component) do { \ + if(!base || cmp(base->component, pgm->component)) \ + dev_part_strct_entry(tsv, ".prog", id, NULL, #component, result); \ +} while(0) + #define _partout(fmt, component) \ dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component)) diff --git a/src/lexer.l b/src/lexer.l index 91d02597..c55d7853 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -67,13 +67,20 @@ SIGN [+-] -# { /* The following eats '#' style comments to end of line */ +# { /* The following captures all '#' style comments to end of line */ BEGIN(comment); } -[^\n] { /* eat comments */ } -\n { cfg_lineno++; BEGIN(INITIAL); } +[^\n]*\n+ { /* eat comments */ + capture_comment_char('#'); + for(int i=0; yytext[i]; i++) { + capture_comment_char(yytext[i]); + if(yytext[i] == '\n') + cfg_lineno++; + } + BEGIN(INITIAL); +} -"/*" { /* The following eats multiline C style comments */ +"/*" { /* The following eats multiline C style comments, they are not captured */ int c; int comment_start; diff --git a/src/libavrdude.h b/src/libavrdude.h index 2dc4bcc5..c17f611b 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -516,7 +516,15 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist const char * avr_pin_name(int pinname); /** - * This function returns a string representation of defined pins eg. ~1,2,~4,~5,7 + * Returns the name of the pin as lowercase string. + * + * @param pinname the pinname which we want as string. + * @returns a lowercase string with the pinname, or if pinname is invalid. + */ +const char * avr_pin_lcname(int pinname); + +/** + * This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)" * Another execution of this function will overwrite the previous result in the static buffer. * * @param[in] pindef the pin definition for which we want the string representation @@ -525,9 +533,17 @@ const char * avr_pin_name(int pinname); const char * pins_to_str(const struct pindef_t * const pindef); /** - * This function returns a string representation of pins in the mask eg. 1,3,5-7,9,12 + * This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or "" + * + * @param[in] pindef the pin definition for which we want the string representation + * @returns a pointer to a string, which was created by strdup (NULL if out of memory) + */ +char *pins_to_strdup(const struct pindef_t * const pindef); + +/** + * This function returns a string representation of pins in the mask, eg, 1,3,5-7,9,12 * Another execution of this function will overwrite the previous result in the static buffer. - * Consecutive pin number are representated as start-end. + * Consecutive pin number are represented as start-end. * * @param[in] pinmask the pin mask for which we want the string representation * @returns pointer to a static string. @@ -670,29 +686,32 @@ typedef enum { typedef struct programmer_t { LISTID id; char desc[PGM_DESCLEN]; - char type[PGM_TYPELEN]; - char port[PGM_PORTLEN]; - const char *parent_id; - unsigned int pinno[N_PINS]; + void (*initpgm)(struct programmer_t *pgm); + const char *parent_id; // Used by developer options -c*/[sr...] struct pindef_t pin[N_PINS]; - exit_vcc_t exit_vcc; - exit_reset_t exit_reset; - exit_datahigh_t exit_datahigh; conntype_t conntype; - int ppidata; - int ppictrl; int baudrate; int usbvid; LISTID usbpid; - LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x - const char *usbdev, *usbsn, *usbvendor, *usbproduct; - double bitclock; // JTAG ICE clock period in microseconds - int ispdelay; // ISP clock delay - int page_size; // Page size if the programmer supports paged write/load + const char *usbdev; + const char *usbsn; + const char *usbvendor; + const char *usbproduct; + LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x - // Values below are not set by config_gram.y; first one must be fd for dev_pgm_raw() + // Values below are not set by config_gram.y; make sure fd is first for dev_pgm_raw() union filedescriptor fd; - void (*initpgm)(struct programmer_t * pgm); + char type[PGM_TYPELEN]; + char port[PGM_PORTLEN]; + unsigned int pinno[N_PINS]; // TODO to be removed if old pin data no longer needed + exit_vcc_t exit_vcc; // Should these be set in avrdude.conf? + exit_reset_t exit_reset; + exit_datahigh_t exit_datahigh; + int ppidata; + int ppictrl; + int ispdelay; // ISP clock delay + int page_size; // Page size if the programmer supports paged write/load + double bitclock; // JTAG ICE clock period in microseconds int (*rdy_led) (struct programmer_t * pgm, int value); int (*err_led) (struct programmer_t * pgm, int value); @@ -957,7 +976,9 @@ typedef struct programmer_type_t { extern "C" { #endif -const PROGRAMMER_TYPE * locate_programmer_type(/*LISTID programmer_types, */const char * id); +const PROGRAMMER_TYPE *locate_programmer_type(const char *id); + +const char *locate_programmer_type_id(const void (*initpgm)(struct programmer_t *pgm)); typedef void (*walk_programmer_types_cb)(const char *id, const char *desc, void *cookie); @@ -991,7 +1012,7 @@ void cleanup_config(void); int read_config(const char * file); -char *cache_string(const char *file); +const char *cache_string(const char *file); #ifdef __cplusplus } diff --git a/src/main.c b/src/main.c index 83bde3e9..ab10b4fa 100644 --- a/src/main.c +++ b/src/main.c @@ -752,13 +752,21 @@ int main(int argc, char * argv []) } - avrdude_message(MSG_NOTICE, "\n"); - + int dev_opts = 0; + // Developer option -c /[ASsrt] prints programmer description(s) and exits + if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) { + dev_output_pgm_defs(programmer); + dev_opts = 1; + } // Developer option -p /[dASsrcow*t] prints part description(s) and exits if(partdesc && (strcmp(partdesc, "*") == 0 || strchr(partdesc, '/'))) { dev_output_part_defs(partdesc); - exit(1); + dev_opts = 1; } + if(dev_opts) + exit(0); + + avrdude_message(MSG_NOTICE, "\n"); if (partdesc) { if (strcmp(partdesc, "?") == 0) { @@ -770,12 +778,6 @@ int main(int argc, char * argv []) } } - // Developer option -c /[ASsrt] prints programmer description(s) and exits - if(programmer && (strcmp(programmer, "*") == 0 || strchr(programmer, '/'))) { - dev_output_pgm_defs(programmer); - exit(1); - } - if (programmer) { if (strcmp(programmer, "?") == 0) { avrdude_message(MSG_INFO, "\n"); diff --git a/src/pgm.c b/src/pgm.c index a4e0ed54..238f61d8 100644 --- a/src/pgm.c +++ b/src/pgm.c @@ -65,7 +65,7 @@ PROGRAMMER * pgm_new(void) { int i; PROGRAMMER * pgm; - char *nulp = cache_string(""); + const char *nulp = cache_string(""); pgm = (PROGRAMMER *)malloc(sizeof(*pgm)); if (pgm == NULL) { diff --git a/src/pgm_type.c b/src/pgm_type.c index 82320fab..46090424 100644 --- a/src/pgm_type.c +++ b/src/pgm_type.c @@ -57,55 +57,55 @@ #include "xbee.h" -const PROGRAMMER_TYPE programmers_types[] = { - {"arduino", arduino_initpgm, arduino_desc}, - {"avr910", avr910_initpgm, avr910_desc}, - {"avrftdi", avrftdi_initpgm, avrftdi_desc}, - {"buspirate", buspirate_initpgm, buspirate_desc}, - {"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc}, - {"butterfly", butterfly_initpgm, butterfly_desc}, - {"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc}, - {"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc}, - {"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc}, - {"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc}, - {"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc}, - {"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc}, - {"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc}, - {"flip1", flip1_initpgm, flip1_desc}, - {"flip2", flip2_initpgm, flip2_desc}, - {"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, - {"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, - {"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, - {"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, - {"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc}, - {"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc}, - {"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc}, - {"jtagmkii_updi", jtagmkII_updi_initpgm, jtagmkII_updi_desc}, - {"jtagice3", jtag3_initpgm, jtag3_desc}, - {"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc}, - {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, - {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, - {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, - {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, - {"linuxspi", linuxspi_initpgm, linuxspi_desc}, - {"micronucleus", micronucleus_initpgm, micronucleus_desc}, - {"par", par_initpgm, par_desc}, - {"pickit2", pickit2_initpgm, pickit2_desc}, - {"serbb", serbb_initpgm, serbb_desc}, - {"serialupdi", serialupdi_initpgm, serialupdi_desc}, - {"stk500", stk500_initpgm, stk500_desc}, - {"stk500generic", stk500generic_initpgm, stk500generic_desc}, - {"stk500v2", stk500v2_initpgm, stk500v2_desc}, - {"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc}, - {"stk500pp", stk500pp_initpgm, stk500pp_desc}, - {"stk600", stk600_initpgm, stk600_desc}, - {"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, - {"stk600pp", stk600pp_initpgm, stk600pp_desc}, - {"teensy", teensy_initpgm, teensy_desc}, - {"usbasp", usbasp_initpgm, usbasp_desc}, - {"usbtiny", usbtiny_initpgm, usbtiny_desc}, - {"wiring", wiring_initpgm, wiring_desc}, - {"xbee", xbee_initpgm, xbee_desc}, +const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call themselves + {"arduino", arduino_initpgm, arduino_desc}, // "Arduino" + {"avr910", avr910_initpgm, avr910_desc}, // "avr910" + {"avrftdi", avrftdi_initpgm, avrftdi_desc}, // "avrftdi" + {"buspirate", buspirate_initpgm, buspirate_desc}, // "BusPirate" + {"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc}, // "BusPirate_BB" + {"butterfly", butterfly_initpgm, butterfly_desc}, // "butterfly" + {"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc}, // "butterfly_mk" + {"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc}, // "DRAGON_DW" + {"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc}, // "DRAGON_HVSP" + {"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc}, // "DRAGON_ISP" + {"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc}, // "DRAGON_JTAG" + {"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc}, // "DRAGON_PDI" + {"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc}, // "DRAGON_PP" + {"flip1", flip1_initpgm, flip1_desc}, // "flip1" + {"flip2", flip2_initpgm, flip2_desc}, // "flip2" + {"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, // "ftdi_syncbb" + {"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, // "JTAGMKI" + {"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, // "JTAGMKII" + {"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, // "JTAGMKII_AVR32" + {"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc}, // "JTAGMKII_DW" + {"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc}, // "JTAGMKII_ISP" + {"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc}, // "JTAGMKII_PDI" + {"jtagmkii_updi", jtagmkII_updi_initpgm, jtagmkII_updi_desc}, // "JTAGMKII_UPDI" + {"jtagice3", jtag3_initpgm, jtag3_desc}, // "JTAGICE3" + {"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc}, // "JTAGICE3_PDI" + {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, // "JTAGICE3_UPDI" + {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, // "JTAGICE3_DW" + {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, // "JTAG3_ISP" + {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio" + {"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI + {"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0" + {"par", par_initpgm, par_desc}, // "PPI" + {"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2" + {"serbb", serbb_initpgm, serbb_desc}, // "SERBB" + {"serialupdi", serialupdi_initpgm, serialupdi_desc}, // "serialupdi" + {"stk500", stk500_initpgm, stk500_desc}, // "STK500" + {"stk500generic", stk500generic_initpgm, stk500generic_desc}, // "STK500GENERIC" + {"stk500v2", stk500v2_initpgm, stk500v2_desc}, // "STK500V2" + {"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc}, // "STK500HVSP" + {"stk500pp", stk500pp_initpgm, stk500pp_desc}, // "STK500PP" + {"stk600", stk600_initpgm, stk600_desc}, // "STK600" + {"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, // "STK600HVSP" + {"stk600pp", stk600pp_initpgm, stk600pp_desc}, // "STK600PP" + {"teensy", teensy_initpgm, teensy_desc}, // "teensy" + {"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp" + {"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny" + {"wiring", wiring_initpgm, wiring_desc}, // "Wiring" + {"xbee", xbee_initpgm, xbee_desc}, // "XBee" }; const PROGRAMMER_TYPE * locate_programmer_type(const char * id) @@ -128,6 +128,16 @@ const PROGRAMMER_TYPE * locate_programmer_type(const char * id) return NULL; } +// Return type id given the init function or "" if not found +const char *locate_programmer_type_id(void (*initpgm)(struct programmer_t *pgm)) { + for (int i=0; i < sizeof programmers_types/sizeof*programmers_types; i++) + if(programmers_types[i].initpgm == initpgm) + return programmers_types[i].id; + + return ""; +} + + /* * Iterate over the list of programmers given as "programmers", and * call the callback function cb for each entry found. cb is being diff --git a/src/pindefs.c b/src/pindefs.c index f51e5c20..1d860ebf 100644 --- a/src/pindefs.c +++ b/src/pindefs.c @@ -312,7 +312,7 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist } /** - * This function returns a string representation of defined pins eg. ~1,2,~4,~5,7 + * This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)" * Another execution of this function will overwrite the previous result in the static buffer. * * @param[in] pindef the pin definition for which we want the string representation @@ -346,6 +346,28 @@ const char * pins_to_str(const struct pindef_t * const pindef) { return buf; } +/** + * This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or "" + * + * @param[in] pindef the pin definition for which we want the string representation + * @returns a pointer to a string, which was created by strdup (NULL if out of memory) + */ +char *pins_to_strdup(const struct pindef_t * const pindef) { + char buf[6*(PIN_MAX+1)], *p = buf; + + *buf = 0; + for(int pin = PIN_MIN; pin <= PIN_MAX; pin++) { + int index = pin / PIN_FIELD_ELEMENT_SIZE, bit = pin % PIN_FIELD_ELEMENT_SIZE; + if(pindef->mask[index] & (1 << bit)) { + if(*buf) + *p++ = ',', *p++=' '; + p += sprintf(p, "~%d" + !(pindef->inverse[index] & (1 << bit)), pin); + } + } + + return strdup(buf); +} + /** * Returns the name of the pin as string. * @@ -369,3 +391,24 @@ const char * avr_pin_name(int pinname) { } +/** + * Returns the name of the pin as string. + * + * @param pinname the pinname which we want as string. + * @returns a lowercase string with the pinname, or if pinname is invalid. + */ +const char * avr_pin_lcname(int pinname) { + switch(pinname) { + case PPI_AVR_VCC : return "vcc"; + case PPI_AVR_BUFF : return "buff"; + case PIN_AVR_RESET : return "reset"; + case PIN_AVR_SCK : return "sck"; + case PIN_AVR_MOSI : return "mosi"; + case PIN_AVR_MISO : return "miso"; + case PIN_LED_ERR : return "errled"; + case PIN_LED_RDY : return "rdyled"; + case PIN_LED_PGM : return "pgmled"; + case PIN_LED_VFY : return "vfyled"; + default : return ""; + } +}