我正在尝试使用 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/