packages feed

evdev 2.1.0 → 2.2.0

raw patch · 8 files changed

+86/−15 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Evdev: AbsInfo :: Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> AbsInfo
+ Evdev: LedOff :: LEDValue
+ Evdev: LedOn :: LEDValue
+ Evdev: [absFlat] :: AbsInfo -> Int32
+ Evdev: [absFuzz] :: AbsInfo -> Int32
+ Evdev: [absMaximum] :: AbsInfo -> Int32
+ Evdev: [absMinimum] :: AbsInfo -> Int32
+ Evdev: [absResolution] :: AbsInfo -> Int32
+ Evdev: [absValue] :: AbsInfo -> Int32
+ Evdev: data AbsInfo
+ Evdev: data LEDValue
+ Evdev: deviceAbsAxis :: Device -> AbsoluteAxis -> IO (Maybe AbsInfo)
+ Evdev: setDeviceLED :: Device -> LEDEvent -> LEDValue -> IO ()
+ Evdev.Codes: RelHWheelHiRes :: RelativeAxis
+ Evdev.Codes: RelReserved :: RelativeAxis
+ Evdev.Codes: RelWheelHiRes :: RelativeAxis
+ Evdev.Uinput: AbsoluteEvent :: AbsoluteAxis -> EventValue -> EventData
+ Evdev.Uinput: Event :: EventData -> DiffTime -> Event
+ Evdev.Uinput: EventCode :: Word16 -> EventCode
+ Evdev.Uinput: EventValue :: Int32 -> EventValue
+ Evdev.Uinput: ForceFeedbackEvent :: EventCode -> EventValue -> EventData
+ Evdev.Uinput: ForceFeedbackStatusEvent :: EventCode -> EventValue -> EventData
+ Evdev.Uinput: KeyEvent :: Key -> KeyEvent -> EventData
+ Evdev.Uinput: LEDEvent :: LEDEvent -> EventValue -> EventData
+ Evdev.Uinput: MiscEvent :: MiscEvent -> EventValue -> EventData
+ Evdev.Uinput: PowerEvent :: EventCode -> EventValue -> EventData
+ Evdev.Uinput: Pressed :: KeyEvent
+ Evdev.Uinput: RelativeEvent :: RelativeAxis -> EventValue -> EventData
+ Evdev.Uinput: Released :: KeyEvent
+ Evdev.Uinput: RepeatEvent :: RepeatEvent -> EventValue -> EventData
+ Evdev.Uinput: Repeated :: KeyEvent
+ Evdev.Uinput: SoundEvent :: SoundEvent -> EventValue -> EventData
+ Evdev.Uinput: SwitchEvent :: SwitchEvent -> EventValue -> EventData
+ Evdev.Uinput: SyncEvent :: SyncEvent -> EventData
+ Evdev.Uinput: UnknownEvent :: Word16 -> EventCode -> EventValue -> EventData
+ Evdev.Uinput: [eventData] :: Event -> EventData
+ Evdev.Uinput: [eventTime] :: Event -> DiffTime
+ Evdev.Uinput: data Event
+ Evdev.Uinput: data EventData
+ Evdev.Uinput: data KeyEvent
+ Evdev.Uinput: newtype EventCode
+ Evdev.Uinput: newtype EventValue
- Evdev: devicePhys :: Device -> IO ByteString
+ Evdev: devicePhys :: Device -> IO (Maybe ByteString)
- Evdev: deviceUniq :: Device -> IO ByteString
+ Evdev: deviceUniq :: Device -> IO (Maybe ByteString)

Files

CHANGELOG.md view
@@ -1,5 +1,14 @@ # Revision history for evdev +## 2.2.0 -- 05-11-2022+* More bindings:+    * `deviceAbsAxis`+    * `REL_WHEEL_HI_RES` and `REL_HWHEEL_HI_RES`+    * `setDeviceLED`+* Open devices with write permissions by default. This is primarily in order to make `setDeviceLED` easier to use.+* Export event types from `Uinput` module. This means that that module can actually reasonably be used without also importing `Evdev` and selectively hiding things.+* Wrap results of `deviceUniq` and `devicePhys` in `Maybe`, to avoid possibly dereferencing null pointers.+ ## 2.1.0 -- 2021-02-12 * Add `Evdev.Uinput` module, for creating virtual devices. * More functions for querying device properties.
README.md view
@@ -13,7 +13,7 @@  # Permissions -Your user will need to be a member of the `input` group in order to read from devices. Try `usermod -a -G input [username]`.+Your user will need to be a member of the `input` group in order to read from devices. Try `usermod -a -G input $USER`.  To create virtual devices (i.e. to use the `Evdev.UInput` module) you will need permission to write to `/dev/uinput`. This can usually be achieved by creating a group specially for uinput permissions: ```
evdev.cabal view
@@ -1,6 +1,6 @@ cabal-version:       3.0 name:                evdev-version:             2.1.0+version:             2.2.0 author:              George Thomas maintainer:          George Thomas description:         Provides access to the Linux event device interface.@@ -25,8 +25,8 @@         extra ^>= {1.6.18, 1.7},         filepath-bytestring ^>= 1.4.2,         monad-loops ^>= 0.4.3,-        rawfilepath ^>= 0.2.4,-        time ^>= {1.9.3, 1.10, 1.11},+        rawfilepath ^>= 1.0.0,+        time ^>= {1.9.3, 1.10, 1.11, 1.12, 1.13},         unix ^>= 2.7.2,     default-language: Haskell2010     default-extensions:
src/Evdev.hs view
@@ -20,6 +20,8 @@     deviceVendor,     deviceBustype,     deviceVersion,+    deviceAbsAxis,+    LL.AbsInfo (..),     -- ** Grabbing     grabDevice,     ungrabDevice,@@ -34,6 +36,8 @@     -- * Lower-level     newDeviceFromFd,     nextEventMay,+    LL.LEDValue(..),+    setDeviceLED,     -- ** C-style types     -- | These correspond more directly to C's /input_event/ and /timeval/.     -- They are used internally, but may be useful for advanced users.@@ -66,7 +70,7 @@ import System.Posix.Process (getProcessID) import System.Posix.Files (readSymbolicLink) import System.Posix.ByteString (Fd, RawFilePath)-import System.Posix.IO.ByteString (OpenMode (ReadOnly), defaultFileFlags, openFd)+import System.Posix.IO.ByteString (OpenMode (..), defaultFileFlags, openFd)  import qualified Evdev.LowLevel as LL import Evdev.Codes@@ -197,11 +201,14 @@ toCTimeVal t = LL.CTimeVal n (round $ f * 1_000_000)     where (n,f) = properFraction t --- | Create a device from a valid path - usually /\/dev\/input\/eventX/ for some /X/.+{- | Create a device from a valid path - usually /\/dev\/input\/eventX/ for some numeric /X/.+Use 'newDeviceFromFd' if you need more control over how the device is created.+-} newDevice :: RawFilePath -> IO Device-newDevice path = newDeviceFromFd =<< openFd path ReadOnly Nothing defaultFileFlags+newDevice path = newDeviceFromFd =<< openFd path ReadWrite Nothing defaultFileFlags -{- | Generalisation of 'newDevice'.+{- | Generalisation of 'newDevice', in case one needs control over the file descriptor,+e.g. in order to set a particular 'System.Posix.FileMode', 'System.Posix.OpenMode', or 'System.Posix.OpenFileFlags'. Note that:  > newDevice path = newDeviceFromFd =<< openFd path ReadOnly Nothing defaultFileFlags@@ -224,9 +231,9 @@  deviceFd :: Device -> IO Fd deviceFd = LL.deviceFd . cDevice-devicePhys :: Device -> IO ByteString+devicePhys :: Device -> IO (Maybe ByteString) devicePhys = join . LL.devicePhys . cDevice-deviceUniq :: Device -> IO ByteString+deviceUniq :: Device -> IO (Maybe ByteString) deviceUniq = join . LL.deviceUniq . cDevice deviceProduct :: Device -> IO Int deviceProduct = LL.deviceProduct . cDevice@@ -248,6 +255,12 @@ deviceHasEvent dev e = LL.hasEventCode (cDevice dev) typ code   where (typ,code,_val) = toCEventData e +deviceAbsAxis :: Device -> AbsoluteAxis -> IO (Maybe LL.AbsInfo)+deviceAbsAxis dev = LL.getAbsInfo (cDevice dev) . fromEnum'++-- | Set the state of a LED on a device.+setDeviceLED :: Device -> LEDEvent -> LL.LEDValue -> IO ()+setDeviceLED dev led val = cErrCall "setDeviceLED" dev (LL.libevdev_kernel_set_led_value (cDevice dev) led val)  {- Util -} 
src/Evdev/Codes.chs view
@@ -582,6 +582,7 @@     deriving (Bounded, Eq, Ord, Read, Show) #}  -- | Relative changes+#if defined(REL_WHEEL_HI_RES) {#enum define RelativeAxis {     REL_X as RelX,     REL_Y as RelY,@@ -592,8 +593,26 @@     REL_HWHEEL as RelHwheel,     REL_DIAL as RelDial,     REL_WHEEL as RelWheel,-    REL_MISC as RelMisc}+    REL_MISC as RelMisc,+    REL_RESERVED as RelReserved,+    REL_WHEEL_HI_RES as RelWheelHiRes,+    REL_HWHEEL_HI_RES as RelHWheelHiRes}     deriving (Bounded, Eq, Ord, Read, Show) #}+# else+{#enum define RelativeAxis {+    REL_X as RelX,+    REL_Y as RelY,+    REL_Z as RelZ,+    REL_RX as RelRx,+    REL_RY as RelRy,+    REL_RZ as RelRz,+    REL_HWHEEL as RelHwheel,+    REL_DIAL as RelDial,+    REL_WHEEL as RelWheel,+    REL_MISC as RelMisc,+    REL_RESERVED as RelReserved}+    deriving (Bounded, Eq, Ord, Read, Show) #}+#endif  -- | Absolute changes {#enum define AbsoluteAxis {
src/Evdev/LowLevel.chs view
@@ -4,7 +4,7 @@ import Data.ByteString (ByteString,packCString,useAsCString) import Data.Coerce (coerce) import Data.Int (Int32,Int64)-import Data.Word (Word16)+import Data.Word (Word16, Word32) import Foreign (Ptr,allocaBytes,mallocBytes,mallocForeignPtrBytes,newForeignPtr_,nullPtr,peek,withForeignPtr) import Foreign.C (CInt(..),CLong(..),CUInt(..),CUShort(..),CString) import Foreign.C.Error (Errno(Errno), eOK, eAGAIN)@@ -128,6 +128,7 @@     , absFlat :: Int32     , absResolution :: Int32     }+    deriving (Show) withAbsInfo :: AbsInfo -> (Ptr () -> IO a) -> IO a withAbsInfo AbsInfo{..} f = do     p <- mallocBytes {#sizeof input_absinfo#}@@ -140,7 +141,21 @@     pf <- newForeignPtr_ p     withForeignPtr pf f +--TODO can c2hs make this simpler at all?+foreign import ccall safe "Evdev/LowLevel.chs.h libevdev_get_abs_info"+  libevdev_get_abs_info :: Ptr Device -> CUInt -> IO (Ptr ())+getAbsInfo :: Device -> Word32 -> IO (Maybe AbsInfo)+getAbsInfo dev x = withDevice dev \devPtr ->+    libevdev_get_abs_info devPtr (CUInt x) >>= handleNull (pure Nothing) \absinfoPtr -> do+        CInt absValue <- {#get input_absinfo.value#} absinfoPtr+        CInt absMinimum <- {#get input_absinfo.minimum#} absinfoPtr+        CInt absMaximum <- {#get input_absinfo.maximum#} absinfoPtr+        CInt absFuzz <- {#get input_absinfo.fuzz#} absinfoPtr+        CInt absFlat <- {#get input_absinfo.flat#} absinfoPtr+        CInt absResolution <- {#get input_absinfo.resolution#} absinfoPtr+        pure $ Just AbsInfo{..} + {- Simpler functions -}  {#fun libevdev_has_property as hasProperty { `Device', convertEnum `DeviceProperty' } -> `Bool' #}@@ -148,8 +163,8 @@ {#fun libevdev_has_event_code as hasEventCode { `Device', `Word16', `Word16' } -> `Bool' #} {#fun libevdev_get_fd as deviceFd { `Device' } -> `Fd' Fd #} {#fun libevdev_get_name as deviceName { `Device' } -> `IO ByteString' packCString #}-{#fun libevdev_get_phys as devicePhys { `Device' } -> `IO ByteString' packCString #}-{#fun libevdev_get_uniq as deviceUniq { `Device' } -> `IO ByteString' packCString #}+{#fun libevdev_get_phys as devicePhys { `Device' } -> `IO (Maybe ByteString)' packCString' #}+{#fun libevdev_get_uniq as deviceUniq { `Device' } -> `IO (Maybe ByteString)' packCString' #} {#fun libevdev_get_id_product as deviceProduct { `Device' } -> `Int' #} {#fun libevdev_get_id_vendor as deviceVendor { `Device' } -> `Int' #} {#fun libevdev_get_id_bustype as deviceBustype { `Device' } -> `Int' #}@@ -162,6 +177,12 @@ {#fun libevdev_enable_event_code as enableCode { `Device', `Word16', `Word16', `Ptr ()' } -> `Errno' Errno #} {#fun libevdev_uinput_write_event as writeEvent { `UDevice', `Word16', `Word16', `Int32' } -> `Errno' Errno #} +-- | LEDs values+{#enum define LEDValue {+    LIBEVDEV_LED_ON as LedOn,+    LIBEVDEV_LED_OFF as LedOff}+    deriving (Bounded, Eq, Ord, Read, Show) #}+{#fun libevdev_kernel_set_led_value { `Device', convertEnum `LEDEvent', `LEDValue' } -> `Errno' Errno #}  {- Util -} 
src/Evdev/Uinput.hs view
@@ -6,9 +6,16 @@     writeBatch,     defaultDeviceOpts,     DeviceOpts (..),-    LL.AbsInfo (..),     deviceSyspath,     deviceDevnode,++    -- * Re-exports from 'Evdev'+    AbsInfo (..),+    Event(..),+    EventData(..),+    KeyEvent(..),+    EventCode(..),+    EventValue(..), ) where  import Control.Monad
test/Test.hs view
@@ -42,6 +42,8 @@             Nothing -> assertFailure "Couldn't find device with correct name"             Just d -> do                 putMVar start ()+                (@?= Nothing) =<< devicePhys d+                (@?= Nothing) =<< deviceUniq d                 (@?= [EvSyn, EvKey]) =<< deviceEventTypes d                 evs' <- whileJust ((\x -> guard (x /= last evs) $> x) . eventData <$> nextEvent d) pure                 filter (/= SyncEvent SynReport) evs' @?= init evs