diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, Paul Bennett
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Paul Bennett nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/System/USB/HID/Descriptor.hs b/System/USB/HID/Descriptor.hs
new file mode 100644
--- /dev/null
+++ b/System/USB/HID/Descriptor.hs
@@ -0,0 +1,202 @@
+{-# LANGUAGE DeriveGeneric , AutoDeriveTypeable  #-}
+-- | Notice that 'LongItem's are not supported as none are specified on the <http://www.usb.org/developers/hidpage/ USB Human Interface device page>
+module System.USB.HID.Descriptor where 
+
+
+import Data.ByteString as B
+import Data.Word 
+import GHC.Generics
+
+data HIDDescriptor = HIDDescriptor 
+    {hIDDescriptorType :: !Word8,
+     hIDcdHID :: !Version,
+     hIDCountryCode :: !Word8,
+     hIDNumDesc :: !Word8,
+     hIDDescType :: !Word8,
+     hIDDescLength :: !Int,
+     hIDDescType' :: !(Maybe Word8),
+     hIDDescLength' :: !(Maybe Word8)
+    } deriving (Show,Eq,Generic)
+
+newtype HIDReportDesc = HIDReport [HIDReportItem]
+                 deriving (Eq,Show,Generic)
+
+data HIDPhysicalDescriptor = PD !HIDDesignator !HIDQualifier !HIDEffort
+                             deriving (Eq,Show,Generic)
+
+data HIDReportItem = HIDReportS !ShortItem 
+                   | HIDReportL !LongItem
+                     deriving (Eq)
+
+instance Show HIDReportItem where 
+    show (HIDReportS x) = show x
+    show (HIDReportL x) = show x 
+
+data ShortItem = Main !HIDMainTag
+               | Global !HIDGlobalTag
+               | Local !HIDLocalTag
+                 deriving (Eq,Generic)
+
+instance Show ShortItem where 
+    show (Main x) = show x
+    show (Global x) = show x 
+    show (Local x) = show x
+
+newtype LongItem = Long ()
+                deriving (Eq,Show,Generic)
+
+data HIDMainTag = Input !HIDMainData 
+                | Output !HIDMainData 
+                | Feature !HIDMainData
+                | Collection !HIDCollectionData
+                | EndCollection
+                  deriving (Show,Eq,Generic)
+
+--Name these more meaningfully
+data HIDMainData = HIDMainData 
+    {bit0 :: !HDMBit0,
+     bit1 :: !HDMBit1,
+     bit2 :: !HDMBit2,
+     bit3 :: !HDMBit3,
+     bit4 :: !HDMBit4,
+     bit5 :: !HDMBit5,
+     bit6 :: !HDMBit6,
+     bit8 :: !HDMBit8
+    } deriving (Show,Eq,Generic)
+
+constructHIDMainD :: [Int] -> HIDMainData
+constructHIDMainD [a,b,c,d,e,f,g,h] = HIDMainData (toEnum a) (toEnum b) (toEnum c) (toEnum d) (toEnum e) (toEnum f) (toEnum g) (toEnum h)
+
+data HDMBit0 = Data | Constant
+               deriving (Eq,Show,Enum,Generic)
+data HDMBit1 = Array | Variable
+               deriving (Eq,Show,Enum,Generic)
+data HDMBit2 = Absolute | Relative
+               deriving (Eq,Show,Enum,Generic)
+data HDMBit3 = NoWrap | Wrap
+               deriving (Eq,Show,Enum,Generic)
+data HDMBit4 = Linear | NonLinear
+               deriving (Eq,Show,Enum,Generic)
+data HDMBit5 = PreferredState | NoPreferred
+               deriving (Eq,Show,Enum,Generic)
+data HDMBit6 = NoNullPosition | NullState
+               deriving (Eq,Show,Enum,Generic)
+data HDMBit8 = BitField | BufferedBytes
+               deriving (Eq,Show,Enum,Generic)
+
+data HIDCollectionData = Physical 
+                       | Application
+                       | Logical
+                       | Report
+                       | NamedArray 
+                       | UsageSwitch
+                       | UsageModifier
+                         deriving (Eq,Show,Enum,Generic)
+
+data HIDGlobalTag = UsagePage !HIDUsagePage
+                  | LogicalMinimum !Int
+                  | LogicalMaximum !Int
+                  | PhysicalMinimum !Int
+                  | PhysicalMaximum !Int
+                  | UnitExponent !Int
+                  | Unit !Int
+                  | ReportSize !Int
+                  | ReportID !Int
+                  | ReportCount !Int
+                  | Push !Int
+                  | Pop !Int 
+                    deriving (Show,Eq,Generic)
+
+data HIDLocalTag = Usage !HIDUsage
+                 | UsageMinimum !Int
+                 | UsageMaximum !Int
+                 | DesignatorIndex !HIDDesignator
+                 | DesignatorMinimum !Int
+                 | DesignatorMaximum !Int
+                 | StringIndex !Int
+                 | StringMinimum !Int
+                 | StringMaximum !Int
+                 | Delimiter !HIDDelimeter
+                   deriving (Show,Eq,Generic)
+
+data HIDDelimeter = Open | Close
+                    deriving (Show,Eq,Enum,Generic)
+
+newtype HIDUsagePage = UP Int
+    deriving (Show,Eq,Generic)
+             
+newtype HIDUsage = U Int
+    deriving (Show,Eq,Generic)
+
+data HIDDesignator = None
+                   | Hand
+                   | Eyeball
+                   | Eyebrow
+                   | Eyelid
+                   | Ear
+                   | Nose
+                   | Mouth
+                   | UpperLip
+                   | LowerLip
+                   | Jaw
+                   | Neck
+                   | UpperArm
+                   | Elbow
+                   | Forearm
+                   | Wrist
+                   | Palm
+                   | Thumb
+                   | IndexFinger
+                   | MiddleFinger
+                   | RingFinger
+                   | LittleFinger
+                   | Head
+                   | Shoulder
+                   | Hip
+                   | Waist
+                   | Thigh
+                   | Knee
+                   | Calf
+                   | Ankle
+                   | Foot
+                   | Heel
+                   | BallOfFoot
+                   | BigToe
+                   | SecondToe
+                   | ThirdToe
+                   | FourthToe
+                   | LittleToe
+                   | Brow
+                   | Cheek
+                     deriving (Show,Eq,Enum,Generic)
+
+data HIDQualifier = QNotApplicable
+                  | RightSide
+                  | LeftSide
+                  | BothSides
+                  | Either
+                  | Center
+                    deriving (Eq,Show,Enum,Generic)
+
+data HIDBias = BNotApplicable
+             | RightHand
+             | LeftHand
+             | BothHands
+             | EitherHand
+               deriving (Eq,Show,Enum,Generic)
+
+data HIDPhysDescSet = PDS !HIDBias !HIDPreference ![HIDPhysicalDescriptor]
+                    deriving (Eq,Show,Generic)
+
+type HIDEffort = Int
+
+type HIDPreference = Int
+
+
+data Version = V {main :: !Int,
+                  minor :: !Int
+                 }
+             deriving (Eq,Generic)
+
+instance Show Version where 
+    show (V ma mi) = (show ma) ++ "." ++ (show mi)
diff --git a/System/USB/HID/Parsers.hs b/System/USB/HID/Parsers.hs
new file mode 100644
--- /dev/null
+++ b/System/USB/HID/Parsers.hs
@@ -0,0 +1,252 @@
+module System.USB.HID.Parsers (-- * Top Level Parsers
+                               -- All "Data.Attoparsec" parsers
+                               parseHIDDesc
+                              ,parsePhysDescSet
+                              ,parseHIDReportDesc
+                               -- ** Second Level Parsers
+                              ,parseInt
+                              ,convertEnum) where
+
+import Data.Bits ((.&.),rotate,rotateR,testBit)
+import Data.Attoparsec.ByteString (Parser,anyWord8,peekWord8',peekWord8,choice,(<?>),many')
+import qualified Data.Attoparsec.ByteString as AB (take)
+import System.USB.HID.Descriptor
+import Data.Word (Word8)
+import Data.ByteString (ByteString, unpack,pack)
+import qualified Data.ByteString as B (zip)
+import Control.Applicative ((<$>))
+import Control.Monad (when, unless)
+
+-- | Parse a 'HIDDescriptor'
+parseHIDDesc :: Parser HIDDescriptor
+parseHIDDesc  = do 
+  hidDesc1 <- anyWord8
+  hidcd <- parseVersion
+  hidCC <- anyWord8
+  hidND <- anyWord8
+  hidDesc2 <- anyWord8
+  hidDescL <- anyWord8
+  hidDescT' <- peekWord8
+  hidDescL' <- peekWord8
+  return (HIDDescriptor hidDesc1 
+                        hidcd 
+                        hidCC
+                        hidND
+                        hidDesc2
+                        (fromEnum hidDescL) 
+                        hidDescT' 
+                        hidDescL')
+
+-- | Parse a 'HIDReportDesc'
+parseHIDReportDesc :: Parser HIDReportDesc
+parseHIDReportDesc = HIDReport <$> many' parseReportItem 
+
+parsePhysicalDesc :: Parser HIDPhysicalDescriptor
+parsePhysicalDesc = do 
+  desig <- convertEnum <$> anyWord8 
+  bq <- anyWord8 
+  return (PD desig (convertEnum . sig3 $ bq) (convertEnum . lsig5 $ bq))
+
+-- | Parse a 'HIDPhysDescSet' 
+parsePhysDescSet :: Parser HIDPhysDescSet
+parsePhysDescSet = do 
+  pref <- anyWord8 
+  sets <- many' parsePhysicalDesc
+  return (PDS (convertEnum . sig3 $ pref) (fromEnum . lsig5 $ pref) sets)
+
+parseVersion :: Parser Version
+parseVersion = do 
+  ma <- anyWord8 
+  mi <- anyWord8
+  return (V (binDec ma) (binDec mi))
+
+
+binDec :: Word8 -> Int 
+binDec w = (t * 10) + s
+    where beS = 0xF0
+          s = fromEnum $ w .&. beS
+          t = fromEnum $ (rotate w 4) .&. beS
+
+parseReportItem :: Parser HIDReportItem
+parseReportItem = choice [HIDReportS <$> parseShortItem
+                         ,HIDReportL <$> parseLongItem 
+                         ]
+
+parseShortItem :: Parser ShortItem
+parseShortItem = choice [Main <$> parseMain
+                        ,Global <$> parseGlobal 
+                        ,Local <$> parseLocal 
+                        ]
+
+parseTop1 :: (Word8 -> Bool) -> String -> Parser a -> Parser a
+parseTop1 test err parser = do 
+  prefix <- peekWord8' 
+  unless (test prefix) $ 
+         fail err
+  parser
+
+parseLongItem :: Parser LongItem
+parseLongItem = parseTop1 isLong "Not a Long Item" (return $ Long ())
+
+parseMain :: Parser HIDMainTag
+parseMain = parseTop1 isMain "Not main Type" $ choice [parseMainInput,parseCollection,parseEndCollection]
+
+parseGlobal :: Parser HIDGlobalTag 
+parseGlobal = parseTop1 isGlobal "Not Global" $ choice [parseUsagePage, parseGlobalRest]
+
+parseLocal :: Parser HIDLocalTag
+parseLocal = parseTop1 isLocal "Not Local Tag" $ choice [parseUsage,parseDesignatorI,parseDelim,parseLocalRest]
+
+parseTop2 :: (Word8 -> Bool) -> String -> (Word8 -> Parser a) 
+          -> Parser a
+parseTop2 test err parseCons = do 
+  prefix <- anyWord8
+  unless (test . preTag $ prefix) $ 
+         fail err
+  parseCons (preDataL $ prefix)
+  
+
+parseDesignatorI :: Parser HIDLocalTag
+parseDesignatorI = parseTop2 (== 3) "Not DesignatorI" ((DesignatorIndex <$>) . parseDesIData . fromEnum)
+
+parseDelim :: Parser HIDLocalTag
+parseDelim = parseTop2 (== 9) "Not Delimiter" ((Delimiter <$>) . parseDelimData . fromEnum)
+  
+parseDelimData :: Int -> Parser HIDDelimeter
+parseDelimData n = toEnum <$> parseInt n 
+
+parseDesIData :: Int -> Parser HIDDesignator
+parseDesIData n = toEnum <$> parseInt n 
+
+parseLocalRest :: Parser HIDLocalTag
+parseLocalRest = do 
+  prefix <- anyWord8
+  let int = parseInt (fromEnum . preDataL $ prefix)
+  case preTag prefix of
+    1 -> UsageMinimum <$> int
+    2 ->  UsageMaximum <$> int
+    4 ->  DesignatorMinimum <$> int
+    5 ->  DesignatorMaximum <$> int
+    7 ->  StringIndex <$> int
+    8 ->  StringMinimum <$> int
+    9 -> StringMaximum <$> int
+    _ -> fail "Not a data Int Local"
+
+parseUsage :: Parser HIDLocalTag
+parseUsage = parseTop2 (== 0) "Not Usage Tag" ((Usage <$>) . parseUsageData . fromEnum)
+
+parseUsageData :: Int -> Parser HIDUsage
+parseUsageData n = U <$> parseInt n 
+   
+parseUsagePage :: Parser HIDGlobalTag
+parseUsagePage = parseTop2 isUsagePage "Not UsagePage" ((UsagePage <$>) . parseUsagePageData . fromEnum)
+
+parseUsagePageData :: Int -> Parser HIDUsagePage
+parseUsagePageData n = UP <$> parseInt n 
+
+-- | @parseInt n@ parses an @Int@ of length encoded in @n@ 'Word8''s
+parseInt :: Int -> Parser Int
+parseInt n = byteStringToInt <$> AB.take n
+
+parseGlobalRest :: Parser HIDGlobalTag
+parseGlobalRest = do
+  prefix <- anyWord8
+  let int = parseInt (fromEnum . preDataL $ prefix)
+  case preTag prefix of
+      1  -> LogicalMinimum  <$> int
+      2  -> LogicalMaximum  <$> int
+      3  -> PhysicalMinimum <$> int
+      4  -> PhysicalMaximum <$> int
+      5  -> UnitExponent    <$> int
+      6  -> Unit            <$> int
+      7  -> ReportSize      <$> int
+      8  -> ReportID        <$> int
+      9  -> ReportCount     <$> int
+      10 -> Push            <$> int
+      11 -> Pop             <$> int
+      _  -> fail "Not a data Int global"
+
+byteStringToInt :: ByteString -> Int
+byteStringToInt = foldl f 0 . B.zip (pack [0..])
+    where f a (b,c) = 2^(8* (fromEnum b)) * (fromEnum c) + a  
+
+parseMainInput :: Parser HIDMainTag 
+parseMainInput = do
+  prefix <- anyWord8
+  let mainData = parseMainData (preDataL prefix)
+  case preTag prefix of 
+    8 -> Input <$> mainData
+    9 -> Output <$> mainData
+    11 -> Feature <$> mainData
+    _ -> fail "Incorrect Tag"
+
+parseCollection :: Parser HIDMainTag
+parseCollection = parseTop2 isCollection "Not Collection" ((Collection <$>) . parseCollectionData)
+
+parseEndCollection :: Parser HIDMainTag
+parseEndCollection = parseTop2 isEndCollection "Not End Collection" (const (return EndCollection))
+  
+parseCollectionData :: Word8 -> Parser HIDCollectionData
+parseCollectionData w = do
+  tdata <- convertEnum <$> anyWord8
+  AB.take (fromEnum (w - 1))
+  return tdata
+
+parseMainData :: Word8 -> Parser HIDMainData
+parseMainData n = do 
+  let a = fromEnum (if n <= 2 
+                   then n
+                   else 2)
+  as <- AB.take a
+  let bs = concatMap takingBits (unpack as) ++ (repeat False)
+  return (constructHIDMainD (map fromEnum (takeBits bs)))
+
+takeBits :: [Bool] -> [Bool]
+takeBits xs = take 7 xs ++ [xs !! 9]
+
+isMain :: Word8 -> Bool
+isMain w = preType w == 0
+
+isGlobal :: Word8 -> Bool
+isGlobal w = preType w == 1
+
+isLocal :: Word8 -> Bool
+isLocal w = preType w == 2
+
+isLong :: Word8 -> Bool 
+isLong w = preTag w == 15
+
+isUsagePage :: Word8 -> Bool
+isUsagePage w = preTag w == 0
+
+isCollection :: Word8 -> Bool
+isCollection w = preTag w == 10
+
+isEndCollection :: Word8 -> Bool
+isEndCollection w = preTag w == 12
+
+preType :: Word8 -> Word8                       
+preType p = rotateR (p .&. typeM) 2
+    where typeM = 0x0C
+
+preTag  ::  Word8 -> Word8                       
+preTag p = rotateR (p .&. tagM) 4
+    where tagM = 0xF0
+
+preDataL :: Word8 -> Word8           
+preDataL p = p .&. dataLengthM
+    where dataLengthM = 0x03
+
+sig3 :: Word8 -> Word8 
+sig3 w = rotate (w .&. m) 3
+    where m = 0xE0
+
+lsig5 :: Word8 -> Word8 
+lsig5 w = w .&. m 
+    where m = 0x1F
+
+convertEnum :: (Enum a, Enum b) => a -> b
+convertEnum = toEnum . fromEnum
+
+takingBits :: Word8 -> [Bool]
+takingBits x = map (testBit x) [0..7]
diff --git a/System/USB/HID/Requests.hs b/System/USB/HID/Requests.hs
new file mode 100644
--- /dev/null
+++ b/System/USB/HID/Requests.hs
@@ -0,0 +1,138 @@
+{-# LANGUAGE DeriveGeneric , AutoDeriveTypeable  #-}
+-- consider writing parsers for physical descriptors
+-- write documentation for all.
+module System.USB.HID.Requests (-- * Request Types 
+                                HIDDescriptorClass
+                               ,HIDControlRequest
+                               ,HIDProtocol
+                               ,DescriptorIndex
+                               ,HIDInterfaceNumber
+                               ,Duration
+                               ,ReportID
+                               ,Report
+                               ,ReportType 
+                                -- * HID Requests
+                                -- | These are all specified in the HID Specification Section 7
+                               ,getHIDReportDesc
+                               ,getPhysicalDescriptor
+                               ,getReport
+                               ,setReport
+                               ,getIdle
+                               ,setIdle
+                               ,getProtocol
+                               ,setProtocol
+                               ) where
+import GHC.Generics
+import Data.Word
+import System.USB
+import Data.Attoparsec.ByteString
+import System.USB.HID.Descriptor
+import System.USB.HID.Parsers
+import Data.ByteString as B (ByteString,empty,head)
+import Data.Maybe (fromJust)
+import Data.Tuple (swap)
+
+data HIDDescriptorClass = HIDR
+                        | HIDReportR 
+                        | PhysicalDescriptorR
+                          deriving (Eq,Show,Generic)
+
+data HIDControlRequest = GetReport 
+                       | GetIdle 
+                       | GetProtocol 
+                       | SetReport 
+                       | SetIdle 
+                       | SetProtocol
+                         deriving (Eq,Show,Generic)
+
+data HIDProtocol = Boot | Report 
+                   deriving (Eq, Show,Enum,Generic)
+
+instance Enum HIDControlRequest where 
+ toEnum x = fromJust (lookup x (zip [1,2,3,9,10,11] [GetReport, GetIdle, GetProtocol, SetReport, SetIdle, SetProtocol]))
+ fromEnum x = fromJust (lookup x (zip [GetReport, GetIdle, GetProtocol, SetReport, SetIdle, SetProtocol] [1,2,3,9,10,11]))
+
+type DescriptorIndex = Word8
+
+type HIDInterfaceNumber = Word16
+
+type Duration = Word8
+
+type ReportID = Word8
+
+type Report = ByteString
+
+data ReportType = RInput | ROutput | RFeature
+                  deriving (Eq,Show,Generic)
+
+instance Enum ReportType where 
+    toEnum x = fromJust (lookup x as)
+        where as = [(1,RInput),(2,ROutput),(3,RFeature)]
+    fromEnum x = fromJust (lookup x (map swap as))
+        where as = [(1,RInput),(2,ROutput),(3,RFeature)]
+
+instance Enum HIDDescriptorClass where 
+    toEnum 0x21 = HIDR
+    toEnum 0x22 = HIDReportR 
+    toEnum 0x23 = PhysicalDescriptorR
+    fromEnum HIDR = 0x21
+    fromEnum HIDReportR = 0x22
+    fromEnum PhysicalDescriptorR = 0x23
+
+getHIDDesc :: DeviceHandle -> Parser a -> HIDControlRequest -> HIDDescriptorClass -> DescriptorIndex -> HIDInterfaceNumber -> Size -> Timeout -> IO a 
+getHIDDesc h parser cr dc di intN s t = do 
+  (bs,s) <- readControl h (ControlSetup Class ToInterface (convertEnum $ cr) ((convertEnum $ dc )*256 + (convertEnum $ di)) intN) s t
+  case parseOnly parser bs of 
+    Left x -> fail "Could not Parse descriptor"
+    Right x -> return x
+
+-- | Performs 'Class' request for the HID report descriptor using the Control pipe
+getHIDReportDesc :: DeviceHandle -> HIDInterfaceNumber -> Size -> Timeout -> IO HIDReportDesc
+getHIDReportDesc h intN = getHIDDesc h parseHIDReportDesc GetReport HIDReportR 0 intN 
+
+
+-- | Performs 'Class' request for a HID Physical Descriptor set using the Control pipe
+getPhysicalDescriptor :: DeviceHandle -> HIDInterfaceNumber -> DescriptorIndex -> Size -> Timeout -> IO HIDPhysDescSet
+getPhysicalDescriptor h intN di = getHIDDesc h parsePhysDescSet GetReport PhysicalDescriptorR di intN 
+
+-- | The GetReport request allows the host to receive a report via the Control pipe.
+
+getReport :: DeviceHandle -> ReportType -> ReportID -> HIDInterfaceNumber -> Size -> Timeout -> IO (ByteString,Status)
+getReport h rt ri intN s t = hidGet h (convertEnum $ SetReport) ((convertEnum $ rt )*256 + (convertEnum $ ri)) intN s t
+
+-- | The SetReport request allows the host to send a report to the device, possibly setting the state of input, output, or feature controls.
+
+setReport :: DeviceHandle -> ReportType -> ReportID -> HIDInterfaceNumber -> Report -> Timeout -> IO (Size,Status)
+setReport h rt ri intN r t = hidSet h (convertEnum $ SetReport) ((convertEnum $ rt )*256 + (convertEnum $ ri)) intN r t
+
+-- | The GetIdle request reads the current idle rate for a particular Input report
+
+getIdle :: DeviceHandle -> HIDInterfaceNumber -> ReportID -> Timeout -> IO (HIDProtocol,Status)
+getIdle h intN rid t = do 
+  (p,s) <- hidGet h (convertEnum $ GetIdle) (convertEnum $ rid) intN 1 t
+  let i = fromEnum (B.head p)
+  return (toEnum i ,s)
+
+-- | The SetIdle request silences a particular report on the Interrupt In pipe until a new event occurs or the specified amount of time passes.
+
+setIdle :: DeviceHandle -> HIDInterfaceNumber -> Duration -> ReportID -> Timeout -> IO (Size,Status)
+setIdle h intN d rid = hidSet h (convertEnum $ SetIdle) ((convertEnum $ d )*256 + (convertEnum $ rid)) intN empty
+
+-- | The GetProtocol request reads which protocol is currently active (either the boot protocol or the report protocol.)
+
+getProtocol :: DeviceHandle -> HIDInterfaceNumber -> Timeout -> IO (HIDProtocol,Status)
+getProtocol h intN t = do 
+  (p,s) <- hidGet h (convertEnum $ GetProtocol) 0 intN 1 t
+  let i = fromEnum (B.head p)
+  return (toEnum i ,s)
+
+-- | The SetProtocol switches between the boot protocol and the report protocol (or vice versa).
+
+setProtocol :: DeviceHandle -> HIDProtocol -> HIDInterfaceNumber -> Timeout -> IO (Size,Status)
+setProtocol h p intN = hidSet h (convertEnum $ SetProtocol) (convertEnum $ p) intN empty
+
+hidSet :: DeviceHandle -> Word8 -> Word16 -> Word16 -> ByteString ->Timeout -> IO (Size,Status)
+hidSet h r v = writeControl h . ControlSetup Class ToInterface r v
+
+hidGet :: DeviceHandle -> Word8 -> Word16 -> Word16 -> Size -> Timeout -> IO (ByteString,Status)
+hidGet h r v = readControl h . ControlSetup Class ToInterface r v
diff --git a/usb-hid.cabal b/usb-hid.cabal
new file mode 100644
--- /dev/null
+++ b/usb-hid.cabal
@@ -0,0 +1,25 @@
+-- Initial usb-hid.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                usb-hid
+version:             0.1.0.0
+synopsis:            Parser and request Library for USB HIDs
+-- description:         
+homepage:            https://github.com/mapinguari/usb-hid
+license:             BSD3
+license-file:        LICENSE
+author:              Paul Bennett
+maintainer:          paul.mic.bennett@gmail.com
+-- copyright:           
+category:            System
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     System.USB.HID.Parsers, System.USB.HID.Requests, System.USB.HID.Descriptor
+  -- other-modules:       
+  other-extensions:    DeriveGeneric, AutoDeriveTypeable
+  build-depends:       base >=4.7 && <4.8, attoparsec >=0.12 && <0.13, bytestring >=0.10 && <0.11, usb >=1.3 && <1.4
+  -- hs-source-dirs:      
+  default-language:    Haskell2010
