diff --git a/tools/sensinode/nano_programmer/Makefile b/tools/sensinode/nano_programmer/Makefile new file mode 100644 index 000000000..06c0fb979 --- /dev/null +++ b/tools/sensinode/nano_programmer/Makefile @@ -0,0 +1,43 @@ +EXE_MAKE=$(notdir $(shell which "make.exe" 2>/dev/null)) +ifeq "$(EXE_MAKE)" "make.exe" +PLATFORM=windows +else +PLATFORM=linux +endif + +OBJECTS = ihex.o $(PLATFORM)/port.o programmer.o cdi_program.o +SUBDIRS = + +ifeq "$(PLATFORM)" "linux" +CFLAGS = -Wall -D_REENTRANT -I. +LDFLAGS = -L. -D_REENTRANT -lpthread +SUFFIX= +else +CFLAGS=-I. -I../nano_usb_programmer/ftdi_win32 +CFLAGS+= -L. -L../nano_usb_programmer/ftdi_win32 -DPLATFORM_WINDOWS +CFLAGS+= -mwin32 +LDFLAGS=../nano_usb_programmer/ftdi_win32/ftd2xx.lib -lkernel32 +SUFFIX=.exe +endif + +TARGET = nano_programmer$(SUFFIX) + +all: binary + +binary: $(TARGET) + strip $(TARGET) + +$(TARGET): $(OBJECTS) + gcc -o $(TARGET) $(OBJECTS) $(LDFLAGS) + +.c.o: + gcc -c -o $(<:.c=.o) -O2 -Wall $(CFLAGS) $< + +platform-test: + @echo $(PLATFORM) + +old-strip: + if [ -x $(TARGET).exe ]; then $(PLATFORM)strip $(TARGET).exe; else $(PLATFORM)strip $(TARGET); fi + +clean: + rm -f $(TARGET) $(OBJECTS) diff --git a/tools/sensinode/nano_programmer/README b/tools/sensinode/nano_programmer/README new file mode 100755 index 000000000..27daa114a --- /dev/null +++ b/tools/sensinode/nano_programmer/README @@ -0,0 +1,34 @@ +Nano Programmer + +Programming tool for the Sensinode Nano series using Dxxx development boards. + +Copyright 2007-2008 Sensinode Ltd. + +1a - Installation (Linux) + +No external libraries required. + +1b - Installation (Windows/Cygwin) + +Installation procedure: +See the nano_usb_programmer README file on how to install FTDI library +for nano_usb_programmer. The nano_programmer build system will fetch +the library from there. + +2 - Usage + +Usage info for the Nano Programmer is available with command +./nano_programmer --help. Note that use might require root/administrator privileges + depending on system configuration. + +3 - Known problems + +Occasional timing failures resulting in "Reinit failed."-messages do come +up in some PC configurations. If you experience programming failures (the programmer +is not able to recover), please report your system configuration to Sensinode. +On Linux, it is known that the "brltty" program causes problems with the FTDI +serial driver. Uninstalling brltty resolves the problem. + +4 - README Version + +v1.3 2008-01-31 Martti Huttunen Multi-platform build and created instructions diff --git a/tools/sensinode/nano_programmer/cdi_program.c b/tools/sensinode/nano_programmer/cdi_program.c new file mode 100644 index 000000000..3b2ecd255 --- /dev/null +++ b/tools/sensinode/nano_programmer/cdi_program.c @@ -0,0 +1,607 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#include +#include +#include + +#include "port.h" +#include "programmer.h" +#include "ihex.h" + +#include + +extern void crc_add(unsigned char *crc, unsigned char byte); + +int cdi_page_write(port_t *port, unsigned long page_addr, unsigned char *page_buffer); +int cdi_write(port_t *port, conf_opts_t *conf, FILE *ihex); + +int cdi_programmer(conf_opts_t *conf, char *filename) +{ + int error = 0; + port_t *port = 0; + unsigned char buffer[256]; + int length = 0; + FILE *ihex = 0; + + error = programmer_init(conf->device, &port); + + if (error < 0) + { + return error; + } + + if((!error) && (conf->action != 'b')) + { + length = port_write_echo(port, "CDI\r"); + bzero(buffer, sizeof(buffer)); + if (length >= 4) + { + length = port_readline(port, buffer, sizeof(buffer), 100); + } + else length = 0; + + if(memcmp(buffer, "OK", 2) == 0) + { + error = 0; + } + else + { + printf("Programming mode selection failed.\n"); + error = -1; + } + } + + if((!error) && (conf->action != 'b')) + { + printf("Initialize.\n"); + // Succesfully in mode 1 + sleep(1); + port_write_echo(port, "i\r"); + + bzero(buffer, 256); + length = port_readline(port, buffer, sizeof(buffer), 100); + + if(memcmp(buffer, "85", 2) == 0) + { /*Found CC2430 device*/ + printf("Found CC2430 device revision %c%c.\n", buffer[2], buffer[3]); + } + else if (memcmp(buffer, "89", 2) == 0) + { + printf("Found CC2431 device revision %c%c.\n", buffer[2], buffer[3]); + } + else + { + printf("CC2430 not found.\n"); + error = -1; + } + } + + if (error) conf->action = ' '; + + switch(conf->action) + { + case 'e': + // Erase programming + port_write_echo(port, "e\r"); + bzero(buffer, 256); + length = port_readline(port, buffer, sizeof(buffer), 100); + + if(memcmp(buffer, "OK", 2) == 0) + { + // Erase successful + printf("Erase successful.\n"); + error = 0; + } + else + { + // Erase failed + printf("Erase failed: %s.\n", buffer); + error = -1; + } + if ((conf->action != 'P') || error) + break; + + case 'P': + case 'w': + ihex = fopen(conf->ihex_file, "rb"); + if(ihex == NULL) + { + printf("Failed to open ihex file %s.\n", conf->ihex_file); + error = -1; + } + else error = 0; + + if (!error) + { + error = cdi_write(port, conf, ihex); + if (error) printf("Programming failed.\n"); + } + + + + if (ihex != NULL) fclose(ihex); + break; + + case 'b': + length = port_write_echo(port, "V\r"); + bzero(buffer, sizeof(buffer)); + if (length >= 2) + { + length = port_readline(port, buffer, sizeof(buffer), 100); + } + else length = 0; + + if(length > 4) + { + buffer[length] = 0; + printf("BIOS: %s\n", buffer); + error = 0; + } + else + { + printf("Failed to get BIOS version. Upgrade recommended.\n"); + error = -1; + } + break; + + case 'v': + break; + + case 'r': + ihex = fopen(conf->ihex_file, "wb"); + if(ihex == NULL) + { + printf("Failed to open ihex file %s.\n", conf->ihex_file); + error = -1; + } + else + { + port_write_echo(port, "a000000\r"); + bzero(buffer, sizeof(buffer)); + length = port_readline(port, buffer, sizeof(buffer), 200); + if (length <0) length = 0; + if(memcmp(buffer, "OK", 2) == 0) + { + uint32_t address = 0; + uint8_t check = 0; + for (address = 0; address < 128*1024; address += 64) + { + uint8_t i; + + if ((address) && ((address & 0xFFFF)==0)) + { + fprintf(ihex, ":02000004%4.4X%2.2X\r\n", + (int)(address>>16), (int)(0xFA-(address>>16))); + } + port_write_echo(port, "r\r"); + bzero(buffer, 256); + length = 0; + while (length < 64) + { + length += port_readline(port, &buffer[length], sizeof(buffer)-length, 100); + } + for (i=0; i<64; i++) + { + if ((i & 0x0F) == 0) + { + check = 0; + check -= 0x10; + check -= (uint8_t) (address >> 8); + check -= (uint8_t) (address + i); + printf("%4.4X", (int) address + i); + fprintf(ihex, ":10%4.4X00", (int) (address + i) & 0xFFFF); + } + fprintf(ihex, "%2.2X", buffer[i]); + check -= buffer[i]; + if ((i & 0x0F) == 0x0F) + { + fprintf(ihex, "%2.2X\r\n", check); + if (i > 0x30) printf("\n"); + else printf(" "); + } + } + } + fprintf(ihex, ":00000001FF\r\n"); + } + else + { + printf("Failed to set read address.\n"); + error = -1; + } + fclose(ihex); + } + break; + /*skip for error case*/ + case ' ': + break; + + case 'm': + port_write_echo(port, "a01F800\r"); + bzero(buffer, sizeof(buffer)); + length = port_readline(port, buffer, sizeof(buffer), 200); + if (length <0) length = 0; + if(memcmp(buffer, "OK", 2) == 0) + { + uint8_t i; + uint32_t address = 0; + + for (address = 0x01F800; address < 128*1024; address += 64) + { + + port_write_echo(port, "r\r"); + bzero(buffer, 256); + length = 0; + while (length < 64) + { + length += port_readline(port, &buffer[length], sizeof(buffer)-length, 100); + } + if ((address & 0xff) == 0) + { printf("."); + fflush(stdout); + } + } + printf("\nDevice MAC: "); + for (i=56; i<64; i++) + { + if (i != 56) printf(":"); + printf("%2.2X", buffer[i]); + } + printf("\n"); + } + break; + + case 'Q': + port_write_echo(port, "a01F800\r"); + bzero(buffer, sizeof(buffer)); + length = port_readline(port, buffer, sizeof(buffer), 200); + if (length <0) length = 0; + if(memcmp(buffer, "OK", 2) == 0) + { + uint8_t p_buffer[2048]; + int error; + + memset(p_buffer, 0xff, sizeof(p_buffer)); + memcpy(&p_buffer[2040], conf->write_mac, 8); + + printf("\rWriting MAC: "); + error = cdi_page_write(port, 0x01F800, p_buffer); + if (!error) + { + printf("Write complete.\n"); + } + else + { + printf("Write failed.\n"); + } + } + break; + + default: + printf("Unknown CDI action.\n"); + break; + } + + printf("Close programmer.\n"); + usleep(100000); + port_write_echo(port, "q\r"); + programmer_close(port); + return error; +} + +int cdi_write(port_t *port, conf_opts_t *conf, FILE *ihex) +{ + int error = 0; + unsigned char buffer[256]; + int length; + int i; + int pages; + + unsigned long ext_addr=0; + unsigned short int addr=0; + unsigned char page_buffer[128*1024]; + unsigned char page_table[64]; + + bzero(buffer, sizeof(buffer)); + + /*initialize page data*/ + memset(page_table, 0, 64); + memset(page_buffer, 0xFF, sizeof(page_buffer)); + pages = 0; + + error = 0; + + if (conf->page_mode == PAGE_UNDEFINED) + { + int retval; + + while((!error) && ((retval = fscanf(ihex, "%s", buffer)) == 1) ) + { + unsigned char data_len = 0; + + if (memcmp(&buffer[7], "00", 2) == 0) + { /*Data record*/ + } + else if (memcmp(&buffer[7], "01", 2) == 0) + { /*end file*/ + printf("\nFile read complete.\n"); + break; + } + else if (memcmp(&buffer[7], "04", 2) == 0) + { + sscanf((char *)&(buffer[3]),"%4hx", &addr); + sscanf((char *)&(buffer[9]),"%4lx", &ext_addr); + + if (ext_addr >= 0x0002) + { + conf->page_mode = PAGE_SDCC; + } + else + { + if (conf->page_mode == PAGE_UNDEFINED) conf->page_mode = PAGE_LINEAR; + } + } + } + if (retval == -1) + { + printf("Read error\n"); + return -1; + } + rewind(ihex); + retval = 0; + error = 0; + } + switch (conf->page_mode) + { + case PAGE_SDCC: + printf("SDCC banked file.\n"); + break; + case PAGE_LINEAR: + printf("Linear banked file.\n"); + break; + case PAGE_UNDEFINED: + printf("Non-banked file, assuming linear.\n"); + conf->page_mode = PAGE_LINEAR; + break; + } + + while( (fscanf(ihex, "%s", buffer) == 1) && !error) + { + unsigned char data_len = 0; + + if (memcmp(&buffer[7], "00", 2) == 0) + { /*Data record*/ + i=0; + sscanf((char *)&buffer[1], "%2hhx", &data_len); + sscanf((char *)&(buffer[3]),"%4hx", &addr); + while(ipage_mode == PAGE_SDCC) + { + if (ext_addr) ext_addr--; + ext_addr *= 0x8000; + } + else + { + ext_addr *= 0x10000; + } + printf("\rExtended page address: 0x%8.8lX\r", ext_addr); + } + } + + if (pages) + { + int retry = 0; + // Successfully in mode 3 (programming) + printf("Starting programming.\n"); + error = 0; + for (i=0; i<64; i++) + { + if (page_table[i] != 0) + { + ext_addr = 2048*i; + + bzero(buffer, sizeof(buffer)); + + // Write the start address and check return + usleep(3000); + sprintf((char *)buffer, "a%6.6lX\r", ext_addr); + port_write_echo(port, (char *)buffer); + + if((length = port_readline(port, buffer, sizeof(buffer), 200)) < 0) + { + printf("Read from serial timed out without data.\n"); + error = -1; + break; + } + else + { + if(strncmp((char *)buffer, "OK\r\n", 4) == 0) + { + printf("\r \r"); + printf("\rWriting @ 0x%6.6lX: ", ext_addr); + fflush(stdout); + error = cdi_page_write(port, ext_addr, &page_buffer[ext_addr]); + if (error) + { + usleep(20000); + port_write_echo(port, "i\r"); + + bzero(buffer, 256); + length = port_readline(port, buffer, sizeof(buffer), 100); + + if(memcmp(buffer, "85", 2) == 0) + { /*Found CC2430 device*/ + } + else + { + printf("Reinit failed.\n"); + error = -1; + } + if (retry++ < 3) + { + error = 0; + i--; + } + } + else retry = 0; + fflush(stdout); + usleep(20000); + } + else + { + printf("Failed to set CDI programming start address.\n"); + error = -1; + break; + } + } + } + if (error) break; + } + usleep(200000); + printf("\n"); + } + + return error; +} + +int cdi_page_write(port_t *port, unsigned long page_addr, unsigned char *page_buffer) +{ + int error = 0; + unsigned char buffer[80]; + unsigned char cmd[16]; + unsigned char block, i; + int length; + int retry = 0; + + // Write page + port_write_echo(port, "w\r"); + usleep(10000); + for (block=0; block<(2048/64); block++) + { + sprintf((char *)cmd, "%6.6lX", page_addr + (64*block)); + bzero(buffer, sizeof(buffer)); + length = port_readline(port, buffer, sizeof(buffer), 2000); + if (length <0) + { length = 0; + printf("l!");fflush(stdout); + } + buffer[length] = 0; + if (block & 1) + { + } + if(memcmp(buffer, cmd, 6) == 0) + { +#define WRITE_SIZE 64 + for (i=0; i<64; i+=WRITE_SIZE) + { + port_write(port, &page_buffer[(unsigned int)(block*64)+i], WRITE_SIZE); + usleep(1250); + } + + bzero(buffer, sizeof(buffer)); + printf("."); + fflush(stdout); + length = port_readline(port, buffer, sizeof(buffer), 200); + if(memcmp(buffer, "OK", 2) == 0) + { + retry = 0; + } + else + { + block--; + if (retry++ >= 8) + { + error = -1; + break; + } + else + { + buffer[length] = 0; + printf("%s",buffer); + port_rts_clear(port); + usleep(300000); + port_rts_set(port); + bzero(buffer, sizeof(buffer)); + length = port_readline(port, buffer, sizeof(buffer), 800); + if(memcmp(buffer, "CDI", 3) == 0) + { + printf("R"); + } + } + } + } + else + { + error = -1; + break; + } + } + + if (!error) + { + printf("w"); fflush(stdout); + bzero(buffer, sizeof(buffer)); + length = port_readline(port, buffer, sizeof(buffer), 800); + if(memcmp(buffer, "WROK", 4) == 0) + { + error = 0; + } + else + { + printf("%c%c", buffer[0], buffer[1]); + error = -1; + } + } + + if (!error) printf("OK\r"); + return error; +} + diff --git a/tools/sensinode/nano_programmer/ihex.c b/tools/sensinode/nano_programmer/ihex.c new file mode 100644 index 000000000..83234714e --- /dev/null +++ b/tools/sensinode/nano_programmer/ihex.c @@ -0,0 +1,99 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#include +#include +#include +#include + +#include + +int hexfile_parse(char *line, unsigned int *type, unsigned int *addr, unsigned char *buffer) +{ + unsigned int row_len = 0; + unsigned int row_index = 7; + unsigned int i; + int tmp; + + uint8_t cksum = 0; + int retval = 0; + + retval = sscanf(line, ":%2x%4x%2x", &row_len, addr, type); + + cksum += row_len; + cksum += *addr >> 8; + cksum += *addr & 0xFF; + cksum += *type; + + i = 0; + if (retval == 3) + { + while(i < row_len) + { + + if (sscanf(&line[row_index], "%2x", &tmp) == 1) + { + cksum += tmp; + buffer[i++] = (unsigned char) tmp; + row_index += 2; + } + else return -1; + } + if (sscanf(&line[row_index], "%2x", &tmp) == 1) + { + if ((cksum + (uint8_t) tmp) == 0) return row_len; + } + } + return -1; +} + +int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes) +{ + uint8_t cksum = 0; + uint8_t i = 0; + char tmp[8]; + + sprintf(line, ":%2.2X%4.4X%2.2X", bytes, address, type); + cksum -= bytes; + cksum -= address >> 8; + cksum -= address & 0xFF; + cksum -= type; + + for (i=0; i + +#include "port.h" + +int port_open(port_t **port, char *device) +{ + port_t *new_port = (port_t *) malloc(sizeof(port_t)); + char err_string[128]; + + *port = new_port; + + new_port->device = 0; + new_port->handle = 0; + + new_port->handle = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); + + if (new_port->handle <= 0) + { + strerror_r(errno, err_string, 128); + + printf("Serial port open failed with error message: %s.\n", err_string); + return(-1); + } + else + { + tcgetattr(new_port->handle, &(new_port->old_params)); + + fcntl(new_port->handle, F_SETFL, FASYNC); + printf("Serial port %s opened succesfully.\n", device); + + return(0); + } +} + +int port_close(port_t *port) +{ + if (!port) + return(-1); + + if ((port->handle) > 0) + { + tcflush(port->handle, TCIFLUSH); + tcsetattr(port->handle,TCSANOW,&(port->old_params)); + + close(port->handle); + port->handle = 0; + } + + if (port->device) free(port->device); + port->device = 0; + free(port); + + return(1); +} + + +/** @todo port_write() function probably needs mutexes -mjs */ + +int port_write(port_t *port, unsigned char *buffer, size_t buflen) +{ + int i=0; + + if (!port) return -1; + + /** @todo The write to serial port is at the moment done one octet at a time with 10ms interval between each write operation due to some minor problems in MCU interrupts. -mjs */ + while(i < buflen) + { + write(port->handle, &(buffer[i]), 1); + tcflush(port->handle, TCIFLUSH); + i++; + } + +/* write(port->handle, &(buffer[i]), buflen);*/ + + tcflush(port->handle, TCIFLUSH); + + return(0); +} + +int port_read(port_t *port, unsigned char *buffer, size_t buflen) +{ + unsigned int l = 0; + l = read(port->handle, buffer, buflen); + return(l); +} + +int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts) +{ + int rate = B115200; + struct termios newtio; + + if (!port) return -1; + + switch (speed) + { + case 230400: + rate = B230400; + break; + + case 0: + case 115200: + rate = B115200; + break; + + case 57600: + rate = B57600; + break; + + case 38400: + rate = B38400; + break; + + case 19200: + rate = B19200; + break; + + case 9600: + rate = B9600; + break; + + default: + return -1; + + } + bzero(&newtio, sizeof(newtio)); + + if (speed == 9600) + { + newtio.c_cflag |= CS8 | CSTOPB | CLOCAL | CREAD; + } + else + { + newtio.c_cflag |= CS8 | CLOCAL | CREAD; + } + if (rtscts) + { + newtio.c_cflag |= CRTSCTS; + } + newtio.c_iflag = IGNPAR; + + cfsetispeed(&newtio, rate); + cfsetospeed(&newtio, rate); + + newtio.c_cc[VTIME] = 0; + newtio.c_cc[VMIN] = 1; + +#if 0 + newtio.c_cflag = rate | CS8 | CLOCAL | CREAD | CSTOPB; +/* if (rts_cts) newtio.c_cflag |= CRTSCTS;*/ + + newtio.c_iflag = IGNPAR; + newtio.c_oflag = 0; + + newtio.c_lflag = 0; + + newtio.c_cc[VTIME] = 0; + newtio.c_cc[VMIN] = 1; +#endif + + tcflush(port->handle, TCIFLUSH); + tcsetattr(port->handle,TCSANOW,&newtio); + + return(0); +} + +int port_dtr_set(port_t *port) +{ + int port_state = TIOCM_DTR; + + if (!port) return(-1); + +/* error = ioctl(port->handle, TIOCMGET, &port_state); + port_state |= TIOCM_RTS; + ioctl(port->handle, TIOCMSET, &port_state);*/ + + ioctl(port->handle, TIOCMBIS, &port_state); + return 0; +} + +int port_dtr_clear(port_t *port) +{ + int port_state = TIOCM_DTR; + + if (!port) return(-1); + + ioctl(port->handle, TIOCMBIC, &port_state); + return 0; +} + +int port_rts_set(port_t *port) +{ + int port_state = TIOCM_RTS; + + if (!port) return(-1); + + ioctl(port->handle, TIOCMBIS, &port_state); + return 0; +} + +int port_rts_clear(port_t *port) +{ + int port_state = TIOCM_RTS; + + if (!port) return(-1); + + ioctl(port->handle, TIOCMBIC, &port_state); + return 0; +} + +int port_get(port_t *port, unsigned char *buffer, int timeout) +{ + struct pollfd pfds; + unsigned int nfds = 1; + int bytes = 0; + int rval; + + pfds.fd = (int)(port->handle); + pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; + + rval = poll(&pfds, nfds, timeout); + + if((rval & POLLIN) != POLLIN) + { + return(-1); + } + else + { + bytes = port_read(port, buffer, 1); + } + return bytes; +} + +int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout) +{ + int length = 0; + struct pollfd pfds; + unsigned int nfds = 1; + int bytes = 0; + int rval; + + pfds.fd = (int)(port->handle); + pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; + + do + { + rval = poll(&pfds, nfds, timeout); + if((rval & POLLIN) != POLLIN) + { + return(length); + } + else + { + bytes = port_read(port, &(buffer[length]), 1); + if (buffer[length] == '\n') + { + buf_size = length; + } + length += bytes; + } + + }while(length < buf_size); + + buffer[length] = 0; + + if(length != 0) + return length; + else + return(-1); +} + +int port_write_echo(port_t *port, char *string) +{ + int length = 0; + int retry = 0; + unsigned char byte; + + while( (string[length]) && (retry < 100) ) + { + port_write(port, (unsigned char *) &string[length], 1); + while (retry++ < 100) + { + if (port_read(port, &byte, 1) == 1) + { +/* printf("%c",byte);*/ + if (byte == string[length]) + { + retry = 0; + length++; + break; + } + else retry = 100; + } + else usleep(1000); + } + } + if ((string[strlen(string)-1] == '\r') && (retry < 100) ) + { /*wait for \n*/ + retry = 0; + while (retry++ < 100) + { + if (port_read(port, &byte, 1) == 1) + { +/* printf("%c",byte);*/ + break; + } + else usleep(1000); + } + } + + if (retry >= 100) return 0; + else return length; +} + + +int port_write_8byte_no_echo(port_t *port, int dlen, char *string) +{ + int length = 0; + int total_len; + int wrbytes = 4; + + total_len = dlen; + +/* printf("total: %d, length: %d, dlen: %d.\n", total_len, length, dlen); */ + while(total_len > length) + { + if((total_len - length) >= wrbytes) + { + port_write(port, (unsigned char *)&string[length], wrbytes); + length += wrbytes; + } + else + { + port_write(port, (unsigned char *)&string[length], total_len - length); + length += total_len - length; + } + usleep(1250); + + } + + return(length); +} + diff --git a/tools/sensinode/nano_programmer/nano_programmer b/tools/sensinode/nano_programmer/nano_programmer new file mode 100755 index 000000000..fd3e46b8a Binary files /dev/null and b/tools/sensinode/nano_programmer/nano_programmer differ diff --git a/tools/sensinode/nano_programmer/port.h b/tools/sensinode/nano_programmer/port.h new file mode 100644 index 000000000..62a6b9270 --- /dev/null +++ b/tools/sensinode/nano_programmer/port.h @@ -0,0 +1,94 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#ifndef _PORT_H +#define _PORT_H + +#ifndef PLATFORM_WINDOWS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include "windows.h" +#include +#include "ftd2xx.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef PLATFORM_WINDOWS +typedef struct +{ + int handle; + char *device; + struct termios old_params; +}port_t; + +extern int port_open(port_t **port, char *device); +#else +typedef struct port_t +{ + FT_HANDLE handle; + int device; + HANDLE event_handle; +}port_t; + +extern int port_open(port_t **port, int device); +#endif + +extern int port_close(port_t *port); +extern int port_write(port_t *port, unsigned char *buffer, size_t buflen); +extern int port_read(port_t *port, unsigned char *buffer, size_t buflen); +extern int port_get(port_t *port, unsigned char *buffer, int timeout); +extern int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts); +extern int port_dtr_set(port_t *port); +extern int port_dtr_clear(port_t *port); +extern int port_rts_set(port_t *port); +extern int port_rts_clear(port_t *port); +extern int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout); +extern int port_write_echo(port_t *port, char *string); +extern int port_write_8byte_no_echo(port_t *port, int dlen, char *string); + +#ifdef __cplusplus +} +#endif +#endif /* _PORT_H */ diff --git a/tools/sensinode/nano_programmer/programmer.c b/tools/sensinode/nano_programmer/programmer.c new file mode 100644 index 000000000..ee82c9389 --- /dev/null +++ b/tools/sensinode/nano_programmer/programmer.c @@ -0,0 +1,440 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#include +#include +#include + +#include "port.h" +#include "programmer.h" + +#include + +extern int cdi_programmer(conf_opts_t *conf, char *filename); + +void usage(char *prg_name) +{ + printf("\nUsage: %s [-d device]\n", prg_name); + printf("General options:\n"); + printf(" -V/--version Get programmer version\n"); + printf(" -1/--d100 Use D100 board (default D200)\n"); + printf("Operating modes:\n"); + printf(" -b/--bios to get programmer BIOS version\n"); + printf(" -P/--program [ihex file] Do a complete programming sequence (write and verify)\n"); + printf(" -v/--verify [ihex file] Verify against ihex file\n"); + printf(" -r/--read [ihex file] Read program code into ihex file\n"); + printf(" -m/--mac Read device MAC address\n"); + printf(" -Q/--write-mac [MAC address] Write device MAC address\n"); + printf(" -e/--erase Erase flash (erases MAC address!)\n"); + printf("Programming options:\n"); + printf(" -l/--linear Force linear model for extended addresses (not SDCC file)\n"); + printf(" -s/--sdcc Force SDCC model for extended addresses (SDCC file)\n"); + printf("Defaults:\n"); +#ifndef PLATFORM_WINDOWS + printf("device /dev/ttyUSB0\n"); +#else + printf("device 0\n"); +#endif +} + +conf_opts_t conf_opts; + +static int option_index = 0; + +int do_exit = 0; + +#define OPTIONS_STRING "d:ec1lsmVbP:v:r:Q:" +/* long option list */ +static struct option long_options[] = +{ + {"device", 1, NULL, 'd'}, + {"psoc", 0, NULL, 'p'}, + {"d100", 0, NULL, '1'}, + {"erase", 0, NULL, 'e'}, + {"mac", 0, NULL, 'm'}, + {"linear", 0, NULL, 'l'}, + {"sdcc", 0, NULL, 's'}, + {"cdi", 0, NULL, 'c'}, + {"version", 0, NULL, 'V'}, + {"bios", 0, NULL, 'b'}, + {"program", 1, NULL, 'P'}, + {"verify", 1, NULL, 'v'}, + {"read", 1, NULL, 'r'}, + {"write-mac", 1, NULL, 'Q'}, + {0, 0, 0, 0} +}; + +int parse_opts(int count, char* param[]) +{ + int opt; + int error=0; + + conf_opts.target_type = CDI; + while ((opt = getopt_long(count, param, OPTIONS_STRING, + long_options, &option_index)) != -1) + { + switch(opt) + { + case 'V': + conf_opts.target_type = VERSION; + break; + + case '1': + conf_opts.prg_type = 1; + break; + + case 'c': + conf_opts.target_type = CDI; + break; + + case 'd': +#ifdef PLATFORM_WINDOWS + if (sscanf(optarg, "%d", &conf_opts.device) != 1) + { + printf("Device ID must be a positive integer.\n"); + conf_opts.action = ' '; + } +#else + printf("device:%s\n", optarg); + strcpy(conf_opts.device, optarg); +#endif + break; + + case 'P': + printf("Programming mode.\n"); + conf_opts.action = 'P'; + strcpy(conf_opts.ihex_file, optarg); + break; + + case 's': + if (conf_opts.page_mode == PAGE_UNDEFINED) + { + conf_opts.page_mode = PAGE_SDCC; + } + else + { + printf("Only one paging option allowed.\n"); + error = -1; + } + break; + + case 'l': + if (conf_opts.page_mode == PAGE_UNDEFINED) + { + conf_opts.page_mode = PAGE_LINEAR; + } + else + { + printf("Only one paging option allowed.\n"); + error = -1; + } + break; + + case 'e': + printf("Erase.\n"); + conf_opts.action = 'e'; + break; + + case 'm': + printf("Get MAC.\n"); + conf_opts.action = 'm'; + break; + + case 'b': + printf("Get BIOS version\n"); + conf_opts.action = 'b'; + break; + + case 'Q': + printf("Write MAC.\n"); + conf_opts.action = 'Q'; + if (sscanf(optarg, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &conf_opts.write_mac[0], &conf_opts.write_mac[1], + &conf_opts.write_mac[2], &conf_opts.write_mac[3], + &conf_opts.write_mac[4], &conf_opts.write_mac[5], + &conf_opts.write_mac[6], &conf_opts.write_mac[7]) != 8) + { + printf("Invalid MAC.\n"); + conf_opts.action = ' '; + } + break; + + case 'v': + printf("Verify by comparing to ihex file:%s\n", optarg); + conf_opts.action = 'v'; + strcpy(conf_opts.ihex_file, optarg); + break; + + case 'r': + printf("Read program to ihex file:%s\n", optarg); + conf_opts.action = 'r'; + strcpy(conf_opts.ihex_file, optarg); + break; + + case '?': + printf("Duh\n"); + error = -1; + break; + } + } + + if (!error && (conf_opts.target_type == CDI) ) + { +#ifdef PLATFORM_WINDOWS + printf("Setup: Device %d.\n", conf_opts.device); +#else + printf("Setup: Device %s.\n", conf_opts.device); +#endif + } + + return error; +} +/* +int port_write_8byte_echo(port_t *port, char *string) +{ + int length = 0; + int total_len; + int i, j; + struct pollfd pfds; + unsigned int nfds = 1; + int rval = 0; + + int wrbytes = 2; + unsigned char byte8[wrbytes]; + + pfds.fd = (int)(port->handle); + pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; + + total_len = strlen(string); + + while(total_len > length) + { + if(total_len - length >= wrbytes) + { + i=0; + port_write(port, (unsigned char *)&string[length], wrbytes); + + if((rval = poll(&pfds, nfds, 100)) == 0) + { + printf("Timed out...\n"); + return(-1); + } + else + { + while(i %.2x\n", string[length+j], byte8[j]); + } + + return(-1); + } + else + { + printf("8Bwok - "); + fflush(stdout); + length += wrbytes; + } + + } + } + else + { + i=0; + port_write(port, (unsigned char *)&string[length], total_len - length); + + if((rval = poll(&pfds, nfds, 100)) == 0) + { + printf("Timed out...\n"); + return(-1); + } + else + { + while(i<(total_len-length)) + { + i = port_read(port, &byte8[i], total_len - length); + } + if(i != total_len - length || memcmp(byte8, &string[length], total_len - length) != 0) + { + printf("Got wrong length or wrong bytes back.\n"); + for(j=0;j %.2x\n", string[length+j], byte8[j]); + } + + return(-1); + } + else + { + printf("<8Bwok - \n"); + fflush(stdout); + length += (total_len - length); + } + } + } + + usleep(5000); + + } + + return(length); +} +*/ +#ifdef PLATFORM_WINDOWS +int programmer_init(int device, port_t **port) +#else +int programmer_init(char *device, port_t **port) +#endif +{ + int error = port_open(port, device); + uint8_t buffer[8]; + + buffer[0] = 0; + + if (error >= 0) + { + if (conf_opts.prg_type == 1) + { + int retry = 0; + port_set_params(*port, 9600, 0); + // Activate programming... + port_dtr_clear(*port); + port_rts_clear(*port); + sleep(1); + printf("Select D100.\n"); + port_rts_set(*port); + sleep(1); + buffer[0] = '\r'; + while (retry++ < 3) + { + int length; + port_write_echo(*port, "q\r"); + length = port_readline(*port, buffer, sizeof(buffer), 800); + if (length) + { + if (*buffer == '!') + { + printf("D100 found.\n"); + return 0; + } + } + } + printf("No programmer found.\n"); + return -1; + } + else + { + port_set_params(*port, 57600, 0); + // Activate programming... + port_dtr_clear(*port); + port_rts_clear(*port); + usleep(300000); + printf("Select D200.\n"); + port_rts_set(*port); + usleep(200000); + port_set_params(*port, 57600, 1); + port_write(*port, (uint8_t *)"\r", 1); + usleep(100000); + if ((port_get(*port, buffer, 500) >= 1) && (buffer[0] == '!')) + { + printf("D200 found.\n"); + return 0; + } + printf("No programmer found.\n"); + return -1; + } + } + return error; +} + +void programmer_close(port_t *port) +{ + if (port) + { + port_rts_clear(port); + port_dtr_set(port); + sleep(1); + port_close(port); + printf("Port closed.\n"); + } +} + +int main(int argc, char *argv[]) +{ + int error = 0; + + conf_opts.target_type = 0; + conf_opts.action = 0; + conf_opts.prg_type = 2; + + +#ifndef PLATFORM_WINDOWS + strncpy(conf_opts.device, "/dev/ttyUSB0", 12); +/* Install a new handler for SIGIO. + * + * According to man 7 signal this signal is by default ignored by most systems. + * It seems that pre FC7 this was true for Fedoras also. We have noticed that at least + * on some FC7 installations the default action has changed. We avoid abnormal program + * exits by defining the SIGIO as SIG_IGN (ignore). - mjs + */ + if(signal(SIGIO, SIG_IGN) == SIG_ERR) + { + printf("%s error: failed to install SIGIO handler. Exit.\n", argv[0]); + exit(EXIT_FAILURE); + } +#else + conf_opts.device = 0; +#endif + + conf_opts.page_mode = PAGE_UNDEFINED; + + if ( (argc <= 1) || (error = parse_opts(argc, argv)) ) + { + usage(argv[0]); + if (error < 0) return error; + else return 0; + } + + if(conf_opts.target_type == CDI) + { /*CDI*/ + error = cdi_programmer(&conf_opts, conf_opts.ihex_file); + } + else + { + printf("\nSensinode Nano series programmer "PROGRAMMER_VERSION "\n"); + } + return error; +} diff --git a/tools/sensinode/nano_programmer/programmer.h b/tools/sensinode/nano_programmer/programmer.h new file mode 100644 index 000000000..d8eab549e --- /dev/null +++ b/tools/sensinode/nano_programmer/programmer.h @@ -0,0 +1,62 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#define PROGRAMMER_VERSION "v1.3" + +typedef enum +{ + PAGE_SDCC, + PAGE_LINEAR, + PAGE_UNDEFINED +}page_mode_t; + +typedef struct { +#ifdef PLATFORM_WINDOWS + int device; +#else + char device[128]; +#endif + int target_type; + int prg_type; + int action; + char ihex_file[128]; + unsigned char write_mac[8]; + page_mode_t page_mode; +}conf_opts_t; + +enum target { UNDEFINED, VERSION, CDI }; + +#ifdef PLATFORM_WINDOWS +extern int programmer_init(int device, port_t **port); +#else +extern int programmer_init(char *device, port_t **port); +#endif + +extern void programmer_close(port_t *port); + diff --git a/tools/sensinode/nano_programmer/windows/port.c b/tools/sensinode/nano_programmer/windows/port.c new file mode 100644 index 000000000..5b9a09f9c --- /dev/null +++ b/tools/sensinode/nano_programmer/windows/port.c @@ -0,0 +1,383 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#include "port.h" +#include + +int port_open(port_t **port, int device) +{ + port_t *new_port = (port_t *) malloc(sizeof(port_t)); + FT_STATUS status; + + *port = new_port; + + new_port->device = device; + new_port->handle = 0; + + status = FT_Open(device, &(new_port->handle)); + + if (status != FT_OK) + { + new_port->handle = 0; + + printf("Serial port open failed with error message: %d.\n", (int)status); + return(-1); + } + else + { + DWORD mask; + new_port->event_handle = CreateEvent(NULL, TRUE, FALSE, "SN_USB_UART_EVENTS"); + if (new_port->event_handle == NULL) + { + printf("Event handle creation failed.\n"); + FT_Close(new_port->handle); + new_port->handle = 0; + return(-1); + } + mask = FT_EVENT_RXCHAR | FT_EVENT_MODEM_STATUS; + status = FT_SetEventNotification(new_port->handle,mask,new_port->event_handle); + if (status != FT_OK) + { + printf("Setting event notification failed.\n"); + } + FT_SetTimeouts(new_port->handle,400,0); + return(0); + } +} + +int port_close(port_t *port) +{ + if (!port) + return(-1); + + if ((port->event_handle) != NULL) + { + CloseHandle(port->event_handle); + port->event_handle = NULL; + + FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX); + FT_Close(port->handle); + port->handle = 0; + } + + port->device = 0; + free(port); + + return(1); +} + +int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts) +{ + FT_STATUS status; + + if (!port) return -1; + status = FT_SetBaudRate (port->handle, speed); + if (status != FT_OK) return -1; + if (speed == 9600) + { + status = FT_SetDataCharacteristics(port->handle, FT_BITS_8, FT_STOP_BITS_2, FT_PARITY_NONE); + } + else + { + status = FT_SetDataCharacteristics(port->handle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); + } + + if (status != FT_OK) return -1; + + if (rtscts) + { + status = FT_SetFlowControl(port->handle, FT_FLOW_RTS_CTS, 0, 0); + } + else + { + status = FT_SetFlowControl(port->handle, FT_FLOW_NONE, 0, 0); + } + + if (status != FT_OK) return -1; + + FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX); + + return(0); +} + +int port_dtr_set(port_t *port) +{ + FT_STATUS status; + + if (!port) return(-1); + + status = FT_SetDtr(port->handle); + if (status != FT_OK) + { + printf("Control failed.\n"); + return -1; + } + return 0; +} + +int port_dtr_clear(port_t *port) +{ + FT_STATUS status; + + if (!port) return(-1); + + status = FT_ClrDtr(port->handle); + if (status != FT_OK) + { + printf("Control failed.\n"); + return -1; + } + return 0; +} + +int port_rts_set(port_t *port) +{ + FT_STATUS status; + + if (!port) return(-1); + + status = FT_SetRts(port->handle); + if (status != FT_OK) + { + printf("Control failed.\n"); + return -1; + } + return 0; +} + +int port_rts_clear(port_t *port) +{ + FT_STATUS status; + + if (!port) return(-1); + + status = FT_ClrRts(port->handle); + if (status != FT_OK) + { + printf("Control failed.\n"); + return -1; + } + return 0; +} + +int port_write(port_t *port, unsigned char *buffer, size_t buflen) +{ + FT_STATUS status; + DWORD bytes_out; + + if (!port) return -1; + +// FT_Purge(port->handle, FT_PURGE_RX); + + status = FT_Write (port->handle, (LPVOID) buffer, (DWORD) buflen,&bytes_out); + if (status != FT_OK) return -1; + + return 0; +} + +int port_read(port_t *port, unsigned char *buffer, size_t buflen) +{ + DWORD l = 0; + FT_STATUS status; + status = FT_Read(port->handle, buffer, buflen, &l); + return((int) l); +} + +int port_get(port_t *port, unsigned char *buffer, int timeout) +{ + DWORD bytes = 0; + FT_STATUS status; + + FT_SetTimeouts(port->handle, timeout, 0); + + status = FT_Read(port->handle, buffer, 1, &bytes); + if (status != FT_OK) + { + return(-1); + } + return bytes; +} + +int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout) +{ + int length = 0; + DWORD bytes = 0; + FT_STATUS status; + + FT_SetTimeouts(port->handle, timeout, 0); + + do + { + status = FT_Read(port->handle, &buffer[length], 1, &bytes); + length += bytes; + if ((status != FT_OK) || (bytes == 0)) + { + return(length); + } + else + { + if (buffer[length-1] == '\n') + { + buf_size = length; + } + } + }while(length < buf_size); + + buffer[length] = 0; + + if(length != 0) + return length; + else + return(-1); +} + +int port_write_echo(port_t *port, char *string) +{ + int length = 0; + int retry = 0; + unsigned char byte; + DWORD bytes_out; + FT_STATUS status; + + FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX); + + while( (string[length]) && (retry < 100) ) + { + retry = 0; + while (retry++ < 100) + { + status = FT_Write (port->handle, (LPVOID) &string[length], (DWORD) 1,&bytes_out); + if (status != FT_OK) return -1; + if (port_get(port, &byte, 1000) == 1) + { +/* printf("%c",byte);*/ + if (byte == string[length]) + { + retry = 0; + length++; + break; + } + else retry = 100; + } + else usleep(500); + } + } + if ((string[strlen(string)-1] == '\r') && (retry < 100) ) + { /*wait for \n*/ + retry = 0; + while (retry++ < 100) + { + if (port_get(port, &byte, 1000) == 1) + { +/* printf("%c",byte);*/ + break; + } + else usleep(500); + } + } + + if (retry >= 100) return 0; + else return length; +} + +#if 0 + +int port_write_echo(port_t *port, char *string) +{ + int length = 0; + int retry = 0; + unsigned char byte; + + while( (string[length]) && (retry < 100) ) + { + port_write(port, (unsigned char *) &string[length], 1); + while (retry++ < 100) + { + if (port_read(port, &byte, 1) == 1) + { +/* printf("%c",byte);*/ + if (byte == string[length]) + { + retry = 0; + length++; + break; + } + else retry = 100; + } + else usleep(1000); + } + } + if ((string[strlen(string)-1] == '\r') && (retry < 100) ) + { /*wait for \n*/ + retry = 0; + while (retry++ < 100) + { + if (port_read(port, &byte, 1) == 1) + { +/* printf("%c",byte);*/ + break; + } + else usleep(1000); + } + } + + if (retry >= 100) return 0; + else return length; +} + + +int port_write_8byte_no_echo(port_t *port, int dlen, char *string) +{ + int length = 0; + int total_len; + int wrbytes = 4; + + total_len = dlen; + +/* printf("total: %d, length: %d, dlen: %d.\n", total_len, length, dlen); */ + while(total_len > length) + { + if((total_len - length) >= wrbytes) + { + port_write(port, (unsigned char *)&string[length], wrbytes); + length += wrbytes; + } + else + { + port_write(port, (unsigned char *)&string[length], total_len - length); + length += total_len - length; + } + usleep(1250); + + } + + return(length); +} + +#endif diff --git a/tools/sensinode/nano_usb_programmer/Makefile b/tools/sensinode/nano_usb_programmer/Makefile new file mode 100644 index 000000000..2c1e40988 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/Makefile @@ -0,0 +1,32 @@ +EXE_MAKE=$(notdir $(shell which "make.exe")) +ifeq "$(EXE_MAKE)" "make.exe" +PLATFORM=windows +else +PLATFORM=linux +endif + +include Rules.make + +APP = nano_usb_programmer$(SUFFIX) +OBJS = $(SOURCES:.c=.o) + +all: $(APP) + +$(APP): $(OBJS) Makefile $(SOURCES) + $(CC) -o $(APP) $(CFLAGS) $(OBJS) $(LDFLAGS) + +platform-test: + @echo $(PLATFORM) + +clean: + rm -f *.o ; rm -f $(APP) + +.c.o: + $(CC) -c -o $(<:.c=.o) $(CFLAGS) $< + +ftd2xx.def: + echo EXPORTS > ftd2xx.def + nm ftd2xx.lib | grep ' T _' | sed 's/.* T _//' >> ftd2xx.def + +ftd2xx.dll.a: ftd2xx.def + dlltool --def ftd2xx.def --dllname ftd2xx.dll --output-lib ftd2xx.dll.a diff --git a/tools/sensinode/nano_usb_programmer/README b/tools/sensinode/nano_usb_programmer/README new file mode 100644 index 000000000..c2c1c706f --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/README @@ -0,0 +1,56 @@ +Nano USB Programmer + +An USB programmer for the Sensinode NanoRouter N600. + +Copyright 2007-2008 Sensinode Ltd. + +1a - Installation (Linux) + +The installation is quite simple but requires the user to obtain the FTDI +development library. The installation also requires root privileges in +some phases (the ldconfig command to be more specific). Running the +Nano_USB_Programmer executable might also require root privileges. + +-unpack the Nano_USB_Programmer-v[xxx].zip to a directory +-get the FTDI development library from + + http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx0.4.13.tar.gz + +-unpack the ftdi archive +-copy the library static_lib/libftd2xx.a.[version] into /usr/lib +-copy the library libftd2xx.so.[version] into /usr/lib +-make a symbolic link to the library, for example: + ln -s /usr/lib/libftd2xx.so.0.4.13 /usr/lib/libftd2xx.so +-run ldconfig +-copy the header files (*.h) into the nano_usb_programmer/ftdi_linux/ directory +-go to the programmer directory and run make + +1b - Installation (Windows/Cygwin) +Installation procedure: +-The FTDI library can be downloaded at: + + http://www.ftdichip.com/Drivers/CDM/CDM%202.02.04%20WHQL%20Certified.zip + +-Copy header files (ftd2xx.h), ftd2xx.lib and ftd2xx.dll to nano_usb_programmer/ftdi_win32 +-Copy the ftd2xx.dll to your windows system32 directory + +2 - Usage + +Usage info for the Nano_USB_Programmer is available with command +./nano_usb_programmer --help. Note that use might require root/administrator privileges + depending on system configuration. + +3 - Known problems (Linux) + +There's one known problem at the moment. The N600 must be unplugged and +plugged in again after it has been programmed or the MAC address has been +read from it before it can respond to the programmer again. The reason for +this is the FTDI library is not perfectly integrated with the Linux +serial driver. + +4 - README Version + +v1.0 2007-11-14 Mikko Saarnivala Initial release +v1.1 2007-11-15 Mikko Saarnivala A small error in the instructions fixed +v1.2 2007-11-19 Mikko Saarnivala Added the FTDI CBUS2 value handling +v1.3 2008-01-31 Martti Huttunen Multi-platform build and updated instructions diff --git a/tools/sensinode/nano_usb_programmer/Rules.make b/tools/sensinode/nano_usb_programmer/Rules.make new file mode 100644 index 000000000..034cd0321 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/Rules.make @@ -0,0 +1,14 @@ +ifeq "$(PLATFORM)" "linux" +CC=gcc +CFLAGS= -I. -I./ftdi_linux -L. -L./ftdi_linux -DPLATFORM_LINUX +LDFLAGS= -lftd2xx -Wl,-rpath /usr/local/lib +SOURCES=main.c prog.c cdi.c ihex.c +SUFFIX= +else +CC=gcc +CFLAGS=-I. -I./ftdi_win32 -L. -L./ftdi_win32 -DPLATFORM_WINDOWS +CFLAGS+= -mwin32 +LDFLAGS=ftdi_win32/ftd2xx.lib -lkernel32 +SOURCES=main.c prog.c cdi.c ihex.c +SUFFIX=.exe +endif diff --git a/tools/sensinode/nano_usb_programmer/cdi.c b/tools/sensinode/nano_usb_programmer/cdi.c new file mode 100644 index 000000000..2d490869f --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/cdi.c @@ -0,0 +1,506 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#include +#ifdef PLATFORM_WINDOWS +#include +#endif +#include "cdi.h" + +/*read none/8*/ +#define CDI_CHIP_ERASE 0x10 +#define CDI_WR_CONFIG 0x19 +#define CDI_SET_HW_BRKPNT 0x3B + +/*read 8*/ +#define CDI_RD_CONFIG 0x24 +#define CDI_READ_STATUS 0x34 +#define CDI_HALT 0x44 +#define CDI_RESUME 0x4C +#define CDI_STEP_INSTR 0x5C + +/*variable len, add data length to command byte*/ +#define CDI_DBGINSTR 0x54 +#define CDI_STEP_REPLACE 0x64 + +/*response = 16 bits*/ +#define CDI_GET_PC 0x28 +#define CDI_GET_CHIP_ID 0x68 + + +/* internals */ +void cdi_command_push(uint8_t *byte, uint8_t bytes_out, uint16_t *retval, uint8_t return_bits); + +void cdi_flash_bank(uint8_t bank, uint8_t unif_mode); + +void cdi_dptr_write(uint16_t value); + +uint8_t cdi_reg_read(uint8_t reg_addr); +void cdi_reg_write(uint8_t reg_addr, uint8_t value); + +void cdi_xdata_write(uint8_t value); +uint8_t cdi_xdata_read(void); + +void cdi_flash_init(void); +void cdi_flash_write_page(void); + +uint32_t cdi_addr = 0; + +#define pause_ms(x) usleep(x*1000) +#define pause_us(x) usleep(x) + +void cdi_command_push(uint8_t *byte, uint8_t bytes_out, uint16_t *retval, uint8_t return_bits) +{ + uint8_t i, val; + + for (i=0; i>= 3; + for (i=0; i> 8); /*immediateh*/ + out[3] = value; /*immediatel*/ + cdi_command_push(out, 4, &retval, 8); +} + + +uint8_t cdi_reg_read(uint8_t reg_addr) +{ + uint8_t out[3]; + uint16_t retval; + + out[0] = CDI_DBGINSTR + 2; /*command length 2 bytes*/ + out[1] = 0xE5; /*mov a, sfr*/ + out[2] = reg_addr; /*sfr = reg_addr*/ + cdi_command_push(out, 3, &retval, 8); + + return (uint8_t) retval; +} + + +void cdi_flash_bank(uint8_t bank, uint8_t unif_mode) +{ + uint8_t out; + + out = (bank << 4) + 1; + out &= 0x31; + if (unif_mode) out |= 0x40; /*set unified memory model*/ + + cdi_reg_write(0xC7, out); +} + + +void cdi_flash_read(uint8_t *ptr, uint16_t bytes) +{ + uint16_t i; + uint8_t out[4]; + uint16_t retval; + + cdi_flash_bank((cdi_addr >> 15), 0); + + cdi_dptr_write(cdi_addr | 0x8000); + + for (i=0; i> 10) & 0x7F); /*sfr = FADDRH*/ + cdi_reg_write(0xAC, (cdi_addr >> 2)); /*sfr = FADDRL*/ + + /*erase page*/ + cdi_reg_write(0xAE, 0x01); + pause_ms(40); + + /*set program counter*/ + out[0] = CDI_DBGINSTR + 3; /*command length 3 bytes*/ + out[1] = 0x02; /*ljmp immediate16*/ + out[2] = 0xE0; /*immediateh*/ + out[3] = 0x00; /*immediatel*/ + cdi_command_push(out, 4, &retval, 8); + + /*set breakpoint*/ + out[0] = CDI_SET_HW_BRKPNT; /*command length 3 bytes*/ + out[1] = 0x04; + out[2] = 0xE0; /*immediateh*/ + out[3] = sizeof(cdi_ram_code)-2; /*immediatel*/ + cdi_command_push(out, 4, &retval, 0); + + cdi_dptr_write(0xE800); /*data area, set your page data here*/ + /*execute*/ + out[0] = CDI_RESUME; /*command length 3 bytes*/ + cdi_command_push(out, 1, &retval, 8); + + pause_ms(30); + out[3]= 0; + do + { + pause_ms(20); + out[0] = CDI_READ_STATUS; + cdi_command_push(out, 1, &retval, 8); + printf("-"); + fflush(stdout); + }while( ((retval & 0x20) == 0) && (out[3]++ < 200) ); +} + +int cdi_flash_write(uint8_t *ptr, uint16_t length) +{ + uint16_t i, retval; + uint8_t out[3]; + + if (length > 2048) return -1; + + cdi_addr &= 0x1F800; /*make sure address is on page boundary*/ + + printf("0x%6.6X: ", cdi_addr); + fflush(stdout); + cdi_dptr_write(0xE800); /*our page data buffer is here*/ + for (i=0; i< length; i++) + { + cdi_xdata_write(*ptr++); + if ((i & 0x3F) == 0) + { + printf("."); + } + if ((i & 0x0F) == 0x00) + { + printf("\bo"); + } + if ((i & 0x0F) == 0x08) + { + printf("\b."); + } + fflush(stdout); + } + while(i<2048) + { + cdi_xdata_write(0xFF); + if ((i & 0x3F) == 0) + { + printf("."); + } + if ((i & 0x0F) == 0x00) + { + printf("\bo"); + } + if ((i & 0x0F) == 0x08) + { + printf("\b."); + } + fflush(stdout); + i++; + } + + out[0] = CDI_HALT; + cdi_command_push(out, 1, &retval, 8); + + out[0] = CDI_READ_STATUS; + retval = 0; + cdi_command_push(out, 1, &retval, 8); + if ((retval & 0xFF) == 0xB2) + { + /*restore config*/ + out[0] = CDI_WR_CONFIG; /*command length 3 bytes*/ + out[1] = 0x0E; /*write flash area*/ + cdi_command_push(out, 2, &retval, 0); + /*set flash timings and copy code to ram*/ + cdi_flash_init(); + /*write page*/ + cdi_flash_write_page(); + cdi_addr += 2048; /*increment page address*/ + pause_ms(10); + } + else + { + return -1; + } + return 0; +} + +int cdi_flash_write_mac(uint8_t *ptr) +{ + uint16_t i, retval; + uint8_t out[3]; + + cdi_addr = 0x1F800; /*last page*/ + + printf("0x%6.6X", cdi_addr); + fflush(stdout); + cdi_dptr_write(0xEFF8); /*our page data buffer is here*/ + for (i=0; i<8; i++) + { + cdi_xdata_write(*ptr++); + if ((i & 0x0F) == 0) + { + printf("."); + fflush(stdout); + } + } + + out[0] = CDI_HALT; + cdi_command_push(out, 1, &retval, 8); + + out[0] = CDI_READ_STATUS; + retval = 0; + cdi_command_push(out, 1, &retval, 8); + if ((retval & 0xFF) == 0xB2) + { + /*restore config*/ + out[0] = CDI_WR_CONFIG; /*command length 3 bytes*/ + out[1] = 0x0E; /*write flash area*/ + cdi_command_push(out, 2, &retval, 0); + /*set flash timings and copy code to ram*/ + cdi_flash_init(); + /*write page*/ + cdi_flash_write_page(); + cdi_addr += 2048; /*increment page address*/ + pause_ms(10); + } + else + { + return -1; + } + return 0; +} + +int cdi_start(uint16_t *chip_id) +{ + uint8_t out[3]; + uint16_t retval; + + prog_start(); /*do the CDI startup sequence*/ + + out[0] = CDI_READ_STATUS; + cdi_command_push(out, 1, &retval, 8); + + printf("Status: %2.2X.\n", retval & 0xFF); + + out[0] = CDI_GET_CHIP_ID; + cdi_command_push(out, 1, &retval, 16); + + *chip_id = retval; + + out[0] = CDI_HALT; + cdi_command_push(out, 1, &retval, 8); + + pause_ms(100); + + out[0] = CDI_WR_CONFIG; /*command length 3 bytes*/ + out[1] = 0x0E; /*write flash area*/ + cdi_command_push(out, 2, &retval, 0); + + pause_ms(10); + + cdi_reg_write(0xC6, 0xC9); /*sfr = CLKCON*/ + + pause_ms(10); + + cdi_reg_write(0xAB, 0x15); /*sfr = FWT*/ + + cdi_addr = 0; + + return 0; +} + +int cdi_erase(void) +{ + uint8_t out[3]; + uint16_t retval; + uint8_t i; + + out[0] = CDI_WR_CONFIG; + out[1] = 0x0E; + cdi_command_push(out, 2, &retval, 0); + out[0] = CDI_CHIP_ERASE; + cdi_command_push(out, 1, &retval, 0); + retval = 0; + i = 0; + do + { + pause_ms(30); + out[0] = CDI_READ_STATUS; + cdi_command_push(out, 1, &retval, 8); + }while( ((retval & 0x84) != 0x80) && (i++ < 100) ); + + cdi_addr = 0; + + if (i >= 100) + { + return -1; + } + return 0; +} + +void cdi_set_address(uint32_t address) +{ + cdi_addr = address; +} diff --git a/tools/sensinode/nano_usb_programmer/cdi.h b/tools/sensinode/nano_usb_programmer/cdi.h new file mode 100644 index 000000000..40e909178 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/cdi.h @@ -0,0 +1,44 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#ifndef _CDI_H +#define _CDI_H + +#include "prog.h" + +/* export these */ +extern int cdi_start(uint16_t *chip_id); +extern int cdi_erase(void); + +extern void cdi_set_address(uint32_t address); + +extern void cdi_flash_read(uint8_t *ptr, uint16_t bytes); +extern int cdi_flash_write(uint8_t *ptr, uint16_t length); + +#endif diff --git a/tools/sensinode/nano_usb_programmer/ftdi_linux/WinTypes.h b/tools/sensinode/nano_usb_programmer/ftdi_linux/WinTypes.h new file mode 100644 index 000000000..4def457b7 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ftdi_linux/WinTypes.h @@ -0,0 +1,116 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#ifndef __WINDOWS_TYPES__ +#define __WINDOWS_TYPES__ + +#define MAX_NUM_DEVICES 50 +#include + +typedef unsigned long DWORD; +typedef unsigned long ULONG; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned char UCHAR; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef unsigned char *LPBYTE; +typedef int BOOL; +typedef char BOOLEAN; +typedef char CHAR; +typedef int *LPBOOL; +typedef unsigned char *PUCHAR; +typedef const char *LPCSTR; +typedef char *PCHAR; +typedef void *PVOID; +typedef void *HANDLE; +typedef long LONG; +typedef int INT; +typedef unsigned int UINT; +typedef char *LPSTR; +typedef char *LPTSTR; +typedef DWORD *LPDWORD; +typedef WORD *LPWORD; +typedef ULONG *PULONG; +typedef PVOID LPVOID; +typedef void VOID; +typedef unsigned long long int ULONGLONG; + +typedef struct _OVERLAPPED { + DWORD Internal; + DWORD InternalHigh; + DWORD Offset; + DWORD OffsetHigh; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +typedef struct _SECURITY_ATTRIBUTES { + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; + +typedef struct timeval SYSTEMTIME; +typedef struct timeval FILETIME; +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +// +// Modem Status Flags +// +#define MS_CTS_ON ((DWORD)0x0010) +#define MS_DSR_ON ((DWORD)0x0020) +#define MS_RING_ON ((DWORD)0x0040) +#define MS_RLSD_ON ((DWORD)0x0080) + +// +// Error Flags +// + +#define CE_RXOVER 0x0001 // Receive Queue overflow +#define CE_OVERRUN 0x0002 // Receive Overrun Error +#define CE_RXPARITY 0x0004 // Receive Parity Error +#define CE_FRAME 0x0008 // Receive Framing error +#define CE_BREAK 0x0010 // Break Detected +#define CE_TXFULL 0x0100 // TX Queue is full +#define CE_PTO 0x0200 // LPTx Timeout +#define CE_IOE 0x0400 // LPTx I/O Error +#define CE_DNS 0x0800 // LPTx Device not selected +#define CE_OOP 0x1000 // LPTx Out-Of-Paper +#define CE_MODE 0x8000 // Requested mode unsupported + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE 0xFFFFFFFF +#endif + +#endif diff --git a/tools/sensinode/nano_usb_programmer/ftdi_linux/ftd2xx.h b/tools/sensinode/nano_usb_programmer/ftdi_linux/ftd2xx.h new file mode 100644 index 000000000..f4146f1d8 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ftdi_linux/ftd2xx.h @@ -0,0 +1,975 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +/*++ + +Copyright (c) 2001-2006 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB interface for FTDI FT8U232/245/2232C + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + /03/04 st modified for linux users + 12/10/04 st added FT_SetVIDPID + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +#ifndef _WINDOWS +#include +#define WINAPI +#endif + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + +#ifndef _WINDOWS +#include "WinTypes.h" + +#ifdef FTD2XX_API +#undef FTD2XX_API +#define FTD2XX_API +#endif +#endif +typedef struct _EVENT_HANDLE{ + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; +} EVENT_HANDLE; + +typedef DWORD *FT_HANDLE; + +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, //7 + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R + }; + + +#ifdef __cplusplus +extern "C" { +#endif + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS FT_SetVIDPID( + DWORD dwVID, + DWORD dwPID + ); + +FTD2XX_API +FT_STATUS FT_GetVIDPID( + DWORD * pdwVID, + DWORD * pdwPID + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( // Linux, OS X: Not supported + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( // Linux, OS X: Not supported + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( // Linux, OS X: Not supported + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // FT2232C extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // FT232R extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + + UCHAR RIsVCP; // zero if using VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( // Linux, OS X: Not supported + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( // Linux, OS X: Not supported + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( // Linux, OS X: Not supported + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( // Linux, OS X: Not supported + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( // Linux, OS X: Not supported + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + +// +// Events +// + +#define EV_RXCHAR 0x0001 // Any Character received +#define EV_RXFLAG 0x0002 // Received certain character +#define EV_TXEMPTY 0x0004 // Transmitt Queue Empty +#define EV_CTS 0x0008 // CTS changed state +#define EV_DSR 0x0010 // DSR changed state +#define EV_RLSD 0x0020 // RLSD changed state +#define EV_BREAK 0x0040 // BREAK received +#define EV_ERR 0x0080 // Line status error occurred +#define EV_RING 0x0100 // Ring signal detected +#define EV_PERR 0x0200 // Printer error occured +#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full +#define EV_EVENT1 0x0800 // Provider specific event 1 +#define EV_EVENT2 0x1000 // Provider specific event 2 + +// +// Escape Functions +// + +#define SETXOFF 1 // Simulate XOFF received +#define SETXON 2 // Simulate XON received +#define SETRTS 3 // Set RTS high +#define CLRRTS 4 // Set RTS low +#define SETDTR 5 // Set DTR high +#define CLRDTR 6 // Set DTR low +#define RESETDEV 7 // Reset device if possible +#define SETBREAK 8 // Set the device break line. +#define CLRBREAK 9 // Clear the device break line. + +// +// PURGE function flags. +// +#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. +#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. +#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. +#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. + + + + + + + + + + + + + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + + + + + + diff --git a/tools/sensinode/nano_usb_programmer/ftdi_win32/ftd2xx.h b/tools/sensinode/nano_usb_programmer/ftdi_win32/ftd2xx.h new file mode 100755 index 000000000..fd15376f8 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ftdi_win32/ftd2xx.h @@ -0,0 +1,923 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +/*++ + +Copyright (c) 2001-2006 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB device driver for FTDI FT8U232/245 + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + 23/01/04 awm Added support for open-by-location. + 16/03/04 awm Added support for FT2232C. + 23/09/04 awm Added support for FT232R. + 20/10/04 awm Added FT_CyclePort. + 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. + 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. + 25/08/05 awm Added FT_SetDeadmanTimeout. + 02/12/05 awm Removed obsolete references. + 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. + 08/09/06 awm Added FT_W32_GetCommMask. + 11/09/06 awm Added FT_Rescan. + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR, + FT_DEVICE_LIST_NOT_READY, +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // FT2232C extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // FT232R extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + + UCHAR RIsD2XX; // non-zero if using D2XX driver + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCTSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommMask( + FT_HANDLE ftHandle, + LPDWORD lpdwEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + +FTD2XX_API +FT_STATUS WINAPI FT_Rescan( + void + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Reload( + WORD wVid, + WORD wPid + ); + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + diff --git a/tools/sensinode/nano_usb_programmer/ihex.c b/tools/sensinode/nano_usb_programmer/ihex.c new file mode 100644 index 000000000..a7889e57b --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ihex.c @@ -0,0 +1,210 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#include +#include +#include +#include + +#include + +int hexfile_build_tables(char *ihexfile, unsigned char *page_buffer, unsigned char *page_table) +{ + unsigned char buffer[256]; + int length; + int i; + int pages; + + unsigned long ext_addr=0; + unsigned short int addr=0; + FILE *ihex_fp; + + if((ihex_fp = (FILE *)fopen(ihexfile, "r")) == NULL) + { + printf("Failed to open .ihex file %s\n", ihexfile); + return(-1); + } + else + { + printf(".ihex file ok.\n"); + } + + bzero(buffer, sizeof(buffer)); + + /*initialize page data*/ + memset(page_table, 0, 64); + memset(page_buffer, 0xFF, sizeof(page_buffer)); + pages = 0; + + while((fscanf(ihex_fp, "%s", buffer) == 1)) + { + unsigned char data_len = 0; + + if (memcmp(&buffer[7], "00", 2) == 0) + { /*Data record*/ + i=0; + sscanf((char *)&buffer[1], "%2hhx", &data_len); + sscanf((char *)&(buffer[3]),"%4hx", &addr); + while(i> 8; + cksum += *addr & 0xFF; + cksum += *type; + + i = 0; + if (retval == 3) + { + while(i < row_len) + { + + if (sscanf(&line[row_index], "%2x", &tmp) == 1) + { + cksum += tmp; + buffer[i++] = (unsigned char) tmp; + row_index += 2; + } + else return -1; + } + if (sscanf(&line[row_index], "%2x", &tmp) == 1) + { + if ((cksum + (uint8_t) tmp) == 0) return row_len; + } + } + return -1; +} + +int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes) +{ + uint8_t cksum = 0; + uint8_t i = 0; + char tmp[8]; + + sprintf(line, ":%2.2X%4.4X%2.2X", bytes, address, type); + cksum -= bytes; + cksum -= address >> 8; + cksum -= address & 0xFF; + cksum -= type; + + for (i=0; i +#include +#include +#include +#include + +#include +#ifdef PLATFORM_WINDOWS +#include +#endif +#include "prog.h" + +#define PRG_VERSION "1.3" + +typedef enum +{ + USAGE, + VERSION, + SCAN, + WRITE, + READ, + WRITE_MAC, + READ_MAC, + ERASE +}mode_t; + +typedef struct opts_t +{ + int port; + mode_t mode; + uint8_t write_mac[8]; + char *filename; +}opts_t; + +opts_t opts; + +void usage(char *prg_name) +{ + printf("\nUsage: %s [-p port] [-h] [-v] [-f file] [-r] [-w] [-m] [-M ]\n", prg_name); + printf("General options:\n"); + printf(" -p/--port [port] Select FTDI device\n"); + printf(" -f/--file [filename] File to read/write\n"); + printf("Operating modes:\n"); + printf(" -d/--devices Scan available devices\n"); + printf(" -v/--version Print program version\n"); + printf(" -r/--read Read program code into ihex file (see -f)\n"); + printf(" -w/--write Program firmware from ihex file (see -f)\n"); + printf(" -m/--read-mac Read device MAC address\n"); + printf(" -M/--write-mac xx:xx:xx:xx:xx:xx:xx:xx Write device MAC address\n"); + printf(" -e/--erase Erase flash (erases MAC address!)\n"); + printf("Defaults:\n"); + printf("mode = usage\n"); + printf("port = undefined\n"); + printf("file = stdout\n"); +} + +int main(int argc, char *argv[]) +{ + DWORD dwBytesInQueue = 0; + FT_STATUS ftStatus; + FT_HANDLE ftHandle; + unsigned char ucMode = 0x00; + int i=0; + unsigned char wr[1] = { 0x30 }; + unsigned char rd[1]; + uint16_t chip_id; + + if (opts_parse(argc, argv) < 0) + { + usage(argv[0]); + return -1; + } + switch(opts.mode) + { + case VERSION: + printf("Sensinode Nano USB Programmer version %s\n", PRG_VERSION); + return 0; + + case USAGE: + usage(argv[0]); + return 0; + + case SCAN: + prog_scan(); + return 0; + + case ERASE: + case READ: + case WRITE: + case READ_MAC: + case WRITE_MAC: + break; + } + + printf("Opening programmer.\n"); + ftHandle = prog_open(opts.port); + if (ftHandle == 0) + { + return (-1); + } + + cdi_start(&chip_id); + + printf("Chip ID = %4.4hX.\n", chip_id); + + if ((chip_id & 0xFF00) == 0x8500) + { + printf("CC2430 chip found.\n"); + } + else if ((chip_id & 0xFF00) == 0x8900) + { + printf("CC2431 chip found.\n"); + } + else + { + printf("Unknown chip found.\n"); + opts.mode = USAGE; + } + + switch(opts.mode) + { + case VERSION: + case USAGE: + break; + + case ERASE: + printf("Erase.\n"); + break; + + case READ: + printf("Read Flash.\n"); + cdi_set_address(0); + break; + + case WRITE: + { + int rval; + unsigned char page_table[64]; + unsigned char page_buffer[128*1024]; + + printf("Write Flash.\n"); + + if((rval = hexfile_build_tables(opts.filename, page_buffer, page_table)) == -1) + { + printf("Error\n"); + return(-1); + } + else if(rval == 0) + { + printf(".ihex file OK but nothing to write...\n"); + return(1); + } + + hexfile_program(page_buffer, page_table); + + break; + } + case READ_MAC: + printf("Read MAC: "); + cdi_set_address(0x1FFF8); + { + uint8_t mac[8]; + + cdi_flash_read(mac, 8); + for (i=0; i<8; i++) + { + if (i) printf(":"); + printf("%2.2X", mac[i]); + } + printf("\n"); + } + break; + + case WRITE_MAC: + printf("Write MAC: "); +/* cdi_set_address(0x1F800); + { + uint8_t block[2048]; + + memset(block, 0xFF, 2048); + for (i=0; i<8; i++) + { + block[2040+i] = opts.write_mac[i]; + } + cdi_flash_write(block, 2048); + printf("\n"); + }*/ + cdi_flash_write_mac(opts.write_mac); + printf("\n"); + break; + + default: + printf("Duh\n"); + break; + } + + + printf("Closing programmer.\n"); + prog_close(); +} + +static int option_index = 0; + +int do_exit = 0; + +#define OPTIONS_STRING "p:vdhf:rwmM:e" +/* long option list */ +static struct option long_options[] = +{ + {"port", 1, NULL, 'p'}, + {"version", 0, NULL, 'v'}, + {"devices", 0, NULL, 'd'}, + {"help", 0, NULL, 'h'}, + {"file", 1, NULL, 'f'}, + {"read", 0, NULL, 'r'}, + {"write", 0, NULL, 'w'}, + {"read-mac", 0, NULL, 'm'}, + {"write-mac", 1, NULL, 'M'}, + {"erase", 0, NULL, 'e'}, + {0, 0, 0, 0} +}; + +int opts_parse(int count, char* param[]) +{ + int opt; + int error=0; + + opts.mode = USAGE; + opts.filename = 0; + while ((opt = getopt_long(count, param, OPTIONS_STRING, + long_options, &option_index)) != -1) + { + fflush(stdout); + switch(opt) + { + case 'p': + opts.port = 0; + if (sscanf(optarg, "%d", &(opts.port)) != 1) + { + if (sscanf(optarg, "/dev/ttyUSB%d", &(opts.port)) != 1) + { + printf("Invalid port.\n"); + opts.mode = USAGE; + return 0; + } + } + printf("Port %d.\n", opts.port); + break; + + case 'v': + opts.mode = VERSION; + return 0; + + case 'd': + opts.mode = SCAN; + return 0; + + case 'h': + opts.mode = USAGE; + return 0; + + case 'e': + opts.mode = ERASE; + break; + + case 'f': + printf("Filename: %s\n", optarg); + opts.filename = malloc(strlen(optarg)+1); + strcpy(opts.filename, optarg); + break; + + case 'r': + opts.mode = READ; + break; + + case 'w': + opts.mode = WRITE; + break; + + case 'm': + opts.mode = READ_MAC; + break; + + case 'M': + opts.mode = WRITE_MAC; + if (sscanf(optarg, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &opts.write_mac[0], &opts.write_mac[1], + &opts.write_mac[2], &opts.write_mac[3], + &opts.write_mac[4], &opts.write_mac[5], + &opts.write_mac[6], &opts.write_mac[7]) != 8) + { + printf("Invalid MAC.\n"); + opts.mode = USAGE; + } + else + { + printf("MAC to write: %2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX\n", + opts.write_mac[0], opts.write_mac[1], + opts.write_mac[2], opts.write_mac[3], + opts.write_mac[4], opts.write_mac[5], + opts.write_mac[6], opts.write_mac[7]); + } + break; + + case '?': + printf("Duh\n"); + error = -1; + break; + } + } + + return error; +} + diff --git a/tools/sensinode/nano_usb_programmer/prog.c b/tools/sensinode/nano_usb_programmer/prog.c new file mode 100644 index 000000000..1cce8ec83 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/prog.c @@ -0,0 +1,372 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#include +#include +#ifdef PLATFORM_WINDOWS +#include +#endif +#include + +FT_HANDLE curr_handle = 0; +uint8_t curr_mode = 0; /* 0 = in, 1=out */ + +/* + * This function checks if the CBUS2 ise set to SLEEP and modifies it if necessary. + * The CBUS2 must be set to sleep in order the programming to succeed. + */ +int check_cbus2(FT_HANDLE fthandle) +{ + FT_PROGRAM_DATA eeprom_data; + char manufacturer_buf[32]; + char manufacturer_id[16]; + char description_buf[64]; + char serialnumber_buf[16]; + eeprom_data.Signature1 = 0x00000000; // This is a given value from the FT232R programming guide + eeprom_data.Signature2 = 0xffffffff; // This is a given value from the FT232R programming guide + eeprom_data.Version = 0x00000002; // This is a given value from the FT232R programming guide + eeprom_data.Manufacturer = manufacturer_buf; + eeprom_data.ManufacturerId = manufacturer_id; + eeprom_data.Description = description_buf; + eeprom_data.SerialNumber = serialnumber_buf; + + + if(FT_EE_Read(fthandle, &eeprom_data) != FT_OK) + { + printf("FTDI EEPROM read failed.\n"); + return(-1); + } + + if(eeprom_data.Cbus2 != 0x05) + { + printf("Need to re-program the CBUS2 to 0x05\n"); + eeprom_data.Cbus2 = 0x05; + + if(FT_EE_Program(fthandle, &eeprom_data) != FT_OK) + { + printf("FTDI EEPROM program error.\n"); + return(-1); + } + else + { + printf("FTDI EEPROM program ok\n"); + return(1); + } + } + else + { + return(1); + } + + return(1); +} + + +void prog_scan(void) +{ + FT_STATUS ftStatus; + FT_DEVICE_LIST_INFO_NODE *info; + unsigned long n_devices = 0; + uint8_t out; + + ftStatus = FT_CreateDeviceInfoList(&n_devices); + if (ftStatus == FT_OK) + { + FT_DEVICE_LIST_INFO_NODE devices[n_devices]; + + ftStatus = FT_GetDeviceInfoList(devices,&n_devices); + if (ftStatus == FT_OK) + { + for (out = 0; out < n_devices; out++) + { + printf("Dev %d:",n_devices - out -1); + printf(" Type=0x%x",devices[n_devices - out -1].Type); + printf(" SerialNumber=%s",devices[n_devices - out -1].SerialNumber); + printf(" Description=%s\n",devices[n_devices - out -1].Description); + } + } + else + { + printf("Failed to fetch device list.\n"); + } + } + else + { + printf("Failed to fetch device list.\n"); + } +} + +FT_HANDLE prog_open(int iport) +{ + FT_HANDLE ftHandle; + FT_STATUS ftStatus; + FT_DEVICE_LIST_INFO_NODE *info; + unsigned long n_devices = 0; + uint8_t out; + + if (curr_handle) return 0; + + ftStatus = FT_CreateDeviceInfoList(&n_devices); + if (ftStatus == FT_OK) + { + FT_DEVICE_LIST_INFO_NODE devices[n_devices]; + + ftStatus = FT_GetDeviceInfoList(devices,&n_devices); + if (ftStatus == FT_OK) + { + iport = n_devices - iport - 1; + + if (iport < 0) + { + printf("Invalid port id.\n"); + for (out = 0; out < n_devices; out++) + { + printf("Dev %d:",n_devices - out -1); + printf(" Type=0x%x",devices[n_devices - out -1].Type); + printf(" SerialNumber=%s",devices[n_devices - out -1].SerialNumber); + printf(" Description=%s\n",devices[n_devices - out -1].Description); + } + return 0; + } + } + } + + ftStatus = FT_Open(iport, &ftHandle); + if(ftStatus != FT_OK) { + /* + This can fail if the ftdi_sio driver is loaded + use lsmod to check this and rmmod ftdi_sio to remove + also rmmod usbserial + */ + printf("FT_Open(%d) failed\n", iport); + return 0; + } + + if(check_cbus2(ftHandle) < 0) + { + printf("Nano USB Programmer exiting...\n"); + return(0); + } + + FT_ResetDevice(ftHandle); + + FT_SetBaudRate(ftHandle, 115200); + + FT_SetUSBParameters(ftHandle, 64, 0); + + out = 0x04; + + ftStatus = FT_SetBitMode(ftHandle, out, 0x20); + if (ftStatus == FT_OK) + { + ftStatus = FT_SetLatencyTimer(ftHandle, 2); + } + if (ftStatus == FT_OK) + { + DWORD bytes; + out = 0xE0; + ftStatus = FT_SetBitMode(ftHandle, out, 0x04); + out = 0x80; + FT_Write(ftHandle, &out, 1, &bytes); /*write reset high*/ + FT_Read(ftHandle, &out, 1, &bytes); /*read out*/ + curr_mode = 1; + } + if (ftStatus != FT_OK) + { + printf("Failed to set CBUS2/bit bang mode.\n"); + + FT_ResetDevice(ftHandle); + sleep(3); + FT_Close(ftHandle); + ftHandle = 0; + } + curr_handle = ftHandle; + return ftHandle; +} + +void prog_close(void) +{ + FT_STATUS ftStatus; + DWORD bytes; + + if (curr_handle) + { + FT_HANDLE ftHandle = curr_handle; + uint8_t out = 0x00; + + FT_Write(ftHandle, &out, 1, &bytes); /*write reset low*/ + FT_Read(ftHandle, &out, 1, &bytes); /*read out*/ + sleep(1); + out = 0x80; + FT_Write(ftHandle, &out, 1, &bytes); /*write reset high*/ + FT_Read(ftHandle, &out, 1, &bytes); /*read out*/ + sleep(1); + out = 0x00; + ftStatus = FT_SetBitMode(ftHandle, out, 0x04); + FT_ResetDevice(ftHandle); + FT_Close(ftHandle); + + ftHandle = 0; + curr_handle = ftHandle; + } +} + +int prog_write(uint8_t byte) +{ + FT_STATUS ftStatus; + uint8_t out[16]; + uint8_t mask = 0x80; + int i; + DWORD bytes; + + if (curr_mode == 0) + { + out[0] = 0xE0; + ftStatus = FT_SetBitMode(curr_handle, out[0], 0x04); /*Set DD as output*/ + if (ftStatus != FT_OK) + { printf("!WR"); + fflush(stdout); + return -1; + } + curr_mode = 1; + } + i = 0; + while (mask) + { + out[i] = 0xC0; /*clock high, reset high*/ + if (byte & mask) out[i] |= 0x20; + i++; + out[i] = 0x80; /*clock low, reset high*/ + if (byte & mask) out[i] |= 0x20; + i++; + mask >>= 1; + } + ftStatus = FT_Write(curr_handle, out, 16, &bytes); /*write clock high and data bit*/ + if (ftStatus != FT_OK) + { + printf("!W"); + fflush(stdout); + return -1; + } + + if(FT_Read(curr_handle, out, 16, &bytes) != FT_OK) + { + printf("!R"); + return(-1); + } + + return 0; +} + +int prog_read(uint8_t *byte) +{ + FT_STATUS ftStatus; + uint8_t rd; + uint8_t mask = 0x80; + DWORD bytes; + uint8_t out[17]; + uint8_t i=0; + + *byte = 0; + if (curr_mode == 1) + { + out[0] = 0xC0; + ftStatus = FT_SetBitMode(curr_handle, out[0], 0x04); /*Set DD as input*/ + if (ftStatus != FT_OK) + { printf("!RD"); + fflush(stdout); + return -1; + } + curr_mode = 0; + } + + while (mask) + { + out[i] = 0xC0; /*clock high, reset high*/ + if (*byte & mask) out[i] |= 0x20; + i++; + out[i] = 0x80; /*clock low, reset high*/ + if (*byte & mask) out[i] |= 0x20; + i++; + mask >>= 1; + } + + out[16] = out[15]; + + ftStatus = FT_Write(curr_handle, out, 17, &bytes); /*write clock high and data bit*/ + + if(FT_Read(curr_handle, out, 17, &bytes) != FT_OK) + { + printf("!R"); + return(-1); + } + + mask = 0x80; + i = 1; + while (mask) + { + if (out[i] & 0x20) *byte |= mask; + mask >>= 1; + i+=2; + } + + return 0; +} + +int prog_start(void) +{ + FT_STATUS ftStatus; + uint8_t wr; + uint8_t mask = 0x80; + DWORD bytes; + uint8_t out[16] = { 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80 }; + + printf("prog_start()\n"); + + if (curr_mode == 0) + { + wr = 0xE0; + + ftStatus = FT_SetBitMode(curr_handle, wr, 0x04); /*Set DD as output*/ + curr_mode = 1; + } + + if(FT_Write(curr_handle, out, 7, &bytes) != FT_OK) + { + printf("!W\n"); + return(-1); + } + + if(FT_Read(curr_handle, out, 7, &bytes) != FT_OK) + { + printf("!R\n"); + return(-1); + } + +} diff --git a/tools/sensinode/nano_usb_programmer/prog.h b/tools/sensinode/nano_usb_programmer/prog.h new file mode 100644 index 000000000..fc2107d47 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/prog.h @@ -0,0 +1,46 @@ +/* + NanoStack: MCU software and PC tools for IP-based wireless sensor networking. + + Copyright (C) 2006-2007 Sensinode Ltd. + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Address: + Sensinode Ltd. + Teknologiantie 6 + 90570 Oulu, Finland + + E-mail: + info@sensinode.com +*/ + + +#ifndef _PROG_H +#define _PROG_H + +#include "ftd2xx.h" +#include + +extern FT_HANDLE prog_open(int iport); +extern void prog_close(void); + +extern int prog_write(uint8_t byte); +extern int prog_read(uint8_t *byte); + +extern int prog_start(void); + +extern int check_cbus2(FT_HANDLE fthandle); + +#endif