CDROM API

A universal device driver exists (cdrom.o) in Linux to access any cd, regardless of the interface it is connected to. (scsi, ide, usb, IIel)

All
functions to access a cdrom device are via linux/cdrom.h

The API is consistent, and, relatively simple. You use the ioctl() function with the constants defined in linux/cdrom.h to access the cdrom itself.

The ioctl() function is universal for all device drivers. Therefore, while a large number of error messages are possible, only a small range is returned for any function to the cdrom interface driver. Those values are listed for each function described below.



Track Layouts

A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336,  2340, or 2352 bytes long.

The basic unit of measure is the FRAME. Regardless of format a frame is universally 2352 bytes long.

CD-DA  audio (red):                | audio bytes
                                   | 98x24 chunks (2352)                   |

       data  (yellow, mode1 form1) | sync - head - data - EDC - zero - ECC |
                                   | 12   -  4   - 2048 - 4   -   8  - 276 |
       data  (yellow, mode2 form2) | sync - head - data                    |

                                   | 12   -  4   - 2336                    |

CD-XA  data  (green,  mode2 form1) | sync - head - sub - data - EDC - ECC  |
                                   | 12   -  4   - 8   - 2048 - 4 -   276  |
       data  (green,  mode2 form2) | sync - head - sub - data - EDC        |

                                   | 12   -  4   - 8   - 2324 - 4          |


CD audio speed is 75 frames per second for 74 minutes playing time making

74*75 = 5550 frames per cd



Addressing

accessing sections of a cd is in one of two formats

LBA: logical block address
MSF: Minutes, Sectors, Frames

most functions contain the ability to work in either mode (and return similar). You can succesfully mix and match at anytime. (Internally, the driver converts all msf commands to lba).

A logical block address is expressed in frames (starting at 0).

The start of MSF addressing is biased 150 frames (2 seconds) into the cd. Thus an msf of 0:0:0 is an lba address of frame 149.

the api uses the struct

struct cdrom_msf
{
    u_char minute;
    u_char second;
    u_char frame;
};

    when working with msf values.


Where relevant the api uses a consistent union to address in both modes

union cdrom_addr
{
     int lba;
     struct cdrom_msf msf;
}


BASIC FILE OPEN AND CLOSE

int cd_fd=    open("/dev/cdrom",O_RDONLY | O_NONBLOCK);

    returns 0 on success

    close(fd);

EJECT AND LOAD

    ioctl(cd_fd,CDROMEJECT);             //eject
    ioctl(cd_fd,CDROMCLOSETRAY);     // load
    ioctl(cd_fd,CDROMEJECT_SW,true | false);  // enable eject on close

Eject and load work irrespective of cd installed or otherwise

Error returns:

-EBUSY drive->usage > 1
-EIO cmdQ failed


PAUSE & RESUME

    ioctl(cd_fd,CDROMPAUSE);
    ioctl(cd_fd,CDROMRESUME);

Error returns:

    -EIO cmdQ failed


START & STOP

    ioctl(cd_fd,CDROMSTART);
    ioctl(cd_fd,CDROMSTOP);

Error Returns:

    -EIO cmdQ failed


VOLUME

u_char volumes[4];

    ioctl(cd_fd,CDROMVOLCTRL, &volumes);    // write values
    ioctl(cd_fd,CDROMVOLREAD, &volumes);    // read values

Returns:

-EFAULT bad struct
-EIO queue packe fail


channels are 0..255 in volume
channels 3 and 4 generally return zero


RESET


ioctl(cd_fd,CDROMRESET);

returns -EPERM op not permitted



READ SUBCHANNEL

// simply reads status of the cd

struct cdrom_subchnl
{
    u_char cdsc_format; // required CDROM_MSF or LBA
    u_char cdsc_audiostatus;         // filled
        CDROM_AUDIO_INVALID 0x00         /* audio status not supported */
        CDROM_AUDIO_PLAY 0x11             /* audio play operation in progress */
        CDROM_AUDIO_PAUSED 0x12        /* audio play operation paused */
        CDROM_AUDIO_COMPLETED 0x13 /* audio play successfully completed */
        CDROM_AUDIO_ERROR 0x14         /* audio play stopped due to error */
        CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */
    u_char cdsc_adr: 4;     // not used
    u_char cdsc_ctrl: 4;     // filled
    u_char cdsc_trk;         // filled
    u_char cdsc_ind;         // filled
    union cdrom_addr relative; // filled
    union cdrom_addr absolute; // filled
};

    ioctl(cd_fd, CDROMSUBCHNL, sc);

Returns:

-EFAULT bad struct
-EIO queue packe fail

GET TOC HEADER

// reads beginning and ending tracks of cd // FROM TRACK 1

struct cdrom_tochdr
{
 u_char cdth_trk0; /* start track */
 u_char cdth_trk1; /* end track */
};
ioctl(cd_fd,CDROMREADTOCHDR,&tochdr);

A pure data cd will return 1:1

Returns:

-EFAULT invalid tochdr struct
-EIO cdrom_read_toc failed.

struct cdrom_tocentry
{
    u_char cdte_track; // required
    u_char cdte_adr :4; // filled
    u_char cdte_ctrl :4; // filled
                               CDROM_DATA_TRACK 0x04 track is data or audio
    u_char cdte_format; // required CDROM_MSF or CDROM_LBA
    union cdrom_addr cdte_addr; // filled;
    u_char cdte_datamode; // not used
};

    ioctl(cd_fd,CDROMREADTOCENTRY,&tc);

returns:

-EFAULT invalid struct
-EINVAL invalid track;
-EIO cdrom_read_toc failed


General flow

controlling aspects of the cd is accomplished using a mix of the above functions. To wit:

    open("/dev/cdrom",O_RDONLY | O_NONBLOCK);
    ioctl(cd_fd,CDROMCLOSETRAY);     // (if required)

    ioctl(cd_fd,CDROMREADTOCHDR,&tochdr); // find out how many tracks
    ioctl(cd_fd,CDROMREADTOCENTRY,&tc);     // read info for each of these tracks

    for(;;)
    {
         ioctl(cd_fd, CDROMSUBCHNL, sc);

/read status    
        .. perfom ops
    }


    ioctl(cd_fd,CDROMEJECT);
            //eject

    close(fd);

The remining functions are what you can do with the cd, including playing tracks.







PLAY TRACK(S)


struct cdrom_ti
{
    u_char start_track //from 1
    u_char cdti_ind0; /* not used */
    u_char end_track; /* from 1*/
    u_char cdti_ind1; /* not used */
};

ioctl(cd_fd,CDROMPLAYTRKIND,&ti);
Returns:

-EFAULT invalid struct
-EINVAL start > end or invalid track
-EIO cmdQ failed


PLAY MSF

struct cdrom_msf
{
    u_char cdmsf_min0; /* start position in real minutes */
    u_char cdmsf_sec0; /* real seconds */
    u_char cdmsf_frame0; /* frames */
    u_char cdmsf_min1; /* end ... */
    u_char cdmsf_sec1;
    u_char cdmsf_frame1;
};

    ioctl(cd_fd, CDROMPLAYMSF, &ms);

Returns:

-EFAULT invalid msf struct
-EINVAL start > end;
-EIO cmdQ failed

PLAY BLOCK

struct cdrom_blk
{
    unsigned from;     // in lba
    unsigned short len;     // in frames
};
    ioctl(cd_fd,CDROMPLAYBLK,&blk);


This ioctl is only used by the scsi-cd driver.
It is for playing audio in logical block addressing mode.


CD BARCODE

struct cdrom_mcn
{
  u_char medium_catalog_number[14]; /* 13 ASCII digits, null-terminated */
};

    ioctl(cd_fd,CDROM_GET_UPC, &mcn); //deprecated
    ioctl(cd_fd,CDROM_GET_MCN, &mcn);

Returns:

 -EFAULT bad struct
 -EIO queue packe fail (playing)


MULTISESSION

struct cdrom_multisession
{
 union cdrom_addr addr; /* Returned: address start-of-last-session
 u_char xa_flag;             /* Returned: 1= XA disk otherwise addr is invalid */
 u_char addr_format;         /* Required: CDROM_LBA or CDROM_MSF */
};

    ioctl(cd_fd,CDROMMULTISESSION,&ms_info);

Returns:

 -EFAULT bad struct, or oversized nframes (blocksize)
 -EINVAL addr_format not set to msf or lba
 -EIO cdrom_read_toc failed.

READ RAW FRAMES

struct cdrom_read_audio ra
{
    union cdrom_addr addr; /* REQUIRED frame address */
    u_char addr_format; /* REQUIRED .....CDROM_LBA or CDROM_MSF */
    int nframes;         /* REQUIRED number of 2352-byte-frames to read
    u_char *buf;         /* REQUIRED frame buffer (size: nframes*2352 bytes) */
};

    ioctl(cd_fd,CDROMREADAUDIO,&ra);

Returns:

returns no fault on nframes =0 (dummy op)

 -EFAULT bad struct, or oversized nframes

 -EINVAL ra.nframes bad or format unknown, or lba oversize
 -ENOMEM can't make temp malloc for buffer
 -EIO packet command or cdrom_read_toc failed.

READ RAW MSF
READ MODE1
READ MODE2

union
{
    struct cdrom_msf msf
    char bigbuf[2536];
};

    ioctl(cd_fd,CDROMREADRAW,&msf);
    ioctl(cd_fd,CDROMREADMODE1,msf);
    ioctl(cd_fd,CDROMREADMODE2,buf);

returns EINVAL on scsi 2048 Bytes
returns EINVAL on scsi 2336 Bytes

In each case, the begiining of the buffer which contains the msf values is overwritten with the requested data


READ SLOT

    ioctl(cd_fd,CDROMLOADFROMSLOT,slot);


// the loadsloat as been deprecated and cuases a kernel message in ide-cdrom.

    ioctl(cd_fd,CDROM_SELECT_DISC,slotnum) ; startng at 0 (-1 = defaultunlodad

Returns:

 -EBUSY in use;
 -EIO cdrom_read_toc failed.
 -ENOENT NOT_READY


searchSearch Index