VirtualBox

Changeset 3665 in vbox for trunk/src


Ignore:
Timestamp:
Jul 17, 2007 4:22:06 AM (18 years ago)
Author:
vboxsync
Message:

Detect HID and in-use MSDs. Currently polling for changes every 5 seconds.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/darwin/iokit.cpp

    r3662 r3665  
    548548
    549549/**
     550 * Decends recursivly into a IORegistry tree locating the first object of a given class.
     551 *
     552 * The search is performed depth first.
     553 *
     554 * @returns Object reference if found, NULL if not.
     555 * @param   Object      The current tree root.
     556 * @param   pszClass    The name of the class we're looking for.
     557 * @param   pszNameBuf  A scratch buffer for query the class name in to avoid
     558 *                      wasting 128 bytes on an io_name_t object for every recursion.
     559 */
     560static io_object_t darwinFindObjectByClass(io_object_t Object, const char *pszClass, io_name_t pszNameBuf)
     561{
     562    io_iterator_t Children;
     563    kern_return_t krc = IORegistryEntryGetChildIterator(Object, kIOServicePlane, &Children);
     564    if (krc != KERN_SUCCESS)
     565        return NULL;
     566    io_object_t Child;
     567    while ((Child = IOIteratorNext(Children)))
     568    {
     569        krc = IOObjectGetClass(Child, pszNameBuf);
     570        if (    krc == KERN_SUCCESS
     571            &&  !strcmp(pszNameBuf, pszClass))
     572            break;
     573
     574        io_object_t GrandChild = darwinFindObjectByClass(Child, pszClass, pszNameBuf);
     575        IOObjectRelease(Child);
     576        if (GrandChild)
     577        {
     578            Child = GrandChild;
     579            break;
     580        }
     581    }
     582    IOObjectRelease(Children);
     583    return Child;
     584}
     585
     586
     587/**
     588 * Decends recursivly into IOUSBMassStorageClass tree to check whether
     589 * the MSD is mounted or not.
     590 *
     591 * The current heuristic is to look for the IOMedia class.
     592 *
     593 * @returns true if mounted, false if not.
     594 * @param   MSDObj      The IOUSBMassStorageClass object.
     595 * @param   pszNameBuf  A scratch buffer for query the class name in to avoid
     596 *                      wasting 128 bytes on an io_name_t object for every recursion.
     597 */
     598static bool darwinIsMassStorageInterfaceInUse(io_object_t MSDObj, io_name_t pszNameBuf)
     599{
     600    io_object_t MediaObj = darwinFindObjectByClass(MSDObj, "IOMedia", pszNameBuf);
     601    if (MediaObj)
     602    {
     603        /* more checks? */
     604        IOObjectRelease(MediaObj);
     605        return true;
     606    }
     607    return false;
     608}
     609
     610
     611/**
    550612 * Worker function for DarwinGetUSBDevices() that tries to figure out
    551613 * what state the device is in.
     
    560622static void darwinDeterminUSBDeviceState(PUSBDEVICE pCur, io_object_t USBDevice, CFMutableDictionaryRef PropsRef)
    561623{
    562     ///@todo
     624    /*
     625     * Iterate the interfaces (among the children of the IOUSBDevice object).
     626     */
     627    io_iterator_t Interfaces;
     628    kern_return_t krc = IORegistryEntryGetChildIterator(USBDevice, kIOServicePlane, &Interfaces);
     629    if (krc != KERN_SUCCESS)
     630        return;
     631
     632    bool fUserClientOnly = true;
     633    bool fConfigured = false;
     634    bool fInUse = false;
     635    bool fSeizable = true;
     636    io_object_t Interface;
     637    while ((Interface = IOIteratorNext(Interfaces)))
     638    {
     639        io_name_t szName;
     640        krc = IOObjectGetClass(Interface, szName);
     641        if (    krc == KERN_SUCCESS
     642            &&  !strcmp(szName, "IOUSBInterface"))
     643        {
     644            fConfigured = true;
     645
     646            /*
     647             * Iterate the interface children looking for stuff other than
     648             * IOUSBUserClientInit objects.
     649             */
     650            io_iterator_t Children1;
     651            krc = IORegistryEntryGetChildIterator(Interface, kIOServicePlane, &Children1);
     652            if (krc == KERN_SUCCESS)
     653            {
     654                io_object_t Child1;
     655                while ((Child1 = IOIteratorNext(Children1)))
     656                {
     657                    krc = IOObjectGetClass(Child1, szName);
     658                    if (    krc == KERN_SUCCESS
     659                        &&  strcmp(szName, "IOUSBUserClientInit"))
     660                    {
     661                        fUserClientOnly = false;
     662
     663                        if (!strcmp(szName, "IOUSBMassStorageClass"))
     664                        {
     665                            /* Only permit capturing MSDs that aren't mounted, at least
     666                               until the GUI starts poping up warnings about data loss
     667                               and such when capturing a busy device. */
     668                            fSeizable = false;
     669                            fInUse |= darwinIsMassStorageInterfaceInUse(Child1, szName);
     670                        }
     671                        else if (!strcmp(szName, "IOUSBHIDDriver")
     672                              || !strcmp(szName, "AppleHIDMouse")
     673                              /** @todo more? */)
     674                        {
     675                            /* For now, just assume that all HID devices are inaccessible
     676                               because of the greedy HID service. */
     677                            fSeizable = false;
     678                            fInUse = true;
     679                        }
     680                        else
     681                            fInUse = true;
     682                    }
     683                    IOObjectRelease(Child1);
     684                }
     685                IOObjectRelease(Children1);
     686            }
     687        }
     688        IOObjectRelease(Interface);
     689    }
     690    IOObjectRelease(Interfaces);
     691
     692    /*
     693     * Calc the status.
     694     */
     695    if (fUserClientOnly)
     696        /** @todo how to detect other user client?!? */
     697        pCur->enmState = !fConfigured
     698                       ? USBDEVICESTATE_UNUSED
     699                       : USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
     700
     701    else if (!fInUse)
     702        pCur->enmState = USBDEVICESTATE_UNUSED;
     703    else
     704        pCur->enmState = fSeizable
     705                       ? USBDEVICESTATE_USED_BY_HOST_CAPTURABLE
     706                       : USBDEVICESTATE_USED_BY_HOST;
    563707}
    564708
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette