filename | src/drivers/cd_linux.c |
changeset | 1025:f32183d273fb |
prev | 1023:264e2fd90be8 |
author | nkeynes |
date | Fri Jul 31 13:45:32 2009 +1000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Remove or change the level of a bunch of INFO messages that shouldn't really be INFO level |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * Linux cd-rom device driver. Implemented using the SCSI transport.
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
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.
12 *
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.
17 */
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <ctype.h>
24 #include <linux/cdrom.h>
25 #include <sys/stat.h>
26 #include <sys/ioctl.h>
27 #include <fstab.h>
28 #include <fcntl.h>
30 #include "gdrom/gddriver.h"
31 #include "gdrom/packet.h"
32 #include "dream.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 )
49 {
50 int caps = ioctl(fileno(f), CDROM_GET_CAPABILITY);
51 if( caps == -1 ) {
52 /* Quick check that this is really a CD device */
53 return FALSE;
54 } else {
55 return TRUE;
56 }
57 }
59 GList *cdrom_get_native_devices(void)
60 {
61 GList *list = NULL;
62 struct fstab *ent;
63 struct stat st;
64 setfsent();
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);
70 if( fd == -1 )
71 continue;
72 int caps = ioctl(fd, CDROM_GET_CAPABILITY);
73 if( caps != -1 ) {
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);
77 if( disc != NULL ) {
78 list = g_list_append( list, gdrom_device_new(disc->name, disc->display_name) );
79 disc->destroy(disc,TRUE);
80 } else {
81 close(fd);
82 }
83 } else {
84 close(fd);
85 }
86 }
87 }
88 return list;
89 }
91 gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )
92 {
93 return NULL;
94 }
96 static gdrom_disc_t linux_open_device( const gchar *filename, FILE *f )
97 {
98 if( !linux_is_cdrom_device(f) ) {
99 return NULL;
100 }
102 return gdrom_scsi_disc_new(filename, f, &linux_scsi_transport);
103 }
105 static gboolean linux_media_changed( gdrom_disc_t disc )
106 {
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;
112 } else {
113 return disc->disc_type == IDE_DISC_NONE ? FALSE : TRUE;
114 }
115 }
117 /**
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.
121 */
122 static gdrom_error_t linux_packet_read( gdrom_disc_t disc, char *cmd,
123 unsigned char *buffer, uint32_t *buflen )
124 {
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 );
132 cgc.buffer = buffer;
133 cgc.buflen = *buflen;
134 cgc.sense = &sense;
135 cgc.data_direction = CGC_DATA_READ;
137 if( ioctl(fd, CDROM_SEND_PACKET, &cgc) < 0 ) {
138 if( sense.sense_key == 0 ) {
139 return -1;
140 } else {
141 /* TODO: Map newer codes back to the ones used by the gd-rom. */
142 return sense.sense_key | (sense.asc<<8);
143 }
144 } else {
145 *buflen = cgc.buflen;
146 return 0;
147 }
148 }
150 static gdrom_error_t linux_packet_cmd( gdrom_disc_t disc, char *cmd )
151 {
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 );
159 cgc.buffer = 0;
160 cgc.buflen = 0;
161 cgc.sense = &sense;
162 cgc.data_direction = CGC_DATA_NONE;
164 if( ioctl(fd, CDROM_SEND_PACKET, &cgc) < 0 ) {
165 if( sense.sense_key == 0 ) {
166 return -1;
167 } else {
168 /* TODO: Map newer codes back to the ones used by the gd-rom. */
169 return sense.sense_key | (sense.asc<<8);
170 }
171 } else {
172 return 0;
173 }
174 }
.