xref: /haiku/src/kits/device/USBInterface.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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,
19 	uint32 alternate, int rawFD)
20 	:	fConfiguration(config),
21 		fIndex(index),
22 		fAlternate(alternate),
23 		fRawFD(rawFD),
24 		fEndpoints(NULL),
25 		fAlternateCount(0),
26 		fAlternates(NULL),
27 		fInterfaceString(NULL)
28 {
29 	_UpdateDescriptorAndEndpoints();
30 }
31 
32 
33 BUSBInterface::~BUSBInterface()
34 {
35 	delete[] fInterfaceString;
36 
37 	if (fEndpoints != NULL) {
38 		for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
39 			delete fEndpoints[i];
40 		delete[] fEndpoints;
41 	}
42 
43 	if (fAlternates != NULL) {
44 		for (uint32 i = 0; i < fAlternateCount; i++)
45 			delete fAlternates[i];
46 		delete[] fAlternates;
47 	}
48 }
49 
50 
51 uint32
52 BUSBInterface::Index() const
53 {
54 	return fIndex;
55 }
56 
57 
58 uint32
59 BUSBInterface::AlternateIndex() const
60 {
61 	if (fAlternate == B_USB_RAW_ACTIVE_ALTERNATE)
62 		return ActiveAlternateIndex();
63 	return fAlternate;
64 }
65 
66 
67 const BUSBConfiguration *
68 BUSBInterface::Configuration() const
69 {
70 	return fConfiguration;
71 }
72 
73 
74 const BUSBDevice *
75 BUSBInterface::Device() const
76 {
77 	return fConfiguration->Device();
78 }
79 
80 
81 uint8
82 BUSBInterface::Class() const
83 {
84 	return fDescriptor.interface_class;
85 }
86 
87 
88 uint8
89 BUSBInterface::Subclass() const
90 {
91 	return fDescriptor.interface_subclass;
92 }
93 
94 
95 uint8
96 BUSBInterface::Protocol() const
97 {
98 	return fDescriptor.interface_protocol;
99 }
100 
101 
102 const char *
103 BUSBInterface::InterfaceString() const
104 {
105 	if (fDescriptor.interface == 0)
106 		return "";
107 
108 	if (fInterfaceString)
109 		return fInterfaceString;
110 
111 	fInterfaceString = Device()->DecodeStringDescriptor(fDescriptor.interface);
112 	if (fInterfaceString == NULL)
113 		return "";
114 
115 	return fInterfaceString;
116 }
117 
118 
119 const usb_interface_descriptor *
120 BUSBInterface::Descriptor() const
121 {
122 	return &fDescriptor;
123 }
124 
125 
126 status_t
127 BUSBInterface::OtherDescriptorAt(uint32 index, usb_descriptor *descriptor,
128 	size_t length) const
129 {
130 	if (length <= 0 || descriptor == NULL)
131 		return B_BAD_VALUE;
132 
133 	usb_raw_command command;
134 	command.generic_etc.descriptor = descriptor;
135 	command.generic_etc.config_index = fConfiguration->Index();
136 	command.generic_etc.interface_index = fIndex;
137 	command.generic_etc.alternate_index = fAlternate;
138 	command.generic_etc.generic_index = index;
139 	command.generic_etc.length = length;
140 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC, &command,
141 		sizeof(command)) || command.generic.status != B_USB_RAW_STATUS_SUCCESS)
142 		return B_ERROR;
143 
144 	return B_OK;
145 }
146 
147 
148 uint32
149 BUSBInterface::CountEndpoints() const
150 {
151 	return fDescriptor.num_endpoints;
152 }
153 
154 
155 const BUSBEndpoint *
156 BUSBInterface::EndpointAt(uint32 index) const
157 {
158 	if (index >= fDescriptor.num_endpoints || fEndpoints == NULL)
159 		return NULL;
160 
161 	return fEndpoints[index];
162 }
163 
164 
165 uint32
166 BUSBInterface::CountAlternates() const
167 {
168 	usb_raw_command command;
169 	command.alternate.config_index = fConfiguration->Index();
170 	command.alternate.interface_index = fIndex;
171 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command,
172 		sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS)
173 		return 1;
174 
175 	return command.alternate.alternate_info;
176 }
177 
178 
179 const BUSBInterface *
180 BUSBInterface::AlternateAt(uint32 alternateIndex) const
181 {
182 	if (fAlternateCount > 0 && fAlternates != NULL) {
183 		if (alternateIndex >= fAlternateCount)
184 			return NULL;
185 
186 		return fAlternates[alternateIndex];
187 	}
188 
189 	if (fAlternateCount == 0)
190 		fAlternateCount = CountAlternates();
191 	if (alternateIndex >= fAlternateCount)
192 		return NULL;
193 
194 	fAlternates = new(std::nothrow) BUSBInterface *[fAlternateCount];
195 	if (fAlternates == NULL)
196 		return NULL;
197 
198 	for (uint32 i = 0; i < fAlternateCount; i++) {
199 		fAlternates[i] = new(std::nothrow) BUSBInterface(fConfiguration, fIndex,
200 			i, fRawFD);
201 	}
202 
203 	return fAlternates[alternateIndex];
204 }
205 
206 
207 uint32
208 BUSBInterface::ActiveAlternateIndex() const
209 {
210 	usb_raw_command command;
211 	command.alternate.config_index = fConfiguration->Index();
212 	command.alternate.interface_index = fIndex;
213 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, &command,
214 		sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS)
215 		return 0;
216 
217 	return command.alternate.alternate_info;
218 }
219 
220 
221 status_t
222 BUSBInterface::SetAlternate(uint32 alternateIndex)
223 {
224 	usb_raw_command command;
225 	command.alternate.alternate_info = alternateIndex;
226 	command.alternate.config_index = fConfiguration->Index();
227 	command.alternate.interface_index = fIndex;
228 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command,
229 		sizeof(command)) || command.alternate.status != B_USB_RAW_STATUS_SUCCESS)
230 		return B_ERROR;
231 
232 	_UpdateDescriptorAndEndpoints();
233 	return B_OK;
234 }
235 
236 
237 void
238 BUSBInterface::_UpdateDescriptorAndEndpoints()
239 {
240 	usb_raw_command command;
241 	command.interface_etc.descriptor = &fDescriptor;
242 	command.interface_etc.config_index = fConfiguration->Index();
243 	command.interface_etc.interface_index = fIndex;
244 	command.interface_etc.alternate_index = fAlternate;
245 	if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command,
246 		sizeof(command)) || command.interface.status != B_USB_RAW_STATUS_SUCCESS)
247 		memset(&fDescriptor, 0, sizeof(fDescriptor));
248 
249 	if (fEndpoints != NULL) {
250 		// Delete old endpoints
251 		for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
252 			delete fEndpoints[i];
253 		delete fEndpoints;
254 	}
255 
256 	fEndpoints = new(std::nothrow) BUSBEndpoint *[fDescriptor.num_endpoints];
257 	if (fEndpoints == NULL)
258 		return;
259 
260 	for (int32 i = 0; i < fDescriptor.num_endpoints; i++)
261 		fEndpoints[i] = new(std::nothrow) BUSBEndpoint(this, i, fRawFD);
262 }
263