The Pedigree Project  0.1
UsbPnP.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 "modules/system/usb/UsbPnP.h"
21 #include "modules/system/usb/UsbDevice.h"
22 #include "pedigree/kernel/machine/Device.h"
23 #include "pedigree/kernel/utilities/Iterator.h"
24 #include "pedigree/kernel/utilities/utility.h"
25 
27 
28 UsbPnP::UsbPnP() : m_Callbacks()
29 {
30 }
31 
32 UsbPnP::~UsbPnP()
33 {
34 }
35 
36 bool UsbPnP::probeDevice(Device *pDeviceBase)
37 {
38  Device *pResult = doProbe(pDeviceBase);
39  return pResult == pDeviceBase;
40 }
41 
43 {
44  // Sanity check.
45  if (!(pDeviceBase->getType() == Device::UsbContainer))
46  {
47  return pDeviceBase;
48  }
49 
50  UsbDevice *pDevice =
51  static_cast<UsbDeviceContainer *>(pDeviceBase)->getUsbDevice();
52 
53  // Is this device already handled by a driver?
54  if (pDevice->getUsbState() == UsbDevice::HasDriver)
55  {
56  return pDeviceBase;
57  }
58  else if (!m_Callbacks.count())
59  {
60  return pDeviceBase;
61  }
62 
63  UsbDevice::DeviceDescriptor *pDes = pDevice->getDescriptor();
64  UsbDevice::Interface *pIface = pDevice->getInterface();
65 
66  for (List<CallbackItem *>::Iterator it = m_Callbacks.begin();
67  it != m_Callbacks.end(); it++)
68  {
69  CallbackItem *item = *it;
70  if (!item)
71  continue;
72 
73  if ((item->nVendorId != VendorIdNone) &&
74  (item->nVendorId != pDes->nVendorId))
75  continue;
76  if ((item->nProductId != ProductIdNone) &&
77  (item->nProductId != pDes->nProductId))
78  continue;
79  if ((item->nClass != ClassNone) && (item->nClass != pIface->nClass))
80  continue;
81  if ((item->nSubclass != SubclassNone) &&
82  (item->nSubclass != pIface->nSubclass))
83  continue;
84  if ((item->nProtocol != ProtocolNone) &&
85  (item->nProtocol != pIface->nProtocol))
86  continue;
87 
88  // Call the callback, which will give us (hopefully) a copy of pDevice,
89  // in the form of a driver class
90  UsbDevice *pNewDevice = item->callback(pDevice);
91 
92  // Was this device rejected by the driver?
93  if (!pNewDevice)
94  continue;
95 
96  // Initialise the driver
97  pNewDevice->initialiseDriver();
98 
99  // Did the device go into the driver state?
100  if (pNewDevice->getUsbState() == UsbDevice::HasDriver)
101  {
102  // Replace the old device with the new one
103  UsbDeviceContainer *pNewContainer =
104  new UsbDeviceContainer(pNewDevice);
105  return pNewContainer;
106  }
107  else
108  {
109  delete pNewDevice;
110  }
111  }
112  return pDeviceBase;
113 }
114 
116 {
117  auto performReprobe = [](Device *p) {
118  if (p->getType() == Device::UsbContainer)
119  {
120  return UsbPnP::instance().doProbe(p);
121  }
122 
123  // don't edit the tree - just iterating
124  return p;
125  };
126 
127  auto c = pedigree_std::make_callable(performReprobe);
128  Device::foreach (c, pParent);
129 }
130 
132  uint16_t nVendorId, uint16_t nProductId, callback_t callback)
133 {
134  CallbackItem *item = new CallbackItem;
135  item->callback = callback;
136  item->nVendorId = nVendorId;
137  item->nProductId = nProductId;
138  item->nClass = ClassNone;
139  item->nSubclass = SubclassNone;
140  item->nProtocol = ProtocolNone;
141 
142  m_Callbacks.pushBack(item);
143 
144  reprobeDevices(nullptr);
145 }
146 
148  uint8_t nClass, uint8_t nSubclass, uint8_t nProtocol, callback_t callback)
149 {
150  CallbackItem *item = new CallbackItem;
151  item->callback = callback;
152  item->nVendorId = VendorIdNone;
153  item->nProductId = ProductIdNone;
154  item->nClass = nClass;
155  item->nSubclass = nSubclass;
156  item->nProtocol = nProtocol;
157 
158  m_Callbacks.pushBack(item);
159 
160  reprobeDevices(nullptr);
161 }
void reprobeDevices(Device *pParent)
Goes down the device tree, reprobing every USB device.
Definition: UsbPnP.cc:115
callback_t callback
The callback function.
Definition: UsbPnP.h:84
uint16_t nVendorId
Vendor and product IDs.
Definition: UsbPnP.h:87
Interface * getInterface()
Returns the interface in use.
Definition: UsbDevice.h:230
Definition: Device.h:43
virtual void initialiseDriver()
Implemented by the driver class, initialises driver-specific stuff.
Definition: UsbDevice.h:184
Device * doProbe(Device *pDeviceBase)
Definition: UsbPnP.cc:42
bool probeDevice(Device *pDeviceBase)
Tries to find a suitable driver for the given USB device.
Definition: UsbPnP.cc:36
Definition: UsbPnP.h:40
uint8_t nClass
Class, subclass and protocol numbers.
Definition: UsbPnP.h:91
::Iterator< T, node_t > Iterator
Definition: List.h:71
static void foreach(Callback callback, Device *root=0)
Definition: Device.cc:94
DeviceDescriptor * getDescriptor()
Returns the device descriptor of the device.
Definition: UsbDevice.h:218
static UsbPnP & instance()
Singleton design.
Definition: UsbPnP.h:51
virtual Type getType()
Definition: Device.h:163
static UsbPnP m_Instance
Static instance.
Definition: UsbPnP.h:74
UsbState getUsbState()
Returns the current state of the device.
Definition: UsbDevice.h:212
void registerCallback(uint16_t nVendorId, uint16_t nProductId, callback_t callback)
Register a callback for the given vendor and product IDs.
Definition: UsbPnP.cc:131