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 <USBKit.h> 10 #include <usb_raw.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 #include <new> 15 16 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) 25 { 26 memset(&fDescriptor, 0, sizeof(fDescriptor)); 27 28 if (path) 29 SetTo(path); 30 } 31 32 33 BUSBDevice::~BUSBDevice() 34 { 35 Unset(); 36 } 37 38 39 status_t 40 BUSBDevice::InitCheck() 41 { 42 return (fRawFD >= 0 ? B_OK : B_ERROR); 43 } 44 45 46 status_t 47 BUSBDevice::SetTo(const char *path) 48 { 49 if (!path) 50 return B_BAD_VALUE; 51 52 fPath = strdup(path); 53 fRawFD = open(path, O_RDWR | O_CLOEXEC); 54 if (fRawFD < 0) { 55 Unset(); 56 return B_ERROR; 57 } 58 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; 64 } 65 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; 71 } 72 73 fConfigurations = new(std::nothrow) BUSBConfiguration *[ 74 fDescriptor.num_configurations]; 75 if (fConfigurations == NULL) 76 return B_NO_MEMORY; 77 78 for (uint32 i = 0; i < fDescriptor.num_configurations; i++) { 79 fConfigurations[i] = new(std::nothrow) BUSBConfiguration(this, i, 80 fRawFD); 81 } 82 83 return B_OK; 84 } 85 86 87 void 88 BUSBDevice::Unset() 89 { 90 if (fRawFD >= 0) 91 close(fRawFD); 92 fRawFD = -1; 93 94 free(fPath); 95 fPath = NULL; 96 97 delete[] fManufacturerString; 98 delete[] fProductString; 99 delete[] fSerialNumberString; 100 fManufacturerString = fProductString = fSerialNumberString = NULL; 101 102 if (fConfigurations != NULL) { 103 for (int32 i = 0; i < fDescriptor.num_configurations; i++) 104 delete fConfigurations[i]; 105 106 delete[] fConfigurations; 107 fConfigurations = NULL; 108 } 109 110 memset(&fDescriptor, 0, sizeof(fDescriptor)); 111 } 112 113 114 const char * 115 BUSBDevice::Location() const 116 { 117 if (!fPath || strlen(fPath) < 12) 118 return NULL; 119 120 return &fPath[12]; 121 } 122 123 124 bool 125 BUSBDevice::IsHub() const 126 { 127 return fDescriptor.device_class == 0x09; 128 } 129 130 131 uint16 132 BUSBDevice::USBVersion() const 133 { 134 return fDescriptor.usb_version; 135 } 136 137 138 uint8 139 BUSBDevice::Class() const 140 { 141 return fDescriptor.device_class; 142 } 143 144 145 uint8 146 BUSBDevice::Subclass() const 147 { 148 return fDescriptor.device_subclass; 149 } 150 151 152 uint8 153 BUSBDevice::Protocol() const 154 { 155 return fDescriptor.device_protocol; 156 } 157 158 159 uint8 160 BUSBDevice::MaxEndpoint0PacketSize() const 161 { 162 return fDescriptor.max_packet_size_0; 163 } 164 165 166 uint16 167 BUSBDevice::VendorID() const 168 { 169 return fDescriptor.vendor_id; 170 } 171 172 173 uint16 174 BUSBDevice::ProductID() const 175 { 176 return fDescriptor.product_id; 177 } 178 179 180 uint16 181 BUSBDevice::Version() const 182 { 183 return fDescriptor.device_version; 184 } 185 186 187 const char * 188 BUSBDevice::ManufacturerString() const 189 { 190 if (fDescriptor.manufacturer == 0) 191 return ""; 192 193 if (fManufacturerString) 194 return fManufacturerString; 195 196 fManufacturerString = DecodeStringDescriptor(fDescriptor.manufacturer); 197 if (fManufacturerString == NULL) 198 return ""; 199 200 return fManufacturerString; 201 } 202 203 204 const char * 205 BUSBDevice::ProductString() const 206 { 207 if (fDescriptor.product == 0) 208 return ""; 209 210 if (fProductString) 211 return fProductString; 212 213 fProductString = DecodeStringDescriptor(fDescriptor.product); 214 if (fProductString == NULL) 215 return ""; 216 217 return fProductString; 218 } 219 220 221 const char * 222 BUSBDevice::SerialNumberString() const 223 { 224 if (fDescriptor.serial_number == 0) 225 return ""; 226 227 if (fSerialNumberString) 228 return fSerialNumberString; 229 230 fSerialNumberString = DecodeStringDescriptor(fDescriptor.serial_number); 231 if (fSerialNumberString == NULL) 232 return ""; 233 234 return fSerialNumberString; 235 } 236 237 238 const usb_device_descriptor * 239 BUSBDevice::Descriptor() const 240 { 241 return &fDescriptor; 242 } 243 244 245 size_t 246 BUSBDevice::GetStringDescriptor(uint32 index, 247 usb_string_descriptor *descriptor, size_t length) const 248 { 249 if (!descriptor) 250 return B_BAD_VALUE; 251 252 usb_raw_command command; 253 command.string.descriptor = descriptor; 254 command.string.string_index = index; 255 command.string.length = length; 256 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; 260 261 return command.string.length; 262 } 263 264 265 char * 266 BUSBDevice::DecodeStringDescriptor(uint32 index) const 267 { 268 char buffer[300]; 269 usb_string_descriptor *stringDescriptor; 270 stringDescriptor = (usb_string_descriptor *)&buffer; 271 272 size_t stringLength = GetStringDescriptor(index, stringDescriptor, 273 sizeof(buffer) - sizeof(usb_string_descriptor)); 274 275 if (stringLength < 3) 276 return NULL; 277 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; 283 284 for (size_t i = 0; i < stringLength; i++) 285 result[i] = stringDescriptor->string[i * 2]; 286 result[stringLength] = 0; 287 return result; 288 } 289 290 291 size_t 292 BUSBDevice::GetDescriptor(uint8 type, uint8 index, uint16 languageID, 293 void *data, size_t length) const 294 { 295 if (length > 0 && data == NULL) 296 return B_BAD_VALUE; 297 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; 304 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; 308 309 return command.descriptor.length; 310 } 311 312 313 uint32 314 BUSBDevice::CountConfigurations() const 315 { 316 return fDescriptor.num_configurations; 317 } 318 319 320 const BUSBConfiguration * 321 BUSBDevice::ConfigurationAt(uint32 index) const 322 { 323 if (index >= fDescriptor.num_configurations || fConfigurations == NULL) 324 return NULL; 325 326 return fConfigurations[index]; 327 } 328 329 330 const BUSBConfiguration * 331 BUSBDevice::ActiveConfiguration() const 332 { 333 if (fConfigurations == NULL) 334 return NULL; 335 336 return fConfigurations[fActiveConfiguration]; 337 } 338 339 340 status_t 341 BUSBDevice::SetConfiguration(const BUSBConfiguration *configuration) 342 { 343 if (!configuration || configuration->Index() >= fDescriptor.num_configurations) 344 return B_BAD_VALUE; 345 346 usb_raw_command command; 347 command.config.config_index = configuration->Index(); 348 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; 352 353 fActiveConfiguration = configuration->Index(); 354 return B_OK; 355 } 356 357 358 ssize_t 359 BUSBDevice::ControlTransfer(uint8 requestType, uint8 request, uint16 value, 360 uint16 index, uint16 length, void *data) const 361 { 362 if (length > 0 && data == NULL) 363 return B_BAD_VALUE; 364 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; 372 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; 376 377 return command.control.length; 378 } 379 380 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() {}; 387