1// -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*- 2/* 3 * USB C++ bindings 4 * 5 * Copyright (C) 2003 Brad Hards <bradh@frogmouth.net> 6 * 7 * This library is covered by the LGPL, read LICENSE for details. 8 */ 9 10#include <errno.h> 11#include <cstdlib> 12#include <stdio.h> 13 14//remove after debugging 15#include <iostream> 16 17#include "usbpp.h" 18 19namespace USB { 20 Busses::Busses(void) 21 { 22 usb_init(); 23 rescan(); 24 } 25 26 void Busses::rescan(void) 27 { 28 struct usb_bus *bus; 29 struct usb_device *dev; 30 Bus *this_Bus; 31 Device *this_Device; 32 Configuration *this_Configuration; 33 Interface *this_Interface; 34 AltSetting *this_AltSetting; 35 Endpoint *this_Endpoint; 36 int i, j, k, l; 37 38 usb_find_busses(); 39 usb_find_devices(); 40 41 for (bus = usb_get_busses(); bus; bus = bus->next) { 42 std::string dirName(bus->dirname); 43 44 this_Bus = new Bus; 45 this_Bus->setDirectoryName(dirName); 46 push_back(this_Bus); 47 48 for (dev = bus->devices; dev; dev = dev->next) { 49 std::string buf, fileName(dev->filename); 50 usb_dev_handle *dev_handle; 51 int ret; 52 53 this_Device = new Device; 54 this_Device->setFileName(fileName); 55 this_Device->setDescriptor(dev->descriptor); 56 57 dev_handle = usb_open(dev); 58 59 if (dev_handle) { 60 this_Device->setDevHandle(dev_handle); 61 62 if (dev->descriptor.iManufacturer) { 63 ret = this_Device->string(buf, dev->descriptor.iManufacturer); 64 if (ret > 0) 65 this_Device->setVendor(buf); 66 } 67 68 if (dev->descriptor.iProduct) { 69 ret = this_Device->string(buf, dev->descriptor.iProduct); 70 if (ret > 0) 71 this_Device->setProduct(buf); 72 } 73 74 if (dev->descriptor.iSerialNumber) { 75 ret = this_Device->string(buf, dev->descriptor.iSerialNumber); 76 if (ret > 0) 77 this_Device->setSerialNumber(buf); 78 } 79 } 80 81 this_Bus->push_back(this_Device); 82 83 for (i = 0; i < this_Device->numConfigurations(); i++) { 84 this_Configuration = new Configuration; 85 this_Configuration->setDescriptor(dev->config[i]); 86 this_Device->push_back(this_Configuration); 87 88 for (j = 0; j < this_Configuration->numInterfaces(); j ++) { 89 this_Interface = new Interface; 90 this_Interface->setNumAltSettings(dev->config[i].interface[j].num_altsetting); 91 this_Interface->setParent(this_Device); 92 this_Interface->setInterfaceNumber(j); 93 this_Configuration->push_back(this_Interface); 94 95 for (k = 0; k < this_Interface->numAltSettings(); k ++) { 96 this_AltSetting = new AltSetting; 97 this_AltSetting->setDescriptor(dev->config[i].interface[j].altsetting[k]); 98 this_Interface->push_back(this_AltSetting); 99 100 for (l = 0; l < this_AltSetting->numEndpoints(); l++) { 101 this_Endpoint = new Endpoint; 102 this_Endpoint->setDescriptor(dev->config[i].interface[j].altsetting[k].endpoint[l]); 103 this_Endpoint->setParent(this_Device); 104 this_AltSetting->push_back(this_Endpoint); 105 } 106 } 107 } 108 } 109 } 110 } 111 } 112 113 std::list<Device *> Busses::match(u_int8_t class_code) 114 { 115 std::list<Device *> match_list; 116 USB::Bus *bus; 117 std::list<USB::Bus *>::const_iterator biter; 118 119 for (biter = begin(); biter != end(); biter++) { 120 USB::Device *device; 121 std::list<USB::Device *>::const_iterator diter; 122 bus = *biter; 123 124 for (diter = bus->begin(); diter != bus->end(); diter++) { 125 device = *diter; 126 if (device->devClass() == class_code) 127 match_list.push_back(device); 128 } 129 } 130 return match_list; 131 } 132 133 std::list<Device *> Busses::match(DeviceIDList devList) 134 { 135 std::list<Device *> match_list; 136 USB::Bus *bus; 137 std::list<USB::Bus *>::const_iterator biter; 138 139 for (biter = begin(); biter != end(); biter++) { 140 USB::Device *device; 141 std::list<USB::Device *>::const_iterator diter; 142 143 bus = *biter; 144 for (diter = bus->begin(); diter != bus->end(); diter++) { 145 DeviceIDList::iterator it; 146 147 device = *diter; 148 149 for (it = devList.begin(); it != devList.end(); it++) { 150 if (device->idVendor() == (*it).vendor() && 151 device->idProduct() == (*it).product()) 152 match_list.push_back(device); 153 } 154 } 155 } 156 return match_list; 157 } 158 159 std::string Bus::directoryName(void) 160 { 161 return m_directoryName; 162 } 163 164 void Bus::setDirectoryName(std::string directoryName) 165 { 166 m_directoryName = directoryName; 167 } 168 169 Device::~Device(void) 170 { 171 usb_close(m_handle); 172 } 173 174 std::string Device::fileName(void) 175 { 176 return m_fileName; 177 } 178 179 int Device::string(std::string &buf, int index, u_int16_t langID) 180 { 181 int retval; 182 char tmpBuff[256]; 183 184 if (0 == langID) { 185 /* we want the first lang ID available, so find out what it is */ 186 retval = usb_get_string(m_handle, 0, 0, tmpBuff, sizeof(tmpBuff)); 187 if (retval < 0) 188 return retval; 189 190 if (retval < 4 || tmpBuff[1] != USB_DT_STRING) 191 return -EIO; 192 193 langID = tmpBuff[2] | (tmpBuff[3] << 8); 194 } 195 196 retval = usb_get_string(m_handle, index, langID, tmpBuff, sizeof(tmpBuff)); 197 198 if (retval < 0) 199 return retval; 200 201 if (tmpBuff[1] != USB_DT_STRING) 202 return -EIO; 203 204 if (tmpBuff[0] > retval) 205 return -EFBIG; 206 207 /* FIXME: Handle unicode? */ 208#if 0 209 if (retval > 0) { 210 std::string.setUnicode((unsigned char *)&tmpBuff[2], tmpBuff[0] / 2 - 1); 211 } 212#endif 213 return retval; 214 } 215 216 struct usb_dev_handle *Device::handle(void) 217 { 218 return m_handle; 219 } 220 221#ifdef USE_UNTESTED_LIBUSBPP_METHODS 222 int Device::reset(void) 223 { 224 return usb_reset(handle()); 225 } 226 227 int Device::setConfiguration(int configurationNumber) 228 { 229 return usb_set_configuration(handle(), configurationNumber); 230 } 231#endif /* USE_UNTESTED_LIBUSBPP_METHODS */ 232 233 u_int16_t Device::idVendor(void) 234 { 235 return m_descriptor.idVendor; 236 } 237 238 u_int16_t Device::idProduct(void) 239 { 240 return m_descriptor.idProduct; 241 } 242 243 u_int16_t Device::idRevision(void) 244 { 245 return m_descriptor.bcdDevice; 246 } 247 248 u_int8_t Device::devClass(void) 249 { 250 return m_descriptor.bDeviceClass; 251 } 252 253 u_int8_t Device::devSubClass(void) 254 { 255 return m_descriptor.bDeviceSubClass; 256 } 257 258 u_int8_t Device::devProtocol(void) 259 { 260 return m_descriptor.bDeviceProtocol; 261 } 262 263 std::string Device::Vendor(void) 264 { 265 return m_Vendor; 266 } 267 268 std::string Device::Product(void) 269 { 270 return m_Product; 271 } 272 273 std::string Device::SerialNumber(void) 274 { 275 return m_SerialNumber; 276 } 277 278 void Device::setVendor(std::string vendor) 279 { 280 m_Vendor = vendor; 281 } 282 283 void Device::setDevHandle(struct usb_dev_handle *device) 284 { 285 m_handle = device; 286 } 287 288 void Device::setProduct(std::string product) 289 { 290 m_Product = product; 291 } 292 293 void Device::setSerialNumber(std::string serialnumber) 294 { 295 m_SerialNumber = serialnumber; 296 } 297 298 u_int8_t Device::numConfigurations(void) 299 { 300 return m_descriptor.bNumConfigurations; 301 } 302 303 void Device::setFileName(std::string fileName) 304 { 305 m_fileName = fileName; 306 } 307 308 void Device::setDescriptor(struct usb_device_descriptor descriptor) 309 { 310 m_descriptor = descriptor; 311 } 312 313 Configuration *Device::firstConfiguration(void) 314 { 315 iter = begin(); 316 return *iter++; 317 } 318 319 Configuration *Device::nextConfiguration(void) 320 { 321 if (iter == end()) 322 return NULL; 323 324 return *iter++; 325 } 326 327 Configuration *Device::lastConfiguration(void) 328 { 329 return back(); 330 } 331 332 int Device::controlTransfer(u_int8_t requestType, u_int8_t request, 333 u_int16_t value, u_int16_t index, u_int16_t length, 334 unsigned char *payload, int timeout) 335 { 336 return usb_control_msg(m_handle, requestType, request, value, index, (char *)payload, length, timeout); 337 } 338 339 u_int8_t Configuration::numInterfaces(void) 340 { 341 return m_NumInterfaces; 342 } 343 344 void Configuration::setDescriptor(struct usb_config_descriptor descriptor) 345 { 346 m_Length = descriptor.bLength; 347 m_DescriptorType = descriptor.bDescriptorType; 348 m_TotalLength = descriptor.wTotalLength; 349 m_NumInterfaces = descriptor.bNumInterfaces; 350 m_ConfigurationValue = descriptor.bConfigurationValue; 351 m_Configuration = descriptor.iConfiguration; 352 m_Attributes = descriptor.bmAttributes; 353 m_MaxPower = descriptor.MaxPower; 354 } 355 356 void Configuration::dumpDescriptor(void) 357 { 358 printf(" wTotalLength: %d\n", m_TotalLength); 359 printf(" bNumInterfaces: %d\n", m_NumInterfaces); 360 printf(" bConfigurationValue: %d\n", m_ConfigurationValue); 361 printf(" iConfiguration: %d\n", m_Configuration); 362 printf(" bmAttributes: %02xh\n", m_Attributes); 363 printf(" MaxPower: %d\n", m_MaxPower); 364 } 365 366 Interface *Configuration::firstInterface(void) 367 { 368 iter = begin(); 369 return *iter++; 370 } 371 372 Interface *Configuration::nextInterface(void) 373 { 374 if (iter == end()) 375 return NULL; 376 377 return *iter++; 378 } 379 380 Interface *Configuration::lastInterface(void) 381 { 382 return back(); 383 } 384 385#ifdef LIBUSB_HAS_GET_DRIVER_NP 386 int Interface::driverName(std::string &driver) 387 { 388 int retval; 389 char tmpString[256]; 390 391 retval = usb_get_driver_np(m_parent->handle(), m_interfaceNumber, tmpString, sizeof(tmpString)); 392 if (retval == 0) { 393 std::string buf(tmpString); 394 395 driver = buf; 396 } 397 return retval; 398 } 399#endif 400 401#ifdef USE_UNTESTED_LIBUSBPP_METHODS 402 int Interface::claim(void) 403 { 404 return usb_claim_interface(m_parent->handle(), m_interfaceNumber); 405 } 406 407 int Interface::release(void) 408 { 409 return usb_claim_interface(m_parent->handle(), m_interfaceNumber); 410 } 411 412 int Interface::setAltSetting(int altSettingNumber) 413 { 414 return usb_set_altinterface(m_parent->handle(), altSettingNumber); 415 } 416#endif /* USE_UNTESTED_LIBUSBPP_METHODS */ 417 418 u_int8_t Interface::numAltSettings(void) 419 { 420 return m_numAltSettings; 421 } 422 423 void Interface::setNumAltSettings(u_int8_t num_altsetting) 424 { 425 m_numAltSettings = num_altsetting; 426 } 427 428 void Interface::setInterfaceNumber(int interfaceNumber) 429 { 430 m_interfaceNumber = interfaceNumber; 431 } 432 433 void Interface::setParent(Device *parent) 434 { 435 m_parent = parent; 436 } 437 438 AltSetting *Interface::firstAltSetting(void) 439 { 440 iter = begin(); 441 return *iter++; 442 } 443 444 AltSetting *Interface::nextAltSetting(void) 445 { 446 if (iter == end()) 447 return NULL; 448 449 return *iter++; 450 } 451 452 AltSetting *Interface::lastAltSetting(void) 453 { 454 return back(); 455 } 456 457 void AltSetting::setDescriptor(struct usb_interface_descriptor descriptor) 458 { 459 m_Length = descriptor.bLength; 460 m_DescriptorType = descriptor.bDescriptorType; 461 m_InterfaceNumber = descriptor.bInterfaceNumber; 462 m_AlternateSetting = descriptor.bAlternateSetting; 463 m_NumEndpoints = descriptor.bNumEndpoints; 464 m_InterfaceClass = descriptor.bInterfaceClass; 465 m_InterfaceSubClass = descriptor.bInterfaceSubClass; 466 m_InterfaceProtocol = descriptor.bInterfaceProtocol; 467 m_Interface = descriptor.iInterface; 468 } 469 470 void AltSetting::dumpDescriptor(void) 471 { 472 printf(" bInterfaceNumber: %d\n", m_InterfaceNumber); 473 printf(" bAlternateSetting: %d\n", m_AlternateSetting); 474 printf(" bNumEndpoints: %d\n", m_NumEndpoints); 475 printf(" bInterfaceClass: %d\n", m_InterfaceClass); 476 printf(" bInterfaceSubClass: %d\n", m_InterfaceSubClass); 477 printf(" bInterfaceProtocol: %d\n", m_InterfaceProtocol); 478 printf(" iInterface: %d\n", m_Interface); 479 } 480 481 Endpoint *AltSetting::firstEndpoint(void) 482 { 483 iter = begin(); 484 return *iter++; 485 } 486 487 Endpoint *AltSetting::nextEndpoint(void) 488 { 489 if (iter == end()) 490 return NULL; 491 492 return *iter++; 493 } 494 495 Endpoint *AltSetting::lastEndpoint(void) 496 { 497 return back(); 498 } 499 500 u_int8_t AltSetting::numEndpoints(void) 501 { 502 return m_NumEndpoints; 503 } 504 505 void Endpoint::setDescriptor(struct usb_endpoint_descriptor descriptor) 506 { 507 m_EndpointAddress = descriptor.bEndpointAddress; 508 m_Attributes = descriptor.bmAttributes; 509 m_MaxPacketSize = descriptor.wMaxPacketSize; 510 m_Interval = descriptor.bInterval; 511 m_Refresh = descriptor.bRefresh; 512 m_SynchAddress = descriptor.bSynchAddress; 513 } 514 515 void Endpoint::setParent(Device *parent) 516 { 517 m_parent = parent; 518 } 519 520#ifdef USE_UNTESTED_LIBUSBPP_METHODS 521 int Endpoint::bulkWrite(unsigned char *message, int timeout) 522 { 523 return usb_bulk_write(m_parent->handle(), m_EndpointAddress, message.data(), 524 message.size(), timeout); 525 } 526 527 int Endpoint::bulkRead(int length, unsigned char *message, int timeout) 528 { 529 char *buf; 530 int res; 531 532 buf = (char *)malloc(length); 533 res = usb_bulk_read(m_parent->handle(), m_EndpointAddress, buf, length, timeout); 534 535 if (res > 0) { 536 message.resize(length); 537 message.duplicate(buf, res); 538 } 539 540 return res; 541 } 542 543 int Endpoint::reset(void) 544 { 545 return usb_resetep(m_parent->handle(), m_EndpointAddress); 546 } 547 548 int Endpoint::clearHalt(void) 549 { 550 return usb_clear_halt(m_parent->handle(), m_EndpointAddress); 551 } 552 553#endif /* USE_UNTESTED_LIBUSBPP_METHODS */ 554 555 void Endpoint::dumpDescriptor(void) 556 { 557 printf(" bEndpointAddress: %02xh\n", m_EndpointAddress); 558 printf(" bmAttributes: %02xh\n", m_Attributes); 559 printf(" wMaxPacketSize: %d\n", m_MaxPacketSize); 560 printf(" bInterval: %d\n", m_Interval); 561 printf(" bRefresh: %d\n", m_Refresh); 562 printf(" bSynchAddress: %d\n", m_SynchAddress); 563 } 564 565 DeviceID::DeviceID(u_int16_t vendor, u_int16_t product) 566 { 567 m_vendor = vendor; 568 m_product = product; 569 } 570 571 u_int16_t DeviceID::vendor(void) 572 { 573 return m_vendor; 574 } 575 576 u_int16_t DeviceID::product(void) 577 { 578 return m_product; 579 } 580} 581 582