CDROM ioctl 呼叫總結

2004 年 11 月

本文件旨在描述 CDROM 層支援的 ioctl(2) 呼叫。這些呼叫在 Linux 2.6 版本中主要在 `drivers/cdrom/cdrom.c` 和 `drivers/block/scsi_ioctl.c` 中實現。

ioctl 值列在 `` 中。截至本文撰寫時,它們如下所示:

CDROMPAUSE

暫停音訊操作

CDROMRESUME

恢復暫停的音訊操作

CDROMPLAYMSF

播放音訊 MSF (struct cdrom_msf)

CDROMPLAYTRKIND

播放音訊軌道/索引 (struct cdrom_ti)

CDROMREADTOCHDR

讀取 TOC 頭 (struct cdrom_tochdr)

CDROMREADTOCENTRY

讀取 TOC 條目 (struct cdrom_tocentry)

CDROMSTOP

停止光碟驅動器

CDROMSTART

啟動光碟驅動器

CDROMEJECT

彈出光碟介質

CDROMVOLCTRL

控制輸出音量 (struct cdrom_volctrl)

CDROMSUBCHNL

讀取子通道資料 (struct cdrom_subchnl)

CDROMREADMODE2

讀取 CDROM 模式 2 資料 (2336 位元組) (struct cdrom_read)

CDROMREADMODE1

讀取 CDROM 模式 1 資料 (2048 位元組) (struct cdrom_read)

CDROMREADAUDIO

(struct cdrom_read_audio)

CDROMEJECT_SW

啟用(1)/停用(0) 自動彈出

CDROMMULTISESSION

獲取多段會話光碟的最後一段會話起始地址 (struct cdrom_multisession)

CDROM_GET_MCN

獲取“通用產品程式碼”(如果可用)(struct cdrom_mcn)

CDROM_GET_UPC

已廢棄,請改用 CDROM_GET_MCN。

CDROMRESET

硬重置驅動器

CDROMVOLREAD

獲取驅動器的音量設定 (struct cdrom_volctrl)

CDROMREADRAW

以原始模式讀取資料 (2352 位元組) (struct cdrom_read)

CDROMREADCOOKED

以處理模式讀取資料

CDROMSEEK

定址到 msf 地址

CDROMPLAYBLK

僅限 scsi-cd, (struct cdrom_blk)

CDROMREADALL

讀取所有 2646 位元組

CDROMGETSPINDOWN

返回 4 位 spindown 值

CDROMSETSPINDOWN

設定 4 位 spindown 值

CDROMCLOSETRAY

CDROMEJECT 的對應操作

CDROM_SET_OPTIONS

設定行為選項

CDROM_CLEAR_OPTIONS

清除行為選項

CDROM_SELECT_SPEED

設定光碟驅動器速度

CDROM_SELECT_DISC

選擇光碟 (適用於自動點唱機)

CDROM_MEDIA_CHANGED

檢查介質是否改變

CDROM_TIMED_MEDIA_CHANGE

檢查介質自給定時間以來是否改變 (struct cdrom_timed_media_change_info)

CDROM_DRIVE_STATUS

獲取托盤位置等

CDROM_DISC_STATUS

獲取光碟型別等

CDROM_CHANGER_NSLOTS

獲取插槽數量

CDROM_LOCKDOOR

鎖定或解鎖倉門

CDROM_DEBUG

開啟/關閉除錯訊息

CDROM_GET_CAPABILITY

獲取能力

CDROMAUDIOBUFSIZ

設定音訊緩衝區大小

DVD_READ_STRUCT

讀取結構

DVD_WRITE_STRUCT

寫入結構

DVD_AUTH

認證

CDROM_SEND_PACKET

傳送資料包到驅動器

CDROM_NEXT_WRITABLE

獲取下一個可寫塊

CDROM_LAST_WRITTEN

獲取光碟上最後寫入的塊

以下資訊是透過閱讀核心原始碼確定的。隨著時間的推移,可能會進行一些更正。


一般

除非另有說明,所有 ioctl 呼叫在成功時返回 0,在錯誤時返回 -1 並將 errno 設定為適當的值。(某些 ioctl 返回非負資料值。)

除非另有說明,所有 ioctl 呼叫在嘗試將資料複製到或從使用者地址空間複製失敗時,返回 -1 並將 errno 設定為 EFAULT。

各個驅動程式可能會返回此處未列出的錯誤程式碼。

除非另有說明,所有資料結構和常量均定義在 `` 中。


CDROMPAUSE

暫停音訊操作

用法

ioctl(fd, CDROMPAUSE, 0);
輸入

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

CDROMRESUME

恢復暫停的音訊操作

用法

ioctl(fd, CDROMRESUME, 0);
輸入

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

CDROMPLAYMSF

播放音訊 MSF

(struct cdrom_msf)

用法

struct cdrom_msf msf;

ioctl(fd, CDROMPLAYMSF, &msf);
輸入

`cdrom_msf` 結構,描述要播放的音樂片段

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

注意
  • MSF 代表分-秒-幀

  • LBA 代表邏輯塊地址

  • 片段以開始和結束時間描述,其中每個時間都以分:秒:幀表示。一幀是 1/75 秒。

CDROMPLAYTRKIND

播放音訊軌道/索引

(struct cdrom_ti)

用法

struct cdrom_ti ti;

ioctl(fd, CDROMPLAYTRKIND, &ti);
輸入

`cdrom_ti` 結構,描述要播放的音樂片段

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

注意
  • 片段以開始和結束時間描述,其中每個時間都以軌道和索引表示。

CDROMREADTOCHDR

讀取 TOC 頭

(struct cdrom_tochdr)

用法

cdrom_tochdr header;

ioctl(fd, CDROMREADTOCHDR, &header);
輸入

`cdrom_tochdr` 結構

輸出

`cdrom_tochdr` 結構

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

CDROMREADTOCENTRY

讀取 TOC 條目

(struct cdrom_tocentry)

用法

struct cdrom_tocentry entry;

ioctl(fd, CDROMREADTOCENTRY, &entry);
輸入

`cdrom_tocentry` 結構

輸出

`cdrom_tocentry` 結構

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

  • EINVAL `entry.cdte_format` 不是 CDROM_MSF 或 CDROM_LBA

  • EINVAL 請求的軌道超出範圍

  • EIO 讀取 TOC 時發生 I/O 錯誤

注意
  • TOC 代表目錄 (Table Of Contents)

  • MSF 代表分-秒-幀

  • LBA 代表邏輯塊地址

CDROMSTOP

停止光碟驅動器

用法

ioctl(fd, CDROMSTOP, 0);
輸入

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

注意
  • 此 ioctl 的確切解釋取決於裝置,但大多數裝置似乎都會使驅動器停止轉動。

CDROMSTART

啟動光碟驅動器

用法

ioctl(fd, CDROMSTART, 0);
輸入

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

注意
  • 此 ioctl 的確切解釋取決於裝置,但大多數裝置似乎都會使驅動器啟動和/或關閉托盤。其他裝置則完全忽略此 ioctl。

CDROMEJECT
  • 彈出光碟介質

用法

ioctl(fd, CDROMEJECT, 0);
輸入

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備彈出能力

  • EBUSY 其他程序正在訪問驅動器,或倉門已鎖定

注意
  • 參見下面的 CDROM_LOCKDOOR。

CDROMCLOSETRAY

CDROMEJECT 的對應操作

用法

ioctl(fd, CDROMCLOSETRAY, 0);
輸入

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備關閉托盤的能力

  • EBUSY 其他程序正在訪問驅動器,或倉門已鎖定

注意
  • 參見下面的 CDROM_LOCKDOOR。

CDROMVOLCTRL

控制輸出音量 (struct cdrom_volctrl)

用法

struct cdrom_volctrl volume;

ioctl(fd, CDROMVOLCTRL, &volume);
輸入

`cdrom_volctrl` 結構,包含多達 4 個通道的音量。

輸出

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

CDROMVOLREAD

獲取驅動器的音量設定

(struct cdrom_volctrl)

用法

struct cdrom_volctrl volume;

ioctl(fd, CDROMVOLREAD, &volume);
輸入

輸出

當前音量設定。

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

CDROMSUBCHNL

讀取子通道資料

(struct cdrom_subchnl)

用法

struct cdrom_subchnl q;

ioctl(fd, CDROMSUBCHNL, &q);
輸入

`cdrom_subchnl` 結構

輸出

`cdrom_subchnl` 結構

錯誤返回
  • ENOSYS 光碟驅動器不具備音訊功能。

  • EINVAL 格式不是 CDROM_MSF 或 CDROM_LBA

注意
  • 返回時,格式根據使用者請求轉換為 CDROM_MSF 或 CDROM_LBA

CDROMREADRAW

以原始模式讀取資料 (2352 位元組)

(struct cdrom_read)

用法

union {

  struct cdrom_msf msf;               /* input */
  char buffer[CD_FRAMESIZE_RAW];      /* return */
} arg;
ioctl(fd, CDROMREADRAW, &arg);
輸入

`cdrom_msf` 結構,指示要讀取的地址。

只有起始值是重要的。

輸出

資料寫入使用者提供的地址。

錯誤返回
  • EINVAL 地址小於 0,或 msf 小於 0:2:0

  • ENOMEM 記憶體不足

注意
  • 截至 2.6.8.1 版本,`` 中的註釋表明此 ioctl 接受 `cdrom_read` 結構,但實際原始碼讀取的是 `cdrom_msf` 結構並將資料緩衝區寫入同一地址。

  • MSF 值透過此公式轉換為 LBA 值

    lba = (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
    
CDROMREADMODE1

讀取 CDROM 模式 1 資料 (2048 位元組)

(struct cdrom_read)

注意

與 CDROMREADRAW 相同,只是塊大小為 CD_FRAMESIZE (2048) 位元組

CDROMREADMODE2

讀取 CDROM 模式 2 資料 (2336 位元組)

(struct cdrom_read)

注意

與 CDROMREADRAW 相同,只是塊大小為 CD_FRAMESIZE_RAW0 (2336) 位元組

CDROMREADAUDIO

(struct cdrom_read_audio)

用法

struct cdrom_read_audio ra;

ioctl(fd, CDROMREADAUDIO, &ra);
輸入

`cdrom_read_audio` 結構,包含讀取起始點和長度

輸出

音訊資料,返回到由 ra 指示的緩衝區

錯誤返回
  • EINVAL 格式不是 CDROM_MSF 或 CDROM_LBA

  • EINVAL `nframes` 不在 [1 75] 範圍內

  • ENXIO 驅動器沒有佇列 (可能意味著無效的檔案描述符 fd)

  • ENOMEM 記憶體不足

CDROMEJECT_SW

啟用(1)/停用(0) 自動彈出

用法

int val;

ioctl(fd, CDROMEJECT_SW, val);
輸入

指定自動彈出標誌。

輸出

錯誤返回
  • ENOSYS 驅動器不具備彈出能力。

  • EBUSY 倉門已鎖定

CDROMMULTISESSION

獲取多段會話光碟的最後一段會話起始地址

(struct cdrom_multisession)

用法

struct cdrom_multisession ms_info;

ioctl(fd, CDROMMULTISESSION, &ms_info);
輸入

`cdrom_multisession` 結構,包含所需

格式。

輸出

`cdrom_multisession` 結構填充有 `last_session` 資訊。

錯誤返回
  • EINVAL 格式不是 CDROM_MSF 或 CDROM_LBA

CDROM_GET_MCN

獲取“通用產品程式碼”(如果可用)

(struct cdrom_mcn)

用法

struct cdrom_mcn mcn;

ioctl(fd, CDROM_GET_MCN, &mcn);
輸入

輸出

通用產品程式碼

錯誤返回
  • ENOSYS 驅動器不具備讀取 MCN 資料的能力。

注意
  • 原始碼註釋說明

    The following function is implemented, although very few
    audio discs give Universal Product Code information, which
    should just be the Medium Catalog Number on the box.  Note,
    that the way the code is written on the CD is /not/ uniform
    across all discs!
    
CDROM_GET_UPC

CDROM_GET_MCN (已廢棄)

截至 2.6.8.1 版本,未實現

CDROMRESET

硬重置驅動器

用法

ioctl(fd, CDROMRESET, 0);
輸入

輸出

錯誤返回
  • EACCES 訪問被拒絕:需要 CAP_SYS_ADMIN 許可權

  • ENOSYS 驅動器不具備重置能力。

CDROMREADCOOKED

以處理模式讀取資料

用法

u8 buffer[CD_FRAMESIZE]

ioctl(fd, CDROMREADCOOKED, buffer);
輸入

輸出

2048 位元組資料,“處理”模式。

注意

並非所有驅動器都實現。

CDROMREADALL

讀取所有 2646 位元組

與 CDROMREADCOOKED 相同,但讀取 2646 位元組。

CDROMSEEK

定址到 msf 地址

用法

struct cdrom_msf msf;

ioctl(fd, CDROMSEEK, &msf);
輸入

要定址到的 MSF 地址。

輸出

CDROMPLAYBLK

僅限 scsi-cd

(struct cdrom_blk)

用法

struct cdrom_blk blk;

ioctl(fd, CDROMPLAYBLK, &blk);
輸入

要播放的區域

輸出

CDROMGETSPINDOWN

已過時,曾僅限於 ide-cd

用法

char spindown;

ioctl(fd, CDROMGETSPINDOWN, &spindown);
輸入

輸出

當前 4 位 spindown 值。

CDROMSETSPINDOWN

已過時,曾僅限於 ide-cd

用法

char spindown

ioctl(fd, CDROMSETSPINDOWN, &spindown);
輸入

用於控制 spindown 的 4 位值 (待辦:此處需更多細節)

輸出

CDROM_SET_OPTIONS

設定行為選項

用法

int options;

ioctl(fd, CDROM_SET_OPTIONS, options);
輸入

驅動器選項的新值。以下各項的邏輯“或”:

CDO_AUTO_CLOSE

首次 open(2) 時關閉托盤

CDO_AUTO_EJECT

最後釋放時開啟托盤

CDO_USE_FFLAGS

在 open 時使用 O_NONBLOCK 資訊

CDO_LOCK

在檔案開啟時鎖定托盤

CDO_CHECK_TYPE

在開啟資料時檢查型別

輸出

在 ioctl 返回值中返回結果選項設定。錯誤時返回 -1。

錯誤返回
  • ENOSYS 所選選項不受驅動器支援。

CDROM_CLEAR_OPTIONS

清除行為選項

與 CDROM_SET_OPTIONS 相同,只是所選選項被關閉。

CDROM_SELECT_SPEED

設定光碟驅動器速度

用法

int speed;

ioctl(fd, CDROM_SELECT_SPEED, speed);
輸入

新的驅動器速度。

輸出

錯誤返回
  • ENOSYS 驅動器不支援速度選擇。

CDROM_SELECT_DISC

選擇光碟 (適用於自動點唱機)

用法

int disk;

ioctl(fd, CDROM_SELECT_DISC, disk);
輸入

要載入到驅動器中的光碟。

輸出

錯誤返回
  • EINVAL 光碟編號超出驅動器容量

CDROM_MEDIA_CHANGED

檢查介質是否改變

用法

int slot;

ioctl(fd, CDROM_MEDIA_CHANGED, slot);
輸入

要測試的插槽編號,除了自動換碟機外始終為零。

也可能是特殊值 CDSL_NONE 或 CDSL_CURRENT

輸出

ioctl 返回值為 0 或 1,取決於介質是否

已改變,或錯誤時返回 -1。

錯誤返回
  • ENOSYS 驅動器無法檢測到介質改變

  • EINVAL 插槽編號超出驅動器容量

  • ENOMEM 記憶體不足

CDROM_DRIVE_STATUS

獲取托盤位置等

用法

int slot;

ioctl(fd, CDROM_DRIVE_STATUS, slot);
輸入

要測試的插槽編號,除了自動換碟機外始終為零。

也可能是特殊值 CDSL_NONE 或 CDSL_CURRENT

輸出

ioctl 返回值將是以下值之一

來自 ``

CDS_NO_INFO

資訊不可用。

CDS_NO_DISC

CDS_TRAY_OPEN

CDS_DRIVE_NOT_READY

CDS_DISC_OK

-1

錯誤

錯誤返回
  • ENOSYS 驅動器無法檢測到驅動器狀態

  • EINVAL 插槽編號超出驅動器容量

  • ENOMEM 記憶體不足

CDROM_DISC_STATUS

獲取光碟型別等

用法

ioctl(fd, CDROM_DISC_STATUS, 0);
輸入

輸出

ioctl 返回值將是以下值之一

來自 ``

  • CDS_NO_INFO

  • CDS_AUDIO

  • CDS_MIXED

  • CDS_XA_2_2

  • CDS_XA_2_1

  • CDS_DATA_1

錯誤返回

目前無

注意
  • 原始碼註釋說明

    Ok, this is where problems start.  The current interface for
    the CDROM_DISC_STATUS ioctl is flawed.  It makes the false
    assumption that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc.
    Unfortunately, while this is often the case, it is also
    very common for CDs to have some tracks with data, and some
    tracks with audio.      Just because I feel like it, I declare
    the following to be the best way to cope.  If the CD has
    ANY data tracks on it, it will be returned as a data CD.
    If it has any XA tracks, I will return it as that.      Now I
    could simplify this interface by combining these returns with
    the above, but this more clearly demonstrates the problem
    with the current interface.  Too bad this wasn't designed
    to use bitmasks...             -Erik
    
    Well, now we have the option CDS_MIXED: a mixed-type CD.
    User level programmers might feel the ioctl is not very
    useful.
                    ---david
    
CDROM_CHANGER_NSLOTS

獲取插槽數量

用法

ioctl(fd, CDROM_CHANGER_NSLOTS, 0);
輸入

輸出

ioctl 返回值將是 CD 換碟機中的插槽數量。對於非多碟裝置,通常為 1。

錯誤返回

CDROM_LOCKDOOR

鎖定或解鎖倉門

用法

int lock;

ioctl(fd, CDROM_LOCKDOOR, lock);
輸入

倉門鎖定標誌,1=鎖定,0=解鎖

輸出

錯誤返回
  • EDRIVE_CANT_DO_THIS

    不支援倉門鎖定功能。

  • EBUSY

    當多個使用者開啟驅動器且不具備 CAP_SYS_ADMIN 許可權時嘗試解鎖

注意

截至 2.6.8.1 版本,鎖定標誌是全域性的,意味著所有 CD 驅動器將同時鎖定或解鎖。這可能是一個錯誤。

EDRIVE_CANT_DO_THIS 值在 `` 中定義,目前 (2.6.8.1) 與 EOPNOTSUPP 相同。

CDROM_DEBUG

開啟/關閉除錯訊息

用法

int debug;

ioctl(fd, CDROM_DEBUG, debug);
輸入

光碟除錯標誌,0=停用,1=啟用

輸出

ioctl 返回值將是新的除錯標誌。

錯誤返回
  • EACCES 訪問被拒絕:需要 CAP_SYS_ADMIN 許可權

CDROM_GET_CAPABILITY

獲取能力

用法

ioctl(fd, CDROM_GET_CAPABILITY, 0);
輸入

輸出

ioctl 返回值是當前裝置能力標誌。參見 CDC_CLOSE_TRAY, CDC_OPEN_TRAY 等。

CDROMAUDIOBUFSIZ

設定音訊緩衝區大小

用法

int arg;

ioctl(fd, CDROMAUDIOBUFSIZ, val);
輸入

新的音訊緩衝區大小

輸出

ioctl 返回值是新的音訊緩衝區大小,或錯誤時返回 -1。

錯誤返回
  • ENOSYS 該驅動程式不支援。

注意

並非所有驅動程式都支援。

DVD_READ_STRUCT 讀取結構

用法

dvd_struct s;

ioctl(fd, DVD_READ_STRUCT, &s);
輸入

`dvd_struct` 結構,包含

型別

指定所需資訊,可以是 DVD_STRUCT_PHYSICAL, DVD_STRUCT_COPYRIGHT, DVD_STRUCT_DISCKEY, DVD_STRUCT_BCA, DVD_STRUCT_MANUFACT 之一

physical.layer_num

所需層,從 0 開始索引

copyright.layer_num

所需層,從 0 開始索引

disckey.agid

輸出

`dvd_struct` 結構,包含

物理

當 `type == DVD_STRUCT_PHYSICAL` 時

版權

當 `type == DVD_STRUCT_COPYRIGHT` 時

disckey.value

當 `type == DVD_STRUCT_DISCKEY` 時

bca.{len,value}

當 `type == DVD_STRUCT_BCA` 時

manufact.{len,valu}

當 `type == DVD_STRUCT_MANUFACT` 時

錯誤返回
  • EINVAL `physical.layer_num` 超過層數

  • EIO 從驅動器收到無效響應

DVD_WRITE_STRUCT 寫入結構

截至 2.6.8.1 版本,未實現

DVD_AUTH 認證

用法

dvd_authinfo ai;

ioctl(fd, DVD_AUTH, &ai);
輸入

`dvd_authinfo` 結構。參見 ``

輸出

`dvd_authinfo` 結構。

錯誤返回
  • ENOTTY `ai.type` 未識別。

CDROM_SEND_PACKET

傳送資料包到驅動器

用法

struct cdrom_generic_command cgc;

ioctl(fd, CDROM_SEND_PACKET, &cgc);
輸入

`cdrom_generic_command` 結構,包含要傳送的資料包。

輸出

`cdrom_generic_command` 結構,包含結果。

錯誤返回
  • EIO

    命令失敗。

  • EPERM

    操作不允許,原因可能是嘗試對只讀開啟的驅動器執行寫入命令,或該命令需要 CAP_SYS_RAWIO 許可權

  • EINVAL

    `cgc.data_direction` 未設定

CDROM_NEXT_WRITABLE

獲取下一個可寫塊

用法

long next;

ioctl(fd, CDROM_NEXT_WRITABLE, &next);
輸入

輸出

下一個可寫塊。

注意

如果裝置不直接支援此 ioctl,則

ioctl 將返回 CDROM_LAST_WRITTEN + 7。

CDROM_LAST_WRITTEN

獲取光碟上最後寫入的塊

用法

long last;

ioctl(fd, CDROM_LAST_WRITTEN, &last);
輸入

輸出

光碟上最後寫入的塊

注意

如果裝置不直接支援此 ioctl,則結果將從光碟的目錄表中匯出。如果目錄表無法讀取,此 ioctl 將返回錯誤。