summaryrefslogtreecommitdiff
path: root/wodim/scsi_mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'wodim/scsi_mmc.c')
-rw-r--r--wodim/scsi_mmc.c411
1 files changed, 411 insertions, 0 deletions
diff --git a/wodim/scsi_mmc.c b/wodim/scsi_mmc.c
new file mode 100644
index 0000000..f8baa1f
--- /dev/null
+++ b/wodim/scsi_mmc.c
@@ -0,0 +1,411 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_mmc.c 1.13 05/05/16 Copyright 2002-2005 J. Schilling */
+/*
+ * SCSI command functions for cdrecord
+ * covering MMC-3 level and above
+ *
+ * Copyright (c) 2002-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+Includes code from http://libburnia.pykix.org/browser/libburn/trunk/libburn/mmc.c?format=txt
+*/
+
+/*#define DEBUG*/
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsimmc.h"
+#include "wodim.h"
+
+extern int xdebug;
+
+
+
+int get_configuration(SCSI *usalp, caddr_t bp, int cnt, int st_feature,
+ int rt);
+static int get_conflen(SCSI *usalp, int st_feature, int rt);
+int get_curprofile(SCSI *usalp);
+static int get_profiles(SCSI *usalp, caddr_t bp, int cnt);
+int print_profiles(SCSI *usalp);
+int get_proflist(SCSI *usalp, BOOL *wp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp,
+ BOOL *ddcdp);
+int get_wproflist(SCSI *usalp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp,
+ BOOL *ddcdp);
+
+/*
+ * Get feature codes
+ */
+int
+get_configuration(SCSI *usalp, caddr_t bp, int cnt, int st_feature, int rt)
+{
+ register struct usal_cmd *scmd = usalp->scmd;
+
+ fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+ scmd->addr = bp;
+ scmd->size = cnt;
+ scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+ scmd->cdb_len = SC_G1_CDBLEN;
+ scmd->sense_len = CCS_SENSE_LEN;
+ scmd->cdb.g1_cdb.cmd = 0x46;
+ scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+ if (rt & 1)
+ scmd->cdb.g1_cdb.reladr = 1;
+ if (rt & 2)
+ scmd->cdb.g1_cdb.res = 1;
+
+ i_to_2_byte(scmd->cdb.g1_cdb.addr, st_feature);
+ g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+ usalp->cmdname = "get_configuration";
+
+ return (usal_cmd(usalp));
+}
+
+/*
+ * Retrieve feature code list length
+ */
+static int
+get_conflen(SCSI *usalp, int st_feature, int rt)
+{
+ Uchar cbuf[8];
+ int flen;
+ int i;
+
+ fillbytes(cbuf, sizeof (cbuf), '\0');
+ usalp->silent++;
+ i = get_configuration(usalp, (char *)cbuf, sizeof (cbuf), st_feature, rt);
+ usalp->silent--;
+ if (i < 0)
+ return (-1);
+ i = sizeof (cbuf) - usal_getresid(usalp);
+ if (i < 4)
+ return (-1);
+
+ flen = a_to_u_4_byte(cbuf);
+ if (flen < 4)
+ return (-1);
+ return (flen);
+}
+
+int
+get_curprofile(SCSI *usalp)
+{
+ Uchar cbuf[8];
+ int amt;
+ int flen;
+ int profile;
+ int i;
+
+ fillbytes(cbuf, sizeof (cbuf), '\0');
+ usalp->silent++;
+ i = get_configuration(usalp, (char *)cbuf, sizeof (cbuf), 0, 0);
+ usalp->silent--;
+ if (i < 0)
+ return (-1);
+
+ amt = sizeof (cbuf) - usal_getresid(usalp);
+ if (amt < 8)
+ return (-1);
+ flen = a_to_u_4_byte(cbuf);
+ if (flen < 4)
+ return (-1);
+
+ profile = a_to_u_2_byte(&cbuf[6]);
+
+ if (xdebug > 1)
+ usal_prbytes("Features: ", cbuf, amt);
+
+ if (xdebug > 0)
+ printf("feature len: %d current profile 0x%04X (%s) len %d\n",
+ flen, profile,
+ mmc_obtain_profile_name(profile), amt);
+
+ return (profile);
+}
+
+static int
+get_profiles(SCSI *usalp, caddr_t bp, int cnt)
+{
+ int amt;
+ int flen;
+ int i;
+
+ flen = get_conflen(usalp, 0, 0);
+ if (flen < 0)
+ return (-1);
+ if (cnt < flen)
+ flen = cnt;
+
+ fillbytes(bp, cnt, '\0');
+ usalp->silent++;
+ i = get_configuration(usalp, (char *)bp, flen, 0, 0);
+ usalp->silent--;
+ if (i < 0)
+ return (-1);
+ amt = flen - usal_getresid(usalp);
+
+ flen = a_to_u_4_byte(bp);
+ if ((flen+4) < amt)
+ amt = flen+4;
+
+ return (amt);
+}
+
+int
+print_profiles(SCSI *usalp)
+{
+ Uchar cbuf[1024];
+ Uchar *p;
+ int flen;
+ int curprofile;
+ int profile;
+ int i;
+ int n;
+
+ flen = get_profiles(usalp, (caddr_t)cbuf, sizeof (cbuf));
+ if (flen < 0)
+ return (-1);
+
+ p = cbuf;
+ if (xdebug > 1)
+ usal_prbytes("Features: ", cbuf, flen);
+
+ curprofile = a_to_u_2_byte(&p[6]);
+ if (xdebug > 0)
+ printf("feature len: %d current profile 0x%04X (%s)\n",
+ flen, curprofile,
+ mmc_obtain_profile_name(curprofile));
+
+ printf("Current: 0x%04X (%s)\n", curprofile,
+ mmc_obtain_profile_name(curprofile));
+
+ p += 8; /* Skip feature header */
+ n = p[3]; /* Additional length */
+ n /= 4;
+ p += 4;
+
+ for (i = 0; i < n; i++) {
+ profile = a_to_u_2_byte(p);
+ if (xdebug > 0)
+ printf("Profile: 0x%04X (%s)", profile,
+ mmc_obtain_profile_name(profile));
+ else
+ printf("Profile: ");
+ printf("0x%04X (%s) %s\n", profile,
+ mmc_obtain_profile_name(profile),
+ p[2] & 1 ? "(current)":"");
+ p += 4;
+ }
+ return (curprofile);
+}
+
+int
+get_proflist(SCSI *usalp, BOOL *wp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp,
+ BOOL *ddcdp)
+{
+ Uchar cbuf[1024];
+ Uchar *p;
+ int flen;
+ int curprofile;
+ int profile;
+ int i;
+ int n;
+ BOOL wr = FALSE;
+ BOOL cd = FALSE;
+ BOOL dvd = FALSE;
+ BOOL dvdplus = FALSE;
+ BOOL ddcd = FALSE;
+
+ flen = get_profiles(usalp, (caddr_t)cbuf, sizeof (cbuf));
+ if (flen < 0)
+ return (-1);
+
+ p = cbuf;
+ if (xdebug > 1)
+ usal_prbytes("Features: ", cbuf, flen);
+
+ curprofile = a_to_u_2_byte(&p[6]);
+ if (xdebug > 0)
+ printf("feature len: %d current profile 0x%04X (%s)\n",
+ flen, curprofile,
+ mmc_obtain_profile_name(curprofile));
+
+ p += 8; /* Skip feature header */
+ n = p[3]; /* Additional length */
+ n /= 4;
+ p += 4;
+
+ for (i = 0; i < n; i++) {
+ profile = a_to_u_2_byte(p);
+ p += 4;
+ if (profile >= 0x0008 && profile < 0x0010)
+ cd = TRUE;
+ if (profile > 0x0008 && profile < 0x0010)
+ wr = TRUE;
+
+ if (profile >= 0x0010 && profile < 0x0018)
+ dvd = TRUE;
+ if (profile > 0x0010 && profile < 0x0018)
+ wr = TRUE;
+
+ if (profile >= 0x0018 && profile < 0x0020)
+ dvdplus = TRUE;
+ if (profile > 0x0018 && profile < 0x0020)
+ wr = TRUE;
+
+ if (profile >= 0x0020 && profile < 0x0028)
+ ddcd = TRUE;
+ if (profile > 0x0020 && profile < 0x0028)
+ wr = TRUE;
+ }
+ if (wp)
+ *wp = wr;
+ if (cdp)
+ *cdp = cd;
+ if (dvdp)
+ *dvdp = dvd;
+ if (dvdplusp)
+ *dvdplusp = dvdplus;
+ if (ddcdp)
+ *ddcdp = ddcd;
+
+ return (curprofile);
+}
+
+int
+get_wproflist(SCSI *usalp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp, BOOL *ddcdp)
+{
+ Uchar cbuf[1024];
+ Uchar *p;
+ int flen;
+ int curprofile;
+ int profile;
+ int i;
+ int n;
+ BOOL cd = FALSE;
+ BOOL dvd = FALSE;
+ BOOL dvdplus = FALSE;
+ BOOL ddcd = FALSE;
+
+ flen = get_profiles(usalp, (caddr_t)cbuf, sizeof (cbuf));
+ if (flen < 0)
+ return (-1);
+ p = cbuf;
+ curprofile = a_to_u_2_byte(&p[6]);
+
+ p += 8; /* Skip feature header */
+ n = p[3]; /* Additional length */
+ n /= 4;
+ p += 4;
+
+ for (i = 0; i < n; i++) {
+ profile = a_to_u_2_byte(p);
+ p += 4;
+ if (profile > 0x0008 && profile < 0x0010)
+ cd = TRUE;
+ if (profile > 0x0010 && profile < 0x0018)
+ dvd = TRUE;
+ if (profile > 0x0018 && profile < 0x0020)
+ dvdplus = TRUE;
+ if (profile > 0x0020 && profile < 0x0028)
+ ddcd = TRUE;
+ }
+ if (cdp)
+ *cdp = cd;
+ if (dvdp)
+ *dvdp = dvd;
+ if (dvdplusp)
+ *dvdplusp = dvdplus;
+ if (ddcdp)
+ *ddcdp = ddcd;
+
+ return (curprofile);
+}
+
+
+char *mmc_obtain_profile_name(int profile_number) {
+ static char *texts[0x53] = {NULL};
+ static char *reserved="Reserved/Unknown";
+ int i, max_pno = 0x53;
+
+ if (texts[0] == NULL) {
+ for (i = 0; i<max_pno; i++)
+ texts[i] = reserved;
+ /* mmc5r04c.pdf , Table 88, human readable profile names */
+ texts[0x01] = "Non-removable disk";
+ texts[0x02] = "Removable disk";
+ texts[0x03] = "MO erasable";
+ texts[0x04] = "Optical write once";
+ texts[0x05] = "AS-MO";
+ texts[0x08] = "CD-ROM";
+ texts[0x09] = "CD-R";
+ texts[0x0a] = "CD-RW";
+ texts[0x10] = "DVD-ROM";
+ texts[0x11] = "DVD-R sequential recording";
+ texts[0x12] = "DVD-RAM";
+ texts[0x13] = "DVD-RW restricted overwrite";
+ texts[0x14] = "DVD-RW sequential recording";
+ texts[0x15] = "DVD-R/DL sequential recording";
+ texts[0x16] = "DVD-R/DL layer jump recording";
+ texts[0x1a] = "DVD+RW";
+ texts[0x1b] = "DVD+R";
+ texts[0x2a] = "DVD+RW/DL";
+ texts[0x2b] = "DVD+R/DL";
+ texts[0x40] = "BD-ROM";
+ texts[0x41] = "BD-R sequential recording";
+ texts[0x42] = "BD-R random recording";
+ texts[0x43] = "BD-RE";
+ texts[0x50] = "HD-DVD-ROM";
+ texts[0x51] = "HD-DVD-R";
+ texts[0x52] = "HD-DVD-RAM";
+ }
+ if (profile_number<0 || profile_number>=max_pno)
+ return "";
+ return texts[profile_number];
+}
+