filename | src/drivers/cd_linux.c |
changeset | 1025:f32183d273fb |
prev | 1023:264e2fd90be8 |
author | nkeynes |
date | Sat Jun 13 07:12:51 2009 +0000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Load plugins from the directory containing the executable first if they're there - simplifies development testing. Add dummy plugin for easy identification of the plugin directory |
file | annotate | diff | log | raw |
nkeynes@520 | 1 | /** |
nkeynes@561 | 2 | * $Id$ |
nkeynes@520 | 3 | * |
nkeynes@1023 | 4 | * Linux cd-rom device driver. Implemented using the SCSI transport. |
nkeynes@520 | 5 | * |
nkeynes@520 | 6 | * Copyright (c) 2005 Nathan Keynes. |
nkeynes@520 | 7 | * |
nkeynes@520 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@520 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@520 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@520 | 11 | * (at your option) any later version. |
nkeynes@520 | 12 | * |
nkeynes@520 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@520 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@520 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@520 | 16 | * GNU General Public License for more details. |
nkeynes@520 | 17 | */ |
nkeynes@520 | 18 | #include <unistd.h> |
nkeynes@520 | 19 | #include <stdlib.h> |
nkeynes@520 | 20 | #include <stdio.h> |
nkeynes@520 | 21 | #include <string.h> |
nkeynes@520 | 22 | #include <errno.h> |
nkeynes@806 | 23 | #include <ctype.h> |
nkeynes@520 | 24 | #include <linux/cdrom.h> |
nkeynes@520 | 25 | #include <sys/stat.h> |
nkeynes@520 | 26 | #include <sys/ioctl.h> |
nkeynes@520 | 27 | #include <fstab.h> |
nkeynes@520 | 28 | #include <fcntl.h> |
nkeynes@520 | 29 | |
nkeynes@678 | 30 | #include "gdrom/gddriver.h" |
nkeynes@520 | 31 | #include "gdrom/packet.h" |
nkeynes@520 | 32 | #include "dream.h" |
nkeynes@520 | 33 | |
nkeynes@1023 | 34 | static gboolean linux_is_cdrom_device( FILE *f ); |
nkeynes@1023 | 35 | static gdrom_disc_t linux_open_device( const gchar *filename, FILE *f ); |
nkeynes@1025 | 36 | static gdrom_error_t linux_packet_read( gdrom_disc_t disc, char *cmd, |
nkeynes@1023 | 37 | unsigned char *buf, uint32_t *buflen ); |
nkeynes@1025 | 38 | static gdrom_error_t linux_packet_cmd( gdrom_disc_t disc, char *cmd ); |
nkeynes@1023 | 39 | static gboolean linux_media_changed( gdrom_disc_t disc ); |
nkeynes@520 | 40 | |
nkeynes@520 | 41 | |
nkeynes@520 | 42 | struct gdrom_image_class cdrom_device_class = { "Linux", NULL, |
nkeynes@1023 | 43 | linux_is_cdrom_device, linux_open_device }; |
nkeynes@1023 | 44 | |
nkeynes@1023 | 45 | static struct gdrom_scsi_transport linux_scsi_transport = { |
nkeynes@1023 | 46 | linux_packet_read, linux_packet_cmd, linux_media_changed }; |
nkeynes@1023 | 47 | |
nkeynes@1023 | 48 | static gboolean linux_is_cdrom_device( FILE *f ) |
nkeynes@1023 | 49 | { |
nkeynes@1023 | 50 | int caps = ioctl(fileno(f), CDROM_GET_CAPABILITY); |
nkeynes@1023 | 51 | if( caps == -1 ) { |
nkeynes@1023 | 52 | /* Quick check that this is really a CD device */ |
nkeynes@1023 | 53 | return FALSE; |
nkeynes@1023 | 54 | } else { |
nkeynes@1023 | 55 | return TRUE; |
nkeynes@1023 | 56 | } |
nkeynes@1023 | 57 | } |
nkeynes@1023 | 58 | |
nkeynes@709 | 59 | GList *cdrom_get_native_devices(void) |
nkeynes@520 | 60 | { |
nkeynes@520 | 61 | GList *list = NULL; |
nkeynes@520 | 62 | struct fstab *ent; |
nkeynes@520 | 63 | struct stat st; |
nkeynes@520 | 64 | setfsent(); |
nkeynes@520 | 65 | while( (ent = getfsent()) != NULL ) { |
nkeynes@736 | 66 | if( (stat(ent->fs_spec, &st) != -1) && |
nkeynes@736 | 67 | S_ISBLK(st.st_mode) ) { |
nkeynes@736 | 68 | /* Got a valid block device - is it a CDROM? */ |
nkeynes@736 | 69 | int fd = open(ent->fs_spec, O_RDONLY|O_NONBLOCK); |
nkeynes@736 | 70 | if( fd == -1 ) |
nkeynes@736 | 71 | continue; |
nkeynes@736 | 72 | int caps = ioctl(fd, CDROM_GET_CAPABILITY); |
nkeynes@736 | 73 | if( caps != -1 ) { |
nkeynes@736 | 74 | /* Appears to support CDROM functions */ |
nkeynes@1023 | 75 | FILE *f = fdopen(fd,"r"); |
nkeynes@1023 | 76 | gdrom_disc_t disc = gdrom_scsi_disc_new(ent->fs_spec, f, &linux_scsi_transport); |
nkeynes@1023 | 77 | if( disc != NULL ) { |
nkeynes@1023 | 78 | list = g_list_append( list, gdrom_device_new(disc->name, disc->display_name) ); |
nkeynes@1023 | 79 | disc->destroy(disc,TRUE); |
nkeynes@1023 | 80 | } else { |
nkeynes@1023 | 81 | close(fd); |
nkeynes@1023 | 82 | } |
nkeynes@1023 | 83 | } else { |
nkeynes@1023 | 84 | close(fd); |
nkeynes@736 | 85 | } |
nkeynes@736 | 86 | } |
nkeynes@520 | 87 | } |
nkeynes@520 | 88 | return list; |
nkeynes@520 | 89 | } |
nkeynes@520 | 90 | |
nkeynes@709 | 91 | gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path ) |
nkeynes@709 | 92 | { |
nkeynes@709 | 93 | return NULL; |
nkeynes@709 | 94 | } |
nkeynes@709 | 95 | |
nkeynes@1023 | 96 | static gdrom_disc_t linux_open_device( const gchar *filename, FILE *f ) |
nkeynes@520 | 97 | { |
nkeynes@1023 | 98 | if( !linux_is_cdrom_device(f) ) { |
nkeynes@1023 | 99 | return NULL; |
nkeynes@1023 | 100 | } |
nkeynes@520 | 101 | |
nkeynes@1023 | 102 | return gdrom_scsi_disc_new(filename, f, &linux_scsi_transport); |
nkeynes@520 | 103 | } |
nkeynes@520 | 104 | |
nkeynes@1023 | 105 | static gboolean linux_media_changed( gdrom_disc_t disc ) |
nkeynes@520 | 106 | { |
nkeynes@1023 | 107 | int fd = fileno(disc->file); |
nkeynes@520 | 108 | int status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); |
nkeynes@520 | 109 | if( status == CDS_DISC_OK ) { |
nkeynes@736 | 110 | status = ioctl(fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT); |
nkeynes@1023 | 111 | return status == 0 ? FALSE : TRUE; |
nkeynes@520 | 112 | } else { |
nkeynes@1023 | 113 | return disc->disc_type == IDE_DISC_NONE ? FALSE : TRUE; |
nkeynes@520 | 114 | } |
nkeynes@520 | 115 | } |
nkeynes@520 | 116 | |
nkeynes@520 | 117 | /** |
nkeynes@520 | 118 | * Send a packet command to the device and wait for a response. |
nkeynes@520 | 119 | * @return 0 on success, -1 on an operating system error, or a sense error |
nkeynes@520 | 120 | * code on a device error. |
nkeynes@520 | 121 | */ |
nkeynes@1025 | 122 | static gdrom_error_t linux_packet_read( gdrom_disc_t disc, char *cmd, |
nkeynes@1023 | 123 | unsigned char *buffer, uint32_t *buflen ) |
nkeynes@520 | 124 | { |
nkeynes@1023 | 125 | int fd = fileno(disc->file); |
nkeynes@520 | 126 | struct request_sense sense; |
nkeynes@520 | 127 | struct cdrom_generic_command cgc; |
nkeynes@520 | 128 | |
nkeynes@520 | 129 | memset( &cgc, 0, sizeof(cgc) ); |
nkeynes@520 | 130 | memset( &sense, 0, sizeof(sense) ); |
nkeynes@520 | 131 | memcpy( cgc.cmd, cmd, 12 ); |
nkeynes@520 | 132 | cgc.buffer = buffer; |
nkeynes@520 | 133 | cgc.buflen = *buflen; |
nkeynes@520 | 134 | cgc.sense = &sense; |
nkeynes@1023 | 135 | cgc.data_direction = CGC_DATA_READ; |
nkeynes@736 | 136 | |
nkeynes@644 | 137 | if( ioctl(fd, CDROM_SEND_PACKET, &cgc) < 0 ) { |
nkeynes@736 | 138 | if( sense.sense_key == 0 ) { |
nkeynes@736 | 139 | return -1; |
nkeynes@736 | 140 | } else { |
nkeynes@736 | 141 | /* TODO: Map newer codes back to the ones used by the gd-rom. */ |
nkeynes@736 | 142 | return sense.sense_key | (sense.asc<<8); |
nkeynes@736 | 143 | } |
nkeynes@520 | 144 | } else { |
nkeynes@736 | 145 | *buflen = cgc.buflen; |
nkeynes@736 | 146 | return 0; |
nkeynes@520 | 147 | } |
nkeynes@520 | 148 | } |
nkeynes@1023 | 149 | |
nkeynes@1025 | 150 | static gdrom_error_t linux_packet_cmd( gdrom_disc_t disc, char *cmd ) |
nkeynes@1023 | 151 | { |
nkeynes@1023 | 152 | int fd = fileno(disc->file); |
nkeynes@1023 | 153 | struct request_sense sense; |
nkeynes@1023 | 154 | struct cdrom_generic_command cgc; |
nkeynes@1023 | 155 | |
nkeynes@1023 | 156 | memset( &cgc, 0, sizeof(cgc) ); |
nkeynes@1023 | 157 | memset( &sense, 0, sizeof(sense) ); |
nkeynes@1023 | 158 | memcpy( cgc.cmd, cmd, 12 ); |
nkeynes@1023 | 159 | cgc.buffer = 0; |
nkeynes@1023 | 160 | cgc.buflen = 0; |
nkeynes@1023 | 161 | cgc.sense = &sense; |
nkeynes@1023 | 162 | cgc.data_direction = CGC_DATA_NONE; |
nkeynes@1023 | 163 | |
nkeynes@1023 | 164 | if( ioctl(fd, CDROM_SEND_PACKET, &cgc) < 0 ) { |
nkeynes@1023 | 165 | if( sense.sense_key == 0 ) { |
nkeynes@1023 | 166 | return -1; |
nkeynes@1023 | 167 | } else { |
nkeynes@1023 | 168 | /* TODO: Map newer codes back to the ones used by the gd-rom. */ |
nkeynes@1023 | 169 | return sense.sense_key | (sense.asc<<8); |
nkeynes@1023 | 170 | } |
nkeynes@1023 | 171 | } else { |
nkeynes@1023 | 172 | return 0; |
nkeynes@1023 | 173 | } |
nkeynes@1023 | 174 | } |
.