/*
* This file is part of the QPxTool project.
* Copyright (C) 2005-2006 Gennady "ShultZ" Kozlov <qpxtool@mail.ru>
*
* original version of CD-R(W) manufacturer identification code got from cdrecord, (C) Joerg Schilling
*
* 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.
* See the file "COPYING" for the exact licensing terms.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
//#include <sys/time.h>
//#include "transport.hxx"
#include "qpx_mmc.h"
const unsigned int bufsz_dev = 0x0000FF;
const unsigned int bufsz_rd = 0x010000;
const unsigned int bufsz_ATIP = 0x000800;
drive_info::drive_info(){
}
drive_info::drive_info(char* _device){
device=(char*)malloc(bufsz_dev);
strcpy(device,_device);
rd_buf=(unsigned char*)malloc(bufsz_rd);
ATIP=(unsigned char*)malloc(bufsz_ATIP);
if (!cmd.associate(device, NULL)) {
// printf("** Can't open device: %16s\n",_device);
err=1;
mmc=-1;
return;
}
mmc=0;
parms.interval=1;
parms.tests=0;
capabilities=0;
rd_capabilities=0;
wr_capabilities=0;
ven_features=0;
chk_features=0;
plextor.gigarec=0;
plextor.varirec_state_cd=0;
plextor.varirec_pwr_cd=0;
plextor.varirec_str_cd=0;
plextor.varirec_state_dvd=0;
plextor.varirec_pwr_dvd=0;
plextor.varirec_str_dvd=0;
plextor.powerec_state=0;
plextor.plexeraser=0;
ven_ID=0;
dev_ID=0;
iface_id=0;
iface[0]=0;
loader_id=0;
parms.scan_speed_cd=8;
parms.scan_speed_dvd=5;
parms.spindown_idx=0;
silent=0;
}
drive_info::~drive_info(){
// delete urd_buf;
busy=1;
// delete pthread_t;
delete rd_buf;
delete ATIP;
delete device;
}
void drivecpy(drive_info* dst, drive_info* src){
dst->device=(char*)malloc(bufsz_dev);
// printf("Can't copy device:(\n");
memcpy(dst->device, src->device,bufsz_dev);
// printf("Can't copy device:(\n");
// if (!dst->cmd.associate(dst->device, NULL)) {
// dst->mmc=-1;
// printf("Can't copy device:(\n");
// return;
// }
dst->mmc=src->mmc;
// dst->memcpy(dst, src, 0xFF);
dst->rd_buf=(unsigned char*)malloc(bufsz_rd);
dst->ATIP=(unsigned char*)malloc(bufsz_ATIP);
dst->ATIP_len = src->ATIP_len;
dst->ven_ID=src->ven_ID;
memcpy(dst->ven,src->ven,9);
dst->dev_ID=src->dev_ID;
memcpy(dst->dev,src->dev,17);
memcpy(dst->fw,src->fw,5);
memcpy(dst->serial,src->serial,17);
memcpy(dst->TLA,src->TLA,5);
dst->buffer_size = src->buffer_size;
dst->capabilities = src->capabilities;
dst->rd_capabilities = src->rd_capabilities;
dst->wr_capabilities = src->wr_capabilities;
dst->ven_features = src->ven_features;
dst->chk_features = src->chk_features;
dst->iface_id = src->iface_id;
memcpy(dst->iface,src->iface,sizeof(str_if));
dst->loader_id = src->loader_id;
dst->book_plus_r = src->book_plus_r;
dst->book_plus_rw = src->book_plus_rw;
dst->book_plus_rdl = src->book_plus_rdl;
memcpy(&(dst->plextor),&(src->plextor),sizeof(plex_features));
memcpy(&(dst->astrategy),&(src->astrategy),sizeof(plex_as));
memcpy(&(dst->plextor_silent),&(src->plextor_silent),sizeof(plex_silent));
memcpy(&(dst->media),&(src->media),sizeof(media_info));
memcpy(&(dst->parms),&(src->parms),sizeof(drive_parms));
memcpy(&(dst->perf),&(src->perf),sizeof(perf_desc));
// memcpy(dst->,src->,sizeof());
dst->parms.tests = src->parms.tests;
dst->parms.interval = src->parms.interval;
dst->parms.scan_speed_cd = src->parms.scan_speed_cd;
dst->parms.scan_speed_dvd = src->parms.scan_speed_dvd;
// dst->media.type = src->media.type;
// memcpy(dst->media.MID,src->media.MID,32);
// dst->media.disc_type = src->media.disc_type;
// dst->media.book_type = src->media.book_type;
// dst->media.layers = src->media.layers;
dst->media.capacity = src->media.capacity;
dst->silent = src->silent;
}
void drive_info::cmd_clear(){
for (int i=0; i<12; i++) cmd[i]=0;
}
/*
bool drive_info::lock(){
if (!busy) {busy=true; return true; }
else { return false; }
}
bool drive_info::unlock(){
busy=false;
return true;
}
bool drive_info::isBusy(){
return busy;
}
void drive_info::wait_free(){
while (busy);
}
*/
void spinup(drive_info* drive, unsigned char secs) {
long st, et;
char use_readcd = 0;
const int addt = 250;
int i = 0;
st = getmsecs() + addt;
if ((drive->media.disc_type & DISC_CD) && (drive->capabilities & CAP_DAE)) use_readcd = 1;
printf("SpinUp using READ%s command...\n", use_readcd ? " CD" : "" );
seek(drive, 0);
// if (use_readcd) read_cd(drive, 0, 1, 0xF8, 1);
for ( et = getmsecs(); (et-st) < (secs*1000); et = getmsecs() ) {
printf("Remaining: %.3f sec...\r", secs - ((et-st) / 1000.0));
if (use_readcd) read_cd(drive, i*15, 15, 0xF8);
else read(drive, i*15, 15);
i++;
}
seek(drive, 0);
if (use_readcd) read_cd(drive, 0, 1, 0xF8);
else read(drive, 0, 1);
seek(drive, 0);
usleep( addt );
}
int inquiry(drive_info* drive) {
char data[36];
if (drive->mmc == -1) return ERR_NO_DEV;
drive->cmd_clear();
drive->cmd[0] = MMC_INQUIRY;
drive->cmd[4] = 36;
drive->cmd[5] = 0;
drive->err=drive->cmd.transport(READ,data,36);
if (drive->err) return ERR_NO_SCSI;
memcpy(drive->ven,data+8,8);
drive->ven[8] = 0;
memcpy(drive->dev,data+16,16);
drive->dev[16] = 0;
memcpy(drive->fw,data+32,4);
drive->fw[4] = 0;
if ((data[0]&0x1F) != 5) return ERR_NO_MMC;
drive->mmc=1;
return 0;
}
int test_unit_ready(drive_info* drive) {
drive->cmd_clear();
drive->cmd[0] = MMC_TEST_UNIT_READY;
if ((drive->err=drive->cmd.transport(NONE, NULL, 0) )) return drive->err;
return 0;
}
int request_sense(drive_info* drive, char add){
drive->cmd_clear();
drive->cmd[0]= MMC_REQUEST_SENSE;
drive->cmd[4]= 0x12+add;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,0x12) ))
{sperror ("REQUEST_SENSE",drive->err); return (drive->err); }
return 0;
}
/*
int mode_sense6(drive_info* drive, int page, int page_control, short dest_len) {
drive->cmd_clear();
drive->cmd[0]=MMC_MODE_SENSE6;
drive->cmd[1]= 0x10;
drive->cmd[2]=page_control << 6 | page;
drive->cmd[4]=dest_len & 0xFF;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,dest_len) ))
{sperror ("MODE_SENSE(6)",drive->err); return (drive->err); }
return 0;
}
*/
int mode_sense(drive_info* drive, int page, int page_control, int dest_len) {
drive->cmd_clear();
drive->cmd[0]=MMC_MODE_SENSE10;
drive->cmd[2]=page_control << 6 | page;
drive->cmd[7]=(dest_len >> 8) & 0xFF;
drive->cmd[8]=dest_len & 0xFF;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,dest_len) ))
{sperror ("MODE_SENSE(10)",drive->err); return (drive->err); }
return 0;
}
/*
int mode_select6(drive_info* drive, short dest_len) {
drive->cmd_clear();
drive->cmd[0]=MMC_MODE_SELECT6;
// drive->cmd[1]= 0x10;
drive->cmd[4]=dest_len & 0xFF;
if ((drive->err=drive->cmd.transport(WRITE,drive->rd_buf,dest_len) ))
{sperror ("MODE_SELECT(6)",drive->err); return (drive->err); }
return 0;
}
*/
int mode_select(drive_info* drive, int dest_len) {
drive->cmd_clear();
drive->cmd[0]=MMC_MODE_SELECT10;
drive->cmd[1]= 0x10;
drive->cmd[7]=(dest_len >> 8) & 0xFF;
drive->cmd[8]=dest_len & 0xFF;
if ((drive->err=drive->cmd.transport(WRITE,drive->rd_buf,dest_len) ))
{sperror ("MODE_SELECT(10)",drive->err); return (drive->err); }
return 0;
}
int get_configuration(drive_info* drive, int feature_number, unsigned int* data_length, int* current, unsigned char ReqType = 0x02) {
if (data_length) *data_length = 0;
if (current) *current = 0;
drive->cmd_clear();
drive->cmd[0] = MMC_GET_CONFIGURATION;
drive->cmd[1] = ReqType;
drive->cmd[2] = (feature_number >> 8) & 0xFF;
drive->cmd[3] = feature_number & 0xFF;
drive->cmd[7] = 0;
drive->cmd[8] = 8;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,8)))
{sperror ("GET_CONFIGURATION LENGTH",drive->err);
return (drive->err);}
if (data_length)
{
*data_length = swap4(drive->rd_buf);
// *data_length = (drive->rd_buf[0]<<24) | (drive->rd_buf[1]<<16) | (drive->rd_buf[2]<<8) | drive->rd_buf[3];
drive->cmd[7] = ((*data_length+4) >> 8) & 0xFF;
drive->cmd[8] = (*data_length+4) & 0xFF;
if (*data_length > 4)
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,*data_length+4)))
{sperror ("GET_CONFIGURATION",drive->err);
return (drive->err);}
}
if (current) *current = drive->rd_buf[10] & 0x01;
return 0;
}
void detect_iface(drive_info* drive){
unsigned int len=0;
get_configuration(drive, FEATURE_CORE, &len, NULL);
drive->iface_id= (drive->rd_buf[12] << 12) | (drive->rd_buf[13] << 8) | (drive->rd_buf[14] << 4) | drive->rd_buf[15];
if (drive->iface_id<iface_id_max)
strcpy(drive->iface,iface_list[drive->iface_id]);
else
strcpy(drive->iface,iface_list[iface_id_max+1]);
}
int get_mode_pages_list(drive_info* drive) {
unsigned int len, i, ii;
unsigned char ml=0, mn=0;
if (!drive->silent) printf("\n** Reading supported mode pages...\n");
if (mode_sense(drive, 0x3F, 2, 0x4000)) return 1;
len = swap2u (drive->rd_buf);
// printf("data len: %4X (%4d), Header:\n", len, len);
// for (i=0; i<8; i++) printf(" 0x%02X",drive->rd_buf[i] & 0xFF); printf("\n");
for (i=8; i<len; i+=ml) {
mn = drive->rd_buf[i] & 0x3F;
ml = drive->rd_buf[i+1] & 0xFF;
ii = 0;
while ((MODE_PAGES[ii].id != mn) && (MODE_PAGES[ii].id < 0x3F)) ii++;
if (!drive->silent) {
printf("Mode Page: 0x%02X [%s]", mn, MODE_PAGES[ii].name);
// for (ii=0; ii<(ml+2); ii++) { if (!(ii%32)) printf("\n"); printf(" %02X",drive->rd_buf[i+ii] & 0xFF); }
printf("\n");
}
ml += 2;
}
return 0;
}
int get_features_list(drive_info* drive) {
unsigned int len, i, ii;
unsigned short fn;
unsigned char fl;
if (!drive->silent) printf("\n** Reading supported features...\n");
if (get_configuration(drive, 0 , &len, NULL, 0)) return 1;
// printf("data len: %4X (%4d), Header:\n", len, len);
// for (i=0; i<8; i++) printf(" 0x%02X",drive->rd_buf[i] & 0xFF); printf("\n");
for (i=8; i<len; i+=fl) {
fn = swap2u (drive->rd_buf+i);
fl = drive->rd_buf[i+3];
ii = 0;
while ((FEATURES[ii].id != fn) && (FEATURES[ii].id < 0xFFFF)) ii++;
if (!drive->silent) {
printf("Feature: 0x%04X [%s]", fn, FEATURES[ii].name);
// for (ii=0; ii<(fl+4); ii++) { if (!(ii%32)) printf("\n"); printf(" %02X",drive->rd_buf[i+ii] & 0xFF); }
printf("\n");
}
fl += 4;
}
return 0;
}
int get_profiles_list(drive_info* drive) {
unsigned int len, i, ii;
unsigned short profile;
if (!drive->silent) printf("\n** Reading supported profiles...\n");
if (get_configuration(drive, FEATURE_PROFILE_LIST , &len, NULL)) return 1;
for( i = 0; i < len-8; i+=4 ) {
profile = swap2u (drive->rd_buf+i+12);
ii=0;
while ((PROFILES[ii].id != profile) && (PROFILES[ii].id < 0xFFFF)) ii++;
if (!drive->silent) printf("Profile: 0x%04X [%s]\n", profile, PROFILES[ii].name);
switch (profile) {
case 0x10: // DVD-ROM
drive->rd_capabilities |= DEVICE_DVD_ROM;
break;
case 0x11: // DVD-R Sequential
drive->rd_capabilities |= DEVICE_DVD_R;
drive->wr_capabilities |= DEVICE_DVD_R;
break;
case 0x12: // DVD-RAM
drive->rd_capabilities |= DEVICE_DVD_RAM;
drive->wr_capabilities |= DEVICE_DVD_RAM;
break;
case 0x13: // DVD-RW Restricted Overwrite
drive->rd_capabilities |= DEVICE_DVD_RW;
drive->wr_capabilities |= DEVICE_DVD_RW;
break;
case 0x14: // DVD-RW Sequential
drive->rd_capabilities |= DEVICE_DVD_RW;
drive->wr_capabilities |= DEVICE_DVD_RW;
break;
case 0x15: // DVD-R DL Sequential
drive->rd_capabilities |= (DEVICE_DVD_R_DL);
drive->wr_capabilities |= (DEVICE_DVD_R_DL);
break;
case 0x16: // DVD-R DL Layer Jump
drive->rd_capabilities |= (DEVICE_DVD_R_DL);
drive->wr_capabilities |= (DEVICE_DVD_R_DL);
break;
case 0x1A: // DVD+RW
drive->rd_capabilities |= DEVICE_DVD_PLUS_RW;
drive->wr_capabilities |= DEVICE_DVD_PLUS_RW;
break;
case 0x1B: // DVD+R
drive->rd_capabilities |= DEVICE_DVD_PLUS_R;
drive->wr_capabilities |= DEVICE_DVD_PLUS_R;
break;
case 0x2B: // DVD+R DL
drive->rd_capabilities |= (DEVICE_DVD_PLUS_R_DL);
drive->wr_capabilities |= (DEVICE_DVD_PLUS_R_DL);
break;
case 0x08: // CD-ROM
drive->rd_capabilities |= DEVICE_CD_ROM;
drive->wr_capabilities |= DEVICE_CD_ROM;
break;
case 0x09: // CD-R
drive->rd_capabilities |= DEVICE_CD_R;
drive->wr_capabilities |= DEVICE_CD_R;
break;
case 0x0A: // CD-RW
drive->rd_capabilities |= DEVICE_CD_RW;
drive->wr_capabilities |= DEVICE_CD_RW;
break;
}
}
profile = swap2(drive->rd_buf+6);
ii=0;
while ((PROFILES[ii].id != profile) && (PROFILES[ii].id < 0xFFFF)) ii++;
if (!drive->silent) printf("Current: 0x%04X [%s]\n", profile, PROFILES[ii].name);
return 0;
}
void detect_capabilities(drive_info* drive){
unsigned int len=4;
drive->capabilities=CAP_SET_CD_SPEED;
drive->rd_capabilities=0;
drive->wr_capabilities=0;
detect_mm_capabilities(drive);
get_mode_pages_list(drive);
if (drive->mmc>1) {
// LU is MMC2 or later. Detecting capabilities by GET_CONFIGURATION
get_profiles_list(drive);
get_features_list(drive);
get_configuration(drive, FEATURE_REMOVABLE_MEDIA , &len, NULL);
if (len >= 0x0C) drive->capabilities|=CAP_REMOVABLE_MEDIA;
get_configuration(drive, FEATURE_SMART , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_SMART;
get_configuration(drive, FEATURE_MICROCODE_UPGRADE , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_MICROCODE_UPGRADE;
get_configuration(drive, FEATURE_MORPHING , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_MORPHING;
get_configuration(drive, FEATURE_POWER_MANAGEMENT , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_POWER_MANAGEMENT;
get_configuration(drive, FEATURE_EMBEDDED_CHANGER , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_EMBEDDED_CHANGER;
get_configuration(drive, FEATURE_DEFECT_MANAGEMENT , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_DEFECT_MANAGEMENT;
get_configuration(drive, FEATURE_REAL_TIME_STREAMING , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_REAL_TIME_STREAMING;
get_configuration(drive, FEATURE_MRW , &len, NULL);
if (len >= 0x0C) {
drive->rd_capabilities|=DEVICE_MRW;
if (drive->rd_buf[12]&0x01) drive->wr_capabilities|=DEVICE_MRW;
}
get_configuration(drive, FEATURE_CD_READ , &len, NULL); // LU can Reed/Write CD's
if (len >= 0x0C) {
// drive->rd_capabilities|=DEVICE_CD_ROM;
if (drive->rd_buf[12]&0x1) drive->capabilities|=CAP_CD_TEXT;
if (drive->rd_buf[12]&0x2) drive->capabilities|=CAP_C2;
}
get_configuration(drive, FEATURE_DVD_READ , &len, NULL); // LU can Reed/Write DVD's
if (len >= 0x08) {
if (drive->rd_buf[14]&0x01) drive->rd_capabilities|=DEVICE_DVD_R_DL;
get_configuration(drive, FEATURE_DVD_CPRM , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_DVD_CPRM;
get_configuration(drive, FEATURE_DVD_CSS , &len, NULL);
if (len >= 0x08) drive->capabilities|=CAP_DVD_CSS;
get_configuration(drive, FEATURE_DVD_R_RW_WRITE , &len, NULL);
if (len >= 0x08) {
drive->wr_capabilities|=DEVICE_DVD_R;
if (drive->rd_buf[12]&0x02) drive->wr_capabilities|=DEVICE_DVD_RW;
// if (drive->rd_buf[12]&0x04) drive->wr_capabilities|=DEVICE_DVD_R_DL;
}
get_configuration(drive, FEATURE_LAYER_JUMP_RECORDING , &len, NULL);
if (len >= 0x08) drive->wr_capabilities|=DEVICE_DVD_R_DL;
get_configuration(drive, FEATURE_DVD_PLUS_R , &len, NULL);
if (len >= 0x08) {
// drive->mmc=4;
drive->rd_capabilities|=DEVICE_DVD_PLUS_R;
if (drive->rd_buf[12]&0x01) drive->wr_capabilities|=DEVICE_DVD_PLUS_R;
}
get_configuration(drive, FEATURE_DVD_PLUS_RW , &len, NULL);
if (len >= 0x0C) {
drive->rd_capabilities|=DEVICE_DVD_PLUS_RW;
if (drive->rd_buf[12]&0x01) drive->wr_capabilities|=DEVICE_DVD_PLUS_RW;
}
get_configuration(drive, FEATURE_DVD_PLUS_R_DOUBLE_LAYER , &len, NULL);
if (len >= 0x0C) {
// drive->mmc=5;
drive->rd_capabilities|=DEVICE_DVD_PLUS_R_DL;
if (drive->rd_buf[12]&0x01) drive->wr_capabilities|=DEVICE_DVD_PLUS_R_DL;
}
}
get_configuration(drive, FEATURE_DDCD_READ , &len, NULL); // LU can Reed/Write DDCD's
if (len >= 0x0C) {
drive->rd_capabilities|=DEVICE_DDCD_R;
drive->rd_capabilities|=DEVICE_DDCD_RW;
get_configuration(drive, FEATURE_DDCD_R_WRITE , &len, NULL);
if (len >= 0x0C) drive->wr_capabilities|=DEVICE_DDCD_R;
get_configuration(drive, FEATURE_DDCD_RW_WRITE , &len, NULL);
if (len >= 0x0C) drive->wr_capabilities|=DEVICE_DDCD_RW;
}
if (!drive->silent) printf("** Device is MMC-%d\n",drive->mmc);
}
}
int read_atip(drive_info* drive) {
unsigned char data[4];
int size = 0;
int i;
drive->ATIP_len = 0;
drive->cmd_clear();
drive->cmd[0]=MMC_READ_TOC_PMA_ATIP;
drive->cmd[1]=0;
drive->cmd[2]= 4; // ATIP
drive->cmd[3]=0;
drive->cmd[8]=4;
if ((drive->err=drive->cmd.transport(READ,data,4) ))
{if (!drive->silent) sperror ("READ_ATIP",drive->err); drive->ATIP_len = 0; return 1;}
size = swap2u((char*)data);
size += 2;
drive->cmd_clear();
drive->cmd[0]=MMC_READ_TOC_PMA_ATIP;
drive->cmd[1]=0;
drive->cmd[2]= 4; // ATIP
drive->cmd[3]=0;
drive->cmd[7]=(size >> 8) & 0xFF;
drive->cmd[8]=size & 0xFF;
if ((drive->err=drive->cmd.transport(READ,drive->ATIP,size) ))
{sperror ("READ_ATIP",drive->err); drive->ATIP_len = 0; return 1;}
drive->ATIP_len = size;
if (!drive->silent) {
printf("ATIP (%d bytes):\n",size);
for (i=0; i<(min(size, 4)); i++) printf(" %3d (%02X)",drive->ATIP[i],drive->ATIP[i]);
if (size > 4) for (i=0; i<(size-4); i++) {
if (!(i % 8)) printf("\n");
else if (!(i % 4)) printf(" ");
printf(" %3d (%02X)",drive->ATIP[i+4] & 0xFF,drive->ATIP[i+4] & 0xFF);
}
printf("\n");
}
return 0;
}
int read_toc(drive_info* drive) {
unsigned char data[4];
int size = 0;
int i;
drive->cmd_clear();
drive->cmd[0]=MMC_READ_TOC_PMA_ATIP;
drive->cmd[1]=0;
drive->cmd[2]= 0; // TOC
drive->cmd[3]=0;
drive->cmd[8]=4;
if ((drive->err=drive->cmd.transport(READ,data,4) ))
{sperror ("READ_TOC",drive->err); return 1;}
// if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,2048) ))
// {sperror ("READ_TOC",drive->err); return 1;}
size = swap2u((char*)data);
size += 2;
drive->cmd_clear();
drive->cmd[0]=MMC_READ_TOC_PMA_ATIP;
drive->cmd[1]=0;
drive->cmd[2]= 0; // TOC
drive->cmd[3]=0;
drive->cmd[7]=(size >> 8) & 0xFF;
drive->cmd[8]=size & 0xFF;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,size) ))
{if (!drive->silent) sperror ("READ_TOC",drive->err); return 1;}
if (!drive->silent) {
printf("TOC (%d bytes):\n",size);
for (i=0; i<(min(size, 4)); i++) printf(" %3d (%02X)",drive->rd_buf[i] & 0xFF,drive->rd_buf[i] & 0xFF);
if (size > 4) for (i=0; i<(size-4); i++) {
if (!(i % 8)) printf("\n");
else if (!(i % 4)) printf(" ");
printf(" %3d (%02X)",drive->rd_buf[i+4] & 0xFF,drive->rd_buf[i+4] & 0xFF);
}
printf("\n");
}
return 0;
}
int read_capacity(drive_info* drive) {
unsigned char data[8]; memset(data, 0, 8);
unsigned int ccity,bsize;
drive->cmd_clear();
drive->cmd[0] = MMC_READ_RECORDED_CAPACITY;
drive->cmd[9] = 0;
drive->cmd.transport (READ,data,8);
ccity = data[0]<<24|data[1]<<16|data[2]<<8|data[3], ccity++;
bsize = data[4]<<24|data[5]<<16|data[6]<<8|data[7];
drive->media.capacity = ccity; //capacity in blocks
lba2msf(&drive->media.capacity,&drive->media.capacity_msf);
drive->media.sectsize = bsize; //block size
return 0;
}
int read_track_info(drive_info* drive, trk* track, unsigned int track_n){
int size = 2048;
drive->cmd_clear();
drive->cmd[0] = MMC_READ_TRACK_INFORMATION;
drive->cmd[1] = 0x01;
drive->cmd[2] = (track_n >> 24) & 0xFF;
drive->cmd[3] = (track_n >> 16) & 0xFF;
drive->cmd[4] = (track_n >> 8) & 0xFF;
drive->cmd[5] = track_n & 0xFF ;
drive->cmd[7] = (size >> 8) & 0xFF ;
drive->cmd[8] = size & 0xFF ;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,size) ))
{if (!drive->silent) sperror ("READ_TRACK_INFO",drive->err); return 1;}
// int i,
int len;
len = ( drive->rd_buf[0] << 8 ) | drive->rd_buf[1];
/* printf("\nTrack #%d info:\n ",track->n);
for (i=0; i<len+2; i++) { printf(" 0x%02X",drive->rd_buf[i] & 0xFF); if (!((i+1)%8)) printf("\n ");}
if (((i)%8)) printf("\n");*/
track->n = ((drive->rd_buf[32]&0xFF) << 8) | (drive->rd_buf[2]&0xFF);
track->session = ((drive->rd_buf[33]&0xFF) << 8) | (drive->rd_buf[3]&0xFF);
track->track_mode = drive->rd_buf[5] & 0x0F;
track->data_mode = drive->rd_buf[6] & 0x0F;
track->start = ((drive->rd_buf[8]&0xFF) << 24) | ((drive->rd_buf[9]&0xFF) << 16) |
((drive->rd_buf[10]&0xFF) << 8) | (drive->rd_buf[11]&0xFF);
track->next_writable = ((drive->rd_buf[12]&0xFF) << 24) | ((drive->rd_buf[13]&0xFF) << 16) |
((drive->rd_buf[14]&0xFF) << 8) | (drive->rd_buf[15]&0xFF);
track->free = ((drive->rd_buf[16]&0xFF) << 24) | ((drive->rd_buf[17]&0xFF) << 16) |
((drive->rd_buf[18]&0xFF) << 8) | (drive->rd_buf[19]&0xFF);
track->size = ((drive->rd_buf[24]&0xFF) << 24) | ((drive->rd_buf[25]&0xFF) << 16) |
((drive->rd_buf[26]&0xFF) << 8) | (drive->rd_buf[27]&0xFF);
track->last_recorded = ((drive->rd_buf[28]&0xFF) << 24) | ((drive->rd_buf[29]&0xFF) << 16) |
((drive->rd_buf[30]&0xFF) << 8) | (drive->rd_buf[31]&0xFF);
track->end = track->start+track->size-1;
lba2msf(&track->start,&track->msf_start);
lba2msf(&track->next_writable,&track->msf_next);
lba2msf(&track->last_recorded,&track->msf_last);
lba2msf(&track->end,&track->msf_end);
lba2msf(&track->size,&track->time);
return 0;
}
int get_track_list(drive_info* drive){
int i;
if (drive->media.disc_type & DISC_CD) {
if (!drive->silent) printf("Get CD track list\n");
if (read_toc(drive)) {
printf("Error reading TOC :(\n");
drive->media.tracks = 0;
} else {
// drive->media.tracks = 0;
drive->media.tracks = drive->rd_buf[3] & 0xFF;
for (i=0; i<drive->media.tracks; i++) {
drive->media.track[i].n = i+1;
drive->media.track[i].session = 1;
drive->media.track[i].start = swap4(drive->rd_buf+i*8+8);
drive->media.track[i].end = swap4(drive->rd_buf+i*8+16);
drive->media.track[i].size = drive->media.track[i].end - drive->media.track[i].start;
drive->media.track[i].free = 0;
drive->media.track[i].last_recorded = 0;
drive->media.track[i].track_mode = drive->rd_buf[i*8+5] & 0x0F;
// drive->media.track[i].data_mode = 0;
drive->media.track[i].data_mode = (drive->rd_buf[i*8+5] >> 4) & 0x0F;
lba2msf(&drive->media.track[i].start, &drive->media.track[i].msf_start);
lba2msf(&drive->media.track[i].next_writable, &drive->media.track[i].msf_next);
lba2msf(&drive->media.track[i].last_recorded, &drive->media.track[i].msf_last);
lba2msf(&drive->media.track[i].end, &drive->media.track[i].msf_end);
lba2msf(&drive->media.track[i].size, &drive->media.track[i].time);
}
printf("tracks: %d\n",drive->media.tracks);
}
} else if (drive->media.disc_type & DISC_DVD) {
printf("Get DVD track list\n");
for (i=0; i<drive->media.tracks; i++) {
// track.n = ++i;
read_track_info(drive, &drive->media.track[i], i+1);
}
if (!drive->silent) printf("tracks: %d\n",drive->media.tracks);
}
if ((drive->media.tracks) && (!drive->silent)) for (i=0; i<drive->media.tracks; i++) {
printf("\nTrack # : %d\n", drive->media.track[i].n);
printf("Session #: %d\n", drive->media.track[i].session);
printf("Track mode : %d\n",drive->media.track[i].track_mode);
printf("Data mode : %d\n",drive->media.track[i].data_mode);
printf("Track start : %d\n",drive->media.track[i].start);
printf("Next writable : %d\n",drive->media.track[i].next_writable);
printf("Free : %d\n",drive->media.track[i].free);
printf("Size : %d\n",drive->media.track[i].size);
printf("Last recorded : %d\n",drive->media.track[i].last_recorded);
}
return 0;
}
int read_free(drive_info* drive) {
trk track;
if (drive->media.dstatus == 2) {
drive->media.capacity_free = 0;
return 0;
}
if (drive->media.disc_type & DISC_CD) {
if (((drive->media.last_lead_out >> 24) & 0xFF ) == 0xFF) {
drive->media.capacity_free = 0;
return 0;
} else {
drive->media.capacity_free = drive->media.last_lead_out - drive->media.capacity - 150;
lba2msf(&drive->media.capacity_free,&drive->media.capacity_free_msf);
return 0;
}
} else if (drive->media.disc_type & DISC_DVD) {
// track.n = drive->media.sessions+1;
read_track_info(drive, &track, drive->media.sessions+1);
drive->media.capacity_free = track.free;
return 0;
}
drive->media.capacity_free = 0;
return 1;
}
int read_disc_information(drive_info* drive) {
int i=0,len=0;
drive->cmd_clear();
drive->cmd[0] = MMC_READ_DISC_INFORMATION;
drive->cmd[7] = 0x08;
drive->cmd[8] = 0x00;
drive->cmd.transport (READ,drive->rd_buf,2048);
len= (drive->rd_buf[0]<<8)|drive->rd_buf[1];
if (!drive->silent) printf("Disc info length: 0x%04X\n ",len);
if (len!=0x20) {
drive->media.erasable = 0;
drive->media.dstatus = 0;
drive->media.sstatus = 0;
drive->media.sessions = 0;
drive->media.tracks = 0;
return 1;
}
if (!drive->silent) for (i=0; i<len+2; i++) {
printf(" 0x%02X",drive->rd_buf[i] & 0xFF);
if (!((i+1)%8)) printf("\n ");
}
if (((i)%8)) printf("\n");
drive->media.erasable = (drive->rd_buf[2]&0x10);
drive->media.dstatus = drive->rd_buf[2]&0x03;
drive->media.sstatus = (drive->rd_buf[2]>>2)&0x03;
drive->media.sessions = (drive->rd_buf[4]|(drive->rd_buf[9]<<8));
// if (!drive->media.sstatus) drive->media.sessions--;
drive->media.tracks = drive->rd_buf[6]|(drive->rd_buf[11]<<8);
if (!drive->silent) {
printf(" first track# on disc: %d\n", drive->rd_buf[3]);
printf(" first track# in last session: %d\n", drive->rd_buf[5]|(drive->rd_buf[10]<<8));
printf(" last track# in last session: %d\n", drive->media.tracks);
printf(" disc type: %02X\n", drive->rd_buf[8]&0xFF);
printf(" disc ID: %02X%02X%02X%02X\n",
drive->rd_buf[12],drive->rd_buf[13],drive->rd_buf[14],drive->rd_buf[15]);
printf(" Last session lead-in start: %d:%02d.%02d\n",
(drive->rd_buf[16]<<8)|drive->rd_buf[17],drive->rd_buf[18],drive->rd_buf[19]);
drive->media.last_lead_out = (((drive->rd_buf[20]&0xFF) << 8) | (drive->rd_buf[21]&0xFF))*75*60 + ((drive->rd_buf[22]&0xFF)*75) + (drive->rd_buf[23]&0xFF);
printf(" Last possible lead-out start: %d:%02d.%02d (sector 0x%08X)\n",
(drive->rd_buf[20]<<8)|drive->rd_buf[21],drive->rd_buf[22],drive->rd_buf[23],drive->media.last_lead_out);
}
if (!drive->media.sstatus) {
drive->media.sessions--;
drive->media.tracks--;
}
return 0;
}
void read_disc_regions(drive_info* drive){
//#warning "read_disc_regions()"
int len=8;
unsigned char enc;
unsigned char regmask;
int i;
drive->cmd_clear();
drive->cmd[0] = MMC_READ_DVD_STRUCTURE;
drive->cmd[7] = 0x01;
drive->cmd[8] = len>>8;
drive->cmd[9] = len & 0xFF;
drive->cmd[11] = 0;
if (( drive->err = drive->cmd.transport(READ,drive->rd_buf,len) ))
{ if (!drive->silent) sperror ("READ_DISC_REGIONS",drive->err); return; }
if (!drive->silent) {
printf("READ_DISC_REGIONS data: ");
for(i=0; i<len ;i++) printf(" %02X",drive->rd_buf[i] & 0xFF);
printf("\n");
}
enc = drive->rd_buf[5];
regmask = drive->rd_buf[5];
printf("Disc is %sprotected\n", enc ? "" : "NOT ");
printf("Disc regions : ");
if (regmask != 0xFF) {
for (i=0; i<8; i++)
if (!((regmask >> i) & 1))
{printf("%d",i+1); drive->rpc.region = i+1;}
printf("\n");
} else
printf("does not set\n");
}
void read_rpc_state(drive_info* drive){
int len=8;
int i;
unsigned char regmask;
unsigned char t;//,vl,ul;
unsigned char sh;
if (!(drive->rd_capabilities & DEVICE_DVD))
{drive->rpc.phase = 0; return;}
drive->cmd_clear();
drive->cmd[0] = MMC_REPORT_KEY;
drive->cmd[8] = len>>8;
drive->cmd[9] = len & 0xFF;
drive->cmd[10] = 0x08;
drive->cmd[11] = 0;
if (( drive->err = drive->cmd.transport(READ,drive->rd_buf,len) ))
{ if (drive->err == 0x52400)
{printf("\n** Unit is RPC-I\n"); drive->rpc.phase = 1; }
else
{if (!drive->silent) sperror ("READ_RPC_STATE",drive->err); drive->rpc.phase = 0; }
return; }
/* printf("MMC_REPORT_KEY data: ");
for(i=0; i<len ;i++) printf(" %02X",drive->rd_buf[i] & 0xFF);
printf("\n");*/
if (swap2(drive->rd_buf) < 6) return;
drive->rpc.ch_u = drive->rd_buf[4] & 0x07;
drive->rpc.ch_v = (drive->rd_buf[4] >> 3) & 0x07;
t = (drive->rd_buf[4] >> 6) & 0x03;
regmask = drive->rd_buf[5];
sh = drive->rd_buf[6];
drive->rpc.phase = 2;
printf("\n** Unit is RPC-II\n");
printf("Current region : ");
if (regmask != 0xFF) {
for (i=0; i<8; i++)
if (!((regmask >> i) & 1))
{printf("%d",i+1); drive->rpc.region = i+1;}
printf("\n");
} else
printf("does not set\n");
printf("User changes left : %d\n",drive->rpc.ch_u);
printf("Vendor resets left : %d\n",drive->rpc.ch_v);
}
int determine_cd_type(drive_info* drive) {
// unsigned char* ATIP;
// int ATIP_len;
// int i;
int ratip = read_atip(drive);
if (ratip) {
if (!drive->silent) printf("no ATIP found, assuming disc type: CD-ROM\n");
return DISC_CDROM; // CD-ROM
// } else {
// drive->ATIP_len += 4;
}
if (drive->ATIP_len < 8) {
if (!drive->silent) printf("ATIP too small, assuming disc type: CD-ROM\n");
return DISC_CDROM; // CD-ROM
}
/*
printf("ATIP_len=%d\nATIP data:",drive->ATIP_len);
for (i=0; i< drive->ATIP_len; i++) printf("%4d",(drive->ATIP[i])&0xFF);
printf("\n");
*/
// CD-RW?
int cdrw = !!(drive->ATIP[6] & 0x40);
int cdrw_subtype = (drive->ATIP[6] & 0x38) >> 3;
if (cdrw) {
if (!drive->silent) printf("disc type: CD-RW\n");
switch (cdrw_subtype) {
case 0: return DISC_CDRW | DISC_CDRWMS; break;
case 1: return DISC_CDRW | DISC_CDRWHS; break;
case 2: return DISC_CDRW | DISC_CDRWUS; break;
case 3: return DISC_CDRW | DISC_CDRWUSP; break;
default: return DISC_CDRW;
}
}
if (!drive->silent) printf("disc type: CD-R\n");
return DISC_CDR;
}
int read_mediaid_dvd(drive_info* drive){
int i;
unsigned int len;
char header[40];
union { unsigned char _e[4+40],_11[4+256]; } dvd;
unsigned char format; // 0x11 +, 0x0E -
if (drive->media.disc_type & DISC_DVDminus)
format=0x0E;
else
format=0x11;
drive->cmd_clear();
drive->cmd[0] = MMC_READ_DVD_STRUCTURE;
drive->cmd[7] = format;
drive->cmd[9] = 4;
drive->cmd[11] = 0;
drive->err = drive->cmd.transport(READ,header,4);//))
len = (header[0]<<8|header[1]) + 2;
if (len>sizeof(dvd)) len=sizeof(dvd);
drive->cmd_clear();
drive->cmd[0] = MMC_READ_DVD_STRUCTURE;
drive->cmd[7] = format;
drive->cmd[8] = len>>8;
drive->cmd[9] = len;
drive->cmd[11] = 0;
drive->err = drive->cmd.transport(READ,&dvd,len);
drive->media.MID[0] = 0;
if (drive->media.disc_type & DISC_DVDminus) {
memcpy(drive->media.MID,dvd._e+21,6);
drive->media.MID[6]='/';
memcpy(drive->media.MID+7,dvd._e+29,6);
drive->media.MID[12]=0;
// drive->media.MID[12]='/';
// memcpy(drive->media.MID+13,dvd._e+37,6);
// drive->media.MID[18]=0;
} else {
memcpy(drive->media.MID,dvd._11+23,8);
drive->media.MID[8]='/';
memcpy(drive->media.MID+9,dvd._11+31,3);
drive->media.MID[12]=0;
// for (i=12; i<19; i++) drive->media.MID[i]=0;
}
for (i=0; i<12; i++) if(drive->media.MID[i] == 0) drive->media.MID[i]=0x20;
return 0;
}
int read_mediaid_cd(drive_info* drive)
{
// printf("read_mediaid_cd()\n");
msf lin;
int type;
// int atippr = read_atip(drive);
// if (!atippr) drive->ATIP_len+=4; else return 1;
if (!drive->ATIP_len) return 1;
lin.m=drive->ATIP[8];
lin.s=drive->ATIP[9];
lin.f=drive->ATIP[10];
type = lin.f % 10;
lin.f -= type;
int idx=0;
int nf=1;
while (mi[idx].lin.m && nf)
if (lin.m == mi[idx].lin.m && lin.s == mi[idx].lin.s && lin.f == mi[idx].lin.f) nf=0;
else idx++;
// strncpy(drive->media.MID,mi[idx].name,47));
sprintf(drive->media.MID,"[%02d:%02d.%02d] %s",lin.m,lin.s,lin.f,mi[idx].name);
return 0;
}
int determine_disc_type(drive_info* drive) {
int current = 0;
// int i=0;
drive->media.disc_type = DISC_NODISC;
// drive->media.type = Media_NoMedia;
if (drive->mmc>1) {
get_configuration(drive, FEATURE_PROFILE_LIST, NULL, ¤t);
switch (drive->rd_buf[7]) {
case 0: drive->media.disc_type = DISC_NODISC; break;
case PROFILE_CD_ROM: drive->media.disc_type = DISC_CDROM; break;
case PROFILE_CD_R: drive->media.disc_type = DISC_CDR; break;
case PROFILE_CD_RW: drive->media.disc_type = DISC_CDRW; break;
case PROFILE_DVD_ROM: drive->media.disc_type = DISC_DVDROM; break;
case PROFILE_DVD_R_SEQ: drive->media.disc_type = DISC_DVDminusR; break;
case PROFILE_DVD_RAM: drive->media.disc_type = DISC_DVDRAM; break;
case PROFILE_DVD_RW_RESTOV: drive->media.disc_type = DISC_DVDminusRWR; break;
case PROFILE_DVD_RW_SEQ: drive->media.disc_type = DISC_DVDminusRWS; break;
case PROFILE_DVD_R_DL_SEQ: drive->media.disc_type = DISC_DVDminusRDL; break;
case PROFILE_DVD_R_DL_JUMP: drive->media.disc_type = DISC_DVDminusRDLJ; break;
case PROFILE_DVD_PLUS_RW: drive->media.disc_type = DISC_DVDplusRW; break;
case PROFILE_DVD_PLUS_R: drive->media.disc_type = DISC_DVDplusR; break;
case PROFILE_DVD_PLUS_R_DL: drive->media.disc_type = DISC_DVDplusRDL; break;
default: drive->media.disc_type = DISC_UN; break;
}
if (!drive->media.disc_type) return 0;
read_disc_information(drive);
if (drive->media.disc_type & DISC_CD) {
drive->media.disc_type = determine_cd_type(drive);
read_mediaid_cd(drive);
if (!drive->silent) printf("** MID: '%s'\n",drive->media.MID);
return 0;
} else if (drive->media.disc_type & DISC_DVD) {
// drive->media.type=Media_DVD;
drive->rd_buf[4]=0;
drive->cmd_clear();
drive->cmd[0] = MMC_READ_DVD_STRUCTURE;
drive->cmd[7] = 0;//0x11; //dvd_dash;
drive->cmd[9] = 36;
drive->cmd[11] = 0;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,36)))
if (!drive->silent) sperror ("READ_DVD_STRUCTURE",drive->err);
drive->media.book_type = (drive->rd_buf[4] & 0xFF);
drive->media.layers = 1 + ((drive->rd_buf[6] & 0x60) >> 5);
read_mediaid_dvd(drive);
if (!drive->silent) printf("** MID: '%s'\n",drive->media.MID);
if ((!(drive->wr_capabilities & DEVICE_DVD))||(drive->media.disc_type & DISC_DVDROM)) {
if (!drive->silent) {
printf("Device can't write DVD's or media detected as DVD-ROM,\n");
printf("trying to corectly detect DVD type...\n");
}
switch ((drive->media.book_type>>4)&0x0F){
case BOOK_DVD_R:
if (drive->media.layers == 1)
drive->media.disc_type = DISC_DVDminusR;
else
drive->media.disc_type = DISC_DVDminusRDL;
break;
case BOOK_DVD_RW:
drive->media.disc_type = DISC_DVDminusRWS; break;
case BOOK_DVD_PR:
drive->media.disc_type = DISC_DVDplusR; break;
case BOOK_DVD_PRW:
drive->media.disc_type = DISC_DVDplusRW; break;
case BOOK_DVD_PR_DL:
drive->media.disc_type = DISC_DVDplusRDL; break;
case BOOK_DVD_ROM:
if (strncmp(drive->media.MID," / ",12)) {
if (!drive->silent) printf("MID found:)\n");
if (drive->media.erasable) {
drive->media.disc_type = DISC_DVDplusRW;
} else {
if (drive->media.layers == 1)
drive->media.disc_type = DISC_DVDplusR;
else
drive->media.disc_type = DISC_DVDplusRDL;
}
}
break;
default:
break;
}
}
read_writer_info(drive);
if (!drive->silent) printf("** Writer used: '%s'\n",drive->media.writer);
/*
read_disc_regions(drive);
printf("DVD Copyright info: ");
for (i=0;i<4;i++) printf("0x%02X ",drive->rd_buf[i]);
printf("\n");
*/
return 0;
}
} else {
read_capacity(drive);
if (drive->media.capacity) {
// drive->media.type=Media_CD;
drive->media.disc_type = DISC_CDROM;
read_disc_information(drive);
}
return 0;
}
return 1;
}
int get_spindown(drive_info* drive) {
mode_sense(drive, 0x0D, 00, 192);
if (drive->err)
{drive->parms.spindown_idx=spindowns; return (drive->err);}
drive->parms.spindown_idx = drive->rd_buf[11] & 0x0F;
return 0;
}
int set_spindown(drive_info* drive) {
int i;
for (i=0; i<16; i++) drive->rd_buf[i]=0;
drive->rd_buf[8] = 0x0D;
drive->rd_buf[9] = 0x06;
drive->rd_buf[11] = drive->parms.spindown_idx & 0x0F;
drive->rd_buf[13] = 0x3C;
drive->rd_buf[15] = 0x4B;
mode_select(drive, 16);
return 0;
}
int get_performance(drive_info* drive) {
const int max_descs=52;
const int desc_len=16;
int len, descn;
// int i;
int j,offs;
drive->cmd_clear();
drive->cmd[0] = MMC_GET_PERFORMANCE;
drive->cmd[1] = 0x00;
drive->cmd[8] = (max_descs >> 8) & 0xFF;
drive->cmd[9] = max_descs & 0xFF;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf, 1024)))
{ sperror ("GET_PERFORMANCE",drive->err); return (drive->err); }
// return 1;
len = (drive->rd_buf[0]<<24) | (drive->rd_buf[1]<<16) | (drive->rd_buf[2]<<8) | (drive->rd_buf[3]);
descn = len/desc_len;
// printf("Performance data length: %d; decriptors: %d\n",len, descn);
// printf("GET_PERFORMANCE response dump:\n");
// for (j=0; j*8<len; j++) {
// for (i=0; i<8; i++) printf(" 0x%02X",drive->rd_buf[i]);
// printf("\n");
// }
for (j=0; j<descn; j++) {
offs = 8+j*desc_len;
printf("\tDescriptor #%02d:",j);
// for (i=0; i<desc_len; i++) printf(" 0x%02X",(drive->rd_buf[offs+i])&0xFF);
// printf("\n");
drive->perf.lba_s = ((drive->rd_buf[offs]<<24)&0xFF000000) | ((drive->rd_buf[offs+1]<<16)&0xFF0000) |
((drive->rd_buf[offs+2]<<8)&0xFF00) | ((drive->rd_buf[offs+3])&0xFF);
offs = 8+j*desc_len+4;
drive->perf.spd_s = ((drive->rd_buf[offs]<<24)&0xFF000000) | ((drive->rd_buf[offs+1]<<16)&0xFF0000) |
((drive->rd_buf[offs+2]<<8)&0xFF00) | ((drive->rd_buf[offs+3])&0xFF);
offs = 8+j*desc_len+8;
drive->perf.lba_e = ((drive->rd_buf[offs]<<24)&0xFF000000) | ((drive->rd_buf[offs+1]<<16)&0xFF0000) |
((drive->rd_buf[offs+2]<<8)&0xFF00) | ((drive->rd_buf[offs+3])&0xFF);
offs = 8+j*desc_len+12;
drive->perf.spd_e = ((drive->rd_buf[offs]<<24)&0xFF000000) | ((drive->rd_buf[offs+1]<<16)&0xFF0000) |
((drive->rd_buf[offs+2]<<8)&0xFF00) | ((drive->rd_buf[offs+3])&0xFF);
printf("\t%dkB/s@%d -> %dkB/s@%d\n",
drive->perf.spd_s,drive->perf.lba_s,drive->perf.spd_e,drive->perf.lba_e);
}
return 0;
}
int get_write_speed(drive_info* drive) {
int offs;
mode_sense(drive, 0x2A, 00, 256);
offs=0; while (((drive->rd_buf[offs]) & 0x3F) != 0x2A) offs++;
drive->parms.write_speed_kb = swap2(drive->rd_buf+offs+28);
return 0;
}
int get_write_speed_tbl(drive_info* drive) {
int offs;
int i, spdcnt;
mode_sense(drive, 0x2A, 00, 256);
offs=0; while (((drive->rd_buf[offs]) & 0x3F) != 0x2A) offs++;
// drive->parms.write_speed_kb = swap2(drive->rd_buf+offs+28);
spdcnt = swap2(drive->rd_buf+offs+30);
for (i=0; i<speed_tbl_size;i++)
drive->parms.wr_speed_tbl_kb[i] = 0;
// printf("== Write speeds: %d\n",spdcnt);
for (i=0; (i<spdcnt) && (i<speed_tbl_size); i++) {
drive->parms.wr_speed_tbl_kb[i] = swap2(drive->rd_buf+offs+32+i*4+2);
// printf(" Speed #%02d: %d kB/s\n",i,drive->parms.wr_speed_tbl_kb[i]);
}
return 0;
}
int get_read_speed(drive_info* drive) {
int offs;
mode_sense(drive, 0x2A, 00, 256);
offs=0; while (((drive->rd_buf[offs]) & 0x3F) != 0x2A) offs++;
drive->parms.read_speed_kb = swap2(drive->rd_buf+offs+14);
return 0;
}
int set_streaming(drive_info* drive) {
char data[28]; memset(data, 0, 28);
int* start_lba = (int*)&data[4];
int* end_lba = (int*)&data[8];
int* read_size = (int*)&data[12];
int* read_time = (int*)&data[16];
int* write_size = (int*)&data[20];
int* write_time = (int*)&data[24];
read_capacity(drive);
*start_lba = swap4(0);
*end_lba = swap4(drive->media.capacity);
// *end_lba = swap4(0);
*read_time = swap4(1000);
*read_size = swap4(drive->parms.read_speed_kb);
*write_time = swap4(1000);
*write_size = swap4(drive->parms.write_speed_kb);
drive->cmd_clear();
drive->cmd[0] = MMC_SET_STREAMING;
drive->cmd[10] = 28;
if ((drive->err=drive->cmd.transport(WRITE,data,28)))
{sperror ("SET_STREAMING",drive->err); return (drive->err); }
return 0;
}
int set_cd_speed(drive_info* drive) {
int speed = 0xFFFF;
int speed_wr = 0xFFFF;
if (drive->parms.read_speed_kb) speed = drive->parms.read_speed_kb;
if (drive->parms.write_speed_kb) speed_wr = drive->parms.write_speed_kb;
drive->cmd_clear();
drive->cmd[0] = MMC_SET_SPEED;
drive->cmd[1] = 0x01;
drive->cmd[2] = (speed >> 8) & 0xFF;
drive->cmd[3] = speed & 0xFF;
// drive->cmd[4] = 0xFF;
// drive->cmd[5] = 0xFF;
drive->cmd[4] = (speed_wr >> 8) & 0xFF;
drive->cmd[5] = speed_wr & 0xFF;
if ((drive->err=drive->cmd.transport(NONE,NULL,0) )) {
// if (drive->err != 0x23A02) drive->capabilities&=(NCAP_SET_CD_SPEED);
// sperror ("SET_CD_SPEED",drive->err);
return (drive->err);
}
return 0;
}
//#define __STREAMING_PRIOR
int set_read_speed(drive_info* drive) {
int rez=0;
if ((rez = set_cd_speed(drive)))
rez = set_streaming(drive);
/*
#ifdef __STREAMING_PRIOR
if (drive->media.disc_type & DISC_CD) {
rez = set_cd_speed(drive);
} else if (drive->media.disc_type & DISC_DVD) {
{ if ((rez = set_cd_speed(drive))) rez = set_streaming(drive); }
}
#else
if ((drive->capabilities & CAP_SET_CD_SPEED) )//&& (drive->media.disc_type & DISC_CD))
{ if ((rez = set_cd_speed(drive))) rez = set_streaming(drive); }
else if (drive->capabilities & CAP_REAL_TIME_STREAMING)
{ rez = set_streaming(drive); }
#endif*/
return rez;
}
int get_media_status(drive_info* drive){
drive->cmd_clear();
drive->cmd[0]=MMC_GET_EVENT_STATUS_NOTIFICATION;
drive->cmd[1]=0x01;
drive->cmd[4]=0x10;
drive->cmd[7]=0;
drive->cmd[8]=8;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,8)))
{ sperror ("GET_EVENT_STATUS",drive->err); return (drive->err); }
if (drive->rd_buf[5] & 0x01) drive->parms.status |= STATUS_OPEN;
else drive->parms.status &= (~STATUS_OPEN);
if (drive->rd_buf[5] & 0x02) drive->parms.status |= STATUS_MEDIA_PRESENT;
else drive->parms.status &= (~STATUS_MEDIA_PRESENT);
return 0;
}
int load_eject(drive_info* drive, bool load){
drive->cmd_clear();
drive->cmd[0]=MMC_START_STOP_UNIT;
drive->cmd[4]=0x02 | load;
if ((drive->err=drive->cmd.transport(NONE,NULL,0)))
{ sperror ("LOAD_EJECT",drive->err); return (drive->err); }
return 0;
}
int get_lock(drive_info* drive){
// printf("get_lock()\n");
int offs;
if (mode_sense(drive, 0x2A, 0, 256))
{ sperror ("GET_LOCK",drive->err); return (drive->err); }
offs=0; while (((drive->rd_buf[offs]) & 0x3F) != 0x2A) offs++;
if (drive->rd_buf[offs+6] & 0x02) drive->parms.status |= STATUS_LOCK;
else drive->parms.status &= (~STATUS_LOCK);
#ifndef __PXCONTROL
printf("--- Disc %slocked\n",(drive->parms.status & STATUS_LOCK) ? "" : "UN");
#endif
return 0;
}
int set_lock(drive_info* drive){
int lock;
// printf("--- %slocking disc...\n",(drive->parms.status & STATUS_LOCK) ? "" : "UN");
if (drive->parms.status & STATUS_LOCK) lock=1; else lock=0;
drive->cmd_clear();
drive->cmd[0]=MMC_PREVENT_ALLOW_MEDIUM_REMIVAL;
drive->cmd[4]=lock;
if ((drive->err=drive->cmd.transport(NONE, NULL, 0)))
{ sperror ("SET_LOCK",drive->err); get_lock(drive); return (drive->err); }
get_lock(drive);
return 0;
}
int play_audio_msf(drive_info* drive, int beg, int end){
drive->cmd_clear();
drive->cmd[0]=MMC_PLAY_AUDIO_MSF;
drive->cmd[3]=(beg>>16) & 0xFF;
drive->cmd[4]=(beg>>8) & 0xFF;
drive->cmd[5]=beg & 0xFF;
drive->cmd[6]=(end>>16) & 0xFF;
drive->cmd[7]=(end>>8) & 0xFF;
drive->cmd[8]=end & 0xFF;
if ((drive->err=drive->cmd.transport(NONE, NULL, 0)))
{ sperror ("PLAY_AUDIO_MSF",drive->err); return (drive->err); }
return 0;
}
int play_audio(drive_info* drive, int beg, short int len){
drive->cmd_clear();
drive->cmd[0]=MMC_PLAY_AUDIO;
drive->cmd[2]=(beg>>24) & 0xFF;
drive->cmd[3]=(beg>>16) & 0xFF;
drive->cmd[4]=(beg>>8) & 0xFF;
drive->cmd[5]=beg & 0xFF;
drive->cmd[7]=(len>>8) & 0xFF;
drive->cmd[8]=len & 0xFF;
if ((drive->err=drive->cmd.transport(NONE, NULL, 0)))
{ sperror ("PLAY_AUDIO",drive->err); return (drive->err); }
return 0;
}
int seek(drive_info* drive, int lba, unsigned char flags){
drive->cmd_clear();
drive->cmd[0]=MMC_SEEK;
drive->cmd[2]=(lba>>24) & 0xFF;
drive->cmd[3]=(lba>>16) & 0xFF;
drive->cmd[4]=(lba>>8) & 0xFF;
drive->cmd[5]=lba & 0xFF;
drive->cmd[9]=flags;
if ((drive->err=drive->cmd.transport(NONE, NULL, 0)))
{ sperror ("SEEK",drive->err); return (drive->err); }
return 0;
}
int read_cd(drive_info* drive, int lba, int sector_count, unsigned char flags, unsigned char FUA) {
// int transfer_length = sector_count * 3072;
// int sect_data = 2352;
int sect_data = 3072;
int transfer_length = sector_count * sect_data;
drive->cmd_clear();
drive->cmd[0]=MMC_READ_CD;
drive->cmd[1]= FUA ? 0x08 : 0x00;
drive->cmd[2]=(lba>>24) & 0xFF;
drive->cmd[3]=(lba>>16) & 0xFF;
drive->cmd[4]=(lba>>8) & 0xFF;
drive->cmd[5]=lba & 0xFF;
drive->cmd[8]=sector_count;
drive->cmd[9]=flags;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,transfer_length)))
{ sperror ("READ_CD",drive->err); return (drive->err); }
return 0;
}
int read(drive_info* drive, int lba, int sector_count, unsigned char FUA) {
// int transfer_length = sector_count * 3072;
int transfer_length = sector_count * 2048;
drive->cmd_clear();
drive->cmd[0]=MMC_READ;
drive->cmd[1]= FUA ? 0x08 : 0x00;
drive->cmd[2]=(lba>>24) & 0xFF;
drive->cmd[3]=(lba>>16) & 0xFF;
drive->cmd[4]=(lba>>8) & 0xFF;
drive->cmd[5]=lba & 0xFF;
drive->cmd[8]=sector_count;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,transfer_length)))
{sperror ("READ",drive->err); return (drive->err);}
return 0;
}
int read_one_ecc_block(drive_info* drive, int lba) {
drive->cmd_clear();
drive->cmd[0] = MMC_READ;
drive->cmd[2] = (lba>>24) & 0xFF;
drive->cmd[3] = (lba>>16) & 0xFF;
drive->cmd[4] = (lba>>8) & 0xFF;
drive->cmd[5] = lba & 0xFF;
drive->cmd[8] = 0x10;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,0x8000)))
{sperror ("READ_ONE_ECC_BLOCK",drive->err); return (drive->err);}
// if ((drive->err=drive->cmd.transport(READ,(void*)((unsigned char*)drive->rd_buf+(0x0001<<14)),0x34)))
// {sperror ("READ_ONE_ECC_BLOCK",drive->err); return (drive->err);}
return 0;
}
int get_drive_serial_number(drive_info* drive) {
// char data[2048]; memset(data, 0, sizeof(data));
unsigned int data_length;
unsigned int length;
get_configuration(drive, FEATURE_LOGICAL_UNIT_SERIAL_NUMBER, &data_length, NULL);
length = drive->rd_buf[11]; drive->rd_buf[12+length]=0;
if (data_length>8) strncpy(drive->serial, (char*)drive->rd_buf+12, 16);
else drive->serial[0]=0;
return 1;
}
int read_buffer_capacity(drive_info* drive){
if (mode_sense(drive, 0x2A, 0, 192)) return 1;
drive->buffer_size=((drive->rd_buf[20] & 0xFF) << 8 ) | (drive->rd_buf[21] & 0xFF);
printf("Buffer capacity: 0x%04X (%d)KB\n", drive->buffer_size, drive->buffer_size);
return 0;
}
int read_writer_info(drive_info* drive)
{
if (!(drive->media.disc_type & (DISC_DVDminusR | DISC_DVDminusRWS | DISC_DVDminusRWR))) {
strcpy(drive->media.writer, "n/a (only for DVD-R(W))");
return 1;
}
char format=0x0D;
drive->media.writer[0]=0;
drive->rd_buf[8]=0;
drive->cmd_clear();
drive->cmd[0]=MMC_READ_DVD_STRUCTURE;
drive->cmd[5]=0x62;
drive->cmd[7]=format;
drive->cmd[8]=8;
drive->cmd[9]=8;
if ((drive->err = drive->cmd.transport(READ,drive->rd_buf,2056)) || (!drive->rd_buf[8])) {
printf("Read Writer Info Method 1 failed\n");
drive->cmd_clear();
drive->cmd[0]=MMC_READ_DVD_STRUCTURE;
drive->cmd[5]=0x02;
drive->cmd[7]=format;
drive->cmd[8]=8;
drive->cmd[9]=8;
if ((drive->err=drive->cmd.transport(READ,drive->rd_buf,2056))) {
printf("Read Writer Info Method 2 failed\n");
return 1;
}
}
for (int k=0;k<0x3F;k++) {
if (!drive->rd_buf[8+k]) drive->rd_buf[8+k]=0x20;
}
strncpy(drive->media.writer, (char*)drive->rd_buf+8, 0x3F);
remove_double_spaces(drive->media.writer);
// remove_end_spaces(drive->media.writer);
return 0;
}
int detect_mm_capabilities(drive_info* drive){
char len;
int offs;
int i,j;
if (mode_sense(drive, 0x2A, 0, 256)) return 1;
offs=0; while (((drive->rd_buf[offs]) & 0x3F) != 0x2A) offs++;
len=drive->rd_buf[offs+1];
if (!drive->silent) printf("CD parameters page length: 0x%02X\n",len);
if (len >= 28) {drive->mmc=3;}
else if (len >= 24) {drive->mmc=2;}
else {drive->mmc=1;}
if (!drive->silent) for (i=offs; i<(offs+len+2);i+=8){
for (j=0;j<8;j++) printf(" %02X",drive->rd_buf[i+j] & 0xFF);
printf("\n");
}
// if (drive->mmc) drive->rd_capabilities|=DEVICE_CD_ROM;
if (drive->rd_buf[offs+2] & 0x01)drive->rd_capabilities|=DEVICE_CD_R;
if (drive->rd_buf[offs+2] & 0x02)drive->rd_capabilities|=DEVICE_CD_RW;
if (drive->rd_buf[offs+3] & 0x01)drive->wr_capabilities|=DEVICE_CD_R;
if (drive->rd_buf[offs+3] & 0x02)drive->wr_capabilities|=DEVICE_CD_RW;
if (drive->rd_buf[offs+3] & 0x04)drive->capabilities|=CAP_TEST_WRITE;
if (drive->rd_buf[offs+4] & 0x01)drive->capabilities|=CAP_CD_AUDIO;
if (drive->rd_buf[offs+4] & 0x02)drive->capabilities|=CAP_COMPOSITE;
if (drive->rd_buf[offs+4] & 0x04)drive->capabilities|=CAP_DIGITAL_PORT_1;
if (drive->rd_buf[offs+4] & 0x08)drive->capabilities|=CAP_DIGITAL_PORT_2;
if (drive->rd_buf[offs+4] & 0x10)drive->capabilities|=CAP_MODE2_FORM1;
if (drive->rd_buf[offs+4] & 0x20)drive->capabilities|=CAP_MODE2_FORM2;
if (drive->rd_buf[offs+4] & 0x40)drive->capabilities|=CAP_MULTISESSION;
if (drive->rd_buf[offs+5] & 0x01)drive->capabilities|=CAP_DAE;
if (drive->rd_buf[offs+5] & 0x02)drive->capabilities|=CAP_ACCURATE_STREAM;
if (drive->rd_buf[offs+5] & 0x10)drive->capabilities|=CAP_C2;
if (drive->rd_buf[offs+5] & 0x20)drive->capabilities|=CAP_ISRC;
if (drive->rd_buf[offs+5] & 0x40)drive->capabilities|=CAP_UPC;
if (drive->rd_buf[offs+5] & 0x80)drive->capabilities|=CAP_READ_BAR_CODE;
if (drive->rd_buf[offs+6] & 0x01)drive->capabilities|=CAP_LOCK;
if (drive->rd_buf[offs+6] & 0x08)drive->capabilities|=CAP_EJECT;
drive->loader_id = (drive->rd_buf[offs+6] >> 5) & 0x07;
if (drive->rd_buf[offs+7] & 0x10)drive->capabilities|=CAP_SIDE_CHANGE;
switch (drive->mmc) {
case 3:
drive->parms.write_speed_kb=drive->rd_buf[37] << 8 | drive->rd_buf[36];
case 2:
if (drive->rd_buf[offs+2] & 0x08)drive->rd_capabilities|=DEVICE_DVD_ROM;
if (drive->rd_buf[offs+2] & 0x10)drive->rd_capabilities|=DEVICE_DVD_R;
if (drive->rd_buf[offs+2] & 0x20)drive->rd_capabilities|=DEVICE_DVD_RAM;
if (drive->rd_buf[offs+3] & 0x10)drive->wr_capabilities|=DEVICE_DVD_R;
if (drive->rd_buf[offs+3] & 0x20)drive->wr_capabilities|=DEVICE_DVD_RAM;
// break;
case 1:
drive->parms.max_read_speed_kb=drive->rd_buf[offs+9] <<8 | drive->rd_buf[offs+8];
drive->parms.read_speed_kb=drive->rd_buf[offs+15] <<8 | drive->rd_buf[offs+14];
drive->parms.max_write_speed_kb=drive->rd_buf[offs+19] <<8 | drive->rd_buf[offs+19];
drive->parms.write_speed_kb=drive->rd_buf[offs+21] << 8 | drive->rd_buf[offs+20];
break;
}
if (!drive->silent) printf("Max speeds:\tR@%dKBps / W@%dKBps\nCurrent speeds:\tR@%dKBps / W@%dKBps\n",
drive->parms.max_read_speed_kb, drive->parms.max_write_speed_kb,
drive->parms.read_speed_kb, drive->parms.write_speed_kb);
return 0;
}
int convert_to_ID (drive_info* drive) {
if (!strncmp(drive->ven,"PLEXTOR ",8)) {
drive->ven_ID=WR_PLEXTOR;
if(!strncmp(drive->dev,"CD-R PREMIUM",14))
drive->dev_ID=PLEXTOR_PREMIUM;
else
if(!strncmp(drive->dev,"DVD-ROM PX-130",14))
{ drive->ven_ID=RD_BENQ;
drive->dev_ID=BENQ_DV1650V;}
else
if(!strncmp(drive->dev,"DVDR PX-708A2",15))
drive->dev_ID=PLEXTOR_708A2;
else
if(!strncmp(drive->dev,"DVDR PX-712",13))
drive->dev_ID=PLEXTOR_712;
else
if(!strncmp(drive->dev,"DVDR PX-714",13))
drive->dev_ID=PLEXTOR_716;
else
if(!strncmp(drive->dev,"DVDR PX-716",13))
drive->dev_ID=PLEXTOR_716;
else
if(!strncmp(drive->dev,"DVDR PX-740",13))
{ drive->ven_ID=WR_BENQ;
drive->dev_ID=BENQ_DW1640;}
else
/* if(!strncmp(drive->dev,"DVDR PX-750",13))
else*/
if(!strncmp(drive->dev,"DVDR PX-755",13))
drive->dev_ID=PLEXTOR_760;
else
if(!strncmp(drive->dev,"DVDR PX-760",13))
drive->dev_ID=PLEXTOR_760;
else
drive->dev_ID=PLEXTOR_OLD;
// { drive->ven_ID = WR_GENERIC; drive->dev_ID = 0; }
}
else if (!strncmp(drive->ven,"PIONEER ",8)) {
drive->ven_ID=WR_PIONEER;
if(!strncmp(drive->dev,"DVD-RW DVR-106",15))
drive->dev_ID=PIO_DVR_106;
else
if(!strncmp(drive->dev,"DVD-RW DVR-107",15))
drive->dev_ID=PIO_DVR_107;
else
if(!strncmp(drive->dev,"DVD-RW DVR-108",15))
drive->dev_ID=PIO_DVR_108;
else
if(!strncmp(drive->dev,"DVD-RW DVR-109",15))
drive->dev_ID=PIO_DVR_109;
else
if(!strncmp(drive->dev,"DVD-RW DVR-110",15))
drive->dev_ID=PIO_DVR_110;
else
if(!strncmp(drive->dev,"DVD-RW DVR-111",15))
drive->dev_ID=PIO_DVR_111;
else
drive->dev_ID=PIO_OLD;
// { drive->ven_ID = WR_GENERIC; drive->dev_ID = 0; }
}
else if (!strncmp(drive->ven,"ASUS ",8)) {
drive->ven_ID=WR_PIONEER;
if(!strncmp(drive->dev,"DRW-0402P",9))
drive->dev_ID=PIO_DVR_106;
else
if(!strncmp(drive->dev,"DRW-0804P",9))
drive->dev_ID=PIO_DVR_107;
else
if(!strncmp(drive->dev,"DRW-1604P",9))
drive->dev_ID=PIO_DVR_108;
else
if(!strncmp(drive->dev,"DRW-1608P ",10))
drive->dev_ID=PIO_DVR_109;
else
if(!strncmp(drive->dev,"DRW-1608P2",10))
drive->dev_ID=PIO_DVR_110;
else
if(!strncmp(drive->dev,"DRW-1608P3",10))
drive->dev_ID=PIO_DVR_111;
else
drive->dev_ID=PIO_OLD;
}
else if (!strncmp(drive->ven,"_NEC ",8)) {
drive->ven_ID=WR_NEC;
if(!strncmp(drive->dev,"DVD_RW ND-352",13))
drive->dev_ID=NEC_3520;
else
if(!strncmp(drive->dev,"DVD_RW ND-353",13))
drive->dev_ID=NEC_3530;
else
if(!strncmp(drive->dev,"DVD_RW ND-354",13))
drive->dev_ID=NEC_3540;
else
if(!strncmp(drive->dev,"DVD_RW ND-355",13))
drive->dev_ID=NEC_4550;
else
if(!strncmp(drive->dev,"DVD_RW ND-357",13))
drive->dev_ID=NEC_4570;
else
if(!strncmp(drive->dev,"DVD_RW ND-365",13))
drive->dev_ID=NEC_4650;
else
if(!strncmp(drive->dev,"DVD_RW ND-455",13))
drive->dev_ID=NEC_4550;
else
if(!strncmp(drive->dev,"DVD_RW ND-457",13))
drive->dev_ID=NEC_4570;
else
if(!strncmp(drive->dev,"DVD_RW ND-465",13))
drive->dev_ID=NEC_4650;
else
drive->dev_ID=NEC_OLD;
// { drive->ven_ID = WR_GENERIC; drive->dev_ID = 0; }
}
else if (!strncmp(drive->ven,"LITE-ON ",8)) {
drive->ven_ID=WR_LITEON;
if(!strncmp(drive->dev,"LTR-52327S",10))
drive->dev_ID=LTN_LTR_52327;
else
if(!strncmp(drive->dev,"DVDRW SOHW-811S",14))
drive->dev_ID=LTN_SOHW_811S;
else
if(!strncmp(drive->dev,"DVDRW SOHW-812S",14))
drive->dev_ID=LTN_SOHW_812S;
else
if(!strncmp(drive->dev,"DVDRW SOHW-832S",14))
drive->dev_ID=LTN_SOHW_832S;
else
if(!strncmp(drive->dev,"DVDRW SOHW-1653S",15))
drive->dev_ID=LTN_SOHW_1653S;
else
if(!strncmp(drive->dev,"DVDRW SOHW-1673S",15))
drive->dev_ID=LTN_SOHW_1673S;
else
if(!strncmp(drive->dev,"DVDRW SOHW-1693S",15))
drive->dev_ID=LTN_SOHW_1693S;
else
if(!strncmp(drive->dev,"DVDRW SHW-1635S",14))
drive->dev_ID=LTN_SHW_1635S;
else
drive->dev_ID=LTN_OLD;
}
else if (!strncmp(drive->ven,"BENQ ",8)) {
drive->ven_ID=WR_BENQ;
if(!strncmp(drive->dev,"DVD DD DW1620",13))
drive->dev_ID=BENQ_DW1620;
else
if(!strncmp(drive->dev,"DVD DD DW1640",13))
drive->dev_ID=BENQ_DW1640;
else
drive->dev_ID=BENQ_OLD;
}
else if (!strncmp(drive->ven,"TEAC ",8)) {
// if(!strncmp(drive->dev,"DW-552GA",8))
if(!strncmp(drive->dev,"DV-W50D",7)) {
drive->ven_ID=WR_PIONEER;
drive->dev_ID=PIO_DVR_106;
} else
if(!strncmp(drive->dev,"DV-W58D",7)) {
drive->ven_ID=WR_PIONEER;
drive->dev_ID=PIO_DVR_107;
} else
if(!strncmp(drive->dev,"DV-W516D",8)) {
drive->ven_ID=WR_PIONEER;
drive->dev_ID=PIO_DVR_108;
} else
if(!strncmp(drive->dev,"DV-W58G",7)) {
drive->ven_ID=WR_LITEON;
drive->dev_ID=LTN_SOHW_811S;
} else
if(!strncmp(drive->dev,"DV-W58G-A",9)) {
drive->ven_ID=WR_LITEON;
drive->dev_ID=LTN_SOHW_812S;
} else {
drive->ven_ID = WR_GENERIC;
drive->dev_ID = 0;
}
}
else if (!strncmp(drive->ven,"SONY ",8)) {
drive->ven_ID=WR_LITEON;
if(!strncmp(drive->dev,"DVD RW DRU-700A",15))
drive->dev_ID=LTN_SOHW_832S;
else
drive->dev_ID=LTN_OLD;
}
else { drive->ven_ID = WR_GENERIC; drive->dev_ID = 0; }
return 0;
}
int detect_check_capabilities(drive_info* drive){
drive->chk_features=0;
switch (drive->ven_ID) {
case WR_PLEXTOR:
switch (drive->dev_ID) {
case PLEXTOR_760:
case PLEXTOR_716:
drive->chk_features|=CHK_TA;
case PLEXTOR_712:
case PLEXTOR_708A2:
drive->chk_features|=CHK_JB_DVD;
drive->chk_features|=CHK_PI;
drive->chk_features|=CHK_PO;
case PLEXTOR_PREMIUM:
drive->chk_features|=CHK_JB_CD;
drive->chk_features|=CHK_CX;
drive->chk_features|=CHK_FETE;
}
break;
case WR_PIONEER:
drive->chk_features|=CHK_CX;
if (drive->rd_capabilities & DEVICE_DVD) {
drive->chk_features|=CHK_PIE;
// drive->chk_features|=CHK_PIF;
}
break;
case WR_NEC:
drive->chk_features|=CHK_CX;
if (drive->rd_capabilities & DEVICE_DVD) {
drive->chk_features|=CHK_PIE;
drive->chk_features|=CHK_PIF;
}
break;
case WR_LITEON:
drive->chk_features|=CHK_CX;
// drive->chk_features|=CHK_JB_CD;
if (drive->rd_capabilities & DEVICE_DVD) {
drive->chk_features|=CHK_PIE;
// drive->chk_features|=CHK_PIF;
// drive->chk_features|=CHK_JB_DVD;
}
break;
case RD_BENQ:
drive->chk_features|=CHK_CX;
drive->chk_features|=CHK_JB_CD;
if (drive->rd_capabilities & DEVICE_DVD) {
drive->chk_features|=CHK_PIE;
// drive->chk_features|=CHK_PIF;
drive->chk_features|=CHK_JB_DVD;
}
break;
case WR_BENQ:
drive->chk_features|=CHK_CX;
// drive->chk_features|=CHK_JB_CD;
if (drive->rd_capabilities & DEVICE_DVD) {
drive->chk_features|=CHK_PIE;
// drive->chk_features|=CHK_PIF;
// drive->chk_features|=CHK_JB_DVD;
}
break;
case WR_GENERIC:
if (drive->capabilities | CAP_C2)
drive->chk_features|=CHK_CX;
break;
default:
break;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1