aboutsummaryrefslogtreecommitdiff
path: root/ports/libusb/libfreenect2.patch
blob: 2c2b859b0107e6b6f5db70c007ab9be8ac2d1e88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index 93668f3..7fdafd6 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -66,6 +66,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
 static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
 static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
+static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
 static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
 static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
@@ -1901,6 +1902,10 @@ void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
 
 	usbi_free_fd(&transfer_priv->pollable_fd);
 	safe_free(transfer_priv->hid_buffer);
+
+	//TODO this should occur during windows_free_transfer instead
+	safe_free(transfer_priv->iso_context);
+
 	// When auto claim is in use, attempt to release the auto-claimed interface
 	auto_release(itransfer);
 }
@@ -2274,7 +2279,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
 		winusbx_clear_halt,
 		winusbx_reset_device,
 		winusbx_submit_bulk_transfer,
-		unsupported_submit_iso_transfer,
+		winusbx_submit_iso_transfer,
 		winusbx_submit_control_transfer,
 		winusbx_abort_control,
 		winusbx_abort_transfers,
@@ -2374,6 +2379,8 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx)
 		WinUSBX_Set(SetPipePolicy);
 		WinUSBX_Set(SetPowerPolicy);
 		WinUSBX_Set(WritePipe);
+		WinUSBX_Set(IsoReadPipe);
+		WinUSBX_Set(IsoWritePipe);
 		if (!native_winusb)
 			WinUSBX_Set(ResetDevice);
 
@@ -2803,6 +2810,100 @@ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_ha
 	return LIBUSB_SUCCESS;
 }
 
+static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
+{
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+	struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	HANDLE winusb_handle;
+	bool ret;
+	int current_interface;
+	struct winfd wfd;
+	int i;
+	uint16_t maxPacketSize;
+	uint32_t offset;
+	size_t ctx_size;
+
+	CHECK_WINUSBX_AVAILABLE(sub_api);
+
+	if (sub_api != SUB_API_LIBUSBK && sub_api != SUB_API_LIBUSB0)
+	{
+		//iso only supported on libusbk-based backends
+		return unsupported_submit_iso_transfer(sub_api, itransfer);
+	};
+
+	transfer_priv->pollable_fd = INVALID_WINFD;
+
+	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
+	if (current_interface < 0) {
+		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+		return LIBUSB_ERROR_NOT_FOUND;
+	}
+
+	usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+
+	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
+
+	wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
+	// Always use the handle returned from usbi_create_fd (wfd.handle)
+	if (wfd.fd < 0) {
+		return LIBUSB_ERROR_NO_MEM;
+	}
+
+	ctx_size = sizeof(KISO_CONTEXT)+sizeof(KISO_PACKET)* transfer->num_iso_packets;
+	//Init the libusbk iso_context
+	if (!transfer_priv->iso_context)
+	{
+		transfer_priv->iso_context = (PKISO_CONTEXT)malloc(ctx_size);
+		if (!transfer_priv->iso_context)
+		{
+			//TODO does this return leak mem, or does the transfer get cleaned up?
+			return LIBUSB_ERROR_NO_MEM;
+		}
+	}
+	memset(transfer_priv->iso_context, 0, ctx_size);
+
+	//start ASAP
+	transfer_priv->iso_context->StartFrame = 0;
+	transfer_priv->iso_context->NumberOfPackets = transfer->num_iso_packets;
+
+	/* convert the transfer packet lengths to iso_packet offsets */
+	offset = 0;
+	for (i = 0; i < transfer->num_iso_packets; i++)
+	{
+		transfer_priv->iso_context->IsoPackets[i].offset = offset;
+		offset += transfer->iso_packet_desc[i].length;
+	}
+
+	if (IS_XFERIN(transfer)) {
+		usbi_dbg("reading %d iso packets", transfer->num_iso_packets);
+		ret = WinUSBX[sub_api].IsoReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, wfd.overlapped, transfer_priv->iso_context);
+	}
+	else {
+		usbi_dbg("writing %d iso packets", transfer->num_iso_packets);
+		ret = WinUSBX[sub_api].IsoWritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, wfd.overlapped, transfer_priv->iso_context);
+	}
+
+	if (!ret) {
+		if (GetLastError() != ERROR_IO_PENDING) {
+			usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0));
+			usbi_free_fd(&wfd);
+			return LIBUSB_ERROR_IO;
+		}
+	}
+	else {
+		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
+		wfd.overlapped->InternalHigh = (DWORD)transfer->length;
+	}
+
+	transfer_priv->pollable_fd = wfd;
+	transfer_priv->interface_number = (uint8_t)current_interface;
+
+	return LIBUSB_SUCCESS;
+}
+
 static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
 {
 	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
@@ -2989,7 +3090,36 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha
 
 static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
 {
+	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+	struct windows_transfer_priv *transfer_priv = (struct windows_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
+	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+	int i;
+
+	CHECK_WINUSBX_AVAILABLE(sub_api);
+
+	if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
+	{
+		//for isochronous, need to copy the individual iso packet actual_lengths and statuses
+		if (sub_api == SUB_API_LIBUSBK || sub_api == SUB_API_LIBUSB0)
+		{
+			//iso only supported on libusbk-based backends for now
+
+			for (i = 0; i < transfer->num_iso_packets; i++)
+			{
+				transfer->iso_packet_desc[i].actual_length = transfer_priv->iso_context->IsoPackets[i].actual_length;
+				//TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status
+				//transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status;
+			}
+		}
+		else
+		{
+			//This should only occur if backend is not set correctly or other backend isoc is partially implemented
+			return unsupported_copy_transfer_data(sub_api, itransfer, io_size);
+		}
+	}
+	
 	itransfer->transferred += io_size;
+
 	return LIBUSB_TRANSFER_COMPLETED;
 }
 
diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h
index 89ebc24..28a7e4f 100644
--- a/libusb/os/windows_winusb.h
+++ b/libusb/os/windows_winusb.h
@@ -154,6 +154,42 @@ struct libusb_hid_descriptor {
 #define LIBUSB_REQ_IN(request_type)		((request_type) & LIBUSB_ENDPOINT_IN)
 #define LIBUSB_REQ_OUT(request_type)		(!LIBUSB_REQ_IN(request_type))
 
+
+/* start libusbk_shared.h definitions, must match libusbk_shared.h for isochronous support */
+
+//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths
+typedef struct _KISO_PACKET
+{
+	UINT offset;
+	USHORT actual_length; //changed from libusbk_shared.h "Length" for clarity
+	USHORT status;
+
+} KISO_PACKET;
+
+typedef KISO_PACKET* PKISO_PACKET;
+
+typedef enum _KISO_FLAG
+{
+	KISO_FLAG_NONE = 0,
+	KISO_FLAG_SET_START_FRAME = 0x00000001,
+} KISO_FLAG;
+
+//KISO_CONTEXT is the conceptual equivalent of libusb_transfer except is isochronous-specific and must match libusbk's version
+typedef struct _KISO_CONTEXT
+{
+	KISO_FLAG Flags;
+	UINT StartFrame;
+	SHORT ErrorCount;
+	SHORT NumberOfPackets;
+	UINT UrbHdrStatus;
+	KISO_PACKET IsoPackets[0];
+
+} KISO_CONTEXT;
+
+typedef KISO_CONTEXT* PKISO_CONTEXT;
+
+/* end libusbk_shared.h definitions */
+
 // The following are used for HID reports IOCTLs
 #define HID_CTL_CODE(id) \
 	CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
@@ -280,6 +316,8 @@ struct windows_transfer_priv {
 	uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
 	uint8_t *hid_dest;   // transfer buffer destination, required for HID
 	size_t hid_expected_size;
+	/* Isoc */
+	PKISO_CONTEXT iso_context;
 };
 
 // used to match a device driver (including filter drivers) against a supported API
@@ -623,6 +661,23 @@ typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
 	WINUSB_INTERFACE_HANDLE InterfaceHandle
 );
 
+typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR PipeID,
+	PUCHAR Buffer,
+	ULONG BufferLength,
+	LPOVERLAPPED Overlapped,
+	PKISO_CONTEXT IsoContext
+	);
+typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)(
+	WINUSB_INTERFACE_HANDLE InterfaceHandle,
+	UCHAR PipeID,
+	PUCHAR Buffer,
+	ULONG BufferLength,
+	LPOVERLAPPED Overlapped,
+	PKISO_CONTEXT IsoContext
+	);
+
 /* /!\ These must match the ones from the official libusbk.h */
 typedef enum _KUSB_FNID {
 	KUSB_FNID_Init,
@@ -703,6 +758,8 @@ struct winusb_interface {
 	WinUsb_SetPowerPolicy_t SetPowerPolicy;
 	WinUsb_WritePipe_t WritePipe;
 	WinUsb_ResetDevice_t ResetDevice;
+	WinUsb_IsoReadPipe_t IsoReadPipe;
+	WinUsb_IsoWritePipe_t IsoWritePipe;
 };
 
 /* hid.dll interface */