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 */ 8 9 #include <ByteOrder.h> 10 #include <USBKit.h> 11 #include <usb_raw.h> 12 #include <UTF8.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include <new> 17 18 19 BUSBDevice::BUSBDevice(const char *path) 20 : fPath(NULL), 21 fRawFD(-1), 22 fConfigurations(NULL), 23 fActiveConfiguration(0), 24 fManufacturerString(NULL), 25 fProductString(NULL), 26 fSerialNumberString(NULL) 27 { 28 memset(&fDescriptor, 0, sizeof(fDescriptor)); 29 30 if (path) 31 SetTo(path); 32 } 33 34 35 BUSBDevice::~BUSBDevice() 36 { 37 Unset(); 38 } 39 40 41 status_t 42 BUSBDevice::InitCheck() 43 { 44 return (fRawFD >= 0 ? B_OK : B_ERROR); 45 } 46 47 48 status_t 49 BUSBDevice::SetTo(const char *path) 50 { 51 if (!path) 52 return B_BAD_VALUE; 53 54 fPath = strdup(path); 55 fRawFD = open(path, O_RDWR | O_CLOEXEC); 56 if (fRawFD < 0) { 57 Unset(); 58 return B_ERROR; 59 } 60 61 usb_raw_command command; 62 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_VERSION, &command, sizeof(command)) 63 || command.version.status != B_USB_RAW_PROTOCOL_VERSION) { 64 Unset(); 65 return B_ERROR; 66 } 67 68 command.device.descriptor = &fDescriptor; 69 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command, 70 sizeof(command)) || command.device.status != B_USB_RAW_STATUS_SUCCESS) { 71 Unset(); 72 return B_ERROR; 73 } 74 75 fConfigurations = new(std::nothrow) BUSBConfiguration *[ 76 fDescriptor.num_configurations]; 77 if (fConfigurations == NULL) 78 return B_NO_MEMORY; 79 80 for (uint32 i = 0; i < fDescriptor.num_configurations; i++) { 81 fConfigurations[i] = new(std::nothrow) BUSBConfiguration(this, i, 82 fRawFD); 83 } 84 85 return B_OK; 86 } 87 88 89 void 90 BUSBDevice::Unset() 91 { 92 if (fRawFD >= 0) 93 close(fRawFD); 94 fRawFD = -1; 95 96 free(fPath); 97 fPath = NULL; 98 99 delete[] fManufacturerString; 100 delete[] fProductString; 101 delete[] fSerialNumberString; 102 fManufacturerString = fProductString = fSerialNumberString = NULL; 103 104 if (fConfigurations != NULL) { 105 for (int32 i = 0; i < fDescriptor.num_configurations; i++) 106 delete fConfigurations[i]; 107 108 delete[] fConfigurations; 109 fConfigurations = NULL; 110 } 111 112 memset(&fDescriptor, 0, sizeof(fDescriptor)); 113 } 114 115 116 const char * 117 BUSBDevice::Location() const 118 { 119 if (!fPath || strlen(fPath) < 12) 120 return NULL; 121 122 return &fPath[12]; 123 } 124 125 126 bool 127 BUSBDevice::IsHub() const 128 { 129 return fDescriptor.device_class == 0x09; 130 } 131 132 133 uint16 134 BUSBDevice::USBVersion() const 135 { 136 return fDescriptor.usb_version; 137 } 138 139 140 uint8 141 BUSBDevice::Class() const 142 { 143 return fDescriptor.device_class; 144 } 145 146 147 uint8 148 BUSBDevice::Subclass() const 149 { 150 return fDescriptor.device_subclass; 151 } 152 153 154 uint8 155 BUSBDevice::Protocol() const 156 { 157 return fDescriptor.device_protocol; 158 } 159 160 161 uint8 162 BUSBDevice::MaxEndpoint0PacketSize() const 163 { 164 return fDescriptor.max_packet_size_0; 165 } 166 167 168 uint16 169 BUSBDevice::VendorID() const 170 { 171 return fDescriptor.vendor_id; 172 } 173 174 175 uint16 176 BUSBDevice::ProductID() const 177 { 178 return fDescriptor.product_id; 179 } 180 181 182 uint16 183 BUSBDevice::Version() const 184 { 185 return fDescriptor.device_version; 186 } 187 188 189 const char * 190 BUSBDevice::ManufacturerString() const 191 { 192 if (fDescriptor.manufacturer == 0) 193 return ""; 194 195 if (fManufacturerString) 196 return fManufacturerString; 197 198 fManufacturerString = DecodeStringDescriptor(fDescriptor.manufacturer); 199 if (fManufacturerString == NULL) 200 return ""; 201 202 return fManufacturerString; 203 } 204 205 206 const char * 207 BUSBDevice::ProductString() const 208 { 209 if (fDescriptor.product == 0) 210 return ""; 211 212 if (fProductString) 213 return fProductString; 214 215 fProductString = DecodeStringDescriptor(fDescriptor.product); 216 if (fProductString == NULL) 217 return ""; 218 219 return fProductString; 220 } 221 222 223 const char * 224 BUSBDevice::SerialNumberString() const 225 { 226 if (fDescriptor.serial_number == 0) 227 return ""; 228 229 if (fSerialNumberString) 230 return fSerialNumberString; 231 232 fSerialNumberString = DecodeStringDescriptor(fDescriptor.serial_number); 233 if (fSerialNumberString == NULL) 234 return ""; 235 236 return fSerialNumberString; 237 } 238 239 240 const usb_device_descriptor * 241 BUSBDevice::Descriptor() const 242 { 243 return &fDescriptor; 244 } 245 246 247 size_t 248 BUSBDevice::GetStringDescriptor(uint32 index, 249 usb_string_descriptor *descriptor, size_t length) const 250 { 251 if (!descriptor) 252 return B_BAD_VALUE; 253 254 usb_raw_command command; 255 command.string.descriptor = descriptor; 256 command.string.string_index = index; 257 command.string.length = length; 258 259 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR, &command, 260 sizeof(command)) || command.string.status != B_USB_RAW_STATUS_SUCCESS) 261 return 0; 262 263 return command.string.length; 264 } 265 266 267 char * 268 BUSBDevice::DecodeStringDescriptor(uint32 index) const 269 { 270 char buffer[300]; 271 usb_string_descriptor *stringDescriptor; 272 stringDescriptor = (usb_string_descriptor *)&buffer; 273 274 int32 stringLength = GetStringDescriptor(index, stringDescriptor, 275 sizeof(buffer) - sizeof(usb_string_descriptor)) - 1; 276 277 if (stringLength < 3) 278 return NULL; 279 280 int32 resultLength = 0; 281 282 // USB is always little-endian, UCS-2 is big-endian. 283 uint16* ustr = (uint16*)stringDescriptor->string; 284 for (int32 i = 0; i < (stringLength / 2); i++) { 285 // Increase size of result as needed by source character. 286 const uint16 character = B_LENDIAN_TO_HOST_INT16(ustr[i]); 287 resultLength++; 288 if (character >= 0x80) 289 resultLength++; 290 if (character >= 0x800) 291 resultLength++; 292 293 ustr[i] = B_SWAP_INT16(ustr[i]); 294 } 295 296 char *result = new(std::nothrow) char[resultLength + 1]; 297 if (result == NULL) 298 return NULL; 299 300 status_t status = convert_to_utf8(B_UNICODE_CONVERSION, 301 (const char*)stringDescriptor->string, &stringLength, 302 result, &resultLength, NULL); 303 if (status != B_OK) { 304 delete[] result; 305 return NULL; 306 } 307 result[resultLength] = 0; 308 return result; 309 } 310 311 312 size_t 313 BUSBDevice::GetDescriptor(uint8 type, uint8 index, uint16 languageID, 314 void *data, size_t length) const 315 { 316 if (length > 0 && data == NULL) 317 return B_BAD_VALUE; 318 319 usb_raw_command command; 320 command.descriptor.type = type; 321 command.descriptor.index = index; 322 command.descriptor.language_id = languageID; 323 command.descriptor.data = data; 324 command.descriptor.length = length; 325 326 if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DESCRIPTOR, &command, 327 sizeof(command)) || command.descriptor.status != B_USB_RAW_STATUS_SUCCESS) 328 return 0; 329 330 return command.descriptor.length; 331 } 332 333 334 uint32 335 BUSBDevice::CountConfigurations() const 336 { 337 return fDescriptor.num_configurations; 338 } 339 340 341 const BUSBConfiguration * 342 BUSBDevice::ConfigurationAt(uint32 index) const 343 { 344 if (index >= fDescriptor.num_configurations || fConfigurations == NULL) 345 return NULL; 346 347 return fConfigurations[index]; 348 } 349 350 351 const BUSBConfiguration * 352 BUSBDevice::ActiveConfiguration() const 353 { 354 if (fConfigurations == NULL) 355 return NULL; 356 357 return fConfigurations[fActiveConfiguration]; 358 } 359 360 361 status_t 362 BUSBDevice::SetConfiguration(const BUSBConfiguration *configuration) 363 { 364 if (!configuration || configuration->Index() >= fDescriptor.num_configurations) 365 return B_BAD_VALUE; 366 367 usb_raw_command command; 368 command.config.config_index = configuration->Index(); 369 370 if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command, 371 sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) 372 return B_ERROR; 373 374 fActiveConfiguration = configuration->Index(); 375 return B_OK; 376 } 377 378 379 ssize_t 380 BUSBDevice::ControlTransfer(uint8 requestType, uint8 request, uint16 value, 381 uint16 index, uint16 length, void *data) const 382 { 383 if (length > 0 && data == NULL) 384 return B_BAD_VALUE; 385 386 usb_raw_command command; 387 command.control.request_type = requestType; 388 command.control.request = request; 389 command.control.value = value; 390 command.control.index = index; 391 command.control.length = length; 392 command.control.data = data; 393 394 if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, 395 sizeof(command)) || command.control.status != B_USB_RAW_STATUS_SUCCESS) 396 return B_ERROR; 397 398 return command.control.length; 399 } 400 401 402 // definition of reserved virtual functions 403 void BUSBDevice::_ReservedUSBDevice1() {}; 404 void BUSBDevice::_ReservedUSBDevice2() {}; 405 void BUSBDevice::_ReservedUSBDevice3() {}; 406 void BUSBDevice::_ReservedUSBDevice4() {}; 407 void BUSBDevice::_ReservedUSBDevice5() {}; 408