def _print_receiver(receiver): paired_count = receiver.count() print(receiver.name) print(' Device path :', receiver.path) print(' USB id : 046d:%s' % receiver.product_id) print(' Serial :', receiver.serial) if receiver.firmware: for f in receiver.firmware: print(' %-11s: %s' % (f.kind, f.version)) print(' Has', paired_count, 'paired device(s) out of a maximum of %d.' % receiver.max_devices) if receiver.remaining_pairings() and receiver.remaining_pairings() >= 0: print(' Has %d successful pairing(s) remaining.' % receiver.remaining_pairings()) notification_flags = _hidpp10.get_notification_flags(receiver) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names( notification_flags) print(' Notifications: %s (0x%06X)' % (', '.join(notification_names), notification_flags)) else: print(' Notifications: (none)') activity = receiver.read_register(_hidpp10.REGISTERS.devices_activity) if activity: activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)] activity_text = ', '.join( ('%d=%d' % (d, a)) for d, a in activity if a > 0) print(' Device activity counters:', activity_text or '(empty)')
def _print_receiver(receiver): paired_count = receiver.count() print ('Unifying Receiver') print (' Device path :', receiver.path) print (' USB id : 046d:%s' % receiver.product_id) print (' Serial :', receiver.serial) for f in receiver.firmware: print (' %-11s: %s' % (f.kind, f.version)) print (' Has', paired_count, 'paired device(s) out of a maximum of %d.' % receiver.max_devices) notification_flags = _hidpp10.get_notification_flags(receiver) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags) print (' Notifications: %s (0x%06X)' % (', '.join(notification_names), notification_flags)) else: print (' Notifications: (none)') activity = receiver.read_register(_hidpp10.REGISTERS.devices_activity) if activity: activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)] activity_text = ', '.join(('%d=%d' % (d, a)) for d, a in activity if a > 0) print (' Device activity counters:', activity_text or '(empty)')
def _print_receiver(receiver, verbose=False): paired_count = receiver.count() if not verbose: print ("Unifying Receiver [%s:%s] with %d devices" % (receiver.path, receiver.serial, paired_count)) return print ("Unifying Receiver") print (" Device path :", receiver.path) print (" USB id : 046d:%s" % receiver.product_id) print (" Serial :", receiver.serial) for f in receiver.firmware: print (" %-11s: %s" % (f.kind, f.version)) print (" Has", paired_count, "paired device(s) out of a maximum of", receiver.max_devices, ".") from logitech_receiver import hidpp10 notification_flags = hidpp10.get_notification_flags(receiver) if notification_flags is not None: if notification_flags: notification_names = hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags) print (" Notifications: 0x%06X = %s" % (notification_flags, ', '.join(notification_names))) else: print (" Notifications: (none)") activity = receiver.read_register(hidpp10.REGISTERS.devices_activity) if activity: activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)] activity_text = ', '.join(('%d=%d' % (d, a)) for d, a in activity if a > 0) print (" Device activity counters:", activity_text or '(empty)')
def run(receivers, args, find_receiver, _ignore): assert receivers if args.receiver: receiver_name = args.receiver.lower() receiver = find_receiver(receiver_name) if not receiver: raise Exception("no receiver found matching '%s'" % receiver_name) else: receiver = receivers[0] assert receiver receiver.status = _status.ReceiverStatus(receiver, lambda *args, **kwargs: None) # check if it's necessary to set the notification flags old_notification_flags = _hidpp10.get_notification_flags(receiver) or 0 if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless): _hidpp10.set_notification_flags(receiver, old_notification_flags | _hidpp10.NOTIFICATION_FLAG.wireless) # get all current devices known_devices = [dev.number for dev in receiver] class _HandleWithNotificationHook(int): def notifications_hook(self, n): assert n if n.devnumber == 0xFF: _notifications.process(receiver, n) elif n.sub_id == 0x41 and n.address == 0x04: if n.devnumber not in known_devices: receiver.status.new_device = receiver[n.devnumber] timeout = 20 # seconds receiver.handle = _HandleWithNotificationHook(receiver.handle) receiver.set_lock(False, timeout=timeout) print ('Pairing: turn your new device on (timing out in', timeout, 'seconds).') # the lock-open notification may come slightly later, wait for it a bit pairing_start = _timestamp() patience = 5 # seconds while receiver.status.lock_open or _timestamp() - pairing_start < patience: n = _base.read(receiver.handle) if n: n = _base.make_notification(*n) if n: receiver.handle.notifications_hook(n) if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless): # only clear the flags if they weren't set before, otherwise a # concurrently running Solaar app might stop working properly _hidpp10.set_notification_flags(receiver, old_notification_flags) if receiver.status.new_device: dev = receiver.status.new_device print ('Paired device %d: %s (%s) [%s:%s]' % (dev.number, dev.name, dev.codename, dev.wpid, dev.serial)) else: error = receiver.status.get(_status.KEYS.ERROR) or 'no device detected?' raise Exception("pairing failed: %s" % error)
def pair_device(receiver, args): # get all current devices known_devices = [dev.number for dev in receiver] from logitech_receiver import base, hidpp10, status, notifications receiver.status = status.ReceiverStatus(receiver, lambda *args, **kwargs: None) # check if it's necessary to set the notification flags old_notification_flags = hidpp10.get_notification_flags(receiver) or 0 if not (old_notification_flags & hidpp10.NOTIFICATION_FLAG.wireless): hidpp10.set_notification_flags(receiver, old_notification_flags | hidpp10.NOTIFICATION_FLAG.wireless) class HandleWithNotificationHook(int): def notifications_hook(self, n): assert n if n.devnumber == 0xFF: notifications.process(receiver, n) elif n.sub_id == 0x41 and n.address == 0x04: if n.devnumber not in known_devices: receiver.status.new_device = receiver[n.devnumber] timeout = 20 # seconds receiver.handle = HandleWithNotificationHook(receiver.handle) receiver.set_lock(False, timeout=timeout) print ("Pairing: turn your new device on (timing out in", timeout, "seconds).") # the lock-open notification may come slightly later, wait for it a bit from time import time as timestamp pairing_start = timestamp() patience = 5 # seconds while receiver.status.lock_open or timestamp() - pairing_start < patience: n = base.read(receiver.handle) if n: n = base.make_notification(*n) if n: receiver.handle.notifications_hook(n) if not (old_notification_flags & hidpp10.NOTIFICATION_FLAG.wireless): # only clear the flags if they weren't set before, otherwise a # concurrently running Solaar app might stop working properly hidpp10.set_notification_flags(receiver, old_notification_flags) if receiver.status.new_device: dev = receiver.status.new_device print ("Paired device %d: %s [%s:%s:%s]" % (dev.number, dev.name, dev.wpid, dev.codename, dev.serial)) else: error = receiver.status[status.KEYS.ERROR] or 'no device detected?' _fail(error)
def _print_device(dev): assert dev print (' %d: %s' % (dev.number, dev.name)) print (' Codename :', dev.codename) print (' Kind :', dev.kind) print (' Wireless PID :', dev.wpid) if dev.protocol: print (' Protocol : HID++ %1.1f' % dev.protocol) else: print (' Protocol : unknown (device is offline)') if dev.polling_rate: print (' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate)) print (' Serial number:', dev.serial) for fw in dev.firmware: print (' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip()) if dev.power_switch_location: print (' The power switch is located on the %s.' % dev.power_switch_location) if dev.online: notification_flags = _hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags) print (' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags)) else: print (' Notifications: (none).') if dev.online and dev.features: print (' Supports %d HID++ 2.0 features:' % len(dev.features)) for index, feature in enumerate(dev.features): feature = dev.features[index] flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) flags = _hidpp20.FEATURE_FLAG.flag_names(flags) print (' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags))) if dev.online and dev.keys: print (' Has %d reprogrammable keys:' % len(dev.keys)) for k in dev.keys: flags = _special_keys.KEY_FLAG.flag_names(k.flags) print (' %2d: %-26s => %-27s %s' % (k.index, k.key, k.task, ', '.join(flags))) _print_battery_status(dev)
def _print_device(dev): assert dev # check if the device is online dev.ping() print(' %d: %s' % (dev.number, dev.name)) print(' Codename :', dev.codename) print(' Kind :', dev.kind) print(' Wireless PID :', dev.wpid) if dev.protocol: print(' Protocol : HID++ %1.1f' % dev.protocol) else: print(' Protocol : unknown (device is offline)') if dev.polling_rate: print(' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate)) print(' Serial number:', dev.serial) if dev.firmware: for fw in dev.firmware: print(' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip()) if dev.power_switch_location: print(' The power switch is located on the %s.' % dev.power_switch_location) if dev.online: notification_flags = _hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names( notification_flags) print(' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags)) else: print(' Notifications: (none).') device_features = _hidpp10.get_device_features(dev) if device_features is not None: if device_features: device_features_names = _hidpp10.DEVICE_FEATURES.flag_names( device_features) print(' Features: %s (0x%06X)' % (', '.join(device_features_names), device_features)) else: print(' Features: (none)') if dev.online and dev.features: print(' Supports %d HID++ 2.0 features:' % len(dev.features)) dev.persister = None # Give the device a fake persister dev_settings = [] _settings_templates.check_feature_settings(dev, dev_settings) for index, feature in enumerate(dev.features): feature = dev.features[index] flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) flags = _hidpp20.FEATURE_FLAG.flag_names(flags) print(' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags))) if feature == _hidpp20.FEATURE.HIRES_WHEEL: wheel = _hidpp20.get_hires_wheel(dev) if wheel: multi, has_invert, has_switch, inv, res, target, ratchet = wheel print(' Multiplier: %s' % multi) if has_invert: print(' Has invert') if inv: print(' Inverse wheel motion') else: print(' Normal wheel motion') if has_switch: print(' Has ratchet switch') if ratchet: print(' Normal wheel mode') else: print(' Free wheel mode') if res: print(' High resolution mode') else: print(' Low resolution mode') if target: print(' HID++ notification') else: print(' HID notification') elif feature == _hidpp20.FEATURE.MOUSE_POINTER: mouse_pointer = _hidpp20.get_mouse_pointer_info(dev) if mouse_pointer: print(' DPI: %s' % mouse_pointer['dpi']) print(' Acceleration: %s' % mouse_pointer['acceleration']) if mouse_pointer['suggest_os_ballistics']: print(' Use OS ballistics') else: print(' Override OS ballistics') if mouse_pointer['suggest_vertical_orientation']: print(' Provide vertical tuning, trackball') else: print(' No vertical tuning, standard mice') if feature == _hidpp20.FEATURE.VERTICAL_SCROLLING: vertical_scrolling_info = _hidpp20.get_vertical_scrolling_info( dev) if vertical_scrolling_info: print(' Roller type: %s' % vertical_scrolling_info['roller']) print(' Ratchet per turn: %s' % vertical_scrolling_info['ratchet']) print(' Scroll lines: %s' % vertical_scrolling_info['lines']) elif feature == _hidpp20.FEATURE.HI_RES_SCROLLING: scrolling_mode, scrolling_resolution = _hidpp20.get_hi_res_scrolling_info( dev) if scrolling_mode: print(' Hi-res scrolling enabled') else: print(' Hi-res scrolling disabled') if scrolling_resolution: print(' Hi-res scrolling multiplier: %s' % scrolling_resolution) elif feature == _hidpp20.FEATURE.POINTER_SPEED: pointer_speed = _hidpp20.get_pointer_speed_info(dev) if pointer_speed: print(' Pointer Speed: %s' % pointer_speed) elif feature == _hidpp20.FEATURE.LOWRES_WHEEL: wheel_status = _hidpp20.get_lowres_wheel_status(dev) if wheel_status: print(' Wheel Reports: %s' % wheel_status) elif feature == _hidpp20.FEATURE.NEW_FN_INVERSION: inverted, default_inverted = _hidpp20.get_new_fn_inversion(dev) print(' Fn-swap:', 'enabled' if inverted else 'disabled') print(' Fn-swap default:', 'enabled' if default_inverted else 'disabled') elif feature == _hidpp20.FEATURE.HOSTS_INFO: host_names = _hidpp20.get_host_names(dev) for host, (paired, name) in host_names.items(): print(' Host %s (%s): %s' % (host, 'paired' if paired else 'unpaired', name)) for setting in dev_settings: if setting.feature == feature: v = setting.read(False) print(' %s: %s' % (setting.label, v)) if dev.online and dev.keys: print(' Has %d reprogrammable keys:' % len(dev.keys)) for k in dev.keys: flags = _special_keys.KEY_FLAG.flag_names(k.flags) # TODO: add here additional variants for other REPROG_CONTROLS if dev.keys.keyversion == 1: print(' %2d: %-26s => %-27s %s' % (k.index, k.key, k.task, ', '.join(flags))) if dev.keys.keyversion == 4: print(' %2d: %-26s, default: %-27s => %-26s' % (k.index, k.key, k.task, k.remapped)) print(' %s, pos:%d, group:%1d, gmask:%d' % (', '.join(flags), k.pos, k.group, k.group_mask)) if dev.online: battery = _hidpp20.get_battery(dev) if battery is None: battery = _hidpp10.get_battery(dev) if battery is not None: level, status, nextLevel = battery text = _battery_text(level) nextText = '' if nextLevel is None else ', next level ' + _battery_text( nextLevel) print(' Battery: %s, %s%s.' % (text, status, nextText)) else: battery_voltage = _hidpp20.get_voltage(dev) if battery_voltage: (level, status, voltage, charge_sts, charge_type) = battery_voltage print(' Battery: %smV, %s, %s.' % (voltage, status, level)) else: print(' Battery status unavailable.') else: print(' Battery: unknown (device is offline).')
def _print_device(dev): assert dev # check if the device is online dev.ping() print(' %d: %s' % (dev.number, dev.name)) print(' Codename :', dev.codename) print(' Kind :', dev.kind) print(' Wireless PID :', dev.wpid) if dev.protocol: print(' Protocol : HID++ %1.1f' % dev.protocol) else: print(' Protocol : unknown (device is offline)') if dev.polling_rate: print(' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate)) print(' Serial number:', dev.serial) for fw in dev.firmware: print(' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip()) if dev.power_switch_location: print(' The power switch is located on the %s.' % dev.power_switch_location) if dev.online: notification_flags = _hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names( notification_flags) print(' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags)) else: print(' Notifications: (none).') if dev.online and dev.features: print(' Supports %d HID++ 2.0 features:' % len(dev.features)) for index, feature in enumerate(dev.features): feature = dev.features[index] flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) flags = _hidpp20.FEATURE_FLAG.flag_names(flags) print(' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags))) if feature == _hidpp20.FEATURE.HIRES_WHEEL: wheel = _hidpp20.get_hires_wheel(dev) if wheel: multi, has_invert, has_switch, inv, res, target, ratchet = wheel print(" Multiplier: %s" % multi) if has_invert: print(" Has invert") if inv: print(" Inverse wheel motion") else: print(" Normal wheel motion") if has_switch: print(" Has ratchet switch") if ratchet: print(" Normal wheel mode") else: print(" Free wheel mode") if res: print(" High resolution mode") else: print(" Low resolution mode") if target: print(" HID++ notification") else: print(" HID notification") if feature == _hidpp20.FEATURE.MOUSE_POINTER: mouse_pointer = _hidpp20.get_mouse_pointer_info(dev) if mouse_pointer: print(" DPI: %s" % mouse_pointer['dpi']) print(" Acceleration: %s" % mouse_pointer['acceleration']) if mouse_pointer['suggest_os_ballistics']: print(" Use OS ballistics") else: print(" Override OS ballistics") if mouse_pointer['suggest_vertical_orientation']: print(" Provide vertical tuning, trackball") else: print(" No vertical tuning, standard mice") if feature == _hidpp20.FEATURE.VERTICAL_SCROLLING: vertical_scrolling_info = _hidpp20.get_vertical_scrolling_info( dev) if vertical_scrolling_info: print(" Roller type: %s" % vertical_scrolling_info['roller']) print(" Ratchet per turn: %s" % vertical_scrolling_info['ratchet']) print(" Scroll lines: %s" % vertical_scrolling_info['lines']) if feature == _hidpp20.FEATURE.HI_RES_SCROLLING: scrolling_mode, scrolling_resolution = _hidpp20.get_hi_res_scrolling_info( dev) if scrolling_mode: print(" Hi-res scrolling enabled") else: print(" Hi-res scrolling disabled") if scrolling_resolution: print(" Hi-res scrolling multiplier: %s" % scrolling_resolution) if feature == _hidpp20.FEATURE.POINTER_SPEED: pointer_speed = _hidpp20.get_pointer_speed_info(dev) if pointer_speed: print(" Pointer Speed: %s" % pointer_speed) if feature == _hidpp20.FEATURE.LOWRES_WHEEL: wheel_status = _hidpp20.get_lowres_wheel_status(dev) if wheel_status: print(" Wheel Reports: %s" % wheel_status) if dev.online and dev.keys: print(' Has %d reprogrammable keys:' % len(dev.keys)) for k in dev.keys: flags = _special_keys.KEY_FLAG.flag_names(k.flags) # TODO: add here additional variants for other REPROG_CONTROLS if dev.keys.keyversion == 1: print(' %2d: %-26s => %-27s %s' % (k.index, k.key, k.task, ', '.join(flags))) if dev.keys.keyversion == 4: print(' %2d: %-26s, default: %-27s => %-26s' % (k.index, k.key, k.task, k.remapped)) print(' %s, pos:%d, group:%1d, gmask:%d' % (', '.join(flags), k.pos, k.group, k.group_mask)) if dev.online: battery = _hidpp20.get_battery(dev) if battery is None: battery = _hidpp10.get_battery(dev) if battery is not None: from logitech_receiver.common import NamedInt as _NamedInt level, status = battery if level is not None: if isinstance(level, _NamedInt): text = str(level) else: text = '%d%%' % level else: text = 'N/A' print(' Battery: %s, %s.' % (text, status)) else: battery_voltage = _hidpp20.get_voltage(dev) if battery_voltage: (voltage, charging, charge_sts, charge_lvl, charge_type) = battery_voltage print(' Battery: %smV, %s.' % (voltage, 'Charging' if charging else 'Discharging')) else: print(' Battery status unavailable.') else: print(' Battery: unknown (device is offline).')
def _print_device(dev, num=None): assert dev is not None # check if the device is online dev.ping() print(' %d: %s' % (num or dev.number, dev.name)) print(' Device path :', dev.path) if dev.wpid: print(' WPID : %s' % dev.wpid) if dev.product_id: print(' USB id : 046d:%s' % dev.product_id) print(' Codename :', dev.codename) print(' Kind :', dev.kind) if dev.protocol: print(' Protocol : HID++ %1.1f' % dev.protocol) else: print(' Protocol : unknown (device is offline)') if dev.polling_rate: print(' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate)) print(' Serial number:', dev.serial) if dev.modelId: print(' Model ID: ', dev.modelId) if dev.unitId: print(' Unit ID: ', dev.unitId) if dev.firmware: for fw in dev.firmware: print(' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip()) if dev.power_switch_location: print(' The power switch is located on the %s.' % dev.power_switch_location) if dev.online: notification_flags = _hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names( notification_flags) print(' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags)) else: print(' Notifications: (none).') device_features = _hidpp10.get_device_features(dev) if device_features is not None: if device_features: device_features_names = _hidpp10.DEVICE_FEATURES.flag_names( device_features) print(' Features: %s (0x%06X)' % (', '.join(device_features_names), device_features)) else: print(' Features: (none)') if dev.online and dev.features: print(' Supports %d HID++ 2.0 features:' % len(dev.features)) dev_settings = [] _settings_templates.check_feature_settings(dev, dev_settings) for index, feature in enumerate(dev.features): feature = dev.features[index] flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) flags = _hidpp20.FEATURE_FLAG.flag_names(flags) print(' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags))) if feature == _hidpp20.FEATURE.HIRES_WHEEL: wheel = _hidpp20.get_hires_wheel(dev) if wheel: multi, has_invert, has_switch, inv, res, target, ratchet = wheel print(' Multiplier: %s' % multi) if has_invert: print( ' Has invert:', 'Inverse wheel motion' if inv else 'Normal wheel motion') if has_switch: print( ' Has ratchet switch:', 'Normal wheel mode' if ratchet else 'Free wheel mode') if res: print(' High resolution mode') else: print(' Low resolution mode') if target: print(' HID++ notification') else: print(' HID notification') elif feature == _hidpp20.FEATURE.MOUSE_POINTER: mouse_pointer = _hidpp20.get_mouse_pointer_info(dev) if mouse_pointer: print(' DPI: %s' % mouse_pointer['dpi']) print(' Acceleration: %s' % mouse_pointer['acceleration']) if mouse_pointer['suggest_os_ballistics']: print(' Use OS ballistics') else: print(' Override OS ballistics') if mouse_pointer['suggest_vertical_orientation']: print(' Provide vertical tuning, trackball') else: print(' No vertical tuning, standard mice') if feature == _hidpp20.FEATURE.VERTICAL_SCROLLING: vertical_scrolling_info = _hidpp20.get_vertical_scrolling_info( dev) if vertical_scrolling_info: print(' Roller type: %s' % vertical_scrolling_info['roller']) print(' Ratchet per turn: %s' % vertical_scrolling_info['ratchet']) print(' Scroll lines: %s' % vertical_scrolling_info['lines']) elif feature == _hidpp20.FEATURE.HI_RES_SCROLLING: scrolling_mode, scrolling_resolution = _hidpp20.get_hi_res_scrolling_info( dev) if scrolling_mode: print(' Hi-res scrolling enabled') else: print(' Hi-res scrolling disabled') if scrolling_resolution: print(' Hi-res scrolling multiplier: %s' % scrolling_resolution) elif feature == _hidpp20.FEATURE.POINTER_SPEED: pointer_speed = _hidpp20.get_pointer_speed_info(dev) if pointer_speed: print(' Pointer Speed: %s' % pointer_speed) elif feature == _hidpp20.FEATURE.LOWRES_WHEEL: wheel_status = _hidpp20.get_lowres_wheel_status(dev) if wheel_status: print(' Wheel Reports: %s' % wheel_status) elif feature == _hidpp20.FEATURE.NEW_FN_INVERSION: inversion = _hidpp20.get_new_fn_inversion(dev) if inversion: inverted, default_inverted = inversion print(' Fn-swap:', 'enabled' if inverted else 'disabled') print(' Fn-swap default:', 'enabled' if default_inverted else 'disabled') elif feature == _hidpp20.FEATURE.HOSTS_INFO: host_names = _hidpp20.get_host_names(dev) for host, (paired, name) in host_names.items(): print(' Host %s (%s): %s' % (host, 'paired' if paired else 'unpaired', name)) elif feature == _hidpp20.FEATURE.DEVICE_NAME: print(' Name: %s' % _hidpp20.get_name(dev)) print(' Kind: %s' % _hidpp20.get_kind(dev)) elif feature == _hidpp20.FEATURE.DEVICE_FRIENDLY_NAME: print(' Friendly Name: %s' % _hidpp20.get_friendly_name(dev)) elif feature == _hidpp20.FEATURE.DEVICE_FW_VERSION: for fw in _hidpp20.get_firmware(dev): extras = _strhex(fw.extras) if fw.extras else '' print(' Firmware: %s %s %s %s' % (fw.kind, fw.name, fw.version, extras)) ids = _hidpp20.get_ids(dev) if ids: unitId, modelId, tid_map = ids print( ' Unit ID: %s Model ID: %s Transport IDs: %s' % (unitId, modelId, tid_map)) elif feature == _hidpp20.FEATURE.REPORT_RATE: print(' Polling Rate (ms): %d' % _hidpp20.get_polling_rate(dev)) elif feature == _hidpp20.FEATURE.REMAINING_PAIRING: print(' Remaining Pairings: %d' % _hidpp20.get_remaining_pairing(dev)) elif feature == _hidpp20.FEATURE.ONBOARD_PROFILES: if _hidpp20.get_onboard_mode( dev) == _hidpp20.ONBOARD_MODES.MODE_HOST: mode = 'Host' else: mode = 'On-Board' print(' Device Mode: %s' % mode) elif feature in (_F.BATTERY_STATUS, _F.BATTERY_VOLTAGE, _F.BATTERY_VOLTAGE): print('', end=' ') _battery_line(dev) for setting in dev_settings: if setting.feature == feature: if setting._device and getattr( setting._device, 'persister', None) and setting._device.persister.get( setting.name) is not None: print(' %s (saved): %s' % (setting.label, setting._device.persister.get(setting.name))) v = setting.read(False) print(' %s : %s' % (setting.label, v)) if dev.online and dev.keys: print(' Has %d reprogrammable keys:' % len(dev.keys)) for k in dev.keys: # TODO: add here additional variants for other REPROG_CONTROLS if dev.keys.keyversion == _hidpp20.FEATURE.REPROG_CONTROLS_V2: print(' %2d: %-26s => %-27s %s' % (k.index, k.key, k.default_task, ', '.join(k.flags))) if dev.keys.keyversion == _hidpp20.FEATURE.REPROG_CONTROLS_V4: print(' %2d: %-26s, default: %-27s => %-26s' % (k.index, k.key, k.default_task, k.mapped_to)) gmask_fmt = ','.join(k.group_mask) gmask_fmt = gmask_fmt if gmask_fmt else 'empty' print(' %s, pos:%d, group:%1d, group mask:%s' % (', '.join(k.flags), k.pos, k.group, gmask_fmt)) report_fmt = ', '.join(k.mapping_flags) report_fmt = report_fmt if report_fmt else 'default' print(' reporting: %s' % (report_fmt)) if dev.online and dev.gestures: print(' Has %d gesture(s), %d param(s) and %d spec(s):' % (len(dev.gestures.gestures), len( dev.gestures.params), len(dev.gestures.specs))) for k in dev.gestures.gestures.values(): print(' %-26s Enabled (%4s): %s' % (k.gesture, k.index, k.enabled())) for k in dev.gestures.params.values(): print(' %-26s Value (%4s): %s [Default: %s]' % (k.param, k.index, k.value, k.default_value)) for k in dev.gestures.specs.values(): print(' %-26s Spec (%4s): %s' % (k.spec, k.id, k.value)) if dev.online: _battery_line(dev) else: print(' Battery: unknown (device is offline).')
def _print_device(dev, verbose=False): assert dev state = '' if dev.ping() else 'offline' if not verbose: print ("%d: %s [%s:%s]" % (dev.number, dev.name, dev.codename, dev.serial), state) return print ("%d: %s" % (dev.number, dev.name)) print (" Codename :", dev.codename) print (" Kind :", dev.kind) print (" Wireless PID :", dev.wpid) if dev.protocol: print (" Protocol : HID++ %1.1f" % dev.protocol) else: print (" Protocol : unknown (device is offline)") print (" Polling rate :", dev.polling_rate, "ms") print (" Serial number:", dev.serial) for fw in dev.firmware: print (" %11s:" % fw.kind, (fw.name + ' ' + fw.version).strip()) if dev.power_switch_location: print (" The power switch is located on the %s." % dev.power_switch_location) from logitech_receiver import hidpp10, hidpp20, special_keys if dev.online: notification_flags = hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags) print (" Notifications: 0x%06X = %s." % (notification_flags, ', '.join(notification_names))) else: print (" Notifications: (none).") if dev.online: if dev.features: print (" Supports %d HID++ 2.0 features:" % len(dev.features)) for index, feature in enumerate(dev.features): feature = dev.features[index] flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) flags = hidpp20.FEATURE_FLAG.flag_names(flags) print (" %2d: %-22s {%04X} %s" % (index, feature, feature, ', '.join(flags))) if dev.online: if dev.keys: print (" Has %d reprogrammable keys:" % len(dev.keys)) for k in dev.keys: flags = special_keys.KEY_FLAG.flag_names(k.flags) print (" %2d: %-26s => %-27s %s" % (k.index, k.key, k.task, ', '.join(flags))) if dev.online: battery = hidpp20.get_battery(dev) if battery is None: battery = hidpp10.get_battery(dev) if battery is not None: from logitech_receiver.common import NamedInt as _NamedInt level, status = battery if isinstance(level, _NamedInt): text = str(level) else: text = '%d%%' % level print (" Battery: %s, %s," % (text, status)) else: print (" Battery status unavailable.") else: print (" Battery status is unknown (device is offline).")
def _print_device(dev): assert dev # check if the device is online dev.ping() print(' %d: %s' % (dev.number, dev.name)) print(' Codename :', dev.codename) print(' Kind :', dev.kind) print(' Wireless PID :', dev.wpid) if dev.protocol: print(' Protocol : HID++ %1.1f' % dev.protocol) else: print(' Protocol : unknown (device is offline)') if dev.polling_rate: print(' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate)) print(' Serial number:', dev.serial) for fw in dev.firmware: print(' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip()) if dev.power_switch_location: print(' The power switch is located on the %s.' % dev.power_switch_location) if dev.online: notification_flags = _hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names( notification_flags) print(' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags)) else: print(' Notifications: (none).') if dev.online and dev.features: print(' Supports %d HID++ 2.0 features:' % len(dev.features)) for index, feature in enumerate(dev.features): feature = dev.features[index] flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) flags = _hidpp20.FEATURE_FLAG.flag_names(flags) print(' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags))) if dev.online and dev.keys: print(' Has %d reprogrammable keys:' % len(dev.keys)) for k in dev.keys: flags = _special_keys.KEY_FLAG.flag_names(k.flags) # TODO: add here additional variants for other REPROG_CONTROLS if dev.keys.keyversion == 1: print(' %2d: %-26s => %-27s %s' % (k.index, k.key, k.task, ', '.join(flags))) if dev.keys.keyversion == 4: print(' %2d: %-26s, default: %-27s => %-26s' % (k.index, k.key, k.task, k.remapped)) print(' %s, pos:%d, group:%1d, gmask:%d' % (', '.join(flags), k.pos, k.group, k.group_mask)) if dev.online: battery = _hidpp20.get_battery(dev) if battery is None: battery = _hidpp10.get_battery(dev) if battery is not None: from logitech_receiver.common import NamedInt as _NamedInt level, status = battery if level is not None: if isinstance(level, _NamedInt): text = str(level) else: text = '%d%%' % level else: text = 'N/A' print(' Battery: %s, %s.' % (text, status)) else: print(' Battery status unavailable.') else: print(' Battery: unknown (device is offline).')
def run(receivers, args, find_receiver, _ignore): assert receivers if args.receiver: receiver_name = args.receiver.lower() receiver = find_receiver(receivers, receiver_name) if not receiver: raise Exception("no receiver found matching '%s'" % receiver_name) else: receiver = receivers[0] assert receiver receiver.status = _status.ReceiverStatus(receiver, lambda *args, **kwargs: None) # check if it's necessary to set the notification flags old_notification_flags = _hidpp10.get_notification_flags(receiver) or 0 if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless): _hidpp10.set_notification_flags( receiver, old_notification_flags | _hidpp10.NOTIFICATION_FLAG.wireless) # get all current devices known_devices = [dev.number for dev in receiver] class _HandleWithNotificationHook(int): def notifications_hook(self, n): nonlocal known_devices assert n if n.devnumber == 0xFF: _notifications.process(receiver, n) elif n.sub_id == 0x41 and len( n.data) == _base._SHORT_MESSAGE_SIZE - 4: kd, known_devices = known_devices, None # only process one connection notification if kd is not None: if n.devnumber not in kd: receiver.status.new_device = receiver.register_new_device( n.devnumber, n) elif receiver.re_pairs: del receiver[ n. devnumber] # get rid of information on device re-paired away receiver.status.new_device = receiver.register_new_device( n.devnumber, n) timeout = 30 # seconds receiver.handle = _HandleWithNotificationHook(receiver.handle) if receiver.receiver_kind == 'bolt': # Bolt receivers require authentication to pair a device receiver.discover(timeout=timeout) print( 'Bolt Pairing: long-press the pairing key or button on your device (timing out in', timeout, 'seconds).') pairing_start = _timestamp() patience = 5 # the discovering notification may come slightly later, so be patient while receiver.status.discovering or _timestamp( ) - pairing_start < patience: if receiver.status.device_address and receiver.status.device_authentication and receiver.status.device_name: break n = _base.read(receiver.handle) n = _base.make_notification(*n) if n else None if n: receiver.handle.notifications_hook(n) address = receiver.status.device_address name = receiver.status.device_name authentication = receiver.status.device_authentication kind = receiver.status.device_kind print(f'Bolt Pairing: discovered {name}') receiver.pair_device( address=address, authentication=authentication, entropy=20 if kind == _hidpp10.DEVICE_KIND.keyboard else 10) pairing_start = _timestamp() patience = 5 # the discovering notification may come slightly later, so be patient while receiver.status.lock_open or _timestamp( ) - pairing_start < patience: if receiver.status.device_passkey: break n = _base.read(receiver.handle) n = _base.make_notification(*n) if n else None if n: receiver.handle.notifications_hook(n) if authentication & 0x01: print( f'Bolt Pairing: type passkey {receiver.status.device_passkey} and then press the enter key' ) else: passkey = f'{int(receiver.status.device_passkey):010b}' passkey = ', '.join( ['right' if bit == '1' else 'left' for bit in passkey]) print(f'Bolt Pairing: press {passkey}') print('and then press left and right buttons simultaneously') while receiver.status.lock_open: n = _base.read(receiver.handle) n = _base.make_notification(*n) if n else None if n: receiver.handle.notifications_hook(n) else: receiver.set_lock(False, timeout=timeout) print('Pairing: turn your new device on (timing out in', timeout, 'seconds).') pairing_start = _timestamp() patience = 5 # the lock-open notification may come slightly later, wait for it a bit while receiver.status.lock_open or _timestamp( ) - pairing_start < patience: n = _base.read(receiver.handle) if n: n = _base.make_notification(*n) if n: receiver.handle.notifications_hook(n) if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless): # only clear the flags if they weren't set before, otherwise a # concurrently running Solaar app might stop working properly _hidpp10.set_notification_flags(receiver, old_notification_flags) if receiver.status.new_device: dev = receiver.status.new_device print('Paired device %d: %s (%s) [%s:%s]' % (dev.number, dev.name, dev.codename, dev.wpid, dev.serial)) else: error = receiver.status.get(_status.KEYS.ERROR) if error: raise Exception('pairing failed: %s' % error) else: print('Paired device') # this is better than an error
def _print_device(dev): assert dev # check if the device is online dev.ping() print (' %d: %s' % (dev.number, dev.name)) print (' Codename :', dev.codename) print (' Kind :', dev.kind) print (' Wireless PID :', dev.wpid) if dev.protocol: print (' Protocol : HID++ %1.1f' % dev.protocol) else: print (' Protocol : unknown (device is offline)') if dev.polling_rate: print (' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate)) print (' Serial number:', dev.serial) for fw in dev.firmware: print (' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip()) if dev.power_switch_location: print (' The power switch is located on the %s.' % dev.power_switch_location) if dev.online: notification_flags = _hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags) print (' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags)) else: print (' Notifications: (none).') if dev.online and dev.features: print (' Supports %d HID++ 2.0 features:' % len(dev.features)) for index, feature in enumerate(dev.features): feature = dev.features[index] flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) flags = _hidpp20.FEATURE_FLAG.flag_names(flags) print (' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags))) if feature == _hidpp20.FEATURE.HIRES_WHEEL: wheel = _hidpp20.get_hires_wheel(dev) if wheel: multi, has_invert, has_switch, inv, res, target, ratchet = wheel print(" Multiplier: %s" % multi) if has_invert: print(" Has invert") if inv: print(" Inverse wheel motion") else: print(" Normal wheel motion") if has_switch: print(" Has ratchet switch") if ratchet: print(" Normal wheel mode") else: print(" Free wheel mode") if res: print(" High resolution mode") else: print(" Low resolution mode") if target: print(" HID++ notification") else: print(" HID notification") if dev.online and dev.keys: print (' Has %d reprogrammable keys:' % len(dev.keys)) for k in dev.keys: flags = _special_keys.KEY_FLAG.flag_names(k.flags) # TODO: add here additional variants for other REPROG_CONTROLS if dev.keys.keyversion == 1: print (' %2d: %-26s => %-27s %s' % (k.index, k.key, k.task, ', '.join(flags))) if dev.keys.keyversion == 4: print (' %2d: %-26s, default: %-27s => %-26s' % (k.index, k.key, k.task, k.remapped)) print (' %s, pos:%d, group:%1d, gmask:%d' % ( ', '.join(flags), k.pos, k.group, k.group_mask)) if dev.online: battery = _hidpp20.get_battery(dev) if battery is None: battery = _hidpp10.get_battery(dev) if battery is not None: from logitech_receiver.common import NamedInt as _NamedInt level, status = battery if level is not None: if isinstance(level, _NamedInt): text = str(level) else: text = '%d%%' % level else: text = 'N/A' print (' Battery: %s, %s.' % (text, status)) else: print (' Battery status unavailable.') else: print (' Battery: unknown (device is offline).')