def fwreboot(dev, recipient): event_id = (EVENT_GROUP_DFU << GROUP_FIELD_POS) | ( DFU_REBOOT << TYPE_FIELD_POS) success, _ = exchange_feature_report(dev, recipient, event_id, None, True) if success: logging.debug('Firmware rebooted') else: logging.debug('FW reboot request failed') return success
def fwinfo(dev, recipient): event_id = (EVENT_GROUP_DFU << GROUP_FIELD_POS) | ( DFU_IMGINFO << TYPE_FIELD_POS) success, fetched_data = exchange_feature_report(dev, recipient, event_id, None, True) if success and fetched_data: fw_info = FwInfo(fetched_data) return fw_info else: return None
def change_config(dev, recipient, config_name, config_value, device_options, module_id): config_opts = device_options[config_name] opt_id = config_opts.event_id event_id = (EVENT_GROUP_SETUP << GROUP_FIELD_POS) | (module_id << MOD_FIELD_POS) | (opt_id << OPT_FIELD_POS) value_range = config_opts.range logging.debug('Send request to update {}: {}'.format(config_name, config_value)) dev_name = get_device_type(recipient) format = get_option_format(dev_name, module_id) if format is not None: # Read out first, then modify and write back (even if there is only one member in struct, to simplify code) success, fetched_data = exchange_feature_report(dev, recipient, event_id, None, True) if not success: return success try: config = ConfigParser(fetched_data, *format[opt_id]) config.config_update(config_name, config_value) event_data = config.serialize() except (ValueError, KeyError): print('Failed. Invalid value for {}'.format(config_name)) return False else: if config_value is not None: if not check_range(config_value, value_range): print('Failed. Config value for {} must be in range {}'.format(config_name, value_range)) return False event_data = struct.pack('<I', config_value) else: event_data = None success = exchange_feature_report(dev, recipient, event_id, event_data, False) if success: logging.debug('Config changed') else: logging.debug('Config change failed') return success
def led_send_single_step(dev, recipient, step, led_id): event_id = (EVENT_GROUP_LED_STREAM << GROUP_FIELD_POS) \ | (LED_STREAM_DATA << TYPE_FIELD_POS) # Chosen data layout for struct is defined using format string. event_data = struct.pack('<BBBHHB', step.r, step.g, step.b, step.substep_count, step.substep_time, led_id) success = exchange_feature_report(dev, recipient, event_id, event_data, False, poll_interval=0.001) return success
def dfu_sync(dev, recipient): event_id = (EVENT_GROUP_DFU << GROUP_FIELD_POS) | ( DFU_SYNC << TYPE_FIELD_POS) success, fetched_data = exchange_feature_report(dev, recipient, event_id, None, True) if not success: return None fmt = '<BIII' assert struct.calcsize(fmt) <= EVENT_DATA_LEN_MAX if (fetched_data is None) or (len(fetched_data) < struct.calcsize(fmt)): return None return struct.unpack(fmt, fetched_data)
def dfu_start(dev, recipient, img_length, img_csum, offset): # Start DFU operation at selected offset. # It can happen that device will reject this request - this will be # verified by dfu sync at data exchange. event_id = (EVENT_GROUP_DFU << GROUP_FIELD_POS) | ( DFU_START << TYPE_FIELD_POS) event_data = struct.pack('<III', img_length, img_csum, offset) success = exchange_feature_report(dev, recipient, event_id, event_data, False) if success: logging.debug('DFU started') else: logging.debug('DFU start failed') return success
def fetch_config(dev, recipient, config_name, device_options, module_id): config_opts = device_options[config_name] opt_id = config_opts.event_id event_id = (EVENT_GROUP_SETUP << GROUP_FIELD_POS) | (module_id << MOD_FIELD_POS) | (opt_id << OPT_FIELD_POS) logging.debug('Fetch the current value of {} from the firmware'.format(config_name)) success, fetched_data = exchange_feature_report(dev, recipient, event_id, None, True) if not success or not fetched_data: return success, None dev_name = get_device_type(recipient) format = get_option_format(dev_name, module_id) if format is None: return success, config_opts.type.from_bytes(fetched_data, byteorder='little') else: return success, ConfigParser(fetched_data, *format[opt_id]).config_get(config_name)
def send_chunk(dev, img_csum, img_file, img_length, offset, recipient, success, progress_callback): event_id = (EVENT_GROUP_DFU << GROUP_FIELD_POS) | ( DFU_DATA << TYPE_FIELD_POS) while offset < img_length: if offset % FLASH_PAGE_SIZE == 0: # Sync DFU state at regular intervals to ensure everything # is all right. success = False dfu_info = dfu_sync(dev, recipient) if dfu_info is None: print('Lost communication with the device') break if dfu_info[0] == 0: print('DFU interrupted by device') break if (dfu_info[1] != img_length) or (dfu_info[2] != img_csum) or ( dfu_info[3] != offset): print('Invalid sync information') break chunk_data = img_file.read(EVENT_DATA_LEN_MAX) chunk_len = len(chunk_data) if chunk_len == 0: break logging.debug('Send DFU request: offset {}, size {}'.format( offset, chunk_len)) progress_callback(int(offset / img_length * 1000)) success = exchange_feature_report(dev, recipient, event_id, chunk_data, False) if not success: print('Lost communication with the device') break offset += chunk_len return offset, success
def fetch_free_steps_buffer_info(dev, recipient, led_id): event_id = (EVENT_GROUP_LED_STREAM << GROUP_FIELD_POS) \ | (led_id << MOD_FIELD_POS) success, fetched_data = exchange_feature_report(dev, recipient, event_id, None, True, poll_interval=0.001) if (not success) or (fetched_data is None): return False, (None, None) # Chosen data layout for struct is defined using format string. fmt = '<B?' assert struct.calcsize(fmt) <= EVENT_DATA_LEN_MAX if len(fetched_data) != struct.calcsize(fmt): return False, (None, None) return success, struct.unpack(fmt, fetched_data)