messenger-winusb.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2015 Intel Corporation. All Rights Reserved.
3 
4 #if (_MSC_FULL_VER < 180031101)
5 #error At least Visual Studio 2013 Update 4 is required to compile this backend
6 #endif
7 
8 #include "messenger-winusb.h"
9 #include "device-winusb.h"
10 #include "usb/usb-enumerator.h"
11 #include "types.h"
12 
13 #include <atlstr.h>
14 #include <Windows.h>
15 #include <Sddl.h>
16 #include <string>
17 #include <regex>
18 #include <sstream>
19 #include <mutex>
20 
21 #pragma comment(lib, "winusb.lib")
22 
23 namespace librealsense
24 {
25  namespace platform
26  {
27  usb_messenger_winusb::usb_messenger_winusb(const std::shared_ptr<usb_device_winusb> device,
28  std::shared_ptr<handle_winusb> handle)
29  : _device(device), _handle(handle)
30  {
31 
32  }
33 
35  {
36  for (auto&& d : _dispatchers)
37  {
38  d.second->stop();
39  d.second.reset();
40  }
41  }
42 
43  usb_status usb_messenger_winusb::control_transfer(int request_type, int request, int value, int index, uint8_t* buffer, uint32_t length, uint32_t& transferred, uint32_t timeout_ms)
44  {
45  WINUSB_SETUP_PACKET setupPacket;
46  ULONG length_transferred;
47 
48  setupPacket.RequestType = request_type;
49  setupPacket.Request = request;
50  setupPacket.Value = value;
51  setupPacket.Index = index;
52  setupPacket.Length = length;
53 
54  auto interface_number = 0xFF & index;
55  auto h = _handle->get_interface_handle(interface_number);
56 
57  auto sts = set_timeout_policy(h, 0, timeout_ms);
58  if (sts != RS2_USB_STATUS_SUCCESS)
59  return sts;
60 
61  if (!WinUsb_ControlTransfer(h, setupPacket, buffer, length, &length_transferred, NULL))
62  {
63  auto lastResult = GetLastError();
64  LOG_WARNING("control_transfer failed, error: " << lastResult);
65  return winusb_status_to_rs(lastResult);
66  }
67  transferred = length_transferred;
69  }
70 
72  {
73  auto h = _handle->get_interface_handle(endpoint->get_interface_number());
74 
75  if (!WinUsb_ResetPipe(h, endpoint->get_address()))
76  {
77  auto lastResult = GetLastError();
78  LOG_ERROR("control_transfer failed, error: " << lastResult);
79  return winusb_status_to_rs(lastResult);
80  }
82  }
83 
85  {
86  ULONG length_transferred;
87 
88  auto h = _handle->get_interface_handle(endpoint->get_interface_number());
89 
90  auto sts = set_timeout_policy(h, endpoint->get_address(), timeout_ms);
91  if (sts != RS2_USB_STATUS_SUCCESS)
92  return sts;
93 
94  bool res;
95  if (USB_ENDPOINT_DIRECTION_IN(endpoint->get_address()))
96  res = WinUsb_ReadPipe(h, endpoint->get_address(), const_cast<unsigned char*>(buffer), length, &length_transferred, NULL);
97  else
98  res = WinUsb_WritePipe(h, endpoint->get_address(), const_cast<unsigned char*>(buffer), length, &length_transferred, NULL);
99  if (!res)
100  {
101  auto lastResult = GetLastError();
102  LOG_ERROR("bulk_transfer failed, error: " << lastResult);
103  return winusb_status_to_rs(lastResult);
104  }
105  transferred = length_transferred;
106  return RS2_USB_STATUS_SUCCESS;
107  }
108 
109  usb_status usb_messenger_winusb::set_timeout_policy(WINUSB_INTERFACE_HANDLE handle, uint8_t endpoint, uint32_t timeout_ms)
110  {
111  // WinUsb_SetPipePolicy function sets the policy for a specific pipe associated with an endpoint on the device
112  // PIPE_TRANSFER_TIMEOUT: Waits for a time-out interval before canceling the request
113  auto sts = WinUsb_SetPipePolicy(handle, endpoint, PIPE_TRANSFER_TIMEOUT, sizeof(timeout_ms), &timeout_ms);
114  if (!sts)
115  {
116  auto lastResult = GetLastError();
117  LOG_ERROR("failed to set timeout policy, error: " << lastResult);
118  return winusb_status_to_rs(lastResult);
119  }
120  return RS2_USB_STATUS_SUCCESS;
121  }
122 
124  {
125  auto rv = std::make_shared<usb_request_winusb>(_device, endpoint);
126  return rv;
127  }
128 
130  {
131  ULONG read_pipe_transfer_size = 0;
132  auto ep = request->get_endpoint();
133  auto in = ep->get_interface_number();
134  auto epa = request->get_endpoint()->get_address();
135  auto ovl = reinterpret_cast<OVERLAPPED*>(request->get_native_request());
136  auto h = _handle->get_interface_handle(in);
137 
138  auto buffer = const_cast<uint8_t*>(request->get_buffer().data());
139  int res = WinUsb_ReadPipe(h, epa, buffer, request->get_buffer().size(), &read_pipe_transfer_size, ovl);
140  if (0 != res)
141  return winusb_status_to_rs(res);
142 
143  auto lastError = GetLastError();
144  if (lastError != ERROR_IO_PENDING)
145  return winusb_status_to_rs(lastError);
146 
147  get_dispatcher(epa)->invoke([&, request, h, ovl](dispatcher::cancellable_timer c)
148  {
149  ULONG overlapped_transfer_size = 0;
150 
151  auto sts = WinUsb_GetOverlappedResult(h, ovl, &overlapped_transfer_size, TRUE);
152  if (sts)
153  {
154  auto cb = request->get_callback();
155  cb->callback(request);
156  }
157  });
158 
159  return RS2_USB_STATUS_SUCCESS;
160  }
161 
163  {
164  auto ovl = reinterpret_cast<OVERLAPPED*>(request->get_native_request());
165  auto h = _handle->get_device_handle();
166 
167  if(CancelIoEx(h, ovl))
168  return RS2_USB_STATUS_SUCCESS;
169 
170  auto sts = GetLastError();
171  return winusb_status_to_rs(sts);
172  }
173 
174  std::shared_ptr<dispatcher> usb_messenger_winusb::get_dispatcher(uint8_t endpoint)
175  {
176  std::lock_guard<std::mutex> lk(_mutex);
177  if (_dispatchers.find(endpoint) == _dispatchers.end())
178  {
179  _dispatchers[endpoint] = std::make_shared<dispatcher>(10);
180  _dispatchers[endpoint]->start();
181  }
182  return _dispatchers.at(endpoint);
183  }
184  }
185 }
virtual usb_status reset_endpoint(const rs_usb_endpoint &endpoint, uint32_t timeout_ms) override
std::shared_ptr< usb_request > rs_usb_request
Definition: usb-request.h:41
#define LOG_WARNING(...)
Definition: src/types.h:241
GLuint64 GLenum void * handle
Definition: glext.h:7785
GLfloat value
static usb_status winusb_status_to_rs(DWORD sts)
Definition: handle-winusb.h:16
d
Definition: rmse.py:171
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:1960
unsigned char uint8_t
Definition: stdint.h:78
GLenum GLfloat * buffer
enum librealsense::platform::_usb_status usb_status
GLuint index
std::shared_ptr< dispatcher > get_dispatcher(uint8_t endpoint)
virtual rs_usb_request create_request(rs_usb_endpoint endpoint) override
const GLubyte * c
Definition: glext.h:12690
unsigned int uint32_t
Definition: stdint.h:80
usb_messenger_winusb(const std::shared_ptr< usb_device_winusb > device, std::shared_ptr< handle_winusb > handle)
std::shared_ptr< usb_endpoint > rs_usb_endpoint
Definition: usb-endpoint.h:24
virtual usb_status control_transfer(int request_type, int request, int value, int index, uint8_t *buffer, uint32_t length, uint32_t &transferred, uint32_t timeout_ms) override
usb_status set_timeout_policy(WINUSB_INTERFACE_HANDLE handle, uint8_t endpoint, uint32_t timeout_ms)
#define LOG_ERROR(...)
Definition: src/types.h:242
std::shared_ptr< usb_device_winusb > _device
virtual usb_status bulk_transfer(const rs_usb_endpoint &endpoint, uint8_t *buffer, uint32_t length, uint32_t &transferred, uint32_t timeout_ms) override
virtual usb_status cancel_request(const rs_usb_request &request) override
virtual usb_status submit_request(const rs_usb_request &request) override
GLuint in
Definition: glext.h:8859
std::shared_ptr< handle_winusb > _handle
#define NULL
Definition: tinycthread.c:47
#define TRUE
Definition: tinycthread.c:50
GLenum GLuint GLenum GLsizei length
GLuint res
Definition: glext.h:8856
std::map< uint8_t, std::shared_ptr< dispatcher > > _dispatchers


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:21