Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute an application on Mac OS X when a particular type of USB device is connected?

Tags:

macos

usb

I need to implement a Mac OS X application. In my application I need to do two things:

  1. Execute / Open an application when a particular type of USB device is connected to the system.
  2. Read the data from USB and upload it to a web server.

I do not have much experience in Mac OS X development. Can anyone please suggest the best documents to reach my goals?

like image 225
ChandraSekhar Avatar asked Aug 30 '11 07:08

ChandraSekhar


People also ask

Where is USB device tree on Mac?

To identify the USB device in a Mac operating system: In the left column, select USB under Hardware. In the main area, the upper panel will display the USB device tree. Select a device in this tree to see more information. In the main area, the lower panel will display details for the selected USB device.


Video Answer


4 Answers

You can use launchd. Try man launchd and man launchd.plist.

It seems that launchd can work with USB events, even though this feature is poorly documented. I found it on: man xpc_set_event_stream_handler

Here's an example. If you put the following into: ~/Library/LaunchAgents/com.example.plist, your program should start when a USB device is connected.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd > <plist version="1.0"> <dict>     <key>Label</key>     <string>com.example.program</string>     <key>ProgramArguments</key>     <array>     <string>/path/to/program</string>     </array>     <key>LaunchEvents</key>     <dict>             <key>com.apple.iokit.matching</key>             <dict>                     <key>com.apple.device-attach</key>                     <dict>                             <key>idProduct</key>                             <integer>1234</integer>                             <key>idVendor</key>                             <integer>1337</integer>                             <key>IOProviderClass</key>                             <string>IOUSBDevice</string>                             <key>IOMatchLaunchStream</key>                             <true/>                     </dict>             </dict>     </dict> </dict> </plist> 
like image 189
Julien Pilet Avatar answered Sep 30 '22 17:09

Julien Pilet


Depending on the type of device you might able to set an application to open automatically via the iPhoto/Image Capture preferences. That will work only for a limited class of devices, for an application already present on the computer and will require changing the preferences on the computer manually.

In general, there's no way to automatically run arbitrary applications on CD/DVD/USB insert because it's a security problem.

like image 39
blahdiblah Avatar answered Sep 30 '22 17:09

blahdiblah


Julien Pilet's answer worked for me. However, to get it to not constantly relaunch the app when the device is still connected when closing the app, I had to:

  • call xpc_set_event_stream_handler() in my app delegate applicationDidFinishLaunching:
    xpc_set_event_stream_handler("com.apple.iokit.matching", NULL, ^(xpc_object_t event) {     
        // Every event has the key XPC_EVENT_KEY_NAME set to a string that
        // is the name you gave the event in your launchd.plist.
        const char *name = xpc_dictionary_get_string(event, XPC_EVENT_KEY_NAME);

        // IOKit events have the IORegistryEntryNumber as a payload.
        uint64_t id = xpc_dictionary_get_uint64(event, "IOMatchLaunchServiceID");
        // Reconstruct the node you were interested in here using the IOKit
        // APIs.
        NSLog(@"Received event: %s: %llu",name,id);
    });
  • add KeepAlive/false key/value pair to the plist
  • add IOMatchLaunchStream/true key/value pair to the com.apple.device-attach dict in the plist. This is in addition to the IOMatchStream key already there. Not sure why that has to be there, I found a reference to it here: http://asciiwwdc.com/2013/sessions/702

Also don't forget to register the plist with the system using

launchctl load <path to your plist>

Note that this seems to work, but I never get the NSLog message from the xpc stream handler.

like image 42
BillyRayCyrus Avatar answered Sep 30 '22 17:09

BillyRayCyrus


It really depends on what sort of application you are looking at.

It does look like there is no way to do it in a similar fashion to udev for example.

Two possible solutions are:

  • Write a custom wrapper driver for your device
  • Use libusb and have a daemon to wait for certain device.

And in fact one could write a program with libusb which will handle this sort of tasks according to a given config file, that would be also cross-platform since libusb supports quite a few platforms.

like image 44
errordeveloper Avatar answered Sep 30 '22 19:09

errordeveloper