Пример #1
0
    def from_json_obj(json_obj):
        result = RFSettings()

        rf_data = try_get(json_obj, "rf_settings")
        # pipes 0-1
        for pipe in ['pipe0', 'pipe1']:
            # bytes are stored in big endian
            data = bytes_from_hex(try_get(rf_data, pipe))
            if len(data) != RF_ADDR_WIDTH:
                raise ParseError("Expected '{}' to be {} byte(s) long", data,
                                 RF_ADDR_WIDTH)
            setattr(result, pipe, data)

        # pipes 2-5
        for pipe in ['pipe2', 'pipe3', 'pipe4', 'pipe5']:
            data = int(try_get(rf_data, pipe), base=16)
            check_range(data, pipe, 0, 255)
            setattr(result, pipe, data)

        # channel
        channel = try_get(rf_data, 'rf_channel', val_type=int)
        if channel < 0 or channel > 255:
            raise ParseError("Expected 'rf_channel' to be in range 0-255")
        result.channel = channel

        # arc
        arc = try_get(rf_data, 'auto_retransmit_count', val_type=int)
        check_range(arc, 'auto_retransmit_count', 0, 15)
        result.arc = arc

        # data rate
        data_rate = try_get(rf_data, 'data_rate')
        if data_rate in RFSettings.DataRateStrMap:
            data_rate = RFSettings.DataRateStrMap[data_rate]
        else:
            raise ParseError(
                "Unexpected value '{}' for 'data_rate'".format(data_rate))
        result.data_rate = data_rate

        # power
        power = try_get(rf_data, 'transmit_power')
        if power in RFSettings.PowerStrMap:
            power = RFSettings.PowerStrMap[power]
        else:
            raise ParseError(
                "Unexpected value '{}' for 'transmit_power'".format(power))
        result.power = power

        # reserved[14]
        result.reserved = bytearray(14)

        # aes encryption key and the final round key data for decryption
        aes_ekey = bytes_from_hex(try_get(rf_data, 'aes_encryption_key'))
        result.ekey = aes_ekey

        return result
Пример #2
0
    def __init__(self, scan_mode_dict, debug_hint):
        self.parse_header(scan_mode_dict, debug_hint)

        self.debounce_time_press = DEFAULT_DEBOUNCE_PRESS_TIME
        self.matrix_map = None
        self.debounce_time_release = DEFAULT_DEBOUNCE_RELEASE_TIME
        self.trigger_time_press = DEFAULT_PRESS_TRIGGER_TIME
        self.trigger_time_release = DEFAULT_RELEASE_TRIGGER_TIME
        self.parasitic_discharge_delay_idle = DEFAULT_PARASITIC_DISCHARGE_DELAY_IDLE
        self.parasitic_discharge_delay_debouncing = DEFAULT_PARASITIC_DISCHARGE_DELAY_DEBOUNCE

        if 'matrix_map' in scan_mode_dict:
            self.parse_matrix_map(scan_mode_dict['matrix_map'], debug_hint)

    # uint8_t trigger_time_press; // The key must be down this long before being registered (ms)
    # uint8_t trigger_time_release; // The key must be up this long before being registered (ms)

    # // Both delays are measured on a scale of 0-48µs
    # uint8_t parasitic_discharge_delay_idle; // How long to hold a row low before reading the columns
    # uint8_t parasitic_discharge_delay_debouncing; // How long to hold a row low when a key is debouncing
        if 'debounce_time_press' in scan_mode_dict:
            self.debounce_time_press = scan_mode_dict['debounce_time_press']

        if 'debounce_time_release' in scan_mode_dict:
            self.debounce_time_release = scan_mode_dict[
                'debounce_time_release']

        if 'trigger_time_press' in scan_mode_dict:
            self.trigger_time_press = scan_mode_dict['trigger_time_press']

        if 'trigger_time_release' in scan_mode_dict:
            self.trigger_time_release = scan_mode_dict['trigger_time_release']

        if 'parasitic_discharge_delay_idle' in scan_mode_dict:
            delay = scan_mode_dict['parasitic_discharge_delay_idle']
            if (0 < delay > 48.0):
                raise ParseError(
                    "parasitic_discharge_delay_idle must less than 48.0µs")
            self.parasitic_discharge_delay_idle = delay

        if 'parasitic_discharge_delay_debouncing' in scan_mode_dict:
            delay = scan_mode_dict['parasitic_discharge_delay_debouncing']
            if (0 < delay > 48.0):
                raise ParseError(
                    "parasitic_discharge_delay_debouncing must less than 48.0µs"
                )
            self.parasitic_discharge_delay_debouncing = delay

        self.get_pin_numbers_for_device(None)
Пример #3
0
    def parse_header(self, sm_raw, debug_hint):
        self.mode = try_get(sm_raw, 'mode', debug_hint, val_type=str)
        mode = self.mode
        if self.mode not in ScanMode.MODE_MAP:
            raise ParseError(
                "Unsupported scan mode '{}' for device '{}'".format(
                    self.mode, debug_hint))
        self.mode = ScanMode.MODE_MAP[self.mode]

        self.col_pins = None
        self.row_pins = None
        self.row_count = 0
        self.col_count = 0

        if self.mode == ScanMode.NO_MATRIX:
            pass
        elif self.mode == ScanMode.COL_ROW:
            # Get the row pins
            row_data = try_get(sm_raw,
                               'rows',
                               debug_hint,
                               val_type=[int, list])
            if isinstance(row_data, int):
                self.row_pins = None
                self.row_count = row_data
            elif isinstance(row_data, list):
                self.row_pins = row_data
                self.row_count = len(self.row_pins)

            # Get the column pins
            col_data = try_get(sm_raw,
                               'cols',
                               debug_hint,
                               val_type=[int, list])
            if isinstance(col_data, int):
                self.col_pins = None
                self.col_count = col_data
            elif isinstance(col_data, list):
                self.col_pins = col_data
                self.col_count = len(self.col_pins)
        elif self.mode == ScanMode.PINS:
            # TODO:
            # self.row_count = 1
            # self.col_count = 10
            raise ParseError("pins not implemented")
        else:
            raise ParseError("InternalError: Unknown ScanMode({})".format(
                self.mode))
Пример #4
0
    def get_pin_numbers_for_device(self, target_device):
        # TODO: don't hard code the chip id, instead obtain it from the device
        ATMEL_ID = 0x03eb0000
        self.pin_mapper = get_io_mapper_for_chip(ATMEL_ID | 0x000A)

        if self.row_pins == None:
            row_pins = self.pin_mapper.get_default_rows(self.row_count)
        else:
            row_pins = [
                self.pin_mapper.get_pin_number(pin) for pin in self.row_pins
            ]

        if len(row_pins) < MAX_NUM_ROWS:
            row_pins += [0] * (MAX_NUM_ROWS - len(row_pins))
        elif len(row_pins) > MAX_NUM_ROWS:
            raise ParseError(
                "Device only supports a maximum of 10 rows, got '{}'".format(
                    len(row_pins)))

        if self.col_pins == None:
            col_pins = self.pin_mapper.get_default_cols(self.col_count)
        else:
            col_pins = [
                self.pin_mapper.get_pin_number(pin) for pin in self.col_pins
            ]

        self.col_pin_numbers = col_pins
        self.row_pin_numbers = row_pins

        if self.mode != ScanMode.NO_MATRIX:
            self.max_col_pin_num = max(self.col_pin_numbers)
            self.max_key_num = max(self.inverse_map)
        else:
            self.max_col_pin_num = 0
            self.max_key_num = 0
Пример #5
0
    def parse_matrix_map(self, mmap_raw, kb_name):
        """ The matrix_map is used to map the keys from how they are "visually
        arranged" to to how they are physically wired. """
        if len(mmap_raw) > self.row_count * self.col_count:
            raise ParseError("Too many keys in matrix_map for '{}'"
                             "got {} but expected at most {} (={}*{})".format(
                                 kb_name, len(mmap_raw),
                                 self.row_count * self.col_count,
                                 self.row_count, self.col_count))
        matrix_map = []
        inverse_map = [0x00] * self.row_count * self.col_count
        for (key_pos, map_key) in enumerate(mmap_raw):
            # these values can be used as spaces and are ignored
            if map_key in [
                    'none', '_' * 4, '_' * 5, '_' * 6, '-' * 4, '-' * 5,
                    '-' * 6
            ]:
                continue

            r, c = None, None
            try:
                results = re.match('r(\d+)c(\d+)', map_key)
                if results == None:
                    raise ParseError
                r, c = results.groups()
                r, c = int(r), int(c)
            except (ParseError, TypeError):
                raise ParseError(
                    "Expected string of the form rXcY, but got '{}' "
                    "in matrix_map '{}'".format(map_key, kb_name))
            key_num = self.col_count * r + c
            if r >= self.row_count or c >= self.col_count:
                raise ParseError(
                    "Key remap {} out of bounds "
                    "rows={}, cols={} in device matrix_map '{}'".format(
                        map_key, self.row_count, self.col_count, kb_name))

            if key_num in matrix_map:
                raise ParseError(
                    "The key '{}' appears twice in the matrix_map "
                    "of '{}'".format(map_key, kb_name))
            matrix_map.append(key_num)
            inverse_map[key_num] = key_pos

        self.matrix_map = matrix_map
        self.inverse_map = inverse_map
Пример #6
0
    def parse_header(self, sm_raw, debug_hint):
        self.mode = try_get(sm_raw, 'mode', debug_hint, val_type=str)
        self.mode = ScanMode.MODE_MAP[self.mode]

        self.rows = 0
        self.cols = 0

        if self.mode == ScanMode.COL_ROW:
            self.rows = try_get(sm_raw, 'rows', debug_hint, val_type=int)
            self.cols = try_get(sm_raw, 'cols', debug_hint, val_type=int)
        elif self.mode == ScanMode.PINS:
            # self.rows =
            self.cols = 1
            raise ParseError("pins not implemented")
        else:
            pass # TODO
Пример #7
0
    def to_json_obj(self):
        error_msgs = self.checkSettings()
        if len(error_msgs) != 0:
            msg = "Invalid Settings: " + "\n".join(error_msgs)
            raise ParseError(msg)

        return {
            'rf_settings': {
                'pipe0': RFSettings.bytearray_to_hex(self.pipe0),
                'pipe1': RFSettings.bytearray_to_hex(self.pipe1),
                'pipe2': "{:02x}".format(self.pipe2),
                'pipe3': "{:02x}".format(self.pipe3),
                'pipe4': "{:02x}".format(self.pipe4),
                'pipe5': "{:02x}".format(self.pipe5),
                'aes_encryption_key': RFSettings.bytearray_to_hex(self.ekey),
                'rf_channel': self.channel,
                'data_rate': RFSettings.data_rate_to_str(self.data_rate),
                'power': RFSettings.power_to_str(self.power),
            }
        }