Esempio n. 1
0
BOOL IOKitDevice::GetDeviceString(const io_service_t& hService_, CFStringRef hProperty_, UCHAR* pucBsdName_, ULONG ulSize_, BOOL bSearchChildren_)
{
   if(pucBsdName_ == NULL)
      return FALSE;

   CFStringRef	hBsdPathAsCFString;  //CFTypeRef	hBsdPathAsCFString;

   if(bSearchChildren_)
   {
      hBsdPathAsCFString = (CFStringRef)IORegistryEntrySearchCFProperty(
                                                            hService_,
                                                            kIOServicePlane,
                                                            hProperty_,
                                                            kCFAllocatorDefault,
                                                            kIORegistryIterateRecursively);
   }
   else
   {
      hBsdPathAsCFString = (CFStringRef)IORegistryEntryCreateCFProperty(
                                                            hService_,
                                                            hProperty_,
                                                            kCFAllocatorDefault,
                                                            0);
   }

   if(hBsdPathAsCFString == NULL)
   {
      pucBsdName_[0] = '\0';
		return FALSE;
   }


    // Convert the path from a CFString to a C (NUL-terminated) string for use
	// with the POSIX open() call.
	BOOL bResult = CFStringGetCString(hBsdPathAsCFString,
                                 (char*)pucBsdName_,
                                 ulSize_,
                                 kCFStringEncodingUTF8);
    CFRelease(hBsdPathAsCFString);

   if(!bResult)
   {
      pucBsdName_[0] = '\0';
		return FALSE;
   }

   return TRUE;
}
static int iokit_find_service_matching (MMCDEV *mmc, io_service_t *servp) {
    CFMutableDictionaryRef matchingDict = IOServiceMatching("IOBDServices");
    io_iterator_t deviceIterator;
    io_service_t service;
    int rc;

    assert (NULL != servp);

    *servp = 0;

    if (!matchingDict) {
        BD_DEBUG(DBG_MMC, "Could not create a matching dictionary for IOBDServices\n");
        return -1;
    }

    /* this call consumes the reference to the matchingDict. we do not need to release it */
    rc = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &deviceIterator);
    if (kIOReturnSuccess != rc) {
        BD_DEBUG(DBG_MMC, "Could not create device iterator\n");
        return -1;
    }

    while (0 != (service = IOIteratorNext (deviceIterator))) {
        CFStringRef data;
        char name[128] = "";

        data = IORegistryEntrySearchCFProperty (service, kIOServicePlane, CFSTR("BSD Name"),
                                                kCFAllocatorDefault, kIORegistryIterateRecursively);

        if (NULL != data) {
            rc = CFStringGetCString (data, name, sizeof (name), kCFStringEncodingASCII);
            CFRelease (data);
            if (0 == strcmp (name, mmc->bsd_name)) {
                break;
            }
        }

        (void) IOObjectRelease (service);
    }

    IOObjectRelease (deviceIterator);

    *servp = service;

    return (service) ? 0 : -1;
}
Esempio n. 3
0
static PyObject* 
usbobserver_find_prop(io_registry_entry_t e, CFStringRef key, int is_string )
{
    char buf[500]; long val = 0;
    PyObject *ans;
    IOOptionBits bits = kIORegistryIterateRecursively | kIORegistryIterateParents;
    CFTypeRef PropRef = IORegistryEntrySearchCFProperty( e, kIOServicePlane, key, NULL, bits );

    if (!PropRef) return NULL;
    buf[0] = '\0';

    if(is_string) {
        CFStringGetCString(PropRef, buf, 500, kCFStringEncodingUTF8);
        ans = PyUnicode_DecodeUTF8(buf, strlen(buf), "replace");
    } else {
        CFNumberGetValue((CFNumberRef)PropRef, kCFNumberLongType, &val);
        ans = PyLong_FromLong(val);
    }

    CFRelease(PropRef);
    return ans;
} 
bool QextSerialEnumerator::getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo )
{
    bool retval = true;
    CFTypeRef bsdPathAsCFString = NULL;
    CFTypeRef productNameAsCFString = NULL;
    CFTypeRef vendorIdAsCFNumber = NULL;
    CFTypeRef productIdAsCFNumber = NULL;
    // check the name of the modem's callout device
    bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey),
                                                        kCFAllocatorDefault, 0);

    // wander up the hierarchy until we find the level that can give us the
    // vendor/product IDs and the product name, if available
    io_registry_entry_t parent;
    kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
    while( kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber )
    {
        if(!productNameAsCFString)
            productNameAsCFString = IORegistryEntrySearchCFProperty(parent,
                                                                    kIOServicePlane,
                                                                    CFSTR("Product Name"),
                                                                    kCFAllocatorDefault, 0);
        vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent,
                                                             kIOServicePlane,
                                                             CFSTR(kUSBVendorID),
                                                             kCFAllocatorDefault, 0);
        productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent,
                                                              kIOServicePlane,
                                                              CFSTR(kUSBProductID),
                                                              kCFAllocatorDefault, 0);
        io_registry_entry_t oldparent = parent;
        kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent);
        IOObjectRelease(oldparent);
    }

    io_string_t ioPathName;
    IORegistryEntryGetPath( service, kIOServicePlane, ioPathName );
    portInfo->physName = ioPathName;

    if( bsdPathAsCFString )
    {
        char path[MAXPATHLEN];
        if( CFStringGetCString((CFStringRef)bsdPathAsCFString, path,
                               PATH_MAX, kCFStringEncodingUTF8) )
            portInfo->portName = path;
        CFRelease(bsdPathAsCFString);
    }

    if(productNameAsCFString)
    {
        char productName[MAXPATHLEN];
        if( CFStringGetCString((CFStringRef)productNameAsCFString, productName,
                               PATH_MAX, kCFStringEncodingUTF8) )
            portInfo->friendName = productName;
        CFRelease(productNameAsCFString);
    }

    if(vendorIdAsCFNumber)
    {
        SInt32 vID;
        if(CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID))
            portInfo->vendorID = vID;
        CFRelease(vendorIdAsCFNumber);
    }

    if(productIdAsCFNumber)
    {
        SInt32 pID;
        if(CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID))
            portInfo->productID = pID;
        CFRelease(productIdAsCFNumber);
    }
    IOObjectRelease(service);
    return retval;
}
Esempio n. 5
0
//================================================================================================
//
//  DeviceAdded
//
//  This routine is the callback for our IOServiceAddMatchingNotification.  When we get called
//  we will look at all the devices that were added and we will:
//
//  1.  Create some private data to relate to each device (in this case we use the service's name
//      and the location ID of the device
//  2.  Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device,
//      using the refCon field to store a pointer to our private data.  When we get called with
//      this interest notification, we can grab the refCon and access our private data.
//
//================================================================================================
static void DeviceAdded(void *refCon, io_iterator_t iterator) {
	kern_return_t kr;
	io_service_t usbDevice;
	IOCFPlugInInterface **plugInInterface = NULL;
	SInt32 score;
	HRESULT res;

	while((usbDevice = IOIteratorNext(iterator))) {
		io_name_t deviceName;
		CFStringRef deviceNameAsCFString;
		UInt32 locationID;
		UInt16 vendorId;
		UInt16 productId;
		UInt16 addr;

		DeviceItem_t* deviceItem = new DeviceItem_t();

		// Get the USB device's name.
		kr = IORegistryEntryGetName(usbDevice, deviceName);
		if(KERN_SUCCESS != kr) {
			deviceName[0] = '\0';
		}

		deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII);


		if(deviceNameAsCFString) {
			Boolean result;
			char    deviceName[MAXPATHLEN];

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(deviceNameAsCFString,
										deviceName,
										sizeof(deviceName),
										kCFStringEncodingUTF8);

			if(result) {
				deviceItem->deviceParams.deviceName = deviceName;
			}

			CFRelease(deviceNameAsCFString);
		}

		CFStringRef manufacturerAsCFString = (CFStringRef)IORegistryEntrySearchCFProperty(
				usbDevice,
				kIOServicePlane,
				CFSTR(kUSBVendorString),
				kCFAllocatorDefault,
				kIORegistryIterateRecursively
			);

		if(manufacturerAsCFString) {
			Boolean result;
			char    manufacturer[MAXPATHLEN];

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(
					manufacturerAsCFString,
					manufacturer,
					sizeof(manufacturer),
					kCFStringEncodingUTF8
				);

			if(result) {
				deviceItem->deviceParams.manufacturer = manufacturer;
			}

			CFRelease(manufacturerAsCFString);
		}

		CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(
				usbDevice,
				kIOServicePlane,
				CFSTR(kUSBSerialNumberString),
				kCFAllocatorDefault,
				kIORegistryIterateRecursively
			);

		if(serialNumberAsCFString) {
			Boolean result;
			char    serialNumber[MAXPATHLEN];

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(
					serialNumberAsCFString,
					serialNumber,
					sizeof(serialNumber),
					kCFStringEncodingUTF8
				);

			if(result) {
				deviceItem->deviceParams.serialNumber = serialNumber;
			}

			CFRelease(serialNumberAsCFString);
		}


		// Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface
		// for our device. This will create the necessary connections between our userland application and the
		// kernel object for the USB Device.
		kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);

		if((kIOReturnSuccess != kr) || !plugInInterface) {
			fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr);
			continue;
		}

		stDeviceListItem *deviceListItem = new stDeviceListItem();

		// Use the plugin interface to retrieve the device interface.
		res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceListItem->deviceInterface);

		// Now done with the plugin interface.
		(*plugInInterface)->Release(plugInInterface);

		if(res || deviceListItem->deviceInterface == NULL) {
			fprintf(stderr, "QueryInterface returned %d.\n", (int) res);
			continue;
		}

		// Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h.
		// In this case, fetch the locationID. The locationID uniquely identifies the device
		// and will remain the same, even across reboots, so long as the bus topology doesn't change.

		kr = (*deviceListItem->deviceInterface)->GetLocationID(deviceListItem->deviceInterface, &locationID);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr);
			continue;
		}
		std::stringstream sstream;
		sstream << std::hex << locationID;
		deviceItem->deviceParams.locationId = sstream.str();

		kr = (*deviceListItem->deviceInterface)->GetDeviceAddress(deviceListItem->deviceInterface, &addr);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetDeviceAddress returned 0x%08x.\n", kr);
			continue;
		}
		deviceItem->deviceParams.deviceAddress = addr;


		kr = (*deviceListItem->deviceInterface)->GetDeviceVendor(deviceListItem->deviceInterface, &vendorId);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetDeviceVendor returned 0x%08x.\n", kr);
			continue;
		}
		deviceItem->deviceParams.vendorId = vendorId;

		kr = (*deviceListItem->deviceInterface)->GetDeviceProduct(deviceListItem->deviceInterface, &productId);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetDeviceProduct returned 0x%08x.\n", kr);
			continue;
		}
		deviceItem->deviceParams.productId = productId;


		// Extract path name as unique key
		io_string_t pathName;
		IORegistryEntryGetPath(usbDevice, kIOServicePlane, pathName);
		deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, pathName, kCFStringEncodingASCII);
		char cPathName[MAXPATHLEN];

		if(deviceNameAsCFString) {
			Boolean result;

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(
					deviceNameAsCFString,
					cPathName,
					sizeof(cPathName),
					kCFStringEncodingUTF8
				);


			CFRelease(deviceNameAsCFString);
		}

		AddItemToList(cPathName, deviceItem);
		deviceListItem->deviceItem = deviceItem;

		if(initialDeviceImport == false) {
			WaitForDeviceHandled();
			currentItem = &deviceItem->deviceParams;
			isAdded = true;
			uv_async_send(&async_handler);
		}

		// Register for an interest notification of this device being removed. Use a reference to our
		// private data as the refCon which will be passed to the notification callback.
		kr = IOServiceAddInterestNotification(
				gNotifyPort, // notifyPort
				usbDevice, // service
				kIOGeneralInterest, // interestType
				DeviceRemoved, // callback
				deviceListItem, // refCon
				&(deviceListItem->notification) // notification
			);

		if(KERN_SUCCESS != kr) {
			printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr);
		}

		// Done with this USB device; release the reference added by IOIteratorNext
		kr = IOObjectRelease(usbDevice);
	}
}
Esempio n. 6
0
/** @brief detect devices based on usb pid / vid.
 *  @return list with usb VID / PID values.
 */
QMap<uint32_t, QString> System::listUsbDevices(void)
{
    QMap<uint32_t, QString> usbids;
    // usb pid detection
    LOG_INFO() << "Searching for USB devices";
#if defined(Q_OS_LINUX)
#if defined(LIBUSB1)
    libusb_device **devs;
    if(libusb_init(NULL) != 0) {
        LOG_ERROR() << "Initializing libusb-1 failed.";
        return usbids;
    }

    if(libusb_get_device_list(NULL, &devs) < 1) {
        LOG_ERROR() << "Error getting device list.";
        return usbids;
    }
    libusb_device *dev;
    int i = 0;
    while((dev = devs[i++]) != NULL) {
        QString name;
        unsigned char buf[256];
        uint32_t id;
        struct libusb_device_descriptor descriptor;
        if(libusb_get_device_descriptor(dev, &descriptor) == 0) {
            id = descriptor.idVendor << 16 | descriptor.idProduct;

            libusb_device_handle *dh;
            if(libusb_open(dev, &dh) == 0) {
                libusb_get_string_descriptor_ascii(dh, descriptor.iManufacturer, buf, 256);
                name += QString::fromLatin1((char*)buf) + " ";
                libusb_get_string_descriptor_ascii(dh, descriptor.iProduct, buf, 256);
                name += QString::fromLatin1((char*)buf);
                libusb_close(dh);
            }
            if(name.isEmpty())
                name = tr("(no description available)");
            if(id) {
                usbids.insertMulti(id, name);
                LOG_INFO("USB: 0x%08x, %s", id, name.toLocal8Bit().data());
            }
        }
    }

    libusb_free_device_list(devs, 1);
    libusb_exit(NULL);
#else
    usb_init();
    usb_find_busses();
    usb_find_devices();
    struct usb_bus *b;
    b = usb_busses;

    while(b) {
        if(b->devices) {
            struct usb_device *u;
            u = b->devices;
            while(u) {
                uint32_t id;
                id = u->descriptor.idVendor << 16 | u->descriptor.idProduct;
                // get identification strings
                usb_dev_handle *dev;
                QString name;
                char string[256];
                int res;
                dev = usb_open(u);
                if(dev) {
                    if(u->descriptor.iManufacturer) {
                        res = usb_get_string_simple(dev, u->descriptor.iManufacturer,
                                                    string, sizeof(string));
                        if(res > 0)
                            name += QString::fromLatin1(string) + " ";
                    }
                    if(u->descriptor.iProduct) {
                        res = usb_get_string_simple(dev, u->descriptor.iProduct,
                                                    string, sizeof(string));
                        if(res > 0)
                            name += QString::fromLatin1(string);
                    }
                    usb_close(dev);
                }
                if(name.isEmpty()) name = tr("(no description available)");

                if(id) {
                    usbids.insertMulti(id, name);
                    LOG_INFO() << "USB:" << QString("0x%1").arg(id, 8, 16) << name;
                }
                u = u->next;
            }
        }
        b = b->next;
    }
#endif
#endif

#if defined(Q_OS_MACX)
    kern_return_t result = KERN_FAILURE;
    CFMutableDictionaryRef usb_matching_dictionary;
    io_iterator_t usb_iterator = IO_OBJECT_NULL;
    usb_matching_dictionary = IOServiceMatching(kIOUSBDeviceClassName);
    result = IOServiceGetMatchingServices(kIOMasterPortDefault, usb_matching_dictionary,
                                          &usb_iterator);
    if(result) {
        LOG_ERROR() << "USB: IOKit: Could not get matching services.";
        return usbids;
    }

    io_object_t usbCurrentObj;
    while((usbCurrentObj = IOIteratorNext(usb_iterator))) {
        uint32_t id;
        QString name;
        /* get vendor ID */
        CFTypeRef vidref = NULL;
        int vid = 0;
        vidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idVendor"),
                                kCFAllocatorDefault, 0);
        CFNumberGetValue((CFNumberRef)vidref, kCFNumberIntType, &vid);
        CFRelease(vidref);

        /* get product ID */
        CFTypeRef pidref = NULL;
        int pid = 0;
        pidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idProduct"),
                                kCFAllocatorDefault, 0);
        CFNumberGetValue((CFNumberRef)pidref, kCFNumberIntType, &pid);
        CFRelease(pidref);
        id = vid << 16 | pid;

        /* get product vendor */
        char vendor_buf[256];
        CFIndex vendor_buflen = 256;
        CFTypeRef vendor_name_ref = NULL;

        vendor_name_ref = IORegistryEntrySearchCFProperty(usbCurrentObj,
                                 kIOServicePlane, CFSTR("USB Vendor Name"),
                                 kCFAllocatorDefault, 0);
        if(vendor_name_ref != NULL) {
            CFStringGetCString((CFStringRef)vendor_name_ref, vendor_buf, vendor_buflen,
                               kCFStringEncodingUTF8);
            name += QString::fromUtf8(vendor_buf) + " ";
            CFRelease(vendor_name_ref);
        }
        else {
            name += QObject::tr("(unknown vendor name) ");
        }

        /* get product name */
        char product_buf[256];
        CFIndex product_buflen = 256;
        CFTypeRef product_name_ref = NULL;

        product_name_ref = IORegistryEntrySearchCFProperty(usbCurrentObj,
                                kIOServicePlane, CFSTR("USB Product Name"),
                                kCFAllocatorDefault, 0);
        if(product_name_ref != NULL) {
            CFStringGetCString((CFStringRef)product_name_ref, product_buf, product_buflen,
                               kCFStringEncodingUTF8);
            name += QString::fromUtf8(product_buf);
            CFRelease(product_name_ref);
        }
        else {
            name += QObject::tr("(unknown product name)");
        }

        if(id) {
            usbids.insertMulti(id, name);
            LOG_INFO() << "USB:" << QString("0x%1").arg(id, 8, 16) << name;
        }

    }
    IOObjectRelease(usb_iterator);
#endif

#if defined(Q_OS_WIN32)
    HDEVINFO deviceInfo;
    SP_DEVINFO_DATA infoData;
    DWORD i;

    // Iterate over all devices
    // by doing it this way it's unneccessary to use GUIDs which might be not
    // present in current MinGW. It also seemed to be more reliably than using
    // a GUID.
    // See KB259695 for an example.
    deviceInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);

    infoData.cbSize = sizeof(SP_DEVINFO_DATA);

    for(i = 0; SetupDiEnumDeviceInfo(deviceInfo, i, &infoData); i++) {
        DWORD data;
        LPTSTR buffer = NULL;
        DWORD buffersize = 0;
        QString description;

        // get device descriptor first
        // for some reason not doing so results in bad things (tm)
        while(!SetupDiGetDeviceRegistryProperty(deviceInfo, &infoData,
            SPDRP_DEVICEDESC, &data, (PBYTE)buffer, buffersize, &buffersize)) {
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                if(buffer) free(buffer);
                // double buffer size to avoid problems as per KB888609
                buffer = (LPTSTR)malloc(buffersize * 2);
            }
            else {
                break;
            }
        }
        if(!buffer) {
            LOG_WARNING() << "Got no device description"
                          << "(SetupDiGetDeviceRegistryProperty), item" << i;
            continue;
        }
        description = QString::fromWCharArray(buffer);

        // now get the hardware id, which contains PID and VID.
        while(!SetupDiGetDeviceRegistryProperty(deviceInfo, &infoData,
            SPDRP_HARDWAREID, &data, (PBYTE)buffer, buffersize, &buffersize)) {
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                if(buffer) free(buffer);
                // double buffer size to avoid problems as per KB888609
                buffer = (LPTSTR)malloc(buffersize * 2);
            }
            else {
                break;
            }
        }

        if(buffer) {
            // convert buffer text to upper case to avoid depending on the case of
            // the keys (W7 uses different casing than XP at least), in addition
            // XP may use "Vid_" and "Pid_".
            QString data = QString::fromWCharArray(buffer).toUpper();
            QRegExp rex("USB\\\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4}).*");
            if(rex.indexIn(data) >= 0) {
                uint32_t id;
                id = rex.cap(1).toUInt(0, 16) << 16 | rex.cap(2).toUInt(0, 16);
                usbids.insert(id, description);
                LOG_INFO() << "USB:" << QString("0x%1").arg(id, 8, 16);
            }
            free(buffer);
        }
    }
    SetupDiDestroyDeviceInfoList(deviceInfo);

#endif
    return usbids;
}
static stDeviceListItem* GetSerialDevices() {
  char bsdPath[MAXPATHLEN];

  io_iterator_t serialPortIterator;
  FindModems(&serialPortIterator);

  kern_return_t kernResult = KERN_FAILURE;
  Boolean modemFound = false;

  // Initialize the returned path
  *bsdPath = '\0';

  stDeviceListItem* devices = NULL;
  stDeviceListItem* lastDevice = NULL;
  int length = 0;

  io_service_t modemService;
  while ((modemService = IOIteratorNext(serialPortIterator))) {
    CFTypeRef bsdPathAsCFString;
    bsdPathAsCFString = IORegistryEntrySearchCFProperty(
      modemService,
      kIOServicePlane,
      CFSTR(kIODialinDeviceKey),
      kCFAllocatorDefault,
      kIORegistryIterateRecursively);

    if (bsdPathAsCFString) {
      Boolean result;

      // Convert the path from a CFString to a C (NUL-terminated)
      result = CFStringGetCString((CFStringRef) bsdPathAsCFString,
                    bsdPath,
                    sizeof(bsdPath),
                    kCFStringEncodingUTF8);
      CFRelease(bsdPathAsCFString);

      if (result) {
        stDeviceListItem *deviceListItem = reinterpret_cast<stDeviceListItem*>( malloc(sizeof(stDeviceListItem)));
        stSerialDevice *serialDevice = &(deviceListItem->value);
        snprintf(serialDevice->port, sizeof(serialDevice->port), "%s", bsdPath);
        memset(serialDevice->locationId, 0, sizeof(serialDevice->locationId));
        memset(serialDevice->vendorId, 0, sizeof(serialDevice->vendorId));
        memset(serialDevice->productId, 0, sizeof(serialDevice->productId));
        serialDevice->manufacturer[0] = '\0';
        serialDevice->serialNumber[0] = '\0';
        deviceListItem->next = NULL;
        deviceListItem->length = &length;

        if (devices == NULL) {
          devices = deviceListItem;
        } else {
          lastDevice->next = deviceListItem;
        }

        lastDevice = deviceListItem;
        length++;

        modemFound = true;
        kernResult = KERN_SUCCESS;

        uv_mutex_lock(&list_mutex);

        io_service_t device = GetUsbDevice(modemService);

        if (device) {
          CFStringRef manufacturerAsCFString = (CFStringRef) IORegistryEntryCreateCFProperty(device,
                      CFSTR(kUSBVendorString),
                      kCFAllocatorDefault,
                      0);

          if (manufacturerAsCFString) {
            Boolean result;
            char    manufacturer[MAXPATHLEN];

            // Convert from a CFString to a C (NUL-terminated)
            result = CFStringGetCString(manufacturerAsCFString,
                          manufacturer,
                          sizeof(manufacturer),
                          kCFStringEncodingUTF8);

            if (result) {
              snprintf(serialDevice->manufacturer, sizeof(serialDevice->manufacturer), "%s", manufacturer);
            }

            CFRelease(manufacturerAsCFString);
          }

          CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device,
                      kIOServicePlane,
                      CFSTR(kUSBSerialNumberString),
                      kCFAllocatorDefault,
                      kIORegistryIterateRecursively);

          if (serialNumberAsCFString) {
            Boolean result;
            char    serialNumber[MAXPATHLEN];

            // Convert from a CFString to a C (NUL-terminated)
            result = CFStringGetCString(serialNumberAsCFString,
                          serialNumber,
                          sizeof(serialNumber),
                          kCFStringEncodingUTF8);

            if (result) {
              snprintf(serialDevice->serialNumber, sizeof(serialDevice->serialNumber), "%s", serialNumber);
            }

            CFRelease(serialNumberAsCFString);
          }

          IOCFPlugInInterface **plugInInterface = NULL;
          SInt32        score;
          HRESULT       res;

          IOUSBDeviceInterface  **deviceInterface = NULL;

          kernResult = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
                               &plugInInterface, &score);

          if ((kIOReturnSuccess != kernResult) || !plugInInterface) {
            continue;
          }

          // Use the plugin interface to retrieve the device interface.
          res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
                               reinterpret_cast<LPVOID*> (&deviceInterface));

          // Now done with the plugin interface.
          (*plugInInterface)->Release(plugInInterface);

          if (res || deviceInterface == NULL) {
            continue;
          }

          // Extract the desired Information
          ExtractUsbInformation(serialDevice, deviceInterface);

          // Release the Interface
          (*deviceInterface)->Release(deviceInterface);

          // Release the device
          (void) IOObjectRelease(device);
        }

        uv_mutex_unlock(&list_mutex);
      }
    }

    // Release the io_service_t now that we are done with it.
    (void) IOObjectRelease(modemService);
  }

  IOObjectRelease(serialPortIterator);  // Release the iterator.

  return devices;
}
Esempio n. 8
0
	std::map<int, std::pair<std::string, std::string> > SerialPortEnumerator::getPorts()
	{
		std::map<int, std::pair<std::string, std::string> > ports;
		


#ifdef MACOSX
		// use IOKit to enumerates devices
		
		// get a matching dictionary to specify which IOService class we're interested in
		CFMutableDictionaryRef classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
		if (classesToMatch == NULL)
			throw DashelException(DashelException::EnumerationError, 0, "IOServiceMatching returned a NULL dictionary");
		
		// specify all types of serial devices
		CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
		
		// get an iterator to serial port services
		io_iterator_t matchingServices;
		kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, &matchingServices);    
		if (KERN_SUCCESS != kernResult)
			throw DashelException(DashelException::EnumerationError, kernResult, "IOServiceGetMatchingServices failed");
			
		// iterate over services
		io_object_t modemService;
		int index = 0;
		while((modemService = IOIteratorNext(matchingServices)))
		{
			// get path for device
			CFTypeRef bsdPathAsCFString = IORegistryEntryCreateCFProperty(modemService, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
			if (bsdPathAsCFString)
			{
				std::string path;
				char cStr[255];
				std::string name;
				
				bool res = CFStringGetCString((CFStringRef) bsdPathAsCFString, cStr, 255, kCFStringEncodingUTF8);
				if(res)
					path = cStr;
				else
					throw DashelException(DashelException::EnumerationError, 0, "CFStringGetCString failed");
				
				CFRelease(bsdPathAsCFString);
				
				CFTypeRef fn = IORegistryEntrySearchCFProperty(modemService, kIOServicePlane, CFSTR("USB Product Name"), kCFAllocatorDefault,
										kIORegistryIterateRecursively | kIORegistryIterateParents);
				if(fn) {
					res = CFStringGetCString((CFStringRef) fn, cStr, 255, kCFStringEncodingUTF8);
					if(res) 
						name = cStr;
					else
						throw DashelException(DashelException::EnumerationError, 0, "CFStringGetString failed");

					CFRelease(fn);
				} else 
					name = "Serial Port";
				name = name + " (" + path + ")";
				ports[index++] = std::make_pair<std::string, std::string>(path, name);
			}
			else
				throw DashelException(DashelException::EnumerationError, 0, "IORegistryEntryCreateCFProperty returned a NULL path");
			
			// release service
			IOObjectRelease(modemService);
		}

		IOObjectRelease(matchingServices);

			
#elif defined(USE_LIBUDEV)

		struct udev *udev;
		struct udev_enumerate *enumerate;
		struct udev_list_entry *devices, *dev_list_entry;
		struct udev_device *dev;
		int index = 0;

		udev = udev_new();
		if(!udev)
			throw DashelException(DashelException::EnumerationError, 0, "Cannot create udev context");

		enumerate = udev_enumerate_new(udev);
		udev_enumerate_add_match_subsystem(enumerate, "tty");
		udev_enumerate_scan_devices(enumerate);
		devices = udev_enumerate_get_list_entry(enumerate);

		udev_list_entry_foreach(dev_list_entry, devices) {
			const char *sysfs_path;
			struct udev_device *usb_dev;
			const char * path;
			struct stat st;
			unsigned int maj,min;

			/* Get sysfs path and create the udev device */
			sysfs_path = udev_list_entry_get_name(dev_list_entry);
			dev = udev_device_new_from_syspath(udev, sysfs_path);

			// Some sanity check
			path = udev_device_get_devnode(dev);
			if(stat(path, &st)) 
				throw DashelException(DashelException::EnumerationError, 0, "Cannot stat serial port");
			
			if(!S_ISCHR(st.st_mode))
				throw DashelException(DashelException::EnumerationError, 0, "Serial port is not character device");

			// Get the major/minor number
			maj = major(st.st_rdev);
			min = minor(st.st_rdev);

			// Ignore all the non physical ports
			if(!(maj == 2 || (maj == 4 && min < 64) || maj == 3 || maj == 5)) {
				ostringstream oss;

				// Check if usb, if yes get the device name
				usb_dev = udev_device_get_parent_with_subsystem_devtype(dev,"usb","usb_device");
				if(usb_dev)
					oss << udev_device_get_sysattr_value(usb_dev,"product");
				else
					oss << "Serial Port";

				oss << " (" << path << ")";

				ports[index++] = std::make_pair<std::string, std::string>(path,oss.str());
			}
			udev_device_unref(dev);
		}
		
		udev_enumerate_unref(enumerate);

		udev_unref(udev);

#elif defined(USE_HAL)

		// use HAL to enumerates devices
		DBusConnection* dbusConnection = dbus_bus_get(DBUS_BUS_SYSTEM, 0);
		if (!dbusConnection)
			throw DashelException(DashelException::EnumerationError, 0, "cannot connect to D-BUS.");
		
		LibHalContext* halContext = libhal_ctx_new();
		if (!halContext)
			throw DashelException(DashelException::EnumerationError, 0, "cannot create HAL context: cannot create context");
		if (!libhal_ctx_set_dbus_connection(halContext, dbusConnection))
			throw DashelException(DashelException::EnumerationError, 0, "cannot create HAL context: cannot connect to D-BUS");
		if (!libhal_ctx_init(halContext, 0))
			throw DashelException(DashelException::EnumerationError, 0, "cannot create HAL context: cannot init context");
		
		int devicesCount;
		char** devices = libhal_find_device_by_capability(halContext, "serial", &devicesCount, 0);
		for (int i = 0; i < devicesCount; i++)
		{
			char* devFileName = libhal_device_get_property_string(halContext, devices[i], "serial.device", 0);
			char* info = libhal_device_get_property_string(halContext, devices[i], "info.product", 0);
			int port = libhal_device_get_property_int(halContext, devices[i], "serial.port", 0);
			
			ostringstream oss;
			oss << info << " " << port;
			ports[devicesCount - i] = std::make_pair<std::string, std::string>(devFileName, oss.str());
			
			libhal_free_string(info);
			libhal_free_string(devFileName);
		}
		
		libhal_free_string_array(devices);
		libhal_ctx_shutdown(halContext, 0);
		libhal_ctx_free(halContext);
#endif
		
		return ports;
	};
static kern_return_t ModemOrSerialDeviceToDictProc(void *contextPtr, 
												   io_object_t interface, 
												   CFMutableDictionaryRef interfaceInfo)
	// This routine is called (via function pointer) by AddMatchingDevicesToArray 
	// to add modem/serial-specific information for the modem/serial-like device 
	// (which includes internal modems, built-in serial ports, USB serial adapters, 
	// USB modems, and IrDA) specified by interface to the interfaceInfo dictionary.
{
	#pragma unused(contextPtr)
	kern_return_t 			err;
	kern_return_t 			junk;
	CFMutableDictionaryRef	interfaceDict;
	CFStringRef				baseName;
	CFNumberRef				supportsHold;
	
	assert(interface        != 0  );
	assert(interfaceInfo    != NULL);

	interfaceDict = NULL;
	supportsHold  = false;
	
    err = IORegistryEntryCreateCFProperties(interface, &interfaceDict, NULL, kNilOptions );
 
    // Get IOTTYBaseName

	// Yetch.  We specifically exclude ports named "irda" because otherwise the IrDA 
	// ports on the original iMac (rev's A through D) show up as serial ports.  Given 
	// that only the rev A actually had an IrDA port, and Mac OS X doesn't even support 
	// it, these ports definitely shouldn't be listed.
	    
    if (err == 0 
    		&& CFDictionaryGetValueIfPresent(interfaceDict, CFSTR(kIOTTYBaseNameKey), (const void **) &baseName )
    		&& ! CFEqual(baseName, CFSTR("irda")) ) {
    	junk = CFQDictionarySetNumber(interfaceInfo, kSortOrderKey, kSerialSortOrder);
    	assert(junk == 0);
    
		// kSCPropNetInterfaceDeviceName

        CFDictionarySetValue(interfaceInfo, kSCPropNetInterfaceDeviceName, CFDictionaryGetValue(interfaceDict, CFSTR(kIOTTYDeviceKey)));
        
        // kSCPropNetInterfaceHardware
        
        CFDictionarySetValue(interfaceInfo, kSCPropNetInterfaceHardware, kSCEntNetModem);

        // kSCPropNetInterfaceType
        
        CFDictionarySetValue(interfaceInfo, kSCPropNetInterfaceType, kSCValNetInterfaceTypePPP);

        // kSCPropNetInterfaceSubType
        
        CFDictionarySetValue(interfaceInfo, kSCPropNetInterfaceSubType, kSCValNetInterfaceSubTypePPPSerial);

        // "HardwareVariant"
        
        // A special hack for IrDA, modelled directly on the code from the 
        // control panel.
        
        if ( CFStringHasPrefix(baseName, kMoreSCValNetInterfaceHardwareVariantIrDACOMM) ) {
	    	junk = CFQDictionarySetNumber(interfaceInfo, kSortOrderKey, kIrDASerialSortOrder);
    		assert(junk == 0);
    		
        	CFDictionarySetValue(interfaceInfo, kMoreSCPropNetInterfaceHardwareVariant, kMoreSCValNetInterfaceHardwareVariantIrDACOMM);
        }
        
        // kSCPropNetInterfaceSupportsModemOnHold
        
		supportsHold = (CFNumberRef) IORegistryEntrySearchCFProperty(interface, kIOServicePlane,
                            						  CFSTR("V92Modem"), 
                            						  NULL, 
                            						  kIORegistryIterateRecursively | kIORegistryIterateParents);
		if (supportsHold != NULL) {
			assert( CFGetTypeID(supportsHold) == CFNumberGetTypeID() );
			CFDictionarySetValue(interfaceInfo, kSCPropNetInterfaceSupportsModemOnHold, supportsHold);
		}

		// kSCPropUserDefinedName set up by caller.
    }
    
    CFQRelease(interfaceDict);
   	CFQRelease(supportsHold);
    
    return err;
}
static kern_return_t CopyUserVisibleNameForModemOrSerialPort(io_object_t interface, 
															 CFMutableDictionaryRef interfaceInfo,
															 CFStringRef *userVisibleName)
	// Given a serial device (interface) and a dictionary of 
	// information about the device (interfaceInfo), guess at the 
	// user-visible name for the device.
	// 
	// I'm somewhat unhappy with this code (both its length and its style) 
	// but there really isn't a better solution right now.  Apple 
	// is actively working on a better way to do this.
{
	kern_return_t 	err;
	kern_return_t 	junk;
	CFStringRef   	serialType;
	Boolean			isModem;
	CFStringRef		baseName;
	CFStringRef		productName;
	
	assert(interface        != 0  );
	assert(interfaceInfo    != NULL);
	assert( userVisibleName != NULL);
	assert(*userVisibleName == NULL);

	serialType = NULL;
	baseName = NULL;
	productName = NULL;
	
	// Determine whether the device is a modem.
	
	err = 0;
	serialType = (CFStringRef) IORegistryEntryCreateCFProperty(interface, CFSTR(kIOSerialBSDTypeKey), NULL, kNilOptions);
	if (serialType == NULL) {
		err = -1;
	}
	if (err == 0) {
		isModem = CFEqual(serialType, CFSTR(kIOSerialBSDModemType));
		if (isModem) {
			junk = CFQDictionarySetNumber(interfaceInfo, kSortOrderKey, kModemSortOrder);
			assert(junk == 0);
		}
	}

	// Get the "IOTTYBaseName" property and derive the user-visible name from that.
	
	if (err == 0) {
		baseName = (CFStringRef) IORegistryEntryCreateCFProperty(interface, CFSTR(kIOTTYBaseNameKey), NULL, kNilOptions);
		if (baseName == NULL) {
			err = -1;
		}
	}
	if (err == noErr) {
		// See whether the device has a "Product Name" property anywhere in its 
		// parent chain.

		productName = (CFStringRef) IORegistryEntrySearchCFProperty(interface, kIOServicePlane,
                            						  CFSTR(kIOPropertyProductNameKey), 
                            						  NULL, 
                            						  kIORegistryIterateRecursively | kIORegistryIterateParents);
	}
	if (err == 0) {
	    if ( isModem && CFEqualString(baseName, CFSTR("modem")) ) {

			junk = CFQDictionarySetNumber(interfaceInfo, kSortOrderKey, kInternalModemSortOrder);
			assert(junk == 0);
	    	
	        *userVisibleName = kMoreSCPortLabelModemInternal;
		    CFRetain(*userVisibleName);
	    } else if ( CFEqualString(baseName, CFSTR("modem"))) {
	        *userVisibleName = kMoreSCPortLabelModemPort;
		    CFRetain(*userVisibleName);
	    } else if ( CFEqualString(baseName, CFSTR("printer"))) {
	        *userVisibleName = kMoreSCPortLabelPrinterPort;
		    CFRetain(*userVisibleName);
	    } else if ( CFEqualString(baseName, CFSTR("modem-printer"))) {
	        *userVisibleName = kMoreSCPortLabelModemPrinterPort;
		    CFRetain(*userVisibleName);
	    } else if ( CFEqualString(baseName, CFSTR("IrDA-IrCOMM"))) {
	        *userVisibleName = kMoreSCPortLabelModemIrDA;
		    CFRetain(*userVisibleName);
	    } else if ( CFEqualString(baseName, CFSTR("usbmodem")) || (productName != NULL) ) {

			// It may not be a modem (it may just be a USB serial device), so 
			// we only override the default sort order (serial) if the we 
			// know it's a modem.
			
			if (isModem) {
				junk = CFQDictionarySetNumber(interfaceInfo, kSortOrderKey, kUSBModemSortOrder);
				assert(junk == 0);
			}
			
			if (productName != NULL) {
				// Serial or modem USB device with "Product Name" key.
				*userVisibleName = productName;
			} else {
				// productName is NULL so baseName must be "usbmodem".
		        *userVisibleName = kMoreSCPortLabelModemUSB;
			}
		    CFRetain(*userVisibleName);
			
	    } else {
			CFStringRef 		baseNameProperty;
			CFMutableStringRef	ttyBase;
			
			ttyBase = NULL;
			baseNameProperty = (CFStringRef) IORegistryEntryCreateCFProperty(interface, CFSTR(kIOTTYBaseNameKey), NULL, kNilOptions);
			if (baseNameProperty != NULL) {
				ttyBase = CFStringCreateMutableCopy(NULL, 0, baseNameProperty);
			}
			if (ttyBase == NULL) {
				CFDictionarySetValue(interfaceInfo, CFSTR(kIOTTYBaseNameKey), CFSTR("unknown"));
			} else {
				CFStringLowercase(ttyBase, NULL);
				CFDictionarySetValue(interfaceInfo, CFSTR(kIOTTYBaseNameKey), ttyBase);
			}
			CFQRelease(ttyBase);
			CFQRelease(baseNameProperty);

	    	// This string is pretty unlikely, but it does match what the 
	    	// Network preferences panel creates in Mac OS X 10.1.x for 
	    	// unknown devices, such as a Keyspan serial adapter.

	    	*userVisibleName = kMoreSCPortLabelSerial;
		    CFRetain(*userVisibleName);
	    }
	}

	CFQRelease(serialType);
	CFQRelease(baseName);
	CFQRelease(productName);
	
	assert( (err == 0) == (*userVisibleName != NULL) );
	
	return err;
}
Esempio n. 11
0
TorcUSBDevice TorcUSBPrivOSX::GetDevice(io_service_t Device)
{
    TorcUSBDevice usbdevice;

    if (Device)
    {
        io_name_t buffer;
        IOReturn ok = IORegistryEntryGetName(Device, buffer);

        QString name = kIOReturnSuccess == ok ?  QString(buffer) : "Unknown";

        IOCFPlugInInterface **plugin;
        qint32 score;

        ok = IOCreatePlugInInterfaceForService(Device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score);
        if (kIOReturnSuccess == ok)
        {
            IOUSBDeviceInterface **interface;

            ok = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void**)&interface);
            if (kIOReturnSuccess == ok)
            {
                quint16  vendor;
                quint16  product;
                quint32  location;
                quint8   classtype;

                IOReturn vendorok    = (*interface)->GetDeviceVendor(interface, &vendor);
                IOReturn productok   = (*interface)->GetDeviceProduct(interface, &product);
                IOReturn locationok  = (*interface)->GetLocationID(interface, &location);
                IOReturn classtypeok = (*interface)->GetDeviceClass(interface, &classtype);

                if ((classtypeok == kIOReturnSuccess) && !TorcUSBDevice::IgnoreClass(ToTorcClass(classtype)))
                {
                    TorcUSBDevice::Classes torcclass = ToTorcClass(classtype);

                    io_service_t usbinterface;
                    io_iterator_t iterator;
                    IOUSBFindInterfaceRequest request;
                    request.bInterfaceClass    = kIOUSBFindInterfaceDontCare;
                    request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
                    request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
                    request.bAlternateSetting  = kIOUSBFindInterfaceDontCare;

                    ok = (*interface)->CreateInterfaceIterator(interface, &request, &iterator);

                    while ((ok == kIOReturnSuccess) && (usbinterface = IOIteratorNext(iterator)))
                    {
                        IOCFPlugInInterface **interfaceplugin;
                        if (kIOReturnSuccess == IOCreatePlugInInterfaceForService(usbinterface, kIOUSBInterfaceUserClientTypeID,
                                                                                  kIOCFPlugInInterfaceID, &interfaceplugin, &score))
                        {
                            IOUSBInterfaceInterface** interfaceinterface;
                            if (kIOReturnSuccess == (*interfaceplugin)->QueryInterface(interfaceplugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
                                                                        (void**)&interfaceinterface))
                            {
                                QString path = locationok == kIOReturnSuccess ? QString::number(location) : "Error";

                                quint8 interfaceclass;
                                IOReturn result = (*interfaceinterface)->GetInterfaceClass(interfaceinterface, &interfaceclass);

                                if (result == kIOReturnSuccess)
                                {
                                    io_registry_entry_t parent;
                                    kern_return_t kernresult;
                                    kernresult = IORegistryEntryGetParentEntry(usbinterface, kIOServicePlane, &parent);
                                    if (kernresult == KERN_SUCCESS)
                                    {
                                        CFStringRef pathstring = (CFStringRef)IORegistryEntrySearchCFProperty(parent,
                                                kIOServicePlane, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, kIORegistryIterateRecursively);
                                        if (pathstring)
                                            path = CFStringReftoQString(pathstring);
                                        IOObjectRelease(parent);
                                    }
                                }

                                usbdevice = TorcUSBDevice(path, vendorok == kIOReturnSuccess ? vendor : 0,
                                                          productok == kIOReturnSuccess ? product : 0, torcclass);
                                usbdevice.m_product = name;
                            }

                            IODestroyPlugInInterface(interfaceplugin);
                        }

                        IOObjectRelease(usbinterface);
                    }
                }
            }

            IODestroyPlugInInterface(plugin);
        }
    }

    return usbdevice;
}
Esempio n. 12
0
/*
 * Get a list of SD card devices.
 * Linux version.
 */
void get_devices(char *devtab[], int maxdev)
{
    int ndev = 0;

#if defined(__linux__)
    /*
     * Create the udev object.
     */
    struct udev *udev = udev_new();
    if (! udev) {
        printf("Can't create udev\n");
        quit(0);
    }

    /*
     * Create a list of the devices in the 'block' subsystem.
     */
    struct udev_enumerate *enumerate = udev_enumerate_new(udev);
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_scan_devices(enumerate);

    struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);

    /*
     * For each item enumerated, print out its information.
     */
    struct udev_list_entry *dev_list_entry;
    udev_list_entry_foreach(dev_list_entry, devices) {
        if (ndev >= maxdev)
            break;

        /*
         * Get the filename of the /sys entry for the device
         * and create a udev_device object (dev) representing it.
         */
        const char *path = udev_list_entry_get_name(dev_list_entry);
        struct udev_device *dev = udev_device_new_from_syspath(udev, path);

        /*
         * Get the parent device with the subsystem/devtype pair
         * of "usb"/"usb_device".
         */
        struct udev_device *usb = udev_device_get_parent_with_subsystem_devtype(dev,
               "usb", "usb_device");
        if (! usb) {
            //printf("Unable to find parent usb device.\n");
            continue;
        }

        /* Get the 'removable' attribute. */
        const char *removable = udev_device_get_sysattr_value(dev, "removable");
        if (! removable || *removable != '1') {
            continue;
        }

        /* Get the disk size in 512-byte blocks. */
        unsigned size = strtoul(udev_device_get_sysattr_value(dev, "size"), 0, 0);
        if (size == 0) {
            /* SD reader without SD card inserted. */
            continue;
        }

        /* Get the path to the device node in /dev. */
        const char *devpath = udev_device_get_devnode(dev);

        /* From here, we can call get_sysattr_value() for each file
         * in the device's /sys entry. The strings passed into these
         * functions (idProduct, idVendor, serial, etc.) correspond
         * directly to the files in the directory which represents
         * the USB device. Note that USB strings are Unicode, UCS2
         * encoded, but the strings returned from
         * udev_device_get_sysattr_value() are UTF-8 encoded.
         */
        const char *vendor  = udev_device_get_sysattr_value(usb, "manufacturer");
        const char *product = udev_device_get_sysattr_value(usb, "product");

        char buf[1024];
        sprintf(buf, "%s - %s %s, size %u MB",
            devpath, vendor, product, size/2000);
        udev_device_unref(usb);
        devtab[ndev++] = strdup(buf);
    }

    /* Free the enumerator object */
    udev_enumerate_unref(enumerate);
    udev_unref(udev);

#elif defined(__APPLE__)
    /*
     * Create a list of the devices in the 'IOMedia' class.
     */
    CFMutableDictionaryRef dict = IOServiceMatching(kIOMediaClass);
    if (! dict) {
        printf("Cannot create IO Service dictionary.\n");
        return;
    }

    /*
     * Select devices with attributes Removeable=True and Whole=True.
     */
    CFDictionarySetValue(dict, CFSTR(kIOMediaRemovableKey), kCFBooleanTrue);
    CFDictionarySetValue(dict, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);

    io_iterator_t devices = IO_OBJECT_NULL;
    kern_return_t result = IOServiceGetMatchingServices(kIOMasterPortDefault,
        dict, &devices);
    if (result != KERN_SUCCESS) {
        printf("Cannot find matching IO services.\n");
        return;
    }

    /*
     * For each matching device, print out its information.
     */
    io_object_t device;
    while ((device = IOIteratorNext(devices)) != MACH_PORT_NULL) {
        /*
         * Get device path.
         */
        char devname[1024] = "/dev/r";
        CFStringRef ref = (CFStringRef) IORegistryEntrySearchCFProperty(device,
            kIOServicePlane, CFSTR(kIOBSDNameKey),
            kCFAllocatorDefault, kIORegistryIterateRecursively);
        if (! ref || ! CFStringGetCString(ref, devname + 6,
            sizeof(devname) - 6, kCFStringEncodingUTF8)) {
            /* Cannot get device path. */
            continue;
        }

        /*
         * Get device size in bytes.
         */
        long long size;
        ref = IORegistryEntryCreateCFProperty(device,
            CFSTR(kIOMediaSizeKey), kCFAllocatorDefault, 0);
        if (! ref || ! CFNumberGetValue((CFNumberRef)ref, kCFNumberLongLongType, &size)) {
            /* Cannot get device size. */
            continue;
        }

        /*
         * Get a list of device characteristics.
         */
        CFMutableDictionaryRef dict = (CFMutableDictionaryRef)
            IORegistryEntrySearchCFProperty(device, kIOServicePlane,
            CFSTR(kIOPropertyDeviceCharacteristicsKey),
            kCFAllocatorDefault, kIORegistryIterateParents | kIORegistryIterateRecursively);
        if (! dict) {
            /* Cannot get device characteristics. */
            continue;
        }

        /*
         * Get vendor and product names.
         */
        char vendor[1024], product[1024];
        ref = CFDictionaryGetValue(dict, CFSTR(kIOPropertyVendorNameKey));
        if (! ref || ! CFStringGetCString(ref, vendor,
            sizeof(vendor), kCFStringEncodingUTF8)) {
            /* Cannot get vendor name. */
            continue;
        }
        ref = CFDictionaryGetValue(dict, CFSTR(kIOPropertyProductNameKey));
        if (! ref || ! CFStringGetCString(ref, product,
            sizeof(product), kCFStringEncodingUTF8)) {
            /* Cannot get product name. */
            continue;
        }

        char buf[1024];
        sprintf(buf, "%s - size %u MB, %s %s",
            devname, (unsigned) (size / 1000000), vendor, product);
        IOObjectRelease(device);
        devtab[ndev++] = strdup(buf);
    }

    /* Free the iterator object */
    IOObjectRelease(devices);
#else
    printf("Don't know how to get the list of CD devices on this system.\n");
#endif

    devtab[ndev] = 0;
}
Esempio n. 13
0
kern_return_t UsbSerial::getDevicePath(io_iterator_t serialPortIterator, char *path, CFIndex maxPathSize)
{
    io_object_t modemService;
		char productName[50] = "";
    kern_return_t kernResult = KERN_FAILURE;
    Boolean deviceFound = false;
    // Initialize the returned path
    *path = '\0';
	
	CFMutableDictionaryRef bsdMatchingDictionary;
	
	// create a dictionary that looks for all BSD modems
	bsdMatchingDictionary = IOServiceMatching( kIOSerialBSDServiceValue );
	if (bsdMatchingDictionary == NULL)
		printf("IOServiceMatching returned a NULL dictionary.\n");
	else
		CFDictionarySetValue(bsdMatchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDModemType));
	
	// then create the iterator with all the matching devices
	kernResult = IOServiceGetMatchingServices( kIOMasterPortDefault, bsdMatchingDictionary, &serialPortIterator );    
	if ( KERN_SUCCESS != kernResult )
	{
		printf("IOServiceGetMatchingServices returned %d\n", kernResult);
		return kernResult;
	}
	
	// Iterate through all modems found. In this example, we bail after finding the first modem.
	while ((modemService = IOIteratorNext(serialPortIterator)) && !deviceFound)
	{
		CFTypeRef bsdPathAsCFString;
		CFTypeRef productNameAsCFString;
		// check the name of the modem's callout device
		bsdPathAsCFString = IORegistryEntrySearchCFProperty(modemService,
																													kIOServicePlane,
																													CFSTR(kIOCalloutDeviceKey),
																													kCFAllocatorDefault,
																													0);
		// then, because the callout device could be any old thing, and because the reference to the modem returned by the
		// iterator doesn't include much device specific info, look at its parent, and check the product name
		io_registry_entry_t parent;  
		kernResult = IORegistryEntryGetParentEntry( modemService,	kIOServicePlane, &parent );																										
		productNameAsCFString = IORegistryEntrySearchCFProperty(parent,
																													kIOServicePlane,
																													CFSTR("Product Name"),
																													kCFAllocatorDefault,
																													0);
		
		if( bsdPathAsCFString )
		{
			Boolean result;      
			result = CFStringGetCString( (CFStringRef)bsdPathAsCFString,
																	path,
																	maxPathSize, 
																	kCFStringEncodingUTF8);
			
			if( productNameAsCFString )
			{
			result = CFStringGetCString( (CFStringRef)productNameAsCFString,
																	productName,
																	maxPathSize, 
																	kCFStringEncodingUTF8);
			}
			if (result)
			{
				//printf("Modem found with BSD path: %s", path);
				if( (strcmp( productName, "Make Controller Ki") == 0) )
				{
					CFRelease(bsdPathAsCFString);
					IOObjectRelease(parent);
					deviceFound = true;
					kernResult = KERN_SUCCESS;
				}
				else
					*path = '\0';  // clear this, since this is checked above.
			}
			printf("\n");
			(void) IOObjectRelease(modemService);
		}
	}
	return kernResult;
}