iPod Work
I started working on a generic iPod device class that provides lots of information about the iPod and will work with Snorp’s ipod-sharp. It provides things like the name of the iPod (not the volume name, but the assigned name), the model/type (shuffle, regular, mini, photo), version info, serial numbers, capacity, used space, etc. It also supports safe ejection of the iPod. Initially I was doing this by just calling ‘eject’ on the device.
However, I decided I’d try doing this by making an ioctl call on the device. Not giving much thought to it, I came up with a few lines of code to eject a CD-ROM drive. It didn’t dawn on me until after the CD ejection code was working that the iPod is not a CD-ROM drive (it’s okay, you can smack me). It needs to be ejected as a SCSI device. The ioctl call[s] for this task are much more complicated (a structure must be passed to the device instead of a plain integer), and I’m not sure how to do this easily in C#. I’m not sure that it’s even worth it, and will probably go back to just execing ‘eject.’
Anyway, if anyone wants to eject a CD-ROM drive in C#, here you go. This may be useful for making basic ioctls in C# for other reasons. I’ve never seen an example of ioctl from C#, so maybe this is new.
using System;
using System.Runtime.InteropServices;
using Mono.Unix;
public class SimpleEject
{
public static void Main(string [] args)
{
if(args.Length <= 0) {
Console.WriteLine(”Usage: mono-eject.exe [-t]
return;
}
string device = args[0];
bool open = true;
if(args.Length > 1 && args[0].Equals(”-t”)) {
device = args[1];
open = false;
}
Console.WriteLine(Eject(device, open)
? String.Format(”Device {0} {1} successfully”, device,
open ? “opened” : “closed”)
: “Error ejecting device ” + device);
}
[DllImport(”libc”)]
static extern int ioctl(int device, EjectOperation request);
private enum EjectOperation {
Open = 0×5309,
Close = 0×5319
}
public static bool Eject(string devicePath, bool open)
{
try {
using(UnixStream stream = UnixFile.Open(devicePath,
OpenFlags.O_RDONLY | OpenFlags.O_NONBLOCK)) {
return ioctl(stream.Handle, open
? EjectOperation.Open
: EjectOperation.Close) == 0;
}
} catch {
return false;
}
}
}
And with that we have a simple Mono eject replacement for basic opening/closing CD-ROM trays. Woo-hoo!

June 2nd, 2005 at 10:40 am
Mono.Unix.UnixStream implements IDisposable, so your Eject function could instead be:
public static bool Eject(string devicePath, bool open)
{
try {
using (UnixStream stream =
UnixFile.Open(devicePath,
OpenFlags.O_RDONLY |
OpenFlags.O_NONBLOCK)) {
return ioctl(stream.Handle, open
? EjectOperation.Open
: EjectOperation.Close) == 0;
}
} catch {
return false;
}
}
- Jon
June 2nd, 2005 at 1:05 pm
Thanks! I hadn’t even looked into UnixStream that closely. First time I’ve ever used it. I’ll update the post to reflect the optimization. Best, Aaron.
April 8th, 2006 at 7:31 pm
Hi Aaron,
your article is very useful, I’m trying to write a lib for DVD access in c# (porting dvdcss and libdvdread), but I can’t find IOCTL codes. Where did you get the open/close codes?
thank you, keep up the good work
andrea - tek (italy)