1 
2 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
3    Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net>
4    Provided under GPL version 2 or later.
5 */
6 
7 #ifdef HAVE_CONFIG_H
8 #include "../config.h"
9 #endif
10 
11 #include "libburn.h"
12 #include "options.h"
13 #include "drive.h"
14 #include "transport.h"
15 #include "init.h"
16 #include "write.h"
17 
18 /* ts A61007 */
19 /* #include <a ssert.h> */
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 
25 #include "libdax_msgs.h"
26 extern struct libdax_msgs *libdax_messenger;
27 
28 
burn_write_opts_new(struct burn_drive * drive)29 struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
30 {
31 	struct burn_write_opts *opts;
32 
33 	opts = calloc(1, sizeof(struct burn_write_opts));
34 	if (opts == NULL) {
35 		libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
36 			LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
37 			"Could not allocate new auxiliary object", 0, 0);
38 		return NULL;
39 	}
40 	opts->drive = drive;
41 	opts->refcount = 1;
42 	opts->write_type = BURN_WRITE_TAO;
43 	opts->block_type = BURN_BLOCK_MODE1;
44 	opts->toc_entry = NULL;
45 	opts->toc_entries = 0;
46 	opts->simulate = 0;
47 	opts->underrun_proof = drive->mdata->p2a_valid > 0 &&
48 	                       drive->mdata->underrun_proof;
49 	opts->perform_opc = 1;
50 	opts->obs = -1;
51 
52 #ifdef Libburn_dvd_always_obs_paD
53 	opts->obs_pad = 1;
54 #else
55 	opts->obs_pad = 0;
56 #endif
57 
58 	opts->start_byte = -1;
59 	opts->fill_up_media = 0;
60 	opts->force_is_set = 0;
61 	opts->do_stream_recording = 0;
62 	opts->dvd_obs_override = 0;
63 	opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
64 	opts->text_packs = NULL;
65 	opts->num_text_packs = 0;
66 	opts->no_text_pack_crc_check = 0;
67 	opts->has_mediacatalog = 0;
68 	opts->format = BURN_CDROM;
69 	opts->multi = 0;
70 	opts->control = 0;
71 	return opts;
72 }
73 
burn_write_opts_free(struct burn_write_opts * opts)74 void burn_write_opts_free(struct burn_write_opts *opts)
75 {
76 	if (--opts->refcount > 0)
77 		return;
78 	if (opts->text_packs != NULL)
79 		free(opts->text_packs);
80 	free(opts);
81 }
82 
burn_write_opts_clone(struct burn_write_opts * from,struct burn_write_opts ** to,int flag)83 int burn_write_opts_clone(struct burn_write_opts *from,
84                           struct burn_write_opts **to, int flag)
85 {
86 	if (*to != NULL)
87 		burn_write_opts_free(*to);
88 	if (from == NULL)
89 		return 1;
90 	*to = calloc(1, sizeof(struct burn_write_opts));
91 	if (*to == NULL) {
92 out_of_mem:;
93 		libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
94 				LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
95 				"Out of virtual memory", 0, 0);
96 		return -1;
97 	}
98 	memcpy(*to, from, sizeof(struct burn_write_opts));
99 	(*to)->text_packs = NULL;
100 	(*to)->num_text_packs = 0;
101 	if (from->text_packs != NULL && from->num_text_packs > 0) {
102 		(*to)->text_packs = calloc(1, from->num_text_packs * 18);
103 		if ((*to)->text_packs == NULL)
104 			goto out_of_mem;
105 		memcpy((*to)->text_packs, from->text_packs,
106 		       from->num_text_packs * 18);
107 	}
108 	(*to)->refcount= 1;
109 	return 1;
110 }
111 
burn_read_opts_new(struct burn_drive * drive)112 struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive)
113 {
114 	struct burn_read_opts *opts;
115 
116 	opts = calloc(1, sizeof(struct burn_read_opts));
117 	opts->drive = drive;
118 	opts->refcount = 1;
119 	opts->raw = 0;
120 	opts->c2errors = 0;
121 	opts->subcodes_audio = 0;
122 	opts->subcodes_data = 0;
123 	opts->hardware_error_recovery = 0;
124 	opts->report_recovered_errors = 0;
125 	opts->transfer_damaged_blocks = 0;
126 	opts->hardware_error_retries = 3;
127 	opts->dap_bit = 0;
128 
129 	return opts;
130 }
131 
burn_read_opts_free(struct burn_read_opts * opts)132 void burn_read_opts_free(struct burn_read_opts *opts)
133 {
134 	if (--opts->refcount <= 0)
135 		free(opts);
136 }
137 
burn_write_opts_set_write_type(struct burn_write_opts * opts,enum burn_write_types write_type,int block_type)138 int burn_write_opts_set_write_type(struct burn_write_opts *opts,
139 				   enum burn_write_types write_type,
140 				   int block_type)
141 {
142 	int sector_get_outmode(enum burn_write_types write_type,
143 				enum burn_block_types block_type);
144 	int spc_block_type(enum burn_block_types b);
145 
146 	/* ts A61007 */
147 	if (! ( (write_type == BURN_WRITE_SAO && block_type == BURN_BLOCK_SAO)
148 		 || (opts->drive->block_types[write_type] & block_type) ) ) {
149 bad_combination:;
150 		libdax_msgs_submit(libdax_messenger, -1, 0x00020112,
151 			LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
152 			"Bad combination of write_type and block_type", 0, 0);
153 		return 0;
154 	}
155 	/*  ts A61007 : obsoleting Assert in sector.c:get_outmode() */
156 	if (sector_get_outmode(write_type, (enum burn_block_types) block_type)
157 		 == -1)
158 		goto bad_combination;
159 	/*  ts A61007 : obsoleting Assert in spc.c:spc_block_type() */
160 	if (spc_block_type((enum burn_block_types) block_type) == -1)
161 		goto bad_combination;
162 
163 	opts->write_type = write_type;
164 	opts->block_type = block_type;
165 	return 1;
166 
167 	/* a ssert(0); */
168 }
169 
burn_write_opts_set_toc_entries(struct burn_write_opts * opts,int count,struct burn_toc_entry * toc_entries)170 void burn_write_opts_set_toc_entries(struct burn_write_opts *opts, int count,
171 				     struct burn_toc_entry *toc_entries)
172 {
173 	opts->toc_entries = count;
174 	opts->toc_entry = calloc(count, sizeof(struct burn_toc_entry));
175 	memcpy(opts->toc_entry, &toc_entries,
176 	       sizeof(struct burn_toc_entry) * count);
177 }
178 
burn_write_opts_set_format(struct burn_write_opts * opts,int format)179 void burn_write_opts_set_format(struct burn_write_opts *opts, int format)
180 {
181 	opts->format = format;
182 }
183 
burn_write_opts_set_simulate(struct burn_write_opts * opts,int sim)184 int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
185 {
186 	opts->simulate = !!sim;
187 	return 1;
188 }
189 
burn_write_opts_set_underrun_proof(struct burn_write_opts * opts,int underrun_proof)190 int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
191 				       int underrun_proof)
192 {
193 	if (opts->drive->mdata->p2a_valid <= 0 ||
194 	    opts->drive->mdata->underrun_proof) {
195 		opts->underrun_proof = underrun_proof;
196 		return 1;
197 	}
198 	return 0;
199 }
200 
burn_write_opts_set_perform_opc(struct burn_write_opts * opts,int opc)201 void burn_write_opts_set_perform_opc(struct burn_write_opts *opts, int opc)
202 {
203 	opts->perform_opc = opc;
204 }
205 
burn_write_opts_set_has_mediacatalog(struct burn_write_opts * opts,int has_mediacatalog)206 void burn_write_opts_set_has_mediacatalog(struct burn_write_opts *opts,
207 					  int has_mediacatalog)
208 {
209 	opts->has_mediacatalog = has_mediacatalog;
210 }
211 
burn_write_opts_set_mediacatalog(struct burn_write_opts * opts,unsigned char mediacatalog[13])212 void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts,
213 				      unsigned char mediacatalog[13])
214 {
215 	memcpy(opts->mediacatalog, mediacatalog, 13);
216 }
217 
218 
219 /* ts A61106 */
burn_write_opts_set_multi(struct burn_write_opts * opts,int multi)220 void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
221 {
222 	opts->multi = !!multi;
223 }
224 
225 
226 /* ts B31024 */
227 /* API */
burn_write_opts_set_fail21h_sev(struct burn_write_opts * opts,char * severity)228 void burn_write_opts_set_fail21h_sev(struct burn_write_opts *opts,
229                                      char *severity)
230 {
231 	int ret, sevno;
232 
233 	ret = libdax_msgs__text_to_sev(severity, &sevno, 0);
234 	if (ret <= 0)
235 		opts->feat21h_fail_sev = 0;
236 	else
237 		opts->feat21h_fail_sev = sevno;
238 }
239 
240 
241 /* ts B11204 */
242 /* @param flag bit0=do not verify checksums
243                bit1= repair mismatching checksums
244                bit2= repair checksums if they are 00 00 with each pack
245 */
burn_write_opts_set_leadin_text(struct burn_write_opts * opts,unsigned char * text_packs,int num_packs,int flag)246 int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
247                                     unsigned char *text_packs,
248                                     int num_packs, int flag)
249 {
250 	int ret;
251 	unsigned char *pack_buffer = NULL;
252 
253 	if (num_packs > Libburn_leadin_cdtext_packs_maX ) {
254 		libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
255 				0x0002018b,
256 				LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
257 				"Too many CD-TEXT packs", 0, 0);
258 		ret= 0; goto ex;
259 	}
260 
261 	if (num_packs > 0)
262 		BURN_ALLOC_MEM(pack_buffer, unsigned char, num_packs * 18);
263 
264 	if (opts->text_packs != NULL) {
265 		free(opts->text_packs);
266 		opts->text_packs = NULL;
267 	}
268 
269 	if (flag & 1) {
270 		opts->no_text_pack_crc_check = 1;
271 	} else {
272 		opts->no_text_pack_crc_check = 0;
273 		ret = burn_cdtext_crc_mismatches(text_packs, num_packs,
274 							(flag >> 1) & 3);
275 		if (ret > 0) {
276 			libdax_msgs_submit(libdax_messenger, -1, 0x0002018f,
277 				LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
278 				"CD-TEXT pack CRC mismatch", 0, 0);
279 			ret = 0; goto ex;
280 		} else if (ret < 0) {
281 			libdax_msgs_submit(libdax_messenger, -1, 0x00020190,
282 				LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
283 			    "CD-TEXT pack CRC mismatch had to be corrected",
284 				0, 0);
285 		}
286 	}
287 
288 	if (num_packs > 0) {
289 		memcpy(pack_buffer, text_packs, num_packs * 18);
290 		opts->text_packs = pack_buffer;
291 		pack_buffer = NULL;
292 	}
293 	opts->num_text_packs = num_packs;
294 	ret = 1;
295 ex:;
296 	BURN_FREE_MEM(pack_buffer);
297 	return ret;
298 }
299 
300 
301 /* ts A61222 */
burn_write_opts_set_start_byte(struct burn_write_opts * opts,off_t value)302 void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value)
303 {
304 	opts->start_byte = value;
305 }
306 
307 
308 /* ts A70207 API */
309 /** @param flag Bitfield for control purposes:
310                 bit0= do not choose type but check the one that is already set
311                 bit1= do not issue error messages via burn_msgs queue
312 */
burn_write_opts_auto_write_type(struct burn_write_opts * opts,struct burn_disc * disc,char reasons[BURN_REASONS_LEN],int flag)313 enum burn_write_types burn_write_opts_auto_write_type(
314 		struct burn_write_opts *opts, struct burn_disc *disc,
315 		char reasons[BURN_REASONS_LEN], int flag)
316 {
317 	struct burn_multi_caps *caps = NULL;
318 	struct burn_drive *d = opts->drive;
319 	struct burn_disc_mode_demands demands;
320 	enum burn_write_types wt;
321 	int ret, would_do_sao = 0;
322 	char *reason_pt;
323 
324 	reasons[0] = 0;
325 
326 	if (burn_drive_get_bd_r_pow(d)) {
327 		strcat(reasons,
328 		       "MEDIA: unsuitable BD-R Pseudo Overwrite formatting, ");
329 		return BURN_WRITE_NONE;
330 	}
331 	if (d->status != BURN_DISC_BLANK &&
332 	    d->status != BURN_DISC_APPENDABLE){
333 		if (d->status == BURN_DISC_FULL)
334 			strcat(reasons, "MEDIA: closed or not recordable, ");
335 		else
336 			strcat(reasons,"MEDIA: no writeable media detected, ");
337 		if (!(flag & 3))
338 			libdax_msgs_submit(libdax_messenger, d->global_index,
339 				0x0002013a,
340 				LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
341 				"No suitable media detected", 0, 0);
342 		return BURN_WRITE_NONE;
343 	}
344 	ret = burn_disc_get_write_mode_demands(disc, opts, &demands,
345 			 			!!opts->fill_up_media);
346 	if (ret <= 0) {
347 		strcat(reasons, "cannot recognize job demands, ");
348 		{wt = BURN_WRITE_NONE; goto ex;}
349 	}
350 	if (demands.exotic_track && !d->current_is_cd_profile) {
351 		if (demands.audio)
352 			strcat(reasons, "audio track prohibited by non-CD, ");
353 		else
354 			strcat(reasons, "exotic track prohibited by non-CD, ");
355 		{wt = BURN_WRITE_NONE; goto ex;}
356 	}
357 	if ((flag & 1) && opts->write_type != BURN_WRITE_SAO)
358 		goto try_tao;
359 	reason_pt = reasons + strlen(reasons);
360 	strcat(reasons, "SAO: ");
361 	if (d->status != BURN_DISC_BLANK) {
362 		strcat(reasons, "write type SAO works only on blank media, ");
363 		goto try_tao;
364 	}
365 	burn_disc_free_multi_caps(&caps);
366 	ret = burn_disc_get_multi_caps(d, BURN_WRITE_SAO, &caps, 0);
367 	if (ret < 0) {
368 no_caps:;
369 		strcat(reasons, "cannot inquire write mode capabilities, ");
370 		{wt = BURN_WRITE_NONE; goto ex;}
371 	} else if (ret == 0) {
372 		strcat(reasons, "no SAO offered by drive and media, ");
373 		goto no_sao;
374 	}
375 	if ((opts->multi || demands.multi_session) &&
376 	    !caps->multi_session)
377 		strcat(reasons, "multi session capability lacking, ");
378 	if (demands.will_append)
379 		strcat(reasons, "appended session capability lacking, ");
380 	if (demands.multi_track && !caps->multi_track)
381 		strcat(reasons, "multi track capability lacking, ");
382 	if (demands.unknown_track_size == 1 &&
383 	    (caps->might_do_sao == 1 || caps->might_do_sao == 3))
384 		strcat(reasons, "track size unpredictable, ");
385 	if (demands.mixed_mode)
386 		strcat(reasons, "tracks of different modes mixed, ");
387 	if (demands.exotic_track && !d->current_is_cd_profile)
388 		strcat(reasons, "non-data track on non-cd, ");
389 	else if (d->current_is_cd_profile)
390 		if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
391 			demands.block_types)
392 			strcat(reasons, "drive dislikes block type, ");
393 	if (d->current_is_cd_profile && opts->fill_up_media)
394 		strcat(reasons, "cd sao cannot do media fill up yet, ");
395 	if (strcmp(reason_pt, "SAO: ") != 0)
396 		goto no_sao;
397 	would_do_sao = 1;
398 	if (demands.unknown_track_size == 2 && (!(flag & 1)) &&
399 	    (caps->might_do_sao == 1 || caps->might_do_sao == 3)) {
400 		strcat(reasons, "would have to use default track sizes, ");
401 		goto no_sao;
402 	} else if (caps->might_do_sao >= 3 && !(flag & 1))
403 		goto try_tao;
404 do_sao:;
405 	if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
406 		goto no_simulate;
407 	if (!(flag & 1))
408 		burn_write_opts_set_write_type(
409 					opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
410 	{wt = BURN_WRITE_SAO; goto ex;}
411 no_sao:;
412 try_tao:;
413 	if (opts->num_text_packs > 0) {
414 		strcat(reasons, "CD-TEXT: write type SAO required, ");
415 		{wt = BURN_WRITE_NONE; goto ex;}
416 	}
417 	if ((flag & 1) && opts->write_type != BURN_WRITE_TAO)
418 		goto try_raw;
419 	reason_pt = reasons + strlen(reasons);
420 	strcat(reasons, "TAO: ");
421 	burn_disc_free_multi_caps(&caps);
422 	ret = burn_disc_get_multi_caps(d, BURN_WRITE_TAO, &caps, 0);
423 	if (ret < 0)
424 		goto no_caps;
425 	if (ret == 0) {
426 		strcat(reasons, "no TAO offered by drive and media, ");
427 		goto no_tao;
428 	}
429 	if ((opts->multi || demands.multi_session) && !caps->multi_session)
430 		strcat(reasons, "multi session capability lacking, ");
431 	if (demands.multi_track && !caps->multi_track)
432 		strcat(reasons, "multi track capability lacking, ");
433 	if (demands.exotic_track && !d->current_is_cd_profile)
434 		strcat(reasons, "non-data track on non-cd, ");
435 	if (d->current_is_cd_profile && !opts->force_is_set)
436 		if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
437 			demands.block_types)
438 			strcat(reasons, "drive dislikes block type, ");
439 	if (strcmp(reason_pt, "TAO: ") != 0)
440 		goto no_tao;
441 	/* ( TAO data/audio block size will be handled automatically ) */
442 	if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
443 		goto no_simulate;
444 	if (!(flag & 1))
445 		burn_write_opts_set_write_type(
446 				opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
447 	{wt = BURN_WRITE_TAO; goto ex;}
448 no_tao:;
449 	if (would_do_sao && !(flag & 1))
450 		goto do_sao;
451 	if (!d->current_is_cd_profile)
452 		goto no_write_mode;
453 try_raw:;
454 	if ((flag & 1) && opts->write_type != BURN_WRITE_RAW)
455 		goto no_write_mode;
456 
457 	if (!(flag & 1)) /* For now: no automatic raw write modes */
458 		goto no_write_mode;
459 
460 	reason_pt = reasons + strlen(reasons);
461 	strcat(reasons, "RAW: ");
462 	if (!d->current_is_cd_profile)
463 		strcat(reasons, "write type RAW prohibited by non-cd, ");
464 	else if (d->status != BURN_DISC_BLANK)
465 		strcat(reasons, "write type RAW works only on blank media, ");
466 	else if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
467 						    	demands.block_types)
468 		strcat(reasons, "drive dislikes block type, ");
469 	if (strcmp(reason_pt, "RAW: ") != 0)
470 		goto no_write_mode;
471 	if (!opts->force_is_set)
472 		goto no_simulate;
473 
474 	/*  For now: no setting of raw write modes */
475 
476 	{wt = BURN_WRITE_RAW; goto ex;}
477 
478 no_write_mode:;
479 	{wt = BURN_WRITE_NONE; goto ex;}
480 
481 no_simulate:;
482 	strcat(reasons,
483 	       "simulation of write job not supported by drive and media, ");
484 	{wt = BURN_WRITE_NONE; goto ex;}
485 
486 ex:;
487 	burn_disc_free_multi_caps(&caps);
488 	if (wt == BURN_WRITE_NONE && !(flag & 3)) {
489 		libdax_msgs_submit(libdax_messenger, d->global_index,
490 			0x0002012b,
491 			LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
492 			"Drive offers no suitable write mode with this job",
493 			0, 0);
494 	}
495 	return wt;
496 }
497 
498 
499 /* ts A70213 : new API function */
burn_write_opts_set_fillup(struct burn_write_opts * opts,int fill_up_media)500 void burn_write_opts_set_fillup(struct burn_write_opts *opts,int fill_up_media)
501 {
502 	opts->fill_up_media = !!fill_up_media;
503 	return;
504 }
505 
506 
507 /* ts A70303: API */
burn_write_opts_set_force(struct burn_write_opts * opts,int use_force)508 void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force)
509 {
510 	opts->force_is_set = !!use_force;
511 }
512 
513 
514 /* ts A80412: API */
burn_write_opts_set_stream_recording(struct burn_write_opts * opts,int value)515 void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
516 					 int value)
517 {
518 	opts->do_stream_recording = value;
519 }
520 
521 
522 /* ts A91115: API */
burn_write_opts_set_dvd_obs(struct burn_write_opts * opts,int obs)523 void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs)
524 {
525 	if (obs != 0 && obs != 32 * 1024 && obs != 64 * 1024)
526 		return;
527 	opts->dvd_obs_override = obs;
528 }
529 
530 
531 /* ts B20406: API */
burn_write_opts_set_obs_pad(struct burn_write_opts * opts,int pad)532 void burn_write_opts_set_obs_pad(struct burn_write_opts *opts, int pad)
533 {
534 	opts->obs_pad = 2 * !!pad;
535 }
536 
537 
538 /* ts A91115: API */
burn_write_opts_set_stdio_fsync(struct burn_write_opts * opts,int rhythm)539 void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rhythm)
540 {
541 	if (rhythm == -1)
542 		opts->stdio_fsync_size = -1; /* never */
543 	else if (rhythm == 0)
544 		opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
545 	else if (rhythm == 1)
546 		opts->stdio_fsync_size = 0; /* only at end of writing */
547 	else if (rhythm >= 32)
548 		opts->stdio_fsync_size = rhythm;
549 }
550 
551 
552 /* ts A70901: API */
burn_write_opts_get_drive(struct burn_write_opts * opts)553 struct burn_drive *burn_write_opts_get_drive(struct burn_write_opts *opts)
554 {
555 	return opts->drive;
556 }
557 
558 
burn_read_opts_set_raw(struct burn_read_opts * opts,int raw)559 void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw)
560 {
561 	opts->raw = raw;
562 }
563 
burn_read_opts_set_c2errors(struct burn_read_opts * opts,int c2errors)564 void burn_read_opts_set_c2errors(struct burn_read_opts *opts, int c2errors)
565 {
566 	opts->c2errors = c2errors;
567 }
568 
burn_read_opts_read_subcodes_audio(struct burn_read_opts * opts,int subcodes_audio)569 void burn_read_opts_read_subcodes_audio(struct burn_read_opts *opts,
570 					int subcodes_audio)
571 {
572 	opts->subcodes_audio = subcodes_audio;
573 }
574 
burn_read_opts_read_subcodes_data(struct burn_read_opts * opts,int subcodes_data)575 void burn_read_opts_read_subcodes_data(struct burn_read_opts *opts,
576 				       int subcodes_data)
577 {
578 	opts->subcodes_data = subcodes_data;
579 }
580 
burn_read_opts_set_hardware_error_recovery(struct burn_read_opts * opts,int hardware_error_recovery)581 void burn_read_opts_set_hardware_error_recovery(struct burn_read_opts *opts,
582 						int hardware_error_recovery)
583 {
584 	opts->hardware_error_recovery = hardware_error_recovery;
585 }
586 
burn_read_opts_report_recovered_errors(struct burn_read_opts * opts,int report_recovered_errors)587 void burn_read_opts_report_recovered_errors(struct burn_read_opts *opts,
588 					    int report_recovered_errors)
589 {
590 	opts->report_recovered_errors = report_recovered_errors;
591 }
592 
burn_read_opts_transfer_damaged_blocks(struct burn_read_opts * opts,int transfer_damaged_blocks)593 void burn_read_opts_transfer_damaged_blocks(struct burn_read_opts *opts,
594 					    int transfer_damaged_blocks)
595 {
596 	opts->transfer_damaged_blocks = transfer_damaged_blocks;
597 }
598 
burn_read_opts_set_hardware_error_retries(struct burn_read_opts * opts,unsigned char hardware_error_retries)599 void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
600 					       unsigned char
601 					       hardware_error_retries)
602 {
603 	opts->hardware_error_retries = hardware_error_retries;
604 }
605 
606