New API calls burn_drive_get_speedlist() , burn_drive_free_speedlist()
This commit is contained in:
parent
ae1b8ce61c
commit
1bd1985aeb
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2006.12.25.190811"
|
||||
#define Cdrskin_timestamP "2006.12.26.170459"
|
||||
|
@ -54,6 +54,7 @@ void burn_drive_free(struct burn_drive *d)
|
||||
if (burn_drive_is_open(d))
|
||||
d->release(d);
|
||||
free((void *) d->idata);
|
||||
burn_mdata_free_subs(d->mdata);
|
||||
free((void *) d->mdata);
|
||||
if(d->toc_entry != NULL)
|
||||
free((void *) d->toc_entry);
|
||||
@ -144,6 +145,9 @@ int burn_drive_inquire_media(struct burn_drive *d)
|
||||
int loop_count, old_speed = -1234567890, new_speed = -987654321;
|
||||
int old_erasable = -1234567890, new_erasable = -987654321;
|
||||
|
||||
/* ts A61225 : after loading the tray, mode page 2Ah can change */
|
||||
d->getcaps(d);
|
||||
|
||||
/* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */
|
||||
|
||||
if (d->mdata->cdr_write || d->mdata->cdrw_write ||
|
||||
@ -152,6 +156,8 @@ int burn_drive_inquire_media(struct burn_drive *d)
|
||||
#ifdef Libburn_grab_release_and_grab_agaiN
|
||||
/* This code demanded the app to release and re-grab. */
|
||||
|
||||
/* ??? ts A61225 : is this safe now (after d->getcaps()) ? */
|
||||
|
||||
d->read_disc_info(d);
|
||||
|
||||
#else
|
||||
@ -226,9 +232,6 @@ int burn_drive_grab(struct burn_drive *d, int le)
|
||||
/* ts A61118 */
|
||||
d->start_unit(d);
|
||||
|
||||
/* ts A61225 : after loading the tray, mode page 2Ah can change */
|
||||
d->getcaps(d);
|
||||
|
||||
/* ts A61202 : gave bit1 of le a meaning */
|
||||
sose = d->silent_on_scsi_error;
|
||||
if (!le)
|
||||
@ -1290,3 +1293,111 @@ int burn_drive_wrote_well(struct burn_drive *d)
|
||||
return !d->cancel;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61226 */
|
||||
int burn_speed_descriptor_new(struct burn_speed_descriptor **s,
|
||||
struct burn_speed_descriptor *prev,
|
||||
struct burn_speed_descriptor *next, int flag)
|
||||
{
|
||||
struct burn_speed_descriptor *o;
|
||||
|
||||
(*s) = o = malloc(sizeof(struct burn_speed_descriptor));
|
||||
if (o == NULL)
|
||||
return -1;
|
||||
o->source = 0;
|
||||
o->profile_loaded = -2;
|
||||
o->profile_name[0] = 0;
|
||||
o->wrc = 0;
|
||||
o->exact = 0;
|
||||
o->mrw = 0;
|
||||
o->end_lba = -1;
|
||||
o->write_speed = 0;
|
||||
o->read_speed = 0;
|
||||
|
||||
o->prev = prev;
|
||||
if (prev != NULL) {
|
||||
next = prev->next;
|
||||
prev->next = o;
|
||||
}
|
||||
o->next = next;
|
||||
if (next != NULL)
|
||||
next->prev = o;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61226 */
|
||||
/* @param flag bit0= destroy whole next-chain of descriptors */
|
||||
int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag)
|
||||
{
|
||||
struct burn_speed_descriptor *next, *o;
|
||||
|
||||
if ((*s) == NULL)
|
||||
return 0;
|
||||
if (flag&1)
|
||||
for (o = (*s); o->prev != NULL; o = o->prev);
|
||||
else
|
||||
o = (*s);
|
||||
next = o->next;
|
||||
if (next != NULL)
|
||||
next->prev = o->prev;
|
||||
if (o->prev != NULL)
|
||||
o->prev->next = next;
|
||||
free((char *) (*s));
|
||||
(*s) = NULL;
|
||||
if (flag&1)
|
||||
return burn_speed_descriptor_destroy(&next, flag&1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61226 */
|
||||
int burn_speed_descriptor_copy(struct burn_speed_descriptor *from,
|
||||
struct burn_speed_descriptor *to, int flag)
|
||||
{
|
||||
to->source = from->source;
|
||||
to->profile_loaded = from->profile_loaded;
|
||||
strcpy(to->profile_name, from->profile_name);
|
||||
to->wrc = from->wrc;
|
||||
to->exact = from->exact;
|
||||
to->mrw = from->mrw;
|
||||
to->end_lba = from->end_lba;
|
||||
to->write_speed = from->write_speed;
|
||||
to->read_speed = from->read_speed;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
|
||||
int burn_mdata_free_subs(struct scsi_mode_data *m)
|
||||
{
|
||||
burn_speed_descriptor_destroy(&(m->speed_descriptors), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61226 : API function */
|
||||
int burn_drive_get_speedlist(struct burn_drive *d,
|
||||
struct burn_speed_descriptor **speed_list)
|
||||
{
|
||||
int ret;
|
||||
struct burn_speed_descriptor *sd, *csd = NULL;
|
||||
|
||||
(*speed_list) = NULL;
|
||||
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
|
||||
ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
burn_speed_descriptor_copy(sd, csd, 0);
|
||||
}
|
||||
(*speed_list) = csd;
|
||||
return (csd != NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ts A61226 : API function */
|
||||
int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list)
|
||||
{
|
||||
return burn_speed_descriptor_destroy(speed_list, 1);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
struct burn_drive;
|
||||
struct command;
|
||||
struct mempage;
|
||||
struct scsi_mode_data;
|
||||
struct burn_speed_descriptor;
|
||||
|
||||
#define LEAD_IN 1
|
||||
#define GAP 2
|
||||
@ -75,4 +77,18 @@ int burn_drive_inquire_media(struct burn_drive *d);
|
||||
/* ts A61125 : model aspects of burn_drive_release */
|
||||
int burn_drive_mark_unready(struct burn_drive *d);
|
||||
|
||||
|
||||
/* ts A61226 */
|
||||
int burn_speed_descriptor_new(struct burn_speed_descriptor **s,
|
||||
struct burn_speed_descriptor *prev,
|
||||
struct burn_speed_descriptor *next, int flag);
|
||||
|
||||
/* ts A61226 */
|
||||
/* @param flag bit0= destroy whole next-chain of descriptors */
|
||||
int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag);
|
||||
|
||||
|
||||
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
|
||||
int burn_mdata_free_subs(struct scsi_mode_data *m);
|
||||
|
||||
#endif /* __DRIVE */
|
||||
|
@ -414,6 +414,55 @@ struct burn_progress {
|
||||
unsigned buffer_min_fill;
|
||||
};
|
||||
|
||||
|
||||
/* ts A61226 */
|
||||
/** Description of a speed capability as reported by the drive in conjunction
|
||||
with eventually loaded media. There can be more than one such object per
|
||||
drive. So they are chained via .next and .prev , where NULL marks the end
|
||||
of the chain. This list is set up by burn_drive_scan() and gets updated
|
||||
by burn_drive_grab().
|
||||
A copy may be obtained by burn_drive_get_speedlist() and disposed by
|
||||
burn_drive_free_speedlist().
|
||||
For technical background info see SCSI specs MMC and SPC:
|
||||
mode page 2Ah (from SPC 5Ah MODE SENSE) , mmc3r10g.pdf , 6.3.11 Table 364
|
||||
ACh GET PERFORMANCE, Type 03h , mmc5r03c.pdf , 6.8.5.3 Table 312
|
||||
*/
|
||||
struct burn_speed_descriptor {
|
||||
|
||||
/** Where this info comes from :
|
||||
0 = misc , 1 = mode page 2Ah , 2 = ACh GET PERFORMANCE */
|
||||
int source;
|
||||
|
||||
/** The media type that was reported as current at the time of report
|
||||
-2 = state unknown, -1 = no media was loaded , else see
|
||||
burn_disc_get_profile() */
|
||||
int profile_loaded;
|
||||
char profile_name[80];
|
||||
|
||||
/** The attributed capacity of appropriate media in logical block units
|
||||
i.e. 2352 raw bytes or 2048 data bytes. -1 = capacity unknown. */
|
||||
int end_lba;
|
||||
|
||||
/** Write speed is given in 1000 bytes/s , 0 = invalid. The numbers
|
||||
are supposed to be usable with burn_drive_set_speed() */
|
||||
int write_speed;
|
||||
int read_speed;
|
||||
|
||||
/** Expert info from ACh GET PERFORMANCE and/or mode page 2Ah.
|
||||
Expect values other than 0 or 1 to get a meaning in future.*/
|
||||
/* Rotational control: 0 = CLV/default , 1 = CAV */
|
||||
int wrc;
|
||||
/* 1 = drive promises reported performance over full media */
|
||||
int exact;
|
||||
/* 1 = suitable for mixture of read and write */
|
||||
int mrw;
|
||||
|
||||
/** List chaining. Use .next until NULL to iterate over the list */
|
||||
struct burn_speed_descriptor *prev;
|
||||
struct burn_speed_descriptor *next;
|
||||
};
|
||||
|
||||
|
||||
/** Initialize the library.
|
||||
This must be called before using any other functions in the library. It
|
||||
may be called more than once with no effect.
|
||||
@ -735,11 +784,12 @@ int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
|
||||
/* ts A61202 */
|
||||
/** Tells the MMC Profile identifier of the loaded media. The drive must be
|
||||
grabbed in order to get a non-zero result.
|
||||
libburn currently writes only to profiles 0x09 "CD-R", 0x0a "CD-RW" or
|
||||
0x1a "DVD+RW".
|
||||
@param d The drive where the media is inserted.
|
||||
@param pno Profile Number as of mmc5r03c.pdf, table 89
|
||||
@param name Profile Name (e.g "CD-RW", unknown profiles have empty name)
|
||||
@return 1 profile is valid, 0 no profile info available
|
||||
Note: libburn currently writes only to profiles 0x09 "CD-R", 0x0a "CD-RW".
|
||||
*/
|
||||
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80]);
|
||||
|
||||
@ -1177,6 +1227,31 @@ int burn_drive_get_min_write_speed(struct burn_drive *d);
|
||||
*/
|
||||
int burn_drive_get_read_speed(struct burn_drive *d);
|
||||
|
||||
|
||||
/* ts A61226 */
|
||||
/** Obtain a copy of the current speed descriptor list. The drive's list gets
|
||||
updated on various occasions such as burn_drive_grab() but the copy
|
||||
obtained here stays untouched. It has to be disposed via
|
||||
burn_drive_free_speedlist() when it is not longer needed. Speeds
|
||||
may appear several times in the list. The list content depends much on
|
||||
drive and media type. It seems that .source == 1 applies mostly to CD media
|
||||
whereas .source == 2 applies to any media.
|
||||
@param d Drive to query
|
||||
@param speed_list The copy. If empty, *speed_list gets returned as NULL.
|
||||
@return 1=success , 0=list empty , <0 severe error
|
||||
*/
|
||||
int burn_drive_get_speedlist(struct burn_drive *d,
|
||||
struct burn_speed_descriptor **speed_list);
|
||||
|
||||
/* ts A61226 */
|
||||
/** Dispose a speed descriptor list copy which was obtained by
|
||||
burn_drive_get_speedlist().
|
||||
@param speed_list The list copy. *speed_list gets set to NULL.
|
||||
@return 1=list disposed , 0= *speedlist was already NULL
|
||||
*/
|
||||
int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list);
|
||||
|
||||
|
||||
/** Gets a copy of the toc_entry structure associated with a track
|
||||
@param t Track to get the entry from
|
||||
@param entry Struct for the library to fill out
|
||||
|
@ -910,7 +910,7 @@ int mmc_set_streaming(struct burn_drive *d, int r_speed, int w_speed)
|
||||
if (d->mdata->max_end_lba > 0)
|
||||
end_lba = d->mdata->max_end_lba - 1;
|
||||
|
||||
sprintf(msg, "mmc_set_streaming: end_lba=%lu , r=%d , w=%d",
|
||||
sprintf(msg, "mmc_set_streaming: end_lba=%d , r=%d , w=%d",
|
||||
end_lba, r_speed, w_speed);
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||
@ -1202,7 +1202,7 @@ int mmc_format_unit(struct burn_drive *d)
|
||||
int mmc_get_write_performance(struct burn_drive *d)
|
||||
{
|
||||
struct buffer buf;
|
||||
int len, i, b, pass, was_exact_bit = 0, max_descr, num_descr;
|
||||
int len, i, b, max_descr, num_descr, ret;
|
||||
int exact_bit, read_speed, write_speed;
|
||||
/* if this call delivers usable data then they should override
|
||||
previously recorded min/max speed and not compete with them */
|
||||
@ -1211,12 +1211,16 @@ int mmc_get_write_performance(struct burn_drive *d)
|
||||
struct command c;
|
||||
unsigned long end_lba;
|
||||
unsigned char *pd;
|
||||
struct burn_speed_descriptor *sd;
|
||||
|
||||
/* A61225 : 1 = report about speed descriptors */
|
||||
static int speed_debug = 0;
|
||||
|
||||
mmc_function_spy("mmc_get_write_performance");
|
||||
|
||||
if (d->current_profile <= 0)
|
||||
mmc_get_configuration(d);
|
||||
|
||||
memcpy(c.opcode, MMC_GET_PERFORMANCE, sizeof(MMC_GET_PERFORMANCE));
|
||||
max_descr = ( BUFFER_SIZE - 8 ) / 16 - 1;
|
||||
|
||||
@ -1248,7 +1252,7 @@ int mmc_get_write_performance(struct burn_drive *d)
|
||||
num_descr = ( len - 4 ) / 16;
|
||||
if (num_descr > max_descr)
|
||||
num_descr = max_descr;
|
||||
for (pass = 0; pass < 2; pass++) for (i = 0; i < num_descr; i++) {
|
||||
for (i = 0; i < num_descr; i++) {
|
||||
exact_bit = !!(pd[8 + i*16] & 2);
|
||||
end_lba = read_speed = write_speed = 0;
|
||||
for (b = 0; b < 4 ; b++) {
|
||||
@ -1259,16 +1263,30 @@ int mmc_get_write_performance(struct burn_drive *d)
|
||||
if (end_lba > 0x7ffffffe)
|
||||
end_lba = 0x7ffffffe;
|
||||
|
||||
if (pass == 0 && speed_debug)
|
||||
if (speed_debug)
|
||||
fprintf(stderr,
|
||||
"LIBBURN_DEBUG: kB/s: write=%d read=%d end=%lu exact=%d\n",
|
||||
write_speed, read_speed, end_lba, exact_bit);
|
||||
|
||||
if (pass == 0 && !exact_bit)
|
||||
continue;
|
||||
if (pass == 1 && was_exact_bit)
|
||||
continue;
|
||||
was_exact_bit |= exact_bit;
|
||||
/* ts A61226 */
|
||||
ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
|
||||
NULL, d->mdata->speed_descriptors, 0);
|
||||
if (ret > 0) {
|
||||
sd = d->mdata->speed_descriptors;
|
||||
sd->source = 2;
|
||||
if (d->current_profile > 0) {
|
||||
sd->profile_loaded = d->current_profile;
|
||||
strcpy(sd->profile_name,
|
||||
d->current_profile_text);
|
||||
}
|
||||
sd->wrc = (pd[8 + i*16] >> 3 ) & 3;
|
||||
sd->exact = exact_bit;
|
||||
sd->mrw = pd[8 + i*16] & 1;
|
||||
sd->end_lba = end_lba;
|
||||
sd->write_speed = write_speed;
|
||||
sd->read_speed = read_speed;
|
||||
}
|
||||
|
||||
if (end_lba > d->mdata->max_end_lba)
|
||||
d->mdata->max_end_lba = end_lba;
|
||||
if (end_lba < d->mdata->min_end_lba)
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libburn.h"
|
||||
#include "transport.h"
|
||||
#include "spc.h"
|
||||
#include "mmc.h"
|
||||
@ -135,6 +136,7 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
int size, page_length, num_write_speeds = 0, i, speed, ret;
|
||||
unsigned char *page;
|
||||
struct command c;
|
||||
struct burn_speed_descriptor *sd;
|
||||
|
||||
/* ts A61225 : 1 = report about post-MMC-1 speed descriptors */
|
||||
static int speed_debug = 0;
|
||||
@ -161,6 +163,9 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
*/
|
||||
page_length = page[1];
|
||||
|
||||
m->valid = 0;
|
||||
burn_mdata_free_subs(m);
|
||||
|
||||
m->buffer_size = page[12] * 256 + page[13];
|
||||
m->dvdram_read = page[2] & 32;
|
||||
m->dvdram_write = page[3] & 32;
|
||||
@ -192,9 +197,11 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
|
||||
m->valid = 1;
|
||||
|
||||
mmc_get_configuration(d);
|
||||
|
||||
/* ts A61225 : end of MMC-1 , begin of MMC-3 */
|
||||
if (page_length < 32) /* no write speed descriptors ? */
|
||||
return;
|
||||
goto try_mmc_get_performance;
|
||||
|
||||
m->cur_write_speed = page[28] * 256 + page[29];
|
||||
|
||||
@ -212,6 +219,21 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
"LIBBURN_DEBUG: write speed #%d = %d kB/s (rc %d)\n",
|
||||
i, speed, page[32 + 4*i +1] & 7);
|
||||
|
||||
/* ts A61226 */
|
||||
ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
|
||||
NULL, d->mdata->speed_descriptors, 0);
|
||||
if (ret > 0) {
|
||||
sd = d->mdata->speed_descriptors;
|
||||
sd->source = 1;
|
||||
if (d->current_profile > 0) {
|
||||
sd->profile_loaded = d->current_profile;
|
||||
strcpy(sd->profile_name,
|
||||
d->current_profile_text);
|
||||
}
|
||||
sd->wrc = (( page[32 + 4*i +1] & 7 ) == 1 );
|
||||
sd->write_speed = speed;
|
||||
}
|
||||
|
||||
if (speed > m->max_write_speed)
|
||||
m->max_write_speed = speed;
|
||||
if (speed < m->min_write_speed)
|
||||
@ -223,13 +245,13 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
"LIBBURN_DEBUG: 5Ah,2Ah min_write_speed = %d , max_write_speed = %d\n",
|
||||
m->min_write_speed, m->max_write_speed);
|
||||
|
||||
try_mmc_get_performance:;
|
||||
ret = mmc_get_write_performance(d);
|
||||
|
||||
if (ret > 0 && speed_debug)
|
||||
fprintf(stderr,
|
||||
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
|
||||
m->min_write_speed, m->max_write_speed);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -551,6 +573,7 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
|
||||
d->idata->valid = 0;
|
||||
d->mdata = malloc(sizeof(struct scsi_mode_data));
|
||||
d->mdata->valid = 0;
|
||||
d->mdata->speed_descriptors = NULL;
|
||||
|
||||
/* ts A61007 : obsolete Assert in drive_getcaps() */
|
||||
if(d->idata == NULL || d->mdata == NULL) {
|
||||
|
@ -65,6 +65,7 @@ struct burn_scsi_inquiry_data
|
||||
int valid;
|
||||
};
|
||||
|
||||
|
||||
struct scsi_mode_data
|
||||
{
|
||||
int buffer_size;
|
||||
@ -88,6 +89,7 @@ struct scsi_mode_data
|
||||
Speed values go into *_*_speed */
|
||||
int min_end_lba;
|
||||
int max_end_lba;
|
||||
struct burn_speed_descriptor *speed_descriptors;
|
||||
|
||||
int cur_read_speed;
|
||||
int cur_write_speed;
|
||||
|
Loading…
Reference in New Issue
Block a user