/********************************************/
/* WCLoader- WheelCommander Firmware Loader */
/*                                          */
/* This example program shows how to        */
/* connect to and invoke operations on a    */
/* nubotics WheelCommander WC-132 using a   */
/* PC serial port.                          */
/*                                          */
/* It relies on the NdiCmdC.h include file, */
/* the NdiCmdC.dll.                         */
/*                                          */
/*                                          */
/* (c)2005 Noetic Design, Inc.              */
/********************************************/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "windows.h"
#undef __cplusplus
#include "NdiCmdC.h"

#define TRUE 1
#define FALSE 0


int __cdecl main(int argc, char *argv[])
{
   int wc;
   char name[32];
   char new_name[32];
   int version;
   int new_version;
   int j;
   char firmware_filename[256] = "";
   BOOL firmware_filename_set = FALSE;
   BOOL verbose = FALSE;
   BOOL force_error = FALSE;
   char *p;
   HWND statwindow = (HWND)-1;
   struct _stat stat;
   int ret = 0;
   int cur_baud = 0;
   int baud = -1;
   int baud_rates[10] = {1200, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0};

   printf("WCLoader v. 1.02  Nubotics WheelCommander Firmware Loader\n(c)2005 Noetic Design, Inc.\n");

//
// scan first for options
//
   for (j = 1; j < argc; j++)
   {
      if ((argv[j][0] == '-') || (argv[j][0] == '/'))
      {
         p = &argv[j][2];
         switch(toupper(argv[j][1]))
         {
            case 'F':
               strcpy(firmware_filename, p);
               if (strlen(firmware_filename))
               {
                  if (_stat(firmware_filename, &stat) == 0)
                  {
                     if (stat.st_size && ((stat.st_mode & _S_IFMT) == _S_IFREG))
                     {
                        firmware_filename_set = TRUE;
                        printf("File to upload: %s, size %d\n", firmware_filename, stat.st_size);
                     }
                     else
                     {
                        printf("File %s not valid.\n", firmware_filename);
                        return 1;
                     }
                  }
                  else
                  {
                     printf("File %s not found.\n", firmware_filename);
                     return 2;
                  }
               }
               break;
            case 'B':
               baud = atoi(p);
               if ((baud < 0) || (baud > 8))
               {
                  printf("Syntax error!  Baud rate must be 0 to 8 inclusive.\n");
                  return 2;
               }
               break;
            case 'V':
               verbose = TRUE;
               break;
            case 'T':
               force_error = TRUE;
               break;
            case '?':
            case 'H':
            default:
               printf("Syntax:\n WCLoader /Ffirmware /V /T /Bn\n");
               printf(" /Ffirmware - specify firmware filename to upload\n");
               printf(" /V         - verbose mode\n");
               printf(" /T         - force error in data to test bootloader error handling\n");
               printf(" /Bn        - set baud rate to n, where n is:\n");
               printf("              0 = 1200\n");
               printf("              1 = 4800\n");
               printf("              2 = 9600\n");
               printf("              3 = 19200\n");
               printf("              4 = 38400\n");
               printf("              5 = 57600\n");
               printf("              6 = 115200\n");
               printf("              7 = 230400\n");
               printf("              8 = 460800\n");
               printf("              This changes the baudrate from the last known good rate\n");
               printf("              after a connection is made.  If the WheelCommander cannot\n");
               printf("              be found, the WCWizard dialog will appear so you can make\n");
               printf("              the initial baud rate setting prior to changing it.\n");
               return 1;
         }
      }
   }

// initialize the NdiCmd DLL
   NdiCmd_Init();

// search for a WheelCommander
   if (!NdiCmd_Search())
   {
      printf("WheelCommander not found.\n");
      ret = 3;
   }

// see if we found one
   wc = NdiCmd_GetWheelCommander();
   if (wc == -1)
   {
      printf("WheelCommander not found.\n");
      ret = 4;
   }

// if not found, run the wizard so user can set it up
   if (ret)
   {
      NdiCmd_RunWizard(TRUE);
      NdiCmd_Search();
      if ((wc = NdiCmd_GetWheelCommander()) == -1)
         return ret;
   }

// once found, check the name and version
   if (!NdiCmd_GetName(wc, name, &version))
   {
      printf("Error retrieving name and version.\n");
      return 5;
   }

   printf("Found WheelCommander %s version %d\n", name, version);

// if user set baud rate on command line, try to pass it to the WheelCommander
   if (baud != -1)
   {
      NdiCmd_GetBaud(wc, &cur_baud);
      printf("Attempting to change baud rate from %d to %d\n", cur_baud, baud_rates[baud]);
      if (!NdiCmd_SetBaud(wc, baud))
      {
         printf("Error setting baud rate.\n");
         return 6;
      }
      if (!NdiCmd_Sync(wc))
      {
         printf("Error confirming connection after baud rate change.\n");
         return 7;
      }
      printf("Baud rate changed.\n");
   }

// if the user specified a firmware file, try to update it
   if (firmware_filename_set)
   {
      if (!NdiCmd_UpdateFirmware(firmware_filename, statwindow))
      {
         printf("Failed to update firmware!");
         return 8;
      }

      if (!NdiCmd_GetName(wc, new_name, &new_version))
      {
         printf("Error retrieving name and version after update.\n");
         return 9;
      }

      printf("Firmware upload succeeded.  Name is: %s, was %s; version is: %d, was %d\n",
         new_name, name, new_version, version);
   }
   return 0;
}