linux-evdev-0.3: System/Linux/Input/Event.hsc
{-# LANGUAGE ForeignFunctionInterface #-}
module System.Linux.Input.Event ( -- * Events
Event(..)
, hReadEvent
, KeyEventType(..)
, module System.Linux.Input.Event.Constants
) where
import Data.Word
import Data.Int
import Data.ByteString as BS
import Data.ByteString.Internal
import Data.Time.Clock
import Foreign.Storable
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.Types
import System.IO
import System.Linux.Input.Event.Constants
#include <linux/input.h>
-- | An Event
data Event = SyncEvent { evTimestamp :: DiffTime
, evSyncCode :: SyncType }
| KeyEvent { evTimestamp :: DiffTime
, evKeyCode :: Key
, evKeyEventType :: KeyEventType }
| RelEvent { evTimestamp :: DiffTime
, evRelAxis :: RelAxis
, evValue :: Int32 }
| AbsEvent { evTimestamp :: DiffTime
, evAbsAxis :: AbsAxis
, evValue :: Int32 }
| MscEvent { evTimestamp :: DiffTime }
| SwEvent { evTimestamp :: DiffTime }
| LedEvent { evTimestamp :: DiffTime }
| SndEvent { evTimestamp :: DiffTime }
| RepEvent { evTimestamp :: DiffTime }
| FfEvent { evTimestamp :: DiffTime }
| FfStatusEvent { evTimestamp :: DiffTime }
deriving (Show, Eq)
data KeyEventType = Released | Depressed | Repeated
deriving (Show, Eq, Ord, Enum, Bounded)
instance Storable Event where
sizeOf _ = (#size struct input_event)
alignment = sizeOf
peek ptr = do let time = (#ptr struct input_event, time) ptr
sec <- (#peek struct timeval, tv_sec) time
usec <- (#peek struct timeval, tv_usec) time
_type <- (#peek struct input_event, type) ptr :: IO Word16
code <- (#peek struct input_event, code) ptr :: IO Word16
value <- (#peek struct input_event, value) ptr :: IO Int32
let t = 1000000000000*fromIntegral (sec::Int) + 1000000*fromIntegral (usec::Int)
return $ case _type of
(#const EV_SYN) -> SyncEvent { evTimestamp = picosecondsToDiffTime t
, evSyncCode = SyncType code
}
(#const EV_KEY) -> KeyEvent { evTimestamp = picosecondsToDiffTime t
, evKeyCode = Key code
, evKeyEventType = toEnum (fromIntegral value)
}
(#const EV_REL) -> RelEvent { evTimestamp = picosecondsToDiffTime t
, evRelAxis = RelAxis code
, evValue = value
}
(#const EV_ABS) -> AbsEvent { evTimestamp = picosecondsToDiffTime t
, evAbsAxis = AbsAxis code
, evValue = value
}
(#const EV_MSC) -> MscEvent { evTimestamp = picosecondsToDiffTime t }
(#const EV_SW ) -> SwEvent { evTimestamp = picosecondsToDiffTime t }
(#const EV_LED) -> LedEvent { evTimestamp = picosecondsToDiffTime t }
(#const EV_SND) -> SndEvent { evTimestamp = picosecondsToDiffTime t }
(#const EV_REP) -> RepEvent { evTimestamp = picosecondsToDiffTime t }
(#const EV_FF) -> FfEvent { evTimestamp = picosecondsToDiffTime t }
(#const EV_FF_STATUS) -> FfStatusEvent { evTimestamp = picosecondsToDiffTime t }
otherwise -> error $ "unknown event type: " ++ show _type
poke = error "Storable(System.Linux.Input.Event): poke not supported"
-- | Read an event
hReadEvent :: Handle -> IO (Maybe Event)
hReadEvent h = do
a <- hGet h $ sizeOf (undefined::Event)
case a of
_ | BS.null a -> return Nothing
_ | otherwise -> getEvent a >>= return . Just
getEvent :: ByteString -> IO Event
getEvent bs = do
let (fptr, off, len) = toForeignPtr bs
withForeignPtr fptr $ peek . castPtr