Skip to content

Wait for uinput device creation #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions evdev/evdev.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ common common
rawfilepath ^>= {1.0, 1.1},
time ^>= {1.9.3, 1.10, 1.11, 1.12, 1.13, 1.14},
unix ^>= 2.8,
udev,
default-language: GHC2021
default-extensions:
BlockArguments
Expand Down
31 changes: 30 additions & 1 deletion evdev/src/Evdev/Uinput.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ import Evdev.Codes
import qualified Evdev.LowLevel as LL
import Util

import Control.Concurrent (newEmptyMVar, putMVar, readMVar, threadDelay)
import Control.Monad.Loops (untilM_)
import Data.Maybe (fromMaybe)
import GHC.Event qualified as Event
import System.UDev qualified as UDev

-- | A `uinput` device.
newtype Device = Device LL.UDevice

Expand Down Expand Up @@ -84,7 +90,30 @@ newDevice name DeviceOpts{..} = do
LL.withAbsInfo absInfo $ \ptr ->
enable ptr EvAbs [fromEnum' axis]

fmap Device $ cec $ LL.createFromDevice dev $ fromEnum' LL.UOMManaged
-- wait for device creation
mv <- newEmptyMVar
udev <- UDev.newUDev
monitor <- UDev.newFromNetlink udev UDev.UDevId
UDev.enableReceiving monitor
UDev.filterAddMatchSubsystemDevtype monitor "input" Nothing
UDev.enableReceiving monitor
fd <- UDev.getFd monitor
eventManager <- fromMaybe (error "not using GHC's threaded RTS") <$> Event.getSystemEventManager
fdKey <-
Event.registerFd
eventManager
(\_ _ -> traverse_ (putMVar mv) . UDev.getDevnode =<< UDev.receiveDevice monitor)
fd
Event.evtRead
Event.MultiShot
uinputDev <- fmap Device $ cec $ LL.createFromDevice dev $ fromEnum' LL.UOMManaged
deviceDevnode uinputDev >>= \case
Nothing -> pure () -- shouldn't generally happen - just return and hope for the best
Just devnode -> untilM_ (pure ()) $ (== devnode) <$> readMVar mv
Event.unregisterFd eventManager fdKey
UDev.freeUDev udev
threadDelay 100000
pure uinputDev
where
cec :: CErrCall a => IO a -> IO (CErrCallRes a)
cec = cErrCall "newDevice" ()
Expand Down
Loading