Detecting iPods programmatically (part 2)

A while back, I wrote a post about detecting iPods connected to your Mac, and finding out their model number in order to deduce information such as the iPod model and colour. Then, in September, Aaron Bockover of the Banshee Project informed me that Apple have changed their approach to storing this information, and no longer store it in an easily-accessible file. It is now hidden in the [tag]iPod[/tag]‘s [tag]SCSI[/tag] codepages, and these are remarkably tricky to access and query under Mac OS X. Fortunately, I’ve worked out how to do it :-)

The iPodLinux project wiki provided me with the base information about how this info is stored in the SCSI codepages, for which I am eternally grateful. Kudos to Aaron for deducing this info and sharing it with me too. The missing link was now how to query these codepages under Mac OS X.

Basicall, I needed to be able to send a SCSI INQUIRY command to the iPod storage device. Apple’s Developer Connection site was the first point of call, which provided some useful info about why this isn’t as easy as one might like. Apple’s [tag]IOKit[/tag] deals with most of the info you’d normally want to get from an INQUIRY command, and so it’s not too harsh that it isn’t a trivial thing to perform the query yourself, when normally you wouldn’t need to.

Next stop was the Apple Developer Connection sample code lists, where I found a sample project called SCSIOldAndNew. This project shows how to communicate with SCSI devices using an old, deprecated method (for Mac OS 10.2 and earlier), and a new STUC (SCSITask User Client) method for more recent versions of Mac OS X.

Taking this project as my base, and with a lot of trial and error, I’ve created a sample XCode project, iPodSCSICodePages, which will find any attached [tag]USB[/tag] iPods and retrieve the hidden XML file from their codepages. It only uses the new STUC method, so if you need to support Mac OS 10.2 and earlier, you’ll need to add the old approach back in.

iPodSCSICodePages gets the XML by first retrieving codepage 0xC0. This contains a list of further codepages, which (when combined) contain the entire XML file we need to retrieve. iPodSCSICodePages then works through each of these further codepages, extracting the XML chunks and (in the sample code) writing them out to the console.

The iPodLinux wiki gives more info about the format of these codepages, together with a sample of the XML output. Although the XML contains lots of lovely info, including the audio, image and video capabilities of the iPod, it is missing one crucial piece of info that my original approach to iPod detection used to work out which iPod you had. This original approach used the iPod’s marketing model number, which was easily accessed from the iPod’s sysinfo file. Unfortunately, the sysinfo file is no more, and the model number is not listed in the SCSI codepage XML.

So how do we deduce the version of the iPod now? Thankfully, there is still a way (as you would expect – after all, iTunes manages it). The codepage XML does contain the iPod’s serial number – and it turns out that part of the serial number identifies the model of the iPod. This is the method that (I believe) iTunes uses to identify these sysinfo-less iPod.

Apple’s 11-character serial number format was decrypted a little while back, and takes the following format:

AABCCDDDEEE

…where…

AA = factory where the device was manufactured
B = single year of production (6 for 2006, 7 for 2007 etc.)
CC = week of production in the year
DDD = a base-34 encoded number representing the production index of the device for that week
EEE = serial code of the model

(Thanks again to Aaron for the clarification on these chunks.)

EEE is the chunk we care about! Each three-letter combination for EEE uniquely identifes an iPod model. One model might have more than one three-letter combination – but each EEE will only ever identify one model.

This is better than nothing, and means we still have a way to identify iPods. What we don’t have is a full list of all possible EEEs. Wheras Apple use the marketing model number to reference iPods on the Apple Store (amongst other things), they don’t ever publish the serial code strings (for obvious reasons).

So the only way to work out which serial endings match which iPods is to start gathering lots of info about lots of iPods. Asking people to submit their iPod serial numbers is something that should be done with care, as a full serial number can be used to register an iPod to a particular address. But submitting the final three characters is safe enough, and this is something that Aaron has been doing over at the Banshee Project, leading to a small but growing table of submitted iPod serial number endings. You can submit your own info to the cause on the Banshee site if you’d like.

I’ve been doing some deducing of my own from various sources, and will update my Big List Of iPods with any serial number endings that I can confidently assign to a particular model.

Update (1 Feb 07): after studying a few more iPod XML files, I’ve discovered a second useful property. This is the iPod’s “FamilyID”. I was trying to work out why the old iPod Updater software (from before the software updates started getting bundled with iTunes 7) didn’t include every single serial number ever used for some iPods. I was looking inside the bundle for the last standalone updater (which was /Applications/Utilities/iPod Software Updater/iPod Updater 2006-06-28.app), and I found a file at /Contents/Resources/Icons.plist which maps some serial numbers to the icons also included in the /Contents/Resources/ folder. Here’s a sample of this XML, with some bits removed for brevity:

<code>
<key>0</key>
<string>DeviceIcon-0.icns</string>
<key>1</key>
<string>DeviceIcon-1.icns</string>
<key>2</key>
<string>DeviceIcon-2.icns</string>
<key>3</key>
<dict>
    <key>Generic</key>
    <string>DeviceIcon-3-1.icns</string>
    <key>PFW</key>
    <string>DeviceIcon-3-1.icns</string>
    (…)
</dict>
<key>4</key>
<dict>
    <key>Generic</key>
    <string>DeviceIcon-4.icns</string>
    <key>S2X</key>
    <string>DeviceIcon-4-1.icns</string>
</dict>
</code>

Using the icons provided, it’s possible to determine which colour of iPod they correspond to. So, serial numbers ending in PWF correspond to DeviceIcon-3-1.icns, which is the icon for a first-generation silver iPod Mini. Likewise, S2X is DeviceIcon-4-1.icns, which is the icon for the 4th generation (greyscale) U2 iPod.

We can deduce from this that all greyscale U2 iPods would have serial numbers ending in S2X, since no other serials are listed. But what about non-U2 4th gen greyscale iPods? The XML file doesn’t list any serial numbers for them at all. This is where the iPod’s FamilyID comes in. The FamilyID value from a 4th-gen greyscale iPod’s SCSI XML file is “4″. This is represented by the chunk of XML beginning with 4 in the XML above. Since all other 4th-gen greyscale iPods were white, it’s sufficient to group all of these under the “Generic” category which gets assigned DeviceIcon-4.icns – the icon for a white 4th gen greyscale iPod.

The FamilyID doesn’t tell us which specific iPod we have – but it does tell us which range of iPods we’re dealing with. And I think that iTunes still uses the same trick even now – using serial number endings to refer to “special” iPods, which usually means non-white iPods. These iPods get detected by a combination of their FamilyID and serial number ending. Any other iPods of a particular FamilyID get caught in the “catch all” Generic category, which removes the need for the Updater (or for iTunes) to know all serial number endings. (For some FamilyIDs, the updater software does list serial number endings for white iPods too, even though it still has a “Generic” catch-all.)

So what does this mean for anyone writing iPod-savvy software? Simply put, use the last three digits of the serial number to try and detect a specific iPod model (if you need to know things like the disk size, and if you have a list of known serial number endings such as my Big List Of iPods). Use the FamilyID as a fallback to detect the iPod model where the serial number ending isn’t known.

If all you want to do is to detect the right icon to use, then this should satisfy everything you need – all you need to choose the right icon is the iPod generation (from the FamilyID) and the colour (from the “special” serial number endings).

An extra note: this SCSI codepage stuff doesn’t work with the first and second generation iPods. They still have sysinfo files, and should be detected by the original sysinfo method. Generally, I’d recommend trying the sysinfo method first, and then the SCSI method if the sysinfo doesn’t succeed. There’s more information available for the sysinfo method – pretty much every model number is know for iPods which have / had sysinfo files.

One final question: What are the FamilyIDs for the different iPods? They’re on the Big List Of iPods. Go look there for the nearest thing I have to a definitive reference.

2 thoughts on “Detecting iPods programmatically (part 2)

  1. Cool. This works perfectly.

    Is there a spot in where you could grab the mount point (/Volumes/XXX) of the device/ipod?

    If I figure this out, I’ll post it back to you. If you know it, please email me.

  2. Hi, thanks for the information. My iPod was stolen, so I wanted to find out what the serial number was. There were a few devices listed on my list (in com.apple.iPod.plist in /library/preferences, and this info helped me deduce which one was which.

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>