kbdupgrade.c

Go to the documentation of this file.
00001 /*
00002  * File Name  : kbdpower.c
00003  *
00004  * Description: Keyboard Firmware upgrader
00005  */
00006 
00007 /*
00008  * This file is part of kbdupgrade.
00009  *
00010  * kbdupgrade is free software: you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation, either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * kbdupgrade is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00022  */
00023 
00024 /**
00025  * Copyright (C) 2008 iRex Technologies B.V.
00026  * All rights reserved.
00027  */
00028  
00029 //----------------------------------------------------------------------------
00030 // Include Files
00031 //----------------------------------------------------------------------------
00032 
00033 // system include files, between < >
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 #include <termios.h>
00039 
00040 // local include files, between " "
00041 #include "proto.h"
00042 
00043 
00044 //----------------------------------------------------------------------------
00045 // Type Declarations
00046 //----------------------------------------------------------------------------
00047 
00048 
00049 //----------------------------------------------------------------------------
00050 // Global Constants
00051 //----------------------------------------------------------------------------
00052 
00053 #define ION_SERIO_FLAGS          CS8
00054 #define ION_SERIO_SPEED          B115200
00055 
00056 #define ACTION_FIRMWARE   1
00057 #define ACTION_BOOTLOADER 2
00058 #define ACTION_GASGAUGE   3
00059 #define ACTION_READTYPE   4
00060 #define ACTION_WRITETYPE  5
00061 
00062 #define DR1000            0
00063 
00064 #define VPRINTF(...) { if (verbose) printf(__VA_ARGS__); }
00065 
00066 static char *device_types[] = {
00067     "DR1000",
00068     "DR1000S",
00069     "DR1000SW",
00070     "DR800",
00071     "DR800S",
00072     "DR800SG",
00073     "DR800SW",
00074     NULL
00075 };
00076 
00077 
00078 //----------------------------------------------------------------------------
00079 // Static Variables
00080 //----------------------------------------------------------------------------
00081 
00082 static int action = ACTION_FIRMWARE;
00083 static int force_update = 0;
00084 static int only_check = 0;
00085 static int gg_req_version = 0;
00086 static int verbose = 1;
00087 char *filename;
00088 uint8_t devicetype;
00089 static int new_devicetype;
00090 
00091 
00092 //============================================================================
00093 // Local Function Definitions
00094 //============================================================================
00095 
00096 static void usage();
00097 static int check_firmware(char *filename, uint16_t *version);
00098 static void parse_args(int argc, char **argv);
00099 
00100 
00101 //============================================================================
00102 // Functions Implementation
00103 //============================================================================
00104 
00105 int device_type_from_name(char *name)
00106 {
00107     int i = 0; 
00108     while (device_types[i]) {
00109         if (strcasecmp(name, device_types[i]) == 0)
00110         {
00111             return i;
00112         }
00113         i++;
00114     }
00115     return 0xFF;
00116 }
00117 
00118 void handle_gasgauge()
00119 {
00120     // No suppoprt for GasGauge on DR800 series yet    
00121     if(devicetype != DR1000)
00122     {
00123         fatal("No support for GasGauge updates on DR800 series devices.");   
00124     }
00125     // check battery is at least 25% and/or charging
00126     if (!micro_check_battery_charge(25))
00127     {
00128         fatalnum(2, "Battery too low or not charging");
00129     }
00130     if (!force_update)
00131     {
00132         uint16_t gg_ver_fw, gg_ver_hw;
00133         if (gasgauge_get_versions(&gg_ver_fw, &gg_ver_hw))
00134         {
00135             fatal("Can't get gas gauge firmware version");
00136         }
00137         if (gg_ver_fw!=gg_req_version)
00138         {
00139             fatal("Invalid gas gauge firmware: got %04d, need %04d",
00140                     gg_ver_fw, gg_req_version);
00141         }
00142         usleep(1000000);
00143     }
00144     gasgauge_flash(filename);
00145 }
00146 
00147 void handle_firmware()
00148 {
00149     uint16_t bver, aver, fver;
00150     // check firware exists
00151     if (!check_firmware(filename, &fver))
00152     {
00153         fatal("Can't open firmware file %s", filename);
00154     } 
00155     // only use this on DR1000 to initialize communication with micro
00156     if (devicetype == DR1000)
00157     {
00158         micro_enter_mode(MODE_BOOT);
00159     }
00160     // check version numbers
00161     micro_get_versions(&bver, &aver);
00162     VPRINTF("Bootloader v%d.%d, app v%d.%d.\n",
00163             bver>>8,bver&0xFF,aver>>8,aver&0xFF);
00164     if (only_check)
00165         return;
00166     if ((!force_update) && 
00167         (((action != ACTION_BOOTLOADER) && fver<=aver && aver!=0xFFFF) ||
00168          ((action == ACTION_BOOTLOADER) && fver<=bver && bver!=0xFFFF)))
00169     {
00170         // firmware file is older than version on micro
00171         warning("Firmware '%s' is v%d.%d, not upgrading.",
00172                 filename, fver>>8, fver&0xFF);
00173     } 
00174     else 
00175     {
00176         // erase and program
00177         if (devicetype == DR1000)
00178         {           
00179             // DR1000 Series
00180             if (action == ACTION_BOOTLOADER)
00181             {
00182                 fatal("DR1000 doesn't support bootloader upgrades");
00183             }
00184             else
00185             {
00186                 micro_erase(MODE_APP, DR1000_APPL_ADDR_MIN, DR1000_APPL_ADDR_MAX);
00187                 dr1000_micro_program_application(filename);
00188             }
00189         }
00190         else
00191         {            
00192             // DR800 Series
00193             if (action == ACTION_BOOTLOADER)
00194             {
00195                 micro_erase(MODE_BOOT, DR800_BOOT_ADDR_MIN, DR800_BOOT_ADDR_MAX);
00196                 dr800_micro_program_bootloader(filename);
00197             }
00198             else
00199             {
00200                 micro_erase(MODE_APP, DR800_APPL_ADDR_MIN, DR800_APPL_ADDR_MAX);
00201                 dr800_micro_program_application(filename);
00202             }
00203         }
00204     }
00205 }
00206 
00207 void handle_devicetype()
00208 {
00209     int mode = micro_get_mode();
00210     VPRINTF("Micro in %s mode\n", mode==MODE_APP ? "app" : "boot");
00211 
00212     if (action == ACTION_READTYPE)
00213     {
00214         int devtype = micro_read_devicetype(mode);
00215         VPRINTF("Device type: ");
00216         printf("%s (%d)\n", 
00217                 devtype == 0xFF ? "Unknown" : device_types[devtype], devtype);
00218     }
00219     else
00220     {
00221         VPRINTF("Writing devicetype %d\n", new_devicetype);
00222         micro_write_devicetype(mode, new_devicetype);
00223     }
00224 }
00225 
00226 int main(int argc, char **argv)
00227 {
00228     char *portname;
00229 
00230     // check arguments
00231     parse_args(argc, argv);
00232     if (((action == ACTION_GASGAUGE || action == ACTION_FIRMWARE || action == ACTION_BOOTLOADER) && 
00233             ((argc-optind)!=2)) ||
00234         (((action == ACTION_WRITETYPE || action == ACTION_READTYPE) && 
00235           ((argc-optind)!=1))))
00236     {
00237         usage();
00238     }
00239     portname = argv[optind];
00240     filename = argv[optind+1];
00241     // open device
00242     port_open(portname, ION_SERIO_FLAGS, ION_SERIO_SPEED);
00243     // Check DeviceType
00244     micro_get_devicetype(&devicetype);
00245     if(devicetype==0)
00246     {    
00247         VPRINTF("Device type is DR1000 Series\n");
00248     }
00249     else
00250     {    
00251         VPRINTF("Device type is DR800 Series\n");
00252     }
00253     // do upgrades
00254     if (action == ACTION_GASGAUGE)
00255     {
00256         handle_gasgauge();
00257     }
00258     else if (action == ACTION_FIRMWARE || action == ACTION_BOOTLOADER)
00259     {
00260         handle_firmware();
00261     }
00262     else if (action == ACTION_WRITETYPE || action == ACTION_READTYPE)
00263     {
00264         handle_devicetype();
00265     }
00266     else
00267     {
00268        fatal("Unknown action: %d\n",action);
00269     }
00270 
00271     return 0;
00272 }
00273 
00274 
00275 //============================================================================
00276 // Local Functions Implementation
00277 //============================================================================
00278 
00279 static void usage()
00280 {
00281     printf("kbdupgrade - keyboard microcontroller firmware upgrader\n");
00282     printf(" usage: kbdupgrade <options> <serial port> <firmware file>\n");
00283     printf(" options:\n");
00284     printf("  -b       Upgrade bootloader instead of application\n");
00285     printf("  -c       Only do version check\n");
00286     printf("  -f       Ignore version check and force upgrade\n");
00287     printf("  -g       Upgrade gas gauge, instead of micro\n");
00288     printf("  -q       Don't print as much\n");
00289     printf("  -r XXXX  Required gas gauge firmware version\n");
00290     printf("  -s XXXX  Set device type (XXXX = DR[800|1000][SWG])\n");
00291     printf("  -t       Get device type\n");
00292     printf("  -h       This text\n");
00293     exit(1);
00294 }
00295 
00296 
00297 static int check_firmware(char *filename, uint16_t *version)
00298 {
00299     FILE *f = fopen(filename, "rb");
00300     if (f)
00301     {
00302         fread(version, 2, 1, f);
00303         fclose(f);
00304         return 1;
00305     }
00306     return 0;
00307 }
00308 
00309 
00310 static void parse_args(int argc, char **argv)
00311 {
00312     int c;
00313 
00314     while (( c = getopt(argc, argv, "bcfghr:s:tq")) != -1)
00315     {
00316         switch (c)
00317         {
00318             case 'b':
00319                 action = ACTION_BOOTLOADER;
00320                 break;
00321             
00322             case 'g':
00323                 action = ACTION_GASGAUGE;
00324                 break;
00325 
00326             case 's':
00327                 action = ACTION_WRITETYPE;
00328                 new_devicetype = device_type_from_name(optarg);
00329                 break;
00330 
00331             case 't':
00332                 action = ACTION_READTYPE;
00333                 break;
00334 
00335             case 'c':
00336                 only_check = 1;
00337                 break;
00338 
00339             case 'f':
00340                 force_update = 1;
00341                 break;
00342             
00343             case 'q':
00344                 verbose = 0;
00345                 break;
00346 
00347             case 'r':
00348                 gg_req_version = atoi(optarg);
00349                 printf("Required gas gauge version: %04d\n", gg_req_version);
00350                 break;
00351 
00352             case 'h':
00353             default:
00354                 usage();
00355                 break;
00356         }
00357     }
00358 }
Generated by  doxygen 1.6.2-20100208