4 * Linux cd-rom device driver. Implemented using the SCSI transport.
6 * Copyright (c) 2005 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
24 #include <linux/cdrom.h>
26 #include <sys/ioctl.h>
30 #include "drivers/cdrom/cdimpl.h"
32 static gboolean linux_is_cdrom_device( FILE *f );
33 static gboolean linux_cdrom_disc_init( cdrom_disc_t disc, ERROR *err );
34 static cdrom_disc_t linux_cdrom_drive_open( cdrom_drive_t drive, ERROR *err );
35 static cdrom_error_t linux_cdrom_do_cmd( int fd, char *cmd,
36 unsigned char *buf, unsigned int *buflen, unsigned char direction );
37 static cdrom_error_t linux_packet_read( cdrom_disc_t disc, char *cmd,
38 unsigned char *buf, uint32_t *buflen );
39 static cdrom_error_t linux_packet_cmd( cdrom_disc_t disc, char *cmd );
40 static gboolean linux_media_changed( cdrom_disc_t disc );
43 struct cdrom_disc_factory linux_cdrom_drive_factory = { "Linux", NULL,
44 linux_is_cdrom_device, linux_cdrom_disc_init, cdrom_disc_scsi_read_toc };
46 static struct cdrom_scsi_transport linux_scsi_transport = {
47 linux_packet_read, linux_packet_cmd, linux_media_changed };
49 static gboolean linux_is_cdrom_device( FILE *f )
51 int caps = ioctl(fileno(f), CDROM_GET_CAPABILITY);
53 /* Quick check that this is really a CD device */
60 void cdrom_drive_scan(void)
62 unsigned char ident[256];
64 char cmd[12] = {0x12,0,0,0, 0xFF,0,0,0, 0,0,0,0};
69 while( (ent = getfsent()) != NULL ) {
70 if( (stat(ent->fs_spec, &st) != -1) &&
71 S_ISBLK(st.st_mode) ) {
72 /* Got a valid block device - is it a CDROM? */
73 int fd = open(ent->fs_spec, O_RDONLY|O_NONBLOCK);
76 int caps = ioctl(fd, CDROM_GET_CAPABILITY);
78 /* Appears to support CDROM functions */
79 identlen = sizeof(ident);
80 if( linux_cdrom_do_cmd( fd, cmd, ident, &identlen, CGC_DATA_READ ) ==
82 const char *drive_name = mmc_parse_inquiry( ident );
83 cdrom_drive_add( ent->fs_spec, drive_name, linux_cdrom_drive_open );
91 gboolean linux_cdrom_disc_init( cdrom_disc_t disc, ERROR *err )
93 if( linux_is_cdrom_device( cdrom_disc_get_base_file(disc) ) ) {
94 cdrom_disc_scsi_init(disc, &linux_scsi_transport);
101 cdrom_disc_t linux_cdrom_drive_open( cdrom_drive_t drive, ERROR *err )
104 int fd = open(drive->name, O_RDONLY|O_NONBLOCK);
106 SET_ERROR(err, LX_ERR_FILE_NOOPEN, "Unable to open device '%s': %s", drive->name, strerror(errno) );
109 FILE *f = fdopen(fd,"ro");
110 if( !linux_is_cdrom_device(f) ) {
111 SET_ERROR(err, LX_ERR_FILE_UNKNOWN, "Device '%s' is not a CDROM drive", drive->name );
114 return cdrom_disc_scsi_new_file(f, drive->name, &linux_scsi_transport, err);
118 static gboolean linux_media_changed( cdrom_disc_t disc )
120 int fd = cdrom_disc_get_base_fd(disc);
121 int status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
122 if( status == CDS_DISC_OK ) {
123 status = ioctl(fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT);
124 return status == 0 ? FALSE : TRUE;
126 return disc->disc_type == CDROM_DISC_NONE ? FALSE : TRUE;
130 static cdrom_error_t linux_cdrom_do_cmd( int fd, char *cmd,
131 unsigned char *buffer, unsigned int *buflen,
132 unsigned char direction )
134 struct request_sense sense;
135 struct cdrom_generic_command cgc;
137 memset( &cgc, 0, sizeof(cgc) );
138 memset( &sense, 0, sizeof(sense) );
139 memcpy( cgc.cmd, cmd, 12 );
144 cgc.buflen = *buflen;
146 cgc.data_direction = direction;
148 if( ioctl(fd, CDROM_SEND_PACKET, &cgc) < 0 ) {
149 if( sense.sense_key == 0 ) {
152 return sense.sense_key | (sense.asc<<8);
156 *buflen = cgc.buflen;
157 return CDROM_ERROR_OK;
163 * Send a packet command to the device and wait for a response.
164 * @return 0 on success, -1 on an operating system error, or a sense error
165 * code on a device error.
167 static cdrom_error_t linux_packet_read( cdrom_disc_t disc, char *cmd,
168 unsigned char *buffer, unsigned int *buflen )
170 int fd = cdrom_disc_get_base_fd(disc);
171 return linux_cdrom_do_cmd( fd, cmd, buffer, buflen, CGC_DATA_READ );
174 static cdrom_error_t linux_packet_cmd( cdrom_disc_t disc, char *cmd )
176 int fd = cdrom_disc_get_base_fd(disc);
177 return linux_cdrom_do_cmd( fd, cmd, NULL, NULL, CGC_DATA_NONE );
.