Пример #1
0
def get_present_ecus(logcan, sendcan):
    queries = list()
    parallel_queries = list()
    responses = set()
    versions = get_interface_attr('FW_VERSIONS', ignore_none=True)

    for r in REQUESTS:
        if r.brand not in versions:
            continue

        for brand_versions in versions[r.brand].values():
            for ecu_type, addr, sub_addr in brand_versions:
                # Only query ecus in whitelist if whitelist is not empty
                if len(r.whitelist_ecus) == 0 or ecu_type in r.whitelist_ecus:
                    a = (addr, sub_addr, r.bus)
                    # Build set of queries
                    if sub_addr is None:
                        if a not in parallel_queries:
                            parallel_queries.append(a)
                    else:  # subaddresses must be queried one by one
                        if [a] not in queries:
                            queries.append([a])

                    # Build set of expected responses to filter
                    response_addr = uds.get_rx_addr_for_tx_addr(
                        addr, r.rx_offset)
                    responses.add((response_addr, sub_addr, r.bus))

    queries.insert(0, parallel_queries)

    ecu_responses: Set[Tuple[int, Optional[int], int]] = set()
    for query in queries:
        ecu_responses.update(
            get_ecu_addrs(logcan, sendcan, set(query), responses, timeout=0.1))
    return ecu_responses
Пример #2
0
def get_fw_versions(logcan, sendcan, extra=None, timeout=0.1, debug=False, progress=False):
  ecu_types = {}

  # Extract ECU addresses to query from fingerprints
  # ECUs using a subaddress need be queried one by one, the rest can be done in parallel
  addrs = []
  parallel_addrs = []

  versions = get_interface_attr('FW_VERSIONS', ignore_none=True)
  if extra is not None:
    versions.update(extra)

  for brand, brand_versions in versions.items():
    for c in brand_versions.values():
      for ecu_type, addr, sub_addr in c.keys():
        a = (brand, addr, sub_addr)
        if a not in ecu_types:
          ecu_types[(addr, sub_addr)] = ecu_type

        if sub_addr is None:
          if a not in parallel_addrs:
            parallel_addrs.append(a)
        else:
          if [a] not in addrs:
            addrs.append([a])

  addrs.insert(0, parallel_addrs)

  fw_versions = {}
  for i, addr in enumerate(tqdm(addrs, disable=not progress)):
    for addr_chunk in chunks(addr):
      for r in REQUESTS:
        try:
          addrs = [(a, s) for (b, a, s) in addr_chunk if b in (r.brand, 'any') and
                   (len(r.whitelist_ecus) == 0 or ecu_types[(a, s)] in r.whitelist_ecus)]

          if addrs:
            query = IsoTpParallelQuery(sendcan, logcan, r.bus, addrs, r.request, r.response, r.rx_offset, debug=debug)
            t = 2 * timeout if i == 0 else timeout
            fw_versions.update({addr: (version, r.request, r.rx_offset) for addr, version in query.get_data(t).items()})
        except Exception:
          cloudlog.warning(f"FW query exception: {traceback.format_exc()}")

  # Build capnp list to put into CarParams
  car_fw = []
  for addr, (version, request, rx_offset) in fw_versions.items():
    f = car.CarParams.CarFw.new_message()

    f.ecu = ecu_types[addr]
    f.fwVersion = version
    f.address = addr[0]
    f.responseAddress = uds.get_rx_addr_for_tx_addr(addr[0], rx_offset)
    f.request = request

    if addr[1] is not None:
      f.subAddress = addr[1]

    car_fw.append(f)

  return car_fw
Пример #3
0
def get_brand_addrs():
    versions = get_interface_attr('FW_VERSIONS', ignore_none=True)
    brand_addrs = defaultdict(set)
    for brand, cars in versions.items():
        for fw in cars.values():
            brand_addrs[brand] |= {(addr, sub_addr)
                                   for _, addr, sub_addr in fw.keys()}
    return brand_addrs
Пример #4
0
def _get_interface_names() -> Dict[str, List[str]]:
  # returns a dict of brand name and its respective models
  brand_names = {}
  for brand_name, model_names in get_interface_attr("CAR").items():
    model_names = [getattr(model_names, c) for c in model_names.__dict__.keys() if not c.startswith("__")]
    brand_names[brand_name] = model_names

  return brand_names
Пример #5
0
def match_fw_to_car(fw_versions, allow_exact=True, allow_fuzzy=True):
    # Try exact matching first
    exact_matches = []
    if allow_exact:
        exact_matches = [(True, match_fw_to_car_exact)]
    if allow_fuzzy:
        exact_matches.append((False, match_fw_to_car_fuzzy))

    brands = get_interface_attr('FW_VERSIONS', ignore_none=True).keys()
    for exact_match, match_func in exact_matches:
        # For each brand, attempt to fingerprint using all FW returned from its queries
        matches = set()
        for brand in brands:
            fw_versions_dict = build_fw_dict(fw_versions, filter_brand=brand)
            matches |= match_func(fw_versions_dict)

        if len(matches):
            return exact_match, matches

    return True, set()
Пример #6
0
def match_fw_to_car(fw_versions, allow_fuzzy=True):
    versions = get_interface_attr('FW_VERSIONS', ignore_none=True)

    # Try exact matching first
    exact_matches = [True]
    if allow_fuzzy:
        exact_matches.append(False)

    for exact_match in exact_matches:
        # For each brand, attempt to fingerprint using FW returned from its queries
        for brand in versions.keys():
            fw_versions_dict = build_fw_dict(fw_versions, filter_brand=brand)

            if exact_match:
                matches = match_fw_to_car_exact(fw_versions_dict)
            else:
                matches = match_fw_to_car_fuzzy(fw_versions_dict)

            if len(matches) == 1:
                return exact_match, matches

    return True, []
Пример #7
0
def get_fw_versions(logcan,
                    sendcan,
                    query_brand=None,
                    extra=None,
                    timeout=0.1,
                    debug=False,
                    progress=False):
    versions = get_interface_attr('FW_VERSIONS', ignore_none=True)
    if query_brand is not None:
        versions = {query_brand: versions[query_brand]}

    if extra is not None:
        versions.update(extra)

    # Extract ECU addresses to query from fingerprints
    # ECUs using a subaddress need be queried one by one, the rest can be done in parallel
    addrs = []
    parallel_addrs = []
    ecu_types = {}

    for brand, brand_versions in versions.items():
        for c in brand_versions.values():
            for ecu_type, addr, sub_addr in c.keys():
                a = (brand, addr, sub_addr)
                if a not in ecu_types:
                    ecu_types[a] = ecu_type

                if sub_addr is None:
                    if a not in parallel_addrs:
                        parallel_addrs.append(a)
                else:
                    if [a] not in addrs:
                        addrs.append([a])

    addrs.insert(0, parallel_addrs)

    # Get versions and build capnp list to put into CarParams
    car_fw = []
    requests = [
        r for r in REQUESTS if query_brand is None or r.brand == query_brand
    ]
    for addr in tqdm(addrs, disable=not progress):
        for addr_chunk in chunks(addr):
            for r in requests:
                try:
                    addrs = [(a, s) for (b, a, s) in addr_chunk
                             if b in (r.brand, 'any') and (
                                 len(r.whitelist_ecus) == 0 or ecu_types[
                                     (b, a, s)] in r.whitelist_ecus)]

                    if addrs:
                        query = IsoTpParallelQuery(sendcan,
                                                   logcan,
                                                   r.bus,
                                                   addrs,
                                                   r.request,
                                                   r.response,
                                                   r.rx_offset,
                                                   debug=debug)
                        for (addr, rx_addr
                             ), version in query.get_data(timeout).items():
                            f = car.CarParams.CarFw.new_message()

                            f.ecu = ecu_types.get((r.brand, addr[0], addr[1]),
                                                  Ecu.unknown)
                            f.fwVersion = version
                            f.address = addr[0]
                            f.responseAddress = rx_addr
                            f.request = r.request
                            f.brand = r.brand
                            f.bus = r.bus

                            if addr[1] is not None:
                                f.subAddress = addr[1]

                            car_fw.append(f)
                except Exception:
                    cloudlog.warning(
                        f"FW query exception: {traceback.format_exc()}")

    return car_fw
Пример #8
0
from selfdrive.car.interfaces import get_interface_attr

FW_VERSIONS = get_interface_attr('FW_VERSIONS',
                                 combine_brands=True,
                                 ignore_none=True)
_FINGERPRINTS = get_interface_attr('FINGERPRINTS',
                                   combine_brands=True,
                                   ignore_none=True)

_DEBUG_ADDRESS = {1880: 8}  # reserved for debug purposes


def is_valid_for_fingerprint(msg, car_fingerprint):
    adr = msg.address
    # ignore addresses that are more than 11 bits
    return (adr in car_fingerprint
            and car_fingerprint[adr] == len(msg.dat)) or adr >= 0x800


def eliminate_incompatible_cars(msg, candidate_cars):
    """Removes cars that could not have sent msg.

     Inputs:
      msg: A cereal/log CanData message from the car.
      candidate_cars: A list of cars to consider.

     Returns:
      A list containing the subset of candidate_cars that could have sent msg.
  """
    compatible_cars = []
Пример #9
0
#!/usr/bin/env python3
# type: ignore

from collections import defaultdict
import argparse
import os
import traceback
from tqdm import tqdm
from tools.lib.logreader import LogReader
from tools.lib.route import Route
from selfdrive.car.interfaces import get_interface_attr
from selfdrive.car.car_helpers import interface_names
from selfdrive.car.fw_versions import match_fw_to_car

NO_API = "NO_API" in os.environ
VERSIONS = get_interface_attr('FW_VERSIONS', ignore_none=True)
SUPPORTED_BRANDS = VERSIONS.keys()
SUPPORTED_CARS = [
    brand for brand in SUPPORTED_BRANDS for brand in interface_names[brand]
]
UNKNOWN_BRAND = "unknown"

try:
    from xx.pipeline.c.CarState import migration
except ImportError:
    migration = {}

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description='Run FW fingerprint on Qlog of route or list of routes')
    parser.add_argument('route', help='Route or file with list of routes')