public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* PATCH for changing of DVD speed via ioctl() call
@ 2005-08-21 15:55 cHitman
  2005-08-22  9:09 ` Bartlomiej Zolnierkiewicz
  0 siblings, 1 reply; 5+ messages in thread
From: cHitman @ 2005-08-21 15:55 UTC (permalink / raw)
  To: linux-kernel

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 <samartsev@gmail.com>

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 <samartsev@gmail.com>
 * 
 *  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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for changing of DVD speed via ioctl() call
       [not found] <4E0p1-3vc-23@gated-at.bofh.it>
@ 2005-08-21 19:56 ` Bodo Eggert
  2005-08-22  2:37   ` Chris Wedgwood
  0 siblings, 1 reply; 5+ messages in thread
From: Bodo Eggert @ 2005-08-21 19:56 UTC (permalink / raw)
  To: cHitman, linux-kernel

cHitman <samartsev@gmail.com> wrote:

> 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.. :(

Introducing another device-specific IOCTL because the other device-specific
request turned out to be wrong is likely to be wrong, too.

>  req.sense = sense;
> -     if (speed == 0)
> +     if (speed <= 0)
>  speed = 0xffff; /* set to max */
>  else
>  speed *= 177;   /* Nx to kbytes/s */

The parameter value should IMHO be a pointer to a struct {
 unsigned long long maxspeed; // (with 0 being the magic max. value?)
 int facility; /* 0=general speed, 2=general read, 4=read data,
                  6=read audio, 8=read raw ... whatever is supported
                  n+1 = s/read/write/ */
}

That will work for any device and speed you can expect in the near future.

> +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;

EINVAL?

-- 
Ich danke GMX dafür, die Verwendung meiner Adressen mittels per SPF
verbreiteten Lügen zu sabotieren.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for changing of DVD speed via ioctl() call
  2005-08-21 19:56 ` Bodo Eggert
@ 2005-08-22  2:37   ` Chris Wedgwood
  2005-08-22 13:42     ` Bodo Eggert
  0 siblings, 1 reply; 5+ messages in thread
From: Chris Wedgwood @ 2005-08-22  2:37 UTC (permalink / raw)
  To: 7eggert; +Cc: cHitman, linux-kernel

On Sun, Aug 21, 2005 at 09:56:45PM +0200, Bodo Eggert wrote:

> The parameter value should IMHO be a pointer to a struct {
>  unsigned long long maxspeed; // (with 0 being the magic max. value?)
>  int facility; /* 0=general speed, 2=general read, 4=read data,
>                   6=read audio, 8=read raw ... whatever is supported
>                   n+1 = s/read/write/ */
> }

Passing pointers inside ioctl's is horrible IMO and if we can avoid it
we should.  It's just asking for problems.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for changing of DVD speed via ioctl() call
  2005-08-21 15:55 PATCH for changing of DVD speed via ioctl() call cHitman
@ 2005-08-22  9:09 ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 5+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2005-08-22  9:09 UTC (permalink / raw)
  To: cHitman; +Cc: linux-kernel

On 8/21/05, cHitman <samartsev@gmail.com> wrote:
> Hello, folks!

Hi,

Please use user-space solution instead:
http://www.ussg.iu.edu/hypermail/linux/kernel/0411.3/0812.html

Thanks,
Bartlomiej

> 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 <samartsev@gmail.com>
> 
> 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 <samartsev@gmail.com>
>  *
>  *  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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for changing of DVD speed via ioctl() call
  2005-08-22  2:37   ` Chris Wedgwood
@ 2005-08-22 13:42     ` Bodo Eggert
  0 siblings, 0 replies; 5+ messages in thread
From: Bodo Eggert @ 2005-08-22 13:42 UTC (permalink / raw)
  To: Chris Wedgwood; +Cc: 7eggert, cHitman, linux-kernel

On Sun, 21 Aug 2005, Chris Wedgwood wrote:
> On Sun, Aug 21, 2005 at 09:56:45PM +0200, Bodo Eggert wrote:

> > The parameter value should IMHO be a pointer to a struct {
> >  unsigned long long maxspeed; // (with 0 being the magic max. value?)
> >  int facility; /* 0=general speed, 2=general read, 4=read data,
> >                   6=read audio, 8=read raw ... whatever is supported
> >                   n+1 = s/read/write/ */
> > }
> 
> Passing pointers inside ioctl's is horrible IMO and if we can avoid it
> we should.  It's just asking for problems.

It's used in all ioctls not requiring a read-only int or a void. See man 
ioctl_list (2).
-- 
Top 100 things you don't want the sysadmin to say:
26. What happens to a Hard Disk when you drop it?

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2005-08-22 23:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-21 15:55 PATCH for changing of DVD speed via ioctl() call cHitman
2005-08-22  9:09 ` Bartlomiej Zolnierkiewicz
     [not found] <4E0p1-3vc-23@gated-at.bofh.it>
2005-08-21 19:56 ` Bodo Eggert
2005-08-22  2:37   ` Chris Wedgwood
2005-08-22 13:42     ` Bodo Eggert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox