HaikuDepot: notify work status from main window
[haiku.git] / src / kits / device / USBDevice.cpp
blob130baa1b2ed0ee6c18b0d4fba54484672542768f
1 /*
2 * Copyright 2007-2008, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 */
9 #include <USBKit.h>
10 #include <usb_raw.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <new>
17 BUSBDevice::BUSBDevice(const char *path)
18 : fPath(NULL),
19 fRawFD(-1),
20 fConfigurations(NULL),
21 fActiveConfiguration(0),
22 fManufacturerString(NULL),
23 fProductString(NULL),
24 fSerialNumberString(NULL)
26 memset(&fDescriptor, 0, sizeof(fDescriptor));
28 if (path)
29 SetTo(path);
33 BUSBDevice::~BUSBDevice()
35 Unset();
39 status_t
40 BUSBDevice::InitCheck()
42 return (fRawFD >= 0 ? B_OK : B_ERROR);
46 status_t
47 BUSBDevice::SetTo(const char *path)
49 if (!path)
50 return B_BAD_VALUE;
52 fPath = strdup(path);
53 fRawFD = open(path, O_RDWR | O_CLOEXEC);
54 if (fRawFD < 0) {
55 Unset();
56 return B_ERROR;
59 usb_raw_command command;
60 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_VERSION, &command, sizeof(command))
61 || command.version.status != B_USB_RAW_PROTOCOL_VERSION) {
62 Unset();
63 return B_ERROR;
66 command.device.descriptor = &fDescriptor;
67 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command,
68 sizeof(command)) || command.device.status != B_USB_RAW_STATUS_SUCCESS) {
69 Unset();
70 return B_ERROR;
73 fConfigurations = new(std::nothrow) BUSBConfiguration *[
74 fDescriptor.num_configurations];
75 if (fConfigurations == NULL)
76 return B_NO_MEMORY;
78 for (uint32 i = 0; i < fDescriptor.num_configurations; i++) {
79 fConfigurations[i] = new(std::nothrow) BUSBConfiguration(this, i,
80 fRawFD);
83 return B_OK;
87 void
88 BUSBDevice::Unset()
90 if (fRawFD >= 0)
91 close(fRawFD);
92 fRawFD = -1;
94 free(fPath);
95 fPath = NULL;
97 delete[] fManufacturerString;
98 delete[] fProductString;
99 delete[] fSerialNumberString;
100 fManufacturerString = fProductString = fSerialNumberString = NULL;
102 if (fConfigurations != NULL) {
103 for (int32 i = 0; i < fDescriptor.num_configurations; i++)
104 delete fConfigurations[i];
106 delete[] fConfigurations;
107 fConfigurations = NULL;
110 memset(&fDescriptor, 0, sizeof(fDescriptor));
114 const char *
115 BUSBDevice::Location() const
117 if (!fPath || strlen(fPath) < 12)
118 return NULL;
120 return &fPath[12];
124 bool
125 BUSBDevice::IsHub() const
127 return fDescriptor.device_class == 0x09;
131 uint16
132 BUSBDevice::USBVersion() const
134 return fDescriptor.usb_version;
138 uint8
139 BUSBDevice::Class() const
141 return fDescriptor.device_class;
145 uint8
146 BUSBDevice::Subclass() const
148 return fDescriptor.device_subclass;
152 uint8
153 BUSBDevice::Protocol() const
155 return fDescriptor.device_protocol;
159 uint8
160 BUSBDevice::MaxEndpoint0PacketSize() const
162 return fDescriptor.max_packet_size_0;
166 uint16
167 BUSBDevice::VendorID() const
169 return fDescriptor.vendor_id;
173 uint16
174 BUSBDevice::ProductID() const
176 return fDescriptor.product_id;
180 uint16
181 BUSBDevice::Version() const
183 return fDescriptor.device_version;
187 const char *
188 BUSBDevice::ManufacturerString() const
190 if (fDescriptor.manufacturer == 0)
191 return "";
193 if (fManufacturerString)
194 return fManufacturerString;
196 fManufacturerString = DecodeStringDescriptor(fDescriptor.manufacturer);
197 if (fManufacturerString == NULL)
198 return "";
200 return fManufacturerString;
204 const char *
205 BUSBDevice::ProductString() const
207 if (fDescriptor.product == 0)
208 return "";
210 if (fProductString)
211 return fProductString;
213 fProductString = DecodeStringDescriptor(fDescriptor.product);
214 if (fProductString == NULL)
215 return "";
217 return fProductString;
221 const char *
222 BUSBDevice::SerialNumberString() const
224 if (fDescriptor.serial_number == 0)
225 return "";
227 if (fSerialNumberString)
228 return fSerialNumberString;
230 fSerialNumberString = DecodeStringDescriptor(fDescriptor.serial_number);
231 if (fSerialNumberString == NULL)
232 return "";
234 return fSerialNumberString;
238 const usb_device_descriptor *
239 BUSBDevice::Descriptor() const
241 return &fDescriptor;
245 size_t
246 BUSBDevice::GetStringDescriptor(uint32 index,
247 usb_string_descriptor *descriptor, size_t length) const
249 if (!descriptor)
250 return B_BAD_VALUE;
252 usb_raw_command command;
253 command.string.descriptor = descriptor;
254 command.string.string_index = index;
255 command.string.length = length;
257 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR, &command,
258 sizeof(command)) || command.string.status != B_USB_RAW_STATUS_SUCCESS)
259 return 0;
261 return command.string.length;
265 char *
266 BUSBDevice::DecodeStringDescriptor(uint32 index) const
268 char buffer[300];
269 usb_string_descriptor *stringDescriptor;
270 stringDescriptor = (usb_string_descriptor *)&buffer;
272 size_t stringLength = GetStringDescriptor(index, stringDescriptor,
273 sizeof(buffer) - sizeof(usb_string_descriptor));
275 if (stringLength < 3)
276 return NULL;
278 // pseudo convert unicode string
279 stringLength = (stringLength - 2) / 2;
280 char *result = new(std::nothrow) char[stringLength + 1];
281 if (result == NULL)
282 return NULL;
284 for (size_t i = 0; i < stringLength; i++)
285 result[i] = stringDescriptor->string[i * 2];
286 result[stringLength] = 0;
287 return result;
291 size_t
292 BUSBDevice::GetDescriptor(uint8 type, uint8 index, uint16 languageID,
293 void *data, size_t length) const
295 if (length > 0 && data == NULL)
296 return B_BAD_VALUE;
298 usb_raw_command command;
299 command.descriptor.type = type;
300 command.descriptor.index = index;
301 command.descriptor.language_id = languageID;
302 command.descriptor.data = data;
303 command.descriptor.length = length;
305 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DESCRIPTOR, &command,
306 sizeof(command)) || command.descriptor.status != B_USB_RAW_STATUS_SUCCESS)
307 return 0;
309 return command.descriptor.length;
313 uint32
314 BUSBDevice::CountConfigurations() const
316 return fDescriptor.num_configurations;
320 const BUSBConfiguration *
321 BUSBDevice::ConfigurationAt(uint32 index) const
323 if (index >= fDescriptor.num_configurations || fConfigurations == NULL)
324 return NULL;
326 return fConfigurations[index];
330 const BUSBConfiguration *
331 BUSBDevice::ActiveConfiguration() const
333 if (fConfigurations == NULL)
334 return NULL;
336 return fConfigurations[fActiveConfiguration];
340 status_t
341 BUSBDevice::SetConfiguration(const BUSBConfiguration *configuration)
343 if (!configuration || configuration->Index() >= fDescriptor.num_configurations)
344 return B_BAD_VALUE;
346 usb_raw_command command;
347 command.config.config_index = configuration->Index();
349 if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command,
350 sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS)
351 return B_ERROR;
353 fActiveConfiguration = configuration->Index();
354 return B_OK;
358 ssize_t
359 BUSBDevice::ControlTransfer(uint8 requestType, uint8 request, uint16 value,
360 uint16 index, uint16 length, void *data) const
362 if (length > 0 && data == NULL)
363 return B_BAD_VALUE;
365 usb_raw_command command;
366 command.control.request_type = requestType;
367 command.control.request = request;
368 command.control.value = value;
369 command.control.index = index;
370 command.control.length = length;
371 command.control.data = data;
373 if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command,
374 sizeof(command)) || command.control.status != B_USB_RAW_STATUS_SUCCESS)
375 return B_ERROR;
377 return command.control.length;
381 // definition of reserved virtual functions
382 void BUSBDevice::_ReservedUSBDevice1() {};
383 void BUSBDevice::_ReservedUSBDevice2() {};
384 void BUSBDevice::_ReservedUSBDevice3() {};
385 void BUSBDevice::_ReservedUSBDevice4() {};
386 void BUSBDevice::_ReservedUSBDevice5() {};