1 /* libusb-win32, Generic Windows USB Library
2 * Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
20 #include "libusb_driver.h"
21
22
vendor_class_request(libusb_device_t * dev,int type,int recipient,int request,int value,int index,void * buffer,int size,int direction,int * ret,int timeout)23 NTSTATUS vendor_class_request(libusb_device_t *dev,
24 int type, int recipient,
25 int request, int value, int index,
26 void *buffer, int size, int direction,
27 int *ret, int timeout)
28 {
29 NTSTATUS status = STATUS_SUCCESS;
30 URB urb;
31
32 *ret = 0;
33
34 memset(&urb, 0, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
35
36 switch (type)
37 {
38 case USB_TYPE_CLASS:
39 USBMSG0("type: class\n");
40 switch (recipient)
41 {
42 case USB_RECIP_DEVICE:
43 USBMSG0("recipient: device\n");
44 urb.UrbHeader.Function = URB_FUNCTION_CLASS_DEVICE;
45 break;
46 case USB_RECIP_INTERFACE:
47 USBMSG0("recipient: interface\n");
48 urb.UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE;
49 break;
50 case USB_RECIP_ENDPOINT:
51 USBMSG0("recipient: endpoint\n");
52 urb.UrbHeader.Function = URB_FUNCTION_CLASS_ENDPOINT;
53 break;
54 case USB_RECIP_OTHER:
55 USBMSG0("recipient: other\n");
56 urb.UrbHeader.Function = URB_FUNCTION_CLASS_OTHER;
57 break;
58 default:
59 USBERR0("invalid recipient\n");
60 return STATUS_INVALID_PARAMETER;
61 }
62 break;
63 case USB_TYPE_VENDOR:
64 USBMSG0("type: vendor\n");
65 switch (recipient)
66 {
67 case USB_RECIP_DEVICE:
68 USBMSG0("recipient: device\n");
69 urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
70 break;
71 case USB_RECIP_INTERFACE:
72 USBMSG0("recipient: interface\n");
73 urb.UrbHeader.Function = URB_FUNCTION_VENDOR_INTERFACE;
74 break;
75 case USB_RECIP_ENDPOINT:
76 USBMSG0("recipient: endpoint\n");
77 urb.UrbHeader.Function = URB_FUNCTION_VENDOR_ENDPOINT;
78 break;
79 case USB_RECIP_OTHER:
80 USBMSG0("recipient: other\n");
81 urb.UrbHeader.Function = URB_FUNCTION_VENDOR_OTHER;
82 break;
83 default:
84 // [Kevin Timmerman Patch]
85 USBMSG("recipient: reserved (0x%02x)\n", recipient);
86 urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
87 urb.UrbControlVendorClassRequest.RequestTypeReservedBits = (UCHAR)recipient;
88 break;
89 /*
90 USBERR0("invalid recipient\n");
91 return STATUS_INVALID_PARAMETER;
92 */
93 }
94 break;
95 default:
96 USBERR0("invalid type\n");
97 return STATUS_INVALID_PARAMETER;
98 }
99
100 USBMSG("request: 0x%02x\n", request);
101 USBMSG("value: 0x%04x\n", value);
102 USBMSG("index: 0x%04x\n", index);
103 USBMSG("size: %d\n", size);
104
105 if (direction == USBD_TRANSFER_DIRECTION_IN)
106 {
107 USBMSG0("direction: in\n");
108 }
109 else
110 {
111 USBMSG0("direction: out\n");
112 }
113
114 USBMSG("timeout: %d\n", timeout);
115
116 urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
117 urb.UrbControlVendorClassRequest.TransferFlags
118 = direction | USBD_SHORT_TRANSFER_OK ;
119 urb.UrbControlVendorClassRequest.TransferBufferLength = size;
120 urb.UrbControlVendorClassRequest.TransferBufferMDL = NULL;
121 urb.UrbControlVendorClassRequest.TransferBuffer = buffer;
122 urb.UrbControlVendorClassRequest.Request = (UCHAR)request;
123 urb.UrbControlVendorClassRequest.Value = (USHORT)value;
124 urb.UrbControlVendorClassRequest.Index = (USHORT)index;
125
126 // no maximum timeout check for vendor request.
127 status = call_usbd_ex(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout, 0);
128
129 if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
130 {
131 USBERR("request failed: status: 0x%x, urb-status: 0x%x\n", status, urb.UrbHeader.Status);
132 }
133 else
134 {
135 if (direction == USBD_TRANSFER_DIRECTION_IN)
136 *ret = urb.UrbControlVendorClassRequest.TransferBufferLength;
137 USBMSG("%d bytes transmitted\n",
138 urb.UrbControlVendorClassRequest.TransferBufferLength);
139 }
140
141 return status;
142 }
143
144