VirtualBox

Changeset 2587 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 11, 2007 3:12:27 AM (18 years ago)
Author:
vboxsync
Message:

Darwin USB (work in progress)...

Location:
trunk/src/VBox/Main
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/HostImpl.cpp

    r2434 r2587  
    113113    mParent = parent;
    114114
    115 #if defined (__LINUX__) && defined (VBOX_WITH_USB)
     115#if defined (__DARWIN__) && defined (VBOX_WITH_USB)
     116    mUSBProxyService = new USBProxyServiceDarwin (this);
     117#elif defined (__LINUX__) && defined (VBOX_WITH_USB)
    116118    mUSBProxyService = new USBProxyServiceLinux (this);
    117119#elif defined (__WIN__) && defined (VBOX_WITH_USB)
  • trunk/src/VBox/Main/Makefile.kmk

    r2486 r2587  
    202202
    203203ifdef VBOX_WITH_USB
     204VBoxSVC_SOURCES.darwin += darwin/USBProxyServiceDarwin.cpp
    204205VBoxSVC_SOURCES.linux += linux/USBProxyServiceLinux.cpp
    205206VBoxSVC_SOURCES.win   += win32/USBProxyServiceWin32.cpp
  • trunk/src/VBox/Main/USBProxyService.cpp

    r1 r2587  
    288288    USBProxyService *pThis = (USBProxyService *)pvUser;
    289289    LogFlow (("USBProxyService::serviceThread: pThis=%p\n", pThis));
     290    pThis->serviceThreadInit();
    290291
    291292    /*
     
    300301    }
    301302
     303    pThis->serviceThreadTerm();
    302304    LogFlow (("USBProxyService::serviceThread: returns VINF_SUCCESS\n"));
    303305    return VINF_SUCCESS;
     
    391393}
    392394
     395
     396void USBProxyService::serviceThreadInit (void)
     397{
     398}
     399
     400
     401void USBProxyService::serviceThreadTerm (void)
     402{
     403}
     404
     405
    393406/**
    394407 *  The default implementation returns non-NULL to emulate successful insertions
  • trunk/src/VBox/Main/darwin/iokit.cpp

    r2342 r2587  
    3434#include <IOKit/scsi-commands/SCSITaskLib.h>
    3535#include <mach/mach_error.h>
     36#ifdef VBOX_WITH_USB
     37# include <IOKit/usb/IOUSBLib.h>
     38#endif
    3639
    3740#include <iprt/mem.h>
     
    4043
    4144#include "iokit.h"
     45
     46
     47/*******************************************************************************
     48*   Defined Constants And Macros                                               *
     49*******************************************************************************/
     50/** An attempt at catching reference leaks. */
     51#define MY_CHECK_CREFS(cRefs)   do { AssertMsg(cRefs < 25, ("%ld\n", cRefs)); NOREF(cRefs); } while (0)
    4252
    4353
     
    4959
    5060
     61/**
     62 * Lazily opens the master port.
     63 *
     64 * @returns true if the port is open, false on failure (very unlikely).
     65 */
     66static bool darwinOpenMasterPort(void)
     67{
     68    if (!g_MasterPort)
     69    {
     70        kern_return_t krc = IOMasterPort(MACH_PORT_NULL, &g_MasterPort);
     71        AssertReturn(krc == KERN_SUCCESS, false);
     72    }
     73    return true;
     74}
     75
     76
     77#ifdef VBOX_WITH_USB
     78
     79/**
     80 * Gets an unsigned 8-bit integer value.
     81 *
     82 * @returns Success indicator (true/false).
     83 * @param   DictRef     The dictionary.
     84 * @param   KeyStrRef   The key name.
     85 * @param   pu8         Where to store the key value.
     86 */
     87static bool darwinDictGetU8(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint8_t *pu8)
     88{
     89    CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
     90    if (ValRef)
     91    {
     92        if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt8Type, pu8))
     93            return true;
     94    }
     95    *pu8 = 0;
     96    return false;
     97}
     98
     99
     100/**
     101 * Gets an unsigned 16-bit integer value.
     102 *
     103 * @returns Success indicator (true/false).
     104 * @param   DictRef     The dictionary.
     105 * @param   KeyStrRef   The key name.
     106 * @param   pu16        Where to store the key value.
     107 */
     108static bool darwinDictGetU16(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint16_t *pu16)
     109{
     110    CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
     111    if (ValRef)
     112    {
     113        if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt16Type, pu16))
     114            return true;
     115    }
     116    *pu16 = 0;
     117    return false;
     118}
     119
     120
     121/**
     122 * Gets an unsigned 32-bit integer value.
     123 *
     124 * @returns Success indicator (true/false).
     125 * @param   DictRef     The dictionary.
     126 * @param   KeyStrRef   The key name.
     127 * @param   pu32        Where to store the key value.
     128 */
     129static bool darwinDictGetU32(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint32_t *pu32)
     130{
     131    CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
     132    if (ValRef)
     133    {
     134        if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt32Type, pu32))
     135            return true;
     136    }
     137    *pu32 = 0;
     138    return false;
     139}
     140
     141
     142/**
     143 * Gets an unsigned 64-bit integer value.
     144 *
     145 * @returns Success indicator (true/false).
     146 * @param   DictRef     The dictionary.
     147 * @param   KeyStrRef   The key name.
     148 * @param   pu64        Where to store the key value.
     149 */
     150static bool darwinDictGetU64(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint64_t *pu64)
     151{
     152    CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
     153    if (ValRef)
     154    {
     155        if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt64Type, pu64))
     156            return true;
     157    }
     158    *pu64 = 0;
     159    return false;
     160}
     161
     162
     163/**
     164 * Gets string value, converted to UTF-8 and put in a IPRT string buffer.
     165 *
     166 * @returns Success indicator (true/false).
     167 * @param   DictRef     The dictionary.
     168 * @param   KeyStrRef   The key name.
     169 * @param   ppsz        Where to store the key value. Free with RTStrFree. Set to NULL on failure.
     170 */
     171static bool darwinDictGetString(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, char **ppsz)
     172{
     173    CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
     174    if (ValRef)
     175    {
     176        char szBuf[512];
     177        if (CFStringGetCString((CFStringRef)ValRef, szBuf, sizeof(szBuf), kCFStringEncodingUTF8))
     178        {
     179            *ppsz = RTStrDup(RTStrStrip(szBuf));
     180            if (*ppsz)
     181                return true;
     182        }
     183    }
     184    *ppsz = NULL;
     185    return false;
     186}
     187
     188
     189
     190void        DarwinSubscribeUSBNotifications(void)
     191{
     192
     193}
     194
     195void        DarwinUnsubscribeUSBNotifications(void)
     196{
     197
     198}
     199
     200
     201/**
     202 * Enumerate the USB devices returning a FIFO of them.
     203 *
     204 * @returns Pointer to the head.
     205 *          USBProxyService::freeDevice is expected to free each of the list elements.
     206 */
     207PUSBDEVICE DarwinGetUSBDevices(void)
     208{
     209    AssertReturn(darwinOpenMasterPort(), NULL);
     210
     211    /*
     212     * Create a matching dictionary for searching for USB Devices in the IOKit.
     213     */
     214    CFMutableDictionaryRef RefMatchingDict = IOServiceMatching(kIOUSBDeviceClassName);
     215    AssertReturn(RefMatchingDict, NULL);
     216
     217    /*
     218     * Perform the search and get a collection of USB Device back.
     219     */
     220    io_iterator_t USBDevices = NULL;
     221    IOReturn rc = IOServiceGetMatchingServices(g_MasterPort, RefMatchingDict, &USBDevices);
     222    AssertMsgReturn(rc == kIOReturnSuccess, ("rc=%d\n", rc), NULL);
     223    RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */
     224
     225    /*
     226     * Enumerate the USB Devices.
     227     */
     228    PUSBDEVICE pHead = NULL;
     229    PUSBDEVICE pTail = NULL;
     230    unsigned i = 0;
     231    io_object_t USBDevice;
     232    while ((USBDevice = IOIteratorNext(USBDevices)) != 0)
     233    {
     234        /*
     235         * Query the device properties from the registry.
     236         *
     237         * We could alternatively use the device and such, but that will be
     238         * slower and we would have to resort to the registry for the three
     239         * string anyway.
     240         */
     241        CFMutableDictionaryRef PropsRef = 0;
     242        kern_return_t krc = IORegistryEntryCreateCFProperties(USBDevice, &PropsRef, kCFAllocatorDefault, kNilOptions);
     243        if (krc == KERN_SUCCESS)
     244        {
     245            bool fOk = false;
     246            PUSBDEVICE pCur = (PUSBDEVICE)RTMemAllocZ(sizeof(*pCur));
     247            do /* loop for breaking out of on failure. */
     248            {
     249                AssertBreak(pCur,);
     250
     251                /*
     252                 * Mandatory
     253                 */
     254                pCur->bcdUSB = 0;                                           /* we've no idea. */
     255                pCur->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;    /* ditto. */
     256
     257                AssertBreak(darwinDictGetU8(PropsRef,  CFSTR(kUSBDeviceClass),           &pCur->bDeviceClass),);
     258                /* skip hubs */
     259                if (pCur->bDeviceClass == 0x09 /* hub, find a define! */)
     260                    break;
     261                AssertBreak(darwinDictGetU8(PropsRef,  CFSTR(kUSBDeviceSubClass),       &pCur->bDeviceSubClass),);
     262                AssertBreak(darwinDictGetU8(PropsRef,  CFSTR(kUSBDeviceProtocol),       &pCur->bDeviceProtocol),);
     263                AssertBreak(darwinDictGetU16(PropsRef, CFSTR(kUSBVendorID),             &pCur->idVendor),);
     264                AssertBreak(darwinDictGetU16(PropsRef, CFSTR(kUSBProductID),            &pCur->idProduct),);
     265                AssertBreak(darwinDictGetU16(PropsRef, CFSTR(kUSBDeviceReleaseNumber),  &pCur->bcdDevice),);
     266                char szAddress[32];
     267#if 0                           
     268                uint32_t u32LocationID;
     269                AssertBreak(darwinDictGetU32(PropsRef, CFSTR(kUSBDevicePropertyLocationID), &u32LocationID),);
     270                RTStrPrintf(szAddress, sizeof(szAddress), "%08RX32", u32LocationID);
     271#else
     272                uint64_t u64SessionID;
     273                AssertBreak(darwinDictGetU64(PropsRef, CFSTR(kUSBDevicePropertyLocationID), &u64SessionID),);
     274                RTStrPrintf(szAddress, sizeof(szAddress), "%016RX32", u64SessionID);
     275#endif
     276                pCur->pszAddress = RTStrDup(szAddress); 
     277                AssertBreak(pCur->pszAddress,);
     278
     279                /*
     280                 * Optional.
     281                 * There are some nameless device in the iMac, apply names to them.
     282                 */
     283                darwinDictGetString(PropsRef, CFSTR("USB Vendor Name"),     (char **)&pCur->pszManufacturer);
     284                if (    !pCur->pszManufacturer
     285                    &&  pCur->idVendor == kIOUSBVendorIDAppleComputer)
     286                    pCur->pszManufacturer = RTStrDup("Apple Computer, Inc.");
     287                darwinDictGetString(PropsRef, CFSTR("USB Product Name"),    (char **)&pCur->pszProduct);
     288                if (    !pCur->pszProduct
     289                    &&  pCur->bDeviceClass == 224 /* Wireless */
     290                    &&  pCur->bDeviceSubClass == 1 /* Radio Frequency */
     291                    &&  pCur->bDeviceProtocol == 1 /* Bluetooth */)
     292                    pCur->pszProduct = RTStrDup("Bluetooth");
     293                darwinDictGetString(PropsRef, CFSTR("USB Serial Number"),   (char **)&pCur->pszSerialNumber);
     294
     295#if 0           /* leave the remainder as zero for now. */
     296                /*
     297                 * Create a plugin interface for the service and query its USB Device interface.
     298                 */
     299                SInt32 Score = 0;
     300                IOCFPlugInInterface **ppPlugInInterface = NULL;
     301                rc = IOCreatePlugInInterfaceForService(USBDevice, kIOUSBDeviceUserClientTypeID,
     302                                                       kIOCFPlugInInterfaceID, &ppPlugInInterface, &Score);
     303                if (rc == kIOReturnSuccess)
     304                {
     305                    IOUSBDeviceInterface245 **ppUSBDevI = NULL;
     306                    HRESULT hrc = (*ppPlugInInterface)->QueryInterface(ppPlugInInterface,
     307                                                                       CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245),
     308                                                                       (LPVOID *)&ppUSBDevI);
     309                    rc = IODestroyPlugInInterface(ppPlugInInterface); Assert(rc == kIOReturnSuccess);
     310                    ppPlugInInterface = NULL;
     311                    if (hrc == S_OK)
     312                    {
     313                        /** @todo enumerate configurations and interfaces if we actually need them. */
     314                        //IOReturn (*GetNumberOfConfigurations)(void *self, UInt8 *numConfig);
     315                        //IOReturn (*GetConfigurationDescriptorPtr)(void *self, UInt8 configIndex, IOUSBConfigurationDescriptorPtr *desc);
     316                        //IOReturn (*CreateInterfaceIterator)(void *self, IOUSBFindInterfaceRequest *req, io_iterator_t *iter);
     317                    }
     318                    long cReft = (*ppUSBDeviceInterface)->Release(ppUSBDeviceInterface); MY_CHECK_CREFS(cRefs);
     319                }
     320#endif
     321
     322                /*
     323                 * We're good. Link the device.
     324                 */
     325                pCur->pPrev = pTail;
     326                if (pTail)
     327                    pTail = pTail->pNext = pCur;
     328                else
     329                    pTail = pHead = pCur;
     330                fOk = true;
     331            } while (0);
     332
     333            /* cleanup on failure / skipped device. */
     334            if (!fOk && pCur)
     335            {
     336                /** @todo */
     337            }
     338
     339            CFRelease(PropsRef);
     340        }
     341        else
     342            AssertMsgFailed(("krc=%#x\n", krc));
     343
     344        IOObjectRelease(USBDevice);
     345        i++;
     346    }
     347
     348    IOObjectRelease(USBDevices);
     349
     350    /*
     351     * Some post processing. There are a couple of things we have to
     352     * make 100% sure about, and that is that the (Apple) keyboard
     353     * and mouse most likely to be in use by the user aren't available
     354     * for capturing. If there is no Apple mouse or keyboard we'll
     355     * take the first one from another vendor.
     356     */
     357    PUSBDEVICE pMouse = NULL;
     358    PUSBDEVICE pKeyboard = NULL;
     359    for (PUSBDEVICE pCur = pHead; pCur; pCur = pCur->pNext)
     360        if (pCur->idVendor == kIOUSBVendorIDAppleComputer)
     361        {
     362            /*
     363             * This test is a bit rough, should check device class/protocol but
     364             * we don't have interface info yet so that might be a bit tricky.
     365             */
     366            if (    (   !pKeyboard
     367                     || pKeyboard->idVendor != kIOUSBVendorIDAppleComputer)
     368                &&  pCur->pszProduct
     369                &&  strstr(pCur->pszProduct, " Keyboard"))
     370                pKeyboard = pCur;
     371            else if (    (   !pMouse
     372                          || pMouse->idVendor != kIOUSBVendorIDAppleComputer)
     373                     &&  pCur->pszProduct
     374                     &&  strstr(pCur->pszProduct, " Mouse")
     375                )
     376                pMouse = pCur;
     377        }
     378        else if (!pKeyboard || !pMouse)
     379        {
     380            if (    pCur->bDeviceClass == 3         /* HID */
     381                &&  pCur->bDeviceProtocol == 1      /* Keyboard */)
     382                pKeyboard = pCur;
     383            else if (   pCur->bDeviceClass == 3     /* HID */
     384                     && pCur->bDeviceProtocol == 2  /* Mouse */)
     385                pMouse = pCur;
     386            /** @todo examin interfaces */
     387        }
     388
     389    if (pKeyboard)
     390        pKeyboard->enmState = USBDEVICESTATE_USED_BY_HOST;
     391    if (pMouse)
     392        pMouse->enmState = USBDEVICESTATE_USED_BY_HOST;
     393
     394    return pHead;
     395}
     396
     397#endif /* VBOX_WITH_USB */
     398
    51399
    52400/**
     
    58406PDARWINDVD DarwinGetDVDDrives(void)
    59407{
    60     PDARWINDVD pHead = NULL;
    61     PDARWINDVD pTail = NULL;
    62 
    63     /*
    64      * Open the master port on the first invocation.
    65      */
    66     if (!g_MasterPort)
    67     {
    68         kern_return_t krc = IOMasterPort(MACH_PORT_NULL, &g_MasterPort);
    69         AssertReturn(krc == KERN_SUCCESS, NULL);
    70     }
     408    AssertReturn(darwinOpenMasterPort(), NULL);
    71409
    72410    /*
     
    83421
    84422    /*
    85      * do the search and get a collection of keyboards.
     423     * Perform the search and get a collection of DVD services.
    86424     */
    87425    io_iterator_t DVDServices = NULL;
     
    91429
    92430    /*
    93      * Enumerate the DVD drives (services).
     431     * Enumerate the DVD services.
    94432     * (This enumeration must be identical to the one performed in DrvHostBase.cpp.)
    95433     */
     434    PDARWINDVD pHead = NULL;
     435    PDARWINDVD pTail = NULL;
    96436    unsigned i = 0;
    97437    io_object_t DVDService;
     
    186526    return pHead;
    187527}
     528
  • trunk/src/VBox/Main/darwin/iokit.h

    r2342 r2587  
    2525#include <iprt/cdefs.h>
    2626#include <iprt/types.h>
     27#ifdef VBOX_WITH_USB
     28# include <VBox/usb.h>
     29#endif
    2730
    2831/**
     
    3740} DARWINDVD, *PDARWINDVD;
    3841
     42/** The run loop mode string used by iokit.cpp when it registers
     43 * notifications events. */
     44#define VBOX_IOKIT_MODE_STRING "VBoxIOKitMode"
    3945
    4046__BEGIN_DECLS
    41 PDARWINDVD DarwinGetDVDDrives(void);
     47PDARWINDVD  DarwinGetDVDDrives(void);
     48#ifdef VBOX_WITH_USB
     49void        DarwinSubscribeUSBNotifications(void);
     50void        DarwinUnsubscribeUSBNotifications(void);
     51PUSBDEVICE  DarwinGetUSBDevices(void);
     52#endif
    4253__END_DECLS
    43 
    4454
    4555#endif
  • trunk/src/VBox/Main/include/USBProxyService.h

    r1 r2587  
    149149    virtual PUSBDEVICE getDevices (void);
    150150
     151    /**
     152     * First call made on the service thread, use it to do
     153     * thread initialization.
     154     */
     155    virtual void serviceThreadInit (void);
     156
     157    /**
     158     * First call made on the service thread, use it to do
     159     * thread termination.
     160     */
     161    virtual void serviceThreadTerm (void);
     162
    151163public:
    152164    /**
     
    190202#ifdef VBOX_WITH_USB
    191203
     204# ifdef __DARWIN__
     205#  include <VBox/param.h>
     206#  undef PAGE_SHIFT
     207#  undef PAGE_SIZE
     208#  define OSType Carbon_OSType
     209#  include <Carbon/Carbon.h>
     210#  undef OSType
     211
     212/**
     213 * The Darwin hosted USB Proxy Service.
     214 */
     215class USBProxyServiceDarwin : public USBProxyService
     216{
     217public:
     218    USBProxyServiceDarwin (Host *aHost);
     219    ~USBProxyServiceDarwin();
     220
     221    virtual int captureDevice (HostUSBDevice *aDevice);
     222    virtual int holdDevice (HostUSBDevice *aDevice);
     223    virtual int releaseDevice (HostUSBDevice *aDevice);
     224    virtual int resetDevice (HostUSBDevice *aDevice);
     225
     226protected:
     227    virtual int wait (unsigned aMillies);
     228    virtual int interruptWait (void);
     229    virtual PUSBDEVICE getDevices (void);
     230    virtual void serviceThreadInit (void);
     231    virtual void serviceThreadTerm (void);
     232
     233private:
     234    /** Reference to the runloop of the service thread.
     235     * This is NULL if the service thread isn't running. */
     236    CFRunLoopRef mServiceRunLoopRef;
     237
     238};
     239# endif /* __DARWIN__ */
     240
     241
    192242# ifdef __LINUX__
    193243#  include <stdio.h>
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