Introduction
The USB Serial Number is one unique number you might wish to use to identify a device- for licensing or whatever. However, keep in mind it is in no way guarded against forging and you can buy special hardware where this ID can be set by the user.
There are other snippets on the web on how to do this (e.g., http://oroboro.com/usb-serial-number-osx/), but they require much more code.
How the Code Works
First, a DADiskRef is created for the file by recursively stripping path components until the mount point is found. It then obtains the io_service
object and searches it using IORegistryEntrySearchCFProperty
for the key "USB Serial Number".
Using the Code
See below. Requires IOKit
and DiskArbitration
Frameworks. Uses functions existing since OSX 10.7.
#include <iostream>
#include <string>
#include <CoreFoundation/CoreFoundation.h>
#include <DiskArbitration/DADisk.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#include <sys/stat.h>
using namespace::std;
string GetSerial(const string &path_in)
{
DASessionRef session = DASessionCreate(NULL);
DADiskRef disk;
string path(path_in);
size_t nPath = path_in.find_last_of("/");
if(nPath != string::npos)
{
path=path_in.substr(0, nPath);
}
else
return "";
if (session)
{
CFURLRef url = CFURLCreateFromFileSystemRepresentation
(NULL, (const UInt8 *)path.c_str(), path.length(), TRUE);
disk = DADiskCreateFromVolumePath(NULL, session, url);
CFRelease(url);
if(disk)
{
io_service_t ioService = DADiskCopyIOMedia( disk );
CFStringRef key = CFSTR("USB Serial Number");
CFTypeRef sResult ;
sResult = IORegistryEntrySearchCFProperty( ioService, kIOServicePlane,
key, NULL,
kIORegistryIterateParents |
kIORegistryIterateRecursively ) ;
if(sResult)
{
string sValue( CFStringRefToStdString((CFStringRef)sResult) ) ;
cerr << "GetSerialBetter got " << sValue << endl;
return sValue;
}
}
else
{
path = path.substr(0, path.length()-1); return GetSerial(path);
}
}
return "";
}
This uses this tiny function to map CFStringRefs
to std::string
.
string CFStringRefToStdString(const CFStringRef pCFStringRef)
{
const char* pCStr = NULL;
string sRet;
if (pCFStringRef)
{
pCStr = CFStringGetCStringPtr(pCFStringRef, kCFStringEncodingMacRoman);
if(pCStr)
sRet.assign(pCStr);
}
return sRet;
}
History