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 "gdrom/gddriver.h"
31 #include "gdrom/packet.h"
34 static gboolean linux_is_cdrom_device( FILE *f );
35 static gdrom_disc_t linux_open_device( const gchar *filename, FILE *f );
36 static gdrom_error_t linux_packet_read( gdrom_disc_t disc, char *cmd,
37 unsigned char *buf, uint32_t *buflen );
38 static gdrom_error_t linux_packet_cmd( gdrom_disc_t disc, char *cmd );
39 static gboolean linux_media_changed( gdrom_disc_t disc );
42 struct gdrom_image_class cdrom_device_class = { "Linux", NULL,
43 linux_is_cdrom_device, linux_open_device };
45 static struct gdrom_scsi_transport linux_scsi_transport = {
46 linux_packet_read, linux_packet_cmd, linux_media_changed };
48 static gboolean linux_is_cdrom_device( FILE *f )
50 int caps = ioctl(fileno(f), CDROM_GET_CAPABILITY);
52 /* Quick check that this is really a CD device */
59 GList *cdrom_get_native_devices(void)
65 while( (ent = getfsent()) != NULL ) {
66 if( (stat(ent->fs_spec, &st) != -1) &&
67 S_ISBLK(st.st_mode) ) {
68 /* Got a valid block device - is it a CDROM? */
69 int fd = open(ent->fs_spec, O_RDONLY|O_NONBLOCK);
72 int caps = ioctl(fd, CDROM_GET_CAPABILITY);
74 /* Appears to support CDROM functions */
75 FILE *f = fdopen(fd,"r");
76 gdrom_disc_t disc = gdrom_scsi_disc_new(ent->fs_spec, f, &linux_scsi_transport);
78 list = g_list_append( list, gdrom_device_new(disc->name, disc->display_name) );
79 disc->destroy(disc,TRUE);
91 gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )
96 static gdrom_disc_t linux_open_device( const gchar *filename, FILE *f )
98 if( !linux_is_cdrom_device(f) ) {
102 return gdrom_scsi_disc_new(filename, f, &linux_scsi_transport);
105 static gboolean linux_media_changed( gdrom_disc_t disc )
107 int fd = fileno(disc->file);
108 int status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
109 if( status == CDS_DISC_OK ) {
110 status = ioctl(fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT);
111 return status == 0 ? FALSE : TRUE;
113 return disc->disc_type == IDE_DISC_NONE ? FALSE : TRUE;
118 * Send a packet command to the device and wait for a response.
119 * @return 0 on success, -1 on an operating system error, or a sense error
120 * code on a device error.
122 static gdrom_error_t linux_packet_read( gdrom_disc_t disc, char *cmd,
123 unsigned char *buffer, uint32_t *buflen )
125 int fd = fileno(disc->file);
126 struct request_sense sense;
127 struct cdrom_generic_command cgc;
129 memset( &cgc, 0, sizeof(cgc) );
130 memset( &sense, 0, sizeof(sense) );
131 memcpy( cgc.cmd, cmd, 12 );
133 cgc.buflen = *buflen;
135 cgc.data_direction = CGC_DATA_READ;
137 if( ioctl(fd, CDROM_SEND_PACKET, &cgc) < 0 ) {
138 if( sense.sense_key == 0 ) {
141 /* TODO: Map newer codes back to the ones used by the gd-rom. */
142 return sense.sense_key | (sense.asc<<8);
145 *buflen = cgc.buflen;
150 static gdrom_error_t linux_packet_cmd( gdrom_disc_t disc, char *cmd )
152 int fd = fileno(disc->file);
153 struct request_sense sense;
154 struct cdrom_generic_command cgc;
156 memset( &cgc, 0, sizeof(cgc) );
157 memset( &sense, 0, sizeof(sense) );
158 memcpy( cgc.cmd, cmd, 12 );
162 cgc.data_direction = CGC_DATA_NONE;
164 if( ioctl(fd, CDROM_SEND_PACKET, &cgc) < 0 ) {
165 if( sense.sense_key == 0 ) {
168 /* TODO: Map newer codes back to the ones used by the gd-rom. */
169 return sense.sense_key | (sense.asc<<8);
.