c - 如何对音频 CD 驱动器使用 ioctl() 函数

标签 c ubuntu system-calls ioctl cd-rom

我正在尝试使用 Ubuntu 中的 I/O 调用系统编写 C 程序。

我找到了这个文档,CDROM API from Linux-sxs.org ,但我不知道在哪里可以找到这些参数。

你能给我一个关于如何使用ioctl()函数的例子吗?

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) */
};

if (ioctl(cdrom, CDROMREADAUDIO, &ra)<0)
{
    perror("ioctl");
    exit(1);
}

最佳答案

根据 cdrom 驱动程序的内核文档,cdrom.txt ,命令格式如下:

CDROMREADAUDIO          (struct cdrom_read_audio)

usage:

  struct cdrom_read_audio ra;
  ioctl(fd, CDROMREADAUDIO, &ra);

inputs:
  cdrom_read_audio structure containing read start
  point and length

outputs:
  audio data, returned to buffer indicated by ra

error return:
  EINVAL    format not CDROM_MSF or CDROM_LBA
  EINVAL    nframes not in range [1 75]
  ENXIO     drive has no queue (probably means invalid fd)
  ENOMEM    out of memory

cdrom_read_audio 结构的格式可以在 cdrom.h 中找到。 :

/* This struct is used by the CDROMREADAUDIO ioctl */
struct cdrom_read_audio
{
    union cdrom_addr addr; /* frame address */
    __u8 addr_format;      /* CDROM_LBA or CDROM_MSF */
    int nframes;           /* number of 2352-byte-frames to read at once */
    __u8 __user *buf;      /* frame buffer (size: nframes*2352 bytes) */
};

它使用一个 union cdrom_addr 类型,定义在同一个文件中:

/* Address in either MSF or logical format */
union cdrom_addr        
{
    struct cdrom_msf0   msf;
    int                 lba;
};

在这里我们有一个选择 - 使用 MSF(分钟-秒-帧)或 LBA(逻辑 block 寻址)。由于您正在阅读音频,因此您可能需要 MSF。 struct cdrom_msf0也可以在头文件中找到:

/* Address in MSF format */
struct cdrom_msf0       
{
    __u8    minute;
    __u8    second;
    __u8    frame;
};

通过这项研究,我们可以编写一个简单的测试:

#include <sys/ioctl.h>    //Provides ioctl()
#include <linux/cdrom.h>  //Provides struct and #defines
#include <unistd.h>       //Provides open() and close()
#include <sys/types.h>    //Provides file-related #defines and functions
#include <sys/stat.h>     //Ditto
#include <fcntl.h>        //Ditto
#include <stdlib.h>       //Provides malloc()
#include <string.h>       //Provides memset()
#include <stdint.h>       //Provides uint8_t, etc
#include <errno.h>        //Provides errno
#include <stdio.h>        //Provides printf(), fprintf()

int main() 
{
  int fd = open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
  if (errno != 0)
  {
    fprintf(stderr, "Error opening file: %u\n", errno);
    return -1;
  }
  struct cdrom_msf0 time; //The start read time ...
  time.minute = 2;
  time.second = 45;
  time.frame = 0;
  union cdrom_addr address;  //... in a union
  address.msf = time;
  struct cdrom_read_audio ra;  //Our data object
  ra.addr = address;           //With the start time
  ra.addr_format = CDROM_MSF;  //We used MSF
  ra.nframes = CD_FRAMES;      //A second - 75 frames (the most we can read at a time anyway)
  uint8_t* buff = malloc(CD_FRAMES * CD_FRAMESIZE_RAW); //Frames per second (75) * bytes per frame (2352)
  memset(buff, 0, CD_FRAMES * CD_FRAMESIZE_RAW); //Make sure it's empty
  ra.buf = buff;               //Set our buffer in our object
  if (ioctl(fd, CDROMREADAUDIO, &ra) != 0)  //The ioctl call
  {
    fprintf(stderr, "Error giving ioctl command: %u\n", errno);
    return -1;
  }
  for (int frame = 0; frame < CD_FRAMES; frame++)  //A hexdump (could be a real use for the data)
  {
    printf("Frame %u:", frame);
    for (int byte = 0; byte < CD_FRAMESIZE_RAW; byte++)
    {
      printf(" %.2X", buff[frame * CD_FRAMESIZE_RAW + byte]);
    }
    printf("\n");
  }
  close(fd);  //Close our file
  return 0;   //And exit
}

确保您使用的是音频 CD,否则 ioctl 调用将抛出 EIO(例如,使用 CD-ROM)。实际上,您可能会将此数据写入文件或对其进行处理。无论哪种方式,您最终可能会使用循环阅读超过一秒。

关于c - 如何对音频 CD 驱动器使用 ioctl() 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53308161/

相关文章:

c - 从 C 套接字中提取 IP 地址

c - sscanf 在我的字符串中添加 0

c - C语言中的#define和 '='有什么区别?

python - ctypes 结构,字节对齐

php - 如何在 ubuntu 15 上安装 pcntl 扩展

optimization - 给定今天的时间,以 golang 中的分钟数获取 UTC 时间的最佳方式

c - tcgetpgrp() 返回值是什么意思?

c - Linux 系统调用 time() 出错时返回 ((time_t) -14)

c - 在 C 中打印一个奇数哈希倒三角形

javascript - 目录 "javascript"被完全忽略