// makes a list of ATA or SCSI devices for the DEVICESCAN directive of // smartd. Returns number N of devices, or -1 if out of // memory. Allocates N+1 arrays: one of N pointers (devlist); the // other N arrays each contain null-terminated character strings. In // the case N==0, no arrays are allocated because the array of 0 // pointers has zero length, equivalent to calling malloc(0). int make_device_names (char*** devlist, const char* name) { IOReturn err; io_iterator_t i; io_object_t device = MACH_PORT_NULL; int result; int index; // We treat all devices as ATA so long as they support SMARTLib. if (strcmp (name, "ATA") != 0) return 0; err = IOServiceGetMatchingServices (kIOMasterPortDefault, IOServiceMatching (kIOBlockStorageDeviceClass), &i); if (err != kIOReturnSuccess) return -1; // Count the devices. result = 0; while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) { if (is_smart_capable (device)) result++; IOObjectRelease (device); } // Create an array of service names. IOIteratorReset (i); *devlist = (char**)Calloc (result, sizeof (char *)); if (! *devlist) goto error; index = 0; while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) { if (is_smart_capable (device)) { io_string_t devName; IORegistryEntryGetPath(device, kIOServicePlane, devName); (*devlist)[index] = CustomStrDup (devName, true, __LINE__, __FILE__); if (! (*devlist)[index]) goto error; index++; } IOObjectRelease (device); } IOObjectRelease (i); return result; error: if (device != MACH_PORT_NULL) IOObjectRelease (device); IOObjectRelease (i); if (*devlist) { for (index = 0; index < result; index++) if ((*devlist)[index]) FreeNonZero ((*devlist)[index], 0, __LINE__, __FILE__); FreeNonZero (*devlist, result * sizeof (char *), __LINE__, __FILE__); } return -1; }
int refresh_disks(struct diskstats *stats, pmdaIndom *indom) { io_registry_entry_t drive; CFMutableDictionaryRef match; int i, status; static int inited = 0; static mach_port_t mach_master_port; static io_iterator_t mach_device_list; if (!inited) { /* Get ports and services for device statistics. */ if (IOMasterPort(bootstrap_port, &mach_master_port)) { fprintf(stderr, "%s: IOMasterPort error\n", __FUNCTION__); return -oserror(); } memset(stats, 0, sizeof(struct diskstats)); inited = 1; } /* Get an interator for IOMedia objects (drives). */ match = IOServiceMatching("IOMedia"); CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue); status = IOServiceGetMatchingServices(mach_master_port, match, &mach_device_list); if (status != KERN_SUCCESS) { fprintf(stderr, "%s: IOServiceGetMatchingServices error\n", __FUNCTION__); return -oserror(); } indom->it_numinst = 0; clear_disk_totals(stats); for (i = 0; (drive = IOIteratorNext(mach_device_list)) != 0; i++) { status = update_disk(stats, drive, i); if (status) break; IOObjectRelease(drive); } IOIteratorReset(mach_device_list); if (!status) status = update_disk_indom(stats, i, indom); return status; }
/** Initializes the USB system. Returns 0 on success, -1 on error. */ static int init_usb(ifc_match_func callback, std::unique_ptr<usb_handle>* handle) { int ret = -1; CFMutableDictionaryRef matchingDict; kern_return_t result; io_iterator_t iterator; usb_handle h; h.success = 0; h.callback = callback; /* * Create our matching dictionary to find appropriate devices. * IOServiceAddMatchingNotification consumes the reference, so we * do not need to release it. */ matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (matchingDict == NULL) { ERR("Couldn't create USB matching dictionary.\n"); return -1; } result = IOServiceGetMatchingServices( kIOMasterPortDefault, matchingDict, &iterator); if (result != 0) { ERR("Could not create iterator."); return -1; } for (;;) { if (! IOIteratorIsValid(iterator)) { /* * Apple documentation advises resetting the iterator if * it should become invalid during iteration. */ IOIteratorReset(iterator); continue; } io_service_t device = IOIteratorNext(iterator); if (device == 0) { break; } if (try_device(device, &h) != 0) { IOObjectRelease(device); continue; } if (h.success) { handle->reset(new usb_handle); memcpy(handle->get(), &h, sizeof(usb_handle)); ret = 0; break; } IOObjectRelease(device); } IOObjectRelease(iterator); return ret; }
brick_t *find_usb_devices ( void *usb, int32_t vendor, int32_t product, int32_t configuration, int32_t interface, brick_type_t type) { usb_handle_t *h = (usb_handle_t *) usb; CFMutableDictionaryRef matching; kern_return_t kr; io_iterator_t devices; io_service_t device; brick_t *bricks = NULL; int count; if (configuration) { matching = IOServiceMatching (kIOUSBInterfaceClassName); } else { matching = IOServiceMatching (kIOUSBDeviceClassName); } if (!matching) { return NULL; } CFDictionarySetValue (matching, CFSTR (kUSBVendorID), CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &vendor)); CFDictionarySetValue (matching, CFSTR (kUSBProductID), CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &product)); if (configuration) { CFDictionarySetValue (matching, CFSTR (kUSBConfigurationValue), CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &configuration)); CFDictionarySetValue (matching, CFSTR (kUSBInterfaceNumber), CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &interface)); } kr = IOServiceGetMatchingServices (h->port, matching, &devices); if (kr) { fprintf (stderr, "IOService matching error = %08x\n", kr); return NULL; } count = 0; while ((device = IOIteratorNext (devices))) count++; if (count > 0) { int i = 0; IOIteratorReset (devices); bricks = malloc ((sizeof (brick_t)) * (count + 1)); memset ((void *) bricks, 0, (sizeof (brick_t )) * (count + 1)); while ((device = IOIteratorNext (devices))) { IOUSBInterfaceInterface182 **intf = NULL; IOUSBDeviceInterface **dev = NULL; IOCFPlugInInterface **plugInInterface = NULL; brick_t *b = &(bricks[i]); HRESULT result; SInt32 score; if (configuration) { kr = IOCreatePlugInInterfaceForService ( device, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score ); } else { kr = IOCreatePlugInInterfaceForService ( device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score ); } if (kr || !plugInInterface) { continue; } if (configuration) { result = (*plugInInterface)->QueryInterface ( plugInInterface, CFUUIDGetUUIDBytes (kIOUSBInterfaceInterfaceID182), (LPVOID *) &intf ); } else { result = (*plugInInterface)->QueryInterface ( plugInInterface, CFUUIDGetUUIDBytes (kIOUSBDeviceInterfaceID), (LPVOID *) &dev ); } (*plugInInterface)->Release (plugInInterface); if (result || !(dev || intf)) { continue; } b->type = type; if (configuration) { b->handle = intf; b->open = open_intf; b->close = close_intf; b->control = control_msg; b->read = read_intf; b->write = write_intf; b->release = release_intf; (*intf)->GetLocationID (intf, &(b->id)); } else { b->handle = dev; b->get_config = get_dev_config; b->set_config = set_dev_config; b->release = release_dev; (*dev)->GetLocationID (dev, &(b->id)); } i = i + 1; } bricks[i].type = NULL_BRICK; } return bricks; }
int do_macos_iokit(int update_every, usec_t dt) { (void)dt; static int do_io = -1, do_space = -1, do_inodes = -1, do_bandwidth = -1; if (unlikely(do_io == -1)) { do_io = config_get_boolean("plugin:macos:iokit", "disk i/o", 1); do_space = config_get_boolean("plugin:macos:sysctl", "space usage for all disks", 1); do_inodes = config_get_boolean("plugin:macos:sysctl", "inodes usage for all disks", 1); do_bandwidth = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1); } RRDSET *st; mach_port_t master_port; io_registry_entry_t drive, drive_media; io_iterator_t drive_list; CFDictionaryRef properties, statistics; CFStringRef name; CFNumberRef number; kern_return_t status; collected_number total_disk_reads = 0; collected_number total_disk_writes = 0; struct diskstat { char name[MAXDRIVENAME]; collected_number bytes_read; collected_number bytes_write; collected_number reads; collected_number writes; collected_number time_read; collected_number time_write; collected_number latency_read; collected_number latency_write; } diskstat; struct cur_diskstat { collected_number duration_read_ns; collected_number duration_write_ns; collected_number busy_time_ns; } cur_diskstat; struct prev_diskstat { collected_number bytes_read; collected_number bytes_write; collected_number operations_read; collected_number operations_write; collected_number duration_read_ns; collected_number duration_write_ns; collected_number busy_time_ns; } prev_diskstat; // NEEDED BY: do_space, do_inodes struct statfs *mntbuf; int mntsize, i; char mntonname[MNAMELEN + 1]; char title[4096 + 1]; // NEEDED BY: do_bandwidth struct ifaddrs *ifa, *ifap; /* Get ports and services for drive statistics. */ if (unlikely(IOMasterPort(bootstrap_port, &master_port))) { error("MACOS: IOMasterPort() failed"); do_io = 0; error("DISABLED: system.io"); /* Get the list of all drive objects. */ } else if (unlikely(IOServiceGetMatchingServices(master_port, IOServiceMatching("IOBlockStorageDriver"), &drive_list))) { error("MACOS: IOServiceGetMatchingServices() failed"); do_io = 0; error("DISABLED: system.io"); } else { while ((drive = IOIteratorNext(drive_list)) != 0) { properties = 0; statistics = 0; number = 0; bzero(&diskstat, sizeof(diskstat)); /* Get drive media object. */ status = IORegistryEntryGetChildEntry(drive, kIOServicePlane, &drive_media); if (unlikely(status != KERN_SUCCESS)) { IOObjectRelease(drive); continue; } /* Get drive media properties. */ if (likely(!IORegistryEntryCreateCFProperties(drive_media, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) { /* Get disk name. */ if (likely(name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)))) { CFStringGetCString(name, diskstat.name, MAXDRIVENAME, kCFStringEncodingUTF8); } } /* Release. */ CFRelease(properties); IOObjectRelease(drive_media); /* Obtain the properties for this drive object. */ if (unlikely(IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, 0))) { error("MACOS: IORegistryEntryCreateCFProperties() failed"); do_io = 0; error("DISABLED: system.io"); break; } else if (likely(properties)) { /* Obtain the statistics from the drive properties. */ if (likely(statistics = (CFDictionaryRef)CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey)))) { // -------------------------------------------------------------------- /* Get bytes read. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_read); total_disk_reads += diskstat.bytes_read; } /* Get bytes written. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.bytes_write); total_disk_writes += diskstat.bytes_write; } st = rrdset_find_bytype("disk", diskstat.name); if (unlikely(!st)) { st = rrdset_create("disk", diskstat.name, NULL, diskstat.name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL); rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL); } else rrdset_next(st); prev_diskstat.bytes_read = rrddim_set(st, "reads", diskstat.bytes_read); prev_diskstat.bytes_write = rrddim_set(st, "writes", diskstat.bytes_write); rrdset_done(st); // -------------------------------------------------------------------- /* Get number of reads. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.reads); } /* Get number of writes. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.writes); } st = rrdset_find_bytype("disk_ops", diskstat.name); if (unlikely(!st)) { st = rrdset_create("disk_ops", diskstat.name, NULL, diskstat.name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); prev_diskstat.operations_read = rrddim_set(st, "reads", diskstat.reads); prev_diskstat.operations_write = rrddim_set(st, "writes", diskstat.writes); rrdset_done(st); // -------------------------------------------------------------------- /* Get reads time. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_read); } /* Get writes time. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_write); } st = rrdset_find_bytype("disk_util", diskstat.name); if (unlikely(!st)) { st = rrdset_create("disk_util", diskstat.name, NULL, diskstat.name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; rrddim_add(st, "utilization", NULL, 1, 10000000, RRDDIM_INCREMENTAL); } else rrdset_next(st); cur_diskstat.busy_time_ns = (diskstat.time_read + diskstat.time_write); prev_diskstat.busy_time_ns = rrddim_set(st, "utilization", cur_diskstat.busy_time_ns); rrdset_done(st); // -------------------------------------------------------------------- /* Get reads latency. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_read); } /* Get writes latency. */ if (likely(number = (CFNumberRef)CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsLatentWriteTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_write); } st = rrdset_find_bytype("disk_iotime", diskstat.name); if (unlikely(!st)) { st = rrdset_create("disk_iotime", diskstat.name, NULL, diskstat.name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_INCREMENTAL); rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_INCREMENTAL); } else rrdset_next(st); cur_diskstat.duration_read_ns = diskstat.time_read + diskstat.latency_read; cur_diskstat.duration_write_ns = diskstat.time_write + diskstat.latency_write; prev_diskstat.duration_read_ns = rrddim_set(st, "reads", cur_diskstat.duration_read_ns); prev_diskstat.duration_write_ns = rrddim_set(st, "writes", cur_diskstat.duration_write_ns); rrdset_done(st); // -------------------------------------------------------------------- // calculate differential charts // only if this is not the first time we run if (likely(dt)) { // -------------------------------------------------------------------- st = rrdset_find_bytype("disk_await", diskstat.name); if (unlikely(!st)) { st = rrdset_create("disk_await", diskstat.name, NULL, diskstat.name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_ABSOLUTE); rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ? (cur_diskstat.duration_read_ns - prev_diskstat.duration_read_ns) / (diskstat.reads - prev_diskstat.operations_read) : 0); rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ? (cur_diskstat.duration_write_ns - prev_diskstat.duration_write_ns) / (diskstat.writes - prev_diskstat.operations_write) : 0); rrdset_done(st); // -------------------------------------------------------------------- st = rrdset_find_bytype("disk_avgsz", diskstat.name); if (unlikely(!st)) { st = rrdset_create("disk_avgsz", diskstat.name, NULL, diskstat.name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "reads", (diskstat.reads - prev_diskstat.operations_read) ? (diskstat.bytes_read - prev_diskstat.bytes_read) / (diskstat.reads - prev_diskstat.operations_read) : 0); rrddim_set(st, "writes", (diskstat.writes - prev_diskstat.operations_write) ? (diskstat.bytes_write - prev_diskstat.bytes_write) / (diskstat.writes - prev_diskstat.operations_write) : 0); rrdset_done(st); // -------------------------------------------------------------------- st = rrdset_find_bytype("disk_svctm", diskstat.name); if (unlikely(!st)) { st = rrdset_create("disk_svctm", diskstat.name, NULL, diskstat.name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "svctm", NULL, 1, 1000000, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "svctm", ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) ? (cur_diskstat.busy_time_ns - prev_diskstat.busy_time_ns) / ((diskstat.reads - prev_diskstat.operations_read) + (diskstat.writes - prev_diskstat.operations_write)) : 0); rrdset_done(st); } } /* Release. */ CFRelease(properties); } /* Release. */ IOObjectRelease(drive); } IOIteratorReset(drive_list); /* Release. */ IOObjectRelease(drive_list); } if (likely(do_io)) { st = rrdset_find_bytype("system", "io"); if (unlikely(!st)) { st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "in", NULL, 1, 1024, RRDDIM_INCREMENTAL); rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "in", total_disk_reads); rrddim_set(st, "out", total_disk_writes); rrdset_done(st); } // Can be merged with FreeBSD plugin // -------------------------------------------------------------------------- if (likely(do_space || do_inodes)) { // there is no mount info in sysctl MIBs if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) { error("MACOS: getmntinfo() failed"); do_space = 0; error("DISABLED: disk_space.X"); do_inodes = 0; error("DISABLED: disk_inodes.X"); } else { for (i = 0; i < mntsize; i++) { if (mntbuf[i].f_flags == MNT_RDONLY || mntbuf[i].f_blocks == 0 || // taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes strcmp(mntbuf[i].f_fstypename, "autofs") == 0 || strcmp(mntbuf[i].f_fstypename, "procfs") == 0 || strcmp(mntbuf[i].f_fstypename, "subfs") == 0 || strcmp(mntbuf[i].f_fstypename, "devfs") == 0 || strcmp(mntbuf[i].f_fstypename, "none") == 0) continue; // -------------------------------------------------------------------------- if (likely(do_space)) { st = rrdset_find_bytype("disk_space", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); st = rrdset_create("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.space", title, "GB", 2023, update_every, RRDSET_TYPE_STACKED); rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE); rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE); rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "avail", (collected_number) mntbuf[i].f_bavail); rrddim_set(st, "used", (collected_number) (mntbuf[i].f_blocks - mntbuf[i].f_bfree)); rrddim_set(st, "reserved_for_root", (collected_number) (mntbuf[i].f_bfree - mntbuf[i].f_bavail)); rrdset_done(st); } // -------------------------------------------------------------------------- if (likely(do_inodes)) { st = rrdset_find_bytype("disk_inodes", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); st = rrdset_create("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.inodes", title, "Inodes", 2024, update_every, RRDSET_TYPE_STACKED); rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE); rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "avail", (collected_number) mntbuf[i].f_ffree); rrddim_set(st, "used", (collected_number) (mntbuf[i].f_files - mntbuf[i].f_ffree)); rrdset_done(st); } } } } // Can be merged with FreeBSD plugin // -------------------------------------------------------------------- if (likely(do_bandwidth)) { if (unlikely(getifaddrs(&ifap))) { error("MACOS: getifaddrs()"); do_bandwidth = 0; error("DISABLED: system.ipv4"); } else { for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; // -------------------------------------------------------------------- st = rrdset_find_bytype("net", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "received", IFA_DATA(ibytes)); rrddim_set(st, "sent", IFA_DATA(obytes)); rrdset_done(st); // -------------------------------------------------------------------- st = rrdset_find_bytype("net_packets", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "multicast_received", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "multicast_sent", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "received", IFA_DATA(ipackets)); rrddim_set(st, "sent", IFA_DATA(opackets)); rrddim_set(st, "multicast_received", IFA_DATA(imcasts)); rrddim_set(st, "multicast_sent", IFA_DATA(omcasts)); rrdset_done(st); // -------------------------------------------------------------------- st = rrdset_find_bytype("net_errors", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "inbound", IFA_DATA(ierrors)); rrddim_set(st, "outbound", IFA_DATA(oerrors)); rrdset_done(st); // -------------------------------------------------------------------- st = rrdset_find_bytype("net_drops", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "inbound", IFA_DATA(iqdrops)); rrdset_done(st); // -------------------------------------------------------------------- st = rrdset_find_bytype("net_events", ifa->ifa_name); if (unlikely(!st)) { st = rrdset_create("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "collisions", IFA_DATA(collisions)); rrdset_done(st); } freeifaddrs(ifap); } } return 0; }
/* this is where most of the getting magic happens.. */ static int get_cam_list(io_iterator_t devIter, uvccCam ***list) { io_iterator_t ifIter; kern_return_t kr; int i, nDevs = 0, nCams = 0; uvccCam **tmp; io_service_t devSrv, ifSrv; /* unsigned int */ IOCFPlugInInterface **pIf; /* needed to find the device interface */ HRESULT qiRes; /* int32_t */ int32_t score; IOUSBDeviceInterface197 **devIf; /* interface to communicate with the device */ if(!uvcc_port) { fprintf(stderr, UVCC_INIT_ERROR_MSG); return -1; } /* get number of devices */ while((IOIteratorNext(devIter)) != 0) nDevs++; if(!nDevs) return 0; IOIteratorReset(devIter); tmp = malloc(nDevs*sizeof(uvccCam *)); while((devSrv = IOIteratorNext(devIter))) { kr = IOCreatePlugInInterfaceForService(devSrv, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &pIf, &score); /* we're done with the devSrv */ IOObjectRelease(devSrv); if(kr != kIOReturnSuccess) { uvcc_err("get_cam_list: IOCreatePlugInInterfaceForService", kr); IOObjectRelease(devSrv); continue; } qiRes = (*pIf)->QueryInterface(pIf, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID197), (LPVOID)&devIf); /* we're done with the plugin */ (*pIf)->Stop(pIf); IODestroyPlugInInterface(pIf); /* kIOReturnSuccess is actually just 0 but since QI strictly talking returns HRESULT (int32_t) and not kern_return_t (int) i figured i'll just do this here */ if(!qiRes && devIf) { kr = (*devIf)->CreateInterfaceIterator(devIf, &vid_ctrl_if_req, &ifIter); if(kr != kIOReturnSuccess || !IOIteratorIsValid(ifIter)) { uvcc_err("get_cam_list: CreateInterfaceIterator", kr); IOObjectRelease(devSrv); continue; } if((ifSrv = IOIteratorNext(ifIter))) { /* we'll just use the first vid ctrl if we get */ if((tmp[nCams] = malloc(sizeof(uvccCam))) == NULL) { if(!logger) perror("uvcc error! get_cam_list: Could not allocate memory for list entry"); else asl_log(logger, NULL, ASL_LEVEL_ERR, "get_cam_list: Could not allocate memory for list entry: %s", strerror(errno)); IOObjectRelease(ifIter); (*devIf)->Release(devIf); IOObjectRelease(devSrv); break; } /* set the data.. */ if((fill_cam_struct(devIf, tmp[nCams])) != 0) { (*devIf)->Release(devIf); IOObjectRelease(devSrv); continue; } /* get the registry name */ set_cam_reg_name(devSrv, tmp[nCams]); nCams++; IOObjectRelease(ifSrv); } /* else: no vid_ctrl_iface, i.e. not cam */ IOObjectRelease(ifIter); } else { if(!logger) perror("uvcc warning! get_cam_list: QueryInterface failed"); else asl_log(logger, NULL, ASL_LEVEL_WARNING, "get_cam_list: QueryInterface failed: %s", strerror(errno)); } IOObjectRelease(devSrv); } if(nCams > 0) { /* only make the allocation if we got cams */ (*list) = malloc(nCams*sizeof(uvccCam *)); for(i = 0; i < nCams; i++) (*list)[i] = tmp[i]; } free(tmp); return nCams; }
/* * Finds PC Card devices currently registered in the system that match any of * the drivers detected in the driver bundle vector. */ static int HPDriversMatchPCCardDevices(HPDriver * driverBundle, HPDeviceList * readerList) { CFDictionaryRef pccMatch = IOServiceMatching("IOPCCard16Device"); if (pccMatch == NULL) { Log1(PCSC_LOG_ERROR, "error getting PCCard match from IOServiceMatching()"); return 1; } io_iterator_t pccIter; kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch, &pccIter); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting iterator from IOServiceGetMatchingServices()"); return 1; } IOIteratorReset(pccIter); io_object_t pccDevice = 0; while ((pccDevice = IOIteratorNext(pccIter))) { char namebuf[1024]; kret = IORegistryEntryGetName(pccDevice, namebuf); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()"); return 1; } UInt32 vendorId = 0; UInt32 productId = 0; UInt32 pccAddress = 0; CFTypeRef valueRef = IORegistryEntryCreateCFProperty(pccDevice, CFSTR("VendorID"), kCFAllocatorDefault, 0); if (!valueRef) { Log1(PCSC_LOG_ERROR, "error getting vendor"); } else { CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, &vendorId); } valueRef = IORegistryEntryCreateCFProperty(pccDevice, CFSTR("DeviceID"), kCFAllocatorDefault, 0); if (!valueRef) { Log1(PCSC_LOG_ERROR, "error getting device"); } else { CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, &productId); } valueRef = IORegistryEntryCreateCFProperty(pccDevice, CFSTR("SocketNumber"), kCFAllocatorDefault, 0); if (!valueRef) { Log1(PCSC_LOG_ERROR, "error getting PC Card socket"); } else { CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, &pccAddress); } HPDriver *driver = driverBundle; for (; driver->m_vendorId; ++driver) { if ((driver->m_vendorId == vendorId) && (driver->m_productId == productId)) { *readerList = HPDeviceListInsert(*readerList, driver, pccAddress); } } } IOObjectRelease(pccIter); return 0; }
/* * Finds USB devices currently registered in the system that match any of * the drivers detected in the driver bundle vector. */ static int HPDriversMatchUSBDevices(HPDriverVector driverBundle, HPDeviceList * readerList) { CFDictionaryRef usbMatch = IOServiceMatching("IOUSBDevice"); if (0 == usbMatch) { Log1(PCSC_LOG_ERROR, "error getting USB match from IOServiceMatching()"); return 1; } io_iterator_t usbIter; kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault, usbMatch, &usbIter); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting iterator from IOServiceGetMatchingServices()"); return 1; } IOIteratorReset(usbIter); io_object_t usbDevice = 0; while ((usbDevice = IOIteratorNext(usbIter))) { char namebuf[1024]; kret = IORegistryEntryGetName(usbDevice, namebuf); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting device name from IORegistryEntryGetName()"); return 1; } IOCFPlugInInterface **iodev; SInt32 score; kret = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score); if (kret != 0) { Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()"); return 1; } IOObjectRelease(usbDevice); IOUSBDeviceInterface **usbdev; HRESULT hres = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *) & usbdev); (*iodev)->Release(iodev); if (hres) { Log1(PCSC_LOG_ERROR, "error querying interface in QueryInterface()"); return 1; } UInt16 vendorId = 0; UInt16 productId = 0; UInt32 usbAddress = 0; kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId); kret = (*usbdev)->GetDeviceProduct(usbdev, &productId); kret = (*usbdev)->GetLocationID(usbdev, &usbAddress); (*usbdev)->Release(usbdev); #ifdef DEBUG_HOTPLUG Log4(PCSC_LOG_DEBUG, "Found USB device 0x%04X:0x%04X at 0x%X", vendorId, productId, usbAddress); #endif HPDriver *driver; for (driver = driverBundle; driver->m_vendorId; ++driver) { if ((driver->m_vendorId == vendorId) && (driver->m_productId == productId)) { #ifdef DEBUG_HOTPLUG Log4(PCSC_LOG_DEBUG, "Adding USB device %04X:%04X at 0x%X", vendorId, productId, usbAddress); #endif *readerList = HPDeviceListInsert(*readerList, driver, usbAddress); } } } IOObjectRelease(usbIter); return 0; }
int iterateDevices(io_iterator_t deviceIterator) { io_object_t usbDevice; int err = -1; IOReturn ret; IOUSBDeviceInterface245 **dev=NULL; SInt32 config = 0; int exclusiveErrs, attempts; for(attempts = 1; attempts < 5; attempts++) { exclusiveErrs = 0; usbDevice = IOIteratorNext(deviceIterator); if(usbDevice == IO_OBJECT_NULL) { fprintf(stderr, "Unable to find first matching USB device\n"); return(-1); } while(usbDevice != IO_OBJECT_NULL) { dev = getUSBDevice(usbDevice); if(dev != nil) { config = openUSBDevice(dev); if(config == -2) { exclusiveErrs++; } else if(config >= 0) { // Device sucessfully opened if(config > 0) { useUSBDevice(dev, config); } else { printf("What use is a device with a zero configuration????\n"); } ret = (*dev)->USBDeviceClose(dev); } ret = (*dev)->Release(dev); // Not worth bothering with errors here } IOObjectRelease(usbDevice); if(config >= 0) // we have sucessfully used device { return(0); } usbDevice = IOIteratorNext(deviceIterator); }; if(exclusiveErrs > 0) { sleep(1); IOIteratorReset(deviceIterator); printf("Trying open again %d\n", attempts); } else { break; } } return(err); }