Search
lxdream.org :: lxdream/src/drivers/cd_linux.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/cd_linux.c
changeset 1025:f32183d273fb
prev1023: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 }
.