├── .gitignore ├── Makefile ├── ftdi_dev.hpp ├── README.md ├── main.cpp ├── Options.hpp ├── ftdi_dev.cpp ├── Options.cpp └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CC = g++ 3 | CFLAGS = -I. -std=gnu++11 -D_DEBUG -ggdb `pkg-config --cflags libftdi1` 4 | LFLAGS = `pkg-config --libs libftdi1` 5 | TARGET = ftdi_prog 6 | 7 | HEADERS = Options.hpp ftdi_dev.hpp 8 | SOURCES = Options.cpp ftdi_dev.cpp main.cpp 9 | 10 | OBJS = $(patsubst %.cpp, %.o, $(SOURCES)) 11 | 12 | 13 | .PHONY: default all clean 14 | 15 | default: $(TARGET) 16 | all: default 17 | 18 | %.o: %.cpp $(HEADERS) 19 | $(CC) $(CFLAGS) -c $< -o $@ 20 | 21 | $(TARGET): $(OBJS) 22 | $(CC) $(OBJS) -Wall $(LFLAGS) -o $@ 23 | 24 | clean: 25 | -rm -f $(OBJS) 26 | -rm -f $(TARGET) 27 | -rm -f *.cpp~ *.hpp~ Makefile~ 28 | -------------------------------------------------------------------------------- /ftdi_dev.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Header of FTDIDEV class 3 | 4 | Copyright (C) 2017 Alamy Liu 5 | 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | MA 02110-1301, USA. 21 | */ 22 | 23 | 24 | #ifndef _FTDIDEV_HPP_ 25 | #define _FTDIDEV_HPP_ 26 | 27 | #include // malloc, free 28 | #include // ifstream, ofstream 29 | #include // memcpy 30 | #include 31 | #include "Options.hpp" 32 | 33 | 34 | /* copied from libftdi::ftdi_i.h */ 35 | #define FTDI_MAX_EEPROM_SIZE (256) /* MUST fit in INT */ 36 | 37 | 38 | using namespace std; 39 | 40 | 41 | enum EEPROM_BUFFER_INDEX { 42 | I, /* In */ 43 | O, /* Out */ 44 | EEPROM_BUFFER_INDEX_MAX 45 | }; 46 | 47 | 48 | class FTDIDEV { 49 | 50 | private: 51 | /* FTDI */ 52 | struct ftdi_context *ftdi; 53 | bool eeprom_blank; 54 | 55 | unsigned char file_buf[FTDI_MAX_EEPROM_SIZE]; 56 | unsigned int eeprom_buf_size[EEPROM_BUFFER_INDEX_MAX]; /* might be File size or EEPROM size */ 57 | 58 | protected: 59 | int read_file(string path); 60 | int write_file(string path); 61 | 62 | int read_eeprom(); 63 | int write_eeprom(); 64 | 65 | int update_string( enum ftdi_eeprom_value value_name, string s ); 66 | 67 | 68 | public: 69 | /* Constructor / Destructor */ 70 | FTDIDEV( Options *opt ); /* set opt to NULL for file only operation */ 71 | /* TODO: able to set chip type 72 | FTDIDEV( int vid, int pid, enum ftdi_chip_type type ); // set chip type 73 | */ 74 | ~FTDIDEV(); 75 | 76 | bool is_EEPROM_blank() { return eeprom_blank; } 77 | 78 | int get_eeprom_size(void) { 79 | int size = 0; 80 | 81 | if (ftdi) { 82 | ftdi_get_eeprom_value(ftdi, CHIP_SIZE, &size); 83 | } 84 | return size; 85 | } 86 | 87 | void set_buffer_sizes(unsigned int iSize, unsigned oSize) { 88 | eeprom_buf_size[I] = iSize; 89 | eeprom_buf_size[O] = oSize; 90 | } 91 | 92 | 93 | int read(bool isInFTDIDEV, string fName, bool verboseMode); 94 | int write(bool isOutFTDIDEV, string fName, bool verboseMode); 95 | 96 | int decode(int verbose); 97 | int encode(int verbose __attribute__((unused))) 98 | { return ftdi_eeprom_build(ftdi); } 99 | 100 | void show_info(void); 101 | void dump(unsigned int buf_size); 102 | 103 | int update_vid( unsigned int vid ) 104 | { return ftdi_set_eeprom_value(ftdi, VENDOR_ID, vid); } 105 | int update_pid( unsigned int pid ) 106 | { return ftdi_set_eeprom_value(ftdi, PRODUCT_ID, pid); } 107 | 108 | int update_strings( 109 | char *m, /* manufacturer */ 110 | char *p, /* product */ 111 | char *s) /* serial */ 112 | { return ftdi_eeprom_set_strings(ftdi, m, p, s); } 113 | 114 | /* string interface not completed ... yet */ 115 | int update_manufacturer( string s ) 116 | { return update_strings(const_cast(s.c_str()), NULL, NULL); } 117 | int update_product( string s ) 118 | { return update_strings(NULL, const_cast(s.c_str()), NULL); } 119 | int update_serial( string s ) 120 | { return update_strings(NULL, NULL, const_cast(s.c_str())); } 121 | 122 | 123 | }; /* class Options */ 124 | 125 | #endif /* _FTDIDEV_HPP_ */ 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ftdi_prog 2 | The Linux alternative to the FTDI Utility FT_PROG 3 | 4 | ### Windows based FT Prog applicaion 5 | http://www.ftdichip.com/Support/Documents/AppNotes/AN_124_User_Guide_For_FT_PROG.pdf 6 | 7 | ### Required package 8 | - libftdi 1.4 (dev) 9 | - libusb-1.0.0-dev 10 | 11 | #### Install from package 12 | ``` 13 | $ sudo apt install libusb-1.0.0-dev 14 | $ sudo apt install libftdi1-dev 15 | ``` 16 | #### Compile libftdi1 from source 17 | Note: just an idea. You know what you are doing, tweak paths yourself. 18 | ``` 19 | $ cd 20 | $ mkdir BUILD; cd BUILD 21 | $ cmake -DCMAKE_INSTALL_PREFIX=~/local ../ 22 | $ make; make install 23 | 24 | ~/local 25 | |-- bin 26 | | `-- libftdi1-config 27 | |-- include 28 | | `-- libftdi1 29 | | `-- ftdi.h # <-- header 30 | `-- lib 31 | |-- cmake 32 | | `-- libftdi1 33 | | |-- LibFTDI1Config.cmake 34 | | |-- LibFTDI1ConfigVersion.cmake 35 | | `-- UseLibFTDI1.cmake 36 | |-- pkgconfig 37 | | |-- libftdi1.pc 38 | | `-- libftdipp1.pc 39 | |-- libftdi1.a 40 | |-- libftdi1.so -> libftdi1.so.2 41 | |-- libftdi1.so.2 -> libftdi1.so.2.4.0 42 | `-- libftdi1.so.2.4.0 # <-- library 43 | ``` 44 | 45 | ### Compile & Run 46 | If the local built libftdi1 is not installed in one of the system directories 47 | ``` 48 | $ export LD_LIBRARY_PATH=~/local/lib 49 | ``` 50 | Where it could find the **libftdi1.so.2.4.0** 51 | 52 | ``` 53 | $ cd 54 | $ make 55 | 56 | 57 | `-- ftdi_prog # <-- target binary 58 | ``` 59 | 60 | ### The code is based on LIBFTDI 1.4 61 | - Refer to /usr/local/include/libftdi1/ftdi.h 62 | 63 | ``` 64 | parameters 65 | | 66 | V 67 | +----------+ +----------+ +----------+ 68 | | Options | ---> | MAIN | <--> | FTDIDEV | 69 | +----------+ +----------+ +----------+ 70 | /--> | libftdi | 71 | FTDI device <----------------/ +----------+ 72 | 73 | ``` 74 | 75 | ### Procedure 76 | 1. Input (read: EEPROM or FILE: binary) 77 | 2. Decode (binary -> structure) 78 | 3. Update (modify fields in structure) 79 | 4. Encode (structure -> binary) 80 | 5. Output (write: EEPROM or FILE: binary) 81 | 82 | ``` 83 | ___________ ___________ 84 | / / / / 85 | INPUT / EEPROM / / FILE / 86 | / / / / 87 | ------------ ------------ 88 | \ (set_eeprom_buffer) 89 | \ / 90 | V V 91 | +----------+ 92 | DECODE | Decode | 93 | +----------+ 94 | | 95 | v 96 | +----------+ 97 | UPDATE | Update | 98 | +----------+ 99 | | 100 | v 101 | +----------+ 102 | ENCODE | Encode | 103 | +----------+ 104 | / \ 105 | / (get_eeprom_buffer) 106 | _______v___ __v________ 107 | / / / / 108 | OUTPUT / EEPROM / / FILE / 109 | / / / / 110 | ------------ ------------ 111 | ``` 112 | 113 | ### Data flow 114 | ```{.cpp} 115 | ---------------------------------------- 116 | libftdi 1.4 structure 117 | ---------------------------------------- 118 | 119 | /* Even on 93xx66 at max 256 bytes are used (AN_121) */ 120 | #define FTDI_MAX_EEPROM_SIZE 256 121 | 122 | struct ftdi_context # ftdi_new() 123 | { 124 | struct ftdi_eeprom *eeprom # eeprom structure 125 | { ^ | 126 | int vendor_id; | (ENCODE) 127 | int product_id; | | 128 | char *manufacturer; | | 129 | char *product; (DECODE) | 130 | ... | V 131 | unsigned char buf[FTDI_MAX_EEPROM_SIZE]; # eeprom binary 132 | } | ^ 133 | ... | | 134 | } (ftdi_get_eeprom_buf) | 135 | | | 136 | ---------------------------------------- | | 137 | This application | | 138 | ---------------------------------------- | (ftdi_set_eeprom_buf) 139 | class FTDIDEV | | 140 | { V | 141 | unsigned char file_buf[FTDI_MAX_EEPROM_SIZE]; # file_buf[] 142 | } 143 | ``` 144 | 145 | 146 | - References 147 | ftx-prog: https://github.com/richardeoin/ftx-prog 148 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2017 Alamy Liu 3 | 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 18 | MA 02110-1301, USA. 19 | */ 20 | 21 | /* Based on LIBFTDI 0.20.4 */ 22 | 23 | /* 24 | 1. Read binary (buffer) from EEPROM or FILE 25 | 2. (a) Decode: convert binary[IN] to ftdi_eeprom structure[IN] 26 | (b) copy ftdi_eeprom structure IN --> OUT 27 | 3. update ftdi_eeprom[OUT] 28 | 4. Build: convert ftdi_eeprom[OUT] to binary[OUT] 29 | 5. Write binary[OUT] to EEPROM or FILE 30 | */ 31 | 32 | #include 33 | #include 34 | //#include 35 | #include // malloc, free 36 | #include // ifstream, ofstream 37 | #include // setw, setfill, ... 38 | #include // atoi 39 | #include // getopt() 40 | //#include 41 | #include "Options.hpp" 42 | #include "ftdi_dev.hpp" 43 | //#include "DebugW.hpp" // Debug 44 | 45 | using namespace std; 46 | 47 | // Classes 48 | Options *opt; 49 | FTDIDEV *ftdi_dev; 50 | FILE *file; 51 | 52 | //Debug *dbg; /* Warning: should be created before List */ 53 | 54 | 55 | static void atexit_free_options(void) 56 | { 57 | // cout << __func__ << ":" << __LINE__ << endl; 58 | delete opt; 59 | } 60 | static void atexit_delete_ftdidev(void) 61 | { 62 | // cout << __func__ << ":" << __LINE__ << endl; 63 | delete ftdi_dev; 64 | } 65 | 66 | 67 | 68 | 69 | int main(int argc, char* argv[]) 70 | { 71 | int rc = EXIT_SUCCESS; 72 | 73 | try { 74 | opt = new Options(argc, argv); 75 | } catch (int e) { 76 | if (e != -ECANCELED) { 77 | cerr << "Unknown error: " << e << endl; 78 | } 79 | /* 'help' option exit */ 80 | exit( EXIT_SUCCESS ); 81 | } 82 | atexit( &atexit_free_options ); 83 | opt->applyHiddenRules(); 84 | opt->ShowOpts(); 85 | 86 | /* open FTDI device */ 87 | /* Allow fails: so that FTDIDEV methods could still be used. 88 | * i.e.: just browsing file content 89 | */ 90 | try { 91 | ftdi_dev = new FTDIDEV( opt ); 92 | } catch (std::runtime_error &e) { 93 | cerr << e.what() << endl; 94 | exit( EXIT_FAILURE ); 95 | } 96 | /* 97 | } catch (int e) { 98 | cerr << "Error: " << e << endl; 99 | exit( EXIT_FAILURE ); 100 | } 101 | */ 102 | atexit( &atexit_delete_ftdidev ); 103 | 104 | if (opt->isInFTDIDEV() || opt->isOutFTDIDEV()) { 105 | ftdi_dev->show_info(); /* debugging */ 106 | } 107 | 108 | /* At this point, we know 109 | * EEPROM size: from FTDIDEV 110 | * Input file size: from Options 111 | */ 112 | 113 | /* Options conflict/error detection (after we know EEPROM size) */ 114 | if (opt->validateOptions( ftdi_dev->get_eeprom_size() ) != 0) 115 | return EXIT_FAILURE; 116 | 117 | 118 | /* ---------- EEPROM ---------- */ 119 | 120 | /* 121 | * IN OUT size ? 122 | * FTDI file oSize = iSize = EEPROM size 123 | * FTDI FTDI oSize = iSize = EEPROM size 124 | * file file oSize = iSize 125 | * file FTDI just read EEPROM size (pad 0 or truncate) 126 | */ 127 | unsigned int iSize = 0, oSize = 0; 128 | if ( opt->isInFTDIDEV() || opt->isOutFTDIDEV() ) { 129 | iSize = oSize = ftdi_dev->get_eeprom_size(); 130 | } else { 131 | /* eeprom size type is INT, prevent overflow */ 132 | long fSize = min(opt->getInFileSize(), (long)FTDI_MAX_EEPROM_SIZE); 133 | oSize = iSize = static_cast(fSize); /* Safe: value in INT scope */ 134 | } 135 | cout << "Size (I,O) = " << iSize << ", " << oSize << endl; 136 | ftdi_dev->set_buffer_sizes(iSize, oSize); 137 | 138 | 139 | /* 140 | * 1. INPUT: Read from EEPROM or File 141 | */ 142 | if ( ftdi_dev->read( 143 | opt->isInFTDIDEV(), 144 | opt->getInFname(), 145 | opt->verboseMode()) < 0 ) 146 | { 147 | cerr << "Failed to Read!" << endl; 148 | return EXIT_FAILURE; 149 | } 150 | 151 | 152 | /* 153 | * 2. DECODE (binary -> structure) 154 | */ 155 | ftdi_dev->decode( opt->verboseMode() ); 156 | 157 | 158 | /* 159 | * 3. UPDATE 160 | */ 161 | /* Input Only or No Update: Skip UPDATE & ENCODE steps. 162 | * Note: still output data (if required) 163 | */ 164 | if ( !opt->isOutputDefined() || !opt->isUpdate() ) 165 | goto skip_update; 166 | 167 | if ( opt->isUpdate_vid() ) ftdi_dev->update_vid( opt->getUpdate_vid() ); 168 | if ( opt->isUpdate_pid() ) ftdi_dev->update_pid( opt->getUpdate_pid() ); 169 | #if 0 170 | if ( opt->isUpdate_manufacturer() ) 171 | eeprom->update_manufacturer( opt->getUpdate_manufacturer() ); 172 | if ( opt->isUpdate_product() ) 173 | eeprom->update_product( opt->getUpdate_product() ); 174 | if ( opt->isUpdate_serial() ) 175 | eeprom->update_serial( opt->getUpdate_serial() ); 176 | #else 177 | ftdi_dev->update_strings( 178 | opt->getUpdate_manufacturer(), 179 | opt->getUpdate_product(), 180 | opt->getUpdate_serial() 181 | ); 182 | #endif 183 | 184 | 185 | /* 186 | * 4. ENCODE (structure -> binary) 187 | */ 188 | /* if things go wrong, don't write out. But still like to show information */ 189 | try { 190 | if ( ftdi_dev->encode( opt->verboseMode() ) < 0 ) { 191 | cerr << "Something is wrong in ENCODING. No output!" << endl; 192 | opt->setOutNULL(); 193 | rc = EXIT_FAILURE; 194 | } 195 | } catch (int e) { 196 | cout << "Something is wrong (" << e << "). No output!" << endl; 197 | opt->setOutNULL(); 198 | rc = EXIT_FAILURE; 199 | } 200 | 201 | skip_update: 202 | /* show output information */ 203 | if ( opt->isOutputDefined() || opt->isUpdate() ) { 204 | if ( opt->viewBinary() ) ftdi_dev->dump( oSize ); /* Binary dump */ 205 | // if ( opt->viewHuman() ) ftdi_dev->showInOut(); /* Human readable */ 206 | } 207 | 208 | 209 | /* 210 | * 5. OUTPUT: Write to EEPROM or File 211 | */ 212 | /* Need to check isOutputDefined() here, as the _input only_ case 213 | * also comes here. 214 | */ 215 | if ( opt->isOutputDefined() ) { 216 | if ( ftdi_dev->write( 217 | opt->isOutFTDIDEV(), 218 | opt->getOutFname(), 219 | opt->verboseMode()) < 0 ) 220 | { 221 | cerr << "Failed to Write!" << endl; 222 | return EXIT_FAILURE; 223 | } 224 | } 225 | 226 | 227 | // delete dbg; 228 | return rc; 229 | } 230 | -------------------------------------------------------------------------------- /Options.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Header of Options class 3 | 4 | Copyright (C) 2017 Alamy Liu 5 | 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | MA 02110-1301, USA. 21 | */ 22 | 23 | 24 | #ifndef _OPTIONS_HPP_ 25 | #define _OPTIONS_HPP_ 26 | 27 | #include /* string */ 28 | #include // getopt_long() 29 | 30 | 31 | using namespace std; 32 | 33 | 34 | #define IN_OUT_EEPROM_NAME "EEPROM" 35 | 36 | 37 | typedef struct OPT_FLAGS_S { 38 | int verbose; /* Verbose mode */ 39 | 40 | int view_binary; /* Binary dump (eeprom_buffer) */ 41 | int view_human; /* Human readable (struct ftdi_eeprom) */ 42 | 43 | int open_bus; /* open usb with bus:dev */ 44 | int open_id; /* open usb with vid:pid */ 45 | 46 | int update; /* --update-xxx option */ 47 | 48 | int in_ftdidev; /* Read from FTDI Device (EEPROM) */ 49 | int out_ftdidev; /* Write to FTDI Device (EEPROM) */ 50 | } OPT_FLAGS_T; 51 | 52 | typedef struct OPT_UPDATE_S { 53 | unsigned int vid; 54 | unsigned int pid; 55 | #if 0 56 | string manufacturer; 57 | string product; 58 | string serial; 59 | #else 60 | char *manufacturer; 61 | char *product; 62 | char *serial; 63 | #endif 64 | } OPT_UPDATE_T; 65 | 66 | typedef struct OPT_VALUE_S { 67 | OPT_FLAGS_T flags; 68 | 69 | /* bus:devnum */ 70 | unsigned int bus; 71 | unsigned int dev; 72 | 73 | /* vid:pid */ 74 | unsigned int vid; 75 | unsigned int pid; 76 | 77 | string iFname; /* EEPROM, or Input file name */ 78 | string oFname; /* EEPROM, or Output file name */ 79 | 80 | long iFsize; /* Input file size (compare with EEPROM size) */ 81 | 82 | OPT_UPDATE_T update; 83 | 84 | } OPT_VALUE_T; 85 | 86 | 87 | class EEPROM; 88 | 89 | class Options { 90 | //friend class EEPROM; 91 | private: 92 | /* TODO: get rid of the size definition 93 | * 94 | * Options.hpp: error: too many initializers for ‘const option [0]’ 95 | */ 96 | const struct option long_opts[14] = { 97 | {"help", no_argument, NULL, 'h'}, 98 | 99 | {"verbose", no_argument, &(optValue.flags.verbose), 1}, 100 | 101 | {"show-binary", no_argument, &(optValue.flags.view_binary), 1}, 102 | {"show-human", no_argument, &(optValue.flags.view_human), 1}, 103 | 104 | /* -s [bus:dev] : similar to libusb */ 105 | {"bus", required_argument, NULL, 's'}, 106 | /* -d [vid:pid] : similar to libusb */ 107 | {"id", required_argument, NULL, 'd'}, 108 | 109 | {"in", required_argument, NULL, 'i'}, 110 | {"out", required_argument, NULL, 'o'}, 111 | 112 | #if 0 113 | {"manufacturer",required_argument, NULL, 0}, 114 | {"product" ,required_argument, NULL, 0}, 115 | {"max-bus-power",required_argument, NULL, 0}, 116 | #endif 117 | 118 | {"update-vid", required_argument, NULL, 'm'}, 119 | {"update-pid", required_argument, NULL, 'n'}, 120 | 121 | {"update-manufacturer", required_argument, NULL, 'x'}, 122 | {"update-product", required_argument, NULL, 'y'}, 123 | {"update-serial", required_argument, NULL, 'z'}, 124 | 125 | {NULL, 0, NULL, 0}, 126 | }; 127 | 128 | protected: 129 | 130 | OPT_VALUE_T optValue; /* values from parameters */ 131 | 132 | void setInFTDIDEV() { 133 | optValue.flags.in_ftdidev = 1; 134 | optValue.iFname.clear(); 135 | } 136 | void setOutFTDIDEV() { 137 | optValue.flags.out_ftdidev = 1; 138 | optValue.oFname.clear(); 139 | } 140 | void setOutFile( string fName ) { 141 | optValue.flags.out_ftdidev = 0; 142 | optValue.oFname = fName; 143 | } 144 | 145 | public: 146 | /* Constructor / Destructor */ 147 | Options(int argc, char* argv[]); 148 | ~Options() {} 149 | 150 | void applyHiddenRules( void ); 151 | int validateOptions( int eeprom_size ); 152 | 153 | int getBus() { return optValue.bus; } 154 | int getDev() { return optValue.dev; } 155 | bool isBusDefined() { 156 | return ((getBus() != 0) && (getDev() != 0)); 157 | } 158 | int getVid() { return optValue.vid; } 159 | int getPid() { return optValue.pid; } 160 | bool isIdDefined() { 161 | return ((getVid() != 0) && (getPid() != 0)); 162 | } 163 | 164 | bool verboseMode() { return optValue.flags.verbose; } 165 | 166 | bool viewBinary() { return optValue.flags.view_binary; } 167 | bool viewHuman() { return optValue.flags.view_human; } 168 | 169 | bool isInFTDIDEV() { return optValue.flags.in_ftdidev; } 170 | bool isOutFTDIDEV() { return optValue.flags.out_ftdidev; } 171 | 172 | string getInFname() { return optValue.iFname; } 173 | string getOutFname() { return optValue.oFname; } 174 | bool isInFile() { return !getInFname().empty(); } 175 | bool isOutFile() { return !getOutFname().empty(); } 176 | long getInFileSize() { return optValue.iFsize; } 177 | 178 | bool isInputDefined() { 179 | return ( isInFTDIDEV() || !getInFname().empty() ); 180 | } 181 | bool isOutputDefined() { 182 | return ( isOutFTDIDEV() || !getOutFname().empty() ); 183 | } 184 | void setOutNULL() { 185 | optValue.flags.out_ftdidev = 0; 186 | optValue.oFname.clear(); 187 | } 188 | 189 | 190 | bool isUpdate() { return optValue.flags.update; } 191 | bool isUpdate_vid() { return (getUpdate_vid() != 0x0); } 192 | bool isUpdate_pid() { return (getUpdate_pid() != 0x0); } 193 | 194 | #if 0 195 | bool isUpdate_manufacturer() { return !getUpdate_manufacturer().empty(); } 196 | bool isUpdate_product() { return !getUpdate_product().empty(); } 197 | bool isUpdate_serial() { return !getUpdate_serial().empty(); } 198 | #else 199 | bool isUpdate_manufacturer() { return (getUpdate_manufacturer() != NULL); } 200 | bool isUpdate_product() { return (getUpdate_product() != NULL); } 201 | bool isUpdate_serial() { return (getUpdate_serial() != NULL); } 202 | #endif 203 | 204 | unsigned int getUpdate_vid() { return optValue.update.vid; }; 205 | unsigned int getUpdate_pid() { return optValue.update.pid; }; 206 | 207 | #if 0 208 | string getUpdate_manufacturer() { return optValue.update.manufacturer; } 209 | string getUpdate_product() { return optValue.update.product; } 210 | string getUpdate_serial() { return optValue.update.serial; } 211 | #else 212 | char *getUpdate_manufacturer() { return optValue.update.manufacturer; } 213 | char *getUpdate_product() { return optValue.update.product; } 214 | char *getUpdate_serial() { return optValue.update.serial; } 215 | 216 | #endif 217 | 218 | void ShowHelp( void ); 219 | void ShowOpts( void ); 220 | 221 | 222 | }; /* class Options */ 223 | 224 | #endif /* _OPTIONS_HPP_ */ 225 | -------------------------------------------------------------------------------- /ftdi_dev.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation of FTDIDEV class 3 | 4 | Copyright (C) 2017 Alamy Liu 5 | 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | MA 02110-1301, USA. 21 | */ 22 | 23 | #include /* cout */ 24 | #include /* setw, setfill, ... */ 25 | #include /* assert */ 26 | #include "ftdi_dev.hpp" 27 | 28 | 29 | /* -------------------- Constructor / Destructor -------------------- */ 30 | 31 | #if 0 32 | FTDIDEV::FTDIDEV( int vid, int pid, enum ftdi_chip_type type ) 33 | : FTDIDEV( vid, pid ) 34 | { 35 | if (ftdi) { 36 | ftdi->type = type; 37 | } 38 | } 39 | #endif 40 | 41 | FTDIDEV::FTDIDEV( Options *opt ) 42 | { 43 | int rc; 44 | string err_string; 45 | 46 | /* Already created */ 47 | if (ftdi != NULL) { 48 | return; 49 | } 50 | 51 | if ((ftdi = ftdi_new()) == NULL) { 52 | err_string = "Failed to new FTDI!"; 53 | goto err_new; 54 | } 55 | 56 | 57 | /* Not really accessing USB device's EEPROM. i.e.: file */ 58 | if ( 59 | (opt == NULL) 60 | || ( !(opt->isInFTDIDEV() || opt->isOutFTDIDEV()) ) 61 | ) { 62 | return; 63 | } 64 | assert( opt->isBusDefined() || opt->isIdDefined() ); 65 | 66 | 67 | /* Open by bus:dev - ftdi_usb_open_bus_addr */ 68 | if ( opt->isBusDefined() ) { 69 | rc = ftdi_usb_open_bus_addr(ftdi, 70 | opt->getBus(), opt->getDev()); 71 | if (rc < 0) { 72 | goto err_open; 73 | } 74 | } 75 | /* Open by pid:vid - ftdi_usb_open */ 76 | if ( opt->isIdDefined() ) { 77 | rc = ftdi_usb_open(ftdi, 78 | opt->getVid(), opt->getPid()); 79 | if (rc < 0) { 80 | goto err_open; 81 | } 82 | } 83 | /* ToDo: Use ftdi_usb_open_desc() to specify _description_ & _serial_ of 84 | * the device 85 | */ 86 | 87 | 88 | /* IMPORTANT: Perform a EEPROM read to get eeprom size */ 89 | if ((rc = read_eeprom()) < 0) { 90 | goto err_open; 91 | } 92 | 93 | return; 94 | 95 | err_open: 96 | err_string = ftdi_get_error_string(ftdi); 97 | 98 | ftdi_free( ftdi ); 99 | ftdi = NULL; 100 | err_new: 101 | throw std::runtime_error( err_string ); 102 | // cerr << err_string << endl; 103 | // throw rc; 104 | } 105 | 106 | FTDIDEV::~FTDIDEV() 107 | { 108 | if (ftdi) { 109 | ftdi_usb_close( ftdi ); 110 | ftdi_free( ftdi ); 111 | ftdi = NULL; 112 | } 113 | } 114 | 115 | /* ------------------------------------------------------------------ */ 116 | 117 | int FTDIDEV::read_file(string path) 118 | { 119 | int rc; 120 | unsigned int buf_size; 121 | ifstream ifs( path, ios::in | ios::binary); 122 | 123 | /* if output is EEPROM, eeprom_buf_size[I] would be EEPROM size 124 | * see iSize, oSize in main() function. 125 | */ 126 | buf_size = eeprom_buf_size[I]; 127 | 128 | /* TODO: handle ERROR */ 129 | ifs.read( reinterpret_cast(file_buf), buf_size); 130 | ifs.close(); 131 | 132 | /* Copy data to EEPROM buffer */ 133 | // buffer size had been set by set_buffer_sizes() 134 | rc = ftdi_set_eeprom_buf(ftdi, file_buf, buf_size); 135 | if ( rc != 0 ) { 136 | cerr << "Fail to set EEPROM buffer" << endl; 137 | } 138 | 139 | /* CAUTION: Hacking libftdi to enable this feature */ 140 | ftdi_set_eeprom_value(ftdi, CHIP_SIZE, buf_size); 141 | 142 | return 0; 143 | } 144 | 145 | int FTDIDEV::write_file(string path) 146 | { 147 | int rc; 148 | unsigned int buf_size; 149 | ofstream ofs( path, ios::out | ios::trunc | ios::binary); 150 | 151 | /* Copy data from EEPROM buffer */ 152 | buf_size = eeprom_buf_size[O]; 153 | rc = ftdi_get_eeprom_buf(ftdi, file_buf, buf_size); 154 | if (rc < 0) { 155 | cerr << "Fail to get EEPROM buffer" << endl; 156 | return rc; 157 | } 158 | 159 | /* output size depends on input (EEPROM or file) */ 160 | ofs.write( reinterpret_cast(file_buf), buf_size); 161 | ofs.close(); 162 | 163 | return 0; 164 | } 165 | 166 | int FTDIDEV::read_eeprom() 167 | { 168 | int rc; 169 | 170 | if ( !ftdi ) return -ENODEV; 171 | 172 | if ((rc = ftdi_read_eeprom(ftdi)) < 0) { 173 | cerr << "Fail to Read EEPROM: " << rc 174 | << "(" << ftdi_get_error_string(ftdi) << ")" << endl; 175 | } 176 | 177 | /* size will also be set to -1 in the case of Blank EEPROM */ 178 | eeprom_blank = (get_eeprom_size() == -1); 179 | 180 | return rc; 181 | } 182 | 183 | int FTDIDEV::write_eeprom() 184 | { 185 | int rc; 186 | 187 | if ( !ftdi ) return -ENODEV; 188 | 189 | if ((rc = ftdi_write_eeprom(ftdi)) == 0) { 190 | cout << "Replug device to see the result!" << endl; 191 | } else { 192 | cerr << "Fail to Write EEPROM: " << rc 193 | << "(" << ftdi_get_error_string(ftdi) << ")" << endl; 194 | } 195 | 196 | return rc; 197 | } 198 | 199 | /* ------------------------------------------------------------------ */ 200 | 201 | int FTDIDEV::read(bool isInFTDIDEV, string fName, bool verboseMode) 202 | { 203 | int rc; 204 | 205 | if ( isInFTDIDEV ) { 206 | rc = read_eeprom(); 207 | /* data had been directly read into FTDI buffer */ 208 | } else { 209 | rc = read_file(fName); 210 | } 211 | 212 | if ( verboseMode ) { 213 | dump( eeprom_buf_size[I] ); 214 | } 215 | 216 | return rc; 217 | } 218 | 219 | int FTDIDEV::write(bool isOutFTDIDEV, string fName, bool verboseMode) 220 | { 221 | int rc; 222 | 223 | if ( verboseMode ) { 224 | dump( eeprom_buf_size[O] ); 225 | } 226 | 227 | if ( isOutFTDIDEV ) { 228 | rc = write_eeprom(); 229 | /* data had been directly read into FTDI buffer */ 230 | } else { 231 | rc = write_file(fName); 232 | } 233 | 234 | return rc; 235 | } 236 | 237 | /* ------------------------------------------------------------------ */ 238 | 239 | int FTDIDEV::decode(int verbose) 240 | { 241 | int rc; 242 | 243 | if ( !ftdi ) return -ENODEV; 244 | 245 | if ((rc = ftdi_eeprom_decode(ftdi, verbose)) < 0) { 246 | cerr << "Fail to Decode: " << rc << endl; 247 | if ( ftdi ) { 248 | cerr << "(" << ftdi_get_error_string(ftdi) << ")" << endl; 249 | } 250 | } 251 | 252 | return rc; 253 | } 254 | 255 | void FTDIDEV::show_info( void ) 256 | { 257 | char *ChipType[] = { 258 | (char *)"AM", 259 | (char *)"BM", 260 | (char *)"2232C", 261 | (char *)"R", 262 | (char *)"2232H", 263 | (char *)"4232H", 264 | (char *)"232H", 265 | (char *)"230X", 266 | }; 267 | 268 | if ( !ftdi ) { 269 | cerr << __func__ << ": FTDI device not available!" << endl; 270 | return; 271 | } 272 | 273 | cout << "Chip type: " << ChipType[ftdi->type] << endl; 274 | cout << "EEPROM size: " << get_eeprom_size() << endl; 275 | } 276 | 277 | void FTDIDEV::dump(unsigned int buf_size) 278 | { 279 | unsigned int offset, i; 280 | char ch; 281 | unsigned char *buf = file_buf; 282 | 283 | if (is_EEPROM_blank()) { 284 | buf_size = FTDI_MAX_EEPROM_SIZE; 285 | cout << "EEPROM is empty, use maximum size: " << buf_size << endl; 286 | } 287 | 288 | /* The data might already be in the *file_buf* 289 | * i.e.: Input from file_buf 290 | * Just copy it for other cases, don't bother to check 291 | */ 292 | /* Copy data from EEPROM buffer */ 293 | if (ftdi_get_eeprom_buf(ftdi, buf, buf_size) < 0) { 294 | cerr << "Fail to get EEPROM buffer" << endl; 295 | return; 296 | } 297 | 298 | cout << hex << setfill('0'); 299 | 300 | for(offset = 0; offset < buf_size; offset += 16) { 301 | 302 | /* show the offset */ 303 | cout << setw(8) << offset; 304 | 305 | /* show the hex codes */ 306 | for (i = 0; i < 16; i++) { 307 | if (i % 8 == 0) cout << ' '; 308 | if (offset + i < buf_size) 309 | cout << ' ' << setw(2) << (unsigned)(buf[offset + i]); 310 | else 311 | cout << " "; 312 | } 313 | 314 | /* show the ASCII */ 315 | cout << " "; 316 | for (i = 0; i < 16; i++) { 317 | if (offset + i < buf_size) { 318 | ch = buf[offset + i]; 319 | ch = ( ((ch >= 0x20) && (ch <= 0x7E)) ? ch : '.' ); 320 | } else { 321 | ch = '.'; 322 | } 323 | cout << ch; 324 | } 325 | cout << endl; 326 | 327 | } 328 | 329 | cout.unsetf(ios::hex); 330 | cout << endl; 331 | } 332 | -------------------------------------------------------------------------------- /Options.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation of Options class 3 | 4 | Copyright (C) 2017 Alamy Liu 5 | 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | MA 02110-1301, USA. 21 | */ 22 | 23 | #include /* getopt_long */ 24 | #include /* cout */ 25 | #include /* setw, setfill, ... */ 26 | #include /* ifstream, ofstream */ 27 | #include /* strcmp */ 28 | #include "Options.hpp" 29 | 30 | 31 | Options::Options( 32 | int argc, 33 | char* argv[] 34 | ) { 35 | // Retrieve options 36 | int opt_index = 0; 37 | int opt; 38 | char *token; 39 | int rc; 40 | 41 | while ( (opt = getopt_long(argc, argv, "hs:d:i:o:m:n:x:y:z:", 42 | long_opts, &opt_index)) != -1) { 43 | 44 | switch (opt) { 45 | case 'h': ShowHelp(); 46 | throw -ECANCELED; 47 | break; 48 | 49 | /* -s bus:devnum */ 50 | case 's': if ((token = strtok(optarg, ":")) == NULL) break; 51 | optValue.bus = stoi( token, nullptr, 0 ); 52 | if ((token = strtok( NULL, ":")) == NULL) break; 53 | optValue.dev = stoi( token, nullptr, 0 ); 54 | 55 | optValue.flags.open_bus = 1; 56 | break; 57 | 58 | /* -d vid/pid */ 59 | case 'd': if ((token = strtok(optarg, ":")) == NULL) break; 60 | optValue.vid = stoi( token, nullptr, 0 ); 61 | if ((token = strtok( NULL, ":")) == NULL) break; 62 | optValue.pid = stoi( token, nullptr, 0 ); 63 | 64 | optValue.flags.open_id = 1; 65 | break; 66 | 67 | /* In / Out */ 68 | case 'i': if (strcmp(optarg, IN_OUT_EEPROM_NAME) == 0) 69 | optValue.flags.in_ftdidev = 1; 70 | else 71 | optValue.iFname = string( optarg ); 72 | break; 73 | case 'o': if (strcmp(optarg, IN_OUT_EEPROM_NAME) == 0) 74 | optValue.flags.out_ftdidev = 1; 75 | else 76 | optValue.oFname = string( optarg ); 77 | break; 78 | 79 | #if 0 /* enabled by default */ 80 | /* verbose mode */ 81 | case 'v': optValue.flags.verbose = 1; break; 82 | case 'd': optValue.flags.view_binary = 1; break; 83 | case 'd': optValue.flags.view_human = 1; break; 84 | #endif 85 | 86 | /* ----- UPDATE ----- */ 87 | case 'm': optValue.flags.update = 1; 88 | optValue.update.vid = stoi( optarg, nullptr, 0 ); break; 89 | case 'n': optValue.flags.update = 1; 90 | optValue.update.pid = stoi( optarg, nullptr, 0 ); break; 91 | 92 | /* Manufacturer, Product, Serial */ 93 | #if 0 94 | case 'x': optValue.flags.update = 1; 95 | optValue.update.manufacturer = string( optarg ); break; 96 | case 'y': optValue.flags.update = 1; 97 | optValue.update.product = string( optarg ); break; 98 | case 'z': optValue.flags.update = 1; 99 | optValue.update.serial = string( optarg ); break; 100 | #else 101 | case 'x': optValue.flags.update = 1; 102 | optValue.update.manufacturer = optarg; break; 103 | case 'y': optValue.flags.update = 1; 104 | optValue.update.product = optarg; break; 105 | case 'z': optValue.flags.update = 1; 106 | optValue.update.serial = optarg; break; 107 | #endif 108 | 109 | case '?': /* Unknown option (ignore) */ 110 | default : /* Do nothing */ break; 111 | } // End of switch(opt) 112 | } // End of while(opt) 113 | 114 | 115 | /* ---------- Get extra information ---------- */ 116 | 117 | // Get input file size 118 | if ( isInFile() ) { 119 | ifstream in( getInFname(), ios::binary | ios::ate ); 120 | if ( in.good() ) 121 | optValue.iFsize = in.tellg(); 122 | in.close(); 123 | } 124 | 125 | } 126 | 127 | void Options::applyHiddenRules() 128 | { 129 | /* if IN/OUT were not defined, but Bus or ID are provided 130 | * { 131 | * set IN to FTDIDEV 132 | * } 133 | */ 134 | if ( !isInputDefined() 135 | && (isBusDefined() || isIdDefined()) ) 136 | { 137 | setInFTDIDEV(); 138 | } 139 | 140 | 141 | /* if OUT was not defined, but (any update-xxx is provided) 142 | * { 143 | * set OUT to IN 144 | * } 145 | */ 146 | if ( !isOutputDefined() && isUpdate() ) { 147 | if ( isInFTDIDEV() ) setOutFTDIDEV(); 148 | if ( isInFile() ) setOutFile( getInFname() ); 149 | } 150 | 151 | } 152 | 153 | int Options::validateOptions( int eeprom_size ) 154 | { 155 | /* Need Input, eithre from FTDIDEV or File */ 156 | if ( !isInputDefined() ) { 157 | cerr << "No Input (EEPROM or File) specified!" << endl; 158 | return EXIT_FAILURE; 159 | 160 | return -EINVAL; 161 | } 162 | 163 | /* FTDIDEV depends on Bus/ID */ 164 | if ( isInFTDIDEV() || isOutFTDIDEV() ) { 165 | if ( !(isBusDefined() || isIdDefined()) ) { 166 | cerr << "bus:dev or vid:pid is not provided!" << endl; 167 | return -EINVAL; 168 | } 169 | } 170 | 171 | /* Input file existence */ 172 | if ( isInFile() ) { 173 | /* check optValue.iFsize instead of opening file to check f.good() 174 | * as it had been done in Constructor 175 | */ 176 | if ( optValue.iFsize == 0 ) { 177 | cerr << "Input file, " << getInFname() 178 | << ", does not exist or size is zero!" << endl; 179 | return -EINVAL; 180 | } 181 | 182 | /* Input file size > EEPROM size */ 183 | if ( isOutFTDIDEV() && ( optValue.iFsize > eeprom_size ) ) { 184 | cerr << "Input file size (" 185 | << hex << optValue.iFsize << ") > EEPROM size (" 186 | << eeprom_size << ")!" << dec << endl; 187 | return -EINVAL; 188 | } 189 | } 190 | 191 | /* Output file overwrite: use ifstream to test, not typo */ 192 | if ( isOutFile() ) { 193 | ifstream out( getOutFname(), ios::binary | ios::ate ); 194 | if ( out.good() ) { 195 | cerr << "Output file, " << getOutFname() 196 | << ", already exists. Overwrite!" << endl; 197 | } 198 | 199 | /* Output file size depends on input device (EEPROM or File). 200 | * No need to verify 201 | */ 202 | 203 | out.close(); 204 | } 205 | 206 | return 0; 207 | } 208 | 209 | void Options::ShowHelp( void ) 210 | { 211 | cout << endl << "----- Help menu -----" << endl; 212 | cout << "help Help menu" << endl 213 | << "verbose Verbose mode" << endl 214 | << "show-binary Dump EEPROM binary data" << endl 215 | << "show-human Human readable (decode from binary)" << endl 216 | << "bus bus:dev (like lsusb)" << endl 217 | << "id vid:pid (like lsusb)" << endl 218 | << "in Input (EEPROM or filename)" << endl 219 | << "out Output (EEPROM or filename)" << endl 220 | << endl 221 | << "update-xxx update output field, where 'xxx' could be:" << endl 222 | << " vid VID field (update-vid)" << endl 223 | << " pid PID field (update-pid)" << endl 224 | << " manufacturer Manufacturer field" << endl 225 | << " product Product field" << endl 226 | << " serial Serial field" << endl 227 | << endl; 228 | } 229 | 230 | void Options::ShowOpts( void ) 231 | { 232 | cout.setf(ios::hex, ios::basefield); 233 | cout << setfill('0'); 234 | cout << "(bus:dev) = " 235 | << setw(3) << optValue.bus << ":" 236 | << setw(3) << optValue.dev << endl; 237 | cout << "(vid:pid) = " 238 | << setw(4) << optValue.vid << ":" 239 | << setw(4) << optValue.pid << endl; 240 | cout.unsetf(ios::hex); 241 | 242 | cout << "flag: open_bus = " 243 | << (optValue.flags.open_bus ? "Yes" : "No") << endl; 244 | cout << "flag: open_id = " 245 | << (optValue.flags.open_id ? "Yes" : "No") << endl; 246 | cout << "flag: verbose = " 247 | << (optValue.flags.verbose ? "Yes" : "No") << endl; 248 | cout << "flag: view_binary = " 249 | << (optValue.flags.view_binary ? "Yes" : "No") << endl; 250 | cout << "flag: view_human = " 251 | << (optValue.flags.view_human ? "Yes" : "No") << endl; 252 | cout << "flag: in_ftdidev = " 253 | << (optValue.flags.in_ftdidev ? "Yes" : "No") << endl; 254 | cout << "flag: out_ftdidev = " 255 | << (optValue.flags.out_ftdidev ? "Yes" : "No") << endl; 256 | 257 | cout << "In = " 258 | << (isInFile() 259 | ? ("(file) " + getInFname()) 260 | : (isInFTDIDEV() ? "EEPROM" : "(null)") ) << endl; 261 | cout << "Out = " 262 | << (isOutFile() 263 | ? ("(file) " + getOutFname()) 264 | : (isOutFTDIDEV() ? "EEPROM" : "(null)") ) << endl; 265 | 266 | cout << endl; 267 | } 268 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | --------------------------------------------------------------------------------