deviceRemove :: DeviceManager -> DevicePath -> KernelEvent -> Sys ()
deviceRemove dm path ev = do
   notFound <- atomically $ do
      tree <- readTVar (dmDevices dm)
      case deviceTreeLookup path tree of
         Just node  -> do
            -- remove from tree and signal
            writeTVar (dmDevices dm) (deviceTreeRemove path tree)
            writeTChan (deviceNodeOnRemove node) ev

            case deviceNodeSubsystem node of
               Nothing -> return ()
               Just s  -> do
                  -- Remove from index
                  subs <- readTVar (dmSubsystems dm)
                  let
                     index  = subs Map.! s
                     devs   = subsystemDevices index
                     index' = index { subsystemDevices = Set.delete path devs}
                  writeTVar (dmSubsystems dm) (Map.insert s index' subs)
                  -- signal for index
                  writeTChan (subsystemOnRemove index) path
            return False
         Nothing -> return True
   
   when notFound $ do
      sysWarning $ textFormat ("Remove event received for non existing device: " % shown) path

-- | Move a device
--
-- A device can be moved/renamed in the device tree (see kobject_rename
-- in lib/kobject.c in the kernel sources)
deviceRemove :: DeviceManager -> DevicePath -> KernelEvent -> Sys ()
deviceRemove dm path ev = do
   notFound <- atomically $ do
      tree <- readTVar (dmDevices dm)
      case deviceTreeLookup path tree of
         Just node  -> do
            -- remove from tree and signal
            writeTVar (dmDevices dm) (deviceTreeRemove path tree)
            writeTChan (deviceNodeOnRemove node) ev

            case deviceNodeSubsystem node of
               Nothing -> return ()
               Just s  -> do
                  -- Remove from index
                  subs <- readTVar (dmSubsystems dm)
                  let
                     index  = subs Map.! s
                     devs   = subsystemDevices index
                     index' = index { subsystemDevices = Set.delete path devs}
                  writeTVar (dmSubsystems dm) (Map.insert s index' subs)
                  -- signal for index
                  writeTChan (subsystemOnRemove index) path
            return False
         Nothing -> return True
   
   when notFound $ do
      sysWarning $ textFormat ("Remove event received for non existing device: " % shown) path

-- | Move a device
--
-- A device can be moved/renamed in the device tree (see kobject_rename
-- in lib/kobject.c in the kernel sources)
deviceRemove dm path ev = do
   notFound <- atomically $ do
      tree <- readTVar (dmDevices dm)
      case deviceTreeLookup path tree of
         Just node  -> do
            -- remove from tree and signal
            writeTVar (dmDevices dm) (deviceTreeRemove path tree)
            writeTChan (deviceNodeOnRemove node) ev

            case deviceNodeSubsystem node of
               Nothing -> return ()
               Just s  -> do
                  -- Remove from index
                  subs <- readTVar (dmSubsystems dm)
                  let
                     index  = subs Map.! s
                     devs   = subsystemDevices index
                     index' = index { subsystemDevices = Set.delete path devs}
                  writeTVar (dmSubsystems dm) (Map.insert s index' subs)
                  -- signal for index
                  writeTChan (subsystemOnRemove index) path
            return False
         Nothing -> return True
   
   when notFound $ do
      sysWarning $ textFormat ("Remove event received for non existing device: " % shown) path

-- | Move a device
--
-- A device can be moved/renamed in the device tree (see kobject_rename
-- in lib/kobject.c in the kernel sources)