eventThread :: TChan KernelEvent -> DeviceManager -> Sys ()
eventThread ch dm = do
   forever $ do
      -- read kernel event
      ev <- atomically (readTChan ch)


      case Text.unpack (fst (bkPath (kernelEventDevPath ev))) of
         -- TODO: handle module ADD/REMOVE (/module/* path)
         "module" -> sysWarningShow "sysfs event in /module ignored"
                        (kernelEventDevPath ev)
         
         -- event in the device tree: update the device tree and trigger rules
         "devices" -> do
            let 
               -- remove "/devices" from the path
               path = Text.drop 8 (kernelEventDevPath ev)

               signalEvent f = do
                  notFound <- atomically $ do
                     tree <- readTVar (dmDevices dm)
                     case deviceTreeLookup path tree of
                        Just node -> do
                           writeTChan (f node) ev
                           return False
                        Nothing   -> return True
                  when notFound $
                     sysWarning (textFormat ("Event received for non existing device: " % shown) path)

            case kernelEventAction ev of
               ActionAdd     -> do
                  sysLogInfoShow "Added device" path
                  deviceAdd dm path (Just ev)
               ActionRemove  -> do
                  sysLogInfoShow "Removed device" path
                  deviceRemove dm path ev
               ActionMove    -> do
                  sysLogInfoShow "Moved device" path
                  deviceMove dm path ev
               ActionChange  -> do
                  sysLogInfoShow "Changed device" path
                  signalEvent deviceNodeOnChange
               ActionOnline  -> do
                  sysLogInfoShow "Device goes online" path
                  signalEvent deviceNodeOnOnline
               ActionOffline -> do
                  sysLogInfoShow "Device goes offline" path
                  signalEvent deviceNodeOnOffline
               ActionOther _ -> do
                  sysLogInfoShow "Unknown device event" path
                  signalEvent deviceNodeOnOther

         -- warn on unrecognized event
         str -> sysWarningShow (textFormat ("sysfs event in /" % string % " ignored") str) (kernelEventDevPath ev)


-- | Lookup a device by name
eventThread :: TChan KernelEvent -> DeviceManager -> Sys ()
eventThread ch dm = do
   forever $ do
      -- read kernel event
      ev <- atomically (readTChan ch)


      case Text.unpack (fst (bkPath (kernelEventDevPath ev))) of
         -- TODO: handle module ADD/REMOVE (/module/* path)
         "module" -> sysWarningShow "sysfs event in /module ignored"
                        (kernelEventDevPath ev)
         
         -- event in the device tree: update the device tree and trigger rules
         "devices" -> do
            let 
               -- remove "/devices" from the path
               path = Text.drop 8 (kernelEventDevPath ev)

               signalEvent f = do
                  notFound <- atomically $ do
                     tree <- readTVar (dmDevices dm)
                     case deviceTreeLookup path tree of
                        Just node -> do
                           writeTChan (f node) ev
                           return False
                        Nothing   -> return True
                  when notFound $
                     sysWarning (textFormat ("Event received for non existing device: " % shown) path)

            case kernelEventAction ev of
               ActionAdd     -> do
                  sysLogInfoShow "Added device" path
                  deviceAdd dm path (Just ev)
               ActionRemove  -> do
                  sysLogInfoShow "Removed device" path
                  deviceRemove dm path ev
               ActionMove    -> do
                  sysLogInfoShow "Moved device" path
                  deviceMove dm path ev
               ActionChange  -> do
                  sysLogInfoShow "Changed device" path
                  signalEvent deviceNodeOnChange
               ActionOnline  -> do
                  sysLogInfoShow "Device goes online" path
                  signalEvent deviceNodeOnOnline
               ActionOffline -> do
                  sysLogInfoShow "Device goes offline" path
                  signalEvent deviceNodeOnOffline
               ActionOther _ -> do
                  sysLogInfoShow "Unknown device event" path
                  signalEvent deviceNodeOnOther

         -- warn on unrecognized event
         str -> sysWarningShow (textFormat ("sysfs event in /" % string % " ignored") str) (kernelEventDevPath ev)


-- | Lookup a device by name
eventThread ch dm = do
   forever $ do
      -- read kernel event
      ev <- atomically (readTChan ch)


      case Text.unpack (fst (bkPath (kernelEventDevPath ev))) of
         -- TODO: handle module ADD/REMOVE (/module/* path)
         "module" -> sysWarningShow "sysfs event in /module ignored"
                        (kernelEventDevPath ev)
         
         -- event in the device tree: update the device tree and trigger rules
         "devices" -> do
            let 
               -- remove "/devices" from the path
               path = Text.drop 8 (kernelEventDevPath ev)

               signalEvent f = do
                  notFound <- atomically $ do
                     tree <- readTVar (dmDevices dm)
                     case deviceTreeLookup path tree of
                        Just node -> do
                           writeTChan (f node) ev
                           return False
                        Nothing   -> return True
                  when notFound $
                     sysWarning (textFormat ("Event received for non existing device: " % shown) path)

            case kernelEventAction ev of
               ActionAdd     -> do
                  sysLogInfoShow "Added device" path
                  deviceAdd dm path (Just ev)
               ActionRemove  -> do
                  sysLogInfoShow "Removed device" path
                  deviceRemove dm path ev
               ActionMove    -> do
                  sysLogInfoShow "Moved device" path
                  deviceMove dm path ev
               ActionChange  -> do
                  sysLogInfoShow "Changed device" path
                  signalEvent deviceNodeOnChange
               ActionOnline  -> do
                  sysLogInfoShow "Device goes online" path
                  signalEvent deviceNodeOnOnline
               ActionOffline -> do
                  sysLogInfoShow "Device goes offline" path
                  signalEvent deviceNodeOnOffline
               ActionOther _ -> do
                  sysLogInfoShow "Unknown device event" path
                  signalEvent deviceNodeOnOther

         -- warn on unrecognized event
         str -> sysWarningShow (textFormat ("sysfs event in /" % string % " ignored") str) (kernelEventDevPath ev)


-- | Lookup a device by name