/*
 * This file is part of the QPxTool project.
 * Copyright (C) 2005-2006 Gennady "ShultZ" Kozlov <qpxtool@mail.ru>
 *
 *
 * Some Plextor commands got from PxScan and CDVDlib (C) Alexander Noe`
 *
 *
 * 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 <stdlib.h>

#include <qpx_mmc.h>
#include <plextor_features.h>

#include <version.h>


const	unsigned int	FL_HELP			= 0x00000001;
const	unsigned int	FL_SCAN			= 0x00000002;
const	unsigned int	FL_DEVICE		= 0x00000004;
const	unsigned int	FL_CURRENT		= 0x00000008;

const	unsigned int	FL_SUPPORTED		= 0x00000010;
const	unsigned int	FL_LOCK			= 0x00000020;
const	unsigned int	FL_POWEREC		= 0x00000040;
const	unsigned int	FL_GIGAREC		= 0x00000080;

const	unsigned int	FL_VARIREC_CD		= 0x00000100;
const	unsigned int	FL_VARIREC_CD_OFF	= 0x00000200;
const	unsigned int	FL_VARIREC_DVD		= 0x00000400;
const	unsigned int	FL_VARIREC_DVD_OFF	= 0x00000800;

const	unsigned int	FL_HCDR			= 0x00001000;
const	unsigned int	FL_SSS			= 0x00002000;
const	unsigned int	FL_SPDREAD		= 0x00004000;
const	unsigned int	FL_BOOK_R		= 0x00008000;

const	unsigned int	FL_BOOK_RDL		= 0x00010000;
const	unsigned int	FL_TESTWRITE		= 0x00020000;
const	unsigned int	FL_SILENT		= 0x00040000;
const	unsigned int	FL_AS			= 0x00080000;

const	unsigned int	FL_PXERASER		= 0x00100000;
const	unsigned int	FL_SECUREC		= 0x00200000;
const	unsigned int	FL_NOSECUREC		= 0x00400000;
const	unsigned int	FL_VERBOSE		= 0x00800000;


	unsigned int	flags = 0;

int scanbus()
{
	drive_info*	drive;

	int	i, inq;
	int	drvcnt=0;
	char	device[32]="";
 	printf("** scaning IDE/SCSI bus...\n");
	for (i=0; i<_devcnt; i++) {
		strcpy(device,_devtbl[i]);
		drive = new drive_info(device);
//		inq = (*__inquiry)(drive);
		inq = inquiry(drive);
		switch (inq) {
			case 0x00:
				convert_to_ID(drive);
//				strcpy(drvtbl[drvcnt],_devtbl[i]);
				printf("%s [%02d]  %s: %s %s %s\n",(drive->ven_ID == WR_PLEXTOR) ? "*" : " ",
					drvcnt, drive->device, drive->ven, drive->dev, drive->fw);
				drvcnt++;
				break;
			case ERR_NO_DEV:
//				printf("%s: no device found\n",drive->device);
				break;
			case ERR_NO_SCSI:
//				printf("%s: not a valid SCSI device\n",drive->device);
				break;
			case ERR_NO_MMC:
				printf("%s: %s %s %s",drive->device,drive->ven,drive->dev,drive->fw);
				printf(": device is not MMC compliant\n");
				break;
			default:
				printf("%s: ???\n",drive->device);
				break;
			}
		delete drive;
	}
	printf("** Scan compleete: %d device(s) found\n", drvcnt);
	return (drvcnt);
}

int get_device_info(drive_info* drive)
{
	drive->ven_features=0;
	drive->chk_features=0;
	detect_capabilities(drive);
	detect_check_capabilities(drive);
	determine_disc_type(drive);
	if ((drive->ven_ID != WR_PLEXTOR)) {
		printf ("%s: drive not supported\n", drive->device);
		return 1;
	}
	if ((drive->dev_ID == PLEXTOR_760)) px755_do_auth(drive);
	if (!plextor_get_hidecdr_singlesession(drive)) drive->ven_features|=PX_HCDRSS;
	if (!plextor_get_speedread(drive)) drive->ven_features|=PX_SPDREAD;
	if (drive->wr_capabilities) {
		if (!plextor_get_powerec(drive)) {
			drive->ven_features|=PX_POWEREC;
//			plextor_get_speeds(drive);
		}
		if (!plextor_get_gigarec(drive)) drive->ven_features|=PX_GIGAREC;
		if (!plextor_get_varirec(drive, VARIREC_CD)) drive->ven_features|=PX_VARIREC_CD;
//		if (!plextor_get_securec(drive)) drive->ven_features|=PX_SECUREC;
		if (!plextor_get_silentmode(drive)) drive->ven_features|=PX_SILENT;
		if (!plextor_get_securec_state(drive)) drive->ven_features|=PX_SECUREC;
	}
	if (drive->wr_capabilities & DEVICE_DVD) {
		if (!plextor_get_varirec(drive, VARIREC_DVD)) drive->ven_features|=PX_VARIREC_DVD;
		if (!plextor_get_bitset(drive, PLEX_BITSET_R)) drive->ven_features|=PX_BITSET_R;
		if (!plextor_get_bitset(drive, PLEX_BITSET_RDL)) drive->ven_features|=PX_BITSET_RDL;
		if (!plextor_get_autostrategy(drive)) drive->ven_features|=PX_ASTRATEGY;
		if (!plextor_get_testwrite_dvdplus(drive)) drive->ven_features|=PX_SIMUL_PLUS;
	}
	if (drive->dev_ID == PLEXTOR_760) drive->ven_features|=PX_ERASER;

//	printf("Trying opcode E9 modes...\n");
//	for (int i=0; i<256; i++) {if (!plextor_get_mode(drive,i)) printf(" MODE 0x%02X\n",i);}


//	printf("Trying opcode ED modes...\n");
//	for (int i=0; i<256; i++) {if (!plextor_get_mode2(drive,i)) printf(" MODE 0x%02X\n",i);}


 	if (flags & FL_SUPPORTED) {
//		printf("____________________________\n");
		printf("\n** Supported features:\n");
		printf("Hide CD-R           : %s\n", drive->ven_features & PX_HCDRSS ? "YES" : "---");
		printf("SingleSession       : %s\n", drive->ven_features & PX_HCDRSS ? "YES" : "---");
		printf("SpeedRead           : %s\n", drive->ven_features & PX_SPDREAD ? "YES" : "---");
		printf("PoweRec             : %s\n", drive->ven_features & PX_POWEREC ? "YES" : "---");
		printf("GigaRec             : %s\n", drive->ven_features & PX_GIGAREC ? "YES" : "---");
		printf("VariRec CD          : %s\n", drive->ven_features & PX_VARIREC_CD ? "YES" : "---");
		printf("VariRec DVD         : %s\n", drive->ven_features & PX_VARIREC_DVD ? "YES" : "---");
		printf("SecuRec             : %s\n", drive->ven_features & PX_SECUREC ? "YES" : "---");
		printf("Silent mode         : %s\n", drive->ven_features & PX_SILENT ? "YES" : "---");
		printf("DVD+R bitsetting    : %s\n", drive->ven_features & PX_BITSET_R ? "YES" : "---");
		printf("DVD+R DL bitsetting : %s\n", drive->ven_features & PX_BITSET_RDL ? "YES" : "---");
		printf("DVD+R(W) testwrite  : %s\n", drive->ven_features & PX_SIMUL_PLUS ? "YES" : "---");
		printf("AutoStrategy        : %s%s\n",
			drive->ven_features & PX_ASTRATEGY ? "YES" : "---",
			(drive->ven_features & PX_ASTRATEGY) && (drive->dev_ID == PLEXTOR_760) ? " (EXTENDED)" : "");
		printf("PlexEraser          : %s\n", drive->ven_features & PX_ERASER ? "YES" : "---");
	}


//	get_media_info(drive);
//	if (drive->rd_capabilities & DEVICE_DVD) {

	if (flags & FL_CURRENT) {
//		printf("____________________________\n");
		printf("\n** Current drive settings:\n");
	}
	if ((drive->capabilities & CAP_LOCK)      && (flags & FL_CURRENT))
		{ get_lock(drive);
		printf("Lock state          : %s\n", (drive->parms.status & STATUS_LOCK) ? "ON":"OFF"); }
	if ((drive->ven_features & PX_HCDRSS)      && ((flags & FL_CURRENT) || (flags & FL_HCDR)))
		printf("Hide-CDR state      : %s\n", drive->plextor.hcdr ? "ON":"OFF");
	if ((drive->ven_features & PX_HCDRSS)      && ((flags & FL_CURRENT) || (flags & FL_SSS)))
		printf("SingleSession state : %s\n", drive->plextor.sss ? "ON":"OFF");
	if ((drive->ven_features & PX_SPDREAD)     && ((flags & FL_CURRENT) || (flags & FL_SPDREAD)))
		printf("SpdREAD state       : %s\n", drive->plextor.spdread ? "ON":"OFF");
	if ((drive->ven_features & PX_POWEREC)     && ((flags & FL_CURRENT) || (flags & FL_POWEREC))) {
		printf("PoweREC state       : %s\n", drive->plextor.powerec_state ? "ON":"OFF");
		if (drive->media.disc_type & DISC_CD)
			printf("      PoweREC Speed : %dX (CD)\n",drive->plextor.powerec_spd / 176);
		if (drive->media.disc_type & DISC_DVD)
			printf("      PoweREC Speed : %dX (DVD)\n",drive->plextor.powerec_spd / 1385);
//		show_powerec_speed();
	}
	if ((drive->ven_features & PX_GIGAREC)     && ((flags & FL_CURRENT) || (flags & FL_GIGAREC)))
		print_gigarec_value(drive);
	if ((drive->ven_features & PX_VARIREC_CD)  && ((flags & FL_CURRENT) || (flags & FL_VARIREC_CD)))
		{ printf("VariREC CD state    : %s\n", drive->plextor.varirec_state_cd ? "ON":"OFF");
		if (drive->plextor.varirec_state_cd) print_varirec(drive, VARIREC_CD); }
	if ((drive->ven_features & PX_VARIREC_DVD) && ((flags & FL_CURRENT) || (flags & FL_VARIREC_DVD)))
		{ printf("VariREC DVD state   : %s\n", drive->plextor.varirec_state_dvd ? "ON":"OFF");
		if (drive->plextor.varirec_state_dvd) print_varirec(drive, VARIREC_DVD); }
	if ((drive->ven_features & PX_SECUREC)     && ((flags & FL_CURRENT) || (flags & FL_SECUREC)))
		printf("SecuRec state       : %s\n", drive->plextor.securec ? "ON":"OFF");
	if ((drive->ven_features & PX_SILENT)      && ((flags & FL_CURRENT) || (flags & FL_SILENT)))
		{ printf("Silent mode         : %s\n",drive->plextor_silent.state ? "ON":"OFF");
		if (drive->plextor_silent.state) plextor_print_silentmode_state(drive); }
	if ((drive->ven_features & PX_BITSET_R)    && ((flags & FL_CURRENT) || (flags & FL_BOOK_R)))
		printf("DVD+R bitsetting    : %s\n", drive->book_plus_r ? "ON":"OFF");
	if ((drive->ven_features & PX_BITSET_RDL)  && ((flags & FL_CURRENT) || (flags & FL_BOOK_RDL)))
		printf("DVD+R DL bistetting : %s\n", drive->book_plus_rdl ? "ON":"OFF");
	if ((drive->ven_features & PX_SIMUL_PLUS)  && ((flags & FL_CURRENT) || (flags & FL_TESTWRITE)))
		printf("DVD+R(W) testwrite  : %s\n", drive->plextor.testwrite_dvdplus ? "ON":"OFF");
	if ((drive->ven_features & PX_ASTRATEGY)   && ((flags & FL_CURRENT) || (flags & FL_AS)))
		plextor_print_autostrategy_state(drive);
	return 0;
}

void usage(char* bin) {
	fprintf (stderr,"\nusage: %s [optinos]\n",bin);
	printf("\t-d <device>                  use this device\n");
	printf("\t--scan, -l                   list drives (scan IDE/SCSI bus)\n");
	printf("\t--help, -h                   show help\n");
	printf("\t--current, -c                show current drive settings\n");
	printf("\t--supported, -s              show supported features\n");
	printf("\t--lock [on|off]              lock/unlock disc in drive\n");
	printf("\t--spdread [on|off]           turn SpeedRead on/off (default: off)\n");
	printf("\t--sss [on|off]               turn SingleSession on/off (default: off)\n");
	printf("\t--hcdr [on|off]              turn Hide-CDR on/off (default: off)\n");
	printf("\t--powerec [on|off]           turn PoweREC on/off (default: on)\n");
	printf("\t--gigarec <state>            set GigaREC rate or turn it off\n");
	printf("\t                             values: 0.6, 0.7, 0.8, 0.9, 1.1, 1.2, 1.3, 1.4, off\n");
	printf("\t--varirec-cd <pwr>           set VariREC power for CD or turn VariREC off\n");
	printf("\t                             values: +4, +3, +2, +1, 0, -1, -2, -3, -4, off\n");
	printf("\t--varirec-cd-strategy <str>  set VariREC strategy for CD\n");
	printf("\t                             values: default, azo, cya, pha, phb, phc, phd\n");
	printf("\t--varirec-dvd <pwr>          set VariREC power for DVD or turn VariREC off\n");
	printf("\t                             values: +4, +3, +2, +1, 0, -1, -2, -3, -4, off\n");
	printf("\t--varirec-dvd-strategy <str> set VariREC strategy for DVD\n");
	printf("\t                             values: default, 0, 1, 2, 3, 4, 5, 6, 7\n");
	printf("\t--securec <passwd>           set SecuREC password and turn it on\n");
	printf("\t                             passwd must be 4..10 characters length\n");
	printf("\t--nosecurec                  turn SecuRec off\n");
	printf("\t--bitset+r [on|off]          turn on/off setting DVD-ROM book on DVD+R media\n");
	printf("\t--bitset+rdl [on|off]        turn on/off setting DVD-ROM book on DVD+R DL media\n");
	printf("\t--as [forced|auto|on|off]    select AutoStrategy mode\n");
	printf("\t--dvd+testwrite [on|off]     turn on/off testwrite on DVD-PLUS media\n");
	printf("\t--silent [on|off]            just turm Silent Mode on/off (default: on)\n");
	printf("\t--sm-nosave                  don't save Silent Mode settings to NVRAM\n");
	printf("\t--sm-cd-rd <spd>             set max CD READ speed (default: 32X)\n");
	printf("\t                             values: 4, 8, 24, 32, 40, 48\n");
	printf("\t--sm-cd-wr <spd>             set max CD WRITE speed (default: 32X)\n");
	printf("\t                             values: 4, 8, 16, 24, 32, 48\n");
	printf("\t--sm-dvd-rd <spd>            set max DVD READ speed (default: 12X)\n");
	printf("\t                             values: 2, 5, 8, 12, 16\n");
	printf("\t--sm-dvd-wr <spd>            set max DVD WRITE speed (default: 8X)\n");
	printf("\t                             values: 4, 6, 8, 12, 16\n");
	printf("\t--sm-load <spd>              set tray load speed. spd can be 0 to 80 (default: 63)\n");
	printf("\t--sm-eject <spd>             set tray eject speed. spd can be 0 to 80 (default: 0)\n");
	printf("\t--sm-access <slow|fast>      set access time, has effect only with CD/DVD speed setting\n");
	printf("\t--PlexEraser <quick|full>    WARNING! data on inserted CD-R/DVD-R will be lost! (PX-755/PX-760 only)\n");
	printf("\t--verbose, -v                be verbose\n");
}

int main (int argc, char* argv[])
{
	int	i;
	int	drvcnt=0;
	char	device[32]="";
	drive_info* drive;

	int	lock = 0;
	int	powerec = 1;
	int	gigarec = GIGAREC_10;
	int	varirec_cd_pwr  = VARIREC_NULL;
	int	varirec_cd_str  = 0;
	int	varirec_dvd_pwr = VARIREC_NULL;
	int	varirec_dvd_str = 0;
	int	hcdr = 1;
	int	sss = 1;
	int	spdread = 1;
	int	bookr = 1;
	int	bookrdl = 1;
	int	testwrite = 1;
	int	as = AS_AUTO;
	int	silent = 1;
	int	silent_load = 63;
	int	silent_eject = 0;
	int	silent_access = SILENT_ACCESS_FAST;
	int	silent_cd_rd = SILENT_CD_RD_32X;
	int	silent_cd_wr = SILENT_CD_WR_32X;
	int	silent_dvd_rd = SILENT_DVD_RD_12X;
	int	silent_dvd_wr = SILENT_DVD_WR_8X;
	int	silent_cd = 0;
	int	silent_dvd = 0;
	int	silent_tray = 0;
	int	silent_save = 1;
	int	pxeraser = 0;
	char	passwd[256];

	printf("**  PxControl  v%s    (c)  Gennady \"ShultZ\" Kozlov  **\n", VERSION);

//	printf("Parsing commandline options (%d args)...\n",argc-1);
	for (i=1; i<argc; i++) {
//		printf("arg[%02d]: %s\n",i,argv[i]);
		if     (!strcmp(argv[i],"-h")) flags |= FL_HELP;
		else if(!strcmp(argv[i],"--help")) flags |= FL_HELP;
		else if(!strcmp(argv[i],"-c")) flags |= FL_CURRENT;
		else if(!strcmp(argv[i],"--current")) flags |= FL_CURRENT;
		else if(!strcmp(argv[i],"-s")) flags |= FL_SUPPORTED;
		else if(!strcmp(argv[i],"--supported")) flags |= FL_SUPPORTED;
		else if(!strcmp(argv[i],"-l")) flags |= FL_SCAN;
		else if(!strcmp(argv[i],"--scan")) flags |= FL_SCAN;
		else if(!strcmp(argv[i],"-d")) {
			if (argc>(i+1)) {
				i++;
				flags |= FL_DEVICE;
				strcpy(device, argv[i]);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
//  ************   Lock
		else if(!strcmp(argv[i],"--lock")) {
			flags |= FL_LOCK;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) lock = 0;
				else if (!strcmp(argv[i],"on")) lock = 1;
			}
		}
		else if(!strcmp(argv[i],"--spdread")) {
			flags |= FL_SPDREAD;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) spdread = 0;
				else if (!strcmp(argv[i],"on")) spdread = 1;
			}
		}
		else if(!strcmp(argv[i],"--sss")) {
			flags |= FL_SSS;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) sss = 0;
				else if (!strcmp(argv[i],"on")) sss = 1;
			}
		}
		else if(!strcmp(argv[i],"--hcdr")) {
			flags |= FL_HCDR;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) hcdr = 0;
				else if (!strcmp(argv[i],"on")) hcdr = 1;
			}
		}
//  ************   PoweREC
		else if(!strcmp(argv[i],"--powerec")) {
			flags |= FL_POWEREC;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) powerec = 0;
				else if (!strcmp(argv[i],"on")) powerec = 1;
			}
		}
//  ************   GigaREC
		else if(!strcmp(argv[i],"--gigarec")) {
			if (argc>(i+1)) {
				i++;
				flags |= FL_GIGAREC;
				if      (!strcmp(argv[i],"0.6")) gigarec = GIGAREC_06;
				else if (!strcmp(argv[i],"0.7")) gigarec = GIGAREC_07;
				else if (!strcmp(argv[i],"0.8")) gigarec = GIGAREC_08;
				else if (!strcmp(argv[i],"0.9")) gigarec = GIGAREC_09;
				else if (!strcmp(argv[i],"1.0")) gigarec = GIGAREC_10;
				else if (!strcmp(argv[i],"off")) gigarec = GIGAREC_10;
				else if (!strcmp(argv[i],"1.1")) gigarec = GIGAREC_11;
				else if (!strcmp(argv[i],"1.2")) gigarec = GIGAREC_12;
				else if (!strcmp(argv[i],"1.3")) gigarec = GIGAREC_13;
				else if (!strcmp(argv[i],"1.4")) gigarec = GIGAREC_14;
				else {
					printf("Illegal GigaREC value: %s\n", argv[i]);
				}
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
//  ************   VariREC  CD
		else if(!strcmp(argv[i],"--varirec-cd")) {
			if (argc>(i+1)) {
				i++;
				flags |= FL_VARIREC_CD;
				if      (!strcmp(argv[i],"+4")) varirec_cd_pwr = VARIREC_PLUS_4;
				else if (!strcmp(argv[i],"+3")) varirec_cd_pwr = VARIREC_PLUS_3;
				else if (!strcmp(argv[i],"+2")) varirec_cd_pwr = VARIREC_PLUS_2;
				else if (!strcmp(argv[i],"+1")) varirec_cd_pwr = VARIREC_PLUS_1;
				else if (!strcmp(argv[i],"0"))  varirec_cd_pwr = VARIREC_NULL;
				else if (!strcmp(argv[i],"-1")) varirec_cd_pwr = VARIREC_MINUS_1;
				else if (!strcmp(argv[i],"-2")) varirec_cd_pwr = VARIREC_MINUS_2;
				else if (!strcmp(argv[i],"-3")) varirec_cd_pwr = VARIREC_MINUS_3;
				else if (!strcmp(argv[i],"-4")) varirec_cd_pwr = VARIREC_MINUS_4;
				else if (!strcmp(argv[i],"off")) flags |= FL_VARIREC_CD_OFF;
				else {
					printf("Illegal VariREC CD power: %s\n", argv[i]);
				}
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--varirec-cd-strategy")) {
			if (argc>(i+1)) {
				i++;
				if (!strcmp(argv[i],"default"))  varirec_cd_str = 0;
				else if (!strcmp(argv[i],"azo")) varirec_cd_str = 1;
				else if (!strcmp(argv[i],"cya")) varirec_cd_str = 2;
				else if (!strcmp(argv[i],"pha")) varirec_cd_str = 3;
				else if (!strcmp(argv[i],"phb")) varirec_cd_str = 4;
				else if (!strcmp(argv[i],"phc")) varirec_cd_str = 5;
				else if (!strcmp(argv[i],"phd")) varirec_cd_str = 6;
				else {
					printf("Illegal VariREC CD strategy: %s\n", argv[i]);
				}
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
//  ************   VariREC  DVD
		else if(!strcmp(argv[i],"--varirec-dvd")) {
			if (argc>(i+1)) {
				i++;
				flags |= FL_VARIREC_DVD;
				if      (!strcmp(argv[i],"+4")) varirec_dvd_pwr = VARIREC_PLUS_4;
				else if (!strcmp(argv[i],"+3")) varirec_dvd_pwr = VARIREC_PLUS_3;
				else if (!strcmp(argv[i],"+2")) varirec_dvd_pwr = VARIREC_PLUS_2;
				else if (!strcmp(argv[i],"+1")) varirec_dvd_pwr = VARIREC_PLUS_1;
				else if (!strcmp(argv[i],"0"))  varirec_dvd_pwr = VARIREC_NULL;
				else if (!strcmp(argv[i],"-1")) varirec_dvd_pwr = VARIREC_MINUS_1;
				else if (!strcmp(argv[i],"-2")) varirec_dvd_pwr = VARIREC_MINUS_2;
				else if (!strcmp(argv[i],"-3")) varirec_dvd_pwr = VARIREC_MINUS_3;
				else if (!strcmp(argv[i],"-4")) varirec_dvd_pwr = VARIREC_MINUS_4;
				else if (!strcmp(argv[i],"off")) flags |= FL_VARIREC_DVD_OFF;
				else {
					printf("Illegal VariREC DVD power: %s\n", argv[i]);
				}
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--varirec-dvd-strategy")) {
			if (argc>(i+1)) {
				i++;
				if (!strcmp(argv[i],"default"))  varirec_dvd_str = 0;
				else if (!strcmp(argv[i],"0")) varirec_dvd_str = 1;
				else if (!strcmp(argv[i],"1")) varirec_dvd_str = 2;
				else if (!strcmp(argv[i],"2")) varirec_dvd_str = 3;
				else if (!strcmp(argv[i],"3")) varirec_dvd_str = 4;
				else if (!strcmp(argv[i],"4")) varirec_dvd_str = 5;
				else if (!strcmp(argv[i],"5")) varirec_dvd_str = 6;
				else if (!strcmp(argv[i],"6")) varirec_dvd_str = 7;
				else if (!strcmp(argv[i],"7")) varirec_dvd_str = 8;
				else {
					printf("Illegal VariREC DVD strategy: %s\n", argv[i]);
				}
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--securec")) {
			if (argc>(i+1)) {
				i++;
				strcpy(passwd,argv[i]);
				flags |= FL_SECUREC;
			//	printf("SecuRec pass: %s\n", passwd);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--nosecurec")) flags |= FL_NOSECUREC;
		else if(!strcmp(argv[i],"--bitset+r")) {
			flags |= FL_BOOK_R;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) bookr = 0;
				else if (!strcmp(argv[i],"on")) bookr = 1;
			}
		}
		else if(!strcmp(argv[i],"--bitset+rdl")) {
			flags |= FL_BOOK_RDL;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) bookrdl = 0;
				else if (!strcmp(argv[i],"on")) bookrdl = 1;
			}
		}
		else if(!strcmp(argv[i],"--dvd+testwtire")) {
			flags |= FL_TESTWRITE;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) testwrite = 0;
				else if (!strcmp(argv[i],"on")) testwrite = 1;
			}
		}
		else if(!strcmp(argv[i],"--as")) {
			flags |= FL_AS;
			if (argc>(i+1)) {
				i++;
				if (!strcmp(argv[i],"forced"))    as = AS_FORCED;
				else if (!strcmp(argv[i],"on"))   as = AS_ON;
				else if (!strcmp(argv[i],"auto")) as = AS_AUTO;
				else if (!strcmp(argv[i],"off"))  as = AS_OFF;
			}
		}
		else if(!strcmp(argv[i],"--silent")) {
			flags |= FL_SILENT;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"off")) silent = 0;
				else if (!strcmp(argv[i],"on")) silent = 1;
			}
		}
		else if(!strcmp(argv[i],"--sm-load")) {
			flags |= FL_SILENT; silent = 1; silent_tray = 1;
			if (argc>(i+1)) {
				i++;
				silent_load = (int)strtol(argv[i], NULL, 0);
//				printf("tray load speed: %d\n", silent_load);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--sm-eject")) {
			flags |= FL_SILENT; silent = 1; silent_tray = 1;
			if (argc>(i+1)) {
				i++;
				silent_eject = (int)strtol(argv[i], NULL, 0);
//				printf("tray load speed: %d\n", silent_load);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--sm-access")) {
			flags |= FL_SILENT; silent = 1;
			if (argc>(i+1)) {
				i++;
				if     (!strcmp(argv[i],"fast"))  silent_access = SILENT_ACCESS_FAST;
				else if (!strcmp(argv[i],"slow")) silent_access = SILENT_ACCESS_SLOW;
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--sm-cd-rd")) {
			flags |= FL_SILENT; silent = 1; silent_cd = 1;
			if (argc>(i+1)) {
				i++;
				if      (!strcmp(argv[i],"48")) silent_cd_rd = SILENT_CD_RD_48X;
				else if (!strcmp(argv[i],"40")) silent_cd_rd = SILENT_CD_RD_40X;
				else if (!strcmp(argv[i],"32")) silent_cd_rd = SILENT_CD_RD_32X;
				else if (!strcmp(argv[i],"24")) silent_cd_rd = SILENT_CD_RD_24X;
				else if (!strcmp(argv[i], "8")) silent_cd_rd =  SILENT_CD_RD_8X;
				else if (!strcmp(argv[i], "4")) silent_cd_rd =  SILENT_CD_RD_4X;
				else
					printf("invalid --sm-cd-rd parameter: %s\n", argv[i]);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--sm-cd-wr")) {
			flags |= FL_SILENT; silent = 1; silent_cd = 1;
			if (argc>(i+1)) {
				i++;
				if      (!strcmp(argv[i],"48")) silent_cd_wr = SILENT_CD_WR_48X;
				else if (!strcmp(argv[i],"32")) silent_cd_wr = SILENT_CD_WR_32X;
				else if (!strcmp(argv[i],"24")) silent_cd_wr = SILENT_CD_WR_24X;
				else if (!strcmp(argv[i],"16")) silent_cd_wr = SILENT_CD_WR_16X;
				else if (!strcmp(argv[i], "8")) silent_cd_wr =  SILENT_CD_WR_8X;
				else if (!strcmp(argv[i], "4")) silent_cd_wr =  SILENT_CD_WR_4X;
				else
					printf("invalid --sm-cd-wr parameter: %s\n", argv[i]);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--sm-dvd-rd")) {
			flags |= FL_SILENT; silent = 1; silent_dvd = 1;
			if (argc>(i+1)) {
				i++;
				if      (!strcmp(argv[i],"16")) silent_dvd_rd = SILENT_DVD_RD_16X;
				else if (!strcmp(argv[i],"12")) silent_dvd_rd = SILENT_DVD_RD_12X;
				else if (!strcmp(argv[i], "8")) silent_dvd_rd =  SILENT_DVD_RD_8X;
				else if (!strcmp(argv[i], "5")) silent_dvd_rd =  SILENT_DVD_RD_5X;
				else if (!strcmp(argv[i], "2")) silent_dvd_rd =  SILENT_DVD_RD_2X;
				else
					printf("invalid --sm-dvd-rd parameter: %s\n", argv[i]);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--sm-dvd-wr")) {
			flags |= FL_SILENT; silent = 1; silent_dvd = 1;
			if (argc>(i+1)) {
				i++;
				if      (!strcmp(argv[i],"16")) silent_dvd_wr = SILENT_DVD_WR_16X;
				else if (!strcmp(argv[i],"12")) silent_dvd_wr = SILENT_DVD_WR_12X;
				else if (!strcmp(argv[i], "8")) silent_dvd_wr =  SILENT_DVD_WR_8X;
				else if (!strcmp(argv[i], "6")) silent_dvd_wr =  SILENT_DVD_WR_6X;
				else if (!strcmp(argv[i], "4")) silent_dvd_wr =  SILENT_DVD_WR_4X;
				else
					printf("invalid --sm-dvd-wr parameter: %s\n", argv[i]);
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		}
		else if(!strcmp(argv[i],"--sm-nosave")) silent_save = 0;
		else if(!strcmp(argv[i],"--PlexEraser")) {
			if (argc>(i+1)) {
				i++;
				if (!strcmp(argv[i],"quick")) { flags |= FL_PXERASER; pxeraser = PLEXERASER_QUICK; }
				if (!strcmp(argv[i],"full"))  { flags |= FL_PXERASER; pxeraser = PLEXERASER_FULL;  }
			} else {
				printf("option %s needs parameter!\n", argv[i]);
				return 5;
			}
		} else if(!strcmp(argv[i],"-v")) flags |= FL_VERBOSE;
		else if(!strcmp(argv[i],"--verbose")) flags |= FL_VERBOSE;
		else {
			printf("unknown option: %s\n", argv[i]);
			return 6;
		}
	}
	if (flags & FL_HELP) {
		usage(argv[0]);
		return 0;
	}
	if (!flags) {
		usage(argv[0]);
		return 1;
	}

	if (flags & FL_SCAN) {
		drvcnt = scanbus();
		if (!drvcnt) printf("ERR: no drives found!\n");
		return 2;
	}
	if (!(flags & FL_DEVICE)) {
		printf("** ERR: no device selected\n");
		return 3;
	}
//	printf("____________________________\n");
	printf("Device : %s\n", device);
	drive = new drive_info(device);
	if (drive->err) {
		printf("%s: device open error!\n", argv[0]);
		delete drive;
		return 4;
	}

	inquiry(drive);
	convert_to_ID(drive);
	printf("Vendor : '%s'\n",drive->ven);
	printf("Model  : '%s'",drive->dev);
	if ((drive->ven_ID == WR_PLEXTOR)) {
		plextor_get_TLA(drive);
		printf(" (TLA#%s)",drive->TLA);
	}
	printf("\nF/W    : '%s'\n",drive->fw);

	if (!(flags & FL_VERBOSE)) drive->silent++;

	if (get_drive_serial_number(drive)) printf("Serial#: %s\n",drive->serial);

	if (flags) {
//	if (flags & FL_VERBOSE) {
		printf("\nPxControl flags : ");
		if (flags & FL_DEVICE)		printf(" DEVICE");
		if (flags & FL_HELP)		printf(" HELP");
		if (flags & FL_CURRENT)		printf(" CURRENT");
		if (flags & FL_SUPPORTED)	printf(" SUPPORTED");
		if (flags & FL_SCAN)		printf(" SCAN");
		if (flags & FL_LOCK)		printf(" LOCK");
		if (flags & FL_HCDR)		printf(" HCDR");
		if (flags & FL_SSS)		printf(" SSS");
		if (flags & FL_SPDREAD)		printf(" SPDREAD");
		if (flags & FL_POWEREC)		printf(" POWEREC");
		if (flags & FL_GIGAREC)		printf(" GIGAREC");
		if (flags & FL_VARIREC_CD)	printf(" VARIREC_CD");
		if (flags & FL_VARIREC_DVD)	printf(" VARIREC_DVD");
		if (flags & FL_SECUREC)		printf(" SECUREC");
		if (flags & FL_BOOK_R)		printf(" BITSET_R");
		if (flags & FL_BOOK_RDL)	printf(" BITSET_RDL");
		if (flags & FL_TESTWRITE)	printf(" DVD+TESTWRITE");
		if (flags & FL_AS)		printf(" AS");
		if (flags & FL_SILENT)		printf(" SILENT");
		if (flags & FL_VERBOSE)		printf(" VERBOSE");
		printf("\n\n");
	}
	printf("____________________________\n");

	if (flags & FL_POWEREC) {
//		printf("Set PoweREC...\n");
		drive->plextor.powerec_state = powerec;
		plextor_set_powerec(drive);
	}
	if (flags & FL_GIGAREC) {
//		printf("Set GigaREC...\n");
		drive->plextor.gigarec = gigarec;
		plextor_set_gigarec(drive);
	}
	if (flags & FL_VARIREC_CD) {
//		printf("Set VariREC CD...\n");
//		printf("PWR = %02X   STR = %02X\n",varirec_cd_pwr, varirec_cd_str);
		drive->plextor.varirec_state_cd = !(flags & FL_VARIREC_CD_OFF);
		drive->plextor.varirec_pwr_cd = varirec_cd_pwr;
		drive->plextor.varirec_str_cd = varirec_cd_str;
		plextor_set_varirec(drive, VARIREC_CD);
	}
	if (flags & FL_VARIREC_DVD) {
//		printf("Set VariREC DVD...\n");
//		printf("PWR = %02X   STR = %02X\n",varirec_dvd_pwr, varirec_dvd_str);
		drive->plextor.varirec_state_dvd = !(flags & FL_VARIREC_DVD_OFF);
		drive->plextor.varirec_pwr_dvd = varirec_dvd_pwr;
		drive->plextor.varirec_str_dvd = varirec_dvd_str;
		plextor_set_varirec(drive, VARIREC_DVD);
	}
	if (flags & FL_NOSECUREC) {
		plextor_set_securec(drive, 0, NULL);
	}
	else if (flags & FL_SECUREC) {
		int pwdlen = (char)strlen(passwd);
		if ((pwdlen>=4) && (pwdlen<=10))
			plextor_set_securec(drive, pwdlen, passwd);
		else
			printf("Invalid SecuRec password length! must be 4..10\n");
	}
	if (flags & FL_HCDR) {
		plextor_set_hidecdr(drive, hcdr);
	}
	if (flags & FL_SSS) {
		plextor_set_singlesession(drive, sss);
	}
	if (flags & FL_SPDREAD) {
		plextor_set_speedread(drive, spdread);
	}
	if (flags & FL_BOOK_R) {
		drive->book_plus_r = bookr;
		plextor_set_bitset(drive, PLEX_BITSET_R);
	}
	if (flags & FL_BOOK_RDL) {
		drive->book_plus_rdl = bookrdl;
		plextor_set_bitset(drive, PLEX_BITSET_RDL);
	}
	if (flags & FL_AS) {
		drive->astrategy.state = as;
		plextor_set_autostrategy(drive);
	}
	if (flags & FL_TESTWRITE) {
		drive->plextor.testwrite_dvdplus = testwrite;
		plextor_set_testwrite_dvdplus(drive);
	}
	if (flags & FL_SILENT) {
		plextor_get_silentmode(drive);
		if (!silent)
			plextor_set_silentmode_disable(drive, silent_save);
		else {
			if (!drive->plextor_silent.state)
				{ silent_cd = 1; silent_dvd = 1; silent_tray = 1; }
			if (silent_cd) {
				drive->plextor_silent.access_speed = silent_access;
				drive->plextor_silent.read_speed   = silent_cd_rd;
				drive->plextor_silent.write_speed  = silent_cd_wr;
				plextor_set_silentmode_disc(drive, SILENT_CD, silent_save);
			}
			if (silent_dvd) {
				drive->plextor_silent.access_speed = silent_access;
				drive->plextor_silent.read_speed   = silent_dvd_rd;
				drive->plextor_silent.write_speed  = silent_dvd_wr;
				plextor_set_silentmode_disc(drive, SILENT_DVD, silent_save);
			}
			if (silent_tray) {
				drive->plextor_silent.load_speed   = silent_load;
				drive->plextor_silent.eject_speed  = silent_eject;
				plextor_set_silentmode_tray(drive, SILENT_CD, silent_save);
			}
		}
	}
	if (flags & FL_PXERASER) {
		drive->plextor.plexeraser = pxeraser;
		plextor_plexeraser(drive);
	}

	get_device_info(drive);
	if (!(flags & FL_VERBOSE)) drive->silent--;
	delete drive;
	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1