deviceMove :: DeviceManager -> DevicePath -> KernelEvent -> Sys ()
deviceMove dm path ev = do
   -- get old device path
   let oldPath' = Map.lookup (Text.pack "DEVPATH_OLD") (kernelEventDetails ev)
   oldPath <- case oldPath' of
      Nothing -> sysError "Cannot find DEVPATH_OLD entry for device move kernel event"
      Just x  -> return (Text.drop 8 x) -- remove "/devices"

   notFound <- atomically $ do
      -- move the device in the tree
      tree <- readTVar (dmDevices dm)
      case deviceTreeLookup oldPath tree of
         Just node -> do
            -- move the node in the tree
            tree' <- deviceTreeMove oldPath path tree
            writeTVar (dmDevices dm) tree'
            -- signal the event
            writeTChan (deviceNodeOnMove node) ev
            return False

         Nothing -> return True

   when notFound $ do
      sysWarning $ textFormat ("Move event received for non existing device: " % shown % ". We try to add it") path
      deviceAdd dm path (Just ev)

-------------------------------------------------------------------------------
-- Device tree & subsystem index
-------------------------------------------------------------------------------

-- | Device tree
--
-- It is expected that the device tree will not change much after the
-- initialization phase (except when a device is (dis)connected, etc.), hence it
-- is an immutable data structure. It is much easier to perform tree traversal
-- with a single global lock thereafter.
deviceMove :: DeviceManager -> DevicePath -> KernelEvent -> Sys ()
deviceMove dm path ev = do
   -- get old device path
   let oldPath' = Map.lookup (Text.pack "DEVPATH_OLD") (kernelEventDetails ev)
   oldPath <- case oldPath' of
      Nothing -> sysError "Cannot find DEVPATH_OLD entry for device move kernel event"
      Just x  -> return (Text.drop 8 x) -- remove "/devices"

   notFound <- atomically $ do
      -- move the device in the tree
      tree <- readTVar (dmDevices dm)
      case deviceTreeLookup oldPath tree of
         Just node -> do
            -- move the node in the tree
            tree' <- deviceTreeMove oldPath path tree
            writeTVar (dmDevices dm) tree'
            -- signal the event
            writeTChan (deviceNodeOnMove node) ev
            return False

         Nothing -> return True

   when notFound $ do
      sysWarning $ textFormat ("Move event received for non existing device: " % shown % ". We try to add it") path
      deviceAdd dm path (Just ev)

-------------------------------------------------------------------------------
-- Device tree & subsystem index
-------------------------------------------------------------------------------

-- | Device tree
--
-- It is expected that the device tree will not change much after the
-- initialization phase (except when a device is (dis)connected, etc.), hence it
-- is an immutable data structure. It is much easier to perform tree traversal
-- with a single global lock thereafter.
deviceMove dm path ev = do
   -- get old device path
   let oldPath' = Map.lookup (Text.pack "DEVPATH_OLD") (kernelEventDetails ev)
   oldPath <- case oldPath' of
      Nothing -> sysError "Cannot find DEVPATH_OLD entry for device move kernel event"
      Just x  -> return (Text.drop 8 x) -- remove "/devices"

   notFound <- atomically $ do
      -- move the device in the tree
      tree <- readTVar (dmDevices dm)
      case deviceTreeLookup oldPath tree of
         Just node -> do
            -- move the node in the tree
            tree' <- deviceTreeMove oldPath path tree
            writeTVar (dmDevices dm) tree'
            -- signal the event
            writeTChan (deviceNodeOnMove node) ev
            return False

         Nothing -> return True

   when notFound $ do
      sysWarning $ textFormat ("Move event received for non existing device: " % shown % ". We try to add it") path
      deviceAdd dm path (Just ev)

-------------------------------------------------------------------------------
-- Device tree & subsystem index
-------------------------------------------------------------------------------

-- | Device tree
--
-- It is expected that the device tree will not change much after the
-- initialization phase (except when a device is (dis)connected, etc.), hence it
-- is an immutable data structure. It is much easier to perform tree traversal
-- with a single global lock thereafter.