1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2
3 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
4 Copyright (c) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net>
5 Provided under GPL version 2 or later.
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include "../config.h"
10 #endif
11
12
13 /* ts A61009 */
14 /* #include <a ssert.h> */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <sys/time.h>
21 #include <pthread.h>
22 #include <ctype.h>
23
24 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
25 #ifndef O_BINARY
26 #define O_BINARY 0
27 #endif
28
29 #include "error.h"
30 #include "sector.h"
31 #include "libburn.h"
32 #include "transport.h"
33 #include "mmc.h"
34 #include "spc.h"
35 #include "drive.h"
36 #include "debug.h"
37 #include "toc.h"
38 #include "structure.h"
39 #include "options.h"
40 #include "util.h"
41 #include "init.h"
42
43
44 /* ts A70223 : in init.c */
45 extern int burn_support_untested_profiles;
46
47 static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len);
48
49
50 #ifdef Libburn_log_in_and_out_streaM
51 /* <<< ts A61031 */
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <fcntl.h>
55 #endif /* Libburn_log_in_and_out_streaM */
56
57
58 /* ts A61005 */
59 #include "libdax_msgs.h"
60 extern struct libdax_msgs *libdax_messenger;
61
62
63 /* ts A61219 : Based on knowledge from dvd+rw-tools-7.0 and mmc5r03c.pdf */
64 #define Libburn_support_dvd_plus_rW 1
65
66 /* ts A61229 */
67 #define Libburn_support_dvd_minusrw_overW 1
68
69 /* ts A70112 */
70 /* ts A80410 : applies to BD-RE too */
71 #define Libburn_support_dvd_raM 1
72
73 /* ts A70129 */
74 #define Libburn_support_dvd_r_seQ 1
75
76 /* ts A70306 */
77 #define Libburn_support_dvd_plus_R 1
78
79 /* ts A70509 : handling 0x41 as read-only type */
80 #define Libburn_support_bd_r_readonlY 1
81
82 /* ts A81208 */
83 #define Libburn_support_bd_plus_r_srM 1
84
85
86 /* ts A80410 : <<< Dangerous experiment: Pretend that DVD-RAM is BD-RE
87 # define Libburn_dvd_ram_as_bd_rE yes
88 */
89 /* ts A80509 : <<< Experiment: pretend that DVD-ROM and CD-ROM are other media
90 like BD-ROM (0x40), BD-R seq (0x41), BD-R random (0x42)
91 # define Libburn_rom_as_profilE 0x40
92 */
93
94
95 /* ts A80425 : Prevents command FORMAT UNIT for DVD-RAM or BD-RE.
96 Useful only to test the selection of format descriptors without
97 actually formatting the media.
98 # define Libburn_do_not_format_dvd_ram_or_bd_rE 1
99 */
100
101
102 /* ts A90603 : Simulate the command restrictions of an old MMC-1 drive
103 # define Libisofs_simulate_old_mmc1_drivE 1
104 */
105
106
107 /* DVD/BD progress report:
108 ts A61219 : It seems to work with a used (i.e. thoroughly formatted) DVD+RW.
109 Error messages of class DEBUG appear because of inability to
110 read TOC or track info. Nevertheless, the written images verify.
111 ts A61220 : Burned to a virgin DVD+RW by help of new mmc_format_unit()
112 (did not test whether it would work without). Burned to a
113 not completely formatted DVD+RW. (Had worked before without
114 mmc_format_unit() but i did not exceed the formatted range
115 as reported by dvd+rw-mediainfo.)
116 ts A61221 : Speed setting now works for both of my drives. The according
117 functions in dvd+rw-tools are a bit intimidating to the reader.
118 I hope it is possible to leave much of this to the drive.
119 And if it fails ... well, it's only speed setting. :))
120 ts A61229 : Burned to several DVD-RW formatted to mode Restricted Overwrite
121 by dvd+rw-format. Needs Libburn_support_dvd_minusrw_overW.
122 ts A61230 : Other than growisofs, libburn does not send a mode page 5 for
123 such DVD-RW (which the MMC-5 standard does deprecate) and it
124 really seems to work without such a page.
125 ts A70101 : Formatted DVD-RW media. Success is varying with media, but
126 dvd+rw-format does not do better with the same media.
127 ts A70112 : Support for writing to DVD-RAM.
128 ts A70130 : Burned a first non-multi sequential DVD-RW. Feature 0021h
129 Incremental Recording vanishes after that and media thus gets
130 not recognized as suitable any more.
131 After a run with -multi another disc still offers 0021h .
132 dvd+rw-mediainfo shows two tracks. The second, an afio archive
133 is readable by afio. Third and forth veryfy too. Suddenly
134 dvd+rw-mediainfo sees lba 0 with track 2. But #2 still verifies
135 if one knows its address.
136 ts A70203 : DVD-RW need to get blanked fully. Then feature 0021h persists.
137 Meanwhile Incremental streaming is supported like CD TAO:
138 with unpredicted size, multi-track, multi-session.
139 ts A70205 : Beginning to implement DVD-R[W] DAO : single track and session,
140 size prediction mandatory.
141 ts A70208 : Finally made tests with DVD-R. Worked exactly as new DVD-RW.
142 ts A70306 : Implemented DVD+R (always -multi for now)
143 ts A70330 : Allowed finalizing of DVD+R.
144 ts A80228 : Made DVD+R/DL support official after nightmorph reported success
145 in http://libburnia-project.org/ticket/13
146 ts A80416 : drive->do_stream_recording brings DVD-RAM to full nominal
147 writing speed at cost of no defect management.
148 ts A80416 : Giulio Orsero reports success with BD-RE writing. With
149 drive->do_stream_recording it does full nominal speed.
150 ts A80506 : Giulio Orsero reports success with BD-RE formatting.
151 BD-RE is now an officially supported profile.
152 ts A81209 : The first two sessions have been written to BD-R SRM
153 (auto formatted without Defect Management).
154 ts A90107 : BD-R is now supported media type
155 */
156
157 /* ts A70519 : With MMC commands of data direction FROM_DRIVE:
158 Made struct command.dxfer_len equal to Allocation Length
159 of MMC commands. Made sure that not more bytes are allowed
160 for transfer than there are available.
161 */
162
163
164 /* ts A70711 Trying to keep writing from clogging the SCSI driver due to
165 full buffer at burner drive: 0=waiting disabled, 1=enabled
166 These are only defaults which can be overwritten by
167 burn_drive_set_buffer_waiting()
168 */
169 #define Libburn_wait_for_buffer_freE 0
170 #define Libburn_wait_for_buffer_min_useC 10000
171 #define Libburn_wait_for_buffer_max_useC 100000
172 #define Libburn_wait_for_buffer_tio_seC 120
173 #define Libburn_wait_for_buffer_min_perC 65
174 #define Libburn_wait_for_buffer_max_perC 95
175
176 /* ts B31107 The minimum values to be applied if maximum read speed is
177 requested. Some drives tell only the currently set speed and
178 thus cannot be made faster by using the highest told value.
179 (The fractions get added or subtracted to yield an integer
180 number on the safe side of the intended limit.)
181 */
182 #define Libburn_cd_max_read_speeD (52 * 150)
183 #define Libburn_dvd_max_read_speeD (24 * 1385)
184 #define Libburn_bd_max_read_speeD (20 * 4495.625 + 0.5)
185
186 /* ts B31114 The maximum values for minimum speed
187 */
188 #define Libburn_cd_min_read_speeD ( 1 * 150)
189 #define Libburn_dvd_min_read_speeD ( 1 * 1385)
190 #define Libburn_bd_min_read_speeD ( 1 * 4495.625 - 0.625)
191
192
193 static unsigned char MMC_GET_MSINFO[] =
194 { 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 };
195 static unsigned char MMC_GET_TOC[] = { 0x43, 2, 2, 0, 0, 0, 0, 16, 0, 0 };
196 static unsigned char MMC_GET_TOC_FMT0[] = { 0x43, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
197 static unsigned char MMC_GET_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 };
198 static unsigned char MMC_GET_LEADTEXT[] = { 0x43, 2, 5, 0, 0, 0, 0, 4, 0, 0 };
199 static unsigned char MMC_GET_DISC_INFO[] =
200 { 0x51, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
201 static unsigned char MMC_READ_CD[] = { 0xBE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
202 static unsigned char MMC_BLANK[] = { 0xA1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
203 static unsigned char MMC_SEND_OPC[] = { 0x54, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
204 static unsigned char MMC_SET_SPEED[] =
205 { 0xBB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
206 static unsigned char MMC_WRITE_12[] =
207 { 0xAA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
208 static unsigned char MMC_WRITE_10[] = { 0x2A, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
209
210 /* ts A61201 : inserted 0, before 16, */
211 static unsigned char MMC_GET_CONFIGURATION[] =
212 { 0x46, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
213
214 static unsigned char MMC_SYNC_CACHE[] = { 0x35, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
215 static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 0x7e, 0, 0, 0, 8, 0 };
216 static unsigned char MMC_CLOSE[] = { 0x5B, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
217 static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
218
219 static unsigned char MMC_SEND_CUE_SHEET[] =
220 { 0x5D, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
221
222 /* ts A61023 : get size and free space of drive buffer */
223 static unsigned char MMC_READ_BUFFER_CAPACITY[] =
224 { 0x5C, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
225
226 /* ts A61219 : format DVD+RW (and various others) */
227 static unsigned char MMC_FORMAT_UNIT[] = { 0x04, 0x11, 0, 0, 0, 0 };
228
229 /* ts A61221 :
230 To set speed for DVD media (0xBB is for CD but works on my LG GSA drive) */
231 static unsigned char MMC_SET_STREAMING[] =
232 { 0xB6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
233
234 /* ts A61225 :
235 To obtain write speed descriptors (command can do other things too) */
236 static unsigned char MMC_GET_PERFORMANCE[] =
237 { 0xAC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
238
239 /* ts A70108 : To obtain info about drive and media formatting opportunities */
240 static unsigned char MMC_READ_FORMAT_CAPACITIES[] =
241 { 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0};
242
243 /* ts A70205 : To describe the layout of a DVD-R[W] DAO session */
244 static unsigned char MMC_RESERVE_TRACK[] =
245 { 0x53, 0, 0, 0, 0, 0, 0, 0, 0, 0};
246
247 /* ts A70812 : Read data sectors (for types with 2048 bytes/sector only) */
248 static unsigned char MMC_READ_10[] =
249 { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
250
251 /* ts A81210 : Determine the upper limit of readable data size */
252 static unsigned char MMC_READ_CAPACITY[] =
253 { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0};
254
255 /* ts A90903 : Obtain media type specific information. E.g. manufacturer.
256 */
257 static unsigned char MMC_READ_DISC_STRUCTURE[] =
258 { 0xAD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
259
260 /* ts B21125 : An alternative to BEh READ CD
261 */
262 static unsigned char MMC_READ_CD_MSF[] =
263 { 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
264
265 static int mmc_function_spy_do_tell = 0;
266
mmc_function_spy(struct burn_drive * d,char * text)267 int mmc_function_spy(struct burn_drive *d, char * text)
268 {
269 if (mmc_function_spy_do_tell)
270 fprintf(stderr,"libburn: experimental: mmc_function_spy: %s\n",
271 text);
272 if (d == NULL)
273 return 1;
274 if (d->drive_role != 1) {
275 char msg[4096];
276
277 sprintf(msg, "Emulated drive caught in SCSI adapter \"%s\"",
278 text);
279 libdax_msgs_submit(libdax_messenger, d->global_index,
280 0x0002014c,
281 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
282 msg, 0, 0);
283 d->cancel = 1;
284 return 0;
285 }
286 return 1;
287 }
288
mmc_function_spy_ctrl(int do_tell)289 int mmc_function_spy_ctrl(int do_tell)
290 {
291 mmc_function_spy_do_tell= !!do_tell;
292 return 1;
293 }
294
295
296 /* ts A70201 */
mmc_four_char_to_int(unsigned char * data)297 int mmc_four_char_to_int(unsigned char *data)
298 {
299 return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
300 }
301
302
303 /* ts A70201 */
mmc_int_to_four_char(unsigned char * data,int num)304 int mmc_int_to_four_char(unsigned char *data, int num)
305 {
306 data[0] = (num >> 24) & 0xff;
307 data[1] = (num >> 16) & 0xff;
308 data[2] = (num >> 8) & 0xff;
309 data[3] = num & 0xff;
310 return 1;
311 }
312
313
314 static int mmc_start_for_bit0 = 0;
315
316 /* @param flag bit0= the calling function should need no START UNIT.
317 (Handling depends on mmc_start_for_bit0)
318 */
mmc_start_if_needed(struct burn_drive * d,int flag)319 int mmc_start_if_needed(struct burn_drive *d, int flag)
320 {
321 if (!d->is_stopped)
322 return 2;
323 if ((flag & 1) && !mmc_start_for_bit0)
324 return 2;
325 d->start_unit(d);
326 d->is_stopped = 0;
327 return 1;
328 }
329
330
mmc_send_cue_sheet(struct burn_drive * d,struct cue_sheet * s)331 int mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
332 {
333 struct buffer *buf = NULL;
334 struct command *c;
335
336 c = &(d->casual_command);
337 mmc_start_if_needed(d, 0);
338 if (mmc_function_spy(d, "mmc_send_cue_sheet") <= 0)
339 return 0;
340 BURN_ALLOC_MEM_VOID(buf, struct buffer, 1);
341 scsi_init_command(c, MMC_SEND_CUE_SHEET, sizeof(MMC_SEND_CUE_SHEET));
342 c->retry = 1;
343 c->page = buf;
344 c->page->bytes = s->count * 8;
345 c->page->sectors = 0;
346 c->opcode[6] = (c->page->bytes >> 16) & 0xFF;
347 c->opcode[7] = (c->page->bytes >> 8) & 0xFF;
348 c->opcode[8] = c->page->bytes & 0xFF;
349 c->dir = TO_DRIVE;
350 memcpy(c->page->data, s->data, c->page->bytes);
351 d->issue_command(d, c);
352 ex:;
353 BURN_FREE_MEM(buf);
354 if (c->error) {
355 d->cancel = 1;
356 scsi_notify_error(d, c, c->sense, 18, 2);
357 }
358 return !c->error;
359 }
360
361
362 /* ts A70205 : Announce size of a DVD-R[W] DAO session.
363 @param size The size in bytes to be announced to the drive.
364 It will get rounded up to align to 32 KiB.
365 */
mmc_reserve_track(struct burn_drive * d,off_t size)366 int mmc_reserve_track(struct burn_drive *d, off_t size)
367 {
368 struct command *c;
369 int lba;
370 char msg[80];
371
372 c = &(d->casual_command);
373 mmc_start_if_needed(d, 0);
374 if (mmc_function_spy(d, "mmc_reserve_track") <= 0)
375 return 0;
376
377 scsi_init_command(c, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK));
378 c->retry = 1;
379
380 lba = size / 2048;
381 if (size % 2048)
382 lba++;
383 mmc_int_to_four_char(c->opcode+5, lba);
384
385 sprintf(msg, "reserving track of %d blocks", lba);
386 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
387 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
388 msg, 0, 0);
389
390 c->page = NULL;
391 c->dir = NO_TRANSFER;
392 c->timeout = Libburn_mmc_reserve_timeouT;
393 d->issue_command(d, c);
394 if (c->error) {
395 d->cancel = 1;
396 scsi_notify_error(d, c, c->sense, 18, 2);
397 }
398 return !c->error;
399 }
400
401
402 /* ts A70201 :
403 Common track info fetcher for mmc_get_nwa() and mmc_fake_toc()
404 */
mmc_read_track_info(struct burn_drive * d,int trackno,struct buffer * buf,int alloc_len)405 int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf,
406 int alloc_len)
407 {
408 struct command *c;
409
410 c = &(d->casual_command);
411 mmc_start_if_needed(d, 1);
412 if (mmc_function_spy(d, "mmc_read_track_info") <= 0)
413 return 0;
414
415 scsi_init_command(c, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
416 c->dxfer_len = alloc_len;
417 c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
418 c->opcode[8] = c->dxfer_len & 0xff;
419 c->retry = 1;
420 c->opcode[1] = 1;
421 if(trackno<=0) {
422 if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
423 d->current_profile == 0x12 || d->current_profile == 0x42 ||
424 d->current_profile == 0x43)
425 /* DVD+RW , DVD-RW restricted overwrite , DVD-RAM
426 BD-R random recording, BD-RE */
427 trackno = 1;
428 else if (d->current_profile == 0x10 ||
429 d->current_profile == 0x11 ||
430 d->current_profile == 0x14 ||
431 d->current_profile == 0x15 ||
432 d->current_profile == 0x40 ||
433 d->current_profile == 0x41)
434 /* DVD-ROM , DVD-R[W] Sequential ,
435 BD-ROM , BD-R sequential */
436 trackno = d->last_track_no;
437 else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
438 trackno = 0xFF;
439 }
440 mmc_int_to_four_char(c->opcode + 2, trackno);
441 c->page = buf;
442 memset(buf->data, 0, BUFFER_SIZE);
443 c->dir = FROM_DRIVE;
444 d->issue_command(d, c);
445 if (c->error)
446 return 0;
447 return 1;
448 }
449
450
451 /* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
452 @return 1=nwa is valid , 0=nwa is not valid , -1=error */
453 /* ts A70201 : outsourced 52h READ TRACK INFO command */
mmc_get_nwa(struct burn_drive * d,int trackno,int * lba,int * nwa)454 int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
455 {
456 struct buffer *buf = NULL;
457 int ret, num, alloc_len = 20, err;
458 unsigned char *data;
459 char *msg = NULL;
460
461 if (trackno <= 0)
462 d->next_track_damaged = 0;
463 mmc_start_if_needed(d, 1);
464 if (mmc_function_spy(d, "mmc_get_nwa") <= 0)
465 {ret = -1; goto ex;}
466
467 /* ts B00327 : Avoid to inquire unsuitable media states */
468 if (d->status != BURN_DISC_BLANK && d->status != BURN_DISC_APPENDABLE)
469 {ret = 0; goto ex;}
470
471 BURN_ALLOC_MEM(buf, struct buffer, 1);
472 ret = mmc_read_track_info(d, trackno, buf, alloc_len);
473 if (ret <= 0)
474 goto ex;
475 data = buf->data;
476 *lba = mmc_four_char_to_int(data + 8);
477 *nwa = mmc_four_char_to_int(data + 12);
478 num = mmc_four_char_to_int(data + 16);
479
480 /* Pioneer BD-RW BDR-205 and LITE-ON LTR-48125S return -150 as *nwa
481 of blank media */
482 if (*nwa < *lba && d->status == BURN_DISC_BLANK)
483 *nwa = *lba;
484
485 #ifdef Libburn_pioneer_dvr_216d_load_mode5
486 /* >>> memorize track mode : data[6] & 0xf */;
487 #endif
488
489 { static int fake_damage = 0; /* bit0= damage on , bit1= NWA_V off */
490
491 if (fake_damage & 1)
492 data[5] |= 32; /* Damage bit */
493 if (fake_damage & 2)
494 data[7] &= ~1;
495
496 }
497
498 BURN_ALLOC_MEM(msg, char, 160);
499 if (trackno > 0)
500 sprintf(msg, "Track number %d: ", trackno);
501 else
502 sprintf(msg, "Upcoming track: ");
503 if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
504 d->current_profile == 0x12 || d->current_profile == 0x43) {
505 /* overwritable */
506 *lba = *nwa = num = 0;
507
508 } else if (data[5] & 32) { /* ts B10534 : MMC-5 6.27.3.7 Damage Bit */
509 if (!(data[7] & 1)) { /* NWA_V is set to zero */
510 /* "not closed due to an incomplete write" */
511 strcat(msg, "Damaged, not closed and not writable");
512 err= 0x00020185;
513 } else {
514 /* "may be recorded further in an incremental manner"*/
515 strcat(msg, "Damaged and not closed");
516 err= 0x00020186;
517 }
518 libdax_msgs_submit(libdax_messenger, d->global_index, err,
519 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
520 msg, 0, 0);
521 if (trackno <= 0)
522 d->next_track_damaged |= ((!(data[7] & 1)) << 1) | 1;
523 {ret = 0; goto ex;}
524
525 } else if (!(data[7] & 1)) {
526 /* ts A61106 : MMC-1 Table 142 : NWA_V = NWA Valid Flag */
527 strcat(msg, "No Next-Writable-Address");
528 libdax_msgs_submit(libdax_messenger, d->global_index,
529 0x00020184,
530 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
531 msg, 0, 0);
532 if (trackno <= 0)
533 d->next_track_damaged |= 2;
534 {ret = 0; goto ex;}
535
536 }
537 if (num > 0) {
538 burn_drive_set_media_capacity_remaining(d,
539 ((off_t) num) * ((off_t) 2048));
540 d->media_lba_limit = *nwa + num;
541 } else
542 d->media_lba_limit = 0;
543
544 /*
545 fprintf(stderr, "LIBBURN_DEBUG: media_lba_limit= %d\n",
546 d->media_lba_limit);
547 */
548
549 ret = 1;
550 ex:
551 BURN_FREE_MEM(buf);
552 BURN_FREE_MEM(msg);
553 return ret;
554 }
555
556 /* ts A61009 : function is obviously unused. */
557 /* void mmc_close_disc(struct burn_drive *d, struct burn_write_opts *o) */
mmc_close_disc(struct burn_write_opts * o)558 void mmc_close_disc(struct burn_write_opts *o)
559 {
560 struct burn_drive *d = o->drive;
561
562 if (mmc_function_spy(d, "mmc_close_disc") <= 0)
563 return;
564
565 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
566 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
567 "HOW THAT ? mmc_close_disc() was called", 0, 0);
568
569 /* ts A61009 : made impossible by removing redundant parameter d */
570 /* a ssert(o->drive == d); */
571
572 o->multi = 0;
573 spc_select_write_params(d, NULL, 0, o);
574 mmc_close(d, 1, 0);
575 }
576
577 /* ts A61009 : function is obviously unused. */
578 /* void mmc_close_session(struct burn_drive *d, struct burn_write_opts *o) */
mmc_close_session(struct burn_write_opts * o)579 void mmc_close_session(struct burn_write_opts *o)
580 {
581 struct burn_drive *d = o->drive;
582
583 if (mmc_function_spy(d, "mmc_close_session") <= 0)
584 return;
585
586 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
587 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
588 "HOW THAT ? mmc_close_session() was called", 0, 0);
589
590 /* ts A61009 : made impossible by removing redundant parameter d */
591 /* a ssert(o->drive == d); */
592
593 o->multi = 3;
594 spc_select_write_params(d, NULL, 0, o);
595 mmc_close(d, 1, 0);
596 }
597
598 /* ts A70227 : extended meaning of session to address all possible values
599 of 5Bh CLOSE TRACK SESSION to address any Close Function.
600 @param session contains the two high bits of Close Function
601 @param track if not 0: sets the lowest bit of Close Function
602 */
mmc_close(struct burn_drive * d,int session,int track)603 void mmc_close(struct burn_drive *d, int session, int track)
604 {
605 struct command *c;
606 char msg[256];
607 int key, asc, ascq;
608
609 c = &(d->casual_command);
610 if (mmc_function_spy(d, "mmc_close") <= 0)
611 return;
612
613 scsi_init_command(c, MMC_CLOSE, sizeof(MMC_CLOSE));
614 c->retry = 1;
615
616 if (!d->do_no_immed)
617 c->opcode[1] |= 1; /* ts A70918 : Immed */
618
619 /* (ts A61030 : shifted !!session rather than or-ing plain session ) */
620 c->opcode[2] = ((session & 3) << 1) | !!track;
621 c->opcode[4] = track >> 8;
622 c->opcode[5] = track & 0xFF;
623 c->page = NULL;
624 c->dir = NO_TRANSFER;
625 if (d->do_no_immed)
626 c->timeout = Libburn_mmc_close_noim_timeouT;
627 else
628 c->timeout = Libburn_mmc_close_timeouT;
629 d->issue_command(d, c);
630
631 /* ts A70918 : Immed : wait for drive to complete command */
632 if (c->error) {
633 sprintf(msg, "Failed to close %s (%d)",
634 session > 1 ? "disc" : session > 0 ? "session" : "track",
635 ((session & 3) << 1) | !!track);
636 sprintf(msg + strlen(msg), ". SCSI error : ");
637 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
638 &key, &asc, &ascq);
639 libdax_msgs_submit(libdax_messenger, d->global_index,
640 0x0002017e,
641 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
642 msg, 0, 0);
643 d->cancel = 1;
644 return;
645 }
646 spc_human_readable_cmd(c, msg, 160, 0);
647 if (spc_wait_unit_attention(d, 3600, msg, 0) <= 0)
648 d->cancel = 1;
649 }
650
mmc_get_event(struct burn_drive * d)651 void mmc_get_event(struct burn_drive *d)
652 {
653 struct buffer *buf = NULL;
654 struct command *c;
655 int alloc_len = 8, len, evt_code, loops = 0;
656 unsigned char *evt;
657
658 c = &(d->casual_command);
659 BURN_ALLOC_MEM_VOID(buf, struct buffer, 1);
660 if (mmc_function_spy(d, "mmc_get_event") <= 0)
661 goto ex;
662
663 again:;
664 scsi_init_command(c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
665 c->dxfer_len = 8;
666
667 /* >>> have a burn_drive element for Notification Class */;
668 c->opcode[4] = 0x7e;
669
670 c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
671 c->opcode[8] = c->dxfer_len & 0xff;
672 c->retry = 1;
673 c->page = buf;
674 c->page->bytes = 0;
675 c->page->sectors = 0;
676 c->dir = FROM_DRIVE;
677 d->issue_command(d, c);
678 if (c->error)
679 goto ex;
680
681 evt = c->page->data;
682 len = ((evt[0] << 8) | evt[1]) + 2;
683 if (len < 8)
684 goto ex;
685
686 /* >>> memorize evt[3] in burn_drive element for Notification Class */;
687 if (evt[3] == 0) /* No event */
688 goto ex;
689
690 evt_code = evt[4] & 0xf;
691 if (evt_code == 0) /* No change */
692 goto ex;
693
694 switch (evt[2] & 7) {
695 case 0: /* no events supported */
696 goto ex;
697 case 1: /* Operational change */
698 if (((evt[6] << 8) | evt[7])) {
699 alloc_len = 8;
700 mmc_get_configuration_al(d, &alloc_len);
701 }
702 break;
703 case 2: /* Power Management */
704 if (evt[5] >= 2)
705 d->start_unit(d);
706 break;
707 case 3: /* External request */
708
709 /* >>> report about external request */;
710
711 break;
712 case 4: /* Media */
713 if (evt_code == 2) {
714 d->start_unit(d);
715 alloc_len = 8;
716 mmc_get_configuration_al(d, &alloc_len);
717 }
718 break;
719 case 5: /* Multiple Host Events */
720
721 /* >>> report about foreign host interference */;
722
723 break;
724
725 case 6: /* Device busy */
726 if (evt_code == 1 && evt[5]) {
727
728 /* >>> wait the time announced in evt[6],[7]
729 as 100ms units */;
730 }
731 break;
732 default: /* reserved */
733 break;
734 }
735 loops++;
736 if (loops < 100)
737 goto again;
738 ex:;
739 BURN_FREE_MEM(buf);
740 }
741
742
743 /* ts A70711
744 This has become a little monster because of the creative buffer reports of
745 my LG GSA-4082B : Belated, possibly statistically dampened. But only with
746 DVD media. With CD it is ok.
747 */
mmc_wait_for_buffer_free(struct burn_drive * d,struct buffer * buf)748 static int mmc_wait_for_buffer_free(struct burn_drive *d, struct buffer *buf)
749 {
750 int usec= 0, need, reported_3s = 0, first_wait = 1;
751 struct timeval t0,tnow;
752 double max_fac, min_fac, waiting;
753
754 /* Enable to get reported waiting activities and total time.
755 #define Libburn_mmc_wfb_debuG 1
756 */
757 #ifdef Libburn_mmc_wfb_debuG
758 char sleeplist[32768];
759 static int buffer_still_invalid = 1;
760 #endif
761
762 max_fac = ((double) d->wfb_max_percent) / 100.0;
763
764 /* Buffer info from the drive is valid only after writing has begun.
765 Caring for buffer space makes sense mostly after max_percent of the
766 buffer was transmitted. */
767 if (d->progress.buffered_bytes <= 0 ||
768 d->progress.buffer_capacity <= 0 ||
769 d->progress.buffered_bytes + buf->bytes <=
770 d->progress.buffer_capacity * max_fac)
771 return 2;
772
773 #ifdef Libburn_mmc_wfb_debuG
774 if (buffer_still_invalid)
775 fprintf(stderr,
776 "\nLIBBURN_DEBUG: Buffer considered valid now\n");
777 buffer_still_invalid = 0;
778 #endif
779
780 /* The pessimistic counter does not assume any buffer consumption */
781 if (d->pessimistic_buffer_free - buf->bytes >=
782 ( 1.0 - max_fac) * d->progress.buffer_capacity)
783 return 1;
784
785 /* There is need to inquire the buffer fill */
786 d->pessimistic_writes++;
787 min_fac = ((double) d->wfb_min_percent) / 100.0;
788 gettimeofday(&t0, NULL);
789 #ifdef Libburn_mmc_wfb_debuG
790 sleeplist[0]= 0;
791 sprintf(sleeplist,"(%d%s %d)",
792 (int) (d->pessimistic_buffer_free - buf->bytes),
793 (d->pbf_altered ? "? -" : " -"),
794 (int) ((1.0 - max_fac) * d->progress.buffer_capacity));
795 #endif
796
797 while (1) {
798 if ((!first_wait) || d->pbf_altered) {
799 d->pbf_altered = 1;
800 mmc_read_buffer_capacity(d);
801 }
802 #ifdef Libburn_mmc_wfb_debuG
803 if(strlen(sleeplist) < sizeof(sleeplist) - 80)
804 sprintf(sleeplist+strlen(sleeplist)," (%d%s %d)",
805 (int) (d->pessimistic_buffer_free - buf->bytes),
806 (d->pbf_altered ? "? -" : " -"),
807 (int) ((1.0 - min_fac) * d->progress.buffer_capacity));
808 #endif
809 gettimeofday(&tnow, NULL);
810 waiting = (tnow.tv_sec - t0.tv_sec) +
811 ((double) (tnow.tv_usec - t0.tv_usec)) / 1.0e6;
812 if (d->pessimistic_buffer_free - buf->bytes >=
813 (1.0 - min_fac) * d->progress.buffer_capacity) {
814 #ifdef Libburn_mmc_wfb_debuG
815 if(strlen(sleeplist) >= sizeof(sleeplist) - 80)
816 strcat(sleeplist," ...");
817 sprintf(sleeplist+strlen(sleeplist)," -> %d [%.6f]",
818 (int) (
819 d->pessimistic_buffer_free - buf->bytes -
820 (1.0 - min_fac) * d->progress.buffer_capacity
821 ), waiting);
822 fprintf(stderr,
823 "\nLIBBURN_DEBUG: sleeplist= %s\n",sleeplist);
824 #endif
825 return 1;
826 }
827
828 /* Waiting is needed */
829 if (waiting >= 3 && !reported_3s) {
830 libdax_msgs_submit(libdax_messenger, d->global_index,
831 0x0002013d,
832 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
833 "Waiting for free buffer takes more than 3 seconds",
834 0,0);
835 reported_3s = 1;
836 } else if (d->wfb_timeout_sec > 0 &&
837 waiting > d->wfb_timeout_sec) {
838 d->wait_for_buffer_free = 0;
839 libdax_msgs_submit(libdax_messenger, d->global_index,
840 0x0002013d,
841 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
842 "Timeout with waiting for free buffer. Now disabled.",
843 0,0);
844 break;
845 }
846
847 need = (1.0 - min_fac) * d->progress.buffer_capacity +
848 buf->bytes - d->pessimistic_buffer_free;
849 usec = 0;
850 if (d->nominal_write_speed > 0)
851 usec = ((double) need) / 1000.0 /
852 ((double) d->nominal_write_speed) * 1.0e6;
853 else
854 usec = d->wfb_min_usec * 2;
855
856 /* >>> learn about buffer progress and adjust usec */
857
858 if (usec < (int) d->wfb_min_usec)
859 usec = d->wfb_min_usec;
860 else if (usec > (int) d->wfb_max_usec)
861 usec = d->wfb_max_usec;
862 usleep(usec);
863 if (d->waited_usec < 0xf0000000)
864 d->waited_usec += usec;
865 d->waited_tries++;
866 if(first_wait)
867 d->waited_writes++;
868 #ifdef Libburn_mmc_wfb_debuG
869 if(strlen(sleeplist) < sizeof(sleeplist) - 80)
870 sprintf(sleeplist+strlen(sleeplist)," %d", usec);
871 #endif
872 first_wait = 0;
873 }
874 return 0;
875 }
876
877
mmc_write_12(struct burn_drive * d,int start,struct buffer * buf)878 void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
879 {
880 struct command *c;
881 int len;
882
883 c = &(d->casual_command);
884 mmc_start_if_needed(d, 0);
885 if (mmc_function_spy(d, "mmc_write_12") <= 0)
886 return;
887
888 len = buf->sectors;
889
890 scsi_init_command(c, MMC_WRITE_12, sizeof(MMC_WRITE_12));
891 c->retry = 1;
892 mmc_int_to_four_char(c->opcode + 2, start);
893 mmc_int_to_four_char(c->opcode + 6, len);
894 c->page = buf;
895 c->dir = TO_DRIVE;
896 c->timeout = Libburn_scsi_write_timeouT;
897
898 d->issue_command(d, c);
899
900 /* ts A70711 */
901 d->pessimistic_buffer_free -= buf->bytes;
902 d->pbf_altered = 1;
903 }
904
905
906 #ifdef Libburn_write_time_debuG
907
print_time(int flag)908 static int print_time(int flag)
909 {
910 static struct timeval prev = {0, 0};
911 struct timeval now;
912 int ret, diff;
913
914 ret = gettimeofday(&now, NULL);
915 if (ret == -1)
916 return 0;
917 if (now.tv_sec - prev.tv_sec < Libburn_scsi_write_timeouT) {
918 diff = (now.tv_sec - prev.tv_sec) * 1000000 +
919 ((int) (now.tv_usec) - (int) prev.tv_usec);
920 fprintf(stderr, "\nlibburn_DEBUG: %d.%-6d : %d\n", (int) now.tv_sec, (int) now.tv_usec, diff);
921 }
922 memcpy(&prev, &now, sizeof(struct timeval));
923 return 1;
924 }
925
926 #endif /* Libburn_write_time_debuG */
927
928
mmc_write(struct burn_drive * d,int start,struct buffer * buf)929 int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
930 {
931 int cancelled;
932 struct command *c;
933 int len, key, asc, ascq;
934 char *msg = NULL;
935
936 #ifdef Libburn_write_time_debuG
937 extern int burn_sg_log_scsi;
938 #endif
939
940 /*
941 fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n",
942 buf->sectors, buf->bytes);
943 */
944
945
946 c = &(d->casual_command);
947
948 #ifdef Libburn_log_in_and_out_streaM
949 /* <<< ts A61031 */
950 static int tee_fd= -1;
951 if(tee_fd==-1)
952 tee_fd= open("/tmp/libburn_sg_written",
953 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
954 S_IRUSR | S_IWUSR);
955 #endif /* Libburn_log_in_and_out_streaM */
956
957 mmc_start_if_needed(d, 0);
958 if (mmc_function_spy(d, "mmc_write") <= 0)
959 return BE_CANCELLED;
960
961 cancelled = d->cancel;
962 if (cancelled)
963 return BE_CANCELLED;
964
965 /* ts A70215 */
966 if (d->media_lba_limit > 0 && start >= d->media_lba_limit) {
967
968 msg = calloc(1, 320);
969 if (msg != NULL) {
970 sprintf(msg,
971 "Exceeding range of permissible write addresses (%d >= %d)",
972 start, d->media_lba_limit);
973 libdax_msgs_submit(libdax_messenger, d->global_index,
974 0x0002012d,
975 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
976 msg, 0, 0);
977 strcpy(msg, "CDB= ");
978 if (spc_human_readable_cmd(c, msg + strlen(msg),
979 320 - strlen(msg), 1) > 0) {
980 libdax_msgs_submit(libdax_messenger,
981 d->global_index, 0x0002012d,
982 LIBDAX_MSGS_SEV_FATAL,
983 LIBDAX_MSGS_PRIO_HIGH,
984 msg, 0, 0);
985 }
986 free(msg);
987 }
988 d->cancel = 1; /* No need for mutexing because atomic */
989 return BE_CANCELLED;
990 }
991
992 len = buf->sectors;
993
994 /* ts A61009 : buffer fill problems are to be handled by caller */
995 /* a ssert(buf->bytes >= buf->sectors);*/ /* can be == at 0... */
996
997 /* ts A70711 */
998 if(d->wait_for_buffer_free)
999 mmc_wait_for_buffer_free(d, buf);
1000
1001 #ifdef Libburn_write_time_debuG
1002 if (burn_sg_log_scsi & 3)
1003 print_time(0);
1004 #endif
1005
1006 /* ts A80412 */
1007 if(d->do_stream_recording > 0 && start >= d->stream_recording_start) {
1008 scsi_init_command(c, MMC_WRITE_12, sizeof(MMC_WRITE_12));
1009 mmc_int_to_four_char(c->opcode + 2, start);
1010 mmc_int_to_four_char(c->opcode + 6, len);
1011 c->opcode[10] = 1<<7; /* Streaming bit */
1012 } else {
1013 scsi_init_command(c, MMC_WRITE_10, sizeof(MMC_WRITE_10));
1014 mmc_int_to_four_char(c->opcode + 2, start);
1015 c->opcode[6] = 0;
1016 c->opcode[7] = (len >> 8) & 0xFF;
1017 c->opcode[8] = len & 0xFF;
1018 }
1019 c->retry = 1;
1020 c->page = buf;
1021 c->dir = TO_DRIVE;
1022 c->timeout = Libburn_scsi_write_timeouT;
1023
1024 #ifdef Libburn_log_in_and_out_streaM
1025 /* <<< ts A61031 */
1026 if(tee_fd!=-1) {
1027 write(tee_fd, c->page->data, c->page->bytes);
1028 }
1029 #endif /* Libburn_log_in_and_out_streaM */
1030
1031 d->issue_command(d, c);
1032
1033 /* ts A70711 */
1034 d->pessimistic_buffer_free -= buf->bytes;
1035 d->pbf_altered = 1;
1036
1037 /* ts A61112 : react on eventual error condition */
1038 spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
1039 if (c->error && key != 0) {
1040 int key, asc, ascq;
1041 int err_sev = LIBDAX_MSGS_SEV_FATAL;
1042
1043 msg = calloc(1, 320);
1044 if (msg != NULL) {
1045 sprintf(msg, "SCSI error on write(%d,%d): ",
1046 start, len);
1047 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
1048 &key, &asc, &ascq);
1049 }
1050
1051 /* ts B31023 */
1052 /* Memorize if on DVD-RW write mode is TAO/Incremental and
1053 error [5 64 00] occurs within the first drive buffer fill.
1054 */
1055 if (d->current_profile == 0x14 && d->write_opts != NULL &&
1056 (d->progress.buffer_capacity == 0 ||
1057 start < (int) d->progress.buffer_capacity / 2048) &&
1058 key == 5 && asc == 0x64 && ascq == 0) {
1059 if (d->write_opts->write_type == BURN_WRITE_TAO) {
1060 d->was_feat21h_failure = 1 + (start == 0);
1061 if (d->write_opts->feat21h_fail_sev != 0)
1062 err_sev =
1063 d->write_opts->feat21h_fail_sev;
1064 }
1065 }
1066
1067 if (msg != NULL) {
1068 libdax_msgs_submit(libdax_messenger, d->global_index,
1069 0x0002011d,
1070 err_sev, LIBDAX_MSGS_PRIO_HIGH,
1071 msg, 0, 0);
1072 strcpy(msg, "CDB= ");
1073 if (spc_human_readable_cmd(c, msg + strlen(msg),
1074 320 - strlen(msg), 0) > 0) {
1075 libdax_msgs_submit(libdax_messenger,
1076 d->global_index, 0x0002011d,
1077 err_sev, LIBDAX_MSGS_PRIO_HIGH,
1078 msg, 0, 0);
1079 }
1080 free(msg);
1081 }
1082 d->cancel = 1;
1083
1084 return BE_CANCELLED;
1085 }
1086 d->write_retry_count += c->retry_count;
1087
1088 return 0;
1089 }
1090
1091
1092 /* ts A70201 : Set up an entry for mmc_fake_toc() */
mmc_fake_toc_entry(struct burn_toc_entry * entry,int session_number,int track_number,unsigned char * size_data,unsigned char * start_data,unsigned char * last_adr_data)1093 int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
1094 int track_number,
1095 unsigned char *size_data, unsigned char *start_data,
1096 unsigned char *last_adr_data)
1097 {
1098 int min, sec, frames, num;
1099
1100 /* mark DVD extensions and Track Info extension as valid */
1101 entry->extensions_valid |= (1 | 2);
1102
1103 /* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */
1104 entry->session = session_number & 0xff;
1105 entry->session_msb = (session_number >> 8) & 0xff;
1106 entry->adr = 1;
1107 entry->control = 4;
1108 entry->tno = 0;
1109 entry->point = track_number & 0xff;
1110 entry->point_msb = (track_number >> 8) & 0xff;
1111 num = mmc_four_char_to_int(size_data);
1112 entry->track_blocks = num;
1113 burn_lba_to_msf(num, &min, &sec, &frames);
1114 if (min > 255) {
1115 min = 255;
1116 sec = 255;
1117 frames = 255;
1118 }
1119 entry->min = min;
1120 entry->sec = sec;
1121 entry->frame = frames;
1122 entry->zero = 0;
1123 num = mmc_four_char_to_int(start_data);
1124 entry->start_lba = num;
1125 burn_lba_to_msf(num, &min, &sec, &frames);
1126 if (min > 255) {
1127 min = 255;
1128 sec = 255;
1129 frames = 255;
1130 }
1131 entry->pmin = min;
1132 entry->psec = sec;
1133 entry->pframe = frames;
1134 entry->last_recorded_address = mmc_four_char_to_int(last_adr_data);
1135 return 1;
1136 }
1137
1138
1139 /* ts A71128 : for DVD-ROM drives which offer no reliable track information */
mmc_read_toc_fmt0_al(struct burn_drive * d,int * alloc_len)1140 static int mmc_read_toc_fmt0_al(struct burn_drive *d, int *alloc_len)
1141 {
1142 struct burn_track *track;
1143 struct burn_session *session;
1144 struct burn_toc_entry *entry;
1145 struct buffer *buf = NULL;
1146 struct command *c = NULL;
1147 int dlen, i, old_alloc_len, session_number, prev_session = -1, ret;
1148 int lba, size;
1149 unsigned char *tdata, size_data[4], start_data[4], end_data[4];
1150
1151 if (*alloc_len < 4)
1152 {ret = 0; goto ex;}
1153
1154 BURN_ALLOC_MEM(buf, struct buffer, 1);
1155 BURN_ALLOC_MEM(c, struct command, 1);
1156 scsi_init_command(c, MMC_GET_TOC_FMT0, sizeof(MMC_GET_TOC_FMT0));
1157 c->dxfer_len = *alloc_len;
1158 c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
1159 c->opcode[8] = c->dxfer_len & 0xff;
1160 c->retry = 1;
1161 c->page = buf;
1162 c->page->bytes = 0;
1163 c->page->sectors = 0;
1164 c->dir = FROM_DRIVE;
1165 d->issue_command(d, c);
1166
1167 if (c->error) {
1168 err_ex:;
1169 libdax_msgs_submit(libdax_messenger, d->global_index,
1170 0x0002010d,
1171 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
1172 "Could not inquire TOC", 0,0);
1173 d->status = BURN_DISC_UNSUITABLE;
1174 d->toc_entries = 0;
1175 /* Preferring memory leaks over fandangos */
1176 d->toc_entry = calloc(1, sizeof(struct burn_toc_entry));
1177 {ret = 0; goto ex;}
1178 }
1179 dlen = c->page->data[0] * 256 + c->page->data[1];
1180 old_alloc_len = *alloc_len;
1181 *alloc_len = dlen + 2;
1182 if (old_alloc_len < 12)
1183 {ret = 1; goto ex;}
1184 if (dlen + 2 > old_alloc_len)
1185 dlen = old_alloc_len - 2;
1186 d->complete_sessions = 1 + c->page->data[3] - c->page->data[2];
1187
1188 #ifdef Libburn_disc_with_incomplete_sessioN
1189 /* ts B30112 : number of open sessions */
1190 d->incomplete_sessions = 0;
1191 #endif
1192
1193 d->last_track_no = d->complete_sessions;
1194 if (dlen - 2 < (d->last_track_no + 1) * 8) {
1195 libdax_msgs_submit(libdax_messenger, d->global_index,
1196 0x00020159,
1197 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
1198 "TOC Format 0 returns inconsistent data", 0,0);
1199 goto err_ex;
1200 }
1201
1202 d->toc_entries = d->last_track_no + d->complete_sessions;
1203 if (d->toc_entries < 1)
1204 {ret = 0; goto ex;}
1205 d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
1206 if(d->toc_entry == NULL)
1207 {ret = 0; goto ex;}
1208
1209 d->disc = burn_disc_create();
1210 if (d->disc == NULL)
1211 {ret = 0; goto ex;}
1212 for (i = 0; i < d->complete_sessions; i++) {
1213 session = burn_session_create();
1214 if (session == NULL)
1215 {ret = 0; goto ex;}
1216 burn_disc_add_session(d->disc, session, BURN_POS_END);
1217 burn_session_free(session);
1218 }
1219
1220
1221 for (i = 0; i < d->last_track_no; i++) {
1222 tdata = c->page->data + 4 + i * 8;
1223 session_number = i + 1;
1224 if (session_number != prev_session && prev_session > 0) {
1225 /* leadout entry previous session */
1226 entry = &(d->toc_entry[(i - 1) + prev_session]);
1227 lba = mmc_four_char_to_int(start_data) +
1228 mmc_four_char_to_int(size_data);
1229 mmc_int_to_four_char(start_data, lba);
1230 mmc_int_to_four_char(size_data, 0);
1231 mmc_int_to_four_char(end_data, lba - 1);
1232 mmc_fake_toc_entry(entry, prev_session, 0xA2,
1233 size_data, start_data, end_data);
1234 entry->min= entry->sec= entry->frame= 0;
1235 d->disc->session[prev_session - 1]->leadout_entry =
1236 entry;
1237 }
1238
1239 /* ??? >>> d->media_capacity_remaining , d->media_lba_limit
1240 as of mmc_fake_toc()
1241 */
1242
1243 entry = &(d->toc_entry[i + session_number - 1]);
1244 track = burn_track_create();
1245 if (track == NULL)
1246 {ret = -1; goto ex;}
1247 burn_session_add_track(
1248 d->disc->session[session_number - 1],
1249 track, BURN_POS_END);
1250 track->entry = entry;
1251 burn_track_free(track);
1252
1253 memcpy(start_data, tdata + 4, 4);
1254 /* size_data are estimated from next track start */
1255 memcpy(size_data, tdata + 8 + 4, 4);
1256 mmc_int_to_four_char(end_data,
1257 mmc_four_char_to_int(size_data) - 1);
1258 size = mmc_four_char_to_int(size_data) -
1259 mmc_four_char_to_int(start_data);
1260 mmc_int_to_four_char(size_data, size);
1261 mmc_fake_toc_entry(entry, session_number, i + 1,
1262 size_data, start_data, end_data);
1263 if (prev_session != session_number)
1264 d->disc->session[session_number - 1]->firsttrack = i+1;
1265 d->disc->session[session_number - 1]->lasttrack = i+1;
1266 prev_session = session_number;
1267 }
1268 if (prev_session > 0 && prev_session <= d->disc->sessions) {
1269 /* leadout entry of last session of closed disc */
1270 tdata = c->page->data + 4 + d->last_track_no * 8;
1271 entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
1272 memcpy(start_data, tdata + 4, 4);
1273 mmc_int_to_four_char(size_data, 0);
1274 mmc_int_to_four_char(end_data,
1275 mmc_four_char_to_int(start_data) - 1);
1276 mmc_fake_toc_entry(entry, prev_session, 0xA2,
1277 size_data, start_data, end_data);
1278 entry->min= entry->sec= entry->frame= 0;
1279 d->disc->session[prev_session - 1]->leadout_entry = entry;
1280 }
1281 ret = 1;
1282 ex:;
1283 BURN_FREE_MEM(buf);
1284 BURN_FREE_MEM(c);
1285 return ret;
1286 }
1287
1288
1289 /* ts A71128 : for DVD-ROM drives which offer no reliable track information */
mmc_read_toc_fmt0(struct burn_drive * d)1290 static int mmc_read_toc_fmt0(struct burn_drive *d)
1291 {
1292 int alloc_len = 4, ret;
1293
1294 mmc_start_if_needed(d, 1);
1295 if (mmc_function_spy(d, "mmc_read_toc_fmt0") <= 0)
1296 return -1;
1297 ret = mmc_read_toc_fmt0_al(d, &alloc_len);
1298 if (alloc_len >= 12)
1299 ret = mmc_read_toc_fmt0_al(d, &alloc_len);
1300 return ret;
1301 }
1302
1303
1304 /* ts A70131 : compose a disc TOC structure from d->complete_sessions
1305 and 52h READ TRACK INFORMATION */
mmc_fake_toc(struct burn_drive * d)1306 int mmc_fake_toc(struct burn_drive *d)
1307 {
1308 struct burn_track *track;
1309 struct burn_session *session;
1310 struct burn_toc_entry *entry;
1311 struct buffer *buf = NULL;
1312 int i, session_number, prev_session = -1, ret, lba, alloc_len = 34;
1313 unsigned char *tdata, size_data[4], start_data[4], end_data[4];
1314 char *msg = NULL;
1315
1316 if (mmc_function_spy(d, "mmc_fake_toc") <= 0)
1317 {ret = -1; goto ex;}
1318 BURN_ALLOC_MEM(buf, struct buffer, 1);
1319
1320 #ifdef Libburn_disc_with_incomplete_sessioN
1321
1322 if (d->last_track_no <= 0 ||
1323 d->complete_sessions + d->incomplete_sessions <= 0 ||
1324 d->status == BURN_DISC_BLANK)
1325 {ret = 2; goto ex;}
1326
1327 #else
1328
1329 if (d->last_track_no <= 0 || d->complete_sessions <= 0 ||
1330 d->status == BURN_DISC_BLANK)
1331 {ret = 2; goto ex;}
1332
1333 #endif /* ! Libburn_disc_with_incomplete_sessioN */
1334
1335
1336 if (d->last_track_no > BURN_MMC_FAKE_TOC_MAX_SIZE) {
1337 msg = calloc(1, 160);
1338 if (msg != NULL) {
1339 sprintf(msg,
1340 "Too many logical tracks recorded (%d , max. %d)\n",
1341 d->last_track_no, BURN_MMC_FAKE_TOC_MAX_SIZE);
1342 libdax_msgs_submit(libdax_messenger, d->global_index,
1343 0x0002012c,
1344 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
1345 msg, 0,0);
1346 free(msg);
1347 }
1348 {ret = 0; goto ex;}
1349 }
1350 /* ts A71128 : My DVD-ROM drive issues no reliable track info.
1351 One has to try 43h READ TOC/PMA/ATIP Form 0. */
1352 if ((d->current_profile == 0x10) && d->last_track_no <= 1) {
1353 ret = mmc_read_toc_fmt0(d);
1354 goto ex;
1355 }
1356 d->disc = burn_disc_create();
1357 if (d->disc == NULL)
1358 {ret = -1; goto ex;}
1359 d->toc_entries = d->last_track_no
1360 + d->complete_sessions + d->incomplete_sessions;
1361 d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
1362 if (d->toc_entry == NULL)
1363 {ret = -1; goto ex;}
1364 memset(d->toc_entry, 0,d->toc_entries * sizeof(struct burn_toc_entry));
1365
1366 #ifdef Libburn_disc_with_incomplete_sessioN
1367
1368 for (i = 0; i < d->complete_sessions + d->incomplete_sessions; i++) {
1369
1370 #else
1371
1372 for (i = 0; i < d->complete_sessions; i++) {
1373
1374 #endif
1375
1376 session = burn_session_create();
1377 if (session == NULL)
1378 {ret = -1; goto ex;}
1379 burn_disc_add_session(d->disc, session, BURN_POS_END);
1380 burn_session_free(session);
1381 }
1382
1383 #ifdef Libburn_disc_with_incomplete_sessioN
1384 d->disc->incomplete_sessions = d->incomplete_sessions;
1385 #endif
1386
1387 memset(size_data, 0, 4);
1388 memset(start_data, 0, 4);
1389
1390
1391 /* Entry Layout :
1392 session 1 track 1 entry 0
1393 ...
1394 session 1 track N entry N-1
1395 leadout 1 entry N
1396 session 2 track N+1 entry N+1
1397 ...
1398 session 2 track M+1 entry M+1
1399 leadout 2 entry M+2
1400 session X track K entry (K-1)+(X-1)
1401 ...
1402 session X track i+1 entry i+(X-1)
1403 leadout X entry i+X
1404 */
1405 for (i = 0; i < d->last_track_no; i++) {
1406 ret = mmc_read_track_info(d, i+1, buf, alloc_len);
1407 if (ret <= 0)
1408 goto ex;
1409 tdata = buf->data;
1410 session_number = (tdata[33] << 8) | tdata[3];
1411 if (session_number <= 0)
1412 continue;
1413
1414 if (session_number != prev_session && prev_session > 0) {
1415 /* leadout entry previous session */
1416 entry = &(d->toc_entry[(i - 1) + prev_session]);
1417 lba = mmc_four_char_to_int(start_data) +
1418 mmc_four_char_to_int(size_data);
1419 mmc_int_to_four_char(start_data, lba);
1420 mmc_int_to_four_char(size_data, 0);
1421 mmc_int_to_four_char(end_data, lba - 1);
1422 mmc_fake_toc_entry(entry, prev_session, 0xA2,
1423 size_data, start_data, end_data);
1424 entry->min= entry->sec= entry->frame= 0;
1425 d->disc->session[prev_session - 1]->leadout_entry =
1426 entry;
1427 }
1428
1429 #ifdef Libburn_disc_with_incomplete_sessioN
1430
1431 if (session_number > d->complete_sessions) {
1432
1433 #else
1434
1435 if (session_number > d->disc->sessions) {
1436
1437 #endif
1438
1439 if (i == d->last_track_no - 1) {
1440 /* ts A70212 : Last track field Free Blocks */
1441 burn_drive_set_media_capacity_remaining(d,
1442 ((off_t) mmc_four_char_to_int(tdata + 16)) *
1443 ((off_t) 2048));
1444 d->media_lba_limit = 0;
1445 }
1446
1447 #ifdef Libburn_disc_with_incomplete_sessioN
1448
1449 if (session_number > d->disc->sessions )
1450 continue;
1451
1452 #else
1453
1454 continue;
1455
1456 #endif
1457
1458 }
1459
1460 entry = &(d->toc_entry[i + session_number - 1]);
1461 track = burn_track_create();
1462 if (track == NULL)
1463 {ret = -1; goto ex;}
1464 burn_session_add_track(
1465 d->disc->session[session_number - 1],
1466 track, BURN_POS_END);
1467 track->entry = entry;
1468 burn_track_free(track);
1469
1470 memcpy(size_data, tdata + 24, 4);
1471 memcpy(start_data, tdata + 8, 4);
1472 memcpy(end_data, tdata + 28, 4);
1473 mmc_fake_toc_entry(entry, session_number, i + 1,
1474 size_data, start_data, end_data);
1475 entry->track_status_bits = tdata[5] | (tdata[6] << 8) |
1476 (tdata[7] << 16);
1477 entry->extensions_valid |= 4;
1478
1479 if (prev_session != session_number)
1480 d->disc->session[session_number - 1]->firsttrack = i+1;
1481 d->disc->session[session_number - 1]->lasttrack = i+1;
1482 prev_session = session_number;
1483 }
1484
1485 if (prev_session > 0 && prev_session <= d->disc->sessions) {
1486 /* leadout entry of last session of closed disc */
1487 entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
1488 lba = mmc_four_char_to_int(start_data) +
1489 mmc_four_char_to_int(size_data);
1490 mmc_int_to_four_char(start_data, lba);
1491 mmc_int_to_four_char(size_data, 0);
1492 mmc_int_to_four_char(end_data, lba - 1);
1493 mmc_fake_toc_entry(entry, prev_session, 0xA2,
1494 size_data, start_data, end_data);
1495 entry->min= entry->sec= entry->frame= 0;
1496 d->disc->session[prev_session - 1]->leadout_entry = entry;
1497 }
1498 ret = 1;
1499 ex:;
1500 BURN_FREE_MEM(buf);
1501 return ret;
1502 }
1503
1504
1505 static int mmc_register_leadout(struct burn_drive *d, int *highest_leadout,
1506 int toc_idx)
1507 {
1508 int lba;
1509
1510 lba = burn_msf_to_lba(d->toc_entry[toc_idx].pmin,
1511 d->toc_entry[toc_idx].psec,
1512 d->toc_entry[toc_idx].pframe);
1513 if (lba > *highest_leadout)
1514 *highest_leadout = lba;
1515 return 1;
1516 }
1517
1518
1519 static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
1520 {
1521 /* read full toc, all sessions, in m/s/f form, 4k buffer */
1522 /* ts A70201 : or fake a toc from track information */
1523 struct burn_track *track;
1524 struct burn_session *session;
1525 struct buffer *buf = NULL;
1526 struct command *c = NULL;
1527 int dlen;
1528 int i, old_alloc_len, t_idx, ret, highest_leadout = -1;
1529 unsigned char *tdata;
1530 char *msg = NULL;
1531
1532 if (*alloc_len < 4)
1533 {ret = 0; goto ex;}
1534
1535 BURN_ALLOC_MEM(buf, struct buffer, 1);
1536 BURN_ALLOC_MEM(c, struct command, 1);
1537 BURN_ALLOC_MEM(msg, char, 321);
1538
1539 if (!(d->current_profile == -1 || d->current_is_cd_profile)) {
1540 /* ts A70131 : MMC_GET_TOC uses Response Format 2
1541 For DVD this fails with 5,24,00 */
1542 /* mmc_read_toc_fmt0() uses
1543 Response Format 0: mmc5r03.pdf 6.26.3.2
1544 which does not yield the same result with the same disc
1545 on different drives.
1546 */
1547 /* ts A70201 :
1548 This uses the session count from 51h READ DISC INFORMATION
1549 and the track records from 52h READ TRACK INFORMATION.
1550 mmc_read_toc_fmt0() is used as fallback for dull DVD-ROM.
1551 */
1552 mmc_fake_toc(d);
1553
1554 if (d->status == BURN_DISC_UNREADY)
1555 d->status = BURN_DISC_FULL;
1556 {ret = 1; goto ex;}
1557 }
1558
1559 /* ts A90823:
1560 SanDisk Cruzer U3 memory stick stalls on format 2.
1561 Format 0 seems to be more conservative with read-only drives.
1562 */
1563 if (!((d->mdata->p2a_valid > 0 && d->mdata->cdrw_write) ||
1564 d->current_profile != 0x08)) {
1565 ret = mmc_read_toc_fmt0(d);
1566 goto ex;
1567 }
1568
1569 scsi_init_command(c, MMC_GET_TOC, sizeof(MMC_GET_TOC));
1570 c->dxfer_len = *alloc_len;
1571 c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
1572 c->opcode[8] = c->dxfer_len & 0xff;
1573 c->retry = 1;
1574 c->page = buf;
1575 c->page->bytes = 0;
1576 c->page->sectors = 0;
1577 c->dir = FROM_DRIVE;
1578 d->issue_command(d, c);
1579
1580 if (c->error) {
1581
1582 /* ts A61020 : this snaps on non-blank DVD media */
1583 /* ts A61106 : also snaps on CD with unclosed track/session */
1584 /* Very unsure whether this old measure is ok.
1585 Obviously higher levels do not care about this.
1586 outdated info: DVD+RW burns go on after passing through here.
1587
1588 d->busy = BURN_DRIVE_IDLE;
1589 */
1590 libdax_msgs_submit(libdax_messenger, d->global_index,
1591 0x0002010d,
1592 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
1593 "Could not inquire TOC", 0,0);
1594 d->status = BURN_DISC_UNSUITABLE;
1595 d->toc_entries = 0;
1596 /* Preferring memory leaks over fandangos */
1597 d->toc_entry = calloc(1, sizeof(struct burn_toc_entry));
1598 {ret = 0; goto ex;}
1599 }
1600
1601 dlen = c->page->data[0] * 256 + c->page->data[1];
1602 old_alloc_len = *alloc_len;
1603 *alloc_len = dlen + 2;
1604 if (old_alloc_len < 15)
1605 {ret = 1; goto ex;}
1606 if (dlen + 2 > old_alloc_len)
1607 dlen = old_alloc_len - 2;
1608 d->toc_entries = (dlen - 2) / 11;
1609 if (d->toc_entries < 1)
1610 {ret = 0; goto ex;}
1611 /*
1612 some drives fail this check.
1613
1614 ts A61007 : if re-enabled then not via Assert.
1615 a ssert(((dlen - 2) % 11) == 0);
1616 */
1617 /* ts A81202: plus number of sessions as reserve for leadout default */
1618 d->toc_entry = calloc(d->toc_entries + (unsigned char) c->page->data[3],
1619 sizeof(struct burn_toc_entry));
1620 if(d->toc_entry == NULL) /* ts A70825 */
1621 {ret = 0; goto ex;}
1622 tdata = c->page->data + 4;
1623
1624 d->disc = burn_disc_create();
1625 if (d->disc == NULL) /* ts A70825 */
1626 {ret = 0; goto ex;}
1627
1628 for (i = 0; i < c->page->data[3]; i++) {
1629 session = burn_session_create();
1630 if (session == NULL) /* ts A70825 */
1631 {ret = 0; goto ex;}
1632 burn_disc_add_session(d->disc, session, BURN_POS_END);
1633 burn_session_free(session);
1634 }
1635
1636 /* ts A61022 */
1637
1638 for (i = 0; i < d->toc_entries; i++, tdata += 11) {
1639
1640 /*
1641 fprintf(stderr, "libburn_experimental: toc entry #%d : %d %d %d\n",i,tdata[8], tdata[9], tdata[10]);
1642 */
1643
1644 #ifdef Libburn_allow_first_hiddeN
1645 /* ts B00430 : this causes problems because the track has
1646 no entry. One would have to coordinate this
1647 with other parts of libburn.
1648 */
1649 if (tdata[3] == 1) {
1650 if (burn_msf_to_lba(tdata[8], tdata[9], tdata[10])) {
1651 d->disc->session[0]->hidefirst = 1;
1652 track = burn_track_create();
1653 burn_session_add_track(d->disc->
1654 session[tdata[0] - 1],
1655 track, BURN_POS_END);
1656 burn_track_free(track);
1657 }
1658 }
1659 #endif /* Libburn_allow_first_hiddeN */
1660
1661 if (tdata[0] <= 0 || tdata[0] > d->disc->sessions)
1662 tdata[0] = d->disc->sessions;
1663 if (tdata[3] < 100 && tdata[0] > 0) {
1664 track = burn_track_create();
1665 burn_session_add_track(d->disc->session[tdata[0] - 1],
1666 track, BURN_POS_END);
1667 track->entry = &d->toc_entry[i];
1668 burn_track_free(track);
1669 }
1670 d->toc_entry[i].session = tdata[0];
1671 d->toc_entry[i].adr = tdata[1] >> 4;
1672 d->toc_entry[i].control = tdata[1] & 0xF;
1673 d->toc_entry[i].tno = tdata[2];
1674 d->toc_entry[i].point = tdata[3];
1675 d->toc_entry[i].min = tdata[4];
1676 d->toc_entry[i].sec = tdata[5];
1677 d->toc_entry[i].frame = tdata[6];
1678 d->toc_entry[i].zero = tdata[7];
1679 d->toc_entry[i].pmin = tdata[8];
1680 d->toc_entry[i].psec = tdata[9];
1681 d->toc_entry[i].pframe = tdata[10];
1682 if (tdata[3] == 0xA0)
1683 d->disc->session[tdata[0] - 1]->firsttrack = tdata[8];
1684 if (tdata[3] == 0xA1)
1685 d->disc->session[tdata[0] - 1]->lasttrack = tdata[8];
1686 if (tdata[3] == 0xA2) {
1687 d->disc->session[tdata[0] - 1]->leadout_entry =
1688 &d->toc_entry[i];
1689 /* ts B60305 */
1690 mmc_register_leadout(d, &highest_leadout, i);
1691 }
1692 }
1693
1694 /* ts A70131 : was (d->status != BURN_DISC_BLANK) */
1695 if (d->status == BURN_DISC_UNREADY)
1696 d->status = BURN_DISC_FULL;
1697 toc_find_modes(d);
1698
1699 /* ts A81202 ticket 146 : a drive reported a session with no leadout */
1700 for (i = 0; i < d->disc->sessions; i++) {
1701 if (d->disc->session[i]->leadout_entry != NULL)
1702 continue;
1703 sprintf(msg, "Session %d of %d encountered without leadout",
1704 i + 1, d->disc->sessions);
1705 libdax_msgs_submit(libdax_messenger, d->global_index,
1706 0x00020160,
1707 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
1708 msg, 0, 0);
1709
1710 /* Produce default leadout entry from last track of session
1711 which will thus get its size set to 0 */;
1712 if (d->disc->session[i]->track != NULL &&
1713 d->disc->session[i]->tracks > 0) {
1714 t_idx = d->toc_entries++;
1715 memcpy(d->toc_entry + t_idx,
1716 d->disc->session[i]->track[
1717 d->disc->session[i]->tracks - 1]->entry,
1718 sizeof(struct burn_toc_entry));
1719 d->toc_entry[t_idx].point = 0xA2;
1720 d->disc->session[i]->leadout_entry =
1721 d->toc_entry + t_idx;
1722 } else {
1723 burn_disc_remove_session(d->disc, d->disc->session[i]);
1724 sprintf(msg,
1725 "Empty session %d deleted. Now %d sessions.",
1726 i + 1, d->disc->sessions);
1727 libdax_msgs_submit(libdax_messenger, d->global_index,
1728 0x00020161,
1729 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
1730 msg, 0, 0);
1731 i--;
1732 }
1733 }
1734
1735 /* A80808 */
1736 burn_disc_cd_toc_extensions(d, 0);
1737
1738 /* ts B60304
1739 Most drives report READ CAPACITY of TAO CD too high by 2 blocks.
1740 TOC format 2 always reports 2 blocks more than are readable.
1741 So here it is possible to check and mark as trusted.
1742 */
1743 if (highest_leadout > 0 && d->media_read_capacity != 0x7fffffff &&
1744 !d->mr_capacity_trusted) {
1745 if (highest_leadout - 3 == d->media_read_capacity) {
1746 d->mr_capacity_trusted = 1;
1747 libdax_msgs_submit(libdax_messenger, d->global_index,
1748 0x00000002, LIBDAX_MSGS_SEV_DEBUG,
1749 LIBDAX_MSGS_PRIO_ZERO,
1750 "Trusting READ CAPACITY by 2 extra blocks in TOC. Assuming TAO.",
1751 0, 0);
1752 }
1753 }
1754
1755 ret = 1;
1756 ex:;
1757 BURN_FREE_MEM(msg);
1758 BURN_FREE_MEM(c);
1759 BURN_FREE_MEM(buf);
1760 return ret;
1761 }
1762
1763
1764 void mmc_read_toc(struct burn_drive *d)
1765 {
1766 int alloc_len = 4, ret;
1767
1768 mmc_start_if_needed(d, 1);
1769 if (mmc_function_spy(d, "mmc_read_toc") <= 0)
1770 return;
1771
1772 ret = mmc_read_toc_al(d, &alloc_len);
1773 /*
1774 fprintf(stderr,
1775 "LIBBURN_DEBUG: 43h READ TOC alloc_len = %d , ret = %d\n",
1776 alloc_len, ret);
1777 */
1778 if (alloc_len >= 15)
1779 ret = mmc_read_toc_al(d, &alloc_len);
1780 if (ret <= 0)
1781 return;
1782 }
1783
1784
1785 /* ts A70131 : This tries to get the start of the last complete session */
1786 /* man mkisofs , option -C :
1787 The first number is the sector number of the first sector in
1788 the last session of the disk that should be appended to.
1789 */
1790 int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
1791 {
1792 struct buffer *buf = NULL;
1793 struct command *c = NULL;
1794 unsigned char *tdata;
1795 int num_sessions, session_no, num_tracks, alloc_len = 12, ret;
1796 struct burn_disc *disc;
1797 struct burn_session **sessions;
1798 struct burn_track **tracks;
1799 struct burn_toc_entry toc_entry;
1800
1801 BURN_ALLOC_MEM(buf, struct buffer, 1);
1802 BURN_ALLOC_MEM(c, struct command, 1);
1803 mmc_start_if_needed(d, 1);
1804 if (mmc_function_spy(d, "mmc_read_multi_session_c1") <= 0)
1805 {ret = 0; goto ex;}
1806
1807 /* First try to evaluate the possibly loaded TOC before issuing
1808 a MMC command. This search obtains the first track of the last
1809 complete session which has a track.
1810 */
1811 *trackno = 0;
1812 disc = burn_drive_get_disc(d);
1813 if (disc == NULL)
1814 goto inquire_drive;
1815 sessions = burn_disc_get_sessions(disc, &num_sessions);
1816 for (session_no = 0; session_no<num_sessions; session_no++) {
1817 tracks = burn_session_get_tracks(sessions[session_no],
1818 &num_tracks);
1819 if (tracks == NULL || num_tracks <= 0)
1820 continue;
1821 burn_track_get_entry(tracks[0], &toc_entry);
1822 if (toc_entry.extensions_valid & 1) { /* DVD extension valid */
1823 *start = toc_entry.start_lba;
1824 *trackno = (toc_entry.point_msb << 8)| toc_entry.point;
1825 } else {
1826 *start = burn_msf_to_lba(toc_entry.pmin,
1827 toc_entry.psec, toc_entry.pframe);
1828 *trackno = toc_entry.point;
1829 }
1830 }
1831 burn_disc_free(disc);
1832 if(*trackno > 0)
1833 {ret = 1; goto ex;}
1834
1835 inquire_drive:;
1836 /* mmc5r03.pdf 6.26.3.3.3 states that with non-CD this would
1837 be a useless fake always starting at track 1, lba 0.
1838 My drives return useful data, though.
1839 MMC-3 states that DVD had no tracks. So maybe this mandatory fake
1840 is a forgotten legacy ?
1841 */
1842 scsi_init_command(c, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO));
1843 c->dxfer_len = alloc_len;
1844 c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
1845 c->opcode[8]= c->dxfer_len & 0xff;
1846 c->retry = 1;
1847 c->page = buf;
1848 c->page->bytes = 0;
1849 c->page->sectors = 0;
1850 c->dir = FROM_DRIVE;
1851 d->issue_command(d, c);
1852
1853 if (c->error)
1854 {ret = 0; goto ex;}
1855
1856 tdata = c->page->data + 4;
1857 *trackno = tdata[2];
1858 *start = mmc_four_char_to_int(tdata + 4);
1859 ret = 1;
1860 ex:;
1861 BURN_FREE_MEM(buf);
1862 BURN_FREE_MEM(c);
1863 return ret;
1864 }
1865
1866
1867 /* ts A61201 */
1868 char *mmc_obtain_profile_name(int profile_number)
1869 {
1870 static char *texts[0x53] = {NULL};
1871 int i, max_pno = 0x53;
1872
1873 if (texts[0] == NULL) {
1874 for (i = 0; i<max_pno; i++)
1875 texts[i] = "";
1876 /* mmc5r03c.pdf , Table 89, Spelling: guessed cdrecord style */
1877 texts[0x01] = "Non-removable disk";
1878 texts[0x02] = "Removable disk";
1879 texts[0x03] = "MO erasable";
1880 texts[0x04] = "Optical write once";
1881 texts[0x05] = "AS-MO";
1882 texts[0x08] = "CD-ROM";
1883 texts[0x09] = "CD-R";
1884 texts[0x0a] = "CD-RW";
1885 texts[0x10] = "DVD-ROM";
1886 texts[0x11] = "DVD-R sequential recording";
1887 texts[0x12] = "DVD-RAM";
1888 texts[0x13] = "DVD-RW restricted overwrite";
1889 texts[0x14] = "DVD-RW sequential recording";
1890 texts[0x15] = "DVD-R/DL sequential recording";
1891 texts[0x16] = "DVD-R/DL layer jump recording";
1892 texts[0x1a] = "DVD+RW";
1893 texts[0x1b] = "DVD+R";
1894 texts[0x2a] = "DVD+RW/DL";
1895 texts[0x2b] = "DVD+R/DL";
1896 texts[0x40] = "BD-ROM";
1897 texts[0x41] = "BD-R sequential recording";
1898 texts[0x42] = "BD-R random recording";
1899 texts[0x43] = "BD-RE";
1900 texts[0x50] = "HD-DVD-ROM";
1901 texts[0x51] = "HD-DVD-R";
1902 texts[0x52] = "HD-DVD-RAM";
1903 }
1904 if (profile_number<0 || profile_number>=max_pno)
1905 return "";
1906 return texts[profile_number];
1907 }
1908
1909
1910 /* ts A90603 : to be used if the drive knows no GET CONFIGURATION
1911 */
1912 static int mmc_guess_profile(struct burn_drive *d, int flag)
1913 {
1914 int cp;
1915
1916 cp = 0;
1917 if (d->status == BURN_DISC_BLANK ||
1918 d->status == BURN_DISC_APPENDABLE) {
1919 cp = 0x09;
1920 } else if (d->status == BURN_DISC_FULL) {
1921 cp = 0x08;
1922 }
1923 if (cp)
1924 if (d->erasable)
1925 cp = 0x0a;
1926 d->current_profile = cp;
1927 if (cp == 0)
1928 return 0;
1929 d->current_is_cd_profile = 1;
1930 d->current_is_supported_profile = 1;
1931 strcpy(d->current_profile_text, mmc_obtain_profile_name(cp));
1932 return 1;
1933 }
1934
1935
1936 static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
1937 {
1938 struct buffer *buf = NULL;
1939 unsigned char *data;
1940 struct command *c = NULL;
1941 char *msg = NULL;
1942 /* ts A70131 : had to move mmc_read_toc() to end of function */
1943 int do_read_toc = 0, disc_status, len, old_alloc_len;
1944 int ret, number_of_sessions = -1;
1945 int key, asc, ascq;
1946
1947 BURN_ALLOC_MEM(buf, struct buffer, 1);
1948 BURN_ALLOC_MEM(c, struct command, 1);
1949
1950 /* ts A61020 */
1951 d->start_lba = d->end_lba = -2000000000;
1952 d->erasable = 0;
1953 d->last_track_no = 1;
1954
1955 /* ts B10730 */
1956 d->sent_default_page_05 = 0;
1957 /* ts A70212 - A70215 */
1958 d->media_capacity_remaining = 0;
1959 d->media_lba_limit = 0;
1960
1961 /* ts A81210 */
1962 d->media_read_capacity = 0x7fffffff;
1963 d->mr_capacity_trusted = -1;
1964
1965 /* ts A61202 */
1966 d->toc_entries = 0;
1967 if (d->status == BURN_DISC_EMPTY)
1968 {ret = 1; goto ex;}
1969
1970 mmc_get_configuration(d);
1971
1972 scsi_init_command(c, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO));
1973 c->dxfer_len = *alloc_len;
1974 c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
1975 c->opcode[8]= c->dxfer_len & 0xff;
1976 c->retry = 1;
1977 c->page = buf;
1978 c->page->sectors = 0;
1979 c->page->bytes = 0;
1980 c->dir = FROM_DRIVE;
1981 d->issue_command(d, c);
1982
1983 if (c->error) {
1984 spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
1985 if (key == 5 && asc == 0x20 && ascq == 0) {
1986 /* ts B11031 : qemu -cdrom does not know
1987 051h READ DISC INFORMATION
1988 */
1989 ret = mmc_read_toc_fmt0(d);
1990 if (ret > 0) {
1991
1992 /* >>> ??? anything more to be set ? */;
1993
1994 mmc_read_capacity(d);
1995 *alloc_len = 0;
1996 goto ex;
1997 }
1998 }
1999
2000 d->busy = BURN_DRIVE_IDLE;
2001 {ret = 0; goto ex;}
2002 }
2003
2004 data = c->page->data;
2005 len = (data[0] << 8) | data[1];
2006 old_alloc_len = *alloc_len;
2007 *alloc_len = len + 2;
2008 if (old_alloc_len < 34)
2009 {ret = 1; goto ex;}
2010 if (*alloc_len < 24) /* data[23] is the last mandatory byte here */
2011 {ret = 0; goto ex;}
2012 if (len + 2 > old_alloc_len)
2013 len = old_alloc_len - 2;
2014
2015 d->erasable = !!(data[2] & 16);
2016
2017 /* ts A90908 */
2018 d->disc_type = data[8];
2019 d->disc_info_valid = 1;
2020 d->disc_id = mmc_four_char_to_int(data + 12);
2021 d->disc_info_valid |= (!!(data[7] & 128)) << 1;
2022 if (len + 2 > 31 && (data[7] & 64)) {
2023 memcpy(d->disc_bar_code, data + 24, 8);
2024 d->disc_bar_code[8] = 0;
2025 d->disc_info_valid |= 4;
2026 }
2027 if (len + 2 > 32 && (data[7] & 16)) {
2028 d->disc_app_code = data[32];
2029 d->disc_info_valid |= 8;
2030 }
2031 if (data[7] & 32)
2032 d->disc_info_valid |= 16;
2033 if (data[2] & 16)
2034 d->disc_info_valid |= 32;
2035
2036 disc_status = data[2] & 3;
2037 d->state_of_last_session = (data[2] >> 2) & 3;
2038 number_of_sessions = (data[9] << 8) | data[4];
2039
2040 if (d->current_profile == 0x10 || d->current_profile == 0x40) {
2041 /* DVD-ROM , BD-ROM */
2042 disc_status = 2; /* always full and finalized */
2043 d->erasable = 0; /* never erasable */
2044 }
2045
2046 #ifdef Libburn_support_bd_r_readonlY
2047 /* <<< For now: declaring BD-R read-only
2048 */
2049 #ifndef Libburn_support_bd_plus_r_srM
2050 if (d->current_profile == 0x41) {
2051 /* BD-R seq as readonly dummy */
2052 disc_status = 2; /* always full and finalized */
2053 d->erasable = 0; /* never erasable */
2054 }
2055 #endif
2056 if (d->current_profile == 0x42) {
2057 /* BD-R rnd */
2058 disc_status = 2; /* always full and finalized */
2059 d->erasable = 0; /* never erasable */
2060 }
2061 #endif /* Libburn_support_bd_r_readonlY */
2062
2063 /* MMC-5 6.22.3.1.16:
2064 Last Session Lead-in Start Address bytes 16 to 19
2065 Last Possible Lead-out Start Address bytes 20 to 23
2066 MSF for CD, LBA else
2067 */
2068 if(d->current_profile == 0x08 || d->current_profile == 0x09 ||
2069 d->current_profile == 0x0a) {
2070 d->last_lead_in =
2071 burn_msf_to_lba(data[17], data[18], data[19]);
2072 d->last_lead_out =
2073 burn_msf_to_lba(data[21], data[22], data[23]);
2074 } else {
2075 d->last_lead_in = mmc_four_char_to_int(data + 16);
2076 d->last_lead_out = mmc_four_char_to_int(data + 20);
2077 }
2078
2079 switch (disc_status) {
2080 case 0:
2081 regard_as_blank:;
2082 d->toc_entries = 0;
2083
2084 /*
2085 fprintf(stderr, "libburn_experimental: start_lba = %d (%d %d %d) , end_lba = %d (%d %d %d)\n",
2086 d->start_lba, data[17], data[18], data[19],
2087 d->end_lba, data[21], data[22], data[23]);
2088 */
2089
2090 d->status = BURN_DISC_BLANK;
2091 d->start_lba = d->last_lead_in;
2092 d->end_lba = d->last_lead_out;
2093 break;
2094 case 1:
2095 case 2:
2096 if (disc_status == 2)
2097 d->status = BURN_DISC_FULL;
2098 else
2099 d->status = BURN_DISC_APPENDABLE;
2100
2101 /* ts A81210 */
2102 ret = mmc_read_capacity(d);
2103 /* Freshly formatted, unwritten BD-R pretend to be appendable
2104 but in our model they need to be regarded as blank.
2105 Criterion: BD-R seq, read capacity known and 0,
2106 declared appendable, single empty session
2107 */
2108 if (d->current_profile == 0x41 &&
2109 d->status == BURN_DISC_APPENDABLE &&
2110 ret > 0 && d->media_read_capacity == 0 &&
2111 d->state_of_last_session == 0 && number_of_sessions == 1)
2112 goto regard_as_blank;
2113
2114 if (d->current_profile == 0x41 &&
2115 d->status == BURN_DISC_APPENDABLE &&
2116 d->state_of_last_session == 1) {
2117
2118 /* ??? apply this test to other media types ? */
2119
2120 libdax_msgs_submit(libdax_messenger, d->global_index,
2121 0x00020169,
2122 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
2123 "Last session on media is still open.", 0, 0);
2124 }
2125
2126 do_read_toc = 1;
2127 break;
2128 case 3:
2129 /* ts A91009 : DVD-RAM has disc status "others" */
2130 mmc_read_capacity(d);
2131 break;
2132 }
2133
2134 /* ts A90603 : An MMC-1 drive might not know the media type yet */
2135 if (d->current_is_guessed_profile && d->current_profile == 0)
2136 mmc_guess_profile(d, 0);
2137
2138 if ((d->current_profile != 0 || d->status != BURN_DISC_UNREADY)
2139 && ! d->current_is_supported_profile) {
2140 if (!(d->silent_on_scsi_error == 1 ||
2141 d->silent_on_scsi_error == 2)) {
2142 msg = calloc(1, 160);
2143 if (msg != NULL) {
2144 sprintf(msg,
2145 "Unsuitable media detected. Profile %4.4Xh %s",
2146 d->current_profile, d->current_profile_text);
2147 libdax_msgs_submit(libdax_messenger,
2148 d->global_index, 0x0002011e,
2149 d->silent_on_scsi_error == 3 ?
2150 LIBDAX_MSGS_SEV_DEBUG :
2151 LIBDAX_MSGS_SEV_SORRY,
2152 LIBDAX_MSGS_PRIO_HIGH, msg, 0,0);
2153 free(msg);
2154 }
2155 }
2156 d->status = BURN_DISC_UNSUITABLE;
2157 {ret = 0; goto ex;}
2158 }
2159
2160 /* ts A61217 :
2161 growisofs performs OPC if (data[0]<<8)|data[1]<=32
2162 which indicates no OPC entries are attached to the
2163 reply from the drive.
2164 ts A91104 :
2165 Actually growisofs performs OPC only on DVD-R[W].
2166 */
2167 d->num_opc_tables = 0;
2168 if(((data[0] << 8) | data[1]) > 32) /* i.e. > 34 bytes are available */
2169 d->num_opc_tables = data[33];
2170
2171 /* ts A61219 : mmc5r03c.pdf 6.22.3.1.13 BG Format Status
2172 0=blank (not yet started)
2173 1=started but neither running nor complete
2174 2=in progress
2175 3=completed
2176 */
2177 d->bg_format_status = data[7] & 3;
2178
2179 /* Preliminarily declare blank:
2180 ts A61219 : DVD+RW (is not bg_format_status==0 "blank")
2181 ts A61229 : same for DVD-RW Restricted overwrite
2182 ts A70112 : same for DVD-RAM
2183 */
2184 if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
2185 d->current_profile == 0x12 || d->current_profile == 0x43)
2186 d->status = BURN_DISC_BLANK;
2187
2188 #ifdef Libburn_disc_with_incomplete_sessioN
2189 /* ts B30112 : number of open sessions */
2190 d->incomplete_sessions = 0;
2191 #endif
2192
2193 if (d->status == BURN_DISC_BLANK) {
2194 d->last_track_no = 1; /* The "incomplete track" */
2195 d->complete_sessions = 0;
2196 } else {
2197 /* ts A70131 : number of closed sessions */
2198 d->complete_sessions = number_of_sessions;
2199 /* mmc5r03c.pdf 6.22.3.1.3 State of Last Session: 3=complete */
2200 if (d->state_of_last_session != 3 &&
2201 d->complete_sessions >= 1) {
2202 d->complete_sessions--;
2203
2204 #ifdef Libburn_disc_with_incomplete_sessioN
2205 d->incomplete_sessions++;
2206 #endif
2207
2208 }
2209
2210 /* ts A70129 : mmc5r03c.pdf 6.22.3.1.7
2211 This includes the "incomplete track" if the disk is
2212 appendable. I.e number of complete tracks + 1. */
2213 d->last_track_no = (data[11] << 8) | data[6];
2214 }
2215 if (d->current_profile != 0x0a && d->current_profile != 0x13 &&
2216 d->current_profile != 0x14 && d->status != BURN_DISC_FULL)
2217 d->erasable = 0; /* stay in sync with burn_disc_erase() */
2218
2219 if (do_read_toc)
2220 mmc_read_toc(d);
2221 ret = 1;
2222 ex:
2223 BURN_FREE_MEM(buf);
2224 BURN_FREE_MEM(c);
2225 return ret;
2226 }
2227
2228
2229 void mmc_read_disc_info(struct burn_drive *d)
2230 {
2231 int alloc_len = 34, ret;
2232
2233 mmc_start_if_needed(d, 1);
2234 if (mmc_function_spy(d, "mmc_read_disc_info") <= 0)
2235 return;
2236
2237 ret = mmc_read_disc_info_al(d, &alloc_len);
2238 /*
2239 fprintf(stderr,"LIBBURN_DEBUG: 51h alloc_len = %d , ret = %d\n",
2240 alloc_len, ret);
2241 */
2242 if (ret <= 0)
2243 return;
2244
2245 /* for now there is no need to inquire the variable length part */
2246 }
2247
2248
2249 /* @param flag bit= do not allocate text_packs
2250 */
2251 static int mmc_get_leadin_text_al(struct burn_drive *d,
2252 unsigned char **text_packs, int *alloc_len,
2253 int flag)
2254 {
2255 struct buffer *buf = NULL;
2256 struct command *c = NULL;
2257 unsigned char *data;
2258 int ret, data_length;
2259
2260 *text_packs = NULL;
2261
2262 BURN_ALLOC_MEM(buf, struct buffer, 1);
2263 BURN_ALLOC_MEM(c, struct command, 1);
2264
2265 scsi_init_command(c, MMC_GET_LEADTEXT, sizeof(MMC_GET_LEADTEXT));
2266 c->dxfer_len = *alloc_len;
2267 c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
2268 c->opcode[8]= c->dxfer_len & 0xff;
2269 c->retry = 1;
2270 c->page = buf;
2271 c->page->bytes = 0;
2272 c->page->sectors = 0;
2273
2274 c->dir = FROM_DRIVE;
2275 d->issue_command(d, c);
2276 if (c->error)
2277 {ret = 0; goto ex;}
2278
2279 data = c->page->data;
2280 data_length = (data[0] << 8) + data[1];
2281 *alloc_len = data_length + 2;
2282 if (*alloc_len >= 22 && !(flag & 1)) {
2283 BURN_ALLOC_MEM(*text_packs, unsigned char, *alloc_len - 4);
2284 memcpy(*text_packs, data + 4, *alloc_len - 4);
2285 }
2286 ret = 1;
2287 ex:;
2288 BURN_FREE_MEM(c);
2289 BURN_FREE_MEM(buf);
2290 return ret;
2291 }
2292
2293
2294 /* ts B11201 */
2295 /* Read the CD-TEXT data from the Lead-in of an Audio CD
2296 */
2297 int mmc_get_leadin_text(struct burn_drive *d,
2298 unsigned char **text_packs, int *num_packs, int flag)
2299 {
2300 int alloc_len = 4, ret;
2301
2302 *num_packs = 0;
2303 if (mmc_function_spy(d, "mmc_get_leadin_text") <= 0)
2304 return -1;
2305 ret = mmc_get_leadin_text_al(d, text_packs, &alloc_len, 1);
2306 if (ret <= 0 || alloc_len < 22)
2307 return (ret > 0 ? 0 : ret);
2308 ret = mmc_get_leadin_text_al(d, text_packs, &alloc_len, 0);
2309 if (ret <= 0 || alloc_len < 22) {
2310 if (*text_packs != NULL)
2311 free(*text_packs);
2312 *text_packs = NULL;
2313 return (ret > 0 ? 0 : ret);
2314 }
2315 *num_packs = (alloc_len - 4) / 18;
2316 return ret;
2317 }
2318
2319
2320 void mmc_read_atip(struct burn_drive *d)
2321 {
2322 struct buffer *buf = NULL;
2323 struct command *c = NULL;
2324 int alloc_len = 28;
2325
2326 /* ts A61021 */
2327 unsigned char *data;
2328 /* Speed values from A1:
2329 With 4 cdrecord tells "10" or "8" where MMC-1 says "8".
2330 cdrecord "8" appear on 4xCD-RW and thus seem to be quite invalid.
2331 My CD-R (>=24 speed) tell no A1.
2332 The higher non-MMC-1 values are hearsay.
2333 */
2334 /* 0, 2, 4, 6, 10, -, 16, -, */
2335 static int speed_value[16]= { 0, 353, 706, 1059, 1764, -5, 2824, -7,
2336 4234, 5646, 7056, 8468, -12, -13, -14, -15};
2337 /* 24, 32, 40, 48, -, -, -, - */
2338
2339 BURN_ALLOC_MEM_VOID(buf, struct buffer, 1);
2340 BURN_ALLOC_MEM_VOID(c, struct command, 1);
2341 mmc_start_if_needed(d, 1);
2342 if (mmc_function_spy(d, "mmc_read_atip") <= 0)
2343 goto ex;
2344
2345 scsi_init_command(c, MMC_GET_ATIP, sizeof(MMC_GET_ATIP));
2346 c->dxfer_len = alloc_len;
2347 c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
2348 c->opcode[8] = c->dxfer_len & 0xff;
2349 c->retry = 1;
2350 c->page = buf;
2351 c->page->bytes = 0;
2352 c->page->sectors = 0;
2353
2354 c->dir = FROM_DRIVE;
2355 d->issue_command(d, c);
2356 /* ts B00501 : now caring for error */
2357 if (c->error) {
2358 d->erasable = 0;
2359 d->start_lba = 0;
2360 d->end_lba = 0;
2361 goto ex;
2362 }
2363
2364 /* ts A61021 */
2365 data = c->page->data;
2366 d->erasable = !!(data[6]&64);
2367 d->start_lba = burn_msf_to_lba(data[8],data[9],data[10]);
2368 d->end_lba = burn_msf_to_lba(data[12],data[13],data[14]);
2369
2370 /* ts B21124 : LITE-ON LTR-48125S returns crap on pressed
2371 audio CD and CD-ROM
2372 */
2373 if (d->start_lba >= d->end_lba) {
2374 d->start_lba = 0;
2375 d->end_lba = 0;
2376 }
2377
2378 if (data[6]&4) {
2379 if (speed_value[(data[16]>>4)&7] > 0) {
2380 d->mdata->min_write_speed =
2381 speed_value[(data[16]>>4)&7];
2382 if (speed_value[(data[16])&15] <= 0)
2383 d->mdata->max_write_speed =
2384 speed_value[(data[16]>>4)&7];
2385 }
2386 if (speed_value[(data[16])&15] > 0) {
2387 d->mdata->max_write_speed =
2388 speed_value[(data[16])&15];
2389 if (speed_value[(data[16]>>4)&7] <= 0)
2390 d->mdata->min_write_speed =
2391 speed_value[(data[16])&15];
2392 }
2393 }
2394
2395 #ifdef Burn_mmc_be_verbous_about_atiP
2396 { int i;
2397 fprintf(stderr,"libburn_experimental: Returned ATIP Data\n");
2398 for(i= 0; i<28; i++)
2399 fprintf(stderr,"%3.3d (0x%2.2x)%s",
2400 data[i],data[i],(((i + 1) % 5) ? " " : "\n"));
2401 fprintf(stderr,"\n");
2402
2403 fprintf(stderr,
2404 "libburn_experimental: Indicative Target Writing Power= %d\n",
2405 (data[4]>>4)&7);
2406 fprintf(stderr,
2407 "libburn_experimental: Reference speed= %d ->%d\n",
2408 data[4]&7, speed_value[data[4]&7]);
2409 fprintf(stderr,
2410 "libburn_experimental: Is %sunrestricted\n",
2411 (data[5]&64?"":"not "));
2412 fprintf(stderr,
2413 "libburn_experimental: Is %serasable, sub-type %d\n",
2414 (data[6]&64?"":"not "),(data[6]>>3)&3);
2415 fprintf(stderr,
2416 "libburn_experimental: lead in: %d (%-2.2d:%-2.2d/%-2.2d)\n",
2417 burn_msf_to_lba(data[8],data[9],data[10]),
2418 data[8],data[9],data[10]);
2419 fprintf(stderr,
2420 "libburn_experimental: lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n",
2421 burn_msf_to_lba(data[12],data[13],data[14]),
2422 data[12],data[13],data[14]);
2423 if(data[6]&4)
2424 fprintf(stderr,
2425 "libburn_experimental: A1 speed low %d speed high %d\n",
2426 speed_value[(data[16]>>4)&7], speed_value[(data[16])&7]);
2427 if(data[6]&2)
2428 fprintf(stderr,
2429 "libburn_experimental: A2 speed low %d speed high %d\n",
2430 speed_value[(data[20]>>4)&7], speed_value[(data[20])&7]);
2431 if(data[6]&1)
2432 fprintf(stderr,
2433 "libburn_experimental: A3 speed low %d speed high %d\n",
2434 speed_value[(data[24]>>4)&7], speed_value[(data[24])&7]);
2435 }
2436
2437 #endif /* Burn_mmc_be_verbous_about_atiP */
2438
2439 /* ts A61020
2440 http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf , table 77 :
2441
2442 0 ATIP Data Length MSB
2443 1 ATIP Data Length LSB
2444 2 Reserved
2445 3 Reserved
2446 4 bit7=1, bit4-6="Indicative Target Writing Power", bit3=reserved ,
2447 bit0-2="Reference speed"
2448 5 bit7=0, bit6="URU" , bit0-5=reserved
2449 6 bit7=1, bit6="Disc Type", bit3-4="Disc Sub-Type",
2450 bit2="A1", bit1="A2", bit0="A3"
2451 7 reserved
2452 8 ATIP Start Time of lead-in (Min)
2453 9 ATIP Start Time of lead-in (Sec)
2454 10 ATIP Start Time of lead-in (Frame)
2455 11 reserved
2456 12 ATIP Last Possible Start Time of lead-out (Min)
2457 13 ATIP Last Possible Start Time of lead-out (Sec)
2458 14 ATIP Last Possible Start Time of lead-out (Frame)
2459 15 reserved
2460 16 bit7=0, bit4-6="Lowest Usable CLV Recording speed"
2461 bit0-3="Highest Usable CLV Recording speed"
2462 17 bit7=0, bit4-6="Power Multiplication Factor p",
2463 bit1-3="Target y value of the Modulation/Power function", bit0=reserved
2464 18 bit7=1, bit4-6="Recommended Erase/Write Power Ratio (P(inf)/W(inf))"
2465 bit0-3=reserved
2466 19 reserved
2467 20-22 A2 Values
2468 23 reserved
2469 24-26 A3 Values
2470 27 reserved
2471
2472 Disc Type - zero indicates CD-R media; one indicates CD-RW media.
2473
2474 Disc Sub-Type - shall be set to zero.
2475
2476 A1 - when set to one, indicates that bytes 16-18 are valid.
2477
2478 Lowest Usable CLV Recording Speed
2479 000b Reserved
2480 001b 2X
2481 010b - 111b Reserved
2482
2483 Highest CLV Recording Speeds
2484 000b Reserved
2485 001b 2X
2486 010b 4X
2487 011b 6X
2488 100b 8X
2489 101b - 111b Reserved
2490
2491 MMC-3 seems to recommend MODE SENSE (5Ah) page 2Ah rather than A1, A2, A3.
2492 This page is loaded in libburn function spc_sense_caps() .
2493 Speed is given in kbytes/sec there. But i suspect this to be independent
2494 of media. So one would habe to associate the speed descriptor blocks with
2495 the ATIP media characteristics ? How ?
2496
2497 */
2498
2499 ex:;
2500 BURN_FREE_MEM(buf);
2501 BURN_FREE_MEM(c);
2502 }
2503
2504
2505 int mmc_eval_read_error(struct burn_drive *d, struct command *c, char *what,
2506 int start_m, int start_s, int start_f,
2507 int end_m, int end_s, int end_f, int flag)
2508 {
2509 char *msg = NULL;
2510 int key, asc, ascq, silent;
2511
2512 if (!c->error)
2513 return 0;
2514
2515 msg = calloc(1, 256);
2516 if (msg != NULL) {
2517 if (start_s < 0 || start_f < 0 || end_s < 0 || end_f < 0) {
2518 sprintf(msg,
2519 "SCSI error on %s(%d,%d): ", what, start_m, end_m);
2520 } else {
2521 sprintf(msg, "SCSI error on %s(%dm%ds%df,%dm%ds%df): ",
2522 what,
2523 start_m, start_s, start_f, end_m, end_s, end_f);
2524 }
2525 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
2526 &key, &asc, &ascq);
2527 silent = (d->silent_on_scsi_error == 1);
2528 if (key == 5 && asc == 0x64 && ascq == 0x0) {
2529 d->had_particular_error |= 1;
2530 if (d->silent_on_scsi_error == 2)
2531 silent = 1;
2532 }
2533 if(!silent)
2534 libdax_msgs_submit(libdax_messenger,
2535 d->global_index,
2536 0x00020144,
2537 d->silent_on_scsi_error == 3 ?
2538 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
2539 LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
2540 free(msg);
2541 }
2542 return BE_CANCELLED;
2543 }
2544
2545
2546 /* ts B21119 : Derived from older mmc_read_sectors()
2547 @param flag bit0= set DAP bit (also with o->dap_bit)
2548 */
2549 int mmc_read_cd_msf(struct burn_drive *d,
2550 int start_m, int start_s, int start_f,
2551 int end_m, int end_s, int end_f,
2552 int sec_type, int main_ch,
2553 const struct burn_read_opts *o, struct buffer *buf, int flag)
2554 {
2555 int req, ret, dap_bit;
2556 int subcodes_audio = 0, subcodes_data = 0;
2557 struct command *c;
2558 #ifdef Libburn_mmc_report_recovereD
2559 int report_recovered_errors = 0;
2560 #endif
2561
2562 c = &(d->casual_command);
2563 mmc_start_if_needed(d, 0);
2564 if (mmc_function_spy(d, "mmc_read_cd_msf") <= 0)
2565 return -1;
2566
2567 dap_bit = flag & 1;
2568 if (o != NULL) {
2569 subcodes_audio = o->subcodes_audio;
2570 subcodes_data = o->subcodes_data;
2571 dap_bit |= o->dap_bit;
2572
2573 #ifdef Libburn_mmc_report_recovereD
2574 report_recovered_errors = o->report_recovered_errors;
2575 #endif
2576 }
2577
2578 scsi_init_command(c, MMC_READ_CD_MSF, sizeof(MMC_READ_CD_MSF));
2579 c->retry = 1;
2580 c->opcode[1] = ((sec_type & 7) << 2) | ((!!dap_bit) << 1);
2581 c->opcode[3] = start_m;
2582 c->opcode[4] = start_s;
2583 c->opcode[5] = start_f;
2584 c->opcode[6] = end_m;
2585 c->opcode[7] = end_s;
2586 c->opcode[8] = end_f;
2587
2588 req = main_ch & 0xf8;
2589
2590 #ifdef Libburn_mmc_report_recovereD
2591 /* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h */
2592 if (d->busy == BURN_DRIVE_GRABBING || report_recovered_errors)
2593 req |= 2;
2594 #endif /* Libburn_mmc_report_recovereD */
2595
2596 c->opcode[9] = req;
2597
2598 c->opcode[10] = 0;
2599 /* always read the subcode, throw it away later, since we don't know
2600 what we're really reading
2601 */
2602 /* >>> ts B21125 : This is very obscure:
2603 MMC-3 has sub channel selection 001b as "RAW"
2604 MMC-5 does neither mention 001b nor "RAW".
2605 And why should a non-grabbed drive get here ?
2606 */
2607 if (d->busy == BURN_DRIVE_GRABBING || subcodes_audio || subcodes_data)
2608 c->opcode[10] = 1;
2609
2610 /* <<< ts B21125 : test with sub channel selection 100b
2611 no data, only sub channel
2612 c->opcode[9] = 0;
2613 c->opcode[10] = 4;
2614 Did not help either with reading before LBA -150
2615 */
2616 /* <<< ts B21125 : test with sub channel selection 001b and no user data
2617 c->opcode[9] = 0;
2618 c->opcode[10] = 1;
2619 */
2620
2621 c->page = buf;
2622 c->dir = FROM_DRIVE;
2623 d->issue_command(d, c);
2624 ret = mmc_eval_read_error(d, c, "read_cd_msf",
2625 start_m, start_s, start_f,
2626 end_m, end_s, end_f, 0);
2627 return ret;
2628 }
2629
2630
2631 /* ts B21119 : Derived from older mmc_read_sectors()
2632 @param flag bit0= set DAP bit (also with o->dap_bit)
2633 */
2634 int mmc_read_cd(struct burn_drive *d, int start, int len,
2635 int sec_type, int main_ch,
2636 const struct burn_read_opts *o, struct buffer *buf, int flag)
2637 {
2638 int temp, req, ret, dap_bit;
2639 int subcodes_audio = 0, subcodes_data = 0;
2640 struct command *c;
2641
2642 #ifdef Libburn_mmc_report_recovereD
2643 int report_recovered_errors = 0;
2644 #endif
2645
2646 /* # define Libburn_read_cd_by_msF 1 */
2647 #ifdef Libburn_read_cd_by_msF
2648
2649 int start_m, start_s, start_f, end_m, end_s, end_f;
2650
2651 burn_lba_to_msf(start, &start_m, &start_s, &start_f);
2652 burn_lba_to_msf(start + len, &end_m, &end_s, &end_f);
2653 ret = mmc_read_cd_msf(d, start_m, start_s, start_f,
2654 end_m, end_s, end_f,
2655 sec_type, main_ch, o, buf, flag);
2656 return ret;
2657
2658 #endif /* Libburn_read_cd_by_msF */
2659
2660 c = &(d->casual_command);
2661 mmc_start_if_needed(d, 0);
2662 if (mmc_function_spy(d, "mmc_read_cd") <= 0)
2663 return -1;
2664
2665 dap_bit = flag & 1;
2666 if (o != NULL) {
2667 subcodes_audio = o->subcodes_audio;
2668 subcodes_data = o->subcodes_data;
2669 dap_bit |= o->dap_bit;
2670
2671 #ifdef Libburn_mmc_report_recovereD
2672 report_recovered_errors = o->report_recovered_errors;
2673 #endif
2674 }
2675
2676 scsi_init_command(c, MMC_READ_CD, sizeof(MMC_READ_CD));
2677 c->retry = 1;
2678 c->opcode[1] = ((sec_type & 7) << 2) | ((!!dap_bit) << 1);
2679 temp = start;
2680 c->opcode[5] = temp & 0xFF;
2681 temp >>= 8;
2682 c->opcode[4] = temp & 0xFF;
2683 temp >>= 8;
2684 c->opcode[3] = temp & 0xFF;
2685 temp >>= 8;
2686 c->opcode[2] = temp & 0xFF;
2687 c->opcode[8] = len & 0xFF;
2688 len >>= 8;
2689 c->opcode[7] = len & 0xFF;
2690 len >>= 8;
2691 c->opcode[6] = len & 0xFF;
2692 req = main_ch & 0xf8;
2693
2694 #ifdef Libburn_mmc_report_recovereD
2695 /* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h */
2696 if (d->busy == BURN_DRIVE_GRABBING || report_recovered_errors)
2697 req |= 2;
2698 #endif /* Libburn_mmc_report_recovereD */
2699
2700 c->opcode[9] = req;
2701 c->opcode[10] = 0;
2702 /* always read the subcode, throw it away later, since we don't know
2703 what we're really reading
2704 */
2705 /* >>> ts B21125 : This is very obscure:
2706 MMC-3 has sub channel selection 001b as "RAW"
2707 MMC-5 does neither mention 001b nor "RAW".
2708 And why should a non-grabbed drive get here ?
2709 */
2710 if (d->busy == BURN_DRIVE_GRABBING || subcodes_audio || subcodes_data)
2711 c->opcode[10] = 1;
2712
2713 /* <<< ts B21125 : test with sub channel selection 100b
2714 c->opcode[10] = 4;
2715 */
2716 /* <<< ts B21125 : test with sub channel selection 001b and no user data
2717 c->opcode[9] = 0;
2718 c->opcode[10] = 1;
2719 */
2720
2721 c->page = buf;
2722 c->dir = FROM_DRIVE;
2723 d->issue_command(d, c);
2724 ret = mmc_eval_read_error(d, c, "read_cd", start, -1, -1,
2725 len, -1, -1, 0);
2726 return ret;
2727 }
2728
2729 void mmc_erase(struct burn_drive *d, int fast)
2730 {
2731 struct command *c;
2732
2733 c = &(d->casual_command);
2734 mmc_start_if_needed(d, 0);
2735 if (mmc_function_spy(d, "mmc_erase") <= 0)
2736 return;
2737
2738 scsi_init_command(c, MMC_BLANK, sizeof(MMC_BLANK));
2739 if (!d->do_no_immed)
2740 c->opcode[1] = 16; /* IMMED set to 1 */
2741 c->opcode[1] |= !!fast;
2742 c->retry = 1;
2743 c->page = NULL;
2744 c->dir = NO_TRANSFER;
2745 if (d->do_no_immed)
2746 c->timeout = Libburn_mmc_blank_noim_timeouT;
2747 else
2748 c->timeout = Libburn_mmc_blank_timeouT;
2749 d->issue_command(d, c);
2750 if (c->error) {
2751 d->cancel = 1;
2752 scsi_notify_error(d, c, c->sense, 14, 2);
2753 }
2754 }
2755
2756 void mmc_read_lead_in(struct burn_drive *d, struct buffer *buf)
2757 {
2758 struct command *c;
2759
2760 c = &(d->casual_command);
2761 mmc_start_if_needed(d, 0);
2762 if (mmc_function_spy(d, "mmc_read_lead_in") <= 0)
2763 return;
2764
2765 scsi_init_command(c, MMC_READ_CD, sizeof(MMC_READ_CD));
2766 c->retry = 1;
2767 c->opcode[5] = 0;
2768 c->opcode[4] = 0;
2769 c->opcode[3] = 0;
2770 c->opcode[2] = 0xF0;
2771 c->opcode[8] = 1;
2772 c->opcode[7] = 0;
2773 c->opcode[6] = 0;
2774 c->opcode[9] = 0;
2775 c->opcode[10] = 2;
2776 c->page = buf;
2777 c->dir = FROM_DRIVE;
2778 d->issue_command(d, c);
2779 }
2780
2781 void mmc_perform_opc(struct burn_drive *d)
2782 {
2783 struct command *c;
2784
2785 c = &(d->casual_command);
2786 mmc_start_if_needed(d, 0);
2787 if (mmc_function_spy(d, "mmc_perform_opc") <= 0)
2788 return;
2789
2790 scsi_init_command(c, MMC_SEND_OPC, sizeof(MMC_SEND_OPC));
2791 c->retry = 1;
2792 c->opcode[1] = 1;
2793 c->page = NULL;
2794 c->dir = NO_TRANSFER;
2795 c->timeout = Libburn_mmc_opc_timeouT;
2796 d->issue_command(d, c);
2797 }
2798
2799
2800 /* ts A61221 : Learned much from dvd+rw-tools-7.0 set_speed_B6h() but then
2801 made own experiments on base of mmc5r03c.pdf 6.8.3 and 6.39 in the hope
2802 to achieve a leaner solution
2803 ts A70712 : That leaner solution does not suffice for my LG GSA-4082B.
2804 Meanwhile there is a speed descriptor list anyway.
2805 */
2806 int mmc_set_streaming(struct burn_drive *d,
2807 int r_speed, int w_speed, int end_lba)
2808 {
2809 struct buffer *buf = NULL;
2810 struct command *c = NULL;
2811 int b, eff_end_lba, ret;
2812 char *msg = NULL;
2813 unsigned char *pd;
2814 int key, asc, ascq;
2815
2816 BURN_ALLOC_MEM(buf, struct buffer, 1);
2817 BURN_ALLOC_MEM(c, struct command, 1);
2818 BURN_ALLOC_MEM(msg, char, 256);
2819 mmc_start_if_needed(d, 1);
2820 if (mmc_function_spy(d, "mmc_set_streaming") <= 0)
2821 {ret = 0; goto ex;}
2822
2823 scsi_init_command(c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
2824 c->retry = 1;
2825 c->page = buf;
2826 c->page->bytes = 28;
2827 c->opcode[9] = (c->page->bytes >> 8) & 0xff;
2828 c->opcode[10] = c->page->bytes & 0xff;
2829 c->page->sectors = 0;
2830 c->dir = TO_DRIVE;
2831 memset(c->page->data, 0, c->page->bytes);
2832 pd = c->page->data;
2833
2834 pd[0] = 0; /* WRC=0 (Default Rotation Control), RDD=Exact=RA=0 */
2835 if (d->set_streaming_exact_bit)
2836 pd[0] |= 2; /* Exact= 1 */
2837
2838 if (w_speed == 0)
2839 w_speed = 0x10000000; /* ~ 2 TB/s */
2840 else if (w_speed < 0)
2841 w_speed = 177; /* 1x CD */
2842 if (r_speed == 0)
2843 r_speed = 0x10000000; /* ~ 2 TB/s */
2844 else if (r_speed < 0)
2845 r_speed = 177; /* 1x CD */
2846 if (end_lba == 0) {
2847 /* Default computed from 4.7e9 */
2848 eff_end_lba = 2294921 - 1;
2849 if (d->mdata->max_end_lba > 0)
2850 eff_end_lba = d->mdata->max_end_lba - 1;
2851 } else
2852 eff_end_lba = end_lba;
2853
2854 sprintf(msg,
2855 "mmc_set_streaming: end_lba=%d , r=%d , w=%d , exact=%d",
2856 eff_end_lba, r_speed, w_speed, !!(pd[0] & 2));
2857 libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
2858 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
2859 msg, 0, 0);
2860
2861 /* start_lba is 0 , 1000 = 1 second as base time for data rate */
2862 for (b = 0; b < 4 ; b++) {
2863 pd[8+b] = (eff_end_lba >> (24 - 8 * b)) & 0xff;
2864 pd[12+b] = (r_speed >> (24 - 8 * b)) & 0xff;
2865 pd[16+b] = (1000 >> (24 - 8 * b)) & 0xff;
2866 pd[20+b] = (w_speed >> (24 - 8 * b)) & 0xff;
2867 pd[24+b] = (1000 >> (24 - 8 * b)) & 0xff;
2868 }
2869
2870 /* <<<
2871 fprintf(stderr,"LIBBURN_EXPERIMENTAL : B6h Performance descriptor:\n");
2872 for (b = 0; b < 28 ; b++)
2873 fprintf(stderr, "%2.2X%c", pd[b], ((b+1)%4 ? ' ' : '\n'));
2874 */
2875
2876
2877 d->issue_command(d, c);
2878 if (c->error) {
2879 spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
2880 if (key != 0 && d->silent_on_scsi_error != 1 &&
2881 d->silent_on_scsi_error != 2) {
2882 sprintf(msg,
2883 "SCSI error on set_streaming(%d): ", w_speed);
2884 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
2885 &key, &asc, &ascq);
2886 libdax_msgs_submit(libdax_messenger, d->global_index,
2887 0x00020124,
2888 d->silent_on_scsi_error == 3 ?
2889 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
2890 LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
2891 }
2892 if (key != 0)
2893 d->set_streaming_err = 1;
2894 {ret = 0; goto ex;}
2895 }
2896 ret = 1;
2897 ex:;
2898 BURN_FREE_MEM(msg);
2899 BURN_FREE_MEM(c);
2900 BURN_FREE_MEM(buf);
2901 return ret;
2902 }
2903
2904
2905 void mmc_set_speed(struct burn_drive *d, int r, int w)
2906 {
2907 struct command *c;
2908 int ret, end_lba = 0, get_max, get_min;
2909 struct burn_speed_descriptor *best_sd = NULL;
2910
2911 c = &(d->casual_command);
2912 mmc_start_if_needed(d, 1);
2913 if (mmc_function_spy(d, "mmc_set_speed") <= 0)
2914 return;
2915
2916 if (r <= 0 || w <= 0) {
2917 /* ts A70712 : now searching for best speed descriptor */
2918 /* ts B31030 : keeping max read speed from sinking too low */
2919 if (r <= 0) {
2920 get_max = (r == 0);
2921 get_min = (r == -1);
2922 burn_drive_get_best_speed(d, r, &best_sd, 1 | 2);
2923 if (best_sd != NULL) {
2924 r = best_sd->read_speed;
2925 end_lba = best_sd->end_lba;
2926 }
2927 if (get_max) {
2928 if (d->current_is_cd_profile) {
2929 if (r < Libburn_cd_max_read_speeD)
2930 r = Libburn_cd_max_read_speeD;
2931 } else if (d->current_profile >= 0x10 &&
2932 d->current_profile <= 0x2f) {
2933 if (r < Libburn_dvd_max_read_speeD)
2934 r = Libburn_dvd_max_read_speeD;
2935 } else if (d->current_profile >= 0x40 &&
2936 d->current_profile <= 0x43) {
2937 if (r < Libburn_bd_max_read_speeD)
2938 r = Libburn_bd_max_read_speeD;
2939 }
2940 } else if(get_min) {
2941 if (d->current_is_cd_profile) {
2942 if (r > Libburn_cd_min_read_speeD)
2943 r = Libburn_cd_min_read_speeD;
2944 } else if (d->current_profile >= 0x10 &&
2945 d->current_profile <= 0x2f) {
2946 if (r > Libburn_dvd_min_read_speeD)
2947 r = Libburn_dvd_min_read_speeD;
2948 } else if (d->current_profile >= 0x40 &&
2949 d->current_profile <= 0x43) {
2950 if (r > Libburn_bd_min_read_speeD)
2951 r = Libburn_bd_min_read_speeD;
2952 }
2953 }
2954 }
2955 if (w <= 0) {
2956 burn_drive_get_best_speed(d, w, &best_sd, 2);
2957 if (best_sd != NULL) {
2958 w = best_sd->write_speed;
2959 d->nominal_write_speed = w;
2960 if (end_lba < best_sd->end_lba)
2961 end_lba = best_sd->end_lba;
2962 }
2963 }
2964 }
2965
2966 /* A70711 */
2967 d->nominal_write_speed = w;
2968
2969 /* ts A61221 : try to set DVD speed via command B6h */
2970 if (strstr(d->current_profile_text, "DVD") == d->current_profile_text
2971 || strstr(d->current_profile_text, "BD") == d->current_profile_text
2972 || d->set_streaming_exact_bit) {
2973 ret = mmc_set_streaming(d, r, w, end_lba);
2974 if (ret != 0)
2975 return; /* success or really fatal failure */
2976 }
2977
2978 /* ts A61112 : MMC standards prescribe FFFFh as max speed.
2979 But libburn.h prescribes 0.
2980 ts A70715 : <0 now means minimum speed */
2981 if (r == 0 || r > 0xffff)
2982 r = 0xffff;
2983 else if (r < 0)
2984 r = 177; /* 1x CD */
2985 if (w == 0 || w > 0xffff)
2986 w = 0xffff;
2987 else if (w < 0)
2988 w = 177; /* 1x CD */
2989
2990 scsi_init_command(c, MMC_SET_SPEED, sizeof(MMC_SET_SPEED));
2991 c->retry = 1;
2992 c->opcode[2] = r >> 8;
2993 c->opcode[3] = r & 0xFF;
2994 c->opcode[4] = w >> 8;
2995 c->opcode[5] = w & 0xFF;
2996 c->page = NULL;
2997 c->dir = NO_TRANSFER;
2998 d->issue_command(d, c);
2999 }
3000
3001
3002 /* ts A61201 : found in unfunctional state
3003 */
3004 static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
3005 {
3006 struct buffer *buf = NULL;
3007 int len, cp, descr_len = 0, feature_code, only_current = 1, i;
3008 int old_alloc_len, key, asc, ascq, ret;
3009 int feature_is_current;
3010 unsigned char *descr, *prf, *up_to, *prf_end;
3011 struct command *c = NULL;
3012 int phys_if_std = 0;
3013 char *phys_name = "";
3014 struct burn_feature_descr *recent_feature = NULL, *new_feature;
3015 char *msg = NULL;
3016
3017 /* Enable this to get loud and repeated reports about the feature set :
3018 # define Libburn_print_feature_descriptorS 1
3019 */
3020 #ifdef Libburn_print_feature_descriptorS
3021 int prf_number;
3022
3023 only_current = 0;
3024 #endif
3025
3026 if (*alloc_len < 8)
3027 {ret = 0; goto ex;}
3028
3029 BURN_ALLOC_MEM(buf, struct buffer, 1);
3030 BURN_ALLOC_MEM(c, struct command, 1);
3031 d->current_profile = 0;
3032 d->current_profile_text[0] = 0;
3033 d->current_is_cd_profile = 0;
3034 d->current_is_supported_profile = 0;
3035 d->current_is_guessed_profile = 0;
3036 d->num_profiles = 0;
3037 if (d->features != NULL)
3038 burn_feature_descr_free(&(d->features), 0);
3039 d->current_has_feat21h = 0;
3040 d->current_feat21h_link_size = -1;
3041 d->current_feat23h_byte4 = 0;
3042 d->current_feat23h_byte8 = 0;
3043 d->current_feat2fh_byte4 = -1;
3044
3045 scsi_init_command(c, MMC_GET_CONFIGURATION,
3046 sizeof(MMC_GET_CONFIGURATION));
3047 c->dxfer_len= *alloc_len;
3048 c->retry = 1;
3049 c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
3050 c->opcode[8] = c->dxfer_len & 0xff;
3051 c->page = buf;
3052 c->page->sectors = 0;
3053 c->page->bytes = 0;
3054 c->dir = FROM_DRIVE;
3055 d->issue_command(d, c);
3056
3057 #ifdef Libisofs_simulate_old_mmc1_drivE
3058 c->error = 1;
3059 c->sense[0] = 0x70; /* Fixed format sense data */
3060 c->sense[2] = 0x5;
3061 c->sense[12] = 0x20;
3062 c->sense[13] = 0x0;
3063 #endif /* Libisofs_simulate_old_mmc1_drivE */
3064
3065 if (c->error) {
3066 /* ts A90603 : MMC-1 drive do not know 46h GET CONFIGURATION */
3067 spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
3068 if (key == 0x5 && asc == 0x20 && ascq == 0x0) {
3069 d->current_is_guessed_profile = 1;
3070 /* Will yield a non-zero profile only after
3071 mmc_read_disc_info_al() was called */
3072 mmc_guess_profile(d, 0);
3073 }
3074 {ret = 0; goto ex;}
3075 }
3076 old_alloc_len = *alloc_len;
3077 *alloc_len = len = mmc_four_char_to_int(c->page->data) + 4;
3078 if (len > old_alloc_len)
3079 len = old_alloc_len;
3080 if (len < 8)
3081 {ret = 0; goto ex;}
3082 if (len > 4096) {
3083 /* MMC-5 6.6.2.1, Note 11: The maximum is less than 1 KB */
3084 BURN_ALLOC_MEM(msg, char, 256);
3085 sprintf(msg, "Implausible length announcement from SCSI command GET CONFIGURATION: %d", *alloc_len);
3086 libdax_msgs_submit(libdax_messenger, d->global_index,
3087 0x000201a9,
3088 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_ZERO,
3089 msg, 0, 0);
3090 ret = 0; goto ex;
3091 }
3092
3093 cp = (c->page->data[6]<<8) | c->page->data[7];
3094
3095 #ifdef Libburn_rom_as_profilE
3096 if (cp == 0x08 || cp == 0x10 || cp==0x40)
3097 cp = Libburn_rom_as_profilE;
3098 #endif /* Libburn_rom_as_profilE */
3099
3100 d->current_profile = cp;
3101 strcpy(d->current_profile_text, mmc_obtain_profile_name(cp));
3102
3103 /* Read-only supported media */
3104
3105 if (cp == 0x08) /* CD-ROM */
3106 d->current_is_supported_profile = d->current_is_cd_profile = 1;
3107 if (cp == 0x10) /* DVD-ROM */
3108 d->current_is_supported_profile = 1;
3109 if (cp == 0x40) /* BD-ROM */
3110 d->current_is_supported_profile = 1;
3111
3112 #ifdef Libburn_support_bd_r_readonlY
3113 #ifndef Libburn_support_bd_plus_r_srM
3114 if (cp == 0x41) /* BD-R sequential (here as read-only dummy) */
3115 d->current_is_supported_profile = 1;
3116 #endif
3117 if (cp == 0x42) /* BD-R random recording */
3118 d->current_is_supported_profile = 1;
3119 #endif
3120
3121
3122 /* Write supported media (they get declared suitable in
3123 burn_disc_get_multi_caps) */
3124
3125 if (cp == 0x09 || cp == 0x0a)
3126 d->current_is_supported_profile = d->current_is_cd_profile = 1;
3127
3128 #ifdef Libburn_support_dvd_plus_rW
3129 if (cp == 0x1a)
3130 d->current_is_supported_profile = 1;
3131 #endif
3132 #ifdef Libburn_support_dvd_minusrw_overW
3133 if (cp == 0x13)
3134 d->current_is_supported_profile = 1;
3135 #endif
3136 #ifdef Libburn_support_dvd_raM
3137 if (cp == 0x12 || cp == 0x43) { /* DVD-RAM , BD-RE */
3138 d->current_is_supported_profile = 1;
3139
3140 #ifdef Libburn_dvd_ram_as_bd_rE
3141 cp = d->current_profile = 0x43;
3142 strcpy(d->current_profile_text, mmc_obtain_profile_name(cp));
3143 #endif
3144
3145 }
3146 #endif
3147 #ifdef Libburn_support_dvd_r_seQ
3148 if (cp == 0x11 || cp == 0x14) /* DVD-R, DVD-RW */
3149 d->current_is_supported_profile = 1;
3150 if (cp == 0x15) /* DVD-R/DL */
3151 d->current_is_supported_profile = 1;
3152 #endif
3153 #ifdef Libburn_support_dvd_plus_R
3154 if (cp == 0x1b || cp == 0x2b) /* DVD+R , DVD+R/DL */
3155 d->current_is_supported_profile = 1;
3156 #endif
3157 #ifdef Libburn_support_bd_plus_r_srM
3158 if (cp == 0x41) /* BD-R SRM */
3159 d->current_is_supported_profile = 1;
3160 #endif
3161
3162 /* ts A70127 : Interpret list of profile and feature descriptors.
3163 see mmc5r03c.pdf 5.2
3164 */
3165 up_to = c->page->data + len;
3166
3167 #ifdef Libburn_print_feature_descriptorS
3168 fprintf(stderr,
3169 "-----------------------------------------------------------------\n");
3170 fprintf(stderr,
3171 "LIBBURN_EXPERIMENTAL : feature list length = %d , shown = %d\n",
3172 len, (int) (up_to - c->page->data));
3173 #endif /* Libburn_print_feature_descriptorS */
3174
3175 for (descr = c->page->data + 8; descr + 3 < up_to; descr += descr_len){
3176 descr_len = 4 + descr[3];
3177 feature_code = (descr[0] << 8) | descr[1];
3178 feature_is_current = descr[2] & 1;
3179
3180 ret = burn_feature_descr_new(&new_feature, descr,
3181 up_to - descr, 0);
3182 if (ret > 0) {
3183 if (d->features == NULL)
3184 d->features = new_feature;
3185 else
3186 recent_feature->next = new_feature;
3187 recent_feature = new_feature;
3188 }
3189
3190 if (only_current && !feature_is_current)
3191 continue;
3192
3193 #ifdef Libburn_print_feature_descriptorS
3194 fprintf(stderr,
3195 "LIBBURN_EXPERIMENTAL : %s feature %4.4Xh :",
3196 (descr[2] & 1) ? "+" : "-",
3197 feature_code);
3198 if (feature_code != 0x00)
3199 for (i = 2; i < descr_len; i++)
3200 fprintf(stderr, " %2.2X", descr[i]);
3201 fprintf(stderr, "\n");
3202 #endif /* Libburn_print_feature_descriptorS */
3203
3204 if (feature_code == 0x0) {
3205 prf_end = descr + 4 + descr[3];
3206 d->num_profiles = descr[3] / 4;
3207 if (d->num_profiles > 64)
3208 d->num_profiles = 64;
3209 if (d->num_profiles > 0)
3210 memcpy(d->all_profiles, descr + 4,
3211 d->num_profiles * 4);
3212 for (prf = descr + 4; prf + 2 < prf_end; prf += 4) {
3213
3214 #ifdef Libburn_print_feature_descriptorS
3215 prf_number = (prf[0] << 8) | prf[1];
3216 fprintf(stderr,
3217 "LIBBURN_EXPERIMENTAL : %s profile %4.4Xh \"%s\"\n",
3218 prf[2] & 1 ? "+" : "-",
3219 prf_number,
3220 mmc_obtain_profile_name(prf_number));
3221 #endif /* Libburn_print_feature_descriptorS */
3222
3223 }
3224
3225 } else if (feature_code == 0x21) {
3226
3227 d->current_has_feat21h = feature_is_current;
3228 for (i = 0; i < descr[7]; i++) {
3229 if (i == 0 || descr[8 + i] == 16)
3230 d->current_feat21h_link_size =
3231 descr[8 + i];
3232
3233 #ifdef Libburn_print_feature_descriptorS
3234 fprintf(stderr,
3235 "LIBBURN_EXPERIMENTAL : + Link Size = %d\n",
3236 descr[8 + i]);
3237 #endif /* Libburn_print_feature_descriptorS */
3238
3239 }
3240
3241 } else if (feature_code == 0x23) {
3242 if (feature_is_current) {
3243 d->current_feat23h_byte4 = descr[4];
3244 d->current_feat23h_byte8 = descr[8];
3245 }
3246 #ifdef Libburn_print_feature_descriptorS
3247 if (cp >= 0x41 && cp <= 0x43)
3248 fprintf(stderr,
3249 "LIBBURN_EXPERIMENTAL : BD formats: %s%s%s%s%s\n",
3250 descr[4] & 1 ? " Cert" : "",
3251 descr[4] & 2 ? " QCert" : "",
3252 descr[4] & 4 ? " Expand" : "",
3253 descr[4] & 8 ? " RENoSA" : "",
3254 descr[8] & 1 ? " RRM" : "");
3255 #endif /* Libburn_print_feature_descriptorS */
3256
3257 } else if (feature_code == 0x2F) {
3258 if (feature_is_current)
3259 d->current_feat2fh_byte4 = descr[4];
3260
3261 #ifdef Libburn_print_feature_descriptorS
3262 fprintf(stderr, "LIBBURN_EXPERIMENTAL : BUF = %d , Test Write = %d , DVD-RW = %d\n",
3263 !!(descr[4] & 64), !!(descr[4] & 4),
3264 !!(descr[4] & 2));
3265 #endif /* Libburn_print_feature_descriptorS */
3266
3267 } else if (feature_code == 0x01) {
3268 phys_if_std = (descr[4] << 24) | (descr[5] << 16) |
3269 (descr[6] << 8) | descr[7];
3270 if (phys_if_std == 1)
3271 phys_name = "SCSI Family";
3272 else if(phys_if_std == 2)
3273 phys_name = "ATAPI";
3274 else if(phys_if_std == 3 || phys_if_std == 4 ||
3275 phys_if_std == 6)
3276 phys_name = "IEEE 1394 FireWire";
3277 else if(phys_if_std == 7)
3278 phys_name = "Serial ATAPI";
3279 else if(phys_if_std == 8)
3280 phys_name = "USB";
3281
3282 d->phys_if_std = phys_if_std;
3283 strcpy(d->phys_if_name, phys_name);
3284
3285 #ifdef Libburn_print_feature_descriptorS
3286
3287 fprintf(stderr,
3288 "LIBBURN_EXPERIMENTAL : Phys. Interface Standard %Xh \"%s\"\n",
3289 phys_if_std, phys_name);
3290
3291 } else if (feature_code == 0x107) {
3292
3293 fprintf(stderr, "LIBBURN_EXPERIMENTAL : CD SPEED = %d , page 2Ah = %d , SET STREAMING = %d\n",
3294 !!(descr[4] & 8), !!(descr[4] & 4),
3295 !!(descr[4] & 2));
3296
3297 #endif /* Libburn_print_feature_descriptorS */
3298
3299 } else if (feature_code == 0x108 || feature_code == 0x10c) {
3300 int c_limit;
3301
3302 #ifdef Libburn_print_feature_descriptorS
3303 int i;
3304 fprintf(stderr, "LIBBURN_EXPERIMENTAL : %s = ",
3305 feature_code == 0x108 ?
3306 "Drive Serial Number" : "Drive Firmware Date");
3307 #endif /* Libburn_print_feature_descriptorS */
3308
3309 c_limit = descr[3] - 2 * (feature_code == 0x10c);
3310 if (feature_code == 0x108) {
3311 if (d->drive_serial_number != NULL)
3312 BURN_FREE_MEM(d->drive_serial_number);
3313 BURN_ALLOC_MEM(d->drive_serial_number,
3314 char, c_limit + 1);
3315 memcpy(d->drive_serial_number, descr + 4,
3316 c_limit);
3317 d->drive_serial_number[c_limit] = 0;
3318 d->drive_serial_number_len = c_limit;
3319 }
3320
3321 #ifdef Libburn_print_feature_descriptorS
3322 for (i = 0; i < c_limit; i++)
3323 if (descr[4 + i] < 0x20 || descr[4 + i] > 0x7e
3324 || descr[4 + i] == '\\')
3325 fprintf(stderr,"\\%2.2X",descr[4 + i]);
3326 else
3327 fprintf(stderr, "%c", descr[4 + i]);
3328 fprintf(stderr, "\n");
3329
3330 #endif /* Libburn_print_feature_descriptorS */
3331
3332 }
3333 }
3334 ret = 1;
3335 ex:
3336 BURN_FREE_MEM(msg);
3337 BURN_FREE_MEM(buf);
3338 BURN_FREE_MEM(c);
3339 return ret;
3340 }
3341
3342
3343 void mmc_get_configuration(struct burn_drive *d)
3344 {
3345 int alloc_len = 8, ret;
3346
3347 if (d->current_profile > 0 && d->current_profile < 0xffff)
3348 return;
3349
3350 mmc_start_if_needed(d, 1);
3351 if (mmc_function_spy(d, "mmc_get_configuration") <= 0)
3352 return;
3353
3354 /* first command execution to learn Allocation Length */
3355 ret = mmc_get_configuration_al(d, &alloc_len);
3356 /*
3357 fprintf(stderr,"LIBBURN_DEBUG: 46h alloc_len = %d , ret = %d\n",
3358 alloc_len, ret);
3359 */
3360 if (alloc_len > 8 && ret > 0) {
3361 /* second execution with announced length */
3362 mmc_get_configuration_al(d, &alloc_len);
3363 }
3364 }
3365
3366
3367 /* ts A70108 */
3368 /* mmc5r03c.pdf 6.24 */
3369 static int mmc_read_format_capacities_al(struct burn_drive *d,
3370 int *alloc_len, int top_wanted)
3371 {
3372 struct buffer *buf = NULL;
3373 int len, type, score, num_descr, max_score = -2000000000, i, sign = 1;
3374 int old_alloc_len, ret;
3375 off_t size, num_blocks;
3376 struct command *c = NULL;
3377 unsigned char *dpt;
3378
3379 BURN_ALLOC_MEM(buf, struct buffer, 1);
3380 BURN_ALLOC_MEM(c, struct command, 1);
3381 if (*alloc_len < 4)
3382 {ret = 0; goto ex;}
3383
3384 d->format_descr_type = 3;
3385 d->format_curr_max_size = 0;
3386 d->format_curr_blsas = 0;
3387 d->best_format_type = -1;
3388 d->best_format_size = 0;
3389
3390 scsi_init_command(c, MMC_READ_FORMAT_CAPACITIES,
3391 sizeof(MMC_READ_FORMAT_CAPACITIES));
3392 c->dxfer_len = *alloc_len;
3393 c->retry = 1;
3394 c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
3395 c->opcode[8]= c->dxfer_len & 0xff;
3396 c->page = buf;
3397 c->page->sectors = 0;
3398 c->page->bytes = 0;
3399 c->dir = FROM_DRIVE;
3400
3401 d->issue_command(d, c);
3402 if (c->error)
3403 {ret = 0; goto ex;}
3404
3405 len = c->page->data[3];
3406 old_alloc_len = *alloc_len;
3407 *alloc_len = len + 4;
3408 if (old_alloc_len < 12)
3409 {ret = 1; goto ex;}
3410 if (len + 4 > old_alloc_len)
3411 len = old_alloc_len - 4;
3412 if (len < 8)
3413 {ret = 0; goto ex;}
3414
3415 dpt = c->page->data + 4;
3416 /* decode 6.24.3.2 Current/Maximum Capacity Descriptor */
3417 d->format_descr_type = dpt[4] & 3;
3418 d->format_curr_max_size = (((off_t) dpt[0]) << 24)
3419 + (dpt[1] << 16) + (dpt[2] << 8) + dpt[3];
3420 if (d->format_descr_type == BURN_FORMAT_IS_UNKNOWN)
3421 d->format_curr_max_size = 0;
3422 d->format_curr_blsas = (dpt[5] << 16) + (dpt[6] << 8) + dpt[7];
3423 d->format_curr_max_size *= (off_t) 2048;
3424 if((d->current_profile == 0x12 || d->current_profile == 0x43)
3425 && d->media_capacity_remaining == 0) {
3426 burn_drive_set_media_capacity_remaining(d,
3427 d->format_curr_max_size);
3428 d->media_lba_limit = d->format_curr_max_size / 2048;
3429 }
3430
3431
3432 #ifdef Libburn_dvd_ram_as_bd_rE
3433 /* <<< dummy format descriptor list as obtained from
3434 dvd+rw-mediainfo by Giulio Orsero in April 2008
3435 */
3436 d->num_format_descr = 5;
3437 d->format_descriptors[0].type = 0x00;
3438 d->format_descriptors[0].size = (off_t) 11826176 * (off_t) 2048;
3439 d->format_descriptors[0].tdp = 0x3000;
3440 d->format_descriptors[1].type = 0x30;
3441 d->format_descriptors[1].size = (off_t) 11826176 * (off_t) 2048;
3442 d->format_descriptors[1].tdp = 0x3000;
3443 d->format_descriptors[2].type = 0x30;
3444 d->format_descriptors[2].size = (off_t) 11564032 * (off_t) 2048;
3445 d->format_descriptors[2].tdp = 0x5000;
3446 d->format_descriptors[3].type = 0x30;
3447 d->format_descriptors[3].size = (off_t) 12088320 * (off_t) 2048;
3448 d->format_descriptors[3].tdp = 0x1000;
3449 d->format_descriptors[4].type = 0x31;
3450 d->format_descriptors[4].size = (off_t) 12219392 * (off_t) 2048;
3451 d->format_descriptors[4].tdp = 0x800;
3452 d->best_format_type = 0x00;
3453 d->best_format_size = (off_t) 11826176 * (off_t) 2048;
3454
3455 /* silencing compiler warnings about unused variables */
3456 num_blocks = size = sign = i = max_score = num_descr = score = type = 0;
3457
3458 if (d->current_profile == 0x12 || d->current_profile == 0x43)
3459 {ret = 1; goto ex;}
3460 d->num_format_descr = 0;
3461
3462 #endif /* Libburn_dvd_ram_as_bd_rE */
3463
3464 if (top_wanted == 0x00 || top_wanted == 0x10)
3465 sign = -1; /* the caller clearly desires full format */
3466
3467 /* 6.24.3.3 Formattable Capacity Descriptors */
3468 num_descr = (len - 8) / 8;
3469 for (i = 0; i < num_descr; i++) {
3470 dpt = c->page->data + 12 + 8 * i;
3471 num_blocks = mmc_four_char_to_int(dpt);
3472 size = num_blocks * (off_t) 2048;
3473 type = dpt[4] >> 2;
3474
3475 if (i < 32) {
3476 d->format_descriptors[i].type = type;
3477 d->format_descriptors[i].size = size;
3478 d->format_descriptors[i].tdp =
3479 (dpt[5] << 16) + (dpt[6] << 8) + dpt[7];
3480 d->num_format_descr = i + 1;
3481 }
3482 /* Criterion is proximity to quick intermediate state */
3483 if (type == 0x00) { /* full format (with lead out) */
3484 score = 1 * sign;
3485 } else if (type == 0x10) { /* DVD-RW full format */
3486 score = 10 * sign;
3487 } else if(type == 0x13) { /* DVD-RW quick grow last session */
3488 score = 100 * sign;
3489 } else if(type == 0x15) { /* DVD-RW Quick */
3490 score = 50 * sign;
3491 if(d->current_profile == 0x13) {
3492 burn_drive_set_media_capacity_remaining(d,
3493 size);
3494 d->media_lba_limit = num_blocks;
3495 }
3496 } else if(type == 0x26) { /* DVD+RW */
3497 score = 1 * sign;
3498 burn_drive_set_media_capacity_remaining(d, size);
3499 d->media_lba_limit = num_blocks;
3500 } else {
3501 continue;
3502 }
3503 if (type == top_wanted)
3504 score += 1000000000;
3505 if (score > max_score) {
3506 d->best_format_type = type;
3507 d->best_format_size = size;
3508 max_score = score;
3509 }
3510 }
3511 ret = 1;
3512 ex:
3513 BURN_FREE_MEM(buf);
3514 BURN_FREE_MEM(c);
3515 return ret;
3516 }
3517
3518
3519 int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
3520 {
3521 int alloc_len = 4, ret;
3522
3523 mmc_start_if_needed(d, 1);
3524 if (mmc_function_spy(d, "mmc_read_format_capacities") <= 0)
3525 return 0;
3526
3527 ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted);
3528 /*
3529 fprintf(stderr,"LIBBURN_DEBUG: 23h alloc_len = %d , ret = %d\n",
3530 alloc_len, ret);
3531 */
3532 if (alloc_len >= 12 && ret > 0)
3533 ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted);
3534
3535 return ret;
3536 }
3537
3538
3539 void mmc_sync_cache(struct burn_drive *d)
3540 {
3541 struct command *c = NULL;
3542 char *msg = NULL;
3543 int key, asc, ascq;
3544
3545 if (mmc_function_spy(d, "mmc_sync_cache") <= 0)
3546 goto ex;
3547
3548 BURN_ALLOC_MEM_VOID(c, struct command, 1);
3549 BURN_ALLOC_MEM_VOID(msg, char, 256);
3550
3551 scsi_init_command(c, MMC_SYNC_CACHE, sizeof(MMC_SYNC_CACHE));
3552 c->retry = 1;
3553 if (!d->do_no_immed)
3554 c->opcode[1] |= 2; /* ts A70918 : Immed */
3555 c->page = NULL;
3556 c->dir = NO_TRANSFER;
3557 if (d->do_no_immed)
3558 c->timeout = Libburn_mmc_sync_noim_timeouT;
3559 else
3560 c->timeout = Libburn_mmc_sync_timeouT;
3561
3562 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
3563 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
3564 "syncing cache", 0, 0);
3565 if(d->wait_for_buffer_free) {
3566 sprintf(msg,
3567 "Checked buffer %u times. Waited %u+%u times = %.3f s",
3568 d->pessimistic_writes, d->waited_writes,
3569 d->waited_tries - d->waited_writes,
3570 ((double) d->waited_usec) / 1.0e6);
3571 libdax_msgs_submit(libdax_messenger, d->global_index,
3572 0x0002013f,
3573 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
3574 msg, 0,0);
3575 }
3576
3577 d->issue_command(d, c);
3578
3579 /* ts A70918 */
3580 if (c->error) {
3581 sprintf(msg, "Failed to synchronize drive cache");
3582 sprintf(msg + strlen(msg), ". SCSI error : ");
3583 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
3584 &key, &asc, &ascq);
3585 libdax_msgs_submit(libdax_messenger, d->global_index,
3586 0x0002017f,
3587 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
3588 msg, 0, 0);
3589 d->cancel = 1;
3590 goto ex;
3591 }
3592
3593 spc_human_readable_cmd(c, msg, 160, 0);
3594 if (spc_wait_unit_attention(d, 3600, msg, 0) <= 0)
3595 d->cancel = 1;
3596 else
3597 d->needs_sync_cache = 0;
3598 ex:
3599 BURN_FREE_MEM(msg);
3600 BURN_FREE_MEM(c);
3601 }
3602
3603
3604 /* ts A61023 : http://libburn.pykix.org/ticket/14
3605 get size and free space of drive buffer
3606 */
3607 int mmc_read_buffer_capacity(struct burn_drive *d)
3608 {
3609 struct buffer *buf = NULL;
3610 struct command *c = NULL;
3611 unsigned char *data;
3612 int alloc_len = 12, ret;
3613
3614 BURN_ALLOC_MEM(buf, struct buffer, 1);
3615 BURN_ALLOC_MEM(c, struct command, 1);
3616 if (mmc_function_spy(d, "mmc_read_buffer_capacity") <= 0)
3617 {ret = 0; goto ex;}
3618
3619 scsi_init_command(c, MMC_READ_BUFFER_CAPACITY,
3620 sizeof(MMC_READ_BUFFER_CAPACITY));
3621 c->dxfer_len = alloc_len;
3622 c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
3623 c->opcode[8] = c->dxfer_len & 0xff;
3624 c->retry = 1;
3625 c->page = buf;
3626 memset(c->page->data, 0, alloc_len);
3627 c->page->bytes = 0;
3628 c->page->sectors = 0;
3629
3630 c->dir = FROM_DRIVE;
3631 d->issue_command(d, c);
3632
3633 /* >>> ??? error diagnostics */
3634 if (c->error)
3635 {ret = 0; goto ex;}
3636
3637 data = c->page->data;
3638
3639 d->progress.buffer_capacity =
3640 (data[4]<<24)|(data[5]<<16)|(data[6]<<8)|data[7];
3641 d->progress.buffer_available =
3642 (data[8]<<24)|(data[9]<<16)|(data[10]<<8)|data[11];
3643 if (d->progress.buffer_capacity < d->progress.buffer_available) {
3644 /* Default mad buffer usage to 50 percent */
3645 d->progress.buffer_available = d->progress.buffer_capacity / 2;
3646 }
3647 d->pessimistic_buffer_free = d->progress.buffer_available;
3648 d->pbf_altered = 0;
3649 if (d->progress.buffered_bytes >= d->progress.buffer_capacity){
3650 double fill;
3651
3652 fill = d->progress.buffer_capacity
3653 - d->progress.buffer_available;
3654 if (fill < d->progress.buffer_min_fill && fill>=0)
3655 d->progress.buffer_min_fill = fill;
3656 }
3657 ret = 1;
3658 ex:;
3659 BURN_FREE_MEM(c);
3660 BURN_FREE_MEM(buf);
3661 return ret;
3662 }
3663
3664
3665 /* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format()
3666 and mmc5r03c.pdf, 6.5 FORMAT UNIT */
3667 /*
3668 @param size The size (in bytes) to be sent with the FORMAT command
3669 @param flag bit1+2: size mode
3670 0 = use parameter size as far as it makes sense
3671 1 = insist in size 0 even if there is a better default known
3672 2 = without bit7: format to maximum available size
3673 with bit7 : take size from indexed format descriptor
3674 3 = format to default size
3675 bit3= expand format up to at least size
3676 bit4= enforce re-format of (partly) formatted media
3677 bit5= try to disable eventual defect management
3678 bit6= try to avoid lengthy media certification
3679 bit7= bit8 to bit15 contain the index of the format to use
3680 bit8-bit15 = see bit7
3681 bit16= enable POW on blank BD-R
3682 */
3683 int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
3684 {
3685 struct buffer *buf = NULL;
3686 struct command *c = NULL;
3687 int ret, tolerate_failure = 0, return_immediately = 0, i, format_type;
3688 int index, format_sub_type = 0, format_00_index, size_mode;
3689 int accept_count = 0;
3690 off_t num_of_blocks = 0, diff, format_size, i_size, format_00_max_size;
3691 off_t min_size = -1, max_size = -1;
3692 char *msg = NULL, descr[80 + 10 + 22]; /* profile+filltext+index */
3693 int key, asc, ascq;
3694 int full_format_type = 0x00; /* Full Format (or 0x10 for DVD-RW ?) */
3695
3696 BURN_ALLOC_MEM(buf, struct buffer, 1);
3697 BURN_ALLOC_MEM(c, struct command, 1);
3698 BURN_ALLOC_MEM(msg, char, 256);
3699 mmc_start_if_needed(d, 0);
3700 if (mmc_function_spy(d, "mmc_format_unit") <= 0)
3701 {ret = 0; goto ex;}
3702 size_mode = (flag >> 1) & 3;
3703
3704 scsi_init_command(c, MMC_FORMAT_UNIT, sizeof(MMC_FORMAT_UNIT));
3705 c->retry = 1;
3706 c->page = buf;
3707 c->page->bytes = 12;
3708 c->page->sectors = 0;
3709 c->dir = TO_DRIVE;
3710 if (d->do_no_immed)
3711 c->timeout = Libburn_mmc_blank_noim_timeouT;
3712 else
3713 c->timeout = Libburn_mmc_blank_timeouT;
3714 memset(c->page->data, 0, c->page->bytes);
3715
3716 descr[0] = 0;
3717 if (!d->do_no_immed)
3718 c->page->data[1] = 0x02; /* Immed */
3719 c->page->data[3] = 8; /* Format descriptor length */
3720 num_of_blocks = size / 2048;
3721 mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
3722
3723 if (flag & 128) { /* explicitly chosen format descriptor */
3724 /* use case: the app knows what to do */
3725
3726 ret = mmc_read_format_capacities(d, -1);
3727 if (ret <= 0)
3728 goto selected_not_suitable;
3729 index = (flag >> 8) & 0xff;
3730 if(index < 0 || index >= d->num_format_descr) {
3731 selected_not_suitable:;
3732 libdax_msgs_submit(libdax_messenger, d->global_index,
3733 0x00020132,
3734 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
3735 "Selected format is not suitable for libburn",
3736 0, 0);
3737 {ret = 0; goto ex;}
3738 }
3739 if (!(d->current_profile == 0x13 ||
3740 d->current_profile == 0x14 ||
3741 d->current_profile == 0x1a ||
3742 d->current_profile == 0x12 ||
3743 d->current_profile == 0x41 ||
3744 d->current_profile == 0x43))
3745 goto unsuitable_media;
3746
3747 format_type = d->format_descriptors[index].type;
3748 if (!(format_type == 0x00 || format_type == 0x01 ||
3749 format_type == 0x10 ||
3750 format_type == 0x11 || format_type == 0x13 ||
3751 format_type == 0x15 || format_type == 0x26 ||
3752 format_type == 0x30 || format_type == 0x31 ||
3753 format_type == 0x32))
3754 goto selected_not_suitable;
3755 if (flag & 4) {
3756 num_of_blocks =
3757 d->format_descriptors[index].size / 2048;
3758 mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
3759 }
3760 if (format_type != 0x26)
3761 for (i = 0; i < 3; i++)
3762 c->page->data[9 + i] =
3763 ( d->format_descriptors[index].tdp >>
3764 (16 - 8 * i)) & 0xff;
3765 if (format_type == 0x30 || format_type == 0x31) {
3766 format_sub_type = 0;
3767 if (flag & 64) {
3768 if (d->current_feat23h_byte4 & 2)
3769 /* Quick certification */
3770 format_sub_type = 3;
3771 } else {
3772 if (d->current_feat23h_byte4 & 1)
3773 /* Full certification */
3774 format_sub_type = 2;
3775 }
3776 } else if (format_type == 0x32 ||
3777 (format_type == 0x00 && d->current_profile == 0x41)) {
3778 if (flag & (1 << 16))
3779 format_sub_type = 0; /* SRM + POW */
3780 else
3781 format_sub_type = 1; /* SRM (- POW) */
3782 }
3783 if (d->current_profile == 0x12 && format_type !=0x01 &&
3784 (flag & 64)) {
3785 /* DCRT and CmpList, see below */
3786 c->page->data[1] |= 0x20;
3787 c->opcode[1] |= 0x08;
3788 }
3789 c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
3790 sprintf(descr, "%s (descr %d)", d->current_profile_text,index);
3791 return_immediately = 1; /* caller must do the waiting */
3792
3793 } else if (d->current_profile == 0x1a) { /* DVD+RW */
3794 /* use case: background formatting during write !(flag&4)
3795 de-icing as explicit formatting action (flag&4)
3796 */
3797
3798 /* mmc5r03c.pdf , 6.5.4.2.14, DVD+RW Basic Format */
3799 format_type = 0x26;
3800
3801 /* >>> ??? is this "| 8" a bug ? */
3802
3803 if ((size <= 0 && !(flag & 2)) || (flag & (4 | 8))) {
3804 /* maximum capacity */
3805 memset(c->page->data + 4, 0xff, 4);
3806 num_of_blocks = 0xffffffff;
3807 }
3808
3809 if(d->bg_format_status == 2 ||
3810 (d->bg_format_status == 3 && !(flag & 16))) {
3811 sprintf(msg,"FORMAT UNIT ignored. Already %s.",
3812 (d->bg_format_status == 2 ? "in progress" :
3813 "completed"));
3814 libdax_msgs_submit(libdax_messenger, d->global_index,
3815 0x00020120,
3816 LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
3817 msg, 0,0);
3818 {ret = 2; goto ex;}
3819 }
3820 if (!(flag & 16)) /* if not re-format is desired */
3821 if (d->bg_format_status == 1) /* is partly formatted */
3822 c->page->data[11] = 1; /* Restart bit */
3823 sprintf(descr, "DVD+RW (fs=%d,rs=%d)",
3824 d->bg_format_status, (c->page->data[11] == 1));
3825 if (flag & 4)
3826 return_immediately = 1;/* caller must do the waiting */
3827
3828 } else if (d->current_profile == 0x13 && !(flag & 16)) {
3829 /*DVD-RW restricted overwrite*/
3830 /* use case: quick grow formatting during write */
3831
3832 ret = mmc_read_format_capacities(d, 0x13);
3833 if (ret > 0) {
3834 if (d->best_format_type == 0x13) {
3835 if (d->best_format_size <= 0)
3836 {ret = 1; goto ex;}
3837 } else {
3838 if (d->format_descr_type == 2) /* formatted */
3839 {ret = 1; goto ex;}
3840 if (d->format_descr_type == 3){/*intermediate*/
3841 d->needs_close_session = 1;
3842 {ret = 1; goto ex;}
3843 }
3844 /* does trying make sense at all ? */
3845 tolerate_failure = 1;
3846 }
3847 }
3848 if (d->best_format_type == 0x13 && (flag & (4 | 8))) {
3849 num_of_blocks = d->best_format_size / 2048;
3850 if (flag & 8) {
3851 /* num_of_blocks needed to reach size */
3852 diff = (size - d->format_curr_max_size) /32768;
3853 if ((size - d->format_curr_max_size) % 32768)
3854 diff++;
3855 diff *= 16;
3856 if (diff < num_of_blocks)
3857 num_of_blocks = diff;
3858 }
3859 if (num_of_blocks > 0)
3860 mmc_int_to_four_char(c->page->data + 4,
3861 num_of_blocks);
3862 }
3863 /* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */
3864 format_type = 0x13;
3865 c->page->data[11] = 16; /* block size * 2k */
3866 sprintf(descr, "DVD-RW quick grow");
3867
3868 } else if (d->current_profile == 0x14 ||
3869 (d->current_profile == 0x13 && (flag & 16))) {
3870 /* DVD-RW sequential recording (or Overwrite for re-format) */
3871 /* use case : transition from Sequential to Overwrite
3872 re-formatting of Overwrite media */
3873
3874 /* To Restricted Overwrite */
3875 /* 6.5.4.2.10 Format Type = 15h (DVD-RW Quick) */
3876 /* or 6.5.4.2.1 Format Type = 00h (Full Format) */
3877 /* or 6.5.4.2.5 Format Type = 10h (DVD-RW Full Format) */
3878 mmc_read_format_capacities(d,
3879 (flag & 4) ? full_format_type : 0x15);
3880 if (d->best_format_type == 0x15 ||
3881 d->best_format_type == full_format_type) {
3882 if ((flag & 4)
3883 || d->best_format_type == full_format_type) {
3884 num_of_blocks = d->best_format_size / 2048;
3885 mmc_int_to_four_char(c->page->data + 4,
3886 num_of_blocks);
3887 }
3888
3889 } else {
3890 no_suitable_formatting_type:;
3891 libdax_msgs_submit(libdax_messenger, d->global_index,
3892 0x00020131,
3893 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
3894 "No suitable formatting type offered by drive",
3895 0, 0);
3896 {ret = 0; goto ex;}
3897 }
3898 format_type = d->best_format_type;
3899 sprintf(descr, "DVD-RW %s",
3900 format_type == 0x15 ? "quick" : "full");
3901 return_immediately = 1; /* caller must do the waiting */
3902
3903 } else if (d->current_profile == 0x12) {
3904 /* ts A80417 : DVD-RAM */
3905 /* 6.5.4.2.1 Format Type = 00h (Full Format)
3906 6.5.4.2.2 Format Type = 01h (Spare Area Expansion)
3907 */
3908 index = format_00_index = -1;
3909 format_size = format_00_max_size = -1;
3910 for (i = 0; i < d->num_format_descr; i++) {
3911 format_type = d->format_descriptors[i].type;
3912 i_size = d->format_descriptors[i].size;
3913 if (format_type != 0x00 && format_type != 0x01)
3914 continue;
3915 if (flag & 32) { /* No defect mgt */
3916 /* Search for largest 0x00 format descriptor */
3917 if (format_type != 0x00)
3918 continue;
3919 if (i_size < format_size)
3920 continue;
3921 format_size = i_size;
3922 index = i;
3923 continue;
3924 } else if (flag & 4) { /*Max or default size with mgt*/
3925 /* Search for second largest 0x00
3926 format descriptor. For max size allow
3927 format type 0x01.
3928 */
3929 if (format_type == 0x00) {
3930 if (i_size < format_size)
3931 continue;
3932 if (i_size < format_00_max_size) {
3933 format_size = i_size;
3934 index = i;
3935 continue;
3936 }
3937 format_size = format_00_max_size;
3938 index = format_00_index;
3939 format_00_max_size = i_size;
3940 format_00_index = i;
3941 continue;
3942 }
3943 if (size_mode==3)
3944 continue;
3945 if (i_size > format_size) {
3946 format_size = i_size;
3947 index = i;
3948 }
3949 continue;
3950 }
3951 /* Search for smallest 0x0 or 0x01
3952 descriptor >= size */;
3953 if (d->format_descriptors[i].size >= size &&
3954 (format_size < 0 || i_size < format_size)
3955 ) {
3956 format_size = i_size;
3957 index = i;
3958 }
3959 }
3960 if(index < 0 && (flag & 4) && !(flag & 32)) {
3961 format_size = format_00_max_size;
3962 index = format_00_index;
3963 }
3964 if(index < 0)
3965 goto no_suitable_formatting_type;
3966 format_type = d->format_descriptors[index].type;
3967 num_of_blocks = d->format_descriptors[index].size / 2048;
3968 mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
3969 for (i = 0; i < 3; i++)
3970 c->page->data[9 + i] =
3971 ( d->format_descriptors[index].tdp >>
3972 (16 - 8 * i)) & 0xff;
3973 sprintf(descr, "%s", d->current_profile_text);
3974 return_immediately = 1; /* caller must do the waiting */
3975 c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
3976
3977 if ((flag & 64) && format_type != 0x01) {
3978 /* MMC-5 6.5.3.2 , 6.5.4.2.1.2
3979 DCRT: Disable Certification and maintain number
3980 of blocks
3981 CmpList: Override maintaining of number of blocks
3982 with DCRT
3983 */
3984 /* ts A80426 : prevents change of formatted size
3985 with PHILIPS SPD3300L and Verbatim 3x DVD-RAM
3986 and format_type 0x00. Works on TSSTcorp SH-S203B
3987 */
3988 c->page->data[1] |= 0x20;
3989 c->opcode[1] |= 0x08;
3990 }
3991
3992 } else if (d->current_profile == 0x41) {
3993 /* BD-R SRM */
3994
3995 index = -1;
3996 format_size = -1;
3997 if (d->num_format_descr <= 0)
3998 goto no_suitable_formatting_type;
3999 if (d->format_descriptors[0].type != 0)
4000 goto no_suitable_formatting_type;
4001 for (i = 0; i < d->num_format_descr; i++) {
4002 format_type = d->format_descriptors[i].type;
4003 i_size = d->format_descriptors[i].size;
4004 if (format_type != 0x00 && format_type != 0x32)
4005 continue;
4006 if (flag & 32) { /* No defect mgt */
4007 /* ts A81211 : MMC-5 6.5.4.2.17.1
4008 When formatted with Format Type 32h,
4009 the BD-R disc is required to allocate
4010 a non-zero number of spares.
4011 */
4012 goto no_suitable_formatting_type;
4013
4014 } else if(size_mode == 2) { /* max payload size */
4015 /* search largest 0x32 format descriptor */
4016 if(format_type != 0x32)
4017 continue;
4018 } else if(size_mode == 3) { /* default payload size */
4019 if (format_type == 0x00) {
4020 index = i;
4021 break;
4022 }
4023 continue;
4024 } else { /* defect managed format with size wish */
4025
4026 #ifdef Libburn_bd_r_format_olD
4027
4028 /* search for smallest 0x32 >= size */
4029 if(format_type != 0x32)
4030 continue;
4031 if (i_size < size)
4032 continue;
4033 if (format_size >= 0 && i_size >= format_size)
4034 continue;
4035 index = i;
4036 format_size = i_size;
4037 continue;
4038
4039 #else /* Libburn_bd_r_format_olD */
4040
4041 /* search largest and smallest 0x32 */
4042 if(format_type != 0x32)
4043 continue;
4044 if (i_size < min_size || min_size < 0)
4045 min_size = i_size;
4046 if (i_size > max_size)
4047 max_size = i_size;
4048
4049 #endif /* ! Libburn_bd_r_format_olD */
4050
4051 }
4052 /* common for all cases which search largest
4053 descriptors */
4054 if (i_size > format_size) {
4055 format_size = i_size;
4056 index = i;
4057 }
4058 }
4059 if (size_mode == 2 && index < 0 && !(flag & 32))
4060 index = 0;
4061 if (index < 0)
4062 goto no_suitable_formatting_type;
4063 format_type = d->format_descriptors[index].type;
4064 if (flag & (1 << 16))
4065 format_sub_type = 0; /* SRM + POW */
4066 else
4067 format_sub_type = 1; /* SRM (- POW) */
4068
4069 #ifdef Libburn_bd_r_format_olD
4070 if (0) {
4071 #else
4072 if (size_mode == 0 || size_mode == 1) {
4073 #endif /* ! Libburn_bd_r_format_olD */
4074
4075 if (min_size < 0 || max_size < 0)
4076 goto no_suitable_formatting_type;
4077 if (size <= 0)
4078 size = min_size;
4079 if (size % 0x10000)
4080 size += 0x10000 - (size % 0x10000);
4081 if (size < min_size)
4082 goto no_suitable_formatting_type;
4083 else if(size > max_size)
4084 goto no_suitable_formatting_type;
4085 num_of_blocks = size / 2048;
4086 mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4087 for (i = 0; i < 3; i++)
4088 c->page->data[9 + i] = 0;
4089 } else {
4090 num_of_blocks =
4091 d->format_descriptors[index].size / 2048;
4092 mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4093 for (i = 0; i < 3; i++)
4094 c->page->data[9 + i] =
4095 ( d->format_descriptors[index].tdp >>
4096 (16 - 8 * i)) & 0xff;
4097 }
4098 sprintf(descr, "%s", d->current_profile_text);
4099 return_immediately = 1; /* caller must do the waiting */
4100 c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
4101
4102 } else if (d->current_profile == 0x43) {
4103 /* BD-RE */
4104 index = -1;
4105 format_size = -1;
4106 if (d->num_format_descr <= 0)
4107 goto no_suitable_formatting_type;
4108 if (d->format_descriptors[0].type != 0)
4109 goto no_suitable_formatting_type;
4110 for (i = 0; i < d->num_format_descr; i++) {
4111 format_type = d->format_descriptors[i].type;
4112 i_size = d->format_descriptors[i].size;
4113 if (format_type != 0x00 && format_type != 0x30 &&
4114 format_type != 0x31)
4115 continue;
4116 if (flag & 32) { /* No defect mgt */
4117 /* search largest format 0x31 */
4118 if(format_type != 0x31)
4119 continue;
4120 } else if(size_mode == 2) { /* max payload size */
4121 /* search largest 0x30 format descriptor */
4122 if(format_type != 0x30)
4123 continue;
4124 } else if(size_mode == 3) { /* default payload size */
4125 if (accept_count < 1)
4126 index = 0; /* this cannot certify */
4127
4128 /* ts A81129
4129 LG GGW-H20L YL03 refuses on 0x30 with
4130 "Quick certification". dvd+rw-format
4131 does 0x00 by default and succeeds quickly.
4132 */
4133 if ((flag & 64) && format_type == 0x00) {
4134 index = i;
4135 break;
4136 }
4137
4138 if(format_type != 0x30)
4139 continue;
4140 accept_count++;
4141 if (accept_count == 1)
4142 index = i;
4143 continue;
4144 } else { /* defect managed format with size wish */
4145
4146 #ifdef Libburn_bd_re_format_olD
4147
4148 /* search for smallest 0x30 >= size */
4149 if(format_type != 0x30)
4150 continue;
4151 if (i_size < size)
4152 continue;
4153 if (format_size >= 0 && i_size >= format_size)
4154 continue;
4155 index = i;
4156 format_size = i_size;
4157 continue;
4158
4159 #else /* Libburn_bd_re_format_olD */
4160
4161 /* search largest and smallest 0x30 */
4162 if(format_type != 0x30)
4163 continue;
4164 if (i_size < min_size || min_size < 0)
4165 min_size = i_size;
4166 if (i_size > max_size)
4167 max_size = i_size;
4168
4169 #endif /* ! Libburn_bd_re_format_olD */
4170
4171 }
4172 /* common for all cases which search largest
4173 descriptors */
4174 if (i_size > format_size) {
4175 format_size = i_size;
4176 index = i;
4177 }
4178 }
4179
4180 if (size_mode == 2 && index < 0 && !(flag & 32))
4181 index = 0;
4182 if (index < 0)
4183 goto no_suitable_formatting_type;
4184 format_type = d->format_descriptors[index].type;
4185 if (format_type == 0x30 || format_type == 0x31) {
4186 if ((flag & 64) || !(d->current_feat23h_byte4 & 3)) {
4187 format_sub_type = 0;
4188 if (!(flag & 64))
4189 libdax_msgs_submit(libdax_messenger,
4190 d->global_index, 0x0002019e,
4191 LIBDAX_MSGS_SEV_NOTE,
4192 LIBDAX_MSGS_PRIO_HIGH,
4193 "Drive does not support media certification",
4194 0, 0);
4195 } else {
4196 /* With Certification */
4197 if (d->current_feat23h_byte4 & 1)
4198 format_sub_type = 2; /* Full */
4199 else
4200 format_sub_type = 3; /* Quick */
4201 }
4202 }
4203
4204 #ifdef Libburn_bd_re_format_olD
4205 if (0) {
4206 #else
4207 if (size_mode == 0 || size_mode == 1) {
4208 #endif /* ! Libburn_bd_re_format_olD */
4209
4210 if (min_size < 0 || max_size < 0)
4211 goto no_suitable_formatting_type;
4212 if (size <= 0)
4213 size = min_size;
4214 if (size % 0x10000)
4215 size += 0x10000 - (size % 0x10000);
4216 if (size < min_size)
4217 goto no_suitable_formatting_type;
4218 else if(size > max_size)
4219 goto no_suitable_formatting_type;
4220 num_of_blocks = size / 2048;
4221 mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4222 for (i = 0; i < 3; i++)
4223 c->page->data[9 + i] = 0;
4224 } else {
4225 num_of_blocks =
4226 d->format_descriptors[index].size / 2048;
4227 mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4228 for (i = 0; i < 3; i++)
4229 c->page->data[9 + i] =
4230 ( d->format_descriptors[index].tdp >>
4231 (16 - 8 * i)) & 0xff;
4232 }
4233 sprintf(descr, "%s", d->current_profile_text);
4234 return_immediately = 1; /* caller must do the waiting */
4235 c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
4236
4237 } else {
4238
4239 /* >>> other formattable types to come */
4240
4241 unsuitable_media:;
4242 sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s",
4243 d->current_profile, d->current_profile_text);
4244 libdax_msgs_submit(libdax_messenger, d->global_index,
4245 0x0002011e,
4246 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
4247 msg, 0, 0);
4248 {ret = 0; goto ex;}
4249 }
4250 c->page->data[8] = (format_type << 2) | (format_sub_type & 3);
4251
4252 /* MMC-5 Table 253 , column Type Dependent Parameter */
4253 if (format_type == 0x00 || format_type == 0x01 ||
4254 format_type == 0x31) {
4255 /* Block Length 0x0800 = 2k */
4256 c->page->data[ 9] = 0x00;
4257 c->page->data[10] = 0x08;
4258 c->page->data[11] = 0x00;
4259 } else if (format_type >= 0x10 && format_type <= 0x15) {
4260 /* ECC block size = 16 * 2k */
4261 c->page->data[ 9] = 0;
4262 c->page->data[10] = 0;
4263 c->page->data[11] = 16;
4264 }
4265
4266 sprintf(msg, "Format type %2.2Xh \"%s\", blocks = %.f",
4267 format_type, descr, (double) num_of_blocks);
4268 libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
4269 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4270 msg, 0, 0);
4271 sprintf(msg, "CDB: ");
4272 for (i = 0; i < 6; i++)
4273 sprintf(msg + strlen(msg), "%2.2X ", c->opcode[i]);
4274 libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
4275 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4276 msg, 0, 0);
4277 sprintf(msg, "Format list: ");
4278 for (i = 0; i < 12; i++)
4279 sprintf(msg + strlen(msg), "%2.2X ", c->page->data[i]);
4280 strcat(msg, "\n");
4281 libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
4282 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4283 msg, 0, 0);
4284
4285 #ifdef Libburn_do_not_format_dvd_ram_or_bd_rE
4286 if(d->current_profile == 0x43 || d->current_profile == 0x12) {
4287 sprintf(msg,
4288 "Formatting of %s not implemented yet - This is a dummy",
4289 d->current_profile_text);
4290 libdax_msgs_submit(libdax_messenger, d->global_index,
4291 0x00000002,
4292 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_ZERO,
4293 msg, 0, 0);
4294 {ret = 1; goto ex;}
4295 }
4296 #endif /* Libburn_do_not_format_dvd_ram_or_bd_rE */
4297
4298 /* <<<
4299 fprintf(stderr, "\nlibburn_DEBUG: FORMAT UNIT temporarily disabled.\n");
4300 ret = 1; goto ex;
4301 */
4302
4303 d->issue_command(d, c);
4304 if (c->error && !tolerate_failure) {
4305 spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
4306 if (key != 0) {
4307 sprintf(msg, "SCSI error on format_unit(%s): ", descr);
4308 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
4309 &key, &asc, &ascq);
4310 libdax_msgs_submit(libdax_messenger, d->global_index,
4311 0x00020122,
4312 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
4313 msg, 0, 0);
4314
4315 }
4316 {ret = 0; goto ex;}
4317 } else if ((!c->error) && (format_type == 0x13 || format_type == 0x15))
4318 d->needs_close_session = 1;
4319 if (return_immediately)
4320 {ret = 1; goto ex;}
4321 usleep(1000000); /* there seems to be a little race condition */
4322 for (ret = 0; ret <= 0 ;) {
4323 usleep(50000);
4324 ret = spc_test_unit_ready(d);
4325 }
4326 mmc_sync_cache(d);
4327 ret = 1;
4328 ex:;
4329 BURN_FREE_MEM(msg);
4330 BURN_FREE_MEM(c);
4331 BURN_FREE_MEM(buf);
4332 return ret;
4333 }
4334
4335
4336 /* ts B40107 : Outsourced from mmc_get_performance_al()
4337 */
4338 static int new_burn_speed_descr(struct burn_drive *d, int sd_source,
4339 struct burn_speed_descriptor **sd, int flag)
4340 {
4341 int ret;
4342
4343 ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
4344 NULL, d->mdata->speed_descriptors, 0);
4345 if (ret <= 0)
4346 return ret;
4347
4348 *sd = d->mdata->speed_descriptors;
4349 (*sd)->source = sd_source;
4350 if (d->current_profile > 0) {
4351 (*sd)->profile_loaded = d->current_profile;
4352 strcpy((*sd)->profile_name, d->current_profile_text);
4353 }
4354 return 1;
4355 }
4356
4357
4358 /* ts B40107 : Outsourced from mmc_get_performance_al()
4359 and extended for descr_type 0x00
4360 @param flag bit0= register speed descriptors
4361 */
4362 static int interpret_performance(struct burn_drive *d, struct command *c,
4363 int descr_type, int *alloc_len, int *max_descr,
4364 int *num_descr, int flag)
4365 {
4366 int len, i, b, ret, old_alloc_len;
4367 int exact_bit, read_speed, write_speed, start_speed;
4368 int min_write_speed = 0x7fffffff, max_write_speed = 0;
4369 int min_read_speed = 0x7fffffff, max_read_speed = 0;
4370 unsigned long end_lba;
4371 unsigned char *pd;
4372 struct burn_speed_descriptor *sd;
4373
4374 /* ts A61225 : 1 = report about speed descriptors */
4375 static int speed_debug = 0;
4376
4377 len = mmc_four_char_to_int(c->page->data);
4378 old_alloc_len = *alloc_len;
4379 *alloc_len = len + 4;
4380 if (len + 4 > old_alloc_len)
4381 len = old_alloc_len - 4;
4382 *num_descr = ( *alloc_len - 8 ) / 16;
4383 if (*max_descr == 0) {
4384 *max_descr = *num_descr;
4385 {ret = 1; goto ex;}
4386 }
4387 if (old_alloc_len < 16)
4388 {ret = 1; goto ex;}
4389 if (len < 12)
4390 {ret = 0; goto ex;}
4391
4392 min_write_speed = d->mdata->min_write_speed;
4393 max_write_speed = d->mdata->max_write_speed;
4394 pd = c->page->data;
4395 if (*num_descr > *max_descr)
4396 *num_descr = *max_descr;
4397 for (i = 0; i < *num_descr && (flag & 1); i++) {
4398 end_lba = read_speed = write_speed = start_speed = 0;
4399
4400 if (descr_type == 0x03) {
4401 exact_bit = !!(pd[8 + i*16] & 2);
4402 for (b = 0; b < 4 ; b++) {
4403 end_lba += ((unsigned long int)
4404 pd[8 + i*16 + 4 + b])
4405 << (24 - 8 * b);
4406 read_speed += pd[8 + i*16 + 8 + b]
4407 << (24 - 8 * b);
4408 write_speed += pd[8 + i*16 + 12 + b]
4409 << (24 - 8 * b);
4410 }
4411 if (end_lba > 0x7ffffffe)
4412 end_lba = 0x7ffffffe;
4413
4414 if (speed_debug)
4415 fprintf(stderr,
4416 "LIBBURN_DEBUG: kB/s: write=%d read=%d end=%lu exact=%d\n",
4417 write_speed, read_speed,
4418 end_lba, exact_bit);
4419
4420 ret = new_burn_speed_descr(d, 2, &sd, 0);
4421 if (ret > 0) {
4422 sd->wrc = (pd[8 + i*16] >> 3 ) & 3;
4423 sd->exact = exact_bit;
4424 sd->mrw = pd[8 + i*16] & 1;
4425 sd->end_lba = end_lba;
4426 sd->write_speed = write_speed;
4427 sd->read_speed = read_speed;
4428 }
4429
4430 } else { /* descr_type == 0 */
4431 for (b = 0; b < 4 ; b++) {
4432 start_speed += pd[8 + i*16 + 4 + b]
4433 << (24 - 8 * b);
4434 end_lba += ((unsigned long int)
4435 pd[8 + i*16 + 8 + b])
4436 << (24 - 8 * b);
4437 read_speed += pd[8 + i*16 + 12 + b]
4438 << (24 - 8 * b);
4439 }
4440
4441 if (speed_debug)
4442 fprintf(stderr,
4443 "LIBBURN_DEBUG: start=%d end=%d lba=%lu\n",
4444 start_speed, read_speed, end_lba);
4445
4446 if (end_lba > 0x7ffffffe)
4447 end_lba = 0x7ffffffe;
4448 ret = new_burn_speed_descr(d, 3, &sd, 0);
4449 if (ret > 0) {
4450 sd->end_lba = end_lba;
4451 sd->read_speed = start_speed;
4452 }
4453 if (start_speed > 0 && start_speed < min_read_speed)
4454 min_read_speed = start_speed;
4455 if (start_speed > max_read_speed)
4456 max_read_speed = start_speed;
4457 ret = new_burn_speed_descr(d, 3, &sd, 0);
4458 if (ret > 0) {
4459 sd->end_lba = end_lba;
4460 sd->read_speed = read_speed;
4461 }
4462 }
4463
4464 if ((int) end_lba > d->mdata->max_end_lba)
4465 d->mdata->max_end_lba = end_lba;
4466 if ((int) end_lba < d->mdata->min_end_lba)
4467 d->mdata->min_end_lba = end_lba;
4468 if (write_speed > 0 && write_speed < min_write_speed)
4469 min_write_speed = write_speed;
4470 if (write_speed > max_write_speed)
4471 max_write_speed = write_speed;
4472 if (read_speed > 0 && read_speed < min_read_speed)
4473 min_read_speed = read_speed;
4474 if (read_speed > max_read_speed)
4475 max_read_speed = read_speed;
4476 }
4477 if (min_write_speed < 0x7fffffff)
4478 d->mdata->min_write_speed = min_write_speed;
4479 if (max_write_speed > 0)
4480 d->mdata->max_write_speed = max_write_speed;
4481 /* there is no mdata->min_read_speed yet
4482 if (min_read_speed < 0x7fffffff)
4483 d->mdata->min_read_speed = min_read_speed;
4484 */
4485 if (max_read_speed > 0)
4486 d->mdata->max_read_speed = max_read_speed;
4487
4488 ret = 1;
4489 ex:;
4490 return ret;
4491 }
4492
4493
4494 /* ts A61225 */
4495 /* @param flag bit0= register speed descriptors
4496 */
4497 static int mmc_get_performance_al(struct burn_drive *d, int descr_type,
4498 int *alloc_len, int *max_descr, int flag)
4499 {
4500 int num_descr, ret;
4501 struct buffer *buf = NULL;
4502 struct command *c = NULL;
4503
4504 BURN_ALLOC_MEM(buf, struct buffer, 1);
4505 BURN_ALLOC_MEM(c, struct command, 1);
4506
4507 if (d->current_profile < 0)
4508 mmc_get_configuration(d);
4509
4510 if (*alloc_len < 8)
4511 {ret = 0; goto ex;}
4512 if (descr_type != 0x00 && descr_type != 0x03)
4513 {ret = 0; goto ex;}
4514
4515 scsi_init_command(c, MMC_GET_PERFORMANCE,
4516 sizeof(MMC_GET_PERFORMANCE));
4517
4518 /* >>> future: maintain a list of write descriptors
4519 if (max_descr > d->max_write_descr - d->num_write_descr)
4520 max_descr = d->max_write_descr;
4521 */
4522 c->dxfer_len = *alloc_len;
4523
4524 if (descr_type == 0x00)
4525 c->opcode[1] = 0x10; /* Data Type: nominal read performance */
4526 c->opcode[8] = ( *max_descr >> 8 ) & 0xff;
4527 c->opcode[9] = ( *max_descr >> 0 ) & 0xff;
4528 c->opcode[10] = descr_type;
4529 c->retry = 1;
4530 c->page = buf;
4531 c->page->sectors = 0;
4532 c->page->bytes = 0;
4533 c->dir = FROM_DRIVE;
4534 d->issue_command(d, c);
4535
4536 #ifdef Libisofs_simulate_old_mmc1_drivE
4537 c->error = 1;
4538 c->sense[0] = 0x70; /* Fixed format sense data */
4539 c->sense[2] = 0x5;
4540 c->sense[12] = 0x20;
4541 c->sense[13] = 0x0;
4542 #endif /* Libisofs_simulate_old_mmc1_drivE */
4543
4544 if (c->error)
4545 {ret = 0; goto ex;}
4546
4547 ret = interpret_performance(d, c, descr_type, alloc_len, max_descr,
4548 &num_descr, flag);
4549 if (ret <= 0)
4550 goto ex;
4551
4552 ret = num_descr;
4553 ex:;
4554 BURN_FREE_MEM(buf);
4555 BURN_FREE_MEM(c);
4556 return ret;
4557 }
4558
4559
4560 int mmc_get_performance(struct burn_drive *d, int descr_type, int flag)
4561 {
4562 int alloc_len = 8, max_descr = 0, ret;
4563
4564 mmc_start_if_needed(d, 1);
4565 if (mmc_function_spy(d, "mmc_get_write_performance") <= 0)
4566 return 0;
4567
4568 /* first command execution to learn number of descriptors and
4569 dxfer_len
4570 */
4571 ret = mmc_get_performance_al(d, descr_type, &alloc_len, &max_descr, 0);
4572 if (max_descr > 0 && ret > 0) {
4573 /* Some drives announce only 1 descriptor if asked for 0.
4574 So ask twice for non-0 descriptors.
4575 */
4576 ret = mmc_get_performance_al(d, descr_type,
4577 &alloc_len, &max_descr, 0);
4578 }
4579 /*
4580 fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n",
4581 alloc_len, ret);
4582 */
4583 if (max_descr > 0 && ret > 0) {
4584 /* final execution with announced length */
4585 max_descr = (alloc_len - 8) / 16;
4586 ret = mmc_get_performance_al(d, descr_type,
4587 &alloc_len, &max_descr, 1);
4588 }
4589 return ret;
4590 }
4591
4592
4593 int mmc_get_write_performance(struct burn_drive *d)
4594 {
4595 int ret;
4596
4597 ret = mmc_get_performance(d, 0x03, 0);
4598 return ret;
4599 }
4600
4601
4602 /* ts A61229 : outsourced from spc_select_write_params() */
4603 /* Note: Page data is not zeroed here in order not to overwrite preset
4604 defaults. Thus
4605 memset(pd, 0, 2 + d->mdata->write_page_length);
4606 is the eventual duty of the caller.
4607 */
4608 int mmc_compose_mode_page_5(struct burn_drive *d, struct burn_session *s,
4609 int tnum, const struct burn_write_opts *o,
4610 unsigned char *pd)
4611 {
4612 unsigned char *catalog = NULL;
4613 char isrc_text[13 + 21]; /* should suffice for 64 bit oversize */
4614 struct isrc *isrc;
4615
4616 pd[0] = 5;
4617 pd[1] = d->mdata->write_page_length;
4618
4619 if (d->current_profile == 0x13) {
4620 /* A61229 : DVD-RW restricted overwrite */
4621 /* learned from transport.hxx : page05_setup()
4622 and mmc3r10g.pdf table 347 */
4623 /* BUFE (burnproof), no LS_V (i.e. default Link Size, i hope),
4624 no simulate, write type 0 = packet */
4625 pd[2] = (1 << 6);
4626 /* no multi, fixed packet, track mode 5 */
4627 pd[3] = (1 << 5) | 5;
4628 /* Data Block Type */
4629 pd[4] = 8;
4630 /* Link size dummy */
4631 pd[5] = 0;
4632 } else if ((d->current_profile == 0x14 || d->current_profile == 0x11 ||
4633 d->current_profile == 0x15)
4634 && o->write_type == BURN_WRITE_SAO) {
4635 /* ts A70205 : DVD-R[W][/DL] : Disc-at-once, DAO */
4636 /* Learned from dvd+rw-tools and mmc5r03c.pdf .
4637 See doc/cookbook.txt for more detailed references. */
4638
4639 /* BUFE , LS_V = 0, Test Write, Write Type = 2 SAO (DAO) */
4640 pd[2] = ((!!o->underrun_proof) << 6)
4641 | ((!!o->simulate) << 4)
4642 | 2;
4643
4644 /* No multi-session , FP = 0 , Copy = 0, Track Mode = 5 */
4645 pd[3] = 5;
4646
4647 #ifdef Libburn_pioneer_dvr_216d_load_mode5
4648
4649 /* >>> use track mode from mmc_get_nwa() */
4650 /* >>> pd[3] = (pd[3] & ~0xf) | (d->track_inf[5] & 0xf); */
4651
4652 #endif
4653
4654 /* Data Block Type = 8 */
4655 pd[4] = 8;
4656
4657 } else if (d->current_profile == 0x14 || d->current_profile == 0x11 ||
4658 d->current_profile == 0x15) {
4659 /* ts A70128 : DVD-R[W][/DL] Incremental Streaming */
4660 /* Learned from transport.hxx : page05_setup()
4661 and mmc5r03c.pdf 7.5, 4.2.3.4 Table 17
4662 and spc3r23.pdf 6.8, 7.4.3 */
4663
4664 /* BUFE , LS_V = 1, Test Write,
4665 Write Type = 0 Packet/Incremental */
4666 pd[2] = ((!!o->underrun_proof) << 6)
4667 | (1 << 5)
4668 | ((!!o->simulate) << 4);
4669 /* Multi-session , FP = 1 , Track Mode = 5 */
4670 pd[3] = ((3 * !!o->multi) << 6) | (1 << 5) | 5;
4671 /* Data Block Type = 8 */
4672 pd[4] = 8;
4673 /* Link Size */
4674 if (d->current_feat21h_link_size >= 0)
4675 pd[5] = d->current_feat21h_link_size;
4676 else
4677 pd[5] = 16;
4678 if (d->current_feat21h_link_size != 16) {
4679 char msg[80];
4680
4681 sprintf(msg,
4682 "Feature 21h Link Size = %d (expected 16)\n",
4683 d->current_feat21h_link_size);
4684 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
4685 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4686 msg, 0, 0);
4687 }
4688 /* Packet Size */
4689 pd[13] = 16;
4690
4691 } else if (d->current_profile == 0x1a || d->current_profile == 0x1b ||
4692 d->current_profile == 0x2b || d->current_profile == 0x12 ||
4693 d->current_profile == 0x41 || d->current_profile == 0x42 ||
4694 d->current_profile == 0x43) {
4695 /* not with DVD+R[W][/DL] or DVD-RAM or BD-R[E] */;
4696 return 0;
4697 } else {
4698 /* Traditional setup for CD */
4699
4700 pd[2] = ((!!o->underrun_proof) << 6)
4701 | ((!!o->simulate) << 4)
4702 | (o->write_type & 0x0f);
4703
4704 /* ts A61106 : MMC-1 table 110 : multi==0 or multi==3 */
4705 pd[3] = ((3 * !!o->multi) << 6) | (o->control & 0x0f);
4706
4707 pd[4] = spc_block_type(o->block_type);
4708
4709 /*
4710 fprintf(stderr, "libburn_EXPERIMENTAL: block_type = %d, pd[4]= %u\n",
4711 o->block_type, (unsigned int) pd[4]);
4712 */
4713
4714 /* ts A61104 */
4715 if(!(o->control&4)) /* audio (MMC-1 table 61) */
4716 if(o->write_type == BURN_WRITE_TAO)
4717 pd[4] = 0; /* Data Block Type: Raw Data */
4718
4719 pd[14] = 0; /* audio pause length MSB */
4720 pd[15] = 150; /* audio pause length LSB */
4721
4722 /*XXX need session format! */
4723 /* ts A61229 : but session format (pd[8]) = 0 seems ok */
4724
4725 /* Media Catalog Number at byte 16 to 31,
4726 MMC-5, 7.5, Tables 664, 670
4727 */
4728 if (o->has_mediacatalog)
4729 catalog = (unsigned char *) o->mediacatalog;
4730 else if (s != NULL) {
4731 if (s->mediacatalog[0])
4732 catalog = s->mediacatalog;
4733 }
4734 if (catalog != NULL && d->mdata->write_page_length >= 30) {
4735 pd[16] = 0x80; /* MCVAL */
4736 memcpy(pd + 17, catalog, 13);
4737 }
4738
4739 /* ISRC at bytes 32 to 47. Tables 664, 671 */
4740 /* SCMS at byte 3 bit 4 */
4741 isrc_text[0] = 0;
4742 if (s != NULL && o->write_type == BURN_WRITE_TAO) {
4743 if (tnum >= 0 && tnum < s->tracks) {
4744 if (s->track[tnum]->isrc.has_isrc) {
4745 isrc = &(s->track[tnum]->isrc);
4746 isrc_text[0] = isrc->country[0];
4747 isrc_text[1] = isrc->country[1];
4748 isrc_text[2] = isrc->owner[0];
4749 isrc_text[3] = isrc->owner[1];
4750 isrc_text[4] = isrc->owner[2];
4751 sprintf(isrc_text + 5, "%-2.2u",
4752 (unsigned int) isrc->year);
4753 sprintf(isrc_text + 7, "%-5.5u",
4754 isrc->serial);
4755 isrc_text[12]= 0;
4756 }
4757 if ((s->track[tnum]->mode & BURN_SCMS) &&
4758 !(s->track[tnum]->mode & BURN_COPY))
4759 pd[3] |= 0x10;
4760 }
4761 }
4762 if (isrc_text[0] != 0 && d->mdata->write_page_length >= 46) {
4763 pd[32] = 0x80; /* TCVAL */
4764 memcpy(pd + 33, isrc_text, 12);
4765 }
4766 }
4767 return 1;
4768 }
4769
4770
4771 /* A70812 ts */
4772 int mmc_read_10(struct burn_drive *d, int start,int amount, struct buffer *buf)
4773 {
4774 struct command *c;
4775 char *msg = NULL;
4776 int key, asc, ascq, silent;
4777
4778 c = &(d->casual_command);
4779 mmc_start_if_needed(d, 0);
4780 if (mmc_function_spy(d, "mmc_read_10") <= 0)
4781 return -1;
4782
4783 if (amount > BUFFER_SIZE / 2048)
4784 return -1;
4785
4786 scsi_init_command(c, MMC_READ_10, sizeof(MMC_READ_10));
4787 c->dxfer_len = amount * 2048;
4788 c->retry = 1;
4789 mmc_int_to_four_char(c->opcode + 2, start);
4790 c->opcode[7] = (amount >> 8) & 0xFF;
4791 c->opcode[8] = amount & 0xFF;
4792 c->page = buf;
4793 c->page->bytes = 0;
4794 c->page->sectors = 0;
4795 c->dir = FROM_DRIVE;
4796 d->issue_command(d, c);
4797
4798 /* <<< replace by mmc_eval_read_error */;
4799 if (c->error) {
4800 msg = calloc(1, 256);
4801 if (msg != NULL) {
4802 sprintf(msg,
4803 "SCSI error on read_10(%d,%d): ", start, amount);
4804 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
4805 &key, &asc, &ascq);
4806 silent = (d->silent_on_scsi_error == 1);
4807 if (key == 5 && asc == 0x64 && ascq == 0x0) {
4808 d->had_particular_error |= 1;
4809 if (d->silent_on_scsi_error == 2)
4810 silent = 1;
4811 }
4812 if(!silent)
4813 libdax_msgs_submit(libdax_messenger,
4814 d->global_index,
4815 0x00020144,
4816 (d->silent_on_scsi_error == 3) ?
4817 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
4818 LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
4819 free(msg);
4820 }
4821 return BE_CANCELLED;
4822 }
4823
4824 buf->sectors = amount;
4825 buf->bytes = amount * 2048;
4826 return 0;
4827 }
4828
4829
4830 #ifdef Libburn_develop_quality_scaN
4831
4832 /* B21108 ts : Vendor specific command REPORT ERROR RATE, see
4833 http://liggydee.cdfreaks.com/ddl/errorcheck.pdf
4834 */
4835 int mmc_nec_optiarc_f3(struct burn_drive *d, int sub_op,
4836 int start_lba, int rate_period,
4837 int *ret_lba, int *error_rate1, int *error_rate2)
4838 {
4839 struct buffer *buf = NULL;
4840 struct command *c;
4841 char *msg = NULL;
4842 int key, asc, ascq, ret;
4843 static unsigned char MMC_NEC_OPTIARC_F3[] =
4844 { 0xF3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4845
4846 BURN_ALLOC_MEM(buf, struct buffer, 1);
4847 BURN_ALLOC_MEM(c, struct command, 1);
4848 mmc_start_if_needed(d, 0);
4849 if (mmc_function_spy(d, "mmc_nec_optiarc_f3") <= 0)
4850 return -1;
4851
4852 scsi_init_command(c, MMC_NEC_OPTIARC_F3, sizeof(MMC_NEC_OPTIARC_F3));
4853 if (sub_op == 3) {
4854 c->dxfer_len = 8;
4855 c->dir = FROM_DRIVE;
4856 } else {
4857 c->dxfer_len = 0;
4858 c->dir = NO_TRANSFER;
4859 }
4860 c->retry = 0;
4861 c->opcode[1] = sub_op;
4862 mmc_int_to_four_char(c->opcode + 2, start_lba);
4863 c->opcode[8] = rate_period;
4864 c->page = buf;
4865 c->page->bytes = 0;
4866 c->page->sectors = 0;
4867 d->issue_command(d, c);
4868 if (c->error) {
4869 msg = calloc(1, 256);
4870 if (msg != NULL) {
4871 sprintf(msg,
4872 "SCSI error on nec_optiarc_f3(%d, %d, %d): ",
4873 sub_op, start_lba, rate_period);
4874 scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
4875 &key, &asc, &ascq);
4876 libdax_msgs_submit(libdax_messenger,
4877 d->global_index, 0x00020144,
4878 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
4879 msg, 0, 0);
4880 free(msg);
4881 }
4882 return BE_CANCELLED;
4883 }
4884
4885 if (sub_op == 3) {
4886 *ret_lba = mmc_four_char_to_int(c->page->data);
4887 *error_rate1 = c->page->data[4] * 256 + c->page->data[5];
4888 *error_rate2 = c->page->data[6] * 256 + c->page->data[7];
4889 }
4890
4891 ret = 1;
4892 ex:;
4893 BURN_FREE_MEM(c);
4894 BURN_FREE_MEM(buf);
4895 return ret;
4896 }
4897
4898 #endif /* Libburn_develop_quality_scaN */
4899
4900
4901 /* ts A81210 : Determine the upper limit of readable data size */
4902 int mmc_read_capacity(struct burn_drive *d)
4903 {
4904 struct buffer *buf = NULL;
4905 struct command *c = NULL;
4906 int alloc_len= 8, ret;
4907
4908 BURN_ALLOC_MEM(buf, struct buffer, 1);
4909 BURN_ALLOC_MEM(c, struct command, 1);
4910 d->media_read_capacity = 0x7fffffff;
4911 d->mr_capacity_trusted = -1;
4912 mmc_start_if_needed(d, 1);
4913 if (mmc_function_spy(d, "mmc_read_capacity") <= 0)
4914 {ret = 0; goto ex;}
4915
4916 scsi_init_command(c, MMC_READ_CAPACITY, sizeof(MMC_READ_CAPACITY));
4917 c->dxfer_len = alloc_len;
4918 c->retry = 1;
4919 c->page = buf;
4920 c->page->bytes = 0;
4921 c->page->sectors = 0;
4922 c->dir = FROM_DRIVE;
4923 d->issue_command(d, c);
4924 d->media_read_capacity = mmc_four_char_to_int(c->page->data);
4925 if (d->media_read_capacity < 0) {
4926 d->media_read_capacity = 0x7fffffff;
4927 {ret = 0; goto ex;}
4928 }
4929 if (d->current_profile >= 0x08 && d->current_profile <= 0x0A)
4930 d->mr_capacity_trusted = 0;
4931 else
4932 d->mr_capacity_trusted = 1;
4933 ret = 1;
4934 ex:;
4935 BURN_FREE_MEM(c);
4936 BURN_FREE_MEM(buf);
4937 return ret;
4938 }
4939
4940
4941 /* ts A90903 */
4942 /* mmc5r03c.pdf 6.23 ADh READ DISC STRUCTURE obtains media specific information
4943 */
4944 static int mmc_read_disc_structure_al(struct burn_drive *d, int *alloc_len,
4945 int media_type, int layer_number, int format,
4946 int min_len, char **reply, int *reply_len,
4947 int flag)
4948 {
4949 struct buffer *buf = NULL;
4950 int old_alloc_len, len, ret;
4951 struct command *c = NULL;
4952 unsigned char *dpt;
4953
4954 BURN_ALLOC_MEM(buf, struct buffer, 1);
4955 BURN_ALLOC_MEM(c, struct command, 1);
4956 *reply = NULL;
4957 *reply_len = 0;
4958
4959 if (*alloc_len < 4)
4960 {ret = 0; goto ex;}
4961
4962 scsi_init_command(c, MMC_READ_DISC_STRUCTURE,
4963 sizeof(MMC_READ_DISC_STRUCTURE));
4964 c->dxfer_len = *alloc_len;
4965 c->retry = 1;
4966 c->opcode[1]= media_type;
4967 c->opcode[7]= format;
4968 c->opcode[8]= (c->dxfer_len >> 8) & 0xff;
4969 c->opcode[9]= c->dxfer_len & 0xff;
4970 c->page = buf;
4971 c->page->sectors = 0;
4972 c->page->bytes = 0;
4973 c->dir = FROM_DRIVE;
4974
4975 d->issue_command(d, c);
4976 if (c->error)
4977 {ret = 0; goto ex;}
4978
4979 len = (c->page->data[0] << 8) | (c->page->data[1]);
4980 old_alloc_len = *alloc_len;
4981 *alloc_len = len + 2;
4982 if (old_alloc_len <= 4)
4983 {ret = 1; goto ex;}
4984 if (len + 2 > old_alloc_len)
4985 len = old_alloc_len - 2;
4986 if (len < 4)
4987 {ret = 0; goto ex;}
4988
4989 dpt = c->page->data + 4;
4990 if (len - 2 < min_len)
4991 {ret = 0; goto ex;}
4992 *reply = calloc(len - 2, 1);
4993 if (*reply == NULL)
4994 {ret = 0; goto ex;}
4995 *reply_len = len - 2;
4996 memcpy(*reply, dpt, len - 2);
4997 ret = 1;
4998 ex:;
4999 BURN_FREE_MEM(c);
5000 BURN_FREE_MEM(buf);
5001 return ret;
5002 }
5003
5004
5005 int mmc_read_disc_structure(struct burn_drive *d,
5006 int media_type, int layer_number, int format, int min_len,
5007 char **reply, int *reply_len, int flag)
5008 {
5009 int alloc_len = 4, ret;
5010 char msg[80];
5011
5012 mmc_start_if_needed(d, 1);
5013 if (mmc_function_spy(d, "mmc_read_disc_structure") <= 0)
5014 return 0;
5015
5016 ret = mmc_read_disc_structure_al(d, &alloc_len,
5017 media_type, layer_number, format, min_len,
5018 reply, reply_len, 0);
5019 /*
5020 fprintf(stderr,"LIBBURN_DEBUG: ADh alloc_len = %d , ret = %d\n",
5021 alloc_len, ret);
5022 */
5023 if (ret <= 0)
5024 return ret;
5025 if (alloc_len < 12) {
5026 sprintf(msg,
5027 "READ DISC STRUCTURE announces only %d bytes of reply\n",
5028 alloc_len);
5029 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
5030 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
5031 msg, 0, 0);
5032 ret = 0;
5033
5034 /* ts A91205
5035 LG GH22LS30 revision 1.00 returns for DVD-R format
5036 code 0x0E an allocation length of 4 (= 0 payload).
5037 A MS-Windows tool can inquire media code "RITEKF1",
5038 though.
5039 This macro causes a try to unconditionally read the
5040 desired payload bytes. The drive then returns 35
5041 bytes as requested and the media id is "RITEKF1".
5042 Nevertheless this is not a generally usable gesture
5043 because older GNU/Linux USB dislikes requests to fetch
5044 more bytes than the drive will deliver.
5045
5046 # define Libburn_enforce_structure_code_0x0E 1
5047 */
5048
5049 #ifdef Libburn_enforce_structure_code_0x0E
5050 if (format == 0x0E) {
5051 alloc_len = min_len + 4;
5052 ret = mmc_read_disc_structure_al(d, &alloc_len,
5053 media_type, layer_number, format, min_len,
5054 reply, reply_len, 0);
5055 if (*reply_len < min_len || *reply == NULL)
5056 ret = 0;
5057 sprintf(msg, "READ DISC STRUCTURE returns %d bytes of required %d\n",
5058 *reply_len + 4, min_len + 4);
5059 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
5060 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
5061 msg, 0, 0);
5062 }
5063 #endif
5064
5065 } else
5066 ret = mmc_read_disc_structure_al(d, &alloc_len,
5067 media_type, layer_number, format, min_len,
5068 reply, reply_len, 0);
5069 return ret;
5070 }
5071
5072 /* ts A90903 */
5073 /*
5074 @param flag bit0= set bit1 in flag for burn_util_make_printable_word
5075 and do not append media revision
5076 bit1= truncate media_code1 to 6 characters (else 8)
5077 */
5078 static int mmc_set_product_id(char *reply,
5079 int manuf_idx, int type_idx, int rev_idx,
5080 char **product_id, char **media_code1, char **media_code2, int flag)
5081 {
5082 int ret;
5083
5084 *product_id = calloc(17, 1);
5085 *media_code1 = calloc(9, 1);
5086 *media_code2 = calloc(8, 1);
5087 if (*product_id == NULL ||
5088 *media_code1 == NULL || *media_code2 == NULL)
5089 return -1;
5090 if (flag & 2)
5091 sprintf(*media_code1, "%.6s", reply + manuf_idx);
5092 else
5093 sprintf(*media_code1, "%.8s", reply + manuf_idx);
5094 ret = burn_util_make_printable_word(media_code1,
5095 1 | ((flag & 1) << 1));
5096 if (ret <= 0)
5097 return -1;
5098 sprintf(*media_code2, "%.3s%s", reply + type_idx,
5099 (flag & 1) ? "" : "xxxx");
5100 ret = burn_util_make_printable_word(media_code2,
5101 1 | ((flag & 1) << 1));
5102 if (ret <= 0)
5103 return -1;
5104 if (!(flag & 1)) {
5105 sprintf(*media_code2 + strlen(*media_code2) - 4, "/%d",
5106 (int) ((unsigned char *) reply)[rev_idx]);
5107 }
5108 sprintf(*product_id, "%s/%s", *media_code1, *media_code2);
5109 return 1;
5110 }
5111
5112
5113 /* ts A90903 */
5114 /* MMC backend of API call burn_disc_get_media_id()
5115 See also doc/mediainfo.txt
5116 @param flag Bitfield for control purposes
5117 bit0= do not escape " _/" (not suitable for
5118 burn_guess_manufacturer())
5119
5120 */
5121 int mmc_get_media_product_id(struct burn_drive *d,
5122 char **product_id, char **media_code1, char **media_code2,
5123 char **book_type, int flag)
5124 {
5125 int prf, ret, reply_len, i, has_11h = -1, bt, start_lba, end_lba;
5126 int min, sec, fr, media_type = 0;
5127 char *reply = NULL, *wpt;
5128
5129 static char *books[16] = {
5130 "DVD-ROM", "DVD-RAM", "DVD-R", "DVD-RW",
5131 "HD DVD-ROM", "HD DVD-RAM", "HD DVD-R", "unknown",
5132 "unknown", "DVD+RW", "DVD+R", "unknown",
5133 "unknown", "DVD+RW DL", "DVD+R DL", "unknown"};
5134
5135 *product_id = *media_code1 = *media_code2 = *book_type = NULL;
5136 prf = d->current_profile;
5137 if (prf == 0x09 || prf == 0x0A) {
5138
5139 *product_id = calloc(20, 1);
5140 *media_code1 = calloc(10, 1);
5141 *media_code2 = calloc(10, 1);
5142 if (*product_id == NULL ||
5143 *media_code1 == NULL || *media_code2 == NULL) {
5144 ret = -1;
5145 goto ex;
5146 }
5147 ret = burn_disc_read_atip(d);
5148 if (ret <= 0)
5149 goto ex;
5150 ret = burn_drive_get_start_end_lba(d, &start_lba, &end_lba, 0);
5151 if (ret <= 0)
5152 goto ex;
5153 burn_lba_to_msf(start_lba, &min, &sec, &fr);
5154 sprintf(*media_code1, "%2.2dm%2.2ds%2.2df", min, sec, fr);
5155 burn_lba_to_msf(end_lba, &min, &sec, &fr);
5156 sprintf(*media_code2, "%2.2dm%2.2ds%2.2df", min, sec, fr);
5157 sprintf(*product_id, "%s/%s", *media_code1, *media_code2);
5158 ret = 1;
5159 goto ex; /* No booktype with CD media */
5160
5161 } else if (prf == 0x11 || prf == 0x13 || prf == 0x14 || prf == 0x15) {
5162 /* DVD-R */
5163
5164 ret = mmc_read_disc_structure(d, 0, 0, 0x0E, 31, &reply,
5165 &reply_len, 0);
5166 if (ret <= 0)
5167 goto ex;
5168 /* ECMA-279 for DVD-R promises a third sixpack in field 5,
5169 but ECMA-338 for DVD-RW defines a different meaning.
5170 DVD-R and DVD-RW bear unprintable characters in there.
5171 */
5172 if (reply[16] != 3 || reply[24] != 4) {
5173 ret = 0;
5174 goto ex;
5175 }
5176 *media_code1 = calloc(19, 1);
5177 *media_code2 = strdup("");
5178 if (*media_code1 == NULL || *media_code2 == NULL) {
5179 ret = -1;
5180 goto ex;
5181 }
5182 memcpy(*media_code1, reply + 17, 6);
5183 memcpy(*media_code1 + 6, reply + 25, 6);
5184
5185 /* Clean out 0 bytes */
5186 wpt = *media_code1;
5187 for (i = 0; i < 18; i++)
5188 if ((*media_code1)[i])
5189 *(wpt++) = (*media_code1)[i];
5190 *wpt = 0;
5191 ret = burn_util_make_printable_word(media_code1,
5192 1 | ((flag & 1) << 1));
5193 if (ret <= 0)
5194 goto ex;
5195 *product_id = strdup(*media_code1);
5196 if (*product_id == NULL) {
5197 ret = -1;
5198 goto ex;
5199 }
5200
5201 } else if (prf == 0x1a || prf == 0x1b || prf == 0x2b) { /* DVD+R[W] */
5202
5203 /* Check whether the drive supports format 11h */
5204 has_11h = 0;
5205 ret = mmc_read_disc_structure(d, 0, 0, 0xff, 4, &reply,
5206 &reply_len, 0);
5207 if (ret > 0) {
5208 for (i = 0; i < reply_len; i += 4) {
5209 if (reply[i] == 0x11 && (reply[i + 1] & 64))
5210 has_11h = 1;
5211 }
5212 }
5213 if (reply != NULL)
5214 free(reply);
5215 reply = NULL;
5216 ret = mmc_read_disc_structure(d, 0, 0, 0x11, 29, &reply,
5217 &reply_len, 0);
5218 if (ret <= 0) {
5219 /* Hope for format 00h */
5220 has_11h = 0;
5221 } else {
5222 /* Dig out manufacturer, media type and revision */
5223 ret = mmc_set_product_id(reply, 19, 27, 28,
5224 product_id, media_code1, media_code2,
5225 flag & 1);
5226 if (ret <= 0)
5227 goto ex;
5228 }
5229 } else if (prf == 0x41 || prf == 0x43 || prf == 0x40 || prf == 0x42) {
5230 /* BD */
5231 media_type = 1;
5232 ret = mmc_read_disc_structure(d, 1, 0, 0x00, 112, &reply,
5233 &reply_len, 0);
5234 if (ret <= 0)
5235 goto ex;
5236 if (reply[0] != 'D' || reply[1] != 'I') {
5237 ret = 0;
5238 goto ex;
5239 }
5240 /* Dig out manufacturer, media type and revision */
5241 ret = mmc_set_product_id(reply, 100, 106, 111,
5242 product_id, media_code1, media_code2,
5243 2 | (flag & 1));
5244 if (ret <= 0)
5245 goto ex;
5246
5247 } else {
5248
5249 /* Source of DVD-RAM manufacturer and media id not found yet */
5250 ret = 0;
5251 goto ex;
5252 }
5253
5254 if (reply != NULL)
5255 free(reply);
5256 reply = NULL;
5257 ret = mmc_read_disc_structure(d, media_type, 0, 0x00, 1,
5258 &reply, &reply_len, 0);
5259 if (ret <= 0)
5260 goto ex;
5261 bt = (reply[0] >> 4) & 0xf;
5262 *book_type = calloc(80 + strlen(books[bt]), 1);
5263 if (*book_type == NULL) {
5264 ret = -1;
5265 goto ex;
5266 }
5267 sprintf(*book_type, "%2.2Xh, %s book [revision %d]",
5268 bt, books[bt], reply[0] & 0xf);
5269
5270 if (has_11h == 0 && *product_id == NULL && reply_len > 28) {
5271 /* DVD+ with no format 11h */
5272 /* Get manufacturer and media type from bytes 19 and 27 */
5273 ret = mmc_set_product_id(reply, 19, 27, 28, product_id,
5274 media_code1, media_code2,
5275 flag & 1);
5276 if (*product_id == NULL) {
5277 ret = 0;
5278 goto ex;
5279 }
5280 }
5281
5282 ret = 1;
5283 ex:;
5284 if (reply != NULL)
5285 free(reply);
5286 if (ret <= 0) {
5287 if (*product_id != NULL)
5288 free(*product_id);
5289 if (*media_code1 != NULL)
5290 free(*media_code1);
5291 if (*media_code2 != NULL)
5292 free(*media_code2);
5293 if (*book_type != NULL)
5294 free(*book_type);
5295 *product_id = *media_code1 = *media_code2 = *book_type = NULL;
5296 }
5297 return ret;
5298 }
5299
5300
5301 /* ts B00924
5302 MMC-5, 6.23.3.3.4 Format Code 0Ah: Spare Area Information
5303 */
5304 int mmc_get_bd_spare_info(struct burn_drive *d,
5305 int *alloc_blocks, int *free_blocks, int flag)
5306 {
5307 int ret, reply_len, prf;
5308 char *reply = NULL;
5309
5310 prf = d->current_profile;
5311 if (!(prf == 0x41 || prf == 0x43 || prf == 0x42))
5312 return 0; /* Not a BD loaded */
5313
5314 ret = mmc_read_disc_structure(d, 1, 0, 0x0a, 12, &reply,
5315 &reply_len, 0);
5316 if (ret <= 0)
5317 goto ex;
5318 *alloc_blocks = mmc_four_char_to_int((unsigned char *) reply + 8);
5319 *free_blocks = mmc_four_char_to_int((unsigned char *) reply + 4);
5320 ret = 1;
5321 ex:;
5322 if (reply != NULL)
5323 free(reply);
5324 return ret;
5325 }
5326
5327
5328 /* ts B10801
5329 MMC-5, 6.23.3.2.1 Format Code 00h: Physical Format Information
5330 6.23.3.2.16 Format Code 10h: Format Information of
5331 Control Data Zone in the Lead-in
5332 disk_category
5333 */
5334 int mmc_get_phys_format_info(struct burn_drive *d, int *disk_category,
5335 char **book_name, int *part_version, int *num_layers,
5336 int *num_blocks, int flag)
5337 {
5338 int ret, reply_len, prf;
5339 char *reply = NULL;
5340 static char book_names[][16] = {
5341 "DVD-ROM", "DVD-RAM", "DVD-R", "DVD-RW",
5342 "HD DVD-ROM", "HD DVD-RAM", "HD DVD-R", "unknown",
5343 "unknown", "DVD+RW", "DVD+R", "unknown", "unknown",
5344 "unknown", "DVD+RW DL", "DVD+R DL", "unknown"
5345 };
5346
5347 prf = d->current_profile;
5348 if (!(prf == 0x11 || prf == 0x13 || prf == 0x14 || prf == 0x15 ||
5349 prf == 0x51))
5350 return 0; /* Not a [HD] DVD-R[W] loaded */
5351 ret = mmc_read_disc_structure(d, 0, 0, 0x10, 12, &reply,
5352 &reply_len, 0);
5353 if (ret <= 0)
5354 goto ex;
5355 if(reply_len < 12) {
5356 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
5357 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
5358 "READ DISC STRUCTURE format 10h: Less than 12 bytes",
5359 0, 0);
5360 {ret = 0; goto ex;}
5361 }
5362 *disk_category = (reply[0] >> 4) & 0xf;
5363 *book_name = book_names[*disk_category];
5364 *part_version = reply[0] & 0xf;
5365 *num_layers = ((reply[2] >> 5) & 0x3) + 1;
5366 *num_blocks = ((reply[9] << 16) | (reply[10] << 8) | reply[11]) -
5367 ((reply[5] << 16) | (reply[6] << 8) | reply[7]) + 1;
5368 ret = 1;
5369 ex:;
5370 if (reply != NULL)
5371 free(reply);
5372 return ret;
5373 }
5374
5375
5376 /* ts A61021 : the mmc specific part of sg.c:enumerate_common()
5377 */
5378 int mmc_setup_drive(struct burn_drive *d)
5379 {
5380 d->read_atip = mmc_read_atip;
5381 d->read_toc = mmc_read_toc;
5382 d->write = mmc_write;
5383 d->erase = mmc_erase;
5384 d->read_cd = mmc_read_cd;
5385 d->perform_opc = mmc_perform_opc;
5386 d->set_speed = mmc_set_speed;
5387 d->send_cue_sheet = mmc_send_cue_sheet;
5388 d->reserve_track = mmc_reserve_track;
5389 d->sync_cache = mmc_sync_cache;
5390 d->get_nwa = mmc_get_nwa;
5391 d->read_multi_session_c1 = mmc_read_multi_session_c1;
5392 d->close_disc = mmc_close_disc;
5393 d->close_session = mmc_close_session;
5394 d->close_track_session = mmc_close;
5395 d->read_buffer_capacity = mmc_read_buffer_capacity;
5396 d->format_unit = mmc_format_unit;
5397 d->read_format_capacities = mmc_read_format_capacities;
5398 d->read_10 = mmc_read_10;
5399
5400
5401 /* ts A70302 */
5402 d->phys_if_std = -1;
5403 d->phys_if_name[0] = 0;
5404
5405 /* ts A61020 */
5406 d->start_lba = -2000000000;
5407 d->end_lba = -2000000000;
5408
5409 d->do_simulate= 0;
5410
5411 /* ts A61201 - A90815*/
5412 d->erasable = 0;
5413 d->current_profile = -1;
5414 d->current_profile_text[0] = 0;
5415 d->current_is_cd_profile = 0;
5416 d->current_is_supported_profile = 0;
5417 d->current_is_guessed_profile = 0;
5418 memset(d->all_profiles, 0, 256);
5419 d->num_profiles = 0;
5420 d->current_has_feat21h = 0;
5421 d->current_feat21h_link_size = -1;
5422 d->current_feat23h_byte4 = 0;
5423 d->current_feat23h_byte8 = 0;
5424 d->current_feat2fh_byte4 = -1;
5425 d->next_track_damaged = 0;
5426 d->needs_close_session = 0;
5427 d->needs_sync_cache = 0;
5428 d->bg_format_status = -1;
5429 d->num_opc_tables = -1;
5430 d->last_lead_in = -2000000000;
5431 d->last_lead_out = -2000000000;
5432 d->disc_type = 0xff;
5433 d->disc_id = 0;
5434 memset(d->disc_bar_code, 0, 9);
5435 d->disc_app_code = 0;
5436 d->disc_info_valid = 0;
5437 d->num_format_descr = 0;
5438 d->complete_sessions = 0;
5439
5440 #ifdef Libburn_disc_with_incomplete_sessioN
5441 d->incomplete_sessions = 0;
5442 #endif
5443
5444 d->state_of_last_session = -1;
5445 d->last_track_no = 1;
5446 d->media_capacity_remaining = 0;
5447 d->media_lba_limit = 0;
5448 d->media_read_capacity = 0x7fffffff;
5449 d->mr_capacity_trusted = 0;
5450 d->pessimistic_buffer_free = 0;
5451 d->pbf_altered = 0;
5452 d->wait_for_buffer_free = Libburn_wait_for_buffer_freE;
5453 d->nominal_write_speed = 0;
5454 d->pessimistic_writes = 0;
5455 d->waited_writes = 0;
5456 d->waited_tries = 0;
5457 d->waited_usec = 0;
5458 d->wfb_min_usec = Libburn_wait_for_buffer_min_useC;
5459 d->wfb_max_usec = Libburn_wait_for_buffer_max_useC;
5460 d->wfb_timeout_sec = Libburn_wait_for_buffer_tio_seC;
5461 d->wfb_min_percent = Libburn_wait_for_buffer_min_perC;
5462 d->wfb_max_percent = Libburn_wait_for_buffer_max_perC;
5463 d->sent_default_page_05 = 0;
5464
5465 return 1;
5466 }
5467
5468
5469 /* @param flag bit0= really add to text, else only count
5470 */
5471 static void burn__add_to_text(char *text, int *text_len, char *to_add,
5472 int flag)
5473 {
5474 (*text_len) += strlen(to_add);
5475 if (flag & 1)
5476 strcat(text, to_add);
5477 }
5478
5479 /* @param flag bit0= really add to text, else only count
5480 */
5481 static void burn__add_hex_to_text(char *text, int *text_len,
5482 unsigned char *to_add, int add_length,
5483 int flag)
5484 {
5485 int i, l;
5486
5487 (*text_len) += 3 * add_length;
5488 if (!(flag & 1))
5489 return;
5490 l = strlen(text);
5491 for (i = 0; i < add_length; i++)
5492 sprintf(text + l + 3 * i, " %2.2x", to_add[i]);
5493 }
5494
5495 int burn_make_feature_text(struct burn_drive *d, unsigned int feature_code,
5496 unsigned char flags,
5497 unsigned char additional_length,
5498 unsigned char *feature_data,
5499 char **text, int flag)
5500 {
5501 char *feature_name, addon[320], *cpt;
5502 int text_len, ret, i, pass;
5503 unsigned int phys_is, lmt, num;
5504
5505 static unsigned short feature_codes[] = {
5506 0x00, 0x01, 0x02, 0x03,
5507 0x04, 0x10, 0x1d, 0x1e,
5508 0x1f, 0x20, 0x21, 0x22,
5509 0x23, 0x24, 0x25, 0x26,
5510 0x27, 0x28, 0x29, 0x2a,
5511 0x2b, 0x2c, 0x2d, 0x2e,
5512 0x2f, 0x33, 0x37, 0x38,
5513 0x3a, 0x3b, 0x40, 0x41,
5514 0x42, 0x50, 0x51, 0x80,
5515 0x100, 0x101, 0x102, 0x104,
5516 0x105, 0x106, 0x107, 0x108,
5517 0x109, 0x10a, 0x10b, 0x10c,
5518 0x10d, 0x110,
5519 0xffff
5520 };
5521 static char feature_names[][40] = {
5522 "Profile List", "Core", "Morphing", "Removable Medium",
5523 "Write Protect", "Random Readable", "Multi-Read", "CD Read",
5524 "DVD Read", "Random Writable",
5525 "Incremental Streaming Writable", "Sector Erasable",
5526 "Formattable", "Hardware Defect Management", "Write Once",
5527 "Restricted Overwrite",
5528 "CD-RW CAV Write", "MRW", "Enhanced Defect Reporting",
5529 "DVD+RW",
5530 "DVD+R", "Rigid Restricted Overwrite", "CD Track at Once",
5531 "CD Mastering",
5532 "DVD-R/-RW Write", "Layer Jump Recording",
5533 "CD-RW Media Write Support", "BD-R POW",
5534 "DVD+RW Dual Layer", "DVD+R Dual Layer", "BD Read Feature",
5535 "BD Write Feature",
5536 "TSR", "HD DVD Read", "HD DVD Write", "Hybrid Disc",
5537 "Power Management", "SMART", "Embedded Changer",
5538 "Microcode Upgrade",
5539 "Timeout", "DVD-CSS", "Real Time Streaming",
5540 "Drive Serial Number",
5541 "Media Serial Number", "DCBs", "DVD CPRM",
5542 "Firmware Information",
5543 "AACS", "VCPS",
5544 ""
5545 };
5546 static unsigned short legacy_codes[] = {
5547 0x30, 0x31, 0x32, 0x103, 0xffff
5548 };
5549 static unsigned int phys_is_codes[] = {
5550 0x00, 0x01, 0x02, 0x03,
5551 0x04, 0x05, 0x06, 0x07,
5552 0x08, 0xffff,
5553 0xffffffff
5554 };
5555 static char phys_is_names[][40] = {
5556 "Unspecified", "SCSI_Family", "ATAPI", "IEEE_1394-1995",
5557 "IEEE_1394A", "Fibre_Channel", "IEEE_1394B", "Serial_ATAPI",
5558 "USB", "Vendor_Unique",
5559 ""
5560 };
5561 static char load_mech_names[8][40] = {
5562 "Caddy/Slot", "Tray", "Pop-up", "(Reserved)",
5563 "Embedded_changer_individually", "Embedded_changer_magazine",
5564 "(Reserved)", "(Reserved)"
5565 };
5566
5567 feature_name = "(Reserved)";
5568 for (i = 0; feature_codes[i] != 0xffff; i++) {
5569 if (feature_codes[i] == feature_code) {
5570 feature_name = feature_names[i];
5571 break;
5572 }
5573 }
5574 if (feature_codes[i] == 0xffff) {
5575 for (i = 0; legacy_codes[i] != 0xffff; i++) {
5576 if (legacy_codes[i] == feature_code) {
5577 feature_name = "(Legacy)";
5578 break;
5579 }
5580 }
5581 }
5582 if (feature_code >= 0xff00 && feature_code <= 0xffff)
5583 feature_name = "(Vendor Specific)";
5584
5585 *text = NULL;
5586 for (pass = 0; pass < 2; pass++) {
5587 if (pass == 1) {
5588 BURN_ALLOC_MEM(*text, char, text_len + 1);
5589 }
5590 text_len = 0;
5591
5592 sprintf(addon, "%4.4x %c : ", feature_code,
5593 (flags & 1) ? '+' : '-');
5594 burn__add_to_text(*text, &text_len, addon, pass);
5595
5596 burn__add_to_text(*text, &text_len, feature_name, pass);
5597
5598 /* Version, Persistent, Current */
5599 sprintf(addon, " : %1.1x,%c :",
5600 (flags >> 2) & 15, (flags & 2) ? 'P' : 'N');
5601 burn__add_to_text(*text, &text_len, addon, pass);
5602
5603 burn__add_hex_to_text(*text, &text_len,
5604 feature_data, (int) additional_length, pass);
5605 burn__add_to_text(*text, &text_len, " :", pass);
5606
5607 if (feature_code == 0x01 && additional_length >= 4) {
5608 /* Core : Physical Interface Standard , INQ2, DBE */
5609 phys_is = mmc_four_char_to_int(feature_data);
5610 cpt = "(Not_Recognizable)";
5611 for (i = 0; phys_is_codes[i] != 0xffffffff; i++) {
5612 if (phys_is_codes[i] == phys_is) {
5613 cpt = phys_is_names[i];
5614 break;
5615 }
5616
5617 }
5618 num = 0;
5619 if (additional_length >= 9)
5620 num = feature_data[8];
5621 sprintf(addon,
5622 " PhysInterface=%x/%s , INQ2=%d , DBE=%d",
5623 phys_is, cpt, (num >> 1) & 1, num & 1);
5624 burn__add_to_text(*text, &text_len, addon, pass);
5625
5626 } else if (feature_code == 0x03 && additional_length >= 1) {
5627 /* Removable Medium : Lock, Pvnt Jmpr, Eject,
5628 Loading mechanism Type
5629 */
5630 num = feature_data[0];
5631 lmt = (num >> 5) & 7;
5632 sprintf(addon,
5633 " LoadMechType=%x/%s , Eject=%d , PvntJmpr=%d , Lock=%d",
5634 lmt, load_mech_names[lmt], (num >> 3) & 1,
5635 (num >> 2) & 1, num & 1);
5636 burn__add_to_text(*text, &text_len, addon, pass);
5637
5638 } else if (feature_code == 0x10 && additional_length >= 4) {
5639 /* Random Readable: Logical Block Size, Blocking */
5640 num = 0;
5641 if (additional_length >= 6)
5642 num = (feature_data[4] << 8) | feature_data[5];
5643 sprintf(addon, " BlockSize=%d , Blocking=%u",
5644 mmc_four_char_to_int(feature_data), num);
5645 num = 0;
5646 if (additional_length >= 7)
5647 num = feature_data[6];
5648 sprintf(addon + strlen(addon), " , PP=%d", num & 1);
5649 burn__add_to_text(*text, &text_len, addon, pass);
5650
5651 } else if (feature_code == 0x1e && additional_length >= 1) {
5652 /* CD Read: DAP, C2 Flags, CD-Text */
5653 sprintf(addon, " DAP=%d , C2Flags=%d , CDText=%d",
5654 (feature_data[0] >> 7) & 1,
5655 (feature_data[0] >> 1) & 1,
5656 feature_data[0] & 1);
5657 burn__add_to_text(*text, &text_len, addon, pass);
5658
5659 } else if (feature_code == 0x1f && additional_length >= 1) {
5660 /* DVD Read: MULTI110, Dual-R */
5661 num = 0;
5662 if (additional_length >= 3)
5663 num = feature_data[2];
5664 sprintf(addon, " MULTI10=%d , DualR=%d",
5665 feature_data[0] & 1, num & 1);
5666 burn__add_to_text(*text, &text_len, addon, pass);
5667
5668 } else if (feature_code == 0x20 && additional_length >= 4) {
5669 /* Random Writable: Last LBA, Logical Block Size,
5670 Blocking, PP */
5671 num = 0;
5672 if (additional_length >= 8)
5673 num = mmc_four_char_to_int(feature_data + 4);
5674 sprintf(addon, " LastLBA=%d , BlockSize=%u",
5675 mmc_four_char_to_int(feature_data), num);
5676 num = 0;
5677 if (additional_length >= 10)
5678 num = (feature_data[8] << 8) | feature_data[9];
5679 sprintf(addon + strlen(addon), " , Blocking=%u", num);
5680 num = 0;
5681 if (additional_length >= 11)
5682 num = feature_data[10];
5683 sprintf(addon + strlen(addon), " , PP=%u", num);
5684 burn__add_to_text(*text, &text_len, addon, pass);
5685
5686 } else if (feature_code == 0x21 && additional_length >= 2) {
5687 /* Incremental Streaming Writable :
5688 Data Block Types , TRIO , ARSV , BUF
5689 Number of Link Sizes
5690 */
5691 num = 0;
5692 if (additional_length >= 3)
5693 num = feature_data[2];
5694 sprintf(addon,
5695 " DataBlockTypes=%2.2x%2.2x , TRIO=%d , ARSV=%d , BUF=%d",
5696 feature_data[0], feature_data[1],
5697 (num >> 2) & 1, (num >> 1) & 1, num & 1);
5698 num = 0;
5699 if (additional_length >= 4)
5700 num = feature_data[3];
5701 sprintf(addon + strlen(addon), " , NumLinkSizes=%d",
5702 num);
5703 burn__add_to_text(*text, &text_len, addon, pass);
5704
5705 } else if (feature_code == 0x23 && additional_length >= 1) {
5706 /* Formattable: RENoSA, Expand, QCert, Cert, RRM */
5707 num = feature_data[0];
5708 sprintf(addon,
5709 " RENoSA=%d , Expand=%d , QCert=%d , Cert=%d",
5710 (num >> 3) & 1, (num >> 2) & 1,
5711 (num >> 1) & 1, num & 1);
5712 num = 0;
5713 if (additional_length >= 5)
5714 num = feature_data[4];
5715 sprintf(addon + strlen(addon), " , RRM=%d", num & 1);
5716 burn__add_to_text(*text, &text_len, addon, pass);
5717
5718 } else if (feature_code == 0x24 && additional_length >= 1) {
5719 /* Defect Management : SSA */
5720 sprintf(addon, " SSA=%d", (feature_data[0] >> 7) & 1);
5721 burn__add_to_text(*text, &text_len, addon, pass);
5722
5723 } else if (feature_code == 0x28 && additional_length >= 1) {
5724 /* MRW */
5725 num = feature_data[0];
5726 sprintf(addon,
5727 " DVDPWrite=%d , DVDPRead=%d , CDWrite=%d",
5728 (num >> 2) & 1, (num >> 1) & 1, num & 1);
5729 burn__add_to_text(*text, &text_len, addon, pass);
5730
5731 } else if (feature_code == 0x2a && additional_length >= 1) {
5732 /* DVD+RW */
5733 num = 0;
5734 if (additional_length >= 2)
5735 num = feature_data[1];
5736 sprintf(addon,
5737 " Write=%d , QuickStart=%d , CloseOnly=%d",
5738 feature_data[0] & 1, (num >> 1) & 1, num & 1);
5739 burn__add_to_text(*text, &text_len, addon, pass);
5740
5741 } else if (feature_code == 0x2b && additional_length >= 1) {
5742 /* DVD+R */
5743 sprintf(addon, " Write=%d", feature_data[0] & 1);
5744 burn__add_to_text(*text, &text_len, addon, pass);
5745
5746 } else if (feature_code == 0x2c && additional_length >= 1) {
5747 /* Rigid Restricted Overwrite */
5748 num = feature_data[0];
5749 sprintf(addon,
5750 " DSDG=%d , DSDR=%d , Intermediate=%d , Blank=%d",
5751 (num >> 3) & 1, (num >> 2) & 1,
5752 (num >> 1) & 1, num & 1);
5753 burn__add_to_text(*text, &text_len, addon, pass);
5754
5755 } else if (feature_code == 0x2d && additional_length >= 1) {
5756 /* CD Track at Once */
5757 num= feature_data[0];
5758 sprintf(addon,
5759 " BUF=%d , RWRaw=%d , RWPack=%d , TestWrite=%d , CD-RW=%d , RWSubcode=%d",
5760 (num >> 6) & 1, (num >> 4) & 1,
5761 (num >> 3) & 1, (num >> 2) & 1,
5762 (num >> 1) & 1, num & 1);
5763 num = 0;
5764 if (additional_length >= 4)
5765 num = (feature_data[2] << 8) | feature_data[3];
5766 sprintf(addon + strlen(addon), " , DataTypeSupp=%4.4x",
5767 num);
5768 burn__add_to_text(*text, &text_len, addon, pass);
5769
5770 } else if (feature_code == 0x2e && additional_length >= 1) {
5771 /* CD Mastering (SAO) */
5772 num = feature_data[0];
5773 sprintf(addon,
5774 " BUF=%d , SAO=%d , RawMS=%d , Raw=%d , TestWrite=%d , CD-RW=%d , RW=%d",
5775 (num >> 6) & 1, (num >> 5) & 1, (num >> 4) & 1,
5776 (num >> 3) & 1, (num >> 2) & 1,
5777 (num >> 1) & 1, num & 1);
5778 num = 0;
5779 if (additional_length >= 4)
5780 num = (feature_data[1] << 16) |
5781 (feature_data[2] << 8) | feature_data[3];
5782 sprintf(addon + strlen(addon),
5783 " , MaxCueSheetLen=%u", num);
5784 burn__add_to_text(*text, &text_len, addon, pass);
5785
5786 } else if (feature_code == 0x2f && additional_length >= 1) {
5787 /* DVD-R/RW Write */
5788 num = feature_data[0];
5789 sprintf(addon,
5790 " BUF=%d , RDL=%d , TestWrite=%d , DVDRW=%d",
5791 (num >> 6) & 1, (num >> 3) & 1,
5792 (num >> 2) & 1, (num >> 1) & 1);
5793 burn__add_to_text(*text, &text_len, addon, pass);
5794
5795 } else if (feature_code == 0x33 && additional_length >= 4) {
5796 /* Layer Jump Recording */
5797 sprintf(addon, " NumLinkSizes=%d", feature_data[3]);
5798 burn__add_to_text(*text, &text_len, addon, pass);
5799
5800 } else if (feature_code == 0x37 && additional_length >= 2) {
5801 /* CD-RW Media Write Support */
5802 addon[0]= 0;
5803 for (i = 7; i >= 0; i--) {
5804 sprintf(addon + strlen(addon),
5805 " Subtype%d=%d%s",
5806 i, (feature_data[1] >> i) & 1,
5807 i > 0 ? " ," : "");
5808 }
5809 burn__add_to_text(*text, &text_len, addon, pass);
5810
5811 } else if (feature_code == 0x3a && additional_length >= 2) {
5812 /* DVD+RW Dual Layer */
5813 sprintf(addon,
5814 " Write=%d , QuickStart=%d , CloseOnly=%d",
5815 feature_data[0] & 1,
5816 (feature_data[1] >> 1) & 1,
5817 feature_data[1] & 1);
5818 burn__add_to_text(*text, &text_len, addon, pass);
5819
5820 } else if (feature_code == 0x3b && additional_length >= 1) {
5821 /* DVD+R Dual Layer */
5822 sprintf(addon, " Write=%d", feature_data[0] & 1);
5823 burn__add_to_text(*text, &text_len, addon, pass);
5824
5825 } else if (feature_code == 0x50 && additional_length >= 1) {
5826 /* HD DVD Read */
5827 num = 0;
5828 if (additional_length >= 3)
5829 num = feature_data[2];
5830 sprintf(addon, " HDDVDR=%d , HDDVDRAM=%d",
5831 feature_data[0] & 1, num & 1);
5832 burn__add_to_text(*text, &text_len, addon, pass);
5833
5834 } else if (feature_code == 0x51 && additional_length >= 1) {
5835 /* HD DVD Write */
5836 num = 0;
5837 if (additional_length >= 3)
5838 num = feature_data[2];
5839 sprintf(addon, " HDDVDR=%d , HDDVDRAM=%d",
5840 feature_data[0] & 1, num & 1);
5841 burn__add_to_text(*text, &text_len, addon, pass);
5842
5843 } else if (feature_code == 0x101 && additional_length >= 1) {
5844 /* SMART */
5845 sprintf(addon, " PP=%d", feature_data[0] & 1);
5846 burn__add_to_text(*text, &text_len, addon, pass);
5847
5848 } else if (feature_code == 0x102 && additional_length >= 1) {
5849 /* Embedded Changer */
5850 num = 0;
5851 if (additional_length >= 4)
5852 num = feature_data[3];
5853 sprintf(addon, " SCC=%d , SDP=%d , HighestSlotNo=%u",
5854 (feature_data[0] >> 4) & 1,
5855 (feature_data[0] >> 2) & 1, num & 31);
5856 burn__add_to_text(*text, &text_len, addon, pass);
5857
5858 } else if (feature_code == 0x105 && additional_length >= 1) {
5859 /* Timeout */
5860 num = 0;
5861 if (additional_length >= 4)
5862 num = (feature_data[2] << 8) | feature_data[3];
5863 sprintf(addon, " Group3=%d , UnitLength=%u",
5864 feature_data[0] & 1, num);
5865 burn__add_to_text(*text, &text_len, addon, pass);
5866
5867 } else if (feature_code == 0x106 && additional_length >= 4) {
5868 /* DVD CSS */
5869 sprintf(addon, " CSSVersion=%d",
5870 (int) feature_data[3]);
5871 burn__add_to_text(*text, &text_len, addon, pass);
5872
5873 } else if (feature_code == 0x107 && additional_length >= 1) {
5874 /* Real Time Streaming */
5875 num = feature_data[0];
5876 sprintf(addon,
5877 " RBCB=%d , SCS=%d , MP2A=%d , WSPD=%d , SW=%d",
5878 (num >> 4) & 1, (num >> 3) & 1, (num >> 2) & 1,
5879 (num >> 1) & 1, num & 1);
5880 burn__add_to_text(*text, &text_len, addon, pass);
5881
5882 } else if (feature_code == 0x108 && additional_length >= 1) {
5883 /* Drive Serial Number */
5884 strcpy(addon, " SerialNumber=");
5885 for (i = 0; i < additional_length; i++) {
5886 num = feature_data[i];
5887 if (num >= ' ' && num < 127)
5888 addon[14 + i] = feature_data[i];
5889 else
5890 addon[14 + i] = '?';
5891 }
5892 addon[14 + i] = 0;
5893 burn__add_to_text(*text, &text_len, addon, pass);
5894
5895 } else if (feature_code == 0x10a && additional_length >= 4) {
5896 /* DCBs */
5897 addon[0] = 0;
5898 for (i = 0; i < additional_length / 4; i++)
5899 sprintf(addon + strlen(addon),
5900 " SuppEntry%d=%2.2x%2.2x%2.2x%2.2x%s",
5901 i, feature_data[i * 4 + 0],
5902 feature_data[i * 4 + 1],
5903 feature_data[i * 4 + 2],
5904 feature_data[i * 4 + 3],
5905 i < additional_length / 4 - 1 ?
5906 " ," : "");
5907 burn__add_to_text(*text, &text_len, addon, pass);
5908
5909 } else if (feature_code == 0x10b && additional_length >= 4) {
5910 /* DVD CPRM */
5911 sprintf(addon, " CPRMVersion=%d", feature_data[3]);
5912 burn__add_to_text(*text, &text_len, addon, pass);
5913
5914 } else if (feature_code == 0x10c && additional_length >= 14) {
5915 /* Firmware Information */
5916 strcpy(addon, " Date=");
5917 for (i = 0; i < 14; i += 2)
5918 sprintf(addon + 6 + i, "%2.2d",
5919 ((feature_data[i] & 0xf) % 10) * 10 +
5920 ((feature_data[i + 1] & 0xf) % 10));
5921 burn__add_to_text(*text, &text_len, addon, pass);
5922
5923 } else if (feature_code == 0x10d && additional_length >= 4) {
5924 /* AACS */
5925 sprintf(addon,
5926 " BNG=%d , BlockCountBindingNonce=%d , NumberAGIDs=%d , AACSVersion=%d",
5927 feature_data[0] & 1, feature_data[1],
5928 feature_data[2] & 0xf, feature_data[3]);
5929 burn__add_to_text(*text, &text_len, addon, pass);
5930
5931 }
5932 }
5933 ret = 1;
5934 ex:;
5935 return ret;
5936 }
5937