WARNING: This page is not updated since WorkMan Release 1.3
Porting WorkMan to a new platform is a two-step process. The first step is to get the XView toolkit, version 3.0 or higher, running on your system. If you're lucky, someone else has already done so. The alt.toolkits.xview and comp.windows.open-look newsgroups are good places to find out whether XView exists for your system.
Once you have XView installed, you can work on porting WorkMan itself. If your system has builtin libraries for manipulating audio CDs, you can use them. Or you can use your system's user-level SCSI interface, if any. (Or both!)
All of the user interface modules ought to compile without modification. For the most part they're just standard C and documented XView calls.
The platform-dependent code in WorkMan is in source files named plat_xxx.c, where xxx is the platform name. If you look at a directory listing you'll see that there are files like this for Sun, HP, Linux, and other platforms already. Each of these files (called "platform modules") contains a set of well-defined functions for controlling and getting information from a CD-ROM drive. You'll find a list of those functions below. Ordinarily, porting WorkMan is simply a matter of writing those functions for your platform, and you can usually use one of the existing platform modules as a starting point.
WorkMan supports the notion of running any kind of drive on any platform, assuming the platform has facilities for sending arbitrary SCSI commands from user processes. To this end, you'll also find "drive modules" named drv_xxx.c. Each drive module contains replacement functions along the lines of the functions in the platform modules; these replacement functions are called when the drive doesn't respond to generic requests or when something unusual needs to be done. For instance, the Sony CDU-8012 (also known as the SunCD drive) has a weird volume scale, so we need to do a transformation on the volume setting before passing it to the drive. But other than that, the drive responds to generic CD-ROM commands, so drv_sony.c only has code relating to volume control.
Implementing drive modules is fairly simple, but usually isn't necessary so it won't be discussed here. Mail me if you need to do it.
Here are the functions a platform module needs to implement. All functions should return integers. Unless otherwise noted, they should return 0 on okay status, -1 on an error condition.
The first parameter of each function is a pointer to a wm_drive structure. You'll find it defined in "struct.h". It's discussed after the function call list. You will probably find it helpful to look at one of the existing platform modules while reading this list. The Sun module is one of the simpler ones.
wmcd_open() should determine the drive type if possible. If the wm_scsi() function has been implemented, it can simply call wm_scsi_get_drive_type() (which is in scsi.c) to retrieve the necessary information. Then find_drive_struct() (from cdrom.c) should be called to look up the drive from the list of drive modules; it returns a pointer to a wm_drive structure, which should be copied into the buffer pointed to by the "d" parameter. Finally, the drive init function should be called.
Some systems can't determine the drive type at all, for instance because the CD-ROM drive can only be accessed through a limited set of function calls. In that case, just pass empty strings to find_drive_struct() and it'll return a wm_drive structure pointing to the generic platform module routines.
The following functions can be overridden by drive modules, as they're always called indirectly via the wm_drive structure.
The wm_drive structure has at least the following elements:
struct wm_drive { int fd; /* File descriptor, if used by platform */ char vendor[16]; /* Vendor name */ char model[24]; /* Drive model */ void *aux; /* Pointer to optional platform-specific info */ void *daux; /* Pointer to optional drive-specific info */ int (*init)(); int (*get_trackcount)(); int (*get_cdlen)(); int (*get_trackinfo)(); int (*get_drive_status)(); int (*get_volume)(); int (*set_volume)(); int (*pause)(); int (*resume)(); int (*stop)(); int (*play)(); int (*eject)(); }
The "fd" and/or "aux" elements should be filled in by the wmcd_open() function after find_drive_struct() is called. The "fd" element is for an open file descriptor pointing to the drive, though if your platform doesn't use file descriptors to refer to CD-ROM drives (e.g. the BSD/386 platform, whose CD library uses structure pointers) you can use the "fd" element for something else or ignore it completely.
The "aux" element should be used to point to any state information you need to keep across calls to these functions. Since WorkMan may eventually support controlling multiple drives simultaneously, you should not use global variables to keep per-drive state. Define a structure for whatever state you need, and point "aux" to it. You can get at it in any of the routines since they are all passed the wm_drive structure you fill in in wmcd_open(). On many platforms, "aux" isn't needed.
The "daux" element is reserved for use in drive modules.
If you have questions, don't hesitate to send me E-mail. I want to see WorkMan as widely ported as possible.
-dirk <milliByte@DeathsDoor.com>