From fc0faf53d30d331094b79fc77339184854169421 Mon Sep 17 00:00:00 2001 From: spang Date: Tue, 3 Mar 2015 12:35:38 -0800 Subject: [PATCH] ozone: evdev: Sync caps lock LED state to evdev Update LED state in kernel in InputControllerEvdev::SetCapsLockEnabled. This is currently the only way to toggle caps lock. BUG=463242 TEST=plug in external keyboard on link_freon & press caps lock. Light on keyboard should turn on. Review URL: https://codereview.chromium.org/971753006 Cr-Commit-Position: refs/heads/master@{#318934} --- ui/events/ozone/evdev/event_converter_evdev.cc | 33 ++++++++++++++++++++++ ui/events/ozone/evdev/event_converter_evdev.h | 6 ++++ .../ozone/evdev/event_converter_evdev_impl.cc | 5 ++++ ui/events/ozone/evdev/event_converter_evdev_impl.h | 4 +++ ui/events/ozone/evdev/event_modifiers_evdev.cc | 4 --- ui/events/ozone/evdev/input_controller_evdev.cc | 12 ++++++++ ui/events/ozone/evdev/input_controller_evdev.h | 6 ++++ .../ozone/evdev/input_device_factory_evdev.cc | 16 ++++++++++- ui/events/ozone/evdev/input_device_factory_evdev.h | 7 +++++ .../evdev/input_device_factory_evdev_proxy.cc | 6 ++++ .../ozone/evdev/input_device_factory_evdev_proxy.h | 1 + ui/events/ozone/evdev/keyboard_evdev.h | 1 + .../libgestures_glue/event_reader_libevdev_cros.cc | 5 ++++ .../libgestures_glue/event_reader_libevdev_cros.h | 4 +++ 14 files changed, 105 insertions(+), 5 deletions(-) diff --git a/ui/events/ozone/evdev/event_converter_evdev.cc b/ui/events/ozone/evdev/event_converter_evdev.cc index b13bdffaf881..eda2e88527b4 100644 --- a/ui/events/ozone/evdev/event_converter_evdev.cc +++ b/ui/events/ozone/evdev/event_converter_evdev.cc @@ -30,6 +30,8 @@ void EventConverterEvdev::Start() { } void EventConverterEvdev::Stop() { + // TODO(spang): If we reach here due to an error, we should treat it + // as if we have lost sync & release held keys, etc. controller_.StopWatchingFileDescriptor(); } @@ -53,6 +55,10 @@ bool EventConverterEvdev::HasTouchscreen() const { return false; } +bool EventConverterEvdev::HasCapsLockLed() const { + return false; +} + gfx::Size EventConverterEvdev::GetTouchscreenSize() const { NOTREACHED(); return gfx::Size(); @@ -72,6 +78,33 @@ void EventConverterEvdev::AllowAllKeys() { NOTREACHED(); } +void EventConverterEvdev::SetCapsLockLed(bool enabled) { + if (!HasCapsLockLed()) + return; + + input_event events[2]; + memset(&events, 0, sizeof(events)); + + events[0].type = EV_LED; + events[0].code = LED_CAPSL; + events[0].value = enabled; + + events[1].type = EV_SYN; + events[1].code = SYN_REPORT; + events[1].value = 0; + + ssize_t written = write(fd_, events, sizeof(events)); + + if (written < 0) { + if (errno != ENODEV) + PLOG(ERROR) << "cannot set leds for " << path_.value() << ":"; + Stop(); + } else if (written != sizeof(events)) { + LOG(ERROR) << "short write setting leds for " << path_.value(); + Stop(); + } +} + base::TimeDelta EventConverterEvdev::TimeDeltaFromInputEvent( const input_event& event) { return base::TimeDelta::FromMicroseconds(event.time.tv_sec * 1000000 + diff --git a/ui/events/ozone/evdev/event_converter_evdev.h b/ui/events/ozone/evdev/event_converter_evdev.h index 4e78d84cf615..3ca5f0bcd7db 100644 --- a/ui/events/ozone/evdev/event_converter_evdev.h +++ b/ui/events/ozone/evdev/event_converter_evdev.h @@ -55,6 +55,9 @@ class EVENTS_OZONE_EVDEV_EXPORT EventConverterEvdev // Returns true if the converter is used for a touchscreen device. virtual bool HasTouchscreen() const; + // Returns true if the converter is used for a device with a caps lock LED. + virtual bool HasCapsLockLed() const; + // Returns the size of the touchscreen device if the converter is used for a // touchscreen device. virtual gfx::Size GetTouchscreenSize() const; @@ -69,6 +72,9 @@ class EVENTS_OZONE_EVDEV_EXPORT EventConverterEvdev // Allows all keys to be processed. virtual void AllowAllKeys(); + // Update caps lock LED state. + virtual void SetCapsLockLed(bool enabled); + // Helper to generate a base::TimeDelta from an input_event's time static base::TimeDelta TimeDeltaFromInputEvent(const input_event& event); diff --git a/ui/events/ozone/evdev/event_converter_evdev_impl.cc b/ui/events/ozone/evdev/event_converter_evdev_impl.cc index ef1a4c5f1ae2..feaab9a39bb1 100644 --- a/ui/events/ozone/evdev/event_converter_evdev_impl.cc +++ b/ui/events/ozone/evdev/event_converter_evdev_impl.cc @@ -33,6 +33,7 @@ EventConverterEvdevImpl::EventConverterEvdevImpl( : EventConverterEvdev(fd, path, id, type), has_keyboard_(devinfo.HasKeyboard()), has_touchpad_(devinfo.HasTouchpad()), + has_caps_lock_led_(devinfo.HasLedEvent(LED_CAPSL)), x_offset_(0), y_offset_(0), cursor_(cursor), @@ -73,6 +74,10 @@ bool EventConverterEvdevImpl::HasTouchpad() const { return has_touchpad_; } +bool EventConverterEvdevImpl::HasCapsLockLed() const { + return has_caps_lock_led_; +} + void EventConverterEvdevImpl::SetAllowedKeys( scoped_ptr> allowed_keys) { DCHECK(HasKeyboard()); diff --git a/ui/events/ozone/evdev/event_converter_evdev_impl.h b/ui/events/ozone/evdev/event_converter_evdev_impl.h index b04a07df291f..76e867472a7b 100644 --- a/ui/events/ozone/evdev/event_converter_evdev_impl.h +++ b/ui/events/ozone/evdev/event_converter_evdev_impl.h @@ -41,6 +41,7 @@ class EVENTS_OZONE_EVDEV_EXPORT EventConverterEvdevImpl void OnFileCanReadWithoutBlocking(int fd) override; bool HasKeyboard() const override; bool HasTouchpad() const override; + bool HasCapsLockLed() const override; void SetAllowedKeys(scoped_ptr> allowed_keys) override; void AllowAllKeys() override; @@ -61,6 +62,9 @@ class EVENTS_OZONE_EVDEV_EXPORT EventConverterEvdevImpl bool has_keyboard_; bool has_touchpad_; + // LEDs for this device. + bool has_caps_lock_led_; + // Save x-axis events of relative devices to be flushed at EV_SYN time. int x_offset_; diff --git a/ui/events/ozone/evdev/event_modifiers_evdev.cc b/ui/events/ozone/evdev/event_modifiers_evdev.cc index 70a62508aebc..8ead0db581e4 100644 --- a/ui/events/ozone/evdev/event_modifiers_evdev.cc +++ b/ui/events/ozone/evdev/event_modifiers_evdev.cc @@ -55,8 +55,6 @@ void EventModifiersEvdev::UpdateModifierLock(unsigned int modifier, bool down) { if (down) modifier_flags_locked_ ^= kEventFlagFromModifiers[modifier]; - // TODO(spang): Synchronize with the CapsLock LED. - UpdateFlags(modifier); } @@ -68,8 +66,6 @@ void EventModifiersEvdev::SetModifierLock(unsigned int modifier, bool locked) { else modifier_flags_locked_ &= ~kEventFlagFromModifiers[modifier]; - // TODO(spang): Synchronize with the CapsLock LED. - UpdateFlags(modifier); } diff --git a/ui/events/ozone/evdev/input_controller_evdev.cc b/ui/events/ozone/evdev/input_controller_evdev.cc index 19c728b39b70..9e65740b7adb 100644 --- a/ui/events/ozone/evdev/input_controller_evdev.cc +++ b/ui/events/ozone/evdev/input_controller_evdev.cc @@ -22,6 +22,7 @@ InputControllerEvdev::InputControllerEvdev(KeyboardEvdev* keyboard, button_map_(button_map), has_mouse_(false), has_touchpad_(false), + caps_lock_led_state_(false), weak_ptr_factory_(this) { } @@ -33,6 +34,7 @@ void InputControllerEvdev::SetInputDeviceFactory( input_device_factory_ = input_device_factory; UpdateDeviceSettings(); + UpdateCapsLockLed(); } void InputControllerEvdev::set_has_mouse(bool has_mouse) { @@ -57,6 +59,7 @@ bool InputControllerEvdev::IsCapsLockEnabled() { void InputControllerEvdev::SetCapsLockEnabled(bool enabled) { keyboard_->SetCapsLockEnabled(enabled); + UpdateCapsLockLed(); } void InputControllerEvdev::SetNumLockEnabled(bool enabled) { @@ -178,4 +181,13 @@ void InputControllerEvdev::UpdateDeviceSettings() { settings_update_pending_ = false; } +void InputControllerEvdev::UpdateCapsLockLed() { + if (!input_device_factory_) + return; + bool caps_lock_state = IsCapsLockEnabled(); + if (caps_lock_state != caps_lock_led_state_) + input_device_factory_->SetCapsLockLed(caps_lock_state); + caps_lock_led_state_ = caps_lock_state; +} + } // namespace ui diff --git a/ui/events/ozone/evdev/input_controller_evdev.h b/ui/events/ozone/evdev/input_controller_evdev.h index ecd08a0940d2..8791a77a1d40 100644 --- a/ui/events/ozone/evdev/input_controller_evdev.h +++ b/ui/events/ozone/evdev/input_controller_evdev.h @@ -70,6 +70,9 @@ class EVENTS_OZONE_EVDEV_EXPORT InputControllerEvdev : public InputController { // Send settings update to input_device_factory_. void UpdateDeviceSettings(); + // Send caps lock update to input_device_factory_. + void UpdateCapsLockLed(); + // Configuration that needs to be passed on to InputDeviceFactory. InputDeviceSettingsEvdev input_device_settings_; @@ -89,6 +92,9 @@ class EVENTS_OZONE_EVDEV_EXPORT InputControllerEvdev : public InputController { bool has_mouse_; bool has_touchpad_; + // LED state. + bool caps_lock_led_state_; + base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(InputControllerEvdev); diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.cc b/ui/events/ozone/evdev/input_device_factory_evdev.cc index bb5dbe76450a..c9d0baa38aef 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev.cc +++ b/ui/events/ozone/evdev/input_device_factory_evdev.cc @@ -142,7 +142,7 @@ void OpenInputDevice(scoped_ptr params, TRACE_EVENT1("ozone", "OpenInputDevice", "path", path.value()); - int fd = open(path.value().c_str(), O_RDONLY | O_NONBLOCK); + int fd = open(path.value().c_str(), O_RDWR | O_NONBLOCK); if (fd < 0) { PLOG(ERROR) << "Cannot open '" << path.value(); reply_runner->PostTask( @@ -200,6 +200,7 @@ InputDeviceFactoryEvdev::InputDeviceFactoryEvdev( keyboard_list_dirty_(false), mouse_list_dirty_(false), touchpad_list_dirty_(false), + caps_lock_led_enabled_(false), weak_ptr_factory_(this) { } @@ -256,6 +257,7 @@ void InputDeviceFactoryEvdev::AttachInputDevice( // Sync settings to new device. ApplyInputDeviceSettings(); + ApplyCapsLockLed(); } if (--pending_device_changes_ == 0) @@ -328,6 +330,11 @@ void InputDeviceFactoryEvdev::EnableInternalKeyboard() { } } +void InputDeviceFactoryEvdev::SetCapsLockLed(bool enabled) { + caps_lock_led_enabled_ = enabled; + ApplyCapsLockLed(); +} + void InputDeviceFactoryEvdev::UpdateInputDeviceSettings( const InputDeviceSettingsEvdev& settings) { input_device_settings_ = settings; @@ -385,6 +392,13 @@ void InputDeviceFactoryEvdev::ApplyInputDeviceSettings() { input_device_settings_.tap_to_click_paused); } +void InputDeviceFactoryEvdev::ApplyCapsLockLed() { + for (const auto& it : converters_) { + EventConverterEvdev* converter = it.second; + converter->SetCapsLockLed(caps_lock_led_enabled_); + } +} + void InputDeviceFactoryEvdev::UpdateDirtyFlags( const EventConverterEvdev* converter) { if (converter->HasTouchscreen()) diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.h b/ui/events/ozone/evdev/input_device_factory_evdev.h index 58acdc2bf994..976de0dd7a5e 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev.h +++ b/ui/events/ozone/evdev/input_device_factory_evdev.h @@ -63,6 +63,9 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { // Enables all keys on the internal keyboard. void EnableInternalKeyboard(); + // LED state. + void SetCapsLockLed(bool enabled); + // Bits from InputController that have to be answered on IO. void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings); void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply); @@ -80,6 +83,7 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { // Sync input_device_settings_ to attached devices. void ApplyInputDeviceSettings(); + void ApplyCapsLockLed(); // Update observers on device changes. void UpdateDirtyFlags(const EventConverterEvdev* converter); @@ -120,6 +124,9 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { bool mouse_list_dirty_; bool touchpad_list_dirty_; + // LEDs. + bool caps_lock_led_enabled_; + // Device settings. These primarily affect libgestures behavior. InputDeviceSettingsEvdev input_device_settings_; diff --git a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc index cc23da348368..2bade2f62127 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc +++ b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc @@ -80,6 +80,12 @@ void InputDeviceFactoryEvdevProxy::EnableInternalKeyboard() { input_device_factory_)); } +void InputDeviceFactoryEvdevProxy::SetCapsLockLed(bool enabled) { + task_runner_->PostTask(FROM_HERE, + base::Bind(&InputDeviceFactoryEvdev::SetCapsLockLed, + input_device_factory_, enabled)); +} + void InputDeviceFactoryEvdevProxy::UpdateInputDeviceSettings( const InputDeviceSettingsEvdev& settings) { task_runner_->PostTask( diff --git a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h index 0268b5ddd672..3cabdc4e64b6 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h +++ b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h @@ -45,6 +45,7 @@ class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdevProxy { void DisableInternalKeyboardExceptKeys( scoped_ptr> excepted_keys); void EnableInternalKeyboard(); + void SetCapsLockLed(bool enabled); void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings); void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply); void GetTouchEventLog(const base::FilePath& out_dir, diff --git a/ui/events/ozone/evdev/keyboard_evdev.h b/ui/events/ozone/evdev/keyboard_evdev.h index 7974a9519bca..f536e3d6ef23 100644 --- a/ui/events/ozone/evdev/keyboard_evdev.h +++ b/ui/events/ozone/evdev/keyboard_evdev.h @@ -52,6 +52,7 @@ class EVENTS_OZONE_EVDEV_EXPORT KeyboardEvdev { private: void UpdateModifier(int modifier_flag, bool down); + void UpdateCapsLockLed(); void UpdateKeyRepeat(unsigned int key, bool down); void StartKeyRepeat(unsigned int key); void StopKeyRepeat(); diff --git a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc index 4f4dac520b3e..e2cadeca7f17 100644 --- a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc +++ b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc @@ -35,6 +35,7 @@ EventReaderLibevdevCros::EventReaderLibevdevCros(int fd, has_keyboard_(devinfo.HasKeyboard()), has_mouse_(devinfo.HasMouse()), has_touchpad_(devinfo.HasTouchpad()), + has_caps_lock_led_(devinfo.HasLedEvent(LED_CAPSL)), delegate_(delegate.Pass()) { memset(&evdev_, 0, sizeof(evdev_)); evdev_.log = OnLogMessage; @@ -82,6 +83,10 @@ bool EventReaderLibevdevCros::HasTouchpad() const { return has_touchpad_; } +bool EventReaderLibevdevCros::HasCapsLockLed() const { + return has_caps_lock_led_; +} + void EventReaderLibevdevCros::SetAllowedKeys( scoped_ptr> allowed_keys) { DCHECK(HasKeyboard()); diff --git a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h index 2579cb571fa8..23104b898b48 100644 --- a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h +++ b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h @@ -55,6 +55,7 @@ class EventReaderLibevdevCros : public EventConverterEvdev { bool HasKeyboard() const override; bool HasMouse() const override; bool HasTouchpad() const override; + bool HasCapsLockLed() const override; void SetAllowedKeys(scoped_ptr> allowed_keys) override; void AllowAllKeys() override; @@ -69,6 +70,9 @@ class EventReaderLibevdevCros : public EventConverterEvdev { bool has_mouse_; bool has_touchpad_; + // LEDs for this device. + bool has_caps_lock_led_; + // Libevdev state. Evdev evdev_; -- 2.11.4.GIT