예제 #1
0
        static int Main(string[] args)
        {
            /* install global Exception handler
             * Won't do much more than pretify'ing the error messages but better
             * fail gracefully that terribly
             */
            System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;

            bool errors_encountered = false;

            CommandLineParser cmd_parser = new CommandLineParser();

            if (cmd_parser.parse_command_line(args) == false)
            {
                return(RETURN_INVALID_CMDLINE);
            }

            /****** SEED EROS Bdrige mode enable/disable requests */
            if (cmd_parser.bootloader_operations.Contains(CommandLineParser.en_bootloader_operations.SEEDEROS_BRIDGEENABLE))
            {
                return(EROS_EnableBridgeMode(ref cmd_parser));
            }

            if (cmd_parser.bootloader_operations.Contains(CommandLineParser.en_bootloader_operations.SEEDEROS_BRIDGEDISABLE))
            {
                return(EROS_DisableBridgeMode(ref cmd_parser));
            }

            /****** Emergency Erase Request
             *  Emergency Erase restores bootloader access in case of lost password, by wiping
             *  the full FLASH and EEPROM memory areas
             */
            if (cmd_parser.bootloader_operations.Contains(CommandLineParser.en_bootloader_operations.EMERGENCY_ERASE))
            {
                enEmergencyEraseConfirmResult eresult = ConfirmEmergencyErase(ref cmd_parser);

                if (eresult == enEmergencyEraseConfirmResult.ER_CONFIRMED)
                {
                    TSBInterfacing tsb = new TSBInterfacing(UpdateStatusOnScreen, AskQuestion_ToUser);
                    if (!tsb.EmergencyErase(cmd_parser.port_name, cmd_parser.baudrate_bps, cmd_parser.prewait_ms, cmd_parser.replytimeout_ms))
                    {
                        Console.WriteLine();
                        Console.WriteLine("> Error while performing Emergency Erase operation.");
                        return(RETURN_ERRORS_ENCOUNTERED);
                    }
                    else
                    {
                        return(0);
                    }
                }
                else if (eresult == enEmergencyEraseConfirmResult.ER_ERROR)
                {
                    return(RETURN_ERRORS_ENCOUNTERED);
                }
                else
                {
                    return(0);
                }
            }


            /********** Main cycle for multi-device bootloader operations
             *  We will cycle through the list of passwords supplied
             *  (or use empty password if none supplied)
             *
             *  On every iteration we will run the same operations but we will collect user
             *  options on each iteration (bc user may want different options for each
             *  device)
             */

            if (cmd_parser.bootloader_passwords.Count() == 0)
            {
                /* add a bogus entry with an empty password. Assuming user intends to start the session
                 * with no password. */
                cmd_parser.bootloader_passwords.Add("");
            }

            /* only advance to TSB if we have more commands lined up and requested at the command line */
            if (cmd_parser.bootloader_operations.Count == 0)
            {
                Console.WriteLine();
                Console.WriteLine("> No bootloader actions specified. Ending session");
                return(0);
            }


            foreach (string pwd in cmd_parser.bootloader_passwords)
            {
                TSBInterfacing tsb = new TSBInterfacing(UpdateStatusOnScreen, AskQuestion_ToUser);
                bool           activation_result = false;

                /* from TSB versions of 2020 onwards, we now have an operation timeout
                 *     which means the commands must get their complete input in a limited timespan
                 *
                 *    This means that, for setting password, timeout and/or magic bytes
                 *    we should ask the user for them beforehand so that they'r ready to go
                 *    If we wait for the user input while the sesison is active, the session
                 *    will likely timeout.
                 */
                TSBInterfacing.str_tsb_session_data new_user_data = default(TSBInterfacing.str_tsb_session_data);
                new_user_data.magic_bytes = new byte[2]; // we need to explicit allocate space for this

                if (pwd.Length > 0)
                {
                    if (cmd_parser.activation_mode == CommandLineParser.en_bootloader_activation_mode.COLD_BOOT)
                    {
                        Console.WriteLine();
                        Console.WriteLine("> Preparing to activate bootloader for device with password: {0}", pwd);
                        CollectUserOptions_AndUpdateCachedSessionData(ref cmd_parser, ref new_user_data);

                        activation_result = tsb.ActivateBootloaderFromColdStart(cmd_parser.port_name, cmd_parser.baudrate_bps, cmd_parser.prewait_ms, cmd_parser.replytimeout_ms, pwd, cmd_parser.verbose_output);
                    }
                    else
                    {
                        Console.WriteLine("ERROR: Bootloader passwords can only be specified when activating in 'cold' [boot] mode.");
                        return(RETURN_ERRORS_ENCOUNTERED);
                    }
                }
                else if (cmd_parser.activation_mode == CommandLineParser.en_bootloader_activation_mode.COLD_BOOT)
                {
                    Console.WriteLine();
                    Console.WriteLine("> Preparing to activate bootloader (no device password specified)");
                    CollectUserOptions_AndUpdateCachedSessionData(ref cmd_parser, ref new_user_data);

                    activation_result = tsb.ActivateBootloaderFromColdStart(cmd_parser.port_name, cmd_parser.baudrate_bps, cmd_parser.prewait_ms, cmd_parser.replytimeout_ms, pwd, cmd_parser.verbose_output);
                }
                else if (cmd_parser.activation_mode == CommandLineParser.en_bootloader_activation_mode.LIVE_VIA_DYNAMIXEL)
                {
                    if (cmd_parser.dynid < 0 || cmd_parser.dynid > 253)
                    {
                        Console.WriteLine("ERROR: 'live' bootloader activation mode was selected but the '-dynid' parameter was not given or is invalid. Please set a valid '-dynid' for 'live' activation mode.");
                        return(RETURN_ERRORS_ENCOUNTERED);
                    }

                    Console.WriteLine();
                    Console.WriteLine("> Preparing to activate bootloader 'live', on device with DynID {0}", cmd_parser.dynid);
                    CollectUserOptions_AndUpdateCachedSessionData(ref cmd_parser, ref new_user_data);

                    // baud after activation should not be hard coded as we may need to speak at higher bauds if going through the EROS board.
                    // timeout for bootloader activation must exceed the time set in the servo firmware.
                    activation_result = tsb.ActivateBootloaderFromDynamixel(cmd_parser.port_name, cmd_parser.baudrate_bps, 9600, (byte)cmd_parser.dynid, 3500, 6000, TSBInterfacing.en_dyn_protocol_version.DYNAMIXEL_1, cmd_parser.verbose_output);
                }

                if (activation_result == true)
                {
                    /* Bootloader is active. Print all bootloader information */
                    PrintDeviceInfo(tsb);

                    /*  check if the user asked to tag the file names.
                     *  This MUST be done here for the cases where we use multiple
                     *  passwords; in that case, we have sessins starting at different times
                     *  (initiated here) and also different passwords
                     */
                    string tag = string.Format("_{0:yyMMdd}_{0:HHmmss}", DateTime.Now);
                    if (pwd.Length > 0)
                    {
                        tag += string.Format("_{0}", pwd);
                    }

                    string eep_filename   = cmd_parser.eeprom_file_name;
                    string flash_filename = cmd_parser.flash_file_name;

                    if (cmd_parser.tag_eepromfilename_withdatetimepwd && !string.IsNullOrEmpty(cmd_parser.eeprom_file_name))
                    {
                        eep_filename = AddTagToFilename(cmd_parser.eeprom_file_name, tag);
                    }

                    if (cmd_parser.tag_flashfilename_withdatetimepwd && !string.IsNullOrEmpty(cmd_parser.flash_file_name))
                    {
                        flash_filename = AddTagToFilename(cmd_parser.flash_file_name, tag);
                    }


                    bool request_last_page_write = false;
                    /* loop through the various operations requested */
                    foreach (CommandLineParser.en_bootloader_operations bootloader_op in cmd_parser.bootloader_operations)
                    {
                        switch (bootloader_op)
                        {
                        case CommandLineParser.en_bootloader_operations.DISPLAY_DEVICE_INFO:
                            /* do nothing; when we activated TSB it already displayed the device info */
                            break;

                        case CommandLineParser.en_bootloader_operations.EEP_ERASE:
                            if (!tsb.EEProm_Erase())
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Erasing EEProm.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.EEP_WRITE:
                            if (!tsb.EEProm_Write(eep_filename))
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Writing EEPROM.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.EEP_VERIFY:
                            if (!tsb.EEProm_Verify(eep_filename))
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Verifying EEPROM.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.EEP_READ:
                            if (!tsb.EEProm_Read(eep_filename))
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Reading EEPROM.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.FW_ERASE:
                            if (!tsb.Flash_Erase())
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Erasing Flash.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.FW_WRITE:
                            if (!tsb.Flash_Write(flash_filename))
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Writing Flash.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.FW_VERIFY:
                            if (!tsb.Flash_Verify(flash_filename))
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Verifying Flash.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.FW_READ:
                            if (!tsb.Flash_Read(flash_filename))
                            {
                                Console.WriteLine();
                                Console.WriteLine("> Error Reading Flash.");
                                errors_encountered = true;
                            }
                            break;

                        case CommandLineParser.en_bootloader_operations.PASSWORD_CHANGE:
                            tsb.session_data_.password = new_user_data.password;
                            request_last_page_write    = true;
                            break;

                        case CommandLineParser.en_bootloader_operations.TIMEOUT_CHANGE:
                            tsb.session_data_.timeout = new_user_data.timeout;
                            request_last_page_write   = true;
                            break;


                        case CommandLineParser.en_bootloader_operations.WRITE_MAGIC_BYTES:
                            tsb.session_data_.magic_bytes[0] = new_user_data.magic_bytes[0];
                            tsb.session_data_.magic_bytes[1] = new_user_data.magic_bytes[1];
                            request_last_page_write          = true;
                            break;

                        case CommandLineParser.en_bootloader_operations.PATCH_DAISY_CHAIN_BUG:
                            request_last_page_write = true;     // a simple last page write, applies the patch
                            break;

                        default:
                            Console.WriteLine("ERROR: Unknown Bootloader operation in function main()");
                            return(RETURN_UNKOWN_OPTION_IN_CASE);
                        }
                    }

                    // check if there are updated settings in last page, and commit them
                    if (request_last_page_write)
                    {
                        if (!tsb.LastPage_Write())
                        {
                            Console.WriteLine();
                            Console.WriteLine("> Error updating bootloader configuration data.");
                            Console.WriteLine("> (Daisy chain patch, Timeout, password and/or Magic bytes might not have been updated)");
                            errors_encountered = true;
                        }
                        request_last_page_write = false;
                    }

                    tsb.DeactivateBootloader();
                }
                else
                {
                    Console.WriteLine();
                    Console.WriteLine("> Could not activate bootloader for the selected device.");
                    Console.WriteLine("> Hint: Is password correct? Is BAUD rate correct?");
                    tsb.DeactivateBootloader();
                    errors_encountered = true;
                }
            }

            if (errors_encountered)
            {
                Console.WriteLine();
                Console.WriteLine("> Requested operations completed with errors. Please review the error messages above.");
                return(RETURN_ERRORS_ENCOUNTERED);
            }
            else
            {
                Console.WriteLine();
                Console.WriteLine("> All operations complete.");
                return(0);
            }
        }
예제 #2
0
        static void CollectUserOptions_AndUpdateCachedSessionData(ref CommandLineParser cmd_parser, ref TSBInterfacing.str_tsb_session_data new_user_data)
        {
            Console.WriteLine("> Collecting user options");
            if (cmd_parser.bootloader_operations.Contains(CommandLineParser.en_bootloader_operations.PASSWORD_CHANGE))
            {
                string new_pwd;
                while (true)
                {
                    Console.WriteLine("Please enter the _new_ Password (max. {0} chars): ", TSBInterfacing.max_pwd_length);
                    new_pwd = Console.ReadLine();

                    if (string.IsNullOrEmpty(new_pwd))
                    {
                        new_pwd = "";
                        Console.WriteLine("No password specified. The bootloader will be accessible without password.");
                        break;
                    }
                    else if (new_pwd.Length > Tsbloader_adv.TSBInterfacing.max_pwd_length)
                    {
                        Console.WriteLine("ERROR: Password is too long. Maximum password length supported by this tool is {0} characters.", Tsbloader_adv.TSBInterfacing.max_pwd_length);
                    }
                    else
                    {
                        Console.WriteLine("New password will be set to: {0}", new_pwd);
                        Console.WriteLine("(if you lose your password, you may use the Emergency Erase option '-XXX')");
                        break;
                    }
                }
                new_user_data.password = new_pwd;
                Console.WriteLine();
            }

            if (cmd_parser.bootloader_operations.Contains(CommandLineParser.en_bootloader_operations.TIMEOUT_CHANGE))
            {
                int new_timeout_setting;

                while (true)
                {
                    Console.WriteLine("Please enter new Timeout setting: ");
                    string new_timeout = Console.ReadLine();

                    if (string.IsNullOrEmpty(new_timeout))
                    {
                        Console.WriteLine("Invalid timeout specified. Timeout must be number between {0} and 255.", MINIMUM_TIMEOUT_SETTING);
                    }
                    else
                    {
                        if (!int.TryParse(new_timeout, out new_timeout_setting))
                        {
                            Console.WriteLine("Invalid timeout specified. Timeout must be a number, between {0} and 255.", MINIMUM_TIMEOUT_SETTING);
                        }
                        else if (new_timeout_setting < MINIMUM_TIMEOUT_SETTING || new_timeout_setting > 255)
                        {
                            Console.WriteLine("Invalid timeout value specified. Timeout must be between {0} and 255.", MINIMUM_TIMEOUT_SETTING);
                        }
                        else
                        {
                            new_user_data.timeout = (byte)new_timeout_setting;
                            break;
                        }
                    }
                }
                Console.WriteLine();
            }

            if (cmd_parser.bootloader_operations.Contains(CommandLineParser.en_bootloader_operations.WRITE_MAGIC_BYTES))
            {
                /* ask the user for the new magic bytes */
                string[] s_magic_bytes_names = { "First", "Second" };

                //Console.WriteLine("Magic Bytes currently set to [0x{0:X02}] [0x{1:X02}]", tsb.session_data_.magic_bytes[0], tsb.session_data_.magic_bytes[1]);

                for (byte b = 0; b < 2; b++)
                {
                    while (true)
                    {
                        Console.WriteLine("Enter the {0} Magic Byte, in HEX format (ie. for '0xFE', just enter 'FE'): 0x", s_magic_bytes_names[b]);
                        string magic_byte = Console.ReadLine();

                        if (string.IsNullOrWhiteSpace(magic_byte))
                        {
                            Console.WriteLine("Empty Magic Byte specified; will be set to 0xFF");
                            magic_byte = "FF";
                        }

                        int mb;
                        try
                        {
                            // based on tips for parsing HEX here https://theburningmonk.com/2010/02/converting-hex-to-int-in-csharp/
                            mb = int.Parse(magic_byte, System.Globalization.NumberStyles.HexNumber);

                            if (mb > 255)
                            {
                                Console.WriteLine("ERROR: HEX number too big. Magic bytes are of BYTE type in range 0x0 to 0xFF.");
                            }
                            else
                            {
                                new_user_data.magic_bytes[b] = (byte)mb;
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("ERROR: Invalid HEX value. Magic bytes are set in HEX. Example: to set to 0xA7, type 'A7' and ommit the '0x' part.");
                        }
                    }
                    Console.WriteLine();
                }

                Console.WriteLine("Magic Bytes will be set to: [0x{0:X02}] [0x{1:X02}]", new_user_data.magic_bytes[0], new_user_data.magic_bytes[1]);
                Console.WriteLine();
            }

            Console.WriteLine("> Proceeding to Activate Bootloader.");
        }