From c5bc9f6de79b4dd7d0602c418ebd24c66b03f74f Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 17 Apr 2019 11:23:59 +0200 Subject: [PATCH] New API calls burn_drive_get_feature_codes(), burn_drive_get_feature() --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 60 +++++ libburn/libburn.h | 49 ++++ libburn/libburn.ver | 2 + libburn/mmc.c | 469 ++++++++++++++++++++++++++++++++++++ 5 files changed, 581 insertions(+), 1 deletion(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 1f2dd2b..4a7ac5c 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2019.04.17.085941" +#define Cdrskin_timestamP "2019.04.17.092323" diff --git a/libburn/drive.c b/libburn/drive.c index d4e1bb4..a043ef7 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -3677,3 +3677,63 @@ int burn_drive_get_immed(struct burn_drive *drive) } +/* ts B90412 , API */ +int burn_drive_get_feature(struct burn_drive *d, unsigned int feature_code, + unsigned char *flags, + unsigned char *additional_length, + unsigned char **feature_data, + char **feature_text) +{ + int ret, i; + struct burn_feature_descr *descr; + + *flags = 0; + *additional_length = 0; + *feature_data = NULL; + if (feature_text != NULL) + *feature_text = NULL; + if (!burn_drive_has_feature(d, feature_code, &descr, 0)) + return 0; + *flags = descr->flags; + *additional_length = descr->data_lenght; + if (*additional_length > 0) + BURN_ALLOC_MEM(*feature_data, unsigned char, + *additional_length); + for (i = 0; i < *additional_length; i++) + (*feature_data)[i] = descr->data[i]; + + if (feature_text != NULL) { + ret = burn_make_feature_text(d, feature_code, *flags, + *additional_length, *feature_data, + feature_text, 0); + } else { + ret = 1; + } +ex: + return ret; +} + + +/* ts B90412 , API */ +void burn_drive_get_feature_codes(struct burn_drive *d, + int *count, unsigned int **feature_codes) +{ + struct burn_feature_descr *o; + int to_alloc; + + *count = 0; + *feature_codes = NULL; + for (o = d->features; o != NULL; o = o->next) + (*count)++; + if (*count == 0) + return; + to_alloc = *count; + *count = 0; + BURN_ALLOC_MEM_VOID(*feature_codes, unsigned int, to_alloc); + for (o = d->features; o != NULL; o = o->next) { + (*feature_codes)[*count] = o->feature_code; + (*count)++; + } +ex:; +} + diff --git a/libburn/libburn.h b/libburn/libburn.h index 1cd4be0..7e361f6 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -3429,6 +3429,55 @@ int burn_drive_get_all_profiles(struct burn_drive *d, int *num_profiles, int burn_obtain_profile_name(int profile_code, char name[80]); +/* ts B90414 */ +/** Obtains the list of SCSI Feature Codes from feature descriptors which + were obtained from the drive when it was most recently acquired or + re-assessed. + @param d Drive to query + @param count Returns the number of allocated elements in feature_codes + @param feature_codes Returns the allocated array of feature codes. + If returned *feature_codes is not NULL, dispose it + by free() when it is no longer needed. + @since 1.5.2 +*/ +void burn_drive_get_feature_codes(struct burn_drive *d, + int *count, unsigned int **feature_codes); + +/* ts B90414 */ +/** Obtains the fields and data of a particular feature which were obtained + from the drive when it was last acquired or re-assessed. See MMC specs + for full detail. + @param d Drive to query + @param feature_code A number as learned by burn_drive_get_feature_codes() + @param flags Returns byte 2 of the feature descriptor: + bit0= Current + bit1= Persistent + bit2-5= Version + @param additional_length Returns byte 3 of descriptor. + This is the size of feature_data. + @param feature_data Returns further bytes of descriptor. + If returned *feature_data is not NULL, dispose it + by free() when it is no longer needed. + @param feature_text Returns text representation of the feature descriptor: + Code +/- : Name : Version,P/N : Hex bytes : Parsed info + Current features are marked by "+", others by "-". + Persistent features are marked by "P", others by "N". + feature_text may be submitted as NULL. In this case + no text is generated and returned. + If returned *feature_text is not NULL, dispose it + by free() when it is no longer needed. + @return 0 feature descriptor is not present + -1 out of memory + >0 success + @since 1.5.2 +*/ +int burn_drive_get_feature(struct burn_drive *d, unsigned int feature_code, + unsigned char *flags, + unsigned char *additional_length, + unsigned char **feature_data, + char **feature_text); + + /** Gets the maximum write speed for a drive and eventually loaded media. The return value might change by the media type of already loaded media, again by call burn_drive_grab() and again by call burn_disc_read_atip(). diff --git a/libburn/libburn.ver b/libburn/libburn.ver index 8d94627..9dd51c8 100644 --- a/libburn/libburn.ver +++ b/libburn/libburn.ver @@ -54,6 +54,8 @@ burn_drive_get_bd_r_pow; burn_drive_get_best_speed; burn_drive_get_disc; burn_drive_get_drive_role; +burn_drive_get_feature; +burn_drive_get_feature_codes; burn_drive_get_immed; burn_drive_get_media_sno; burn_drive_get_min_write_speed; diff --git a/libburn/mmc.c b/libburn/mmc.c index 00c03c7..3e46c9e 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -5440,3 +5440,472 @@ int mmc_setup_drive(struct burn_drive *d) return 1; } + +/* @param flag bit0= really add to text, else only count +*/ +static void burn__add_to_text(char *text, int *text_len, char *to_add, + int flag) +{ + (*text_len) += strlen(to_add); + if (flag & 1) + strcat(text, to_add); +} + +/* @param flag bit0= really add to text, else only count +*/ +static void burn__add_hex_to_text(char *text, int *text_len, + unsigned char *to_add, int add_length, + int flag) +{ + int i, l; + + (*text_len) += 3 * add_length; + if (!(flag & 1)) + return; + l = strlen(text); + for (i = 0; i < add_length; i++) + sprintf(text + l + 3 * i, " %2.2x", to_add[i]); +} + +int burn_make_feature_text(struct burn_drive *d, unsigned int feature_code, + unsigned char flags, + unsigned char additional_length, + unsigned char *feature_data, + char **text, int flag) +{ + char *feature_name, addon[320], *cpt; + int text_len, ret, i, pass; + unsigned int phys_is, lmt, num; + + static unsigned short feature_codes[] = { + 0x00, 0x01, 0x02, 0x03, + 0x04, 0x10, 0x1d, 0x1e, + 0x1f, 0x20, 0x21, 0x22, + 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2a, + 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x33, 0x37, 0x38, + 0x3a, 0x3b, 0x40, 0x41, + 0x42, 0x50, 0x51, 0x80, + 0x100, 0x101, 0x102, 0x104, + 0x105, 0x106, 0x107, 0x108, + 0x109, 0x10a, 0x10b, 0x10c, + 0x10d, 0x110, + 0xffff + }; + static char feature_names[][40] = { + "Profile List", "Core", "Morphing", "Removable Medium", + "Write Protect", "Random Readable", "Multi-Read", "CD Read", + "DVD Read", "Random Writable", + "Incremental Streaming Writable", "Sector Erasable", + "Formattable", "Hardware Defect Management", "Write Once", + "Restricted Overwrite", + "CD-RW CAV Write", "MRW", "Enhanced Defect Reporting", + "DVD+RW", + "DVD+R", "Rigid Restricted Overwrite", "CD Track at Once", + "CD Mastering", + "DVD-R/-RW Write", "Layer Jump Recording", + "CD-RW Media Write Support", "BD-R POW", + "DVD+RW Dual Layer", "DVD+R Dual Layer", "BD Read Feature", + "BD Write Feature", + "TSR", "HD DVD Read", "HD DVD Write", "Hybrid Disc", + "Power Management", "SMART", "Embedded Changer", + "Microcode Upgrade", + "Timeout", "DVD-CSS", "Real Time Streaming", + "Drive Serial Number", + "Media Serial Number", "DCBs", "DVD CPRM", + "Firmware Information", + "AACS", "VCPS", + "" + }; + static unsigned short legacy_codes[] = { + 0x30, 0x31, 0x32, 0x103, 0xffff + }; + static unsigned int phys_is_codes[] = { + 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0xffff, + 0xffffffff + }; + static char phys_is_names[][40] = { + "Unspecified", "SCSI_Family", "ATAPI", "IEEE_1394-1995", + "IEEE_1394A", "Fibre_Channel", "IEEE_1394B", "Serial_ATAPI", + "USB", "Vendor_Unique", + "" + }; + static char load_mech_names[8][40] = { + "Caddy/Slot", "Tray", "Pop-up", "(Reserved)", + "Embedded_changer_individually", "Embedded_changer_magazine", + "(Reserved)", "(Reserved)" + }; + + feature_name = "(Reserved)"; + for (i = 0; feature_codes[i] != 0xffff; i++) { + if (feature_codes[i] == feature_code) { + feature_name = feature_names[i]; + break; + } + } + if (feature_codes[i] == 0xffff) { + for (i = 0; legacy_codes[i] != 0xffff; i++) { + if (legacy_codes[i] == feature_code) { + feature_name = "(Legacy)"; + break; + } + } + } + if (feature_code >= 0xff00 && feature_code <= 0xffff) + feature_name = "(Vendor Specific)"; + + *text = NULL; + for (pass = 0; pass < 2; pass++) { + if (pass == 1) { + BURN_ALLOC_MEM(*text, char, text_len + 1); + } + text_len = 0; + + sprintf(addon, "%4.4x %c : ", feature_code, + (flags & 1) ? '+' : '-'); + burn__add_to_text(*text, &text_len, addon, pass); + + burn__add_to_text(*text, &text_len, feature_name, pass); + + /* Version, Persistent, Current */ + sprintf(addon, " : %1.1x,%c :", + (flags >> 2) & 15, (flags & 2) ? 'P' : 'N'); + burn__add_to_text(*text, &text_len, addon, pass); + + burn__add_hex_to_text(*text, &text_len, + feature_data, (int) additional_length, pass); + burn__add_to_text(*text, &text_len, " :", pass); + + if (feature_code == 0x01 && additional_length >= 4) { + /* Core : Physical Interface Standard , INQ2, DBE */ + phys_is = mmc_four_char_to_int(feature_data); + cpt = "(Not_Recognizable)"; + for (i = 0; phys_is_codes[i] != 0xffffffff; i++) { + if (phys_is_codes[i] == phys_is) { + cpt = phys_is_names[i]; + break; + } + + } + num = 0; + if (additional_length >= 9) + num = feature_data[8]; + sprintf(addon, + " PhysInterface=%x/%s , INQ2=%d , DBE=%d", + phys_is, cpt, (num >> 1) & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x03 && additional_length >= 1) { + /* Removable Medium : Lock, Pvnt Jmpr, Eject, + Loading mechanism Type + */ + num = feature_data[0]; + lmt = (num >> 5) & 7; + sprintf(addon, + " LoadMechType=%x/%s , Eject=%d , PvntJmpr=%d , Lock=%d", + lmt, load_mech_names[lmt], (num >> 3) & 1, + (num >> 2) & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x10 && additional_length >= 4) { + /* Random Readable: Logical Block Size, Blocking */ + num = 0; + if (additional_length >= 6) + num = (feature_data[4] << 8) | feature_data[5]; + sprintf(addon, " BlockSize=%d , Blocking=%u", + mmc_four_char_to_int(feature_data), num); + num = 0; + if (additional_length >= 7) + num = feature_data[6]; + sprintf(addon + strlen(addon), " , PP=%d", num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x1e && additional_length >= 1) { + /* CD Read: DAP, C2 Flags, CD-Text */ + sprintf(addon, " DAP=%d , C2Flags=%d , CDText=%d", + (feature_data[0] >> 7) & 1, + (feature_data[0] >> 1) & 1, + feature_data[0] & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x1f && additional_length >= 1) { + /* DVD Read: MULTI110, Dual-R */ + num = 0; + if (additional_length >= 3) + num = feature_data[2]; + sprintf(addon, " MULTI10=%d , DualR=%d", + feature_data[0] & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x20 && additional_length >= 4) { + /* Random Writable: Last LBA, Logical Block Size, + Blocking, PP */ + num = 0; + if (additional_length >= 8) + num = mmc_four_char_to_int(feature_data + 4); + sprintf(addon, " LastLBA=%d , BlockSize=%u", + mmc_four_char_to_int(feature_data), num); + num = 0; + if (additional_length >= 10) + num = (feature_data[8] << 8) | feature_data[9]; + sprintf(addon + strlen(addon), " , Blocking=%u", num); + num = 0; + if (additional_length >= 11) + num = feature_data[10]; + sprintf(addon + strlen(addon), " , PP=%u", num); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x21 && additional_length >= 2) { + /* Incremental Streaming Writable : + Data Block Types , TRIO , ARSV , BUF + Number of Link Sizes + */ + num = 0; + if (additional_length >= 3) + num = feature_data[2]; + sprintf(addon, + " DataBlockTypes=%2.2x%2.2x , TRIO=%d , ARSV=%d , BUF=%d", + feature_data[0], feature_data[1], + (num >> 2) & 1, (num >> 1) & 1, num & 1); + num = 0; + if (additional_length >= 4) + num = feature_data[3]; + sprintf(addon + strlen(addon), " , NumLinkSizes=%d", + num); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x23 && additional_length >= 1) { + /* Formattable: RENoSA, Expand, QCert, Cert, RRM */ + num = feature_data[0]; + sprintf(addon, + " RENoSA=%d , Expand=%d , QCert=%d , Cert=%d", + (num >> 3) & 1, (num >> 2) & 1, + (num >> 1) & 1, num & 1); + num = 0; + if (additional_length >= 5) + num = feature_data[4]; + sprintf(addon + strlen(addon), " , RRM=%d", num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x24 && additional_length >= 1) { + /* Defect Management : SSA */ + sprintf(addon, " SSA=%d", (feature_data[0] >> 7) & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x28 && additional_length >= 1) { + /* MRW */ + num = feature_data[0]; + sprintf(addon, + " DVDPWrite=%d , DVDPRead=%d , CDWrite=%d", + (num >> 2) & 1, (num >> 1) & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x2a && additional_length >= 1) { + /* DVD+RW */ + num = 0; + if (additional_length >= 2) + num = feature_data[1]; + sprintf(addon, + " Write=%d , QuickStart=%d , CloseOnly=%d", + feature_data[0] & 1, (num >> 1) & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x2b && additional_length >= 1) { + /* DVD+R */ + sprintf(addon, " Write=%d", feature_data[0] & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x2c && additional_length >= 1) { + /* Rigid Restricted Overwrite */ + num = feature_data[0]; + sprintf(addon, + " DSDG=%d , DSDR=%d , Intermediate=%d , Blank=%d", + (num >> 3) & 1, (num >> 2) & 1, + (num >> 1) & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x2d && additional_length >= 1) { + /* CD Track at Once */ + num= feature_data[0]; + sprintf(addon, + " BUF=%d , RWRaw=%d , RWPack=%d , TestWrite=%d , CD-RW=%d , RWSubcode=%d", + (num >> 6) & 1, (num >> 4) & 1, + (num >> 3) & 1, (num >> 2) & 1, + (num >> 1) & 1, num & 1); + num = 0; + if (additional_length >= 4) + num = (feature_data[2] << 8) | feature_data[3]; + sprintf(addon + strlen(addon), " , DataTypeSupp=%4.4x", + num); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x2e && additional_length >= 1) { + /* CD Mastering (SAO) */ + num = feature_data[0]; + sprintf(addon, + " BUF=%d , SAO=%d , RawMS=%d , Raw=%d , TestWrite=%d , CD-RW=%d , RW=%d", + (num >> 6) & 1, (num >> 5) & 1, (num >> 4) & 1, + (num >> 3) & 1, (num >> 2) & 1, + (num >> 1) & 1, num & 1); + num = 0; + if (additional_length >= 4) + num = (feature_data[1] << 16) | + (feature_data[2] << 8) | feature_data[3]; + sprintf(addon + strlen(addon), + " , MaxCueSheetLen=%u", num); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x2f && additional_length >= 1) { + /* DVD-R/RW Write */ + num = feature_data[0]; + sprintf(addon, + " BUF=%d , RDL=%d , TestWrite=%d , DVDRW=%d", + (num >> 6) & 1, (num >> 3) & 1, + (num >> 2) & 1, (num >> 1) & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x33 && additional_length >= 4) { + /* Layer Jump Recording */ + sprintf(addon, " NumLinkSizes=%d", feature_data[3]); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x37 && additional_length >= 2) { + /* CD-RW Media Write Support */ + addon[0]= 0; + for (i = 7; i >= 0; i--) { + sprintf(addon + strlen(addon), + " Subtype%d=%d%s", + i, (feature_data[1] >> i) & 1, + i > 0 ? " ," : ""); + } + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x3a && additional_length >= 2) { + /* DVD+RW Dual Layer */ + sprintf(addon, + " Write=%d , QuickStart=%d , CloseOnly=%d", + feature_data[0] & 1, + (feature_data[1] >> 1) & 1, + feature_data[1] & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x3b && additional_length >= 1) { + /* DVD+R Dual Layer */ + sprintf(addon, " Write=%d", feature_data[0] & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x50 && additional_length >= 1) { + /* HD DVD Read */ + num = 0; + if (additional_length >= 3) + num = feature_data[2]; + sprintf(addon, " HDDVDR=%d , HDDVDRAM=%d", + feature_data[0] & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x51 && additional_length >= 1) { + /* HD DVD Write */ + num = 0; + if (additional_length >= 3) + num = feature_data[2]; + sprintf(addon, " HDDVDR=%d , HDDVDRAM=%d", + feature_data[0] & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x101 && additional_length >= 1) { + /* SMART */ + sprintf(addon, " PP=%d", feature_data[0] & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x102 && additional_length >= 1) { + /* Embedded Changer */ + num = 0; + if (additional_length >= 4) + num = feature_data[3]; + sprintf(addon, " SCC=%d , SDP=%d , HighestSlotNo=%u", + (feature_data[0] >> 4) & 1, + (feature_data[0] >> 2) & 1, num & 31); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x105 && additional_length >= 1) { + /* Timeout */ + num = 0; + if (additional_length >= 4) + num = (feature_data[2] << 8) | feature_data[3]; + sprintf(addon, " Group3=%d , UnitLength=%u", + feature_data[0] & 1, num); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x106 && additional_length >= 4) { + /* DVD CSS */ + sprintf(addon, " CSSVersion=%d", + (int) feature_data[3]); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x107 && additional_length >= 1) { + /* Real Time Streaming */ + num = feature_data[0]; + sprintf(addon, + " RBCB=%d , SCS=%d , MP2A=%d , WSPD=%d , SW=%d", + (num >> 4) & 1, (num >> 3) & 1, (num >> 2) & 1, + (num >> 1) & 1, num & 1); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x108 && additional_length >= 1) { + /* Drive Serial Number */ + strcpy(addon, " SerialNumber="); + for (i = 0; i < additional_length; i++) { + num = feature_data[i]; + if (num >= ' ' && num < 127) + addon[14 + i] = feature_data[i]; + else + addon[14 + i] = '?'; + } + addon[14 + i] = 0; + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x10a && additional_length >= 4) { + /* DCBs */ + addon[0] = 0; + for (i = 0; i < additional_length / 4; i++) + sprintf(addon + strlen(addon), + " SuppEntry%d=%2.2x%2.2x%2.2x%2.2x%s", + i, feature_data[i * 4 + 0], + feature_data[i * 4 + 1], + feature_data[i * 4 + 2], + feature_data[i * 4 + 3], + i < additional_length / 4 - 1 ? + " ," : ""); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x10b && additional_length >= 4) { + /* DVD CPRM */ + sprintf(addon, " CPRMVersion=%d", feature_data[3]); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x10c && additional_length >= 14) { + /* Firmware Information */ + strcpy(addon, " Date="); + for (i = 0; i < 14; i += 2) + sprintf(addon + 6 + i, "%2.2d", + ((feature_data[i] & 0xf) % 10) * 10 + + ((feature_data[i + 1] & 0xf) % 10)); + burn__add_to_text(*text, &text_len, addon, pass); + + } else if (feature_code == 0x10d && additional_length >= 4) { + /* AACS */ + sprintf(addon, + " BNG=%d , BlockCountBindingNonce=%d , NumberAGIDs=%d , AACSVersion=%d", + feature_data[0] & 1, feature_data[1], + feature_data[2] & 0xf, feature_data[3]); + burn__add_to_text(*text, &text_len, addon, pass); + + } + } + ret = 1; +ex:; + return ret; +}