New API calls burn_drive_get_serial_no() and burn_drive_get_media_sno()
This commit is contained in:
parent
d7e762b9be
commit
60e2e7df28
@ -1 +1 @@
|
|||||||
#define Cdrskin_timestamP "2015.09.23.110012"
|
#define Cdrskin_timestamP "2015.10.18.125353"
|
||||||
|
@ -89,6 +89,10 @@ int burn_setup_drive(struct burn_drive *d, char *fname)
|
|||||||
d->stream_recording_start= 0;
|
d->stream_recording_start= 0;
|
||||||
d->role_5_nwa = 0;
|
d->role_5_nwa = 0;
|
||||||
d->features = NULL;
|
d->features = NULL;
|
||||||
|
d->drive_serial_number = NULL;
|
||||||
|
d->drive_serial_number_len = -1;
|
||||||
|
d->media_serial_number = NULL;
|
||||||
|
d->media_serial_number_len = -1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,6 +708,14 @@ int burn_drive_release_fl(struct burn_drive *d, int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d->needs_sync_cache = 0; /* just to be sure */
|
d->needs_sync_cache = 0; /* just to be sure */
|
||||||
|
|
||||||
|
if (d->drive_serial_number != NULL)
|
||||||
|
BURN_FREE_MEM(d->drive_serial_number);
|
||||||
|
if (d->media_serial_number != NULL)
|
||||||
|
BURN_FREE_MEM(d->media_serial_number);
|
||||||
|
d->drive_serial_number = d->media_serial_number = NULL;
|
||||||
|
d->drive_serial_number_len = d->media_serial_number_len = 0;
|
||||||
|
|
||||||
d->released = 1;
|
d->released = 1;
|
||||||
|
|
||||||
/* ts A61125 : outsourced model aspects */
|
/* ts A61125 : outsourced model aspects */
|
||||||
@ -3490,3 +3502,69 @@ int burn_drive_has_feature(struct burn_drive *d, int feature_code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B51016 API */
|
||||||
|
int burn_drive_get_serial_no(struct burn_drive *d, char **sno, int *sno_len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (*sno != NULL)
|
||||||
|
BURN_FREE_MEM(*sno);
|
||||||
|
if (d->drive_serial_number_len > 0)
|
||||||
|
*sno_len = d->drive_serial_number_len;
|
||||||
|
else
|
||||||
|
*sno_len = 0;
|
||||||
|
BURN_ALLOC_MEM(*sno, char, *sno_len + 1);
|
||||||
|
if (d->drive_serial_number_len > 0)
|
||||||
|
memcpy(*sno, d->drive_serial_number, *sno_len);
|
||||||
|
(*sno)[*sno_len] = 0;
|
||||||
|
ret = 1;
|
||||||
|
ex:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B51016 API */
|
||||||
|
int burn_drive_get_media_sno(struct burn_drive *d, char **sno, int *sno_len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#ifdef Libburn_enable_scsi_cmd_ABh
|
||||||
|
struct burn_feature_descr *feat;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (*sno != NULL)
|
||||||
|
BURN_FREE_MEM(*sno);
|
||||||
|
*sno = NULL;
|
||||||
|
|
||||||
|
if (d->media_serial_number_len == -1) {
|
||||||
|
|
||||||
|
#ifdef Libburn_enable_scsi_cmd_ABh
|
||||||
|
|
||||||
|
if (burn_drive_has_feature(d, 0x109, &feat, 0))
|
||||||
|
|
||||||
|
#ifndef Libburn_enable_scsi_cmd_ABh_pretend_currenT
|
||||||
|
if (feat->flags & 1) /* current */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
spc_read_media_serial_number(d);
|
||||||
|
|
||||||
|
#else
|
||||||
|
;
|
||||||
|
|
||||||
|
#endif /* ! Libburn_enable_scsi_cmd_ABh */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->media_serial_number_len > 0)
|
||||||
|
*sno_len = d->media_serial_number_len;
|
||||||
|
else
|
||||||
|
*sno_len = 0;
|
||||||
|
BURN_ALLOC_MEM(*sno, char, *sno_len + 1);
|
||||||
|
if (*sno_len > 0)
|
||||||
|
memcpy(*sno, d->media_serial_number, *sno_len);
|
||||||
|
(*sno)[*sno_len] = 0;
|
||||||
|
ret = 1;
|
||||||
|
ex:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1257,6 +1257,51 @@ int burn_disc_pretend_full(struct burn_drive *drive);
|
|||||||
int burn_disc_pretend_full_uncond(struct burn_drive *drive);
|
int burn_disc_pretend_full_uncond(struct burn_drive *drive);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B51016 */
|
||||||
|
/** Returns the Drive Serial Number as of MMC feature 108h.
|
||||||
|
@param d The drive to inquire.
|
||||||
|
@param sno Returns the bytes of the serial number. A trailing 0-byte
|
||||||
|
is appended for convenience. MMC specifies ASCII 0x20 to
|
||||||
|
0x7h as possible byte values. But given drive firmware
|
||||||
|
habits there is no warranty that *sno contains no other
|
||||||
|
byte values.
|
||||||
|
Submit *sno as NULL or pointing to free()-able memory.
|
||||||
|
Apply free() to *sno when no longer needed.
|
||||||
|
@param sno_len Returns the number of valid bytes in returned *sno,
|
||||||
|
not counting the appended trailing 0.
|
||||||
|
@return 1= success (but maybe *sno_len is 0), <= 0 severe failure
|
||||||
|
@since 1.4.2
|
||||||
|
*/
|
||||||
|
int burn_drive_get_serial_no(struct burn_drive *d, char **sno, int *sno_len);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B51016 */
|
||||||
|
/** Returns the Media Serial Number as of MMC feature 109h and command ABh
|
||||||
|
READ MEDIA SERIAL NUMBER.
|
||||||
|
|
||||||
|
Note: This call will return an empty result unless the macro
|
||||||
|
Libburn_enable_scsi_cmd_ABh
|
||||||
|
is defined at compile time.
|
||||||
|
This is because the command READ MEDIA SERIAL NUMBER demands
|
||||||
|
superuser authority on Linux, because no medium with serial number
|
||||||
|
could be tested yet, and because this command made one of the test
|
||||||
|
drives unusable until power cycle when it was executed despite
|
||||||
|
feature 109h was not announced as "current".
|
||||||
|
|
||||||
|
@param d The drive to inquire.
|
||||||
|
@param sno Returns the bytes of the serial number. A trailing 0-byte
|
||||||
|
is appended for convenience. There is no warranty that
|
||||||
|
*sno contains no other byte values.
|
||||||
|
Submit *sno as NULL or pointing to free()-able memory.
|
||||||
|
Apply free() to *sno when no longer needed.
|
||||||
|
@param sno_len Returns the number of valid bytes in returned *sno,
|
||||||
|
not counting the appended trailing 0.
|
||||||
|
@return 1= success (but maybe *sno_len is 0), <= 0 severe failure
|
||||||
|
@since 1.4.2
|
||||||
|
*/
|
||||||
|
int burn_drive_get_media_sno(struct burn_drive *d, char **sno, int *sno_len);
|
||||||
|
|
||||||
|
|
||||||
/* ts A61021 */
|
/* ts A61021 */
|
||||||
/** Reads ATIP information from inserted media. To be obtained via
|
/** Reads ATIP information from inserted media. To be obtained via
|
||||||
burn_drive_get_write_speed(), burn_drive_get_min_write_speed(),
|
burn_drive_get_write_speed(), burn_drive_get_min_write_speed(),
|
||||||
@ -4274,5 +4319,12 @@ int burn_nec_optiarc_rep_err_rate(struct burn_drive *d,
|
|||||||
#endif /* Libburn_develop_quality_scaN */
|
#endif /* Libburn_develop_quality_scaN */
|
||||||
|
|
||||||
|
|
||||||
|
/* Linux 3.16 problems with ABh Read Media Serial Number:
|
||||||
|
- as normal user lets ioctl(SG_IO) return -1 and errno = EFAULT
|
||||||
|
- as superuser renders LG BH16NS40 unusable until power cycle
|
||||||
|
#de fine Libburn_enable_scsi_cmd_ABh yes
|
||||||
|
#de fine Libburn_enable_scsi_cmd_ABh_pretend_currenT yes
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#endif /*LIBBURN_H*/
|
#endif /*LIBBURN_H*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||||
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
|
Copyright (c) 2006 - 2015 Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Provided under GPL version 2 or later.
|
Provided under GPL version 2 or later.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ static unsigned char MMC_READ_CAPACITY[] =
|
|||||||
static unsigned char MMC_READ_DISC_STRUCTURE[] =
|
static unsigned char MMC_READ_DISC_STRUCTURE[] =
|
||||||
{ 0xAD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
{ 0xAD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
/* ts B21125 : An alternatvie to BEh READ CD
|
/* ts B21125 : An alternative to BEh READ CD
|
||||||
*/
|
*/
|
||||||
static unsigned char MMC_READ_CD_MSF[] =
|
static unsigned char MMC_READ_CD_MSF[] =
|
||||||
{ 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
{ 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
@ -3225,13 +3225,31 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
|
|||||||
!!(descr[4] & 8), !!(descr[4] & 4),
|
!!(descr[4] & 8), !!(descr[4] & 4),
|
||||||
!!(descr[4] & 2));
|
!!(descr[4] & 2));
|
||||||
|
|
||||||
} else if (feature_code == 0x108 || feature_code == 0x10c) {
|
#endif /* Libburn_print_feature_descriptorS */
|
||||||
int i, c_limit;
|
|
||||||
|
|
||||||
|
} else if (feature_code == 0x108 || feature_code == 0x10c) {
|
||||||
|
int c_limit;
|
||||||
|
|
||||||
|
#ifdef Libburn_print_feature_descriptorS
|
||||||
|
int i;
|
||||||
fprintf(stderr, "LIBBURN_EXPERIMENTAL : %s = ",
|
fprintf(stderr, "LIBBURN_EXPERIMENTAL : %s = ",
|
||||||
feature_code == 0x108 ?
|
feature_code == 0x108 ?
|
||||||
"Drive Serial Number" : "Drive Firmware Date");
|
"Drive Serial Number" : "Drive Firmware Date");
|
||||||
|
#endif /* Libburn_print_feature_descriptorS */
|
||||||
|
|
||||||
c_limit = descr[3] - 2 * (feature_code == 0x10c);
|
c_limit = descr[3] - 2 * (feature_code == 0x10c);
|
||||||
|
if (feature_code == 0x108) {
|
||||||
|
if (d->drive_serial_number != NULL)
|
||||||
|
BURN_FREE_MEM(d->drive_serial_number);
|
||||||
|
BURN_ALLOC_MEM(d->drive_serial_number,
|
||||||
|
char, c_limit + 1);
|
||||||
|
memcpy(d->drive_serial_number, descr + 4,
|
||||||
|
c_limit);
|
||||||
|
d->drive_serial_number[c_limit] = 0;
|
||||||
|
d->drive_serial_number_len = c_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Libburn_print_feature_descriptorS
|
||||||
for (i = 0; i < c_limit; i++)
|
for (i = 0; i < c_limit; i++)
|
||||||
if (descr[4 + i] < 0x20 || descr[4 + i] > 0x7e
|
if (descr[4 + i] < 0x20 || descr[4 + i] > 0x7e
|
||||||
|| descr[4 + i] == '\\')
|
|| descr[4 + i] == '\\')
|
||||||
@ -5281,7 +5299,6 @@ ex:;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
|
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
|
||||||
*/
|
*/
|
||||||
int mmc_setup_drive(struct burn_drive *d)
|
int mmc_setup_drive(struct burn_drive *d)
|
||||||
|
109
libburn/spc.c
109
libburn/spc.c
@ -59,6 +59,10 @@ static unsigned char SPC_MODE_SELECT[] = { 0x55, 16, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|||||||
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
|
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
|
||||||
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
|
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
#ifdef Libburn_enable_scsi_cmd_ABh
|
||||||
|
static unsigned char SPC_READ_MEDIA_SERIAL_NUMBER[] =
|
||||||
|
{ 0xAB, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ts A70519 : An initializer for the abstract SCSI command structure */
|
/* ts A70519 : An initializer for the abstract SCSI command structure */
|
||||||
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen)
|
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen)
|
||||||
@ -891,6 +895,109 @@ ex:;
|
|||||||
BURN_FREE_MEM(c);
|
BURN_FREE_MEM(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Libburn_enable_scsi_cmd_ABh
|
||||||
|
|
||||||
|
/* At least on Linux kernel 3.16 the command ABh causes EFAULT if not sent
|
||||||
|
from the superuser.
|
||||||
|
For a test it may be replaced by a dummy 28h READ12 on block 0.
|
||||||
|
This causes no EFAULT although it sets the wrong dxfer_len 4 rather
|
||||||
|
than 2048. So it is indeed a permission problem and not bad alignment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ts B51016 */
|
||||||
|
int spc_read_media_serial_number_al(struct burn_drive *d, int *alloc_len)
|
||||||
|
{
|
||||||
|
struct buffer *buf = NULL;
|
||||||
|
struct command *c = NULL;
|
||||||
|
unsigned char *data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (*alloc_len < 4)
|
||||||
|
{ret = 0; goto ex;}
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(buf, struct buffer, 1);
|
||||||
|
BURN_ALLOC_MEM(c, struct command, 1);
|
||||||
|
if (mmc_function_spy(d, "spc_read_media_serial_number") <= 0)
|
||||||
|
{ret = 0; goto ex;}
|
||||||
|
/*
|
||||||
|
#de fine Spc_read_media_serial_number_dummY yes
|
||||||
|
*/
|
||||||
|
#ifdef Spc_read_media_serial_number_dummY
|
||||||
|
|
||||||
|
{
|
||||||
|
static unsigned char MMC_READ_12[] =
|
||||||
|
{ 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
|
||||||
|
|
||||||
|
scsi_init_command(c, MMC_READ_12, sizeof(MMC_READ_12));
|
||||||
|
c->dxfer_len = *alloc_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
scsi_init_command(c, SPC_READ_MEDIA_SERIAL_NUMBER,
|
||||||
|
sizeof(SPC_READ_MEDIA_SERIAL_NUMBER));
|
||||||
|
c->dxfer_len = *alloc_len;
|
||||||
|
/* (Will not accept more than 32 KB anyway) */
|
||||||
|
c->opcode[8] = (c->dxfer_len >> 8) & 0xff;
|
||||||
|
c->opcode[9] = c->dxfer_len & 0xff;
|
||||||
|
|
||||||
|
#endif /* ! Spc_read_media_serial_number_dummY */
|
||||||
|
|
||||||
|
c->retry = 1;
|
||||||
|
c->page = buf;
|
||||||
|
memset(c->page->data, 0, *alloc_len);
|
||||||
|
c->page->bytes = 0;
|
||||||
|
c->page->sectors = 0;
|
||||||
|
|
||||||
|
c->dir = FROM_DRIVE;
|
||||||
|
d->issue_command(d, c);
|
||||||
|
|
||||||
|
if (c->error)
|
||||||
|
{ret = 0; goto ex;}
|
||||||
|
|
||||||
|
data = c->page->data;
|
||||||
|
|
||||||
|
#ifdef Spc_read_media_serial_number_dummY
|
||||||
|
d->media_serial_number_len = 0;
|
||||||
|
#else
|
||||||
|
d->media_serial_number_len =
|
||||||
|
(data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[7];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (*alloc_len >= d->media_serial_number_len + 4) {
|
||||||
|
if (d->media_serial_number != NULL)
|
||||||
|
BURN_FREE_MEM(d->media_serial_number);
|
||||||
|
BURN_ALLOC_MEM(d->media_serial_number, char,
|
||||||
|
d->media_serial_number_len + 1);
|
||||||
|
if (d->media_serial_number_len > 0)
|
||||||
|
memcpy(d->media_serial_number, data + 4,
|
||||||
|
d->media_serial_number_len);
|
||||||
|
d->media_serial_number[d->media_serial_number_len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*alloc_len = d->media_serial_number_len + 4;
|
||||||
|
ret = 1;
|
||||||
|
ex:;
|
||||||
|
BURN_FREE_MEM(c);
|
||||||
|
BURN_FREE_MEM(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int spc_read_media_serial_number(struct burn_drive *d)
|
||||||
|
{
|
||||||
|
int alloc_len = 4, ret;
|
||||||
|
|
||||||
|
ret = spc_read_media_serial_number_al(d, &alloc_len);
|
||||||
|
if (alloc_len > 4 && alloc_len <= 0x8000 && ret > 0)
|
||||||
|
ret = spc_read_media_serial_number_al(d, &alloc_len);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Libburn_enable_scsi_cmd_ABh */
|
||||||
|
|
||||||
|
|
||||||
void spc_getcaps(struct burn_drive *d)
|
void spc_getcaps(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
if (mmc_function_spy(d, "getcaps") <= 0)
|
if (mmc_function_spy(d, "getcaps") <= 0)
|
||||||
@ -1554,6 +1661,8 @@ static char *scsi_command_name(unsigned int c, int flag)
|
|||||||
return "BLANK";
|
return "BLANK";
|
||||||
case 0xaa:
|
case 0xaa:
|
||||||
return "WRITE(12)";
|
return "WRITE(12)";
|
||||||
|
case 0xab:
|
||||||
|
return "READ MEDIA SERIAL NUMBER";
|
||||||
case 0xac:
|
case 0xac:
|
||||||
return "GET PERFORMANCE";
|
return "GET PERFORMANCE";
|
||||||
case 0xad:
|
case 0xad:
|
||||||
|
@ -23,6 +23,11 @@ void spc_sense_write_params(struct burn_drive *);
|
|||||||
void spc_select_write_params(struct burn_drive *,
|
void spc_select_write_params(struct burn_drive *,
|
||||||
struct burn_session *, int,
|
struct burn_session *, int,
|
||||||
const struct burn_write_opts *);
|
const struct burn_write_opts *);
|
||||||
|
|
||||||
|
#ifdef Libburn_enable_scsi_cmd_ABh
|
||||||
|
int spc_read_media_serial_number(struct burn_drive *d);
|
||||||
|
#endif
|
||||||
|
|
||||||
void spc_probe_write_modes(struct burn_drive *);
|
void spc_probe_write_modes(struct burn_drive *);
|
||||||
void spc_request_sense(struct burn_drive *d, struct buffer *buf);
|
void spc_request_sense(struct burn_drive *d, struct buffer *buf);
|
||||||
int spc_block_type(enum burn_block_types b);
|
int spc_block_type(enum burn_block_types b);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||||
|
|
||||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||||
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
|
Copyright (c) 2006 - 2015 Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Provided under GPL version 2 or later.
|
Provided under GPL version 2 or later.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -253,6 +253,16 @@ struct burn_drive
|
|||||||
*/
|
*/
|
||||||
int current_feat2fh_byte4;
|
int current_feat2fh_byte4;
|
||||||
|
|
||||||
|
/* ts B51016 : Result from feature 108h : Drive Serial Number
|
||||||
|
*/
|
||||||
|
char *drive_serial_number;
|
||||||
|
char drive_serial_number_len;
|
||||||
|
|
||||||
|
/* ts B51016 : Result from command AB READ MEDIA SERIAL NUMBER
|
||||||
|
*/
|
||||||
|
char *media_serial_number;
|
||||||
|
char media_serial_number_len;
|
||||||
|
|
||||||
/* ts B10524 : whether the damage bit was set for the future track.
|
/* ts B10524 : whether the damage bit was set for the future track.
|
||||||
bit0= damage bit , bit1= nwa valid bit
|
bit0= damage bit , bit1= nwa valid bit
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user