Warning, /utilities/isoimagewriter/isoimagewriter/usbdevicemonitor_mac.mm is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2016 ROSA
0003     SPDX-License-Identifier: GPL-3.0-or-later
0004 */
0005 
0006 ////////////////////////////////////////////////////////////////////////////////
0007 // Mac OS X implementation of UsbDeviceMonitor
0008 
0009 #include "usbdevicemonitor.h"
0010 #include "usbdevicemonitor_mac_p.h"
0011 
0012 #include <Cocoa/Cocoa.h>
0013 #include <IOKit/IOBSD.h>
0014 
0015 
0016 // Private class implementation
0017 
0018 UsbDeviceMonitorPrivate::UsbDeviceMonitorPrivate()
0019 {
0020 }
0021 
0022 UsbDeviceMonitorPrivate::~UsbDeviceMonitorPrivate()
0023 {
0024 }
0025 
0026 
0027 // Supplemental callback functions
0028 
0029 void UsbDeviceAddedCallback(void *refCon, io_iterator_t iterator)
0030 {
0031     while (IOIteratorNext(iterator)) {}; // Run out the iterator or notifications won't start
0032     UsbDeviceMonitor* monitor = (UsbDeviceMonitor*)refCon;
0033     emit monitor->deviceChanged();
0034 }
0035 
0036 void UsbDeviceRemovedCallback(void *refCon, io_iterator_t iterator)
0037 {
0038     while (IOIteratorNext(iterator)) {}; // Run out the iterator or notifications won't start
0039     UsbDeviceMonitor* monitor = (UsbDeviceMonitor*)refCon;
0040     emit monitor->deviceChanged();
0041 }
0042 
0043 
0044 // Main class implementation
0045 
0046 UsbDeviceMonitor::UsbDeviceMonitor(QObject *parent) :
0047     QObject(parent),
0048     d_ptr(new UsbDeviceMonitorPrivate())
0049 {
0050 }
0051 
0052 UsbDeviceMonitor::~UsbDeviceMonitor()
0053 {
0054     cleanup();
0055     delete d_ptr;
0056 }
0057 
0058 // Closes handles and frees resources
0059 void UsbDeviceMonitor::cleanup()
0060 {
0061 }
0062 
0063 // Implements QAbstractNativeEventFilter interface for processing WM_DEVICECHANGE messages (Windows)
0064 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0065 bool UsbDeviceMonitor::nativeEventFilter(const QByteArray& eventType, void* message, long* result)
0066 #else
0067 bool UsbDeviceMonitor::nativeEventFilter(const QByteArray& eventType, void* message, qintptr* result)
0068 #endif
0069 {
0070     Q_UNUSED(eventType);
0071     Q_UNUSED(message);
0072     Q_UNUSED(result);
0073     return false;
0074 }
0075 
0076 bool UsbDeviceMonitor::startMonitoring()
0077 {
0078     IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
0079     CFRunLoopAddSource(CFRunLoopGetCurrent(),
0080                    IONotificationPortGetRunLoopSource(notificationPort),
0081                    kCFRunLoopDefaultMode);
0082 
0083     // If we monitor USB devices, notification comes too early, and the new disk device is not present yet.
0084     // So, instead we monitor for the new disks.
0085     CFMutableDictionaryRef matchingDict = IOServiceMatching("IOMediaBSDClient");
0086     CFRetain(matchingDict); // Need to use it twice and IOServiceAddMatchingNotification() consumes a reference
0087 
0088     io_iterator_t portIterator = 0;
0089     // Register for notifications when a serial port is added to the system
0090     kern_return_t result = IOServiceAddMatchingNotification(notificationPort,
0091                                                             kIOPublishNotification,
0092                                                             matchingDict,
0093                                                             UsbDeviceAddedCallback,
0094                                                             this,
0095                                                             &portIterator);
0096     while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices).
0097 
0098     // Also register for removal notifications
0099     IONotificationPortRef terminationNotificationPort = IONotificationPortCreate(kIOMasterPortDefault);
0100     CFRunLoopAddSource(CFRunLoopGetCurrent(),
0101                        IONotificationPortGetRunLoopSource(terminationNotificationPort),
0102                        kCFRunLoopDefaultMode);
0103     result = IOServiceAddMatchingNotification(terminationNotificationPort,
0104                                               kIOTerminatedNotification,
0105                                               matchingDict,
0106                                               UsbDeviceRemovedCallback,
0107                                               this,         // refCon/contextInfo
0108                                               &portIterator);
0109 
0110     while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices).
0111 
0112     return true;
0113 }