Changeset 15401 in vbox for trunk/src/VBox/Main
- Timestamp:
- Dec 12, 2008 10:05:34 PM (16 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/HostHardwareLinux.h
r14991 r15401 7 7 8 8 /* 9 * Copyright (C) 200 6-2007Sun Microsystems, Inc.9 * Copyright (C) 2008 Sun Microsystems, Inc. 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 * additional information or have any questions. 22 22 */ 23 24 #ifndef ____H_HOSTHARDWARELINUX 25 # define ____H_HOSTHARDWARELINUX 23 26 24 27 #include <iprt/err.h> … … 111 114 typedef VBoxMainDriveInfo::DriveInfo DriveInfo; 112 115 116 /** 117 * Class for probing and returning information about host USB devices 118 */ 119 class VBoxMainUSBDeviceInfo 120 { 121 public: 122 /** Structure describing a host USB device */ 123 struct USBDeviceInfo 124 { 125 /** The device node of the device. */ 126 std::string mDevice; 127 /** The sysfs path of the device. */ 128 std::string mSysfsPath; 129 /** Type for the list of interfaces. */ 130 typedef std::vector <std::string> InterfaceList; 131 /** The sysfs paths of the device's interfaces. */ 132 InterfaceList mInterfaces; 133 134 /** Constructors */ 135 USBDeviceInfo (std::string aDevice, std::string aSysfsPath) 136 : mDevice (aDevice), mSysfsPath (aSysfsPath) {} 137 USBDeviceInfo () {} 138 }; 139 140 /** List (resp vector) holding drive information */ 141 typedef std::vector <USBDeviceInfo> DeviceInfoList; 142 143 /** 144 * Search for host USB devices and rebuild the list, which remains empty 145 * until the first time it is called. 146 * @returns iprt status code 147 */ 148 int UpdateDevices (); 149 150 /** Get the first element in the list of USB devices. */ 151 DeviceInfoList::const_iterator DevicesBegin() 152 { 153 return mDeviceList.begin(); 154 } 155 156 /** Get the last element in the list of USB devices. */ 157 DeviceInfoList::const_iterator DevicesEnd() 158 { 159 return mDeviceList.end(); 160 } 161 162 private: 163 /** The list of currently available USB devices */ 164 DeviceInfoList mDeviceList; 165 }; 166 167 typedef VBoxMainUSBDeviceInfo::DeviceInfoList USBDeviceInfoList; 168 typedef VBoxMainUSBDeviceInfo::USBDeviceInfo USBDeviceInfo; 169 typedef VBoxMainUSBDeviceInfo::USBDeviceInfo::InterfaceList USBInterfaceList; 170 171 class VBoxMainHotplugWaiter 172 { 173 /** Opaque context struct. */ 174 struct Context; 175 176 /** Opaque waiter context. */ 177 Context *mContext; 178 public: 179 /** Constructor */ 180 VBoxMainHotplugWaiter (void); 181 /** Destructor. */ 182 ~VBoxMainHotplugWaiter (void); 183 /** 184 * Wait for a hotplug event. 185 * 186 * @returns VINF_SUCCESS if an event occurred or if Interrupt() was called. 187 * @returns VERR_TRY_AGAIN if the wait failed but this might (!) be a 188 * temporary failure. 189 * @returns VERR_NOT_SUPPORTED if the wait failed and will definitely not 190 * succeed if retried. 191 * @returns Possibly other iprt status codes otherwise. 192 */ 193 int Wait (void); 194 /** Interrupts an active wait. */ 195 void Interrupt (void); 196 }; 197 198 #endif /* ____H_HOSTHARDWARELINUX */ 199 -
trunk/src/VBox/Main/include/vbox-dbus.h
r15058 r15401 29 29 #define LIB_DBUS_1_3 "libdbus-1.so.3" 30 30 31 /** Types from the dbus header files which we need. These are taken more or less32 31 /** Types and defines from the dbus header files which we need. These are 32 * taken more or less verbatim from the DBus public interface header files. */ 33 33 struct DBusError 34 34 { … … 68 68 typedef struct DBusMessageIter DBusMessageIter; 69 69 70 /** Defines from the dbus header files which we need. These are taken more or less71 verbatim from the DBus public interface header files. */72 70 #define DBUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory" 73 71 #define DBUS_TYPE_STRING ((int) 's') 74 72 #define DBUS_TYPE_ARRAY ((int) 'a') 75 73 #define DBUS_TYPE_DICT_ENTRY ((int) 'e') 74 75 typedef enum 76 { 77 DBUS_HANDLER_RESULT_HANDLED, /**< Message has had its effect - no need 78 to run more handlers. */ 79 DBUS_HANDLER_RESULT_NOT_YET_HANDLED, /**< Message has not had any effect - see 80 if other handlers want it. */ 81 DBUS_HANDLER_RESULT_NEED_MEMORY /**< Need more memory in order to return 82 #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try 83 again later with more memory. */ 84 } DBusHandlerResult; 85 86 typedef DBusHandlerResult (*DBusHandleMessageFunction) (DBusConnection *, 87 DBusMessage *, void *); 88 typedef void (*DBusFreeFunction) (void *); 76 89 77 90 /** The following are the symbols which we need from libdbus-1. */ … … 100 113 extern void (*dbus_message_iter_get_basic) (DBusMessageIter *, void *); 101 114 extern dbus_bool_t (*dbus_message_iter_next) (DBusMessageIter *); 115 extern dbus_bool_t (*dbus_connection_add_filter) (DBusConnection *, DBusHandleMessageFunction, 116 void *, DBusFreeFunction); 117 extern void (*dbus_connection_remove_filter) (DBusConnection *, DBusHandleMessageFunction, 118 void *); 119 extern dbus_bool_t (*dbus_connection_read_write_dispatch) (DBusConnection *, int); 120 extern dbus_bool_t (*dbus_message_is_signal) (DBusMessage *, const char *, const char *); 102 121 103 122 extern bool VBoxDBusCheckPresence(void); -
trunk/src/VBox/Main/linux/HostHardwareLinux.cpp
r15058 r15401 7 7 8 8 /* 9 * Copyright (C) 200 6-2007Sun Microsystems, Inc.9 * Copyright (C) 2008 Sun Microsystems, Inc. 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 62 62 63 63 /******************************************************************************* 64 * Defines and Typedefs *64 * Typedefs and Defines * 65 65 *******************************************************************************/ 66 66 67 typedef VBoxMainDriveInfo::DriveInfoList DriveInfoList;68 typedef VBoxMainDriveInfo::DriveInfo DriveInfo; 67 enum { DBUS_POLL_TIMEOUT = 2000 /* ms */ }; 68 69 69 70 70 static bool validateDevice(const char *deviceNode, bool isDVD); … … 73 73 static int getDVDInfoFromMTab(char *mountTable, DriveInfoList *pList); 74 74 #ifdef VBOX_WITH_DBUS 75 static int halInit(DBusConnection **ppConnection);76 75 /* This must be extern to be used in the RTMemAutoPtr template */ 77 76 extern void halShutdown (DBusConnection *pConnection); 77 78 static int halInit(RTMemAutoPtr <DBusConnection, halShutdown> *pConnection); 78 79 static int halFindDeviceStringMatch (DBusConnection *pConnection, 79 80 const char *pszKey, const char *pszValue, 80 DBusMessage **ppMessage);81 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage); 81 82 static int halGetPropertyStrings (DBusConnection *pConnection, 82 83 const char *pszUdi, size_t cKeys, 83 84 const char **papszKeys, char **papszValues, 84 DBusMessage **ppMessage);85 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage); 85 86 static int getDriveInfoFromHal(DriveInfoList *pList, bool isDVD, 86 87 bool *pfSuccess); 88 static int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess); 89 static int getUSBInterfacesFromHal(std::vector <std::string> *pList, 90 const char *pcszUdi, bool *pfSuccess); 91 static DBusHandlerResult dbusFilterFunction (DBusConnection *pConnection, 92 DBusMessage *pMessage, void *pvUser); 87 93 #endif /* VBOX_WITH_DBUS */ 88 94 … … 182 188 LogFlowThisFunc (("rc=%Rrc\n", rc)); 183 189 return rc; 190 } 191 192 /** 193 * Updates the list of host USB devices. 194 * 195 * @returns iprt status code 196 */ 197 int VBoxMainUSBDeviceInfo::UpdateDevices () 198 { 199 LogFlowThisFunc (("entered\n")); 200 int rc = VINF_SUCCESS; 201 bool success = false; /* Have we succeeded in finding anything yet? */ 202 try 203 { 204 mDeviceList.clear(); 205 #if defined(RT_OS_LINUX) 206 #ifdef VBOX_WITH_DBUS 207 if (RT_SUCCESS (rc) && VBoxDBusCheckPresence() && (!success || testing())) 208 rc = getUSBDeviceInfoFromHal(&mDeviceList, &success); 209 #endif /* VBOX_WITH_DBUS defined */ 210 #endif /* RT_OS_LINUX */ 211 } 212 catch (std::bad_alloc) 213 { 214 rc = VERR_NO_MEMORY; 215 } 216 LogFlowThisFunc (("rc=%Rrc\n", rc)); 217 return rc; 218 } 219 220 struct VBoxMainHotplugWaiter::Context 221 { 222 #if defined RT_OS_LINUX && defined VBOX_WITH_DBUS 223 /** The connection to DBus */ 224 RTMemAutoPtr <DBusConnection, halShutdown> mConnection; 225 /** Semaphore which is set when a device is hotplugged and reset when 226 * it is read. */ 227 bool mTriggered; 228 /** A flag to say that we wish to interrupt the current wait. */ 229 bool mInterrupt; 230 #endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */ 231 }; 232 233 /** Constructor */ 234 VBoxMainHotplugWaiter::VBoxMainHotplugWaiter () 235 { 236 #if defined RT_OS_LINUX && defined VBOX_WITH_DBUS 237 int rc = VINF_SUCCESS; 238 239 mContext = new Context; 240 for (unsigned i = 0; RT_SUCCESS(rc) && i < 5 && !mContext->mConnection; ++i) 241 { 242 rc = halInit (&mContext->mConnection); 243 } 244 if (!mContext->mConnection) 245 rc = VERR_NOT_SUPPORTED; 246 if ( RT_SUCCESS (rc) 247 && !dbus_connection_add_filter (mContext->mConnection.get(), 248 dbusFilterFunction, 249 &mContext->mTriggered, NULL)) 250 rc = VERR_NO_MEMORY; 251 if (RT_FAILURE (rc)) 252 mContext->mConnection.reset(); 253 #endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */ 254 } 255 256 /** Destructor */ 257 VBoxMainHotplugWaiter::~VBoxMainHotplugWaiter () 258 { 259 #if defined RT_OS_LINUX && defined VBOX_WITH_DBUS 260 if (!!mContext->mConnection) 261 dbus_connection_remove_filter (mContext->mConnection.get(), dbusFilterFunction, 262 &mContext->mTriggered); 263 delete mContext; 264 #endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */ 265 } 266 267 /** 268 * Wait for a hotplug event. 269 * 270 * @returns VINF_SUCCESS if an event occurred or if Exit() was called. 271 * @returns VERR_TRY_AGAIN if something failed at the DBus level. 272 * @returns VERR_NOT_SUPPORTED if the service could not be contacted. 273 * @returns Possibly other iprt status codes otherwise. 274 */ 275 int VBoxMainHotplugWaiter::Wait() 276 { 277 int rc = VINF_SUCCESS; 278 #if defined RT_OS_LINUX && defined VBOX_WITH_DBUS 279 if (!mContext->mConnection) 280 rc = VERR_NOT_SUPPORTED; 281 bool connected = true; 282 mContext->mTriggered = false; 283 mContext->mInterrupt = false; 284 while ( RT_SUCCESS (rc) && connected && !mContext->mTriggered 285 && !mContext->mInterrupt) 286 connected = dbus_connection_read_write_dispatch (mContext->mConnection.get(), 287 DBUS_POLL_TIMEOUT); 288 if (!connected) 289 rc = VERR_TRY_AGAIN; 290 #else /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS) */ 291 rc = VERR_NOT_IMPLEMENTED; 292 #endif /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS) */ 293 return rc; 294 } 295 296 void VBoxMainHotplugWaiter::Interrupt() 297 { 298 #if defined RT_OS_LINUX && defined VBOX_WITH_DBUS 299 mContext->mInterrupt = true; 300 #endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */ 184 301 } 185 302 … … 429 546 */ 430 547 /* static */ 431 int halInit ( DBusConnection **ppConnection)432 { 433 AssertReturn(VALID_PTR (p pConnection), VERR_INVALID_POINTER);434 LogFlowFunc (("p pConnection=%p\n", ppConnection));548 int halInit (RTMemAutoPtr <DBusConnection, halShutdown> *pConnection) 549 { 550 AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER); 551 LogFlowFunc (("pConnection=%p\n", pConnection)); 435 552 int rc = VINF_SUCCESS; 436 553 bool halSuccess = true; … … 459 576 if (dbusError.HasName (DBUS_ERROR_NO_MEMORY)) 460 577 rc = VERR_NO_MEMORY; 461 *ppConnection = halSuccess ? dbusConnection.release() : NULL; 462 LogFlowFunc(("rc=%Rrc, *ppConnection=%p\n", rc, *ppConnection)); 578 if (halSuccess) 579 *pConnection = dbusConnection.release(); 580 LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get())); 463 581 dbusError.FlowLog(); 464 582 return rc; … … 489 607 /** 490 608 * Find the UDIs of hal entries that contain Key=Value property. 491 * @returns iprt status code 609 * @returns iprt status code. If a non-fatal error occurs, we return success 610 * but reset pMessage to NULL. 492 611 * @param pConnection an initialised connection DBus 493 612 * @param pszKey the property key 494 613 * @param pszValue the property value 495 * @param ppMessage where to store the return DBus message. This must be 496 * parsed to get at the UDIs. NOT optional. The caller 497 * is responsible for freeing this. 614 * @param pMessage where to store the return DBus message. This must be 615 * parsed to get at the UDIs. NOT optional. 498 616 */ 499 617 /* static */ 500 618 int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey, 501 const char *pszValue, DBusMessage **ppMessage) 619 const char *pszValue, 620 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage) 502 621 { 503 622 AssertReturn( VALID_PTR (pConnection) && VALID_PTR (pszKey) 504 && VALID_PTR (pszValue) && VALID_PTR (p pMessage),623 && VALID_PTR (pszValue) && VALID_PTR (pMessage), 505 624 VERR_INVALID_POINTER); 506 LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, p pMessage=%p\n",507 pConnection, pszKey, pszValue, p pMessage));508 int rc = VINF_SUCCESS; 509 bool halSuccess = true; 625 LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMessage=%p\n", 626 pConnection, pszKey, pszValue, pMessage)); 627 int rc = VINF_SUCCESS; /* We set this to failure on fatal errors. */ 628 bool halSuccess = true; /* We set this to false to abort the operation. */ 510 629 autoDBusError dbusError; 511 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message; 512 DBusMessage *pReply = NULL;630 631 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply; 513 632 if (halSuccess && RT_SUCCESS (rc)) 514 633 { … … 526 645 dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszKey); 527 646 dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszValue); 528 pReply = dbus_connection_send_with_reply_and_block (pConnection,647 reply = dbus_connection_send_with_reply_and_block (pConnection, 529 648 message.get(), -1, 530 649 &dbusError.get()); 531 if ( pReply == NULL)532 halSuccess = false; 533 } 534 *p pMessage = pReply;535 LogFlowFunc (("rc=%Rrc, *p pMessage=%p\n", rc, *ppMessage));650 if (!reply) 651 halSuccess = false; 652 } 653 *pMessage = reply.release (); 654 LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get())); 536 655 dbusError.FlowLog(); 537 656 return rc; … … 541 660 * Read a set of string properties for a device. If some of the properties are 542 661 * not of type DBUS_TYPE_STRING then a NULL pointer will be returned for them. 543 * @returns iprt status code 662 * @returns iprt status code. If the operation failed for non-fatal reasons 663 * then we return success and leave pMessage untouched - reset it 664 * before the call to detect this. 544 665 * @param pConnection an initialised connection DBus 545 666 * @param pszUdi the Udi of the device … … 550 671 * returned in @a ppMessage is freed. Undefined if 551 672 * the message is NULL. 552 * @param p pMessagewhere to store the return DBus message. The caller673 * @param pMessage where to store the return DBus message. The caller 553 674 * is responsible for freeing this once they have 554 675 * finished with the value strings. NOT optional. … … 557 678 int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi, 558 679 size_t cProps, const char **papszKeys, 559 char **papszValues, DBusMessage **ppMessage) 680 char **papszValues, 681 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage) 560 682 { 561 683 AssertReturn( VALID_PTR (pConnection) && VALID_PTR (pszUdi) 562 684 && VALID_PTR (papszKeys) && VALID_PTR (papszValues) 563 && VALID_PTR (p pMessage),685 && VALID_PTR (pMessage), 564 686 VERR_INVALID_POINTER); 565 LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, p pMessage=%p\n",566 pConnection, pszUdi, cProps, papszKeys, papszValues, p pMessage));567 int rc = VINF_SUCCESS; 568 bool halSuccess = true; 687 LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, pMessage=%p\n", 688 pConnection, pszUdi, cProps, papszKeys, papszValues, pMessage)); 689 int rc = VINF_SUCCESS; /* We set this to failure on fatal errors. */ 690 bool halSuccess = true; /* We set this to false to abort the operation. */ 569 691 autoDBusError dbusError; 692 570 693 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply; 571 694 DBusMessageIter iterGet, iterProps, iterKey, iterValue; … … 574 697 for (size_t i = 0; i < cProps; ++i) 575 698 papszValues[i] = NULL; 699 700 /* Send a GetAllProperties message to hald */ 576 701 message = dbus_message_new_method_call ("org.freedesktop.Hal", pszUdi, 577 702 "org.freedesktop.Hal.Device", … … 587 712 halSuccess = false; 588 713 } 714 715 /* Parse the reply */ 589 716 if (halSuccess && RT_SUCCESS (rc)) 590 717 { … … 596 723 if (halSuccess && RT_SUCCESS (rc)) 597 724 dbus_message_iter_recurse (&iterGet, &iterProps); 725 /* Go through all entries in the reply and see if any match our keys. */ 598 726 while ( halSuccess && RT_SUCCESS (rc) 599 727 && dbus_message_iter_get_arg_type (&iterProps) … … 606 734 dbus_message_iter_next (&iterEntry); 607 735 dbus_message_iter_recurse (&iterEntry, &iterValue); 736 /* Fill in any matches. */ 608 737 for (size_t i = 0; i < cProps; ++i) 609 738 if (strcmp (pszKey, papszKeys[i]) == 0) … … 615 744 } 616 745 if (RT_SUCCESS (rc) && halSuccess) 617 *ppMessage = reply.release(); 618 else 619 *ppMessage = NULL; 746 *pMessage = reply.release(); 620 747 if (dbusError.HasName (DBUS_ERROR_NO_MEMORY)) 621 622 LogFlowFunc (("rc=%Rrc, *p pMessage=%p\n", rc, *ppMessage));748 rc = VERR_NO_MEMORY; 749 LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get())); 623 750 dbusError.FlowLog(); 624 751 return rc; … … 642 769 VERR_INVALID_POINTER); 643 770 LogFlowFunc (("pList=%p, isDVD=%d, pfSuccess=%p\n", pList, isDVD, pfSuccess)); 644 DBusConnection *pConnection; 771 int rc = VINF_SUCCESS; /* We set this to failure on fatal errors. */ 772 bool halSuccess = true; /* We set this to false to abort the operation. */ 645 773 autoDBusError dbusError; 646 DBusMessage *pReply; 774 647 775 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet; 776 RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection; 648 777 DBusMessageIter iterFind, iterUdis; 649 bool halSuccess = true; /* Did something go wrong with hal or DBus? */ 650 int rc = VINF_SUCCESS; /* Did a fatal error occur? */ 651 652 rc = halInit (&pConnection); 653 RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection; 654 dbusConnection = pConnection; 778 779 rc = halInit (&dbusConnection); 655 780 if (!dbusConnection) 656 781 halSuccess = false; 657 782 if (halSuccess && RT_SUCCESS (rc)) 658 783 { 659 rc = halFindDeviceStringMatch (pConnection, "storage.drive_type", 660 isDVD ? "cdrom" : "floppy", &pReply); 661 replyFind = pReply; 784 rc = halFindDeviceStringMatch (dbusConnection.get(), "storage.drive_type", 785 isDVD ? "cdrom" : "floppy", &replyFind); 662 786 if (!replyFind) 663 787 halSuccess = false; … … 681 805 { "block.device", "info.product", "info.vendor" }; 682 806 char *papszValues[RT_ELEMENTS (papszKeys)]; 683 rc = halGetPropertyStrings (pConnection, pszUdi, RT_ELEMENTS (papszKeys), 684 papszKeys, papszValues, &pReply); 685 replyGet = pReply; 807 rc = halGetPropertyStrings (dbusConnection.get(), pszUdi, RT_ELEMENTS (papszKeys), 808 papszKeys, papszValues, &replyGet); 686 809 std::string description; 687 810 const char *pszDevice = papszValues[0], *pszProduct = papszValues[1], 688 811 *pszVendor = papszValues[2]; 689 if (!!replyGet && pszDevice) 812 if (!!replyGet && pszDevice == NULL) 813 halSuccess = false; 814 if (!!replyGet && pszDevice != NULL) 690 815 { 691 816 if ((pszVendor != NULL) && (pszVendor[0] != '\0')) … … 697 822 } 698 823 if (dbusError.HasName (DBUS_ERROR_NO_MEMORY)) 699 824 rc = VERR_NO_MEMORY; 700 825 if (pfSuccess != NULL) 701 826 *pfSuccess = halSuccess; … … 704 829 return rc; 705 830 } 831 832 /** 833 * Helper function to query the hal subsystem for information about USB devices 834 * attached to the system. 835 * @returns iprt status code 836 * @param pList where to add information about the devices detected 837 * @param pfSuccess will be set to true if all interactions with hal 838 * succeeded and to false otherwise. Optional. 839 * 840 * @returns IPRT status code 841 */ 842 /* static */ 843 int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess) 844 { 845 AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)), 846 VERR_INVALID_POINTER); 847 LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess)); 848 int rc = VINF_SUCCESS; /* We set this to failure on fatal errors. */ 849 bool halSuccess = true; /* We set this to false to abort the operation. */ 850 autoDBusError dbusError; 851 852 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet; 853 RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection; 854 DBusMessageIter iterFind, iterUdis; 855 856 rc = halInit (&dbusConnection); 857 if (!dbusConnection) 858 halSuccess = false; 859 if (halSuccess && RT_SUCCESS (rc)) 860 { 861 rc = halFindDeviceStringMatch (dbusConnection.get(), "info.subsystem", 862 "usb_device", &replyFind); 863 if (!replyFind) 864 halSuccess = false; 865 } 866 if (halSuccess && RT_SUCCESS (rc)) 867 { 868 dbus_message_iter_init (replyFind.get(), &iterFind); 869 if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY) 870 halSuccess = false; 871 } 872 if (halSuccess && RT_SUCCESS (rc)) 873 dbus_message_iter_recurse (&iterFind, &iterUdis); 874 for (; halSuccess && RT_SUCCESS (rc) 875 && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING; 876 dbus_message_iter_next(&iterUdis)) 877 { 878 /* Now get the device node and the sysfs path from the iterator */ 879 const char *pszUdi; 880 dbus_message_iter_get_basic (&iterUdis, &pszUdi); 881 static const char *papszKeys[] = { "linux.device_file", "linux.sysfs_path" }; 882 char *papszValues[RT_ELEMENTS (papszKeys)]; 883 rc = halGetPropertyStrings (dbusConnection.get(), pszUdi, RT_ELEMENTS (papszKeys), 884 papszKeys, papszValues, &replyGet); 885 std::string description; 886 const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1]; 887 /* Get the interfaces for this device. */ 888 if (!!replyGet && pszDevice && pszSysfsPath) 889 { 890 USBDeviceInfo info (pszDevice, pszSysfsPath); 891 bool ifaceSuccess = true; /* If we can't get the interfaces, just 892 * skip this one device. */ 893 rc = getUSBInterfacesFromHal (&info.mInterfaces, pszUdi, &ifaceSuccess); 894 if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess) 895 pList->push_back (info); 896 } 897 } 898 if (dbusError.HasName (DBUS_ERROR_NO_MEMORY)) 899 rc = VERR_NO_MEMORY; 900 if (pfSuccess != NULL) 901 *pfSuccess = halSuccess; 902 LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess)); 903 dbusError.FlowLog(); 904 return rc; 905 } 906 907 /** 908 * Helper function to query the hal subsystem for information about USB devices 909 * attached to the system. 910 * @returns iprt status code 911 * @param pList where to add information about the devices detected. If 912 * certain interfaces are not found (@a pfFound is false on 913 * return) this may contain invalid information. 914 * @param pcszUdi the hal UDI of the device 915 * @param pfSuccess will be set to true if the operation succeeds and to 916 * false if it fails for non-critical reasons. Optional. 917 * 918 * @returns IPRT status code 919 */ 920 /* static */ 921 int getUSBInterfacesFromHal(std::vector <std::string> *pList, 922 const char *pcszUdi, bool *pfSuccess) 923 { 924 AssertReturn(VALID_PTR (pList) && VALID_PTR (pcszUdi) && 925 (pfSuccess == NULL || VALID_PTR (pfSuccess)), 926 VERR_INVALID_POINTER); 927 LogFlowFunc (("pList=%p, pcszUdi=%s, pfSuccess=%p\n", pList, pcszUdi, 928 pfSuccess)); 929 int rc = VINF_SUCCESS; /* We set this to failure on fatal errors. */ 930 bool halSuccess = true; /* We set this to false to abort the operation. */ 931 autoDBusError dbusError; 932 933 RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet; 934 RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection; 935 DBusMessageIter iterFind, iterUdis; 936 937 rc = halInit (&dbusConnection); 938 if (!dbusConnection) 939 halSuccess = false; 940 if (halSuccess && RT_SUCCESS (rc)) 941 { 942 /* Look for children of the current UDI. */ 943 rc = halFindDeviceStringMatch (dbusConnection.get(), "info.parent", 944 pcszUdi, &replyFind); 945 if (!replyFind) 946 halSuccess = false; 947 } 948 if (halSuccess && RT_SUCCESS (rc)) 949 { 950 dbus_message_iter_init (replyFind.get(), &iterFind); 951 if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY) 952 halSuccess = false; 953 } 954 if (halSuccess && RT_SUCCESS (rc)) 955 dbus_message_iter_recurse (&iterFind, &iterUdis); 956 for (; halSuccess && RT_SUCCESS (rc) 957 && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING; 958 dbus_message_iter_next(&iterUdis)) 959 { 960 /* Now get the sysfs path and the subsystem from the iterator */ 961 const char *pszUdi; 962 dbus_message_iter_get_basic (&iterUdis, &pszUdi); 963 static const char *papszKeys[] = { "linux.sysfs_path", "info.subsystem" }; 964 char *papszValues[RT_ELEMENTS (papszKeys)]; 965 rc = halGetPropertyStrings (dbusConnection.get(), pszUdi, RT_ELEMENTS (papszKeys), 966 papszKeys, papszValues, &replyGet); 967 std::string description; 968 const char *pszSysfsPath = papszValues[0], *pszSubsystem = papszValues[1]; 969 if (!replyGet) 970 halSuccess = false; 971 if (!!replyGet && pszSysfsPath == NULL) 972 halSuccess = false; 973 if ( halSuccess && RT_SUCCESS (rc) 974 && RTStrCmp (pszSubsystem, "usb_device") != 0) /* Children of buses can also be devices. */ 975 pList->push_back (pszSysfsPath); 976 } 977 if (dbusError.HasName (DBUS_ERROR_NO_MEMORY)) 978 rc = VERR_NO_MEMORY; 979 if (pfSuccess != NULL) 980 *pfSuccess = halSuccess; 981 LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess)); 982 dbusError.FlowLog(); 983 return rc; 984 } 985 986 /** 987 * When it is registered with DBus, this function will be called by 988 * dbus_connection_read_write_dispatch each time a message is received over the 989 * DBus connection. We check whether that message was caused by a hal device 990 * hotplug event, and if so we set a flag. dbus_connection_read_write_dispatch 991 * will return after calling its filter functions, and its caller should then 992 * check the status of the flag passed to the filter function. 993 * 994 * @param pConnection The DBus connection we are using. 995 * @param pMessage The DBus message which just arrived. 996 * @param pvUser A pointer to the flag variable we are to set. 997 */ 998 /* static */ 999 DBusHandlerResult dbusFilterFunction (DBusConnection *pConnection, 1000 DBusMessage *pMessage, void *pvUser) 1001 { 1002 bool *pTriggered = reinterpret_cast<bool *> (pvUser); 1003 if ( dbus_message_is_signal (pMessage, "org.freedesktop.Hal.Manager", 1004 "DeviceAdded") 1005 || dbus_message_is_signal (pMessage, "org.freedesktop.Hal.Manager", 1006 "DeviceRemoved")) 1007 { 1008 *pTriggered = true; 1009 } 1010 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 1011 } 706 1012 #endif /* RT_OS_LINUX && VBOX_WITH_DBUS */ 707 1013 -
trunk/src/VBox/Main/linux/vbox-dbus.cpp
r15058 r15401 64 64 void (*dbus_message_iter_get_basic) (DBusMessageIter *, void *); 65 65 dbus_bool_t (*dbus_message_iter_next) (DBusMessageIter *); 66 dbus_bool_t (*dbus_connection_add_filter) (DBusConnection *, DBusHandleMessageFunction, 67 void *, DBusFreeFunction); 68 void (*dbus_connection_remove_filter) (DBusConnection *, DBusHandleMessageFunction, 69 void *); 70 dbus_bool_t (*dbus_connection_read_write_dispatch) (DBusConnection *, int); 71 dbus_bool_t (*dbus_message_is_signal) (DBusMessage *, const char *, const char *); 66 72 67 73 bool VBoxDBusCheckPresence(void) … … 116 122 && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_message_iter_next", 117 123 (void **) &dbus_message_iter_next)) 124 && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_connection_add_filter", 125 (void **) &dbus_connection_add_filter)) 126 && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_connection_remove_filter", 127 (void **) &dbus_connection_remove_filter)) 128 && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_connection_read_write_dispatch", 129 (void **) &dbus_connection_read_write_dispatch)) 130 && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_message_is_signal", 131 (void **) &dbus_message_is_signal)) 118 132 ) 119 133 { -
trunk/src/VBox/Main/testcase/Makefile.kmk
r15057 r15401 33 33 $(if $(VBOX_WITH_RESOURCE_USAGE_API),tstCollector,) 34 34 PROGRAMS.linux += \ 35 $(if $(VBOX_OSE),,tstHostHardwareLinux)35 tstHostHardwareLinux 36 36 endif # !VBOX_WITH_TESTCASES 37 37 endif # !VBOX_ONLY_SDK … … 125 125 tstHostHardwareLinux_SOURCES = \ 126 126 tstHostHardwareLinux.cpp \ 127 ../linux/USBProxyServiceLinux.cpp \128 127 ../linux/HostHardwareLinux.cpp \ 129 128 ../linux/vbox-dbus.cpp -
trunk/src/VBox/Main/testcase/tstHostHardwareLinux.cpp
r14991 r15401 1 1 /* $Id$ */ 2 3 2 /** @file 4 3 * 5 * Test executable for quickly excercising/debugging the hal-based Linux USB4 * Test executable for quickly excercising/debugging the Linux host hardware 6 5 * bits. 7 6 */ … … 10 9 * Copyright (C) 2008 Sun Microsystems, Inc. 11 10 * 12 * Sun Microsystems, Inc. confidential 13 * All rights reserved 11 * This file is part of VirtualBox Open Source Edition (OSE), as 12 * available from http://www.virtualbox.org. This file is free software; 13 * you can redistribute it and/or modify it under the terms of the GNU 14 * General Public License (GPL) as published by the Free Software 15 * Foundation, in version 2 as it comes in the "COPYING" file of the 16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 20 * Clara, CA 95054 USA or visit http://www.sun.com if you need 21 * additional information or have any questions. 14 22 */ 15 16 #ifdef VBOX_USB_WITH_SYSFS17 # include "tstUSBLinux.h"18 #endif19 23 20 24 #include <HostHardwareLinux.h> … … 23 27 24 28 #include <iprt/initterm.h> 29 #include <iprt/param.h> 25 30 #include <iprt/stream.h> 31 #include <iprt/linux/sysfs.h> 26 32 27 33 #include <iprt/cdefs.h> 28 34 #include <iprt/types.h> 29 35 36 #include <errno.h> 37 #include <string.h> 38 30 39 int main() 31 40 { 32 41 RTR3Init(); 33 #ifdef VBOX_USB_WITH_SYSFS 34 USBProxyServiceLinux service; 35 service.initSysfs(); 36 if (RT_FAILURE(service.getLastError())) 37 { 38 RTPrintf("Failed to initialise USBProxyServiceLinux, error %Rrc\n", 39 service.getLastError()); 40 return 1; 41 } 42 PUSBDEVICE pChain = service.getDevicesFromSysfs(); 43 if (pChain == NULL) 44 RTPrintf("Failed to get any devices from sysfs\n."); 45 else 46 { 47 PUSBDEVICE pNext = pChain; 48 while (pNext != NULL) 49 { 50 RTPrintf("Device: %s (product string)\n", pNext->pszProduct); 51 RTPrintf(" Manufacturer: %s\n", pNext->pszManufacturer); 52 RTPrintf(" Serial number: %s\n", pNext->pszSerialNumber); 53 RTPrintf(" Address: %s\n", pNext->pszAddress); 54 RTPrintf(" Vendor ID: %d\n", pNext->idVendor); 55 RTPrintf(" Product ID: %d\n", pNext->idProduct); 56 RTPrintf(" Revision: %d.%d\n", pNext->bcdDevice >> 8, pNext->bcdDevice & 255); 57 RTPrintf(" USB Version: %d.%d\n", pNext->bcdUSB >> 8, pNext->bcdUSB & 255); 58 RTPrintf(" Device class: %d\n", pNext->bDeviceClass); 59 RTPrintf(" Device subclass: %d\n", pNext->bDeviceSubClass); 60 RTPrintf(" Device protocol: %d\n", pNext->bDeviceProtocol); 61 RTPrintf(" Number of configurations: %d\n", pNext->bNumConfigurations); 62 RTPrintf(" Device state: %s\n", 63 pNext->enmState == USBDEVICESTATE_UNUSED ? "unused" 64 : pNext->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE ? "used by host" 65 : "unknown" 66 ); 67 RTPrintf(" Device speed: %s\n", 68 pNext->enmSpeed == USBDEVICESPEED_LOW ? "low" 69 : pNext->enmSpeed == USBDEVICESPEED_FULL ? "full" 70 : pNext->enmSpeed == USBDEVICESPEED_HIGH ? "high" 71 : "unknown" 72 ); 73 RTPrintf(" Serial hash: 0x%llx\n", pNext->u64SerialHash); 74 RTPrintf(" Bus number: %d\n", pNext->bBus); 75 RTPrintf(" Port number: %d\n", pNext->bPort); 76 RTPrintf(" Device number: %d\n", pNext->bDevNum); 77 RTPrintf("\n"); 78 pNext = pNext->pNext; 79 } 80 } 81 #endif /* VBOX_USB_WITH_SYSFS */ 42 g_testHostHardwareLinux = true; 43 int rc = VINF_SUCCESS; 82 44 VBoxMainDriveInfo driveInfo; 83 45 g_testHostHardwareLinux = true; 84 intrc = driveInfo.updateFloppies();46 rc = driveInfo.updateFloppies(); 85 47 if (RT_SUCCESS (rc)) 86 48 rc = driveInfo.updateDVDs(); … … 92 54 } 93 55 RTPrintf ("Listing floppy drives detected:\n"); 94 for ( VBoxMainDriveInfo::DriveInfoList::const_iterator it = driveInfo.FloppyBegin();56 for (DriveInfoList::const_iterator it = driveInfo.FloppyBegin(); 95 57 it != driveInfo.FloppyEnd(); ++it) 96 58 { … … 103 65 } 104 66 RTPrintf ("Listing DVD drives detected:\n"); 105 for ( VBoxMainDriveInfo::DriveInfoList::const_iterator it = driveInfo.DVDBegin();67 for (DriveInfoList::const_iterator it = driveInfo.DVDBegin(); 106 68 it != driveInfo.DVDEnd(); ++it) 107 69 { … … 113 75 RTPrintf ("\n"); 114 76 } 77 #ifdef VBOX_USB_WITH_SYSFS 78 VBoxMainUSBDeviceInfo deviceInfo; 79 rc = deviceInfo.UpdateDevices(); 80 if (RT_FAILURE (rc)) 81 { 82 RTPrintf ("Failed to update the host USB device information, error %Rrc\n", 83 rc); 84 return 1; 85 } 86 RTPrintf ("Listing USB devices detected:\n"); 87 for (USBDeviceInfoList::const_iterator it = deviceInfo.DevicesBegin(); 88 it != deviceInfo.DevicesEnd(); ++it) 89 { 90 char szProduct[1024]; 91 if (RTLinuxSysFsReadStrFile(szProduct, sizeof(szProduct), 92 "%s/product", it->mSysfsPath.c_str()) == -1) 93 { 94 if (errno != ENOENT) 95 { 96 RTPrintf ("Failed to get the product name for device %s: error %s\n", 97 it->mDevice.c_str(), strerror(errno)); 98 return 1; 99 } 100 else 101 szProduct[0] = '\0'; 102 } 103 RTPrintf (" device: %s (%s), sysfs path: %s\n", szProduct, it->mDevice.c_str(), 104 it->mSysfsPath.c_str()); 105 RTPrintf (" interfaces:\n"); 106 for (USBInterfaceList::const_iterator it2 = it->mInterfaces.begin(); 107 it2 != it->mInterfaces.end(); ++it2) 108 { 109 char szDriver[RTPATH_MAX]; 110 strcpy(szDriver, "none"); 111 ssize_t size = RTLinuxSysFsGetLinkDest(szDriver, sizeof(szDriver), 112 "%s/driver", it2->c_str()); 113 if (size == -1 && errno != ENOENT) 114 { 115 RTPrintf ("Failed to get the driver for interface %s of device %s: error %s\n", 116 it2->c_str(), it->mDevice.c_str(), strerror(errno)); 117 return 1; 118 } 119 if (RTLinuxSysFsExists("%s/driver", it2->c_str()) != (size != -1)) 120 { 121 RTPrintf ("RTLinuxSysFsExists did not return the expected value for the driver link of interface %s of device %s.\n", 122 it2->c_str(), it->mDevice.c_str()); 123 return 1; 124 } 125 uint64_t u64InterfaceClass; 126 u64InterfaceClass = RTLinuxSysFsReadIntFile(16, "%s/bInterfaceClass", 127 it2->c_str()); 128 RTPrintf (" sysfs path: %s, driver: %s, interface class: 0x%x\n", 129 it2->c_str(), szDriver, u64InterfaceClass); 130 } 131 } 132 RTPrintf ("Waiting for a hotplug event, Ctrl-C to abort...\n"); 133 VBoxMainHotplugWaiter waiter; 134 waiter.Wait(); 135 #endif /* VBOX_USB_WITH_SYSFS */ 115 136 return 0; 116 137 }
Note:
See TracChangeset
for help on using the changeset viewer.