Esempio n. 1
0
def check_interfaces():
    ok = True

    def test_serial_port(glob, name):
        try:
            with open_serial_port(glob):
                info('%s port is OK', name)
                return True
        except Exception:
            error('%s port is not working', name)
            return False

    info('Checking interfaces...')
    ok = test_serial_port(DEBUGGER_PORT_GDB_GLOB, 'GDB') and ok
    ok = test_serial_port(DEBUGGER_PORT_CLI_GLOB, 'CLI') and ok
    try:
        init_can_iface()
        info('CAN interface is OK')
    except Exception:
        logging.debug('CAN check error', exc_info=True)
        error('CAN interface is not working')
        ok = False

    if not ok:
        fatal('Required interfaces are not available. Please check your hardware configuration. '
              'If this application is running on a virtual machine, make sure that hardware '
              'sharing is configured correctly.')
Esempio n. 2
0
 def handle_serial_port_hanging():
     fatal(
         'DRWATSON HAS DETECTED A PROBLEM WITH CONNECTED HARDWARE AND NEEDS TO TERMINATE.\n'
         'A serial port operation has timed out. This usually indicates a problem with the connected '
         'hardware or its drivers. Please disconnect all USB devices currently connected to this computer, '
         "then connect them back and restart Drwatson. If you're using a virtual machine, please reboot it.",
         use_abort=True)
Esempio n. 3
0
def generate_signed_image_for(comma_separated_uid_integers):
    import struct
    import os
    try:
        unique_id_integers = list(
            map(int, comma_separated_uid_integers.split(',')))
        if len(unique_id_integers) != 4:
            raise ValueError(
                'Unique ID must be composed of exactly 4 integers')
        unique_id = struct.pack('<IIII', *unique_id_integers)
        assert len(unique_id) == 128 / 8
    except Exception as ex:
        fatal('Could not parse unique ID: %s', ex)

    info('Requesting signature for unique ID %s',
         ' '.join(['%02x' % x for x in unique_id]))
    gensign_response = api.generate_signature(unique_id, PRODUCT_NAME)
    firmware_with_signature = firmware_base.ljust(
        SIGNATURE_OFFSET, b'\xFF') + gensign_response.signature

    image_name = '-'.join(map(str, unique_id_integers)) + '.bin'
    with open(image_name, 'wb') as f:
        f.write(firmware_with_signature)
    os.chmod(image_name, 0o666)
    info('Signed image stored into %r', image_name)
def check_interfaces():
    ok = True

    def test_serial_port(glob, name):
        try:
            with open_serial_port(DEBUGGER_PORT_GDB_GLOB):
                info("%s port is OK", name)
                return True
        except Exception:
            error("%s port is not working", name)
            return False

    info("Checking interfaces...")
    ok = test_serial_port(DEBUGGER_PORT_GDB_GLOB, "GDB") and ok
    ok = test_serial_port(DEBUGGER_PORT_CLI_GLOB, "CLI") and ok
    try:
        init_can_iface()
        info("CAN interface is OK")
    except Exception:
        logging.debug("CAN check error", exc_info=True)
        error("CAN interface is not working")
        ok = False

    if not ok:
        fatal(
            "Required interfaces are not available. Please check your hardware configuration. "
            "If this application is running on a virtual machine, make sure that hardware "
            "sharing is configured correctly."
        )
 def handle_serial_port_hanging():
     fatal(
         "DRWATSON HAS DETECTED A PROBLEM WITH CONNECTED HARDWARE AND NEEDS TO TERMINATE.\n"
         "A serial port operation has timed out. This usually indicates a problem with the connected "
         "hardware or its drivers. Please disconnect all USB devices currently connected to this computer, "
         "then connect them back and restart Drwatson. If you're using a virtual machine, please reboot it.",
         use_abort=True,
     )
Esempio n. 6
0
def resolve_adapter_uid():
    if '/' not in args.iface:
        return

    iface_real = os.path.normpath(os.path.realpath(args.iface))

    for p in glob.glob('/dev/serial/by-id/*'):
        p_real = os.path.normpath(os.path.realpath(p))
        if p_real == iface_real:
            try:
                uid = re.findall(r'[-_]([0-9A-Fa-f]{8,32})', p)[0]
            except IndexError:
                uid = None
            logger.debug('SLCAN adapter port: %r --> %r, UID: %r', p, p_real,
                         uid)
            return uid.lower()

    fatal('Could not determine the UID of the SLCAN adapter')
Esempio n. 7
0
def generate_signed_image_for(comma_separated_uid_integers):
    import struct
    import os
    try:
        unique_id_integers = list(map(int, comma_separated_uid_integers.split(',')))
        if len(unique_id_integers) != 4:
            raise ValueError('Unique ID must be composed of exactly 4 integers')
        unique_id = struct.pack('<IIII', *unique_id_integers)
        assert len(unique_id) == 128 / 8
    except Exception as ex:
        fatal('Could not parse unique ID: %s', ex)

    info('Requesting signature for unique ID %s', ' '.join(['%02x' % x for x in unique_id]))
    gensign_response = api.generate_signature(unique_id, PRODUCT_NAME)
    firmware_with_signature = firmware_base.ljust(SIGNATURE_OFFSET, b'\xFF') + gensign_response.signature

    image_name = '-'.join(map(str, unique_id_integers)) + '.bin'
    with open(image_name, 'wb') as f:
        f.write(firmware_with_signature)
    os.chmod(image_name, 0o666)
    info('Signed image stored into %r', image_name)
Esempio n. 8
0
    with open(image_name, 'wb') as f:
        f.write(firmware_with_signature)
    os.chmod(image_name, 0o666)
    info('Signed image stored into %r', image_name)


with CLIWaitCursor():
    firmware_base = download(args.firmware)
    assert 0 < len(firmware_base) <= SIGNATURE_OFFSET, 'Firmware size is incorrect'

if args.generate_signed_image_for:
    generate_signed_image_for(args.generate_signed_image_for)
    exit(0)

if not args.iface:
    fatal('Iface is required')
execute_shell_command('ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875',
                      args.iface, args.iface, bootloader.CAN_BITRATE, ignore_failure=True)


def load_and_start_firmware(bootloader_interface, firmware_image):
    while True:
        try:
            info('Flashing the firmware [%d bytes]...', len(firmware_image))
            bootloader_interface.unlock()
            bootloader_interface.load_firmware(firmware_image)
        except Exception as ex:
            error('Flashing failed: %r', ex)
            if not input('Try harder?', yes_no=True):
                abort('Flashing failed')
        else:
Esempio n. 9
0
        f.write(firmware_with_signature)
    os.chmod(image_name, 0o666)
    info('Signed image stored into %r', image_name)


with CLIWaitCursor():
    firmware_base = download(args.firmware)
    assert 0 < len(
        firmware_base) <= SIGNATURE_OFFSET, 'Firmware size is incorrect'

if args.generate_signed_image_for:
    generate_signed_image_for(args.generate_signed_image_for)
    exit(0)

if not args.iface:
    fatal('Iface is required')
execute_shell_command(
    'ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875',
    args.iface,
    args.iface,
    bootloader.CAN_BITRATE,
    ignore_failure=True)


def load_and_start_firmware(bootloader_interface, firmware_image):
    while True:
        try:
            info('Flashing the firmware [%d bytes]...', len(firmware_image))
            bootloader_interface.unlock()
            bootloader_interface.load_firmware(firmware_image)
        except Exception as ex:
Esempio n. 10
0
def process_one_device(set_device_info):
    out = input(
        '1. Connect DroneCode Probe to the debug connector.\n'
        '2. Connect CAN to the first CAN connector on the Babel; leave the other CAN connector empty.\n'
        '3. Connect USB to the Micro USB port on the Babel.\n'
        '4. If you want to skip firmware upload, type F now.\n'
        '5. Press ENTER.')

    skip_fw_upload = 'f' in out.lower()
    if not skip_fw_upload:
        info('Loading the firmware')
        with CLIWaitCursor():
            try:
                load_firmware_via_gdb(
                    firmware_data,
                    toolchain_prefix=TOOLCHAIN_PREFIX,
                    load_offset=FLASH_OFFSET,
                    gdb_port=glob_one(DEBUGGER_PORT_GDB_GLOB),
                    gdb_monitor_scan_command='swdp_scan')
            except Exception as ex:
                logging.info('Firmware load error', exc_info=True)
                fatal(
                    'Could not load firmware; check the debug connector; error: %r',
                    ex)
    else:
        info('Firmware upload skipped')

    info('Waiting for the device to boot...')
    wait_for_boot()

    with closing(
            drwatson.can.SLCAN(get_target_serial_port_symlink(),
                               bitrate=CAN_BITRATE,
                               default_timeout=1)) as drv_target:
        info('Reading Zubax ID...')
        zubax_id = read_zubax_id(drv_target)
        unique_id = b64decode(zubax_id['hw_unique_id'])
        product_id = zubax_id['product_id']
        assert PRODUCT_NAME == product_id
        set_device_info(product_id, unique_id)

        info('Configuring the adapter...')

        drv_target.execute_cli_command(
            'cfg set can.terminator_on 1')  # Terminator ON

        logger.info('Adapter state:\n%s',
                    drv_target.execute_cli_command('stat'))

        with closing(uavcan.driver.make_driver(
                args.iface, bitrate=CAN_BITRATE)) as drv_test:
            random_frames = [
                make_random_can_frame() for _ in range(NUM_TEST_FRAMES)
            ]

            # If we're using another Zubax Babel as a CAN adapter, this command will disable its CAN power output.
            # Otherwise the command will silently fail. The CAN power output must be disabled because it interferes
            # with the power supply delivery testing.
            try:
                drv_test.execute_cli_command('cfg set can.power_on 0',
                                             lambda _: None)
            except Exception as ex:
                logger.debug('CAN adapter CLI command failed: %s', ex)

            info('Testing CAN bus exchange: target --> test')
            for idx, rf in enumerate(random_frames):
                drv_target.send(rf.id, rf.data, rf.extended)
                received = drv_test.receive(1)
                enforce(received is not None,
                        'Timeout when trying to receive frame %d', idx + 1)
                enforce(
                    received.extended == rf.extended
                    and received.data == rf.data and received.id == rf.id,
                    'Received frame %d [%r] does not match the reference [%r]',
                    idx + 1, received, rf)

            info('Testing CAN bus exchange: test --> target')
            for idx, rf in enumerate(random_frames):
                drv_test.send(rf.id, rf.data, rf.extended)
                try:
                    received = drv_target.receive(1)
                except TimeoutError:
                    fatal('Timeout when trying to receive frame %d', idx + 1)
                enforce(
                    received['ext'] == rf.extended
                    and received['data'] == rf.data
                    and received['id'] == rf.id,
                    'Received frame %d [%r] does not match the reference [%r]',
                    idx + 1, received, rf)

            info('Test exchange OK (2x%d frames)', len(random_frames))

            info('Testing power supply...')

            drv_target.execute_cli_command(
                'cfg set can.power_on 0')  # Bus power OFF
            time.sleep(2)
            stat = yaml.load(drv_target.execute_cli_command('stat'))
            enforce(
                BUS_VOLTAGE_RANGE_OFF[0] <= stat['bus_voltage'] <=
                BUS_VOLTAGE_RANGE_OFF[1],
                'Invalid voltage on the bus (power is turned OFF): %r volts; '
                'there may be a short circuit on the board',
                stat['bus_voltage'])
            info('Bus voltage: %r', stat['bus_voltage'])

            drv_target.execute_cli_command(
                'cfg set can.power_on 1')  # Bus power ON
            time.sleep(2)
            stat = yaml.load(drv_target.execute_cli_command('stat'))
            enforce(
                BUS_VOLTAGE_RANGE_ON[0] <= stat['bus_voltage'] <=
                BUS_VOLTAGE_RANGE_ON[1],
                'Invalid voltage on the bus (power is turned ON): %r volts; '
                'the power supply circuit is malfunctioning',
                stat['bus_voltage'])
            info('Bus voltage: %r', stat['bus_voltage'])

            info('Power supply is OK')

            info('Testing LED indicators...')
            # LED1 - CAN Power      - Red
            # LED2 - Terminator ON  - Orange
            # LED3 - Status         - Blue
            # LED4 - CAN Activity   - Green
            enforce(input('Is LED1 (CAN power, RED) turned on?', yes_no=True),
                    'CAN Power LED is not working')

            enforce(
                input('Is LED2 (terminator, ORANGE) turned on?', yes_no=True),
                'Terminator and/or its LED are not working')

            enforce(
                input('Is LED3 (status, BLUE) blinking about once a second?',
                      yes_no=True), 'Status LED is not working')

            def generate_traffic():
                drv_target.send(0, b'', False)
                time.sleep(0.2)

            with BackgroundSpinner(generate_traffic):
                enforce(
                    input('Is LED4 (activity, GREEN) blinking quickly?',
                          yes_no=True),
                    'Activity LED is not working, or the bus has been disconnected'
                )

        info('Resetting configuration to factory defaults...')
        drv_target.execute_cli_command('cfg erase')

        info('Installing signature...')

        # Getting the signature
        info('Requesting signature for unique ID %s',
             binascii.hexlify(unique_id).decode())
        gen_sign_response = licensing_api.generate_signature(
            unique_id, PRODUCT_NAME)
        if gen_sign_response.new:
            info('New signature has been generated')
        else:
            info(
                'This particular device was signed earlier, reusing the existing signature'
            )
        base64_signature = b64encode(gen_sign_response.signature).decode()
        logger.info('Generated signature in Base64: %s', base64_signature)

        # Installing the signature; this may fail if the device has been signed earlier - the failure will be ignored
        out = drv_target.execute_cli_command('zubax_id %s' % base64_signature)
        logger.debug(
            'Signature installation response (may fail, which is OK): %r', out)

        # Reading the signature back and verifying it
        installed_signature = read_zubax_id(drv_target)['hw_signature']
        logger.info('Installed signature in Base64: %s', installed_signature)
        enforce(
            b64decode(installed_signature) == gen_sign_response.signature,
            'Written signature does not match the generated signature')

        info('Signature has been installed and verified')