The Pedigree Project  0.1
UsbHumanInterfaceDevice.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "UsbHumanInterfaceDevice.h"
21 #include "modules/drivers/common/hid/HidReport.h"
22 #include "modules/system/usb/UsbConstants.h"
23 #include "modules/system/usb/UsbDevice.h"
24 #include "pedigree/kernel/Log.h"
25 #include "pedigree/kernel/processor/types.h"
26 #include "pedigree/kernel/utilities/PointerGuard.h"
27 #include "pedigree/kernel/utilities/Vector.h"
28 #include "pedigree/kernel/utilities/utility.h"
29 
30 UsbHumanInterfaceDevice::UsbHumanInterfaceDevice(UsbDevice *pDev)
31  : UsbDevice(pDev), m_pInEndpoint(0)
32 {
33 }
34 
35 UsbHumanInterfaceDevice::~UsbHumanInterfaceDevice()
36 {
37 }
38 
40 {
41  // Get the HID descriptor
42  HidDescriptor *pHidDescriptor = 0;
43  for (size_t i = 0; i < m_pInterface->otherDescriptorList.count(); i++)
44  {
45  UnknownDescriptor *pDescriptor = m_pInterface->otherDescriptorList[i];
46  if (pDescriptor->nType == 0x21)
47  {
48  pHidDescriptor = new HidDescriptor(pDescriptor);
49  break;
50  }
51  }
52  if (!pHidDescriptor)
53  {
54  ERROR("USB: HID: No HID descriptor");
55  return;
56  }
57  PointerGuard<HidDescriptor> guard(pHidDescriptor);
58 
59  // Set Idle Rate to 0
61  UsbRequestType::Class | UsbRequestRecipient::Interface,
62  UsbRequest::GetInterface, 0, 0);
63 
64  // Get the report descriptor
65  uint16_t nReportDescriptorSize = pHidDescriptor->nDescriptorLength;
66  uint8_t *pReportDescriptor = static_cast<uint8_t *>(getDescriptor(
67  0x22, 0, nReportDescriptorSize, UsbRequestRecipient::Interface));
68  PointerGuard<uint8_t> guard2(pReportDescriptor);
69 
70  // Create a new report instance and use it to parse the report descriptor
71  m_pReport = new HidReport();
72  m_pReport->parseDescriptor(pReportDescriptor, nReportDescriptorSize);
73 
74  // Search for an interrupt IN endpoint
75  for (size_t i = 0; i < m_pInterface->endpointList.count(); i++)
76  {
77  Endpoint *pEndpoint = m_pInterface->endpointList[i];
78  if (pEndpoint->nTransferType == Endpoint::Interrupt && pEndpoint->bIn)
79  {
80  m_pInEndpoint = pEndpoint;
81  break;
82  }
83  }
84 
85  // Did we end up with no interrupt IN endpoint?
86  if (!m_pInEndpoint)
87  {
88  ERROR("USB: HID: No Interrupt IN endpoint");
89  delete m_pReport;
90  return;
91  }
92 
93  // Allocate the input report buffers and zero them
94  m_pInReportBuffer = new uint8_t[m_pInEndpoint->nMaxPacketSize];
95  m_pOldInReportBuffer = new uint8_t[m_pInEndpoint->nMaxPacketSize];
96  ByteSet(m_pInReportBuffer, 0, m_pInEndpoint->nMaxPacketSize);
97  ByteSet(m_pOldInReportBuffer, 0, m_pInEndpoint->nMaxPacketSize);
98 
99  // Add the input handler
101  m_pInEndpoint, reinterpret_cast<uintptr_t>(m_pInReportBuffer),
102  m_pInEndpoint->nMaxPacketSize, callback,
103  reinterpret_cast<uintptr_t>(this));
104 
105  m_UsbState = HasDriver;
106 }
107 
108 void UsbHumanInterfaceDevice::callback(uintptr_t pParam, ssize_t ret)
109 {
111  reinterpret_cast<UsbHumanInterfaceDevice *>(pParam);
112  pHid->inputHandler();
113 }
114 
115 void UsbHumanInterfaceDevice::inputHandler()
116 {
117  // Do we have a report instance?
118  if (!m_pReport)
119  return;
120 
121  // Feed the report instance with the input we just got
122  m_pReport->feedInput(
123  m_pInReportBuffer, m_pOldInReportBuffer, m_pInEndpoint->nMaxPacketSize);
124 }
virtual void initialiseDriver()
Implemented by the driver class, initialises driver-specific stuff.
virtual void addInterruptInHandler(UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes, void(*pCallback)(uintptr_t, ssize_t), uintptr_t pParam=0)
Adds a new handler for an interrupt IN transaction.
bool controlRequest(uint8_t nRequestType, uint8_t nRequest, uint16_t nValue, uint16_t nIndex, uint16_t nLength=0, uintptr_t pBuffer=0)
Performs an USB control request.
Definition: UsbDevice.cc:424
UsbState m_UsbState
The current state of the device.
Definition: UsbDevice.h:310
DeviceDescriptor * getDescriptor()
Returns the device descriptor of the device.
Definition: UsbDevice.h:218
#define ERROR(text)
Definition: Log.h:82
Interface * m_pInterface
Interface in use.
Definition: UsbDevice.h:319