/* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2002-2004 Brian S. Dean * Copyright 2007 Joerg Wunsch * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* $Id$ */ #include "ac_cfg.h" #include #include #include #include "avrdude.h" #include "libavrdude.h" static void pgm_default(void); static int pgm_default_2(const PROGRAMMER *, const AVRPART *); static int pgm_default_3(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char * value); static void pgm_default_4(const PROGRAMMER *); static int pgm_default_5(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data); static void pgm_default_6(const PROGRAMMER *, const char *); static int pgm_default_open(PROGRAMMER *pgm, const char *name) { pmsg_error("programmer does not support open()"); return -1; } static void pgm_default_close(PROGRAMMER *pgm) { pgm_default(); } static void pgm_default_enable(PROGRAMMER *pgm, const AVRPART *p) { pgm_default(); } static int pgm_default_led(const PROGRAMMER *pgm, int value) { // If programmer has no LEDs, just do nothing return 0; } static void pgm_default_powerup_powerdown(const PROGRAMMER *pgm) { // If programmer does not support powerup/down, just do nothing } PROGRAMMER *pgm_new(void) { PROGRAMMER *pgm = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm)); const char *nulp = cache_string(""); // Initialise const char * and LISTID entities pgm->id = lcreat(NULL, 0); pgm->usbpid = lcreat(NULL, 0); pgm->hvupdi_support = lcreat(NULL, 0); pgm->desc = nulp; pgm->parent_id = nulp; pgm->usbdev = nulp; pgm->usbsn = nulp; pgm->usbvendor = nulp; pgm->usbproduct = nulp; pgm->config_file = nulp; // Allocate cache structures for flash and EEPROM, *do not* free in pgm_free() pgm->cp_flash = cfg_malloc("pgm_new()", sizeof(AVR_Cache)); pgm->cp_eeprom = cfg_malloc("pgm_new()", sizeof(AVR_Cache)); // Default values pgm->initpgm = NULL; pgm->lineno = 0; pgm->baudrate = 0; // Clear pin array for(int i=0; ipinno[i] = NO_PIN; pin_clear_all(&(pgm->pin[i])); } /* * mandatory functions - these are called without checking to see * whether they are assigned or not */ pgm->initialize = pgm_default_2; pgm->display = pgm_default_6; pgm->enable = pgm_default_enable; pgm->disable = pgm_default_4; pgm->powerup = pgm_default_powerup_powerdown; pgm->powerdown = pgm_default_powerup_powerdown; pgm->program_enable = pgm_default_2; pgm->chip_erase = pgm_default_2; pgm->open = pgm_default_open; pgm->close = pgm_default_close; pgm->read_byte = pgm_default_3; pgm->write_byte = pgm_default_5; /* * predefined functions - these functions have a valid default * implementation. Hence, they don't need to be defined in * the programmer. */ pgm->rdy_led = pgm_default_led; pgm->err_led = pgm_default_led; pgm->pgm_led = pgm_default_led; pgm->vfy_led = pgm_default_led; pgm->read_byte_cached = avr_read_byte_cached; pgm->write_byte_cached = avr_write_byte_cached; pgm->chip_erase_cached = avr_chip_erase_cached; pgm->page_erase_cached = avr_page_erase_cached; pgm->flush_cache = avr_flush_cache; pgm->reset_cache = avr_reset_cache; /* * optional functions - these are checked to make sure they are * assigned before they are called */ pgm->unlock = NULL; pgm->cmd = NULL; pgm->cmd_tpi = NULL; pgm->spi = NULL; pgm->paged_write = NULL; pgm->paged_load = NULL; pgm->page_erase = NULL; pgm->write_setup = NULL; pgm->read_sig_bytes = NULL; pgm->read_sib = NULL; pgm->term_keep_alive= NULL; pgm->print_parms = NULL; pgm->set_vtarget = NULL; pgm->set_varef = NULL; pgm->set_fosc = NULL; pgm->set_sck_period = NULL; pgm->setpin = NULL; pgm->getpin = NULL; pgm->highpulsepin = NULL; pgm->parseexitspecs = NULL; pgm->perform_osccal = NULL; pgm->parseextparams = NULL; pgm->setup = NULL; pgm->teardown = NULL; pgm->readonly = NULL; pgm->flash_readhook = NULL; // For allocating "global" memory by the programmer pgm->cookie = NULL; return pgm; } void pgm_free(PROGRAMMER *p) { if(p) { if(p->id) { ldestroy_cb(p->id, free); p->id = NULL; } if(p->usbpid) { ldestroy_cb(p->usbpid, free); p->usbpid = NULL; } if(p->hvupdi_support) { ldestroy_cb(p->hvupdi_support, free); p->hvupdi_support = NULL; } // Never free const char *, eg, p->desc, which are set by cache_string() // p->cookie is freed by pgm_teardown // Never free cp_eeprom or cp_flash cache structures free(p); } } PROGRAMMER *pgm_dup(const PROGRAMMER *src) { PROGRAMMER *pgm = pgm_new(); if(src) { ldestroy_cb(pgm->id, free); ldestroy_cb(pgm->usbpid, free); ldestroy_cb(pgm->hvupdi_support, free); // There must be only one cache, even though the part is duplicated if(pgm->cp_flash) free(pgm->cp_flash); if(pgm->cp_eeprom) free(pgm->cp_eeprom); memcpy(pgm, src, sizeof(*pgm)); pgm->id = lcreat(NULL, 0); pgm->usbpid = lcreat(NULL, 0); pgm->hvupdi_support = lcreat(NULL, 0); // Leave id list empty but copy usbpid and hvupdi_support over if(src->hvupdi_support) for(LNODEID ln = lfirst(src->hvupdi_support); ln; ln = lnext(ln)) { int *ip = cfg_malloc("pgm_dup()", sizeof(int)); *ip = *(int *) ldata(ln); ladd(pgm->hvupdi_support, ip); } if(src->usbpid) for(LNODEID ln = lfirst(src->usbpid); ln; ln = lnext(ln)) { int *ip = cfg_malloc("pgm_dup()", sizeof(int)); *ip = *(int *) ldata(ln); ladd(pgm->usbpid, ip); } } return pgm; } static void pgm_default(void) { pmsg_error("programmer operation not supported\n"); } static int pgm_default_2 (const PROGRAMMER *pgm, const AVRPART *p) { pgm_default(); return -1; } static int pgm_default_3 (const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char * value) { pgm_default(); return -1; } static void pgm_default_4 (const PROGRAMMER *pgm) { pgm_default(); } static int pgm_default_5 (const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data) { pgm_default(); return -1; } static void pgm_default_6 (const PROGRAMMER *pgm, const char *p) { pgm_default(); } void programmer_display(PROGRAMMER *pgm, const char * p) { msg_info("%sProgrammer Type : %s\n", p, pgm->type); msg_info("%sDescription : %s\n", p, pgm->desc); pgm->display(pgm, p); } void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show) { if(show & (1<pin[PPI_AVR_VCC])); if(show & (1<pin[PPI_AVR_BUFF])); if(show & (1<pin[PIN_AVR_RESET])); if(show & (1<pin[PIN_AVR_SCK])); if(show & (1<pin[PIN_AVR_SDO])); if(show & (1<pin[PIN_AVR_SDI])); if(show & (1<pin[PIN_LED_ERR])); if(show & (1<pin[PIN_LED_RDY])); if(show & (1<pin[PIN_LED_PGM])); if(show & (1<pin[PIN_LED_VFY])); } void pgm_display_generic(const PROGRAMMER *pgm, const char *p) { pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS); } PROGRAMMER *locate_programmer(const LISTID programmers, const char *configid) { PROGRAMMER *p = NULL; int found = 0; for(LNODEID ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) { p = ldata(ln1); for(LNODEID ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2)) if(strcasecmp(configid, (const char *) ldata(ln2)) == 0) found = 1; } return found? p: NULL; } /* * Iterate over the list of programmers given as "programmers", and * call the callback function cb for each entry found. cb is being * passed the following arguments: * . the name of the programmer (for -c) * . the descriptive text given in the config file * . the name of the config file this programmer has been defined in * . the line number of the config file this programmer has been defined at * . the "cookie" passed into walk_programmers() (opaque client data) */ void walk_programmers(LISTID programmers, walk_programmers_cb cb, void *cookie) { LNODEID ln1; LNODEID ln2; PROGRAMMER * p; for (ln1 = lfirst(programmers); ln1; ln1 = lnext(ln1)) { p = ldata(ln1); for (ln2=lfirst(p->id); ln2; ln2=lnext(ln2)) { cb(ldata(ln2), p->desc, p->config_file, p->lineno, cookie); } } } /* * Compare function to sort the list of programmers */ static int sort_programmer_compare(const PROGRAMMER *p1, const PROGRAMMER *p2) { if(p1 == NULL || p1->id == NULL || p2 == NULL || p2->id == NULL) return 0; return strcasecmp(ldata(lfirst(p1->id)), ldata(lfirst(p2->id))); } /* * Sort the list of programmers given as "programmers" */ void sort_programmers(LISTID programmers) { lsort(programmers,(int (*)(void*, void*)) sort_programmer_compare); }