xref: /haiku/src/kits/device/USBInterface.cpp (revision f75a7bf508f3156d63a14f8fd77c5e0ca4d08c42)
1 /*
2  * Copyright 2007-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  *		Salvatore Benedetto <salvatore.benedetto@gmail.com>
8  */
9 
10 #include <USBKit.h>
11 #include <usb_raw.h>
12 
13 #include <new>
14 #include <string.h>
15 #include <unistd.h>
16 
17 
18 BUSBInterface::BUSBInterface(BUSBConfiguration *config, uint32 index, int rawFD)
19 	:	fConfiguration(config),
20 		fIndex(index),
21 		fRawFD(rawFD),
22 		fEndpoints(NULL),
23 		fInterfaceString(NULL)
24 {
25 	_UpdateDescriptorAndEndpoints();
26 }
27 
28 
29 BUSBInterface::~BUSBInterface()
30 {
31 	delete[] fInterfaceString;
32 	for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
33 		delete fEndpoints[i];
34 	delete[] fEndpoints;
35 }
36 
37 
38 uint32
39 BUSBInterface::Index() const
40 {
41 	return fIndex;
42 }
43 
44 
45 const BUSBConfiguration *
46 BUSBInterface::Configuration() const
47 {
48 	return fConfiguration;
49 }
50 
51 
52 const BUSBDevice *
53 BUSBInterface::Device() const
54 {
55 	return fConfiguration->Device();
56 }
57 
58 
59 uint8
60 BUSBInterface::Class() const
61 {
62 	return fDescriptor.interface_class;
63 }
64 
65 
66 uint8
67 BUSBInterface::Subclass() const
68 {
69 	return fDescriptor.interface_subclass;
70 }
71 
72 
73 uint8
74 BUSBInterface::Protocol() const
75 {
76 	return fDescriptor.interface_protocol;
77 }
78 
79 
80 const char *
81 BUSBInterface::InterfaceString() const
82 {
83 	if (fDescriptor.interface == 0)
84 		return "";
85 
86 	if (fInterfaceString)
87 		return fInterfaceString;
88 
89 	fInterfaceString = Device()->DecodeStringDescriptor(fDescriptor.interface);
90 	if (!fInterfaceString) {
91 		fInterfaceString = new char[1];
92 		fInterfaceString[0] = 0;
93 	}
94 
95 	return fInterfaceString;
96 }
97 
98 
99 const usb_interface_descriptor *
100 BUSBInterface::Descriptor() const
101 {
102 	return &fDescriptor;
103 }
104 
105 
106 status_t
107 BUSBInterface::OtherDescriptorAt(uint32 index, usb_descriptor *descriptor,
108 	size_t length) const
109 {
110 	if (length > 0 && descriptor == NULL)
111 		return B_BAD_VALUE;
112 
113 	usb_raw_command command;
114 	command.generic.descriptor = descriptor;
115 	command.generic.config_index = fConfiguration->Index();
116 	command.generic.interface_index = fIndex;
117 	command.generic.length = length;
118 	command.generic.generic_index = index;
119 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR, &command,
120 		sizeof(command)) || command.generic.status != B_USB_RAW_STATUS_SUCCESS)
121 		return B_ERROR;
122 
123 	return B_OK;
124 }
125 
126 
127 uint32
128 BUSBInterface::CountEndpoints() const
129 {
130 	return fDescriptor.num_endpoints;
131 }
132 
133 
134 const BUSBEndpoint *
135 BUSBInterface::EndpointAt(uint32 index) const
136 {
137 	if (index >= fDescriptor.num_endpoints)
138 		return NULL;
139 
140 	return fEndpoints[index];
141 }
142 
143 
144 uint32
145 BUSBInterface::CountAlternates() const
146 {
147 	uint32 alternateCount;
148 	usb_raw_command command;
149 	command.alternate.alternate_count = &alternateCount;
150 	command.alternate.config_index = fConfiguration->Index();
151 	command.alternate.interface_index = fIndex;
152 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command,
153 		sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS)
154 		return 1;
155 
156 	return alternateCount;
157 }
158 
159 
160 usb_interface_descriptor *
161 BUSBInterface::AlternateAt(uint32 alternateIndex)
162 {
163 	usb_interface_descriptor *descriptor
164 		= new(std::nothrow) usb_interface_descriptor;
165 	if (descriptor == NULL)
166 		return NULL;
167 
168 	usb_raw_command command;
169 	command.alternate.descriptor = descriptor;
170 	command.alternate.config_index = fConfiguration->Index();
171 	command.alternate.interface_index = fIndex;
172 	command.alternate.alternate_index = alternateIndex;
173 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_DESCRIPTOR, &command,
174 		sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS) {
175 		delete descriptor;
176 		return NULL;
177 	}
178 
179 	return descriptor;
180 }
181 
182 
183 status_t
184 BUSBInterface::SetAlternate(uint32 alternateIndex)
185 {
186 	usb_raw_command command;
187 	command.alternate.config_index = fConfiguration->Index();
188 	command.alternate.interface_index = fIndex;
189 	command.alternate.alternate_index = alternateIndex;
190 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command,
191 		sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS)
192 		return B_ERROR;
193 
194 	_UpdateDescriptorAndEndpoints();
195 	return B_OK;
196 }
197 
198 
199 void
200 BUSBInterface::_UpdateDescriptorAndEndpoints()
201 {
202 	usb_raw_command command;
203 	command.interface.descriptor = &fDescriptor;
204 	command.interface.config_index = fConfiguration->Index();
205 	command.interface.interface_index = fIndex;
206 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR, &command,
207 		sizeof(command)) || command.interface.status != B_USB_RAW_STATUS_SUCCESS)
208 		memset(&fDescriptor, 0, sizeof(fDescriptor));
209 
210 	if (fEndpoints) {
211 		// Delete old endpoints
212 		for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
213 			delete fEndpoints[i];
214 		delete fEndpoints;
215 	}
216 
217 	fEndpoints = new BUSBEndpoint *[fDescriptor.num_endpoints];
218 	for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
219 		fEndpoints[i] = new BUSBEndpoint(this, i, fRawFD);
220 }
221