diff --git a/homeassistant/components/keyboard_remote/__init__.py b/homeassistant/components/keyboard_remote/__init__.py
index 24889a3f82095add58e995f95a7b73cdd846a350..310bd0189bda39ff2dd7f2cf6996e0f28d146d7d 100644
--- a/homeassistant/components/keyboard_remote/__init__.py
+++ b/homeassistant/components/keyboard_remote/__init__.py
@@ -2,6 +2,7 @@
 # pylint: disable=import-error
 import asyncio
 import logging
+import os
 
 import aionotify
 from evdev import InputDevice, categorize, ecodes, list_devices
@@ -119,9 +120,11 @@ class KeyboardRemote:
         # add initial devices (do this AFTER starting watcher in order to
         # avoid race conditions leading to missing device connections)
         initial_start_monitoring = set()
-        descriptors = list_devices(DEVINPUT)
+        descriptors = await self.hass.async_add_executor_job(list_devices, DEVINPUT)
         for descriptor in descriptors:
-            dev, handler = self.get_device_handler(descriptor)
+            dev, handler = await self.hass.async_add_executor_job(
+                self.get_device_handler, descriptor
+            )
 
             if handler is None:
                 continue
@@ -165,6 +168,15 @@ class KeyboardRemote:
             handler = self.handlers_by_descriptor[descriptor]
         elif dev.name in self.handlers_by_name:
             handler = self.handlers_by_name[dev.name]
+        else:
+            # check for symlinked paths matching descriptor
+            for test_descriptor, test_handler in self.handlers_by_descriptor.items():
+                if test_handler.dev is not None:
+                    fullpath = test_handler.dev.path
+                else:
+                    fullpath = os.path.realpath(test_descriptor)
+                if fullpath == descriptor:
+                    handler = test_handler
 
         return (dev, handler)
 
@@ -186,7 +198,9 @@ class KeyboardRemote:
                     (event.flags & aionotify.Flags.CREATE)
                     or (event.flags & aionotify.Flags.ATTRIB)
                 ) and not descriptor_active:
-                    dev, handler = self.get_device_handler(descriptor)
+                    dev, handler = await self.hass.async_add_executor_job(
+                        self.get_device_handler, descriptor
+                    )
                     if handler is None:
                         continue
                     self.active_handlers_by_descriptor[descriptor] = handler
@@ -242,7 +256,7 @@ class KeyboardRemote:
             """Stop event monitoring task and issue event."""
             if self.monitor_task is not None:
                 try:
-                    self.dev.ungrab()
+                    await self.hass.async_add_executor_job(self.dev.ungrab)
                 except OSError:
                     pass
                 # monitoring of the device form the event loop and closing of the
@@ -272,7 +286,7 @@ class KeyboardRemote:
 
             try:
                 _LOGGER.debug("Start device monitoring")
-                dev.grab()
+                await self.hass.async_add_executor_job(dev.grab)
                 async for event in dev.async_read_loop():
                     if event.type is ecodes.EV_KEY:
                         if event.value in self.key_values: