PATCH for changing of DVD speed via ioctl() call

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

 



Hello, folks!

This patch implements changing of DVD speed via ioctl() call, like
CDROM_SELECT_SPEED do. In CDROM_SELECT_SPEED its implementation isn't
so good (diffirent values of 1x in KB/s, troubles with return value of
cdrom_select_speed() and other). I defined CDROM_SELECT_DVDSPEED ioctl
() call with value 0x5324. But some dvdroms (like Plexter) do not
support this feature.. :(

I've successfully tested this patch on:s
NEC ND-3500AG (fw 2.19)
BENQ DVD-ROM 16X 1650T (fw: A.DD)
HL-DT-ST DVD-RW GCA-4080N (fw: 0A31)

I've mailed this message to Jens Axboe but have not answer :(
Please try it and say what you think about this..

patch for kernel 2.6.12

Signed-off-by: Ilja Samartsev <[email protected]>

PS: I'm not subscribed to LKML please CC me if you can.

=================== PATCH ====================
--- linux/include/linux/cdrom.h	2005-08-13 12:54:06.000000000 +0600
+++ my_linux/include/linux/cdrom.h	2005-08-14 15:06:06.000000000 +0600
@@ -120,6 +120,7 @@
 #define CDROM_CLEAR_OPTIONS	0x5321  /* Clear behavior options */
 #define CDROM_SELECT_SPEED	0x5322  /* Set the CD-ROM speed */
 #define CDROM_SELECT_DISC	0x5323  /* Select disc (for juke-boxes) */
+#define CDROM_SELECT_DVDSPEED	0x5324  /* Set the DVD-ROM speed */
 #define CDROM_MEDIA_CHANGED	0x5325  /* Check is media changed  */
 #define CDROM_DRIVE_STATUS	0x5326  /* Get tray position, etc. */
 #define CDROM_DISC_STATUS	0x5327  /* Get disc type, etc. */
@@ -965,6 +966,7 @@ struct cdrom_device_ops {
 	int (*tray_move) (struct cdrom_device_info *, int);
 	int (*lock_door) (struct cdrom_device_info *, int);
 	int (*select_speed) (struct cdrom_device_info *, int);
+	int (*select_dvd_speed) (struct cdrom_device_info *, int);
 	int (*select_disc) (struct cdrom_device_info *, int);
 	int (*get_last_session) (struct cdrom_device_info *,
 				 struct cdrom_multisession *);
--- linux/drivers/cdrom/cdrom.c	2005-08-13 12:54:06.000000000 +0600
+++ my_linux/drivers/cdrom/cdrom.c	2005-08-12 17:11:20.000000000 +0600
@@ -2327,6 +2327,11 @@ int cdrom_ioctl(struct file * file, stru
 		return cdo->select_speed(cdi, arg);
 		}
 
+	case CDROM_SELECT_DVDSPEED: {
+		cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DVDSPEED\n"); 
+		return cdo->select_dvd_speed(cdi, arg);
+		}
+
 	case CDROM_SELECT_DISC: {
 		cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); 
 		if (!CDROM_CAN(CDC_SELECT_DISC))
--- linux/drivers/ide/ide-cd.c	2005-08-13 12:54:06.000000000 +0600
+++ my_linux/drivers/ide/ide-cd.c	2005-08-16 01:00:09.000000000 +0600
@@ -2393,7 +2393,7 @@ static int cdrom_select_speed(ide_drive_
 	cdrom_prepare_request(drive, &req);
 
 	req.sense = sense;
-	if (speed == 0)
+	if (speed <= 0)
 		speed = 0xffff; /* set to max */
 	else
 		speed *= 177;   /* Nx to kbytes/s */
@@ -2415,6 +2415,63 @@ static int cdrom_select_speed(ide_drive_
 	return cdrom_queue_packet_command(drive, &req);
 }
 
+static int cdrom_select_dvd_speed(ide_drive_t *drive, int speed,
+		struct request_sense *sense)
+{
+	struct request req;
+	struct request_sense cap_sense;
+	unsigned char pd[28];
+	unsigned long cap, spf;
+
+	if (!CDROM_CONFIG_FLAGS(drive)->dvd)
+		return -ENOSYS; 
+ 
+	cdrom_prepare_request(drive, &req);
+
+	req.sense = sense;
+	req.data = pd;
+	req.data_len = sizeof(pd);
+
+	memset(pd, 0, sizeof(pd));
+
+	req.cmd[0] = GPCMD_SET_STREAMING;
+	req.cmd[10] = sizeof(pd); /* parameter list length */
+
+	if (speed <= 0) {
+		pd[0] = 4;	/* restore drive defaults */
+	} else {
+
+		speed *= 1385;	/* Nx to kbytes/s (FIXME: maybe not right value) */
+
+		if (!cdrom_read_capacity(drive, &cap, &spf, &cap_sense) && cap) {
+			/* good End LBA detected */
+			cap++;
+			pd[8] = (cap >> 24) & 0xff;
+			pd[9] = (cap >> 16) & 0xff;
+			pd[10] = (cap >> 8) & 0xff;
+			pd[11] = cap & 0xff; 
+		} else {
+			/* no good End LBA detected, using max */
+			pd[8] = 0xff;
+			pd[9] = 0xff;
+			pd[10] = 0xff;
+			pd[11] = 0xff; 
+		}
+			
+		/* read and write size */
+		pd[12] = pd[20] = (speed >> 24) & 0xff;
+		pd[13] = pd[21] = (speed >> 16) & 0xff;
+		pd[14] = pd[22] = (speed >> 8) & 0xff;
+		pd[15] = pd[23] = speed & 0xff;
+
+		/* read and write time */
+		pd[18] = pd[26] = 1000 >> 8;
+		pd[19] = pd[27] = 1000 & 0xff;
+	}
+
+	return cdrom_queue_packet_command(drive, &req);
+}
+
 static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
 {
 	struct request_sense sense;
@@ -2670,6 +2727,19 @@ int ide_cdrom_select_speed (struct cdrom
         return 0;
 }
 
+static
+int ide_cdrom_select_dvd_speed (struct cdrom_device_info *cdi, int speed)
+{
+	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	struct request_sense sense;
+	int stat;
+
+	if ((stat = cdrom_select_dvd_speed(drive, speed, &sense)) < 0)
+		return stat;
+
+	return 0;
+}
+
 /*
  * add logic to try GET_EVENT command first to check for media and tray
  * status. this should be supported by newer cd-r/w and all DVD etc
@@ -2816,6 +2886,7 @@ static struct cdrom_device_ops ide_cdrom
 	.tray_move		= ide_cdrom_tray_move,
 	.lock_door		= ide_cdrom_lock_door,
 	.select_speed		= ide_cdrom_select_speed,
+	.select_dvd_speed	= ide_cdrom_select_dvd_speed,
 	.get_last_session	= ide_cdrom_get_last_session,
 	.get_mcn		= ide_cdrom_get_mcn,
 	.reset			= ide_cdrom_reset,

====================== EOF ========================

=================== dvdspeed.c ====================
/*  
 *  dvdspeed - small program for selecting speed of DVD drive
 *    Copyright (C) 2005 Ilja Samartsev <[email protected]>
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>

int main (int argc, char **argv)
{
	int fd, speed;
	char *device;
	
	if (argc < 3) {
		printf("usage: %s device speed\n", argv[0]);
		return -1;		
	}

	device = argv[1];
	speed = atoi(argv[2]);

	if ((fd = open(device, O_RDONLY|O_NONBLOCK)) >= 0) {
		if (ioctl(fd, CDROM_SELECT_DVDSPEED, speed) < 0) {
			perror("ioctl()");
			exit(-1);
		}
	}

	return 0;
}
====================== EOF ========================

-- 
Samartsev Ilja
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux