Observing Device Removal

As well as watching for the arrival of devices, an application may wish to watch for a device being removed from the system, such as a USB device being unplugged. Unlike device arrival messages, which are delivered for any device that meets the criteria described by a matching dictionary, a device removal message is delivered only for a particular device that the application has registered an interest in. An application will typically register an interest in all devices that it has opened, since the application will want to respond to the removal of a device that it is accessing.

In our previous code examples, such as Listing 5-3, we obtained a reference to a driver object, read properties from the driver, and then released the driver object, all within the one function. It is far more common that an application will hold on to the driver object beyond the device arrival callback function, perhaps only releasing it when the application exits or the device is removed.

images Note In our previous examples, we were able to use the local variables of a function to hold the driver object, since the driver was released before we returned from the function. However, if an application wishes to use the driver object after returning from the function, it will need to allocate a structure on the heap to hold the driver state.

Having obtained a reference to a driver instance, an application can register to receive notifications when the driver's state changes, including when the driver has terminated in response to its hardware device being removed. This notification callback is installed by calling the function named IOServiceAddInterestNotification(), which is defined in the I/O Kit framework. As with the notification for device arrival, the application needs to provide a port on which the I/O Kit will signal the application when the driver's state has changed. This can be created with the function IONotificationPortCreate(), as was shown in Listing 5-2. If the application has already created a notification port for device arrival events, it can share that same notification port and its corresponding run loop source to receive device removal notifications. This is done by passing the existing notification port to the function IOServiceAddInterestNotification().

When the application receives a notification that a driver instance has terminated, it should release its reference to that driver and take any action that is necessary to inform the user that the device has been removed.

Listing 5-4 demonstrates a modification to the DeviceAdded() function from Listing 5-3 that creates a structure to represent an instance of a driver within the application and then installs a callback to receive notifications from the driver (such as driver termination).

Listing 5-4. Code Snippet Demonstrating How an Application Can Install a Callback Function To Receive a Notification When a Driver Terminates

#include <IOKit/IOMessage.h>

// Structure to describe a driver instance.
typedef struct {
        io_service_t    service;
        io_object_t     notification;
} MyDriverData;

// Notification port used for both device arrival and driver state changes.
IONotificationPortRef   gNotificationPort = NULL;

void DeviceAdded (void* refCon, io_iterator_t iterator)
{
        io_service_t            service = 0;
        
        // Iterate over all matching objects.
        while ((service = IOIteratorNext(iterator)) != 0)
        {
                MyDriverData*   myDriverData;
                kern_return_t   kr;
                
                // Allocate a structure to hold the driver instance.
                myDriverData = (MyDriverData*)malloc(sizeof(MyDriverData));
                // Save the io_service_t for this driver instance.
                myDriverData->service = service;
                
                // Install a callback to receive notification of driver state changes.
                kr = IOServiceAddInterestNotification(gNotificationPort,
                                        service,                        // driver object
                                        kIOGeneralInterest,
                                        DeviceNotification,             // callback
                                        myDriverData,           // refCon passed to callback
                                        &myDriverData->notification);
        }
}

void DeviceNotification (void* refCon, io_service_t service, natural_t messageType,
     void* messageArgument)
{
        MyDriverData*   myDriverData = (MyDriverData*)refCon;
        kern_return_t   kr;
        
        // Only handle driver termination notifications.
        if (messageType == kIOMessageServiceIsTerminated)
        {
                // Print the name of the removed device.
                io_name_t       name;
                IORegistryEntryGetName(service, name);
                printf("Device removed: %s ", name);
                
                // Remove the driver state change notification.
                kr = IOObjectRelease(myDriverData->notification);

                // Release our reference to the driver object.
                IOObjectRelease(myDriverData->service);

                // Release our structure that holds the driver connection.
                free(myDriverData);
        }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.106.212