static void usage_n16(char *msg) { printf("USAGE: n16 [LVP] OPERATION [ARG]\n"); printf("16-bit PIC18F operations.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", p.dotfile); printf("ENVIRONMENT:\n" " PICKLE\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n"); printf(" n16 %ss%select\n" "\t\tShow supported devices.\n", UL_ON, UL_OFF); printf(" n16 %sl%svp OPERATION [ARG]\n" "\t\tLVP 32-bit key entry.\n", UL_ON, UL_OFF); printf(" n16 %sb%slank\n" "\t\tBlank device (disable protection and bulk erase).\n", UL_ON, UL_OFF); printf(" n16 %sc%sonfig\n" "\t\tDisplay device configuration.\n", UL_ON, UL_OFF); printf(" n16 %sda%sta\n" "\t\tDisplay data EEPROM content.\n", UL_ON, UL_OFF); printf(" n16 %sd%sump\n" "\t\tDump device content (INHX32 format).\n", UL_ON, UL_OFF); #if 0 printf(" n14 %ser%sase eeprom | flash | id | row [n]\n" "\t\tErase EEPROM, flash, id or flash at row for n rows.\n", UL_ON, UL_OFF); #endif printf(" n16 %sf%slash [n] [address]\n" "\t\tDisplay all or n words of program flash content from address.\n", UL_ON, UL_OFF); printf(" n16 %si%sd\n" "\t\tDisplay device identification.\n", UL_ON, UL_OFF); #ifdef LOADER printf(" n16 %slo%sader\n" "\t\tOutput boot loader configuration.\n", UL_ON, UL_OFF); #endif printf(" n16 %sp%srogram [file.hex] [noblank]\n" "\t\tBlank and program file.hex or stdin to flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" n16 %sv%serify [file.hex]\n" "\t\tVerify file.hex or stdin in flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" n16 %svi%sew [file.hex] [raw]\n" "\t\tView file.hex or stdin (INHX32 format).\n", UL_ON, UL_OFF); #ifdef STK500 printf(" n16 /dev/ttyUSB0 | %s8%s048\n" "\t\tListen on /dev/ttyUSB0 or network for remote programming.\n", UL_ON, UL_OFF); #endif printf("\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(EX_USAGE); io_exit(EX_OK); }
/* * Dot path */ int getdotpath(void) { struct stat st; if (stat(p.dotfile, &st) < 0) { if (errno == ENOENT) return -1; printf("%s: fatal error: stat failed [%s]\n", __func__, p.dotfile); io_exit(EX_SOFTWARE); /* Panic */ } if (S_ISREG(st.st_mode)) { return access(p.dotfile, R_OK); } if (S_ISDIR(st.st_mode)) { char *dotdup = (char *)strdup(p.dotfile); if (dotdup == NULL) { printf("%s: fatal error: strdup failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } snprintf(p.dotfile, STRLEN, "%s/%s", dotdup, DOTCONFIGNAME); free(dotdup); return access(p.dotfile, R_OK); } return -1; }
void usage_kctrl(struct k8048 *k, char *msg) { printf("USAGE: kctrl RUN|STOP|RESTORE\n"); printf("Control master clear.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", k->dotfile); printf("ENVIRONMENT:\n" " K8048\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n" " kctrl RUN\n" "\t\tRaise master clear to take the device out of reset.\n" " kctrl STOP\n" "\t\tLower master clear to put the device in reset.\n" " kctrl RESTORE\n" "\t\tLower then raise master clear to reset the device.\n" "\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(k, EX_USAGE); io_exit(k, EX_OK); }
void usage_k24(struct k8048 *k, char *msg) { printf("USAGE: k24 [SELECT DEVICE] [LVP|HVP] OPERATION [ARG]\n"); printf("24-bit word PIC24/dsPIC operations.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", k->dotfile); printf("ENVIRONMENT:\n" " K8048\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n"); printf(" k24 %ss%select\n" "\t\tDump supported devices.\n", UL_ON, UL_OFF); printf(" k24 %ss%select 33EP128GP502 OPERATION [ARG]\n" "\t\tSelect device dsPIC33EP128GP502.\n", UL_ON, UL_OFF); printf(" k24 %ss%select 24FJ128GB202 OPERATION [ARG]\n" "\t\tSelect device PIC24FJ128GB202.\n", UL_ON, UL_OFF); printf(" k24 %sl%svp OPERATION [ARG]\n" "\t\tLVP 32-bit key entry.\n", UL_ON, UL_OFF); printf(" k24 %sh%svp OPERATION [ARG]\n" "\t\tHVP 32-bit key entry.\n", UL_ON, UL_OFF); printf(" k24 %sb%slank\n" "\t\tBlank device (disable protection and bulk erase).\n", UL_ON, UL_OFF); printf(" k24 %sc%sonfig\n" "\t\tDisplay device configuration.\n", UL_ON, UL_OFF); printf(" k24 %sda%sta\n" "\t\tDisplay data EEPROM content.\n", UL_ON, UL_OFF); printf(" k24 %sd%sump\n" "\t\tDump device content (INHX32 format).\n", UL_ON, UL_OFF); printf(" k24 %sex%sec [n] [address]\n" "\t\tDisplay all or n words of executive flash content from address.\n", UL_ON, UL_OFF); printf(" k24 %sf%slash [n] [address]\n" "\t\tDisplay all or n words of program flash content from address.\n", UL_ON, UL_OFF); printf(" k24 %si%sd\n" "\t\tDisplay device identification.\n", UL_ON, UL_OFF); printf(" k24 %sp%srogram [file.hex] [noblank]\n" "\t\tBlank and program file.hex or stdin to flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" k24 %sv%serify [file.hex]\n" "\t\tVerify file.hex or stdin in flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" k24 %svi%sew [file.hex]\n" "\t\tView file.hex or stdin (INHX32 format).\n", UL_ON, UL_OFF); printf(" k24 /dev/ttyUSB0 | %s8%s048\n" "\t\tListen on /dev/ttyUSB0 or network for remote programming.\n", UL_ON, UL_OFF); printf("\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(k, EX_USAGE); io_exit(k, EX_OK); }
static void usage_p12(char *msg) { printf("USAGE: p12 SELECT DEVICE OPERATION [ARG]\n"); printf("12-bit word PIC10F/12F/16F operations.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", p.dotfile); printf("ENVIRONMENT:\n" " PICKLE\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n"); printf(" p12 %ss%select\n" "\t\tShow supported devices.\n", UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %sb%slank\n" "\t\tBlank device (disable protection and bulk erase).\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %sc%sonfig\n" "\t\tDisplay device configuration.\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %sda%sta\n" "\t\tDisplay data flash content.\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %sd%sump\n" "\t\tDump device content (INHX32 format).\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %sf%slash [n] [address]\n" "\t\tDisplay all or n words of program flash content from address.\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %si%sd\n" "\t\tDisplay device identification.\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %so%ssccal\n" "\t\tDisplay oscillator calibration.\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %so%ssccal 0x0c1a\n" "\t\tRestore oscillator calibration as 0x0c1a.\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %sp%srogram [file.hex] [noblank]\n" "\t\tBlank and program file.hex or stdin to flash (INHX32 format).\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %sv%serify [file.hex]\n" "\t\tVerify file.hex or stdin in flash (INHX32 format).\n", UL_ON, UL_OFF, UL_ON, UL_OFF); printf(" p12 %ss%select PIC1XFXXX %svi%sew [file.hex] [raw]\n" "\t\tView file.hex or stdin (INHX32 format).\n", UL_ON, UL_OFF, UL_ON, UL_OFF); #ifdef STK500 printf(" p12 %ss%select PIC1XFXXX /dev/ttyUSB0 | %s8%s048\n" "\t\tListen on /dev/ttyUSB0 or network for remote programming.\n", UL_ON, UL_OFF, UL_ON, UL_OFF); #endif printf("\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(EX_USAGE); io_exit(EX_OK); }
void usage(struct k8048 *k, char *execname, char *msg) { printf("USAGE: %s COMMAND [ARG]\n", execname); printf("ICSPIO operations.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("Commands:\n" " LED 0x00..0x3F Set Velleman K8048 LEDs.\n" " SWITCH Get Velleman K8048 switches.\n" " SLEEP Sleep until watchdog time-out.\n" " WATCHDOG E|D Set watchdog enable/disable.\n" " CLOCK 0..7 Set internal RC clock divider.\n" " DIRECTION A..D|G 0x00..0xFF Set port data direction.\n" " OUTPUT A..D|G 0x00..0xFF Set port data output.\n" " INPUT A..D|G Get port data input, output on stdout.\n" " ANALOG 0..N|D Set analog channel enable/disable.\n" " SAMPLE Get analog channel input.\n" " EEREAD 0x00..0xFF Get data EEPROM.\n" " EEWRITE 0x00..0xFF 0x00..0xFF Set data EEPROM.\n" " READ 0x0000..0xFFFF Get program flash.\n" " VREF 0..15|D Set vref voltage level or disable.\n" " 8 0..0xFF Send an 8-bit arg & get an 8-bit answer.\n" " 16 0..0xFFFF Send a 16-bit arg & get an 8-bit answer.\n" " 24 0..0xFFFFFF Send a 24-bit arg & get an 8-bit answer.\n" " 32 0..0xFFFFFFFF Send a 32-bit arg & get an 8-bit answer.\n" " TEST 0..0xFF Send an 8-bit test arg & get no reply.\n" " ERROR Get last firmware error.\n" "\n"); printf("FILES:\n" " %s\n" "\t\tConfiguration.\n\n", k->dotfile); printf("EXAMPLES:\n" " kio WATCHDOG D\n" "\t\tTurn off watchdog.\n" " kio DIRECTION C 0xF0\n" "\t\tSet port C bits 0..3 as output and bits 4..7 as input.\n" " kio OUTPUT C 0x0A\n" "\t\tSet port C bits 0..3 to 0x0A.\n\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(k, EX_USAGE); io_exit(k, EX_OK); }
static void usage_p32(char *msg) { printf("USAGE: p32 OPERATION [ARG]\n"); printf("32-bit word PIC32 operations.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", p.dotfile); printf("ENVIRONMENT:\n" " PICKLE\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n"); printf(" p32 %ss%select\n" "\t\tShow supported devices.\n", UL_ON, UL_OFF); printf(" p32 %sbo%sot [n] [address]\n" "\t\tDisplay all or n words of boot flash content from address.\n", UL_ON, UL_OFF); printf(" p32 %sb%slank\n" "\t\tBlank device (erase).\n", UL_ON, UL_OFF); printf(" p32 %sc%sonfig\n" "\t\tDisplay device configuration.\n", UL_ON, UL_OFF); printf(" p32 %sd%sump\n" "\t\tDump device content (INHX32 format).\n", UL_ON, UL_OFF); printf(" p32 %sf%slash [n] [address]\n" "\t\tDisplay all or n words of program flash content from address.\n", UL_ON, UL_OFF); printf(" p32 %si%sd\n" "\t\tDisplay device identification.\n", UL_ON, UL_OFF); printf(" p32 %sp%srogram [file.hex] [noblank]\n" "\t\tBlank and program file.hex or stdin to flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" p32 %sv%serify [file.hex]\n" "\t\tVerify file.hex or stdin in flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" p32 %svi%sew [file.hex] [raw]\n" "\t\tView file.hex or stdin (INHX32 format).\n", UL_ON, UL_OFF); #ifdef STK500 printf(" p32 /dev/ttyUSB0 | %s8%s048\n" "\t\tListen on /dev/ttyUSB0 or network for remote programming.\n", UL_ON, UL_OFF); #endif printf("\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(EX_USAGE); io_exit(EX_OK); }
/* * Stage 1: Input * * filename should either be `-' for `stdin' else an accessible * disk file. */ uint32_t inhx32_tree_input(void **root, const char *filename, uint32_t *count) { FILE *fp = stdin; uint32_t nbytes = 0; void *entry; pic_data *data; *count = 0; /* Open file or stdin */ if (strcmp(filename, "-") && (fp = fopen(filename, "rb")) == NULL) { printf("%s: error: fopen failed [%s] [%s]\n", __func__, filename, strerror(errno)); return 0; /* Empty */ } /* While not EOF, process data */ while ((data = inhx32_get(fp)) != NULL) { /* Detect duplicate data in tree */ entry = tfind((void *)data, root, inhx32_tree_compare); if (entry != NULL) { printf("%s: fatal error: duplicate address [%08X]\n", __func__, data->address); io_exit(EX_SOFTWARE); /* Panic */ } /* Add new data to tree */ entry = tsearch((void *)data, root, inhx32_tree_compare); if (entry == NULL) { printf("%s: fatal error: tsearch failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } /* Update counters */ (*count)++; nbytes += data->nbytes; } /* Close file or stdin */ if (strcmp(filename, "-")) fclose(fp); /* Information */ if (nbytes == 0) printf("%s: information: no valid input data\n", __func__); /* Return number of bytes */ return nbytes; }
void usage_ktest(struct k8048 *k, char *msg) { printf("USAGE: ktest TEST ARG\n"); printf("Hardware tests.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", k->dotfile); printf("ENVIRONMENT:\n" " K8048\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n" " ktest VPP|PGC|PGD|PGM 5\n" "\t\tVPP, PGC, PGD or PGM LOW->HIGH->LOW test with 5 seconds high time.\n" #ifdef RPI " ktest 0 10\n" "\t\tR-PI GPIO test with 10 seconds mark time.\n" #endif " ktest 1 10\n" "\t\tD-SUB-9 test with 10 seconds per step.\n" " ktest 2 10\n" "\t\tICSP test with 10 seconds per step.\n" " ktest 3 0\n" "\t\tD-SUB-9 RTS 7 (PGC) DTR 4 (PGD) test with no mark time.\n" " ktest 3 1\n" "\t\tD-SUB-9 RTS 7 (PGC) DTR 4 (PGD) test with SLEEP mark time.\n" " ktest 3 100\n" "\t\tD-SUB-9 RTS 7 (PGC) DTR 4 (PGD) test with 100 microseconds mark time.\n" " ktest 4 100\n" "\t\t16F627 debug test with 100 microseconds clock mark time.\n" #if defined(KTEST) && defined(KIO) " ktest 5 100\n" "\t\tICSPIO demo test with 100 microseconds clock mark time.\n" #endif "\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(k, EX_USAGE); io_exit(k, EX_OK); }
int main(int argc, char **argv) { int sd; struct sockaddr_in sin; io_init(); printf("Opening listening socket...\n"); if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } if(set_nonblock(sd) < 0) { perror("setnonblocking"); close(sd); exit(1); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(PORT); sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { perror("bind"); close(sd); exit(1); } if (listen(sd, STD_LISTEN_SIZE) == -1) { perror("listen"); close(sd); exit(1); } g_accepter.fd = sd; g_accepter.proc = accept_proc; if(io_add(&g_accepter, IO_READ) < 0) { perror("io_add_main"); close(sd); exit(1); } printf("Listening on port %d, fd %d.\n", PORT, g_accepter.fd); for(;;) { io_wait(MAXINT); } io_exit(); return 0; }
/* * Reset user */ void resetuid(struct k8048 *k) { if (getuid() != geteuid()) { if (setuid(getuid()) < 0) { printf("%s: fatal error: setuid failed\n", __func__); io_exit(k, EX_OSERR); /* Panic */ } } }
/* * READ PE FILE * * RETURNS BYTE POINTER OR NULL ON ERROR. * * WILL ADJUST FILE NAME WHEN ATTEMPTING TO CREATE CACHED HEX FILE (BIN) */ uint8_t * pic_pe_read_file(char *filename, uint32_t *nbytes) { int rc; struct stat st; uint8_t *pe; FILE *fp; char *s; if (strstr(filename, ".bin")) { rc = stat(filename, &st); if (rc < 0) { printf("%s: error: stat failed [%s]\n", __func__, filename); return NULL; } *nbytes = st.st_size; pe = (uint8_t *)calloc(*nbytes, sizeof(uint8_t)); if (pe == NULL) { printf("%s: fatal error: calloc failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } fp = fopen(filename, "rb"); if (fp == NULL) { printf("%s: error: fopen failed [%s]\n", __func__, filename); return NULL; } rc = fread((void *)pe, 1, *nbytes, fp); if (rc != *nbytes) { printf("%s: error: fread failed [%s]\n", __func__, filename); return NULL; } fclose(fp); } else { /* .hex */ s = strstr(filename, ".hex"); if (s == NULL) { return NULL; } *nbytes = inhx32_memory_create(&pe, filename); if (*nbytes == 0) { return NULL; } strcpy(s, ".bin"); fp = fopen(filename, "wb"); if (fp != NULL) { rc = fwrite((void *)pe, 1, *nbytes, fp); fclose(fp); if (rc != *nbytes) unlink(filename); } } return pe; }
void usage_kload(struct k8048 *k, char *msg) { printf("USAGE: kload PROGRAM|VERIFY TTY|IP FILE [AVR]\n"); printf("Program or verify file on TTY or network.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", k->dotfile); printf("ENVIRONMENT:\n" " K8048\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n" " kload program /dev/ttyS0 file.hex\n" "\t\tProgram file.hex (INHX32 format) on /dev/ttyS0.\n" " kload verify /dev/ttyS0 file.hex\n" "\t\tVerify file.hex (INHX32 format) on /dev/ttyS0.\n" " kload program 192.168.1.100 < led.hex\n" "\t\tProgram stdin (INHX32 format) on 192.168.1.100 port 8048.\n" " kload program /dev/ttyS0 - avr\n" "\t\tProgram stdin (INHX32 format) on /dev/ttyS0 (AVR bootloader).\n" " kload program /dev/ttyUSB0 unix.hex avr\n" "\t\tProgram unix.hex (INHX32 format) on /dev/ttyUSB0 (AVR bootloader).\n" "\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(k, EX_USAGE); io_exit(k, EX_OK); }
/* * Allocate array */ uint32_t inhx32_array_create(pic_data ***pdata, const char *filename, uint32_t *count) { FILE *fp; char tempname[] = "/tmp/inhx32.XXXXXX"; uint32_t nbytes, index = 0; pic_data *data; *count = 0; /* * Stage 1. */ /* Determine number of bytes and line count */ nbytes = inhx32_qsort_input(&fp, filename, tempname, count); if (nbytes == 0) return 0; /* Empty */ /* * Stage 2. */ /* Allocate array */ *pdata = (pic_data **)calloc(*count, sizeof(pic_data *)); if (*pdata == NULL) { printf("%s: fatal error: calloc failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } /* While not EOF, process data */ while ((data = inhx32_get(fp))) { (*pdata)[index++] = data; } fclose(fp); /* Remove any temporary file created in stage 1 */ if (tempname[0]) unlink(tempname); /* Quick sort array */ qsort(*pdata, *count, sizeof(pic_data *), inhx32_array_compare); /* Return number of bytes */ return nbytes; }
/* * Free tree (entries and/or data) */ void inhx32_tree_free(void **root, int flag) { void *entry; pic_data *data; while ((entry = tfind(NULL, root, inhx32_tree_match))) { data = *(pic_data **)entry; tdelete(data, root, inhx32_tree_match); if (flag) free(data); } if (*root != NULL) { printf("%s: fatal error: tree free failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } }
/* * Allocate memory */ uint32_t inhx32_memory_create(uint8_t **pmem, const char *filename) { FILE *fp; char tempname[] = "/tmp/inhx32.XXXXXX"; uint32_t nbytes, count = 0, index = 0; pic_data *data; uint8_t i; /* * Stage 1. */ /* Determine number of bytes and line count */ nbytes = inhx32_qsort_input(&fp, filename, tempname, &count); if (nbytes == 0) return 0; /* Empty */ /* * Stage 2. */ /* Allocate memory */ *pmem = (uint8_t *)calloc(nbytes, sizeof(uint8_t)); if (*pmem == NULL) { printf("%s: fatal error: calloc failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } /* While not EOF, process data */ while ((data = inhx32_get(fp))) { for (i = 0; i < data->nbytes; ++i) (*pmem)[index++] = data->bytes[i]; } fclose(fp); /* Remove any temporary file created in stage 1 */ if (tempname[0]) unlink(tempname); /* Return number of bytes */ return nbytes; }
/* * ======== api_exit ======== */ void api_exit(void) { DBC_REQUIRE(api_c_refs > 0); api_c_refs--; if (api_c_refs == 0) { /* Release all modules initialized in api_init(). */ cod_exit(); dev_exit(); chnl_exit(); msg_exit(); io_exit(); strm_exit(); disp_exit(); node_exit(); proc_exit(); mgr_exit(); rmm_exit(); drv_exit(); } DBC_ENSURE(api_c_refs >= 0); }
/* * Get data * * Returns with either a data record or NULL for EOF */ pic_data * inhx32_get(FILE *fp) { char line[STRLEN]; uint8_t bb, tt; uint16_t aaaa, ix, i; static uint16_t extended_addr = 0; pic_data *data; do { /* Get line */ if (inhx32_fgets(line, fp, &bb, &aaaa, &tt, &extended_addr) == NULL) return NULL; /* EOF */ if (tt == TT_EOF) return NULL; /* EOF */ } while (tt != TT_DATA); /* Not a data record */ /* Allocate data */ data = (pic_data *)calloc(1, sizeof(pic_data)); if (data == NULL) { printf("%s: fatal error: calloc failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } /* Store address and number of bytes */ data->address = (extended_addr << 16) | aaaa; data->nbytes = bb; /* Extract and store bytes */ ix = HHHH; for (i = 0; i < bb; ++i) { data->bytes[i] = hex2byte(&line[ix]); ix += 2; } /* Return data */ return data; }
/* * Allocate array */ uint32_t inhx32_array_create(pic_data ***pdata, const char *filename, uint32_t *count) { uint32_t nbytes; void *root = NULL; /* * Stage 1. */ /* Create tree */ nbytes = inhx32_tree_input(&root, filename, count); if (nbytes == 0) return 0; /* Empty */ /* * Stage 2. */ /* Allocate array */ *pdata = (pic_data **)calloc(*count, sizeof(pic_data *)); if (*pdata == NULL) { printf("%s: fatal error: calloc failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } /* Populate array */ inhx32_pdata = *pdata; inhx32_index = 0; twalk(root, inhx32_array_walk); /* Free tree (entries, not data) */ inhx32_tree_free(&root, 0); /* Return number of bytes */ return nbytes; }
/* * Allocate memory */ uint32_t inhx32_memory_create(uint8_t **pmem, const char *filename) { uint32_t nbytes, count = 0; void *root = NULL; /* * Stage 1. */ /* Create tree */ nbytes = inhx32_tree_input(&root, filename, &count); if (nbytes == 0) return 0; /* Empty */ /* * Stage 2. */ /* Allocate memory */ *pmem = (uint8_t *)calloc(nbytes, sizeof(uint8_t)); if (*pmem == NULL) { printf("%s: fatal error: calloc failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } /* Populate memory */ inhx32_pmem = *pmem; inhx32_index = 0; twalk(root, inhx32_memory_walk); /* Free tree (entries and data) */ inhx32_tree_free(&root, 1); /* Return number of bytes */ return nbytes; }
/* * Dot file */ void getdotfile(void) { char *filename = getenv("PICKLE"); if (filename != NULL) { snprintf(p.dotfile, STRLEN, "%s", filename); if (getdotpath() == 0) return; } char dir[STRLEN]; if (getcwd(dir, STRLEN) == NULL) { printf("%s: fatal error: getcwd failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } snprintf(p.dotfile, STRLEN, "%s/%s", dir, DOTFILENAME); if (getdotpath() == 0) return; char *homedir = getenv("HOME"); if (homedir != NULL) { snprintf(p.dotfile, STRLEN, "%s/%s", homedir, DOTFILENAME); if (getdotpath() == 0) return; } char *username = getenv("USER"); if (username != NULL) { snprintf(p.dotfile, STRLEN, "/home/%s/%s", username, DOTFILENAME); if (getdotpath() == 0) return; } /* No dot file found */ p.dotfile[0] = '\0'; }
/* * LOOK UP PE FILE NAME */ int pic_pe_lookup_file(char *pathname, const char *filename) { if (p.etc[0]) { snprintf(pathname, STRLEN, "%s/%s", p.etc, filename); if (access(pathname, R_OK) == 0) return 0; } char *dotdup = (char *)strdup(p.dotfile); if (dotdup == NULL) { printf("%s: fatal error: strdup failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } char *dname = dirname(dotdup); snprintf(pathname, STRLEN, "%s/%s", dname, filename); free(dotdup); if (access(pathname, R_OK) == 0) return 0; bzero(pathname, STRLEN); return -1; }
/* * Format parser * * Return program data line count */ uint32_t inhx32(struct k8048 *k, const char *filename, uint32_t alignment) { FILE *f1 = stdin; char line[STRLEN]; uint32_t extended_address = 0, bb, ix; uint8_t tt = TT_DATA, cc; uint16_t aaaa; void *root = NULL; inhx32_data *data = NULL; k->count = 0; k->pdata = NULL; if (strcmp(filename, "-") && (f1 = fopen(filename, "rb")) == NULL) { printf("%s: error: file open failed [%s] [%s]\n", __func__, filename, strerror(errno)); return 0; } #ifdef DEBUG if (k->debug >= 100) { printf("FILE [%s]\n", filename); } #endif while (tt != TT_EOF && fgets(line, STRLEN, f1) != NULL) { line[STRMAX] = '\0'; /* Strip CRLF */ int n = strlen(line) - 1; while (n >= 0 && (line[n] == '\n' || line[n] == '\r')) line[n--] = '\0'; /* Validate line prefix and length */ if (line[0] != ':' || (strlen(line) & 1) == 0 || strlen(line) < 11) { if (k->debug >= 10) { printf("%s: warning: ignoring malformed line [%s] invalid format\n", __func__, line); } continue; } /* Validate checksum */ cc = 0; for (n = 1; line[n]; n += 2) cc += inhx32_gethexb(&line[n]); if (cc != 0) { if (k->debug >= 10) { printf("%s: warning: ignoring malformed line [%s] invalid checksum [%02X]\n", __func__, line, cc); } continue; } /* Determine number of data bytes in this line */ bb = inhx32_gethexb(&line[BB]); /* Validate line length */ if (strlen(line) != (2 * bb + 11)) { if (k->debug >= 10) { printf("%s: warning: ignoring malformed line [%s] invalid length [%zu != %u] (BB=0x%02x)\n", __func__, line, strlen(line), 2 * bb + 11, bb); } continue; } /* Determine data address for this line */ aaaa = (inhx32_gethexb(&line[AAAA]) << 8) | inhx32_gethexb(&line[AAAA + 2]); /* Determine record type */ tt = inhx32_gethexb(&line[TT]); switch (tt) { case TT_DATA: if (bb == 0) { if (k->debug >= 10) { printf("%s: warning: ignoring empty line [%s]\n", __func__, line); } break; } if (bb % alignment) { if (k->debug >= 10) { printf("%s: warning: ignoring line with incomplete word [%s]\n", __func__, line); } break; } /* Allocate new array entry for this line */ data = (inhx32_data *)calloc(1, sizeof(inhx32_data)); if (data == NULL) { printf("%s: fatal error: calloc failed\n", __func__); io_exit(k, EX_OSERR); /* Panic */ } /* Increment line counter */ k->count++; /* Save address and word count */ data->address = extended_address | aaaa; data->nbytes = bb; /* Extract data */ ix = HHHH; for (n = 0; n < bb; n++) { data->bytes[n] = inhx32_gethexb(&line[ix]); ix += 2; } #ifdef DEBUG if (k->debug >= 100) { printf("AAAA=%04X BB=%02X ADDR=%06X >> %06X ", aaaa, bb, data->address, data->address >> 1); for (n = 0; n < bb; n++) { printf("%02X ", data->bytes[n]); } putchar('\n'); } #endif /* Find entry in tree */ if (tfind((void *)(data), (void **)(&root), inhx32_compare) != NULL) { printf("%s: fatal error: duplicate address [%08X]\n", __func__, data->address); io_exit(k, EX_SOFTWARE); /* Panic */ } /* Add entry into tree */ if (tsearch((void *)(data), (void **)(&root), inhx32_compare) == NULL) { printf("%s: fatal error: tsearch failed\n", __func__); io_exit(k, EX_OSERR); /* Panic */ } break; case TT_EOF: break; case TT_EXTENDED_LINEAR_ADDRESS: if (aaaa == 0 && bb == 2) { extended_address = (inhx32_gethexb(&line[HHHH]) << 24) | (inhx32_gethexb(&line[HHHH + 2]) << 16); #ifdef DEBUG if (k->debug >= 100) { printf("AAAA=%04X BB=%02X ADDR=%06X\n", aaaa, bb, extended_address); } #endif } else { printf("%s: warning: ignoring invalid extended linear address [aaaa=%04X, bb=%d]\n", __func__, aaaa, bb); } break; case TT_EXTENDED_SEGMENT_ADDRESS: printf("%s: warning: ignoring unhandled extended segment address\n", __func__); break; case TT_START_LINEAR_ADDRESS: printf("%s: warning: ignoring unhandled start linear address\n", __func__); break; case TT_START_SEGMENT_ADDRESS: printf("%s: warning: ignoring unhandled start segment address\n", __func__); break; default: printf("%s: warning: ignoring unknown record type [%d]\n", __func__, tt); break; } }
int main(int argc, char ** argv) { int i; int mode = 0; if (argc == 2) { mode = argv[1][0] - '0'; if (mode < 0 || mode > 4) { mode = 0; } } //mode: // 0x00 D9 켜기 // 0x01 D8 켜기 // 0x02 D8 켜기, D10 블링킹 io_init(); for (i = 0; i < sizeof(pinmaps)/sizeof(struct led_pinmap); i++) { alt(pinmaps[i].module, pinmaps[i].bit, 0); dir(pinmaps[i].module, pinmaps[i].bit, 1); pinmaps[i].value = 1; output(pinmaps[i].module, pinmaps[i].bit, pinmaps[i].value); } // Init switch(mode) { case 0: pinmaps[2].value = 0; output(pinmaps[2].module, pinmaps[2].bit, pinmaps[2].value); break; case 1: pinmaps[0].value = 0; output(pinmaps[0].module, pinmaps[0].bit, pinmaps[0].value); break; case 2: pinmaps[0].value = 0; output(pinmaps[0].module, pinmaps[0].bit, pinmaps[0].value); break; } // Blinking while (1) { switch(mode) { case 1: break; case 2: pinmaps[1].value = !pinmaps[1].value; output(pinmaps[1].module, pinmaps[1].bit, pinmaps[1].value); break; case 3: break; } usleep(500 * 1000); } io_exit(); return 0; }
/* * Open device and perform command */ int main(int argc, char **argv) { struct k8048 k; char *execdup, *execname; /* Initialise to NULL/0 */ memset(&k, 0, sizeof(k)); /* Get exec name */ execdup = (char *)strdup(argv[0]); if (execdup == NULL) { printf("%s: fatal error: strdup failed\n", __func__); io_exit(&k, EX_OSERR); /* Panic */ } execname = basename(execdup); if (execname == NULL) { printf("%s: fatal error: basename failed\n", __func__); io_exit(&k, EX_OSERR); /* Panic */ } /* Get configuration */ getconf(&k); /* Command: k8048 */ if (strcmp(execname, "k8048") == 0) { resetuid(&k); usage_k8048(&k); } #ifdef TTY /* Command: kload */ if (strcmp(execname, "kload") == 0) { resetuid(&k); if (argc < 3) usage_kload(&k, "Missing arg"); if (argc > 5) usage_kload(&k, "Too many args"); int prog_mode = tolower((int)argv[1][0]); if (prog_mode != 'p' && prog_mode != 'v') usage_kload(&k, "Invalid mode"); if (argv[2][0] == '/' && strstr(argv[2], "/dev/tty") != argv[2]) usage_kload(&k, "Invalid tty"); char file[STRLEN]; strcpy(file, "-"); if (argc >= 4) strncpy(file, argv[3], STRMAX); int target = 'n'; if (argc == 5) { target = tolower((int)argv[4][0]); if (target != 'a') usage_kload(&k, "Invalid target"); } io_signal_on(k); // !SIGPIPE stk500v2_load(&k, prog_mode, argv[2], file, target); io_exit(&k, EX_OK); } #endif /* Open device */ if (io_open(&k) < 0) { #ifdef KTEST if (strcmp(execname, "ktest") == 0) usage_ktest(&k, io_error(&k)); #endif usage(&k, execname, io_error(&k)); } /* Raise priority */ setpriority(PRIO_PROCESS, 0, -20); /* Reset user */ resetuid(&k); #ifdef KCTRL /* Command: kctrl */ if (strcmp(execname, "kctrl") == 0) { if (argc < 2) usage_kctrl(&k, "Missing arg"); if (argc > 2) usage_kctrl(&k, "Too many args"); if (strcasecmp(argv[1], "RUN") == 0) { io_close(&k, HIGH); printf("RUN\n"); } else if (strcasecmp(argv[1], "STOP") == 0) { io_close(&k, LOW); printf("STOP\n"); } else if (strcasecmp(argv[1], "RESTORE") == 0) { io_set_vpp(&k, LOW); io_usleep(&k, 10); io_close(&k, HIGH); printf("RESTORE\n"); } io_exit(&k, EX_OK); } #endif #ifdef KTEST /* Command: ktest */ if (strcmp(execname, "ktest") == 0) { if (argc < 3) usage_ktest(&k, "Missing args"); if (argc > 3) usage_ktest(&k, "Too many args"); int32_t testarg = strtol(argv[2], NULL, 0); if (testarg < 0) usage_ktest(&k, "Invalid arg"); if (strcasecmp(argv[1], "VPP") == 0) io_test0(&k, 0, testarg); else if (strcasecmp(argv[1], "PGC") == 0) io_test0(&k, 1, testarg); else if (strcasecmp(argv[1], "PGD") == 0) io_test0(&k, 2, testarg); else if (strcasecmp(argv[1], "PGM") == 0) io_test0(&k, 3, testarg); else if (argv[1][0] >= '0' && argv[1][0] <= '9') { int32_t test = strtol(argv[1], NULL, 0); switch (test) { #ifdef RPI case 0: gpio_test(&k, testarg);break; #endif case 1: io_test1(&k, testarg); break; case 2: io_test2(&k, testarg); break; case 3: io_test3(&k, testarg); break; case 4: io_test4(&k, testarg); break; #if defined(KTEST) && defined(KIO) case 5: io_test5(&k, testarg); break; #endif default:usage_ktest(&k, "Invalid arg");break; } } else { usage_ktest(&k, "Invalid arg"); } io_exit(&k, EX_OK); } #endif /* Determine arch: k12 | k14 | k16 | k24 | k32 */ if (pic_arch(&k, execname) == 0) usage_k8048(&k); if (argc < 2) usage(&k, execname, "Missing arg(s)"); /* Device selection */ int argv1 = tolower((int)argv[1][0]); if (argv1 == 's') { /* Select device */ if (argc < 3) { pic_selector(&k); io_exit(&k, EX_OK); } if (mystrcasestr(argv[2], "dspic") == argv[2]) { strncpy(k.devicename, argv[2], STRLEN); } else if (mystrcasestr(argv[2], "pic") == argv[2]) { strncpy(k.devicename, argv[2], STRLEN); } else { int32_t temp = strtol(argv[2], NULL, 0); if (temp < 10 || temp > 33) { usage(&k, execname, "Invalid arg [select]"); } if (temp == 30 || temp == 33) { strcpy(k.devicename, "dspic"); strncpy(&k.devicename[5], argv[2], STRLEN - 5); } else { strcpy(k.devicename, "pic"); strncpy(&k.devicename[3], argv[2], STRLEN - 3); } } argc -= 2; argv += 2; if (argc < 2) usage(&k, execname, "Missing arg(s)"); } else if (k.pic->arch == ARCH12BIT) { usage(&k, execname, "Missing select"); } /* Key entry */ argv1 = tolower((int)argv[1][0]); if (argv1 == 'l') { /* LVP 32-bit key entry */ if (k.pic->arch == ARCH12BIT) { usage(&k, execname, "Invalid arg [lvp]"); } /* ARCH14BIT || ARCH16BIT || ARCH24BIT || ARCH32BIT */ k.key = LVPKEY; argc -= 1; argv += 1; if (argc < 2) usage(&k, execname, "Missing arg(s)"); } else if (argv1 == 'h') { /* HVP 32-bit key entry */ if (k.pic->arch == ARCH12BIT || k.pic->arch == ARCH14BIT || k.pic->arch == ARCH32BIT) { usage(&k, execname, "Invalid arg [hvp]"); } /* ARCH16BIT || ARCH24BIT */ k.key = HVPKEY; argc -= 1; argv += 1; if (argc < 2) usage(&k, execname, "Missing arg(s)"); } else if (k.pic->arch == ARCH32BIT) { /* LVP 32-bit key entry */ /* ARCH32BIT */ k.key = LVPKEY; } else { /* No key entry */ /* ARCH12BIT || ARCH14BIT || ARCH16BIT || ARCH24BIT */ k.key = NOKEY; } /* Command */ argv1 = tolower((int)argv[1][0]); int argv11 = tolower((int)argv[1][1]); switch (argv1) { case 'b': if (argv11 == 'o') { /* BOOT */ uint32_t addr = UINT32_MAX, words = UINT32_MAX; if (argc > 4) usage(&k, execname, "Too many args [boot]"); if (argc >= 3) { words = strtoul(argv[2], NULL, 0); if (words == 0) usage(&k, execname, "Invalid arg [boot]"); } if (argc == 4) { addr = strtoul(argv[3], NULL, 0); } pic_dumpboot(&k, addr, words); } else { /* BLANK */ if (argc > 2) usage(&k, execname, "Too many args [blank]"); if (areyousure("Blank device")) pic_blank(&k); } break; case 'c': if (argc > 3) usage(&k, execname, "Too many args [config]"); if (argc == 2) pic_dumpconfig(&k); else pic_writebandgap(&k, strtoul(argv[2], NULL, 0)); break; case 'd': if (argv11 == 'a') { /* DATA */ if (argc > 2) usage(&k, execname, "Too many args [data]"); pic_dumpdata(&k); } else if (argv11 == 'e') { /* DEBUG */ printf("Hello world!\n"); } else { /* DUMP */ if (argc > 2) usage(&k, execname, "Too many args [dump]"); pic_dumpdevice(&k); } break; case 'e': if (argv11 == 'r') { /* ERASE FLASH | ID | ROW[NROWS] */ uint32_t row = 0, nrows = 1; char prompt[STRLEN] = {0}, *endptr = NULL; if (argc < 3) usage(&k, execname, "Missing arg [erase]"); if (argc > 4) usage(&k, execname, "Too many args [erase]"); int argv2 = tolower((int)argv[2][0]); switch (argv2) { case 'i': /* IDLOCATION */ case 'u': /* USERID/CONFIG */ row = PIC_ERASE_ID; strncpy(prompt, "Erase id", STRLEN); break; case 'c': /* CONFIG */ row = PIC_ERASE_CONFIG; strncpy(prompt, "Erase config", STRLEN); break; case 'e': /* EEPROM */ row = PIC_ERASE_EEPROM; strncpy(prompt, "Erase EEPROM", STRLEN); break; case 'f': /* FLASH */ nrows = UINT32_MAX; strncpy(prompt, "Erase program flash", STRLEN); break; default: /* FLASH ROW */ row = strtoul(argv[2], &endptr, 0); if (endptr == argv[2]) usage(&k, execname, "Invalid arg [erase]"); if (argc == 4) { nrows = strtoul(argv[3], NULL, 0); if (nrows == 0) usage(&k, execname, "Invalid arg [erase]"); } snprintf(prompt, STRLEN, "Erase %u row(s) at row %u", nrows, row); break; } if (areyousure(prompt)) pic_erase(&k, row, nrows); } else if (argv11 == 'x') { /* EXECUTIVE */ uint32_t addr = UINT32_MAX, words = UINT32_MAX; if (argc > 4) usage(&k, execname, "Too many args [executive]"); if (argc >= 3) { words = strtoul(argv[2], NULL, 0); if (words == 0) usage(&k, execname, "Invalid arg [executive]"); } if (argc == 4) { addr = strtoul(argv[3], NULL, 0); } pic_dumpexec(&k, addr, words); } else { /* EEPROM */ if (argc > 2) usage(&k, execname, "Too many args [eeprom]"); pic_dumpdata(&k); } break; case 'f': { uint32_t words = UINT32_MAX, addr = UINT32_MAX; if (argc > 4) usage(&k, execname, "Too many args [program flash]"); if (argc >= 3) { words = strtoul(argv[2], NULL, 0); if (words == 0) usage(&k, execname, "Invalid arg [program flash]"); } if (argc == 4) { addr = strtoul(argv[3], NULL, 0); } pic_dumpprogram(&k, addr, words); } break; case 'i': if (argc > 2) usage(&k, execname, "Too many args [id]"); pic_dumpdeviceid(&k); break; case 'o': if (argc > 3) usage(&k, execname, "Too many args [osccal]"); if (argc == 2) pic_dumposccal(&k); else pic_writeosccal(&k, strtoul(argv[2], NULL, 0)); break; case 'p': { int blank = 1; if (argc > 4) usage(&k, execname, "Too many args [program]"); if (argc == 4) switch (argv[3][0]) { case 'n': case 'N': case '0': blank = 0; break; case 'y': case 'Y': case '1': blank = 1; break; default:usage(&k, execname, "Invalid arg [program]"); break; } if (argc < 3) pic_program(&k, "-", 1); else pic_program(&k, argv[2], blank); } break; case 'v': if (argv11 == 'i') { /* VIEW */ if (argc > 3) usage(&k, execname, "Too many args [view]"); if (argc < 3) pic_view(&k, "-"); else pic_view(&k, argv[2]); } else { /* VERIFY */ if (argc > 3) usage(&k, execname, "Too many args [verify]"); if (argc < 3) pic_verify(&k, "-"); else pic_verify(&k, argv[2]); } break; #ifdef TTY case '/': if (strstr(argv[1], "/dev/tty") != argv[1]) { usage(&k, execname, "Invalid device [TTY]"); } if (strstr(argv[1], k.device) != NULL) { usage(&k, execname, "Device in use [TTY]"); } stk500v2_listen(&k, argv[1], 0); break; case '8': stk500v2_listen(&k, "0.0.0.0", 8048); break; #endif default: usage(&k, execname, "Unknown operation"); break; } free(execdup); io_exit(&k, EX_OK); }
/* * Open device and perform command */ int main(int argc, char **argv) { char *execdup, *execname; int rc = EX_OK; /* Get exec name */ execdup = (char *)strdup(argv[0]); if (execdup == NULL) { printf("%s: fatal error: strdup failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } execname = basename(execdup); if (execname == NULL) { printf("%s: fatal error: basename failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } /* Get configuration */ getconf(); /* Open device */ if (io_open() < 0) { usage(execname, io_error()); } /* Raise priority */ setpriority(PRIO_PROCESS, 0, -20); /* Reset uid */ if (getuid() != geteuid()) { if (setuid(getuid()) < 0) { printf("%s: fatal error: setuid failed\n", __func__); io_exit(EX_OSERR); /* Panic */ } } /* Determine arch: 12 | 14 | 16 | 24 | 32 */ if (pic_arch(execname) == 0) usage_pickle(); /* Perform operation */ if (argc < 2) usage(execname, "Missing arg(s)"); /* Device selection */ int argv1 = tolower((int)argv[1][0]); if (argv1 == 's') { /* Select device */ if (argc < 3) { pic_selector(); io_exit(EX_OK); } if (mystrcasestr(argv[2], "dspic") == argv[2]) { strncpy(p.devicename, argv[2], STRLEN); } else if (mystrcasestr(argv[2], "pic") == argv[2]) { strncpy(p.devicename, argv[2], STRLEN); } else { int32_t temp = strtol(argv[2], NULL, 0); if (temp < 10 || temp > 33) { usage(execname, "Invalid arg [select]"); } if (temp == 30 || temp == 33) { strcpy(p.devicename, "dspic"); strncpy(&p.devicename[5], argv[2], STRLEN - 5); } else { strcpy(p.devicename, "pic"); strncpy(&p.devicename[3], argv[2], STRLEN - 3); } } argc -= 2; argv += 2; if (argc < 2) usage(execname, "Missing arg(s)"); } else if (p.pic->arch == ARCH12BIT) { usage(execname, "Missing select"); } /* Key entry */ argv1 = tolower((int)argv[1][0]); if (argv1 == 'l') { /* LVP 32-bit key entry */ if (p.pic->arch == ARCH12BIT) { usage(execname, "Invalid arg [lvp]"); } /* ARCH14BIT || ARCH16BIT || ARCH24BIT || ARCH32BIT */ p.key = LVPKEY; argc -= 1; argv += 1; if (argc < 2) usage(execname, "Missing arg(s)"); } else if (argv1 == 'h') { /* HVP 32-bit key entry */ if (p.pic->arch == ARCH12BIT || p.pic->arch == ARCH14BIT || p.pic->arch == ARCH32BIT) { usage(execname, "Invalid arg [hvp]"); } /* ARCH16BIT || ARCH24BIT */ p.key = HVPKEY; argc -= 1; argv += 1; if (argc < 2) usage(execname, "Missing arg(s)"); } else if (p.pic->arch == ARCH32BIT) { /* LVP 32-bit key entry */ /* ARCH32BIT */ p.key = LVPKEY; } else { /* No key entry */ /* ARCH12BIT || ARCH14BIT || ARCH16BIT || ARCH24BIT */ p.key = NOKEY; } /* Command */ argv1 = tolower((int)argv[1][0]); int argv11 = tolower((int)argv[1][1]); switch (argv1) { case 'b': if (argv11 == 'o') { /* BOOT */ uint32_t addr = UINT32_MAX, words = UINT32_MAX; if (argc > 4) usage(execname, "Too many args [boot]"); if (argc >= 3) { words = strtoul(argv[2], NULL, 0); if (words == 0) usage(execname, "Invalid arg [boot]"); } if (argc == 4) { addr = strtoul(argv[3], NULL, 0); } pic_dumpboot(addr, words); } else { /* BLANK */ int config = 1; if (argc > 3) usage(execname, "Too many args [blank]"); if (argc == 3) switch (argv[2][0]) { case 'n': case 'N': case '0': config = 0; break; case 'y': case 'Y': case '1': config = 1; break; default:usage(execname, "invalid arg [blank]"); break; } if (areyousure("Blank device")) { pic_blank(config); } } break; case 'c': if (argc > 3) usage(execname, "Too many args [config]"); if (argc == 2) pic_dumpconfig(); else pic_writebandgap(strtoul(argv[2], NULL, 0)); break; case 'd': if (argv11 == 'a') { /* DATA */ if (argc > 2) usage(execname, "Too many args [data]"); pic_dumpdata(); } else if (argv11 == 'e') { /* DEBUG */ pic_debug(); } else { /* DUMP */ if (argc > 2) usage(execname, "Too many args [dump]"); pic_dumpdevice(); } break; case 'e': if (argv11 == 'r') { /* ERASE FLASH | ID | ROW[NROWS] */ uint32_t row = 0, nrows = 1; char prompt[STRLEN] = {0}, *endptr = NULL; if (argc < 3) usage(execname, "Missing arg [erase]"); if (argc > 4) usage(execname, "Too many args [erase]"); int argv2 = tolower((int)argv[2][0]); switch (argv2) { case 'i': /* IDLOCATION */ case 'u': /* USERID/CONFIG */ row = PIC_ERASE_ID; strncpy(prompt, "Erase id", STRLEN); break; case 'c': /* CONFIG */ row = PIC_ERASE_CONFIG; strncpy(prompt, "Erase config", STRLEN); break; case 'e': /* EEPROM */ row = PIC_ERASE_EEPROM; strncpy(prompt, "Erase EEPROM", STRLEN); break; case 'f': /* FLASH */ nrows = UINT32_MAX; strncpy(prompt, "Erase program flash", STRLEN); break; default: /* FLASH ROW */ row = strtoul(argv[2], &endptr, 0); if (endptr == argv[2]) usage(execname, "Invalid arg [erase]"); if (argc == 4) { nrows = strtoul(argv[3], NULL, 0); if (nrows == 0) usage(execname, "Invalid arg [erase]"); } snprintf(prompt, STRLEN, "Erase %u row(s) at row %u", nrows, row); break; } if (areyousure(prompt)) pic_erase(row, nrows); } else if (argv11 == 'x') { /* EXECUTIVE */ uint32_t addr = UINT32_MAX, words = UINT32_MAX; if (argc > 4) usage(execname, "Too many args [executive]"); if (argc >= 3) { words = strtoul(argv[2], NULL, 0); if (words == 0) usage(execname, "Invalid arg [executive]"); } if (argc == 4) { addr = strtoul(argv[3], NULL, 0); } pic_dumpexec(addr, words); } else { /* EEPROM */ if (argc > 2) usage(execname, "Too many args [eeprom]"); pic_dumpdata(); } break; case 'f': { uint32_t words = UINT32_MAX, addr = UINT32_MAX; if (argc > 4) usage(execname, "Too many args [program flash]"); if (argc >= 3) { words = strtoul(argv[2], NULL, 0); if (words == 0) usage(execname, "Invalid arg [program flash]"); } if (argc == 4) { addr = strtoul(argv[3], NULL, 0); } pic_dumpprogram(addr, words); } break; case 'i': if (argc > 2) usage(execname, "Too many args [id]"); pic_dumpdeviceid(); break; case 'o': if (argc > 3) usage(execname, "Too many args [osccal]"); if (argc == 2) pic_dumposccal(); else pic_writeosccal(strtoul(argv[2], NULL, 0)); break; case 'p': { int blank = 1; if (argc > 4) usage(execname, "Too many args [program]"); if (argc == 4) switch (argv[3][0]) { case 'n': case 'N': case '0': blank = 0; break; case 'y': case 'Y': case '1': blank = 1; break; default:usage(execname, "invalid arg [program]"); break; } if (argc < 3) pic_program("-", 1); else pic_program(argv[2], blank); } break; case 'v': if (argv11 == 'i') { /* VIEW */ int raw = 0; if (argc > 4) usage(execname, "Too many args [view]"); if (argc == 4) switch (argv[3][0]) { case 'r': case 'R': raw = 1; break; default:usage(execname, "invalid arg [view]"); break; } if (argc < 3) pic_view("-", 0); else pic_view(argv[2], raw); } else { /* VERIFY */ if (argc > 3) usage(execname, "Too many args [verify]"); if (argc < 3) rc = 0 - pic_verify("-"); else rc = 0 - pic_verify(argv[2]); } break; #ifdef TTY case '/': if (strstr(argv[1], "/dev/tty") != argv[1]) { usage(execname, "Invalid device [TTY]"); } if (strstr(argv[1], p.device) != NULL) { usage(execname, "Device in use [TTY]"); } stk500v2_listen(argv[1], 0); break; case '8': stk500v2_listen("0.0.0.0", 8048); break; #endif default: usage(execname, "Unknown operation"); break; } free(execdup); io_exit(rc); }
/* * k8048 help */ void usage_k8048(struct k8048 *k) { printf("USAGE: k8048\n"); printf("Usage information.\n\n"); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", k->dotfile); printf("FRONTENDS:\n" " FILE\n" "\t\tFile input (INHX32 format).\n" " STDIN\n" "\t\tStandard input (INHX32 format).\n" #ifdef TTY " TTY\n" "\t\tPOSIX serial I/O.\n" #endif "\n"); printf("BACKENDS:\n" #ifdef BITBANG " BIT-BANG\n" "\t\tLinux GPIO bit-bang.\n" #endif #ifdef MCP23017 " MCP23017\n" "\t\tLinux MCP23017 I2C.\n" #endif #ifdef RPI " RPI\n" "\t\tRaspberry Pi GPIO.\n" #endif #ifdef TTY " TTY\n" "\t\tPOSIX serial I/O.\n" #endif "\n"); printf("ENVIRONMENT:\n" " K8048\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n" #ifdef K12 " k12 SELECT DEVICE OPERATION [ARG]\n" "\t\t12-bit word PIC10F/12F/16F operations.\n" #endif #ifdef K14 " k14 [SELECT DEVICE] [LVP] OPERATION [ARG]\n" "\t\t14-bit word PIC10F/12F/16F operations.\n" #endif #ifdef K16 " k16 [SELECT DEVICE] [LVP|HVP] OPERATION [ARG]\n" "\t\t16-bit word PIC18F operations.\n" #endif #ifdef K24 " k24 [SELECT DEVICE] [LVP|HVP] OPERATION [ARG]\n" "\t\t24-bit word PIC24/dsPIC operations.\n" #endif #ifdef K32 " k32 OPERATION [ARG]\n" "\t\t32-bit word PIC32 operations.\n" #endif #ifdef KCTRL " kctrl RUN|STOP|RESTORE\n" "\t\tControl master clear.\n" #endif #ifdef TTY " kload PROGRAM|VERIFY TTY|IP FILE [AVR]\n" "\t\tProgram or verify file on TTY or network.\n" #endif #ifdef KTEST " ktest TEST [ARG]\n" "\t\tHardware tests.\n" #endif "\n"); printf("VERSION:\n %s\n", VERSION); io_exit(k, EX_OK); }
void usage_k14(struct k8048 *k, char *msg) { printf("USAGE: k14 [SELECT DEVICE] [LVP] OPERATION [ARG]\n"); printf("14-bit word PIC10F/12F/16F operations.\n\n"); if (msg) printf("Error: %s.\n\n", msg); printf("FILES:\n" " %s\n" "\t\tConfiguration file.\n\n", k->dotfile); printf("ENVIRONMENT:\n" " K8048\n" "\t\tConfiguration file.\n\n"); printf("EXAMPLES:\n"); printf(" k14 %ss%select\n" "\t\tDump supported devices.\n", UL_ON, UL_OFF); printf(" k14 %ss%select 16F84 OPERATION [ARG]\n" "\t\tSelect device PIC16F84.\n", UL_ON, UL_OFF); printf(" k14 %sl%svp OPERATION [ARG]\n" "\t\tLVP 32-bit key entry.\n", UL_ON, UL_OFF); printf(" k14 %sb%slank\n" "\t\tBlank device (disable protection and bulk erase).\n", UL_ON, UL_OFF); printf(" k14 %sc%sonfig\n" "\t\tDisplay device configuration.\n", UL_ON, UL_OFF); printf(" k14 %sc%sonfig 0x3000\n" "\t\tRestore band-gap configuration as 0x3000.\n", UL_ON, UL_OFF); printf(" k14 %sda%sta\n" "\t\tDisplay data EEPROM content.\n", UL_ON, UL_OFF); printf(" k14 %sd%sump\n" "\t\tDump device content (INHX32 format).\n", UL_ON, UL_OFF); printf(" k14 %ser%sase eeprom | flash | id | row [n]\n" "\t\tErase EEPROM, flash, id or flash at row for n rows.\n", UL_ON, UL_OFF); printf(" k14 %sf%slash [n] [address]\n" "\t\tDisplay all or n words of program flash content from address.\n", UL_ON, UL_OFF); printf(" k14 %si%sd\n" "\t\tDisplay device identification.\n", UL_ON, UL_OFF); printf(" k14 %so%ssccal\n" "\t\tDisplay oscillator calibration.\n", UL_ON, UL_OFF); printf(" k14 %so%ssccal 0x343c\n" "\t\tRestore oscillator calibration as 0x343c.\n", UL_ON, UL_OFF); printf(" k14 %sp%srogram [file.hex] [noblank]\n" "\t\tBlank and program file.hex or stdin to flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" k14 %sv%serify [file.hex]\n" "\t\tVerify file.hex or stdin in flash (INHX32 format).\n", UL_ON, UL_OFF); printf(" k14 %svi%sew [file.hex]\n" "\t\tView file.hex or stdin (INHX32 format).\n", UL_ON, UL_OFF); printf(" k14 /dev/ttyUSB0 | %s8%s048\n" "\t\tListen on /dev/ttyUSB0 or network for remote programming.\n", UL_ON, UL_OFF); printf("\n"); printf("VERSION:\n %s\n", VERSION); if (msg) io_exit(k, EX_USAGE); io_exit(k, EX_OK); }
int main(int argc, char *argv[]) { struct k8048 k; char *execdup = NULL, *execname = NULL; /* Initialise */ memset(&k, 0, sizeof(k)); /* Get exec name */ execdup = (char *)strdup(argv[0]); if (execdup == NULL) { printf("%s: fatal error: strdup failed\n", __func__); io_exit(&k, EX_OSERR); /* Panic */ } execname = basename(execdup); if (execname == NULL) { printf("%s: fatal error: basename failed\n", __func__); io_exit(&k, EX_OSERR); /* Panic */ } /* Get configuration */ getconf(&k); /* Open device */ if (io_open(&k) < 0) { usage(&k, execname, io_error(&k)); } /* Reset uid */ if (getuid() != geteuid()) { if (setuid(getuid()) < 0) { printf("%s: fatal error: setuid failed\n", __func__); io_exit(&k, EX_OSERR); /* Panic */ } } /* Perform operation */ if (argc < 2) usage(&k, execname, "Missing arg(s)"); int err; uint8_t cmd[STRLEN]; /* * ICSPIO */ if (strcasecmp(argv[1], "LED") == 0) { if (argc < 3) usage(&k, execname, "Missing arg"); if (argc > 3) usage(&k, execname, "Too many args"); cmd[0] = CMD_LED; cmd[1] = getbytearg(&k, execname, argv[2]); /* Data */ do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 1, NULL, 0); fprintf(stderr, "0x%02X(0x%02X) = 0x%02X\n", cmd[0], cmd[1], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "SWITCH") == 0) { if (argc > 2) usage(&k, execname, "Too many args"); uint32_t sw = 0; cmd[0] = CMD_SWITCH; do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 0, &sw, 1); fprintf(stderr, "0x%02X() = 0x%02X\n", cmd[0], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); fprintf(stdout, "0x%02X\n", sw); } else if (strcasecmp(argv[1], "SLEEP") == 0) { if (argc > 2) usage(&k, execname, "Too many args"); cmd[0] = CMD_SLEEP; do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 0, NULL, 0); fprintf(stderr, "0x%02X() = 0x%02X\n", cmd[0], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "WATCHDOG") == 0) { if (argc < 3) usage(&k, execname, "Missing arg"); if (argc > 3) usage(&k, execname, "Too many args"); cmd[0] = CMD_WATCHDOG; if (argv[2][0] == 'd' || argv[2][0] == 'D') { /* Disable */ cmd[1] = 0x00; } else if (argv[2][0] == 'e' || argv[2][0] == 'E') { /* Enable */ cmd[1] = 0x01; } else { usage(&k, execname, "Invalid arg"); } do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 1, NULL, 0); fprintf(stderr, "0x%02X(0x%02X) = 0x%02X\n", cmd[0], cmd[1], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "CLOCK") == 0) { if (argc < 3) usage(&k, execname, "Missing arg"); if (argc > 3) usage(&k, execname, "Too many args"); cmd[0] = CMD_CLOCK; cmd[1] = getbytearg(&k, execname, argv[2]); /* Data */ do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 1, NULL, 0); fprintf(stderr, "0x%02X(0x%02X) = 0x%02X\n", cmd[0], cmd[1], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "DIRECTION") == 0) { if (argc < 4) usage(&k, execname, "Missing arg"); if (argc > 4) usage(&k, execname, "Too many args"); cmd[0] = CMD_DIRECTION; cmd[1] = getportarg(&k, execname, argv[2]); /* Port */ cmd[2] = getbytearg(&k, execname, argv[3]); /* I/O */ do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 2, NULL, 0); fprintf(stderr, "0x%02X(0x%02X, 0x%02X) = 0x%02X\n", cmd[0], cmd[1], cmd[2], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "OUTPUT") == 0) { if (argc < 4) usage(&k, execname, "Missing arg"); if (argc > 4) usage(&k, execname, "Too many args"); cmd[0] = CMD_OUTPUT; cmd[1] = getportarg(&k, execname, argv[2]); /* Port */ cmd[2] = getbytearg(&k, execname, argv[3]); /* Data */ do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 2, NULL, 0); fprintf(stderr, "0x%02X(0x%02X, 0x%02X) = 0x%02X\n", cmd[0], cmd[1], cmd[2], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "INPUT") == 0) { if (argc < 3) usage(&k, execname, "Missing arg"); if (argc > 3) usage(&k, execname, "Too many args"); uint32_t in; cmd[0] = CMD_INPUT; cmd[1] = getportarg(&k, execname, argv[2]); /* Port */ do { in = 0; err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 1, &in, 1); fprintf(stderr, "0x%02X(0x%02X) = 0x%02X\n", cmd[0], cmd[1], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); fprintf(stdout, "0x%02X\n", in); } else if (strcasecmp(argv[1], "ANALOG") == 0) { if (argc < 3) usage(&k, execname, "Missing arg"); if (argc > 3) usage(&k, execname, "Too many args"); cmd[0] = CMD_ANALOG; if (argv[2][0] == 'd' || argv[2][0] == 'D') { /* Disable */ cmd[1] = 0xFF; } else { /* Channel */ cmd[1] = getbytearg(&k, execname, argv[2]); } do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 1, NULL, 0); fprintf(stderr, "0x%02X(0x%02X) = 0x%02X\n", cmd[0], cmd[1], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "SAMPLE") == 0) { if (argc > 2) usage(&k, execname, "Too many args"); uint32_t sample; cmd[0] = CMD_SAMPLE; do { sample = 0; err = io_test_command(&k, k.fwsleep, FWSAMPLE, cmd, 0, &sample, 2); fprintf(stderr, "0x%02X() = 0x%02X\n", cmd[0], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); fprintf(stdout, "0x%04X\n", sample); } else if (strcasecmp(argv[1], "EEREAD") == 0) { if (argc < 3) usage(&k, execname, "Missing arg"); if (argc > 3) usage(&k, execname, "Too many args"); uint32_t data; cmd[0] = CMD_EEREAD; cmd[1] = getbytearg(&k, execname, argv[2]); /* Address */ do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 1, &data, 1); fprintf(stderr, "0x%02X(0x%02X) = 0x%02X\n", cmd[0], cmd[1], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); fprintf(stdout, "0x%02X\n", data); } else if (strcasecmp(argv[1], "EEWRITE") == 0) { if (argc < 4) usage(&k, execname, "Missing arg"); if (argc > 4) usage(&k, execname, "Too many args"); cmd[0] = CMD_EEWRITE; cmd[1] = getbytearg(&k, execname, argv[2]); /* Address */ cmd[2] = getbytearg(&k, execname, argv[3]); /* Data */ do { err = io_test_command(&k, k.fwsleep, FWEEPROM, cmd, 2, NULL, 0); fprintf(stderr, "0x%02X(0x%02X, 0x%02X) = 0x%02X\n", cmd[0], cmd[1], cmd[2], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); } else if (strcasecmp(argv[1], "READ") == 0) { if (argc < 3) usage(&k, execname, "Missing arg"); if (argc > 3) usage(&k, execname, "Too many args"); uint32_t data; uint16_t addr = getshortarg(&k, execname, argv[2]); /* Address */ cmd[0] = CMD_READ; cmd[1] = addr >> 8; /* Address high */ cmd[2] = addr; /* Address low */ do { err = io_test_command(&k, k.fwsleep, k.fwsleep << 1, cmd, 2, &data, 2); fprintf(stderr, "0x%02X(0x%02X,0x%02X) = 0x%02X\n", cmd[0], cmd[1], cmd[2], err); if (err != ERRNONE) { if (k.debug >= 1) { fprintf(stderr, "%s: error: %s [0x%02X]\n", __func__, io_test_err(err), err); } io_usleep(&k, RESYNC * k.fwsleep); } } while (!io_stop && err != ERRNONE && err != ERRNOTSUP); fprintf(stdout, "0x%04X\n", data); } else if (strcasecmp(argv[1], "VREF") == 0) {
/* * ======== api_init ======== * Purpose: * Module initialization used by Bridge API. */ bool api_init(void) { bool ret = true; bool fdrv, fdev, fcod, fchnl, fmsg, fio; bool fmgr, fproc, fnode, fdisp, fstrm, frmm; if (api_c_refs == 0) { /* initialize driver and other modules */ fdrv = drv_init(); fmgr = mgr_init(); fproc = proc_init(); fnode = node_init(); fdisp = disp_init(); fstrm = strm_init(); frmm = rmm_init(); fchnl = chnl_init(); fmsg = msg_mod_init(); fio = io_init(); fdev = dev_init(); fcod = cod_init(); ret = fdrv && fdev && fchnl && fcod && fmsg && fio; ret = ret && fmgr && fproc && frmm; if (!ret) { if (fdrv) drv_exit(); if (fmgr) mgr_exit(); if (fstrm) strm_exit(); if (fproc) proc_exit(); if (fnode) node_exit(); if (fdisp) disp_exit(); if (fchnl) chnl_exit(); if (fmsg) msg_exit(); if (fio) io_exit(); if (fdev) dev_exit(); if (fcod) cod_exit(); if (frmm) rmm_exit(); } } if (ret) api_c_refs++; return ret; }