usb_windows_utils.cpp
Go to the documentation of this file.
1 /*
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2019, Analog Devices, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifdef USE_GLOG
34 #include <glog/logging.h>
35 #else
36 #include <aditof/log.h>
37 #endif
38 #include <memory>
39 #include <usb_windows_utils.h>
40 
41 HRESULT
43  IBaseFilter **pVideoInputFilter) {
44  HRESULT hr = E_FAIL;
45  DWORD uiNumNodes;
46  IKsNodeControl *pUnk = nullptr;
47  GUID guidNodeType;
48 
49  handle->pKsTopologyInfo = nullptr;
50  handle->pKsUnk = nullptr;
51 
52  if (*pVideoInputFilter != nullptr) {
53  hr = (*pVideoInputFilter)
54  ->QueryInterface(__uuidof(IKsTopologyInfo),
55  (VOID **)&handle->pKsTopologyInfo);
56 
57  if (FAILED(hr)) {
58  LOG(WARNING) << "setVideoSetting - QueryInterface Error";
59  (*pVideoInputFilter)->Release();
60  *pVideoInputFilter = nullptr;
61 
62  return hr;
63  }
64  } else {
65  LOG(ERROR) << "pVideoInputFilter should not be NULL";
66  return E_POINTER;
67  }
68 
69  // get nodes number in usb video device capture filter
70  if (handle->pKsTopologyInfo->get_NumNodes(&uiNumNodes) == S_OK) {
71  // go thru all nodes searching for the node of the
72  // KSNODETYPE_DEV_SPECIFIC type, node of this type - represents
73  // extension unit of the USB device
74  for (UINT i = 0; i < uiNumNodes + 1; i++) {
75  if (handle->pKsTopologyInfo->get_NodeType(i, &guidNodeType) ==
76  S_OK) {
77  if (guidNodeType == KSNODETYPE_DEV_SPECIFIC) {
78  // create node instance
79  hr = handle->pKsTopologyInfo->CreateNodeInstance(
80  i, __uuidof(IKsNodeControl), (void **)&pUnk);
81 
82  // get IKsControl interface from node
83  if (hr == S_OK) {
84  hr = pUnk->QueryInterface(__uuidof(IKsControl),
85  (VOID **)&handle->pKsUnk);
86  }
87 
88  // trying to read first control of the extension unit
89  if (hr == S_OK) {
90  handle->node = i;
91  return hr;
92  }
93  }
94  }
95  }
96  }
97 
98  return E_FAIL;
99 }
100 
102  ULONG selector,
103  const uint8_t *buffer,
104  ULONG nbBytes) {
105  KSP_NODE s;
106  ULONG ulBytesReturned;
107 
108  s.Property.Set = EXT_UNIT_GUID;
109  s.Property.Id = selector;
110  s.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
111  s.NodeId = handle->node;
112 
113  uint8_t *nonConstBuffer = const_cast<uint8_t *>(buffer);
114  return handle->pKsUnk->KsProperty(
115  reinterpret_cast<PKSPROPERTY>(&s), sizeof(s),
116  static_cast<LPVOID>(nonConstBuffer), nbBytes, &ulBytesReturned);
117 }
118 
120  ULONG selector, uint8_t *buffer,
121  ULONG nbBytes) {
122  KSP_NODE s;
123  ULONG ulBytesReturned;
124 
125  s.Property.Set = EXT_UNIT_GUID;
126  s.Property.Id = selector;
127  s.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
128  s.NodeId = handle->node;
129 
130  return handle->pKsUnk->KsProperty(reinterpret_cast<PKSPROPERTY>(&s),
131  sizeof(s), static_cast<LPVOID>(buffer),
132  nbBytes, &ulBytesReturned);
133 }
134 
135 HRESULT UsbWindowsUtils::UvcExUnitReadBuffer(IBaseFilter *pVideoInputFilter,
136  ULONG selector, int16_t id,
137  uint32_t address, uint8_t *data,
138  uint32_t bufferLength) {
139  if (id < -1 || id > 255) {
140  LOG(ERROR)
141  << id
142  << " is greater than the maximum size (255) accepted for an id";
143  return E_INVALIDARG;
144  }
145 
146  ExUnitHandle handle;
147  HRESULT hr =
148  UsbWindowsUtils::UvcFindNodeAndGetControl(&handle, &pVideoInputFilter);
149  if (hr != S_OK) {
150  LOG(WARNING) << "Failed to find node and get control";
151  return hr;
152  }
153 
154  uint8_t nbWrPacketBytes = sizeof(address) + (id > -1 ? 1 : 0);
155  uint8_t posAddrInPacket = id > -1 ? 1 : 0;
156  uint8_t packet[MAX_BUF_SIZE];
157  size_t readBytes = 0;
158  size_t readlength = 0;
159  size_t addr = address;
160 
161  while (readBytes < bufferLength) {
162  if (id > -1) {
163  packet[0] = static_cast<uint8_t>(id);
164  }
165  *(reinterpret_cast<uint32_t *>(&packet[posAddrInPacket])) =
166  static_cast<uint32_t>(addr);
167  readlength = bufferLength - readBytes < MAX_BUF_SIZE
168  ? bufferLength - readBytes
169  : MAX_BUF_SIZE;
170  packet[nbWrPacketBytes] = static_cast<uint8_t>(readlength);
171 
172  hr = UvcExUnitSetProperty(&handle, selector, packet, MAX_BUF_SIZE);
173  if (FAILED(hr)) {
174  LOG(WARNING) << "Failed to set property via UVC extension unit";
175  return hr;
176  }
177 
178  hr = UvcExUnitGetProperty(&handle, selector, packet, MAX_BUF_SIZE);
179  if (FAILED(hr)) {
180  LOG(WARNING) << "Failed to read a property via UVC extension unit";
181  return hr;
182  }
183  memcpy(&data[readBytes], packet, readlength);
184  readBytes += readlength;
185  addr += readlength;
186  }
187 
188  return S_OK;
189 }
190 
191 HRESULT UsbWindowsUtils::UvcExUnitWriteBuffer(IBaseFilter *pVideoInputFilter,
192  ULONG selector, int16_t id,
193  uint32_t address,
194  const uint8_t *data,
195  uint32_t bufferLength) {
196  if (id < -1 || id > 255) {
197  LOG(ERROR)
198  << id
199  << " is greater than the maximum size (255) accepted for an id";
200  return E_INVALIDARG;
201  }
202 
203  ExUnitHandle handle;
204  HRESULT hr =
205  UsbWindowsUtils::UvcFindNodeAndGetControl(&handle, &pVideoInputFilter);
206  if (hr != S_OK) {
207  LOG(WARNING) << "Failed to find node and get control";
208  return hr;
209  }
210 
211  uint8_t nbLeadingBytes = sizeof(address) + (id > -1 ? 1 : 0);
212  uint8_t posAddrInPacket = id > -1 ? 1 : 0;
213  uint8_t packet[MAX_BUF_SIZE];
214  size_t writeLen = 0;
215  size_t writtenBytes = 0;
216 
217  if (id > -1) {
218  packet[0] = static_cast<uint8_t>(id);
219  }
220 
221  while (writtenBytes < bufferLength) {
222  *(reinterpret_cast<uint32_t *>(&packet[posAddrInPacket])) = address;
223  writeLen =
224  bufferLength - writtenBytes > MAX_BUF_SIZE - (nbLeadingBytes + 1)
225  ? MAX_BUF_SIZE - (nbLeadingBytes + 1)
226  : bufferLength - writtenBytes;
227  packet[nbLeadingBytes] = static_cast<uint8_t>(writeLen);
228  memcpy(&packet[nbLeadingBytes + 1], data + writtenBytes, writeLen);
229 
230  hr = UvcExUnitSetProperty(&handle, selector, packet, MAX_BUF_SIZE);
231  if (FAILED(hr)) {
232  LOG(WARNING) << "Failed to write a packet via UVC extension unit";
233  return hr;
234  }
235  writtenBytes += writeLen;
236  address += static_cast<uint32_t>(writeLen);
237  }
238 
239  return S_OK;
240 }
241 
243 UsbWindowsUtils::uvcExUnitGetString(IBaseFilter *pVideoInputFilter,
244  int uvcControlId, std::string &outStr) {
245  using namespace aditof;
246 
247  HRESULT hr;
248  uint16_t bufferLength;
249 
251  pVideoInputFilter, uvcControlId, -1, 0,
252  reinterpret_cast<uint8_t *>(&bufferLength), sizeof(bufferLength));
253  if (FAILED(hr)) {
254  pVideoInputFilter->Release();
255  LOG(WARNING)
256  << "Failed to read size of buffer holding sensors info. Error: "
257  << hr;
258  return Status::GENERIC_ERROR;
259  }
260 
261  std::unique_ptr<uint8_t[]> data(new uint8_t[bufferLength + 1]);
262  hr = UsbWindowsUtils::UvcExUnitReadBuffer(pVideoInputFilter, uvcControlId,
263  -1, sizeof(bufferLength),
264  data.get(), bufferLength);
265  if (FAILED(hr)) {
266  pVideoInputFilter->Release();
267  LOG(WARNING) << "Failed to read the content of buffer holding sensors "
268  "info. Error: "
269  << hr;
270  return Status::GENERIC_ERROR;
271  }
272 
273  pVideoInputFilter->Release();
274 
275  data[bufferLength] = '\0';
276  outStr = reinterpret_cast<char *>(data.get());
277 
278  return Status::OK;
279 }
280 
282 UsbWindowsUtils::uvcExUnitSendRequest(IBaseFilter *pVideoInputFilter,
283  const std::string &requestStr) {
284  using namespace aditof;
285 
286  const ULONG uvcSendRequestControl = 1;
287 
288  ExUnitHandle handle;
289  HRESULT hr =
290  UsbWindowsUtils::UvcFindNodeAndGetControl(&handle, &pVideoInputFilter);
291  if (hr != S_OK) {
292  LOG(WARNING) << "Failed to find node and get control. Error: " << hr;
293  return Status::GENERIC_ERROR;
294  }
295 
296  // Send the size of the string we're about to send so that UVC gadget knows how many bytes to expect
297  size_t stringLength = requestStr.size();
298  hr = UvcExUnitSetProperty(&handle, uvcSendRequestControl,
299  reinterpret_cast<uint8_t *>(&stringLength),
300  MAX_BUF_SIZE);
301  if (FAILED(hr)) {
302  LOG(WARNING)
303  << "Failed to write the length of the request string. Error: "
304  << hr;
305  return Status::GENERIC_ERROR;
306  }
307 
308  // Send the entire string to the UVC-gadget
309  uint8_t packet[MAX_BUF_SIZE];
310  size_t writeLen = 0;
311  size_t writtenBytes = 0;
312  const char *data = requestStr.data();
313 
314  while (writtenBytes < stringLength) {
315  writeLen = stringLength - writtenBytes > MAX_BUF_SIZE
316  ? MAX_BUF_SIZE
317  : stringLength - writtenBytes;
318  memcpy(&packet, data + writtenBytes, writeLen);
319 
320  hr = UvcExUnitSetProperty(&handle, uvcSendRequestControl, packet,
321  MAX_BUF_SIZE);
322  if (FAILED(hr)) {
323  LOG(WARNING) << "Failed to write a packet of the send request "
324  "string. Error: "
325  << hr;
326  return Status::GENERIC_ERROR;
327  }
328  writtenBytes += writeLen;
329  }
330 
331  return Status::OK;
332 }
333 
335 UsbWindowsUtils::uvcExUnitGetResponse(IBaseFilter *pVideoInputFilter,
336  std::string &responseStr) {
337  using namespace aditof;
338 
339  const ULONG uvcGetRequestControl = 2;
340 
341  ExUnitHandle handle;
342  HRESULT hr =
343  UsbWindowsUtils::UvcFindNodeAndGetControl(&handle, &pVideoInputFilter);
344  if (hr != S_OK) {
345  LOG(WARNING) << "Failed to find node and get control. Error: " << hr;
346  return Status::GENERIC_ERROR;
347  }
348 
349  uint8_t packet[MAX_BUF_SIZE];
350 
351  // Read the length of the string we're about to read next from the UVC gadget
352  hr = UvcExUnitGetProperty(&handle, uvcGetRequestControl, packet,
353  MAX_BUF_SIZE);
354  if (FAILED(hr)) {
355  LOG(WARNING)
356  << "Failed to read the length of the response string. Error: "
357  << hr;
358  return Status::GENERIC_ERROR;
359  }
360  size_t stringLength = reinterpret_cast<size_t *>(packet)[0];
361 
362  responseStr.reserve(stringLength);
363 
364  size_t readBytes = 0;
365  size_t readlength = 0;
366 
367  while (readBytes < stringLength) {
368  readlength = stringLength - readBytes > MAX_BUF_SIZE
369  ? MAX_BUF_SIZE
370  : stringLength - readBytes;
371 
372  hr = UvcExUnitGetProperty(&handle, uvcGetRequestControl, packet,
373  MAX_BUF_SIZE);
374  if (FAILED(hr)) {
375  LOG(WARNING)
376  << "Failed to read a packet of the response string. Error: "
377  << hr;
378  return Status::GENERIC_ERROR;
379  }
380  responseStr.append(reinterpret_cast<const char *>(packet), readlength);
381  readBytes += readlength;
382  }
383 
384  return Status::OK;
385 }
UsbWindowsUtils::UvcExUnitWriteBuffer
static HRESULT UvcExUnitWriteBuffer(IBaseFilter *pVideoInputFilter, ULONG selector, int16_t id, uint32_t address, const uint8_t *data, uint32_t bufferLength)
Definition: usb_windows_utils.cpp:191
UsbWindowsUtils::uvcExUnitGetString
static aditof::Status uvcExUnitGetString(IBaseFilter *pVideoInputFilter, int uvcControlId, std::string &outStr)
Definition: usb_windows_utils.cpp:243
ExUnitHandle::pKsTopologyInfo
IKsTopologyInfo * pKsTopologyInfo
Definition: usb_windows_utils.h:173
ExUnitHandle::node
ULONG node
Definition: usb_windows_utils.h:175
EXT_UNIT_GUID
static const GUID EXT_UNIT_GUID
Definition: usb_windows_utils.h:69
ERROR
const int ERROR
Definition: log_severity.h:60
s
XmlRpcServer s
usb_windows_utils.h
log.h
UsbWindowsUtils::uvcExUnitSendRequest
static aditof::Status uvcExUnitSendRequest(IBaseFilter *pVideoInputFilter, const std::string &requestStr)
Definition: usb_windows_utils.cpp:282
ExUnitHandle::pKsUnk
IKsControl * pKsUnk
Definition: usb_windows_utils.h:174
MAX_BUF_SIZE
#define MAX_BUF_SIZE
Definition: usb_linux_utils.h:42
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
WARNING
const int WARNING
Definition: log_severity.h:59
address
const char * address
Definition: builds/zos/test_fork.cpp:6
UsbWindowsUtils::UvcExUnitReadBuffer
static HRESULT UvcExUnitReadBuffer(IBaseFilter *pVideoInputFilter, ULONG selector, int16_t id, uint32_t address, uint8_t *data, uint32_t bufferLength)
Definition: usb_windows_utils.cpp:135
responseStr
ROSCPP_DECL XmlRpc::XmlRpcValue responseStr(int code, const std::string &msg, const std::string &response)
aditof
Namespace aditof.
Definition: adsd_errs.h:40
buffer
GLuint buffer
Definition: glcorearb.h:2939
id
GLenum GLuint id
Definition: glcorearb.h:2695
google::protobuf::util::error::OK
@ OK
Definition: status.h:47
UsbWindowsUtils::UvcExUnitGetProperty
static HRESULT UvcExUnitGetProperty(ExUnitHandle *handle, ULONG selector, uint8_t *buffer, ULONG nbBytes)
Definition: usb_windows_utils.cpp:119
buffer
Definition: buffer_processor.h:43
UsbWindowsUtils::uvcExUnitGetResponse
static aditof::Status uvcExUnitGetResponse(IBaseFilter *pVideoInputFilter, std::string &responseStr)
Definition: usb_windows_utils.cpp:335
aditof::Status
Status
Status of any operation that the TOF sdk performs.
Definition: status_definitions.h:48
i
int i
Definition: gmock-matchers_test.cc:764
LOG
#define LOG(x)
Definition: sdk/include/aditof/log.h:72
ExUnitHandle
Definition: usb_windows_utils.h:172
UsbWindowsUtils::UvcFindNodeAndGetControl
static HRESULT UvcFindNodeAndGetControl(ExUnitHandle *handle, IBaseFilter **pVideoInputFilter)
Definition: usb_windows_utils.cpp:42
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: glcorearb.h:2879
UsbWindowsUtils::UvcExUnitSetProperty
static HRESULT UvcExUnitSetProperty(ExUnitHandle *handle, ULONG selector, const uint8_t *buffer, ULONG nbBytes)
Definition: usb_windows_utils.cpp:101


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:01