/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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) return ""; return texts[profile_number]; }