qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [patch] transparent CDROM eject/change for Linux hosts


From: Manu
Subject: [Qemu-devel] [patch] transparent CDROM eject/change for Linux hosts
Date: Sat, 24 Sep 2005 04:52:05 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050404 Thunderbird/1.0.2 Mnenhy/0.7.1

Hi,

Please found attached a patch to allow easier transparent eject/change
of CDROM when the source of the emulated drive is a physical drive.
It still needs improvement ().

diff -ruN qemu-0.7.1/Makefile qemu-0.7.1-cdrom/Makefile
--- qemu-0.7.1/Makefile 2005-07-24 20:52:08.000000000 +0200
+++ qemu-0.7.1-cdrom/Makefile   2005-09-23 18:14:05.000000000 +0200
@@ -25,7 +25,7 @@
 endif
 endif
 
-qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c 
block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
+qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c 
block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c 
block-cdrom-dev.c
        $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
 
 dyngen$(EXESUF): dyngen.c
diff -ruN qemu-0.7.1/Makefile.target qemu-0.7.1-cdrom/Makefile.target
--- qemu-0.7.1/Makefile.target  2005-07-24 20:52:08.000000000 +0200
+++ qemu-0.7.1-cdrom/Makefile.target    2005-09-23 18:22:04.000000000 +0200
@@ -260,7 +260,7 @@
 
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
-VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o 
block-bochs.o block-vpc.o block-vvfat.o
+VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o 
block-bochs.o block-vpc.o block-vvfat.o block-cdrom-dev.o
 
 SOUND_HW = sb16.o
 AUDIODRV = audio.o noaudio.o wavaudio.o
diff -ruN qemu-0.7.1/block-cdrom-dev.c qemu-0.7.1-cdrom/block-cdrom-dev.c
--- qemu-0.7.1/block-cdrom-dev.c        1970-01-01 01:00:00.000000000 +0100
+++ qemu-0.7.1-cdrom/block-cdrom-dev.c  2005-09-23 18:28:59.000000000 +0200
@@ -0,0 +1,278 @@
+/*
+ * QEMU Block driver for real CDROM device
+ * 
+ * Copyright (c) 2005 Emmanuel Varagnat
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * Only works for Linux
+ */
+
+
+#if defined(LINUX) || defined(__LINUX__) || defined(__linux__)
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <linux/cdrom.h>
+
+#include "vl.h"
+#include "block_int.h"
+
+static int cdrom_dev_open(BlockDriverState *bs, const char *filename);
+static void cdrom_dev_close(BlockDriverState *bs);
+
+typedef struct BDRVCDROMDevState {
+  int fd;
+  int cap;
+} BDRVCDROMDevState;
+
+static int cdrom_dev_get_cap(const char *filename) {
+  /*  struct stat fst;*/
+  int fd, cap = 0;
+
+  fd = open(filename, O_RDONLY | O_NONBLOCK);
+  if(fd < 0) {
+    return -1;
+  }
+
+  /*
+  bzero(&fst, sizeof(fst));
+  if( fstat(fd, &fst) < 0 ) {
+    perror("stat");
+    close(fd);
+    return 0;
+  }
+
+  if( 0 && S_ISBLK(fst.st_mode) != S_IFBLK )     {
+    close(fd);
+    return 0;
+  }
+  */
+
+  errno = 0; /* errno can be non zero due to a previous call */
+  cap = ioctl(fd, CDROM_GET_CAPABILITY, 0);
+  if( cap == -1 || ( errno != ENOMEDIUM && errno != 0 ) ) {
+    return -1;
+  }
+
+  close(fd);
+
+  return cap;
+}
+
+static int cdrom_dev_is_inserted(BlockDriverState *bs) {
+  /*  BDRVCDROMDevState *s = bs->opaque;*/
+  int fd, status;
+
+  fd = open(bs->filename, O_RDONLY | O_NONBLOCK | O_NOCTTY);
+  if(fd == -1)
+    return 0;
+  
+  errno = 0;
+  status = ioctl(fd, CDROM_DRIVE_STATUS, 0);
+  close(fd);
+
+  if( status == CDS_DISC_OK ) {
+    if( ! bs->inserted )
+      bdrv_open(bs, bs->filename, 0);
+
+    return 1;
+  }
+  else {
+    if( bs->inserted )
+      bdrv_close(bs);
+
+    return 0;
+  }
+}
+
+static int cdrom_dev_is_locked(BlockDriverState *bs) {
+
+  return 0;
+}
+
+static void cdrom_dev_change_cb(void *opaque) {
+}
+
+static int cdrom_dev_probe(const uint8_t *buf, int buf_size, const char 
*filename)
+{
+  if( cdrom_dev_get_cap(filename) == -1)
+    return -1;
+  else
+    return 100;
+}
+
+static int cdrom_dev_open(BlockDriverState *bs, const char *filename)
+{
+    BDRVCDROMDevState *s = bs->opaque;
+    int fd;
+    int64_t size;
+#ifdef _BSD
+    struct stat sb;
+#endif
+    int cap;
+    int mask;
+
+    cap = cdrom_dev_get_cap(filename);
+    if( cap == -1)
+      return -1;
+
+    s->cap = cap;
+    /*
+    for( mask = 0x1; cap && mask <= (1 << (__WORDSIZE-1)); mask = mask<<1 ) {
+      switch(cap & mask) {
+      case CDC_CLOSE_TRAY:     
+       break;
+      case CDC_OPEN_TRAY:
+       break;
+      case CDC_LOCK:
+       break;
+      case CDC_SELECT_SPEED:
+       break;
+      case CDC_SELECT_DISC:
+       break;
+      case CDC_MULTI_SESSION:
+       break;
+      case CDC_MCN:
+       break;
+      case CDC_MEDIA_CHANGED:
+       break;
+      case CDC_PLAY_AUDIO:
+       break;
+      case CDC_RESET:
+       break;
+      case CDC_IOCTLS:
+       break;
+      case CDC_DRIVE_STATUS:
+       break;
+      case CDC_GENERIC_PACKET:
+       break;
+      case CDC_CD_R:
+       break;
+      case CDC_CD_RW:
+       break;
+      case CDC_DVD:
+       break;
+      case CDC_DVD_R:
+       break;
+      case CDC_DVD_RAM:
+       break;
+      case CDC_MO_DRIVE:
+       break;
+      case CDC_MRW:
+       break;
+      case CDC_MRW_W:
+       break;
+      case CDC_RAM:
+       break;
+      default:
+       break;
+      }
+    }
+    */
+    /* By default */
+    bs->read_only = 1;
+
+    bs->change_cb   = cdrom_dev_change_cb;
+    bs->is_inserted = cdrom_dev_is_inserted;
+    bs->is_locked   = cdrom_dev_is_locked;
+
+    fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+    if (fd < 0) {
+      s->fd = -1;
+      bs->inserted = 0;
+    }
+    else {
+      s->fd = fd;
+      bs->inserted = 1;
+
+#ifdef _BSD
+      if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
+#ifdef DIOCGMEDIASIZE
+       if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
+#endif
+         size = lseek(fd, 0LL, SEEK_END);
+      } else
+#endif
+       {
+         size = lseek(fd, 0, SEEK_END);
+       }
+#ifdef _WIN32
+      /* On Windows hosts it can happen that we're unable to get file size
+        for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
+      if (size == -1)
+        size = LONG_LONG_MAX;
+#endif
+      bs->total_sectors = size / 512;
+      s->fd = fd;
+    }
+
+    return 0;
+}
+
+static int cdrom_dev_read(BlockDriverState *bs, int64_t sector_num, 
+                         uint8_t *buf, int nb_sectors)
+{
+    BDRVCDROMDevState *s = bs->opaque;
+    int ret;
+
+    if(s->fd == -1)
+      return -1;
+
+    lseek(s->fd, sector_num * 512, SEEK_SET);
+    ret = read(s->fd, buf, nb_sectors * 512);
+    if (ret != nb_sectors * 512) 
+      return -1;
+    return 0;
+}
+
+static void cdrom_dev_close(BlockDriverState *bs)
+{
+    BDRVCDROMDevState *s = bs->opaque;
+
+    if(s->fd != -1)
+      close(s->fd);
+}
+
+static int cdrom_dev_create(const char *filename, int64_t total_size,
+                           const char *backing_file, int flags)
+{
+    return -ENOTSUP;
+}
+
+BlockDriver bdrv_cdrom_dev = {
+    "cdrom-dev",
+    sizeof(BDRVCDROMDevState),
+    cdrom_dev_probe,
+    cdrom_dev_open,
+    cdrom_dev_read,
+    NULL, /* write */
+
+    cdrom_dev_close,
+    cdrom_dev_create,
+};
+
+#endif
diff -ruN qemu-0.7.1/block.c qemu-0.7.1-cdrom/block.c
--- qemu-0.7.1/block.c  2005-07-24 20:52:08.000000000 +0200
+++ qemu-0.7.1-cdrom/block.c    2005-09-23 18:12:52.000000000 +0200
@@ -410,17 +410,28 @@
 
 int bdrv_is_inserted(BlockDriverState *bs)
 {
+    if(bs->is_inserted)
+      bs->inserted = bs->is_inserted(bs);
+
     return bs->inserted;
 }
 
 int bdrv_is_locked(BlockDriverState *bs)
 {
+    if(bs->is_locked)
+      bs->locked = bs->is_locked(bs);
+
     return bs->locked;
 }
 
 void bdrv_set_locked(BlockDriverState *bs, int locked)
 {
-    bs->locked = locked;
+  printf("set_locked\n");
+
+    if(bs->lock)
+      bs->locked = bs->lock(locked);
+    else
+      bs->locked = locked;
 }
 
 void bdrv_set_change_cb(BlockDriverState *bs, 
@@ -589,7 +600,7 @@
 {
     BDRVRawState *s = bs->opaque;
     int ret;
-    
+
     lseek(s->fd, sector_num * 512, SEEK_SET);
     ret = read(s->fd, buf, nb_sectors * 512);
     if (ret != nb_sectors * 512) 
@@ -640,6 +651,7 @@
     raw_open,
     raw_read,
     raw_write,
+
     raw_close,
     raw_create,
 };
@@ -647,6 +659,9 @@
 void bdrv_init(void)
 {
     bdrv_register(&bdrv_raw);
+#if defined(LINUX) || defined(__LINUX__) || defined(__linux__)
+    bdrv_register(&bdrv_cdrom_dev);
+#endif
 #ifndef _WIN32
     bdrv_register(&bdrv_cow);
 #endif
diff -ruN qemu-0.7.1/block_int.h qemu-0.7.1-cdrom/block_int.h
--- qemu-0.7.1/block_int.h      2005-07-24 20:52:08.000000000 +0200
+++ qemu-0.7.1-cdrom/block_int.h        2005-09-23 16:30:34.000000000 +0200
@@ -51,6 +51,9 @@
     int encrypted; /* if true, the media is encrypted */
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
+    int (*lock)(int);
+    int (*is_inserted)(BlockDriverState *bs);
+    int (*is_locked)(BlockDriverState *bs);
     void *change_opaque;
 
     BlockDriver *drv;
diff -ruN qemu-0.7.1/vl.h qemu-0.7.1-cdrom/vl.h
--- qemu-0.7.1/vl.h     2005-07-24 20:52:08.000000000 +0200
+++ qemu-0.7.1-cdrom/vl.h       2005-09-23 18:14:55.000000000 +0200
@@ -395,6 +395,7 @@
 extern BlockDriver bdrv_bochs;
 extern BlockDriver bdrv_vpc;
 extern BlockDriver bdrv_vvfat;
+extern BlockDriver bdrv_cdrom_dev;
 
 void bdrv_init(void);
 BlockDriver *bdrv_find_format(const char *format_name);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]