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 
set_interface(libusb_device_t * dev,int interface_number,int alt_interface_number,int timeout)23 NTSTATUS set_interface(libusb_device_t *dev,
24 					   int interface_number,
25 					   int alt_interface_number,
26                        int timeout)
27 {
28     NTSTATUS status = STATUS_SUCCESS;
29     URB *urb;
30     int i, tmp_size;
31 
32     USB_INTERFACE_DESCRIPTOR *interface_descriptor = NULL;
33     USBD_INTERFACE_INFORMATION *interface_information = NULL;
34 
35 
36 	USBMSG("interface-number=%d alt-number=%d timeout=%d\n",
37 		interface_number,alt_interface_number,timeout);
38 
39 	if (!dev->config.value || !dev->config.descriptor)
40     {
41         USBERR0("device is not configured\n");
42         return STATUS_INVALID_DEVICE_STATE;
43     }
44 
45 	interface_descriptor = find_interface_desc(dev->config.descriptor, dev->config.total_size, interface_number, alt_interface_number);
46 
47 	if (!interface_descriptor)
48     {
49 		USBERR("interface-number=%d alt-number=%d does not exists.\n",
50 			interface_number,alt_interface_number,timeout);
51 
52 		return STATUS_NO_MORE_ENTRIES;
53     }
54 
55     tmp_size = sizeof(struct _URB_SELECT_INTERFACE) + interface_descriptor->bNumEndpoints * sizeof(USBD_PIPE_INFORMATION);
56 
57     urb = ExAllocatePool(NonPagedPool, tmp_size);
58 
59     if (!urb)
60     {
61         USBERR0("memory_allocation error\n");
62         return STATUS_NO_MEMORY;
63     }
64 
65     memset(urb, 0, tmp_size);
66 
67     urb->UrbHeader.Function = URB_FUNCTION_SELECT_INTERFACE;
68     urb->UrbHeader.Length = (USHORT)tmp_size;
69 
70     urb->UrbSelectInterface.ConfigurationHandle = dev->config.handle;
71     urb->UrbSelectInterface.Interface.Length = sizeof(struct _USBD_INTERFACE_INFORMATION);
72     urb->UrbSelectInterface.Interface.NumberOfPipes = interface_descriptor->bNumEndpoints;
73     urb->UrbSelectInterface.Interface.Length += interface_descriptor->bNumEndpoints * sizeof(struct _USBD_PIPE_INFORMATION);
74 
75     urb->UrbSelectInterface.Interface.InterfaceNumber = (UCHAR)interface_descriptor->bInterfaceNumber;
76     urb->UrbSelectInterface.Interface.AlternateSetting = (UCHAR)interface_descriptor->bAlternateSetting;
77 
78     interface_information = &urb->UrbSelectInterface.Interface;
79 
80     for (i = 0; i < interface_descriptor->bNumEndpoints; i++)
81     {
82         interface_information->Pipes[i].MaximumTransferSize = LIBUSB_MAX_READ_WRITE;
83     }
84 
85     status = call_usbd(dev, urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
86 
87 
88     if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb->UrbHeader.Status))
89     {
90         USBERR("setting interface failed: status: 0x%x, urb-status: 0x%x\n", status, urb->UrbHeader.Status);
91         ExFreePool(urb);
92         return STATUS_UNSUCCESSFUL;
93     }
94 
95     update_pipe_info(dev, interface_information);
96 
97     ExFreePool(urb);
98 
99     return status;
100 }
101 
set_interface_ex(libusb_device_t * dev,interface_request_t * interface_request,int timeout)102 NTSTATUS set_interface_ex(libusb_device_t *dev,
103 					   interface_request_t* interface_request,
104                        int timeout)
105 {
106     NTSTATUS status = STATUS_SUCCESS;
107 
108     USB_INTERFACE_DESCRIPTOR *interface_descriptor = NULL;
109 
110 	USBMSG("interface-%s=%d alt-%s=%d timeout=%d\n",
111 		interface_request->intf_use_index ? "index" : "number",
112 		interface_request->intf_use_index ? interface_request->interface_index : interface_request->interface_number,
113 		interface_request->altf_use_index ? "index" : "number",
114 		interface_request->altf_use_index ? interface_request->altsetting_index : interface_request->altsetting_number,
115 		timeout);
116 
117 	interface_descriptor = find_interface_desc_ex(dev->config.descriptor,dev->config.total_size,interface_request,NULL);
118 	if (!interface_descriptor)
119 	{
120         return STATUS_NO_MORE_ENTRIES;
121 	}
122 
123 	return set_interface(dev,interface_descriptor->bInterfaceNumber, interface_descriptor->bAlternateSetting, timeout);
124 }
125