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