module System.Linux.HIDRaw
( DevInfo(..)
, devInfo
, setFeature
, getFeature
) where
import Data.Bits ((.|.), shiftL)
import Data.Word (Word8, Word16, Word32)
import Foreign.C.Error
import Foreign.C.Types
import Foreign.Ptr (Ptr)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array
import Foreign.Storable
import System.Posix.Types (Fd)
foreign import ccall unsafe "ioctl" c_ioctl :: CInt -> CInt -> Ptr a -> IO CInt
ioctl :: Storable p => Fd -> CInt -> Ptr p -> IO ()
ioctl f r p = throwErrnoIfMinus1_ "ioctl" $ c_ioctl (fromIntegral f) r p
data DevInfo = DevInfo
{ devBustype :: Word32
, devVendor :: Word16
, devProduct :: Word16
}
instance Storable DevInfo where
sizeOf _ = (8)
alignment _ = 4
peek p = do
b <- (\hsc_ptr -> peekByteOff hsc_ptr 0) p
v <- (\hsc_ptr -> peekByteOff hsc_ptr 4) p
i <- (\hsc_ptr -> peekByteOff hsc_ptr 6) p
return $ DevInfo b v i
poke p (DevInfo b v i) = do
(\hsc_ptr -> pokeByteOff hsc_ptr 0) p b
(\hsc_ptr -> pokeByteOff hsc_ptr 4) p v
(\hsc_ptr -> pokeByteOff hsc_ptr 6) p i
devInfo :: Fd -> IO DevInfo
devInfo d = alloca $ \p -> ioctl d 2148026371 p >> peek p
ioctlLen :: Storable p => Fd -> CInt -> Int -> Ptr p -> IO ()
ioctlLen f r l p
| len > mask = ioError $ errnoToIOError "ioctlLen" eMSGSIZE Nothing Nothing
| otherwise = ioctl f (r .|. (len `shiftL` shift)) p
where
len = fromIntegral $ l * sizeOf (ptrType p)
ptrType :: Ptr p -> p
ptrType _ = undefined
shift = 16
mask = 16383
setFeature :: Fd -> [Word8] -> IO ()
setFeature d x = withArrayLen x $ ioctlLen d 3221243910
getFeature :: Fd -> Int -> IO [Word8]
getFeature d l = allocaArray l $ \p -> do
ioctlLen d 3221243911 l p
peekArray l p