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