Esempio n. 1
0
    def __run(self,
              file_path=None,
              baudrate=921600,
              port=None,
              resume=False,
              load_ffh=False,
              mirror=False,
              switch_ffh=False,
              bootrom=False,
              rgbled=0x050505,
              debug=False,
              pkgdebug=False,
              atneg=True,
              max_try=10,
              direct=True,
              atneg_only=False,
              version_only=False):
        mirror = True if atneg_only else mirror
        recover = True if atneg_only else load_ffh
        resume = True if mirror or recover or atneg_only or version_only else resume
        if debug:
            print(
                'mirror? {}  recover? {}  resume? {}  direct? {}  atneg_only? {} bootrom? {} '
                .format(mirror, recover, resume, direct, atneg_only, bootrom))
        abort = True
        external = False
        self.__serial = None

        if 'FiPy' in self.__sysname or 'GPy' in self.__sysname:

            if 'GPy' in self.__sysname:
                self.__pins = ('P5', 'P98', 'P7', 'P99')
            else:
                self.__pins = ('P20', 'P18', 'P19', 'P17')

            self.__serial = UART(1,
                                 baudrate=115200 if recover else baudrate,
                                 pins=self.__pins,
                                 timeout_chars=100)
            self.__serial.read()
        else:
            if port is None:
                raise ValueError('serial port not specified')
            if debug: print('Setting port {}'.format(port))
            external = True
            br = 115200 if recover and not direct else baudrate
            if debug: print('Setting baudrate to {}'.format(br))
            self.__serial = serial.Serial(port,
                                          br,
                                          bytesize=serial.EIGHTBITS,
                                          timeout=1 if version_only else 0.1)
            self.__serial.reset_input_buffer()
            self.__serial.reset_output_buffer()

        if debug: print('Initial prepartion complete...')

        if version_only:
            self.__serial.read()
            self.__serial.write(b"AT!=\"showver\"\r\n")
            time.sleep(.5)
            shver = self.read_rsp(2000)
            if shver is not None:
                self.print_pretty_response(shver)
            return True

        if not mirror:
            if bootrom:
                if debug: print('Loading built-in recovery bootrom')
                from sqnsbr import bootrom
                blob = bootrom()
                blobsize = blob.get_size()
            else:
                if debug: print('Loading {}'.format(file_path))
                blobsize = os.stat(file_path)[6]
                blob = open(file_path, "rb")

        if not load_ffh:
            if not self.wakeup_modem(baudrate, port, 10, 1, debug):
                return False

        if not resume:

            # disable echo
            self.__serial.write(b"ATE0\r\n")
            response = self.read_rsp(size=6)

            self.__serial.read(100)
            if debug: print('Entering recovery mode')

            self.__serial.write(b"AT+SMOD?\r\n")
            response = self.return_pretty_response(self.read_rsp(size=7))
            self.__serial.read(100)
            if debug: print("AT+SMOD? returned {}".format(response))

            if not bootrom:
                self.__serial.write(b"AT+SMSWBOOT=3,1\r\n")
                time.sleep(2)
                self.wait_for_modem()
                self.__serial.write(b"AT\r\n")
                self.__serial.write(b"AT\r\n")

        else:
            self.__serial.read(100)
            if debug: print('Entering recovery mode')

            self.__serial.write(b"AT+SMOD?\r\n")
            response = self.return_pretty_response(self.read_rsp(size=7))
            self.__serial.read(100)
            if debug: print("AT+SMOD? returned {}".format(response))

        time.sleep(1)
        self.__serial.read()

        if (not recover) and (not direct):
            if mirror:
                time.sleep(.5)
                self.__serial.read(100)
                print(
                    'Going into MIRROR mode... please close this terminal to resume the upgrade via UART'
                )
                self.uart_mirror(rgbled)

            elif bootrom:
                print('Starting STP (DO NOT DISCONNECT POWER!!!)')

            else:
                print('Starting STP ON_THE_FLY')
            self.__serial.read(100)

            self.__serial.write(b'AT+SMSTPU=\"ON_THE_FLY\"\r\n')
            response = self.read_rsp(size=4)
            if response != b'OK\r\n' and response != b'\r\nOK' and response != b'\nOK':
                raise OSError("Invalid answer '%s' from the device" % response)
                blob.close()

            self.__serial.read()
        elif recover and (not direct):
            if atneg:
                result = self.at_negotiation(baudrate, port, max_try, mirror,
                                             atneg_only, debug)
                if result:
                    if atneg_only:
                        return True
                    if mirror:
                        time.sleep(.5)
                        self.__serial.read(100)
                        print(
                            'Going into MIRROR mode... please close this terminal to resume the upgrade via UART'
                        )
                        self.uart_mirror(rgbled)
                    else:
                        self.__serial.write(b"AT+STP\n")
                        response = self.read_rsp(size=6)
                        if not b'OK' in response:
                            print('Failed to start STP mode!')
                            sys.exit(1)
                else:
                    print('AT auto-negotiation failed! Exiting.')
                    return False
        else:
            if debug: print('Starting STP mode...')
            self.__serial.write(b"AT+STP\n")
            response = self.read_rsp(size=6)
            if not b'OK' in response:
                print('Failed to start STP mode!')
                sys.exit(1)

        try:
            if debug:
                print('Starting STP code upload')
            if stp.start(blob,
                         blobsize,
                         self.__serial,
                         baudrate,
                         AT=False,
                         debug=debug,
                         pkgdebug=pkgdebug):
                blob.close()
                if switch_ffh:
                    print(
                        'Bootrom updated successfully, switching to upgrade mode'
                    )
                    abort = False
                elif load_ffh:
                    if not self.wakeup_modem(baudrate, port, 100, 1, debug):
                        return False
                    print(
                        'Upgrader loaded successfully, modem is in upgrade mode'
                    )
                    return True
                else:
                    print('Code download done, returning to user mode')
                    abort = recover
            else:
                blob.close()
                print('Code download failed, aborting!')
                return False
        except:
            blob.close()
            print('Code download failed, aborting!')
            abort = True

        time.sleep(1.5)

        if not abort:
            self.__serial.read()
            if switch_ffh:
                self.__serial.write(b"AT+SMSWBOOT=0,1\r\n")
                return True
            else:
                self.special_print('Resetting (DO NOT DISCONNECT POWER!!!).',
                                   end='',
                                   flush=True)
                self.__serial.write(b"AT+SMSWBOOT=1,1\r\n")
                self.wait_for_modem(send=False, expected=b'+SYSSTART')

                self.__serial.write(b"AT\r\n")
                self.__serial.write(b"AT\r\n")
                time.sleep(0.5)
                self.__serial.read()
                print('Upgrade completed!')
                print("Here's the current firmware version:")
                time.sleep(0.5)
                self.__serial.read()
                self.__serial.write(b"AT!=\"showver\"\r\n")
                time.sleep(.5)
                shver = self.read_rsp(2000)
                if shver is not None:
                    self.print_pretty_response(shver)
                return True
        return False
    def __run(self,
              file_path=None,
              baudrate=921600,
              port=None,
              resume=False,
              load_ffh=False,
              mirror=False,
              switch_ffh=False,
              bootrom=False,
              rgbled=0x050505,
              debug=False,
              pkgdebug=False,
              atneg=True,
              max_try=10,
              direct=True,
              atneg_only=False,
              version_only=False,
              expected_smod=None,
              verbose=False,
              load_fff=False):
        self.__wait_msg = False
        mirror = True if atneg_only else mirror
        recover = True if atneg_only else load_ffh
        resume = True if mirror or recover or atneg_only or version_only else resume
        verbose = True if debug else verbose
        load_fff = False if bootrom and switch_ffh else load_fff
        if debug:
            print(
                'mirror? {}  recover? {}  resume? {}  direct? {}  atneg_only? {} bootrom? {} load_fff? {}'
                .format(mirror, recover, resume, direct, atneg_only, bootrom,
                        load_fff))
        abort = True
        external = False
        self.__serial = None

        if 'FiPy' in self.__sysname or 'GPy' in self.__sysname:

            self.__serial = UART(1,
                                 baudrate=115200 if recover else baudrate,
                                 pins=self.__pins,
                                 timeout_chars=100)
            self.__serial.read()
        else:
            if port is None:
                raise ValueError('serial port not specified')
            if debug: print('Setting port {}'.format(port))
            external = True
            br = 115200 if recover and not direct else baudrate
            if debug: print('Setting baudrate to {}'.format(br))
            self.__serial = serial.Serial(port,
                                          br,
                                          bytesize=serial.EIGHTBITS,
                                          timeout=1 if version_only else 0.1)
            self.__serial.reset_input_buffer()
            self.__serial.reset_output_buffer()

        if version_only:
            self.__serial.read()
            self.__serial.write(b'AT\r\n')
            self.__serial.write(b'AT\r\n')
            self.__serial.read()
            if verbose:
                self.__serial.write(b"AT!=\"showver\"\r\n")
            else:
                self.__serial.write(b"ATI1\r\n")
            time.sleep(.5)
            shver = self.read_rsp(2000)
            if shver is not None:
                self.print_pretty_response(shver)
            return True

        if debug: print('Initial prepartion complete...')

        if not mirror:
            if bootrom:
                if debug: print('Loading built-in recovery bootrom...')
                try:
                    # try compressed bootrom first
                    from sqnsbrz import bootrom
                except:
                    # fallback to uncompressed
                    from sqnsbr import bootrom
                blob = bootrom()
                blobsize = blob.get_size()
            else:
                if debug: print('Loading {}'.format(file_path))
                blobsize = os.stat(file_path)[6]
                if blobsize < 128:
                    print('Firmware file is too small!')
                    reconnect_uart()
                    sys.exit(1)
                if blobsize > 4194304:
                    if load_fff:
                        print(
                            "Firmware file is too big to load via FFF method. Using ON_THE_FLY"
                        )
                    load_fff = False
                blob = open(file_path, "rb")

        if not load_ffh:
            if not self.wakeup_modem(baudrate, port, 10, 1, debug):
                return False

        if not resume:

            # disable echo
            self.__serial.write(b"ATE0\r\n")
            response = self.read_rsp(size=6)

            self.__serial.read(100)
            if debug: print('Entering upgrade mode...')

            self.__serial.write(b"AT+SMOD?\r\n")
            response = self.return_pretty_response(self.read_rsp(size=7))
            self.__serial.read(100)
            if debug: print("AT+SMOD? returned {}".format(response))

            self.__serial.write(b"AT+SQNSUPGRADENTF=\"started\"\r\n")
            self.wait_for_modem()
            if not load_fff:
                self.__serial.write(b"AT+SMSWBOOT=3,1\r\n")
                resp = self.read_rsp(100)
                if debug: print('AT+SMSWBOOT=3,1 returned: {}'.format(resp))
                if b'ERROR' in resp:
                    time.sleep(5)
                    self.__serial.write(b"AT+SMSWBOOT=3,0\r\n")
                    resp = self.read_rsp(100)
                    if debug:
                        print('AT+SMSWBOOT=3,0 returned: {}'.format(resp))
                    if b'OK' in resp:
                        self.__serial.write(b"AT^RESET\r\n")
                        resp = self.read_rsp(100)
                        if debug: print('AT^RESET returned: {}'.format(resp))
                    else:
                        print('Received ERROR from AT+SMSWBOOT=3,1! Aborting!')
                        reconnect_uart()
                        sys.exit(1)
                time.sleep(3)
                resp = self.__serial.read()
                if debug: print("Response after reset: {}".format(resp))
                self.wait_for_modem()
                self.__serial.write(b"AT\r\n")

        else:
            self.__serial.read(100)
            if debug: print('Entering recovery mode')

            self.__serial.write(b"AT+SMOD?\r\n")
            response = self.return_pretty_response(self.read_rsp(size=7))
            self.__serial.read(100)
            if debug: print("AT+SMOD? returned {}".format(response))

        time.sleep(1)
        self.__serial.read()

        if (not recover) and (not direct):
            if mirror:
                time.sleep(.5)
                self.__serial.read(100)
                print(
                    'Going into MIRROR mode... please close this terminal to resume the upgrade via UART'
                )
                self.uart_mirror(rgbled)

            elif bootrom:
                if verbose: print('Starting STP')
            else:
                if verbose:
                    if load_fff:
                        print('Starting STP [FFF]')
                    else:
                        print('Starting STP ON_THE_FLY')

            self.__serial.read(100)
            if verbose: print("Sending AT+CFUN=4")
            resonse = self.__serial.write(b'AT+CFUN=4\r\n')
            if verbose: print("AT+CFUN=4 returned {}".format(response))
            self.__serial.read(100)

            if load_fff:
                if debug: print("Sending AT+SMSTPU")
                self.__serial.write(b'AT+SMSTPU\r\n')
            else:
                if debug: print("Sending AT+SMSTPU=\"ON_THE_FLY\"")
                self.__serial.write(b'AT+SMSTPU=\"ON_THE_FLY\"\r\n')

            response = self.read_rsp(size=4)
            if response != b'OK\r\n' and response != b'\r\nOK' and response != b'\nOK':
                raise OSError("Invalid answer '%s' from the device" % response)
                blob.close()

            self.__serial.read()
        elif recover and (not direct):
            if atneg:
                result = self.at_negotiation(baudrate, port, max_try, mirror,
                                             atneg_only, debug)
                if result:
                    if atneg_only:
                        return True
                    if mirror:
                        time.sleep(.5)
                        self.__serial.read(100)
                        print(
                            'Going into MIRROR mode... please close this terminal to resume the upgrade via UART'
                        )
                        self.uart_mirror(rgbled)
                    else:
                        self.__serial.write(b"AT+STP\n")
                        response = self.read_rsp(size=6)
                        if not b'OK' in response:
                            print('Failed to start STP mode!')
                            reconnect_uart()
                            sys.exit(1)
                else:
                    print('AT auto-negotiation failed! Exiting.')
                    return False
        else:
            if debug: print('Starting STP mode...')
            self.__serial.write(b"AT+STP\n")
            response = self.read_rsp(size=6)
            if not b'OK' in response:
                print('Failed to start STP mode!')
                reconnect_uart()
                sys.exit(1)

        try:
            if debug:
                if verbose: print('Starting STP code upload')
            if stp.start(blob,
                         blobsize,
                         self.__serial,
                         baudrate,
                         AT=False,
                         debug=debug,
                         pkgdebug=pkgdebug):
                blob.close()
                self.__serial.read()
                if switch_ffh:
                    if verbose:
                        print(
                            'Bootrom updated successfully, switching to recovery mode'
                        )
                    abort = False
                elif load_ffh:
                    if not self.wakeup_modem(baudrate, port, 100, 1, debug,
                                             'Waiting for updater to load...'):
                        return False
                    if verbose:
                        print(
                            'Upgrader loaded successfully, modem is in update mode'
                        )
                    return True
                else:
                    if verbose:
                        print('Code download done, returning to user mode')
                    abort = recover
            else:
                blob.close()
                print('Code download failed, aborting!')
                return False
        except:
            blob.close()
            print('Code download failed, aborting!')
            abort = True

        time.sleep(1.5)

        if not abort:
            self.__serial.read()
            if switch_ffh:
                self.__serial.write(b"AT+SMSWBOOT=0,1\r\n")
                resp = self.read_rsp(100)
                if debug: print("AT+SMSWBOOT=0,1 returned {}".format(resp))
                if b"ERROR" in resp:
                    time.sleep(5)
                    self.__serial.write(b"AT+SMSWBOOT=0,0\r\n")
                    resp = self.read_rsp(100)
                    if debug:
                        print('AT+SMSWBOOT=0,0 returned: {}'.format(resp))
                    if b'OK' in resp:
                        self.__serial.write(b"AT^RESET\r\n")
                        resp = self.read_rsp(100)
                        if debug: print('AT^RESET returned: {}'.format(resp))
                        return True
                    else:
                        print('Received ERROR from AT+SMSWBOOT=0,0! Aborting!')
                        return False
                return True
            else:
                if load_fff:
                    self.__serial.write(b"AT+SMUPGRADE\r\n")
                if not self.wakeup_modem(
                        baudrate, port, 100, 1, debug,
                        self.__get_wait_msg(load_fff=load_fff)):
                    print(
                        "Timeout while waiting for modem to finish updating!")
                    reconnect_uart()
                    sys.exit(1)

                start = time.time()
                while True:
                    self.__serial.read()
                    self.__serial.write(b"AT+SMUPGRADE?\r\n")
                    resp = self.read_rsp(1024)
                    if debug:
                        print("AT+SMUPGRADE? returned {} [timeout: {}]".format(
                            resp,
                            time.time() - start))

                    if resp == b'\x00' or resp == b'':
                        time.sleep(2)

                    if b'No report' in resp or b'on-going' in resp:
                        time.sleep(1)

                    if b'success' in resp or b'fail' in resp:
                        break

                    if time.time() - start >= 300:
                        raise OSError('Timeout waiting for modem to respond!')

                self.__serial.write(b"AT+SMSWBOOT?\r\n")
                resp = self.read_rsp(100)
                if debug: print("AT+SMSWBOOT? returned {}".format(resp))
                start = time.time()
                while (b"RECOVERY"
                       not in resp) and (b"FFH" not in resp) and (b"FFF"
                                                                  not in resp):
                    if debug: print("Timeout: {}".format(time.time() - start))
                    if time.time() - start >= 300:
                        reconnect_uart()
                        raise OSError('Timeout waiting for modem to respond!')
                    time.sleep(2)
                    if not self.wakeup_modem(
                            baudrate, port, 100, 1, debug,
                            self.__get_wait_msg(load_fff=load_fff)):
                        reconnect_uart()
                        raise OSError(
                            'Timeout while waiting for modem to finish updating!'
                        )
                    self.__serial.read()
                    self.__serial.write(b"AT+SMSWBOOT?\r\n")
                    resp = self.read_rsp(100)
                    if debug: print("AT+SMSWBOOT? returned {}".format(resp))
                self.__serial.read()
                self.__serial.write(b"AT+SMUPGRADE?\r\n")
                resp = self.read_rsp(1024)
                if debug: print("AT+SMUPGRADE? returned {}".format(resp))
                sqnup_result = self.return_upgrade_response(resp)
                if debug: print('This is my result: {}'.format(sqnup_result))
                if 'success' in sqnup_result:
                    if not load_fff:
                        self.special_print('Resetting.', end='', flush=True)
                        self.__serial.write(b"AT+SMSWBOOT=1,1\r\n")
                        if debug:
                            print("AT+SMSWBOOT=1,1 returned {}".format(resp))
                        if b"ERROR" in resp:
                            time.sleep(5)
                            self.__serial.write(b"AT+SMSWBOOT=1,0\r\n")
                            resp = self.read_rsp(100)
                            if debug:
                                print('AT+SMSWBOOT=1,0 returned: {}'.format(
                                    resp))
                            if b'OK' in resp:
                                self.__serial.write(b"AT^RESET\r\n")
                                resp = self.read_rsp(100)
                                if debug:
                                    print('AT^RESET returned: {}'.format(resp))
                                return True
                            else:
                                print(
                                    'Received ERROR from AT+SMSWBOOT=1,0! Aborting!'
                                )
                                return False
                        self.wait_for_modem(send=False,
                                            echo_char='.',
                                            expected=b'+SYSSTART')

                elif sqnup_result is not None:
                    print(
                        'Upgrade failed with result {}!'.format(sqnup_result))
                    print('Please check your firmware file(s)')
                else:
                    print("Invalid response after upgrade... aborting.")
                    reconnect_uart()
                    sys.exit(1)

                self.__serial.write(b"AT\r\n")
                self.__serial.write(b"AT\r\n")
                time.sleep(0.5)

                if 'success' in sqnup_result:
                    self.__serial.write(b"AT+SQNSUPGRADENTF=\"success\"\r\n")
                    self.__serial.read()
                    return True
                elif sqnup_result is None:
                    print(
                        'Modem upgrade was unsucessfull. Please check your firmware file(s)'
                    )
        return False