CDROM ioctl 呼叫總結¶
Edward A. Falk <efalk@google.com>
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 將返回錯誤。