udftools

- Main Page
- Classes
- Files

- File List
- File Members

All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cdrwtool.c
Go to the documentation of this file.
1 /*
2 * cdrwtool - perform all sort of actions on a CD-R, CD-RW, and DVD-R drive.
3 *
4 * Copyright (c) 1999,2000 Jens Axboe <axboe@suse.de>
5 * Copyright (c) 2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
23 #include "config.h"
24
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <getopt.h>
31 #include <signal.h>
32 #include <limits.h>
33
34 #include <sys/ioctl.h>
35 #include <asm/param.h>
36
37 #include <linux/cdrom.h>
38
39 #include "cdrwtool.h"
40 #include "../mkudffs/mkudffs.h"
41
42 static int progress;
43
44 int msf_to_lba(int m, int s, int f)
45 {
46 return (((m * 60) + s) * 75) + f;
47 }
48
49 void hexdump(const void *buffer, int size)
50 {
51 unsigned char *ptr = (unsigned char *) buffer;
52 int i;
53
54 for (i = 0; i < size; i++)
55 printf("%02x ", ptr[i]);
56 printf("\n");
57 }
58
59 void dump_sense(unsigned char *cdb, struct request_sense *sense)
60 {
61 int i;
62
63 printf("Command failed: ");
64
65 for (i=0; i<12; i++)
66 printf("%02x ", cdb[i]);
67
68 if (sense) {
69 printf("- sense %02x.%02x.%02x\n", sense->sense_key, sense->asc,
70 sense->ascq);
71 } else {
72 printf(", no sense\n");
73 }
74 }
75
76 int wait_cmd(int fd, struct cdrom_generic_command *cgc, unsigned char *buf,
77 int dir, int timeout)
78 {
79 struct request_sense sense;
80 int ret;
81
82 if (cgc->timeout <= 0)
83 cgc->timeout = 500;
84
85 memset(&sense, 0, sizeof(sense));
86
87 cgc->buffer = buf;
88 cgc->data_direction = dir;
89 cgc->sense = &sense;
90 cgc->timeout = timeout;
91
92 ret = ioctl(fd, CDROM_SEND_PACKET, cgc);
93 if (ret)
94 {
95 perror("wait_cmd");
96 dump_sense(cgc->cmd, cgc->sense);
97 }
98 return ret;
99 }
100
101 int sigfd;
102
103 void sig_progress(int sig)
104 {
105 struct cdrom_generic_command cgc;
106 struct request_sense sense;
107 static int did = 0;
108 int ret;
109
110 memset(&cgc, 0, sizeof(cgc));
111 memset(&sense, 0, sizeof(sense));
112
113 cgc.sense = &sense;
114 ret = wait_cmd(sigfd, &cgc, NULL, CGC_DATA_NONE, WAIT_PC);
115
116 if ((ret || !(sense.sks[0] & 0x80)) && !did) {
117 printf("Progress indicator not implemented on this drive\n");
118 printf("Don't access drive until operation has completed\n");
119 progress = 101;
120 return;
121 }
122
123 progress = ((sense.sks[1] << 8 | sense.sks[2]) * 100) / 0xffff;
124 did = 1;
125
126 printf("%02d%% complete\n", progress);
127 if (progress == 99) {
128 progress = 101;
129 return;
130 }
131 alarm(2);
132 }
133
134 void print_completion_info(int fd)
135 {
136 sigfd = fd;
137 /* we can only poll sense for non-blocking commands */
138 #if USE_IMMED == 0
139 return;
140 #else
141 progress = 0;
142 signal(SIGALRM, sig_progress);
143 alarm(5);
144 while (progress < 100)
145 sleep(1);
146 #endif
147 }
148
149 /* buffer must already have been filled by mode_sense */
150 int mode_select(int fd, unsigned char *buffer, int len)
151 {
152 struct cdrom_generic_command cgc;
153
154 memset(&cgc, 0, sizeof(cgc));
155 memset(buffer, 0, 3);
156 cgc.cmd[0] = GPCMD_MODE_SELECT_10;
157 cgc.cmd[1] = 1 << 4;
158 cgc.cmd[8] = cgc.buflen = len;
159
160 return wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_PC);
161 }
162
163 int mode_sense(int fd, unsigned char *buffer, int page, char pc, int size)
164 {
165 struct cdrom_generic_command cgc;
166
167 memset(&cgc, 0, sizeof(cgc));
168 cgc.cmd[0] = GPCMD_MODE_SENSE_10;
169 // cgc.cmd[1] = 1 << 4;
170 cgc.cmd[2] = page | pc << 6;
171 cgc.cmd[8] = cgc.buflen = size;
172
173 return wait_cmd(fd, &cgc, buffer, CGC_DATA_READ, WAIT_PC);
174 }
175
176 int set_write_mode(int fd, write_params_t *w)
177 {
178 unsigned char header[0x10];
179 unsigned char *buffer;
180 int ret, len, offset;
181
182 memset(header, 0x00, sizeof(header));
183
184 len = 0x10;
185
186 if ((ret = mode_sense(fd, header, GPMODE_WRITE_PARMS_PAGE,
187 PAGE_DEFAULT, len)) < 0)
188 {
189 perror("mode_sense_write");
190 return ret;
191 }
192
193 len = 2 + (((header[0] & 0xff) << 8) | (header[1] & 0xff));
194 offset = 8 + (((header[6] & 0xff) << 8) | (header[7] & 0xff));
195 buffer = calloc(len, sizeof(unsigned char));
196
197 if ((len <= offset+13) || (w->data_block == 10 && len <= offset+51))
198 {
199 perror("mode_sense_write");
200 free(buffer);
201 return ret;
202 }
203
204 if ((ret = mode_sense(fd, buffer, GPMODE_WRITE_PARMS_PAGE,
205 PAGE_DEFAULT, len)) < 0)
206 {
207 perror("mode_sense_write");
208 free(buffer);
209 return ret;
210 }
211
212
213 buffer[offset+2] = w->ls_v << 5;
214 buffer[offset+3] = w->track_mode | w->fpacket << 5 | w->border << 6;
215 buffer[offset+4] = w->data_block & 0xf;
216 buffer[offset+5] = w->link_size;
217 buffer[offset+8] = w->session_format & 0xff;
218 buffer[offset+10] = (w->packet_size >> 24) & 0xff;
219 buffer[offset+11] = (w->packet_size >> 16) & 0xff;
220 buffer[offset+12] = (w->packet_size >> 8) & 0xff;
221 buffer[offset+13] = w->packet_size & 0xff;
222 /* sub-header is only a mode-2 thing */
223 if (w->data_block == 10)
224 {
225 buffer[offset+48] = 0x00;
226 buffer[offset+49] = 0x00;
227 buffer[offset+50] = 0x08;
228 buffer[offset+51] = 0x00;
229 }
230
231 if ((ret = mode_select(fd, buffer, len)) < 0) {
232 hexdump(buffer, len);
233 free(buffer);
234 perror("mode_select");
235 return ret;
236 }
237
238 free(buffer);
239 return 0;
240 }
241
242 int get_write_mode(int fd, write_params_t *w)
243 {
244 unsigned char header[0x10];
245 unsigned char *buffer;
246 int ret, len, offset;
247
248 memset(header, 0x00, sizeof(header));
249
250 len = 0x10;
251
252 if ((ret = mode_sense(fd, header, GPMODE_WRITE_PARMS_PAGE,
253 PAGE_CURRENT, len)) < 0)
254 {
255 perror("mode_sense_write");
256 return ret;
257 }
258
259 len = 2 + (((header[0] & 0xff) << 8) | (header[1] & 0xff));
260 offset = 8 + (((header[6] & 0xff) << 8) | (header[7] & 0xff));
261 buffer = calloc(len, sizeof(unsigned char));
262
263 if (len <= offset+13)
264 {
265 perror("mode_sense_write");
266 free(buffer);
267 return ret;
268 }
269
270 if ((ret = mode_sense(fd, buffer, GPMODE_WRITE_PARMS_PAGE,
271 PAGE_CURRENT, len)) < 0)
272 {
273 perror("mode_sense_write");
274 free(buffer);
275 return ret;
276 }
277
278 w->ls_v = (buffer[offset+2] >> 5) & 1;
279 w->border = (buffer[offset+3] >> 6) & 3;
280 w->fpacket = (buffer[offset+3] >> 5) & 1;
281 w->track_mode = buffer[offset+3] & 0xf;
282 w->data_block = buffer[offset+4] & 0xf;
283 w->link_size = buffer[offset+5];
284 w->session_format = buffer[offset+8];
285 w->packet_size = buffer[offset+13];
286
287 free(buffer);
288
289 return 0;
290 }
291
292 int sync_cache(int fd)
293 {
294 struct cdrom_generic_command cgc;
295
296 memset(&cgc, 0, sizeof(cgc));
297 cgc.cmd[0] = 0x35;
298 cgc.cmd[1] = 2;
299 return wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_SYNC);
300 }
301
302 int write_blocks(int fd, unsigned char *buffer, int lba, int blocks)
303 {
304 struct cdrom_generic_command cgc;
305
306 memset(&cgc, 0, sizeof(cgc));
307
308 cgc.cmd[0] = GPCMD_WRITE_10;
309 #if 0
310 cgc.cmd[1] = 1 << 3;
311 #endif
312 cgc.cmd[2] = (lba >> 24) & 0xff;
313 cgc.cmd[3] = (lba >> 16) & 0xff;
314 cgc.cmd[4] = (lba >> 8) & 0xff;
315 cgc.cmd[5] = lba & 0xff;
316 cgc.cmd[7] = (blocks >> 8) & 0xff;
317 cgc.cmd[8] = blocks & 0xff;
318 cgc.buflen = blocks * CDROM_BLOCK;
319
320 return wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_SYNC);
321 }
322
323 int write_file(int fd, struct cdrw_disc *disc)
324 {
325 int file, lba, size, blocks;
326 unsigned char *buf = NULL;
327 int ret = 0, go_on = 1;
328
329 if ((file = open(disc->filename, O_RDONLY)) < 0) {
330 fprintf(stderr, "can't open %s\n", disc->filename);
331 return 1;
332 }
333
334 /* for fixed packets, the write size is set. variable packets,
335 * we write a little less than the buffer capacity. the drive
336 * probably uses some of this for internal housekeeping, and
337 * we want to completely eliminate buffer underruns.
338 */
339 size = disc->fpacket ? disc->packet_size * CDROM_BLOCK : 63 * CDROM_BLOCK;
340 lba = disc->offset;
341
342 buf = (unsigned char *) malloc(size+1);
343 if (buf == NULL) {
344 perror("malloc");
345 close(file);
346 return 1;
347 }
348
349 while (!ret && go_on) {
350 blocks = disc->fpacket ? disc->packet_size : size / CDROM_BLOCK;
351 ret = read(file, buf, size);
352 if (ret == -1) {
353 perror("read from file");
354 break;
355 } else if (ret < size) {
356 /* not enough data to complete the packet. fill
357 * the rest of the data block with zeros. we must
358 * write out complete packets every time with
359 * fixed packets. for variable packets we just
360 * write what we have left.
361 */
362 if (disc->fpacket) {
363 memset(&buf[ret], 0, size - ret - 1);
364 } else {
365 blocks = (ret + CDROM_BLOCK - 1) / CDROM_BLOCK;
366 }
367 /* regardless of type, this is the last write */
368 go_on = 0;
369 }
370
371 fprintf(stdout, "writing at lba = %d, blocks = %d\n", lba, blocks);
372 if ((ret = write_blocks(fd, buf, lba, blocks)))
373 break;
374
375 /* sync to indicate that one packet has been sent */
376 // sync_cache(fd);
377
378 /* for fixed packets, the run-in/run-out blocks are
379 * contained within the packet size. variable packets
380 * don't count them as part of the written size.
381 */
382 lba += blocks;
383 // lba += disc->fpacket ? 0 : 7;
384 }
385 sync_cache(fd);
386
387 close(file);
388 free(buf);
389 return ret;
390 }
391
392 int blank_disc(int fd, int type)
393 {
394 struct cdrom_generic_command cgc;
395 int ret;
396
397 memset(&cgc, 0, sizeof(cgc));
398 cgc.cmd[0] = GPCMD_BLANK;
399 cgc.cmd[1] = (type == BLANK_FULL ? 0 : 1);
400 cgc.cmd[1] |= (USE_IMMED << 4);
401
402 if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0)
403 {
404 perror("blank disc");
405 return ret;
406 }
407
408 print_completion_info(fd);
409 return 0;
410 }
411
412 int format_disc(int fd, struct cdrw_disc *disc)
413 {
414 struct cdrom_generic_command cgc;
415 unsigned char buffer[16];
416 int ret;
417
418 memset(&cgc, 0, sizeof(cgc));
419 memset(buffer, 0, sizeof(buffer));
420
421 cgc.cmd[0] = GPCMD_FORMAT_UNIT;
422 cgc.cmd[1] = 1 << 4 | 7;
423 cgc.buflen = 16;
424
425 /* format list header */
426 buffer[0] = 0;
427 buffer[1] = 0; /* FOV: 0 (use defaults) */
428 buffer[1] |= (USE_IMMED << 1);
429 buffer[2] = 0;
430 buffer[3] = 8;
431
432 /* bytes 4 through 7 are the initialization pattern, which
433 * we just ignore. no use for CD-RW drives.
434 */
435
436 /* format descriptor */
437 buffer[8] = 0x00; /* session and grow bits (7 and 6) */
438 buffer[9] = 0;
439 buffer[10] = 0;
440 buffer[11] = 0;
441 buffer[12] = (disc->offset >> 24) & 0xff;
442 buffer[13] = (disc->offset >> 16) & 0xff;
443 buffer[14] = (disc->offset >> 8) & 0xff;
444 buffer[15] = disc->offset & 0xff;
445
446 if ((ret = wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_BLANK)) < 0)
447 {
448 perror("format disc");
449 return ret;
450 }
451
452 print_completion_info(fd);
453 return 0;
454 }
455
456 int read_disc_info(int fd, disc_info_t *di)
457 {
458 struct cdrom_generic_command cgc;
459 int ret;
460
461 memset(&cgc, 0, sizeof(cgc));
462 memset(di, 0, sizeof(disc_info_t));
463 cgc.cmd[0] = GPCMD_READ_DISC_INFO;
464 cgc.cmd[8] = cgc.buflen = 2;
465
466 if ((ret = wait_cmd(fd, &cgc, (unsigned char *)di, CGC_DATA_READ, WAIT_PC)) < 0)
467 {
468 perror("read disc info");
469 return ret;
470 }
471 cgc.buflen = be16_to_cpu(di->length) + sizeof(di->length);
472
473 if (cgc.buflen > sizeof(disc_info_t))
474 cgc.buflen = sizeof(disc_info_t);
475
476 cgc.cmd[8] = cgc.buflen;
477 if ((ret = wait_cmd(fd, &cgc, (unsigned char *)di, CGC_DATA_READ, WAIT_PC)) < 0)
478 {
479 perror("read disc info");
480 return ret;
481 }
482
483 return 0;
484 }
485
486 int read_track_info(int fd, track_info_t *ti, int trackno)
487 {
488 struct cdrom_generic_command cgc;
489 int ret;
490
491 memset(&cgc, 0, sizeof(cgc));
492 memset(ti, 0, sizeof(track_info_t));
493 cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
494 cgc.cmd[1] = 1;
495 cgc.cmd[5] = trackno;
496 cgc.cmd[8] = cgc.buflen = 28;
497
498 if ((ret = wait_cmd(fd, &cgc, (unsigned char *) ti, CGC_DATA_READ, WAIT_PC)) < 0)
499 {
500 perror("read track info");
501 return ret;
502 }
503
504 return 0;
505 }
506
507 int reserve_track(int fd, struct cdrw_disc *disc)
508 {
509 struct cdrom_generic_command cgc;
510 int ret;
511
512 memset(&cgc, 0, sizeof(cgc));
513 cgc.cmd[0] = GPCMD_RESERVE_RZONE_TRACK;
514 cgc.cmd[5] = (disc->reserve_track >> 24) & 0xff;
515 cgc.cmd[6] = (disc->reserve_track >> 16) & 0xff;
516 cgc.cmd[7] = (disc->reserve_track >> 8) & 0xff;
517 cgc.cmd[8] = disc->reserve_track & 0xff;
518
519 if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0)
520 {
521 perror("reserve track");
522 return ret;
523 }
524
525 return 0;
526 }
527
528 int close_track(int fd, unsigned int track)
529 {
530 struct cdrom_generic_command cgc;
531 int ret;
532
533 memset(&cgc, 0, sizeof(cgc));
534 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
535 cgc.cmd[1] = USE_IMMED;
536 cgc.cmd[2] = 1; /* bit 2 is close session/border */
537 cgc.cmd[4] = (track >> 8) & 0xff;
538 cgc.cmd[5] = track & 0xff;
539
540 if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0)
541 {
542 perror("close track");
543 return ret;
544 }
545 print_completion_info(fd);
546 return 0;
547 }
548
549 int close_session(int fd, unsigned int track)
550 {
551 struct cdrom_generic_command cgc;
552 int ret;
553
554 memset(&cgc, 0, sizeof(cgc));
555 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
556 cgc.cmd[1] = USE_IMMED;
557 cgc.cmd[2] = 2; /* bit 2 is close session/border */
558 cgc.cmd[4] = (track >> 8) & 0xff;
559 cgc.cmd[5] = track & 0xff;
560
561 if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0)
562 {
563 perror("close session");
564 return ret;
565 }
566 print_completion_info(fd);
567 return 0;
568 }
569
570 int read_buffer_cap(int fd, struct cdrw_disc *disc)
571 {
572 struct cdrom_generic_command cgc;
573 struct {
574 unsigned int pad;
575 unsigned int buffer_size;
576 unsigned int buffer_free;
577 } __attribute((packed)) buf;
578 int ret;
579
580 memset(&cgc, 0, sizeof(cgc));
581 memset(&buf, 0, sizeof(buf));
582 cgc.cmd[0] = 0x5c;
583 cgc.cmd[8] = cgc.buflen = 12;
584
585 if ((ret = wait_cmd(fd, &cgc, (unsigned char *)&buf, CGC_DATA_READ, WAIT_PC)))
586 return ret;
587
588 disc->buffer = be32_to_cpu(buf.buffer_size);
589
590 printf("%uKB internal buffer\n", disc->buffer >> 10);
591 return 0;
592 }
593
594 int set_cd_speed(int fd, int speed)
595 {
596 struct cdrom_generic_command cgc;
597
598 printf("setting write speed to %ux\n", speed);
599
600 memset(&cgc, 0, sizeof(cgc));
601 cgc.cmd[0] = 0xbb;
602
603 /* read speed */
604 cgc.cmd[2] = 0xff;
605 cgc.cmd[3] = 0xff;
606
607 /* write speed */
608 cgc.cmd[4] = ((0xb0 * speed) >> 8) & 0xff;
609 cgc.cmd[5] = (0xb0 * speed) & 0xff;
610
611 return wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_PC);
612 }
613
614 void cdrom_close(int fd)
615 {
616 /* enable locking */
617 if (ioctl(fd, CDROM_LOCKDOOR, 0) < 0)
618 printf("can't unlock door\n");
619
620 ioctl(fd, CDROM_SET_OPTIONS, CDO_LOCK);
621 }
622
623 int cdrom_open_check(int fd)
624 {
625 int ret, attempts = 3;
626
627 while (--attempts) {
628 ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
629 if (ret < 0)
630 return ret;
631 if (ret == CDS_DISC_OK)
632 break;
633 }
634
635 if (attempts == 0)
636 return 1;
637
638 /* drive should now be ready. check media */
639 ret = ioctl(fd, CDROM_DISC_STATUS);
640 if (ret == CDS_AUDIO || ret < 0)
641 return 1;
642
643 /* disable locking */
644 if ((ret = ioctl(fd, CDROM_CLEAR_OPTIONS, CDO_LOCK)) < 0)
645 return ret;
646
647 if ((ret = ioctl(fd, CDROM_LOCKDOOR, 1)) < 0) {
648 fprintf(stderr, "CD-ROM appears to already be opened\n");
649 return 1;
650 }
651
652 return 0;
653 }
654
655 void print_disc_info(disc_info_t *di)
656 {
657 printf("\terasable : %s\n", di->erasable ? "Yes" : "No");
658 printf("\tborder = %d\n", di->border);
659 printf("\tDisc status = %d\n", di->status);
660 printf("\tnumber of first track = %d\n", di->n_first_track);
661 printf("\tnumber of sessions = %d\n", (di->n_sessions_m << 8) | di->n_sessions_l);
662 printf("\tnumber of tracks = %d\n", (di->first_track_m << 8) | di->first_track_l);
663 printf("\tstatus of last track = %d\n", (di->last_track_m << 8) | di->last_track_l);
664 printf("\turu = %d\n", di->uru);
665 printf("\tdid_v = %d\n", di->did_v);
666 printf("\tdbc_v = %d\n", di->dbc_v);
667 printf("\tdisc type = %d\n", di->disc_type);
668 printf("\tdisc_id = %u\n", be32_to_cpu(di->disc_id));
669 printf("\tlead_in = %02d:%02d:%02d (%u)\n",
670 di->lead_in_m,
671 di->lead_in_s,
672 di->lead_in_f,
673 msf_to_lba(di->lead_in_m, di->lead_in_s, di->lead_in_f));
674 printf("\tlead_out = %02d:%02d:%02d (%u)\n",
675 di->lead_out_m,
676 di->lead_out_s,
677 di->lead_out_f,
678 msf_to_lba(di->lead_out_m, di->lead_out_s, di->lead_out_f));
679 printf("\tOPC entries = %u\n", di->opc_entries);
680 printf("\n");
681 }
682
683 void print_track_info(track_info_t *ti)
684 {
685 printf("\ttrack_number = %d\n", (ti->track_number_m << 8) | ti->track_number_l);
686 printf("\tsession_number = %d\n", (ti->session_number_m << 8) | ti->session_number_l);
687 printf("\tdamage = %d\n", ti->damage);
688 printf("\tcopy = %d\n", ti->copy);
689 printf("\ttrack_mode = %d\n", ti->track_mode);
690 printf("\tRt = %d\n", ti->rt);
691 printf("\tblank = %d\n", ti->blank);
692 printf("\tpacket = %d\n", ti->packet);
693 printf("\tfp = %d\n", ti->fp);
694 printf("\tdata_mode = %d\n", ti->data_mode);
695 printf("\tlra_v = %d\n", ti->lra_v);
696 printf("\tnwa_v = %d\n", ti->nwa_v);
697 printf("\ttrack_start = %u\n", be32_to_cpu(ti->track_start));
698 printf("\tnext_writable = %u\n", be32_to_cpu(ti->next_writable));
699 printf("\tlast_recorded = %u\n", be32_to_cpu(ti->last_recorded));
700 printf("\tfree_blocks = %u\n", be32_to_cpu(ti->free_blocks));
701 printf("\tpacket_size = %u\n", be32_to_cpu(ti->packet_size));
702 printf("\ttrack_size = %u (%uKB)\n", be32_to_cpu(ti->track_size),
703 be32_to_cpu(ti->track_size) * 2);
704 }
705
706 int print_disc_track_info(int fd)
707 {
708 int ret, i;
709 track_info_t ti;
710 disc_info_t di;
711
712 memset(&di, 0, sizeof(disc_info_t));
713 memset(&ti, 0, sizeof(track_info_t));
714
715 if ((ret = read_disc_info(fd, &di)) < 0)
716 return ret;
717
718 printf("\nDISC INFO:\n");
719 print_disc_info(&di);
720
721
722 /* Assumes no more than 256 tracks ;) */
723 printf("TRACK INFO:\n");
724 for (i = di.n_first_track; i <= di.last_track_l; i++) {
725 if ((ret = read_track_info(fd, &ti, i)) < 0)
726 return ret;
727 printf("\nTrack %d\n", i);
728 print_track_info(&ti);
729 }
730
731 return 0;
732 }
733
734 void make_write_page(write_params_t *w, struct cdrw_disc *disc)
735 {
736 switch (disc->write_type)
737 {
738 case WRITE_MODE1:
739 {
740 w->data_block = 0x8;
741 w->session_format = 0x00;
742 break;
743 }
744 case WRITE_MODE2:
745 {
746 w->data_block = 0xa;
747 w->session_format = 0x20;
748 break;
749 }
750 }
751
752 w->packet_size = disc->packet_size;
753 w->fpacket = disc->fpacket;
754 w->link_size = disc->link_size;
755 w->border = disc->border;
756 w->track_mode = w->track_mode | 0x3;
757 }
758
759 void print_params(write_params_t *wp)
760 {
761 fprintf(stdout, "writing %s packets\n", wp->fpacket ? "fixed" : "variable");
762 fprintf(stdout, "border type\t: %d\n", wp->border);
763 fprintf(stdout, "track mode\t: %d\n", wp->track_mode);
764 fprintf(stdout, "data block type\t: %d\n", wp->data_block);
765 fprintf(stdout, "session format\t: %d\n", wp->session_format);
766 fprintf(stdout, "packet size\t: %lu\n", wp->packet_size);
767 }
768
769 void cdrw_init_disc(struct cdrw_disc *disc)
770 {
771 disc->fpacket = 1;
772 disc->packet_size = PACKET_BLOCK;
773 disc->write_type = WRITE_MODE2;
774 disc->speed = DEFAULT_SPEED;
775 }
cdrw_disc::border
unsigned char border
Definition: cdrwtool.h:87
track_info::track_number_m
uint8_t track_number_m
Definition: cdrwtool.h:200
track_info::damage
uint8_t damage
Definition: cdrwtool.h:169
track_info::track_start
uint32_t track_start
Definition: cdrwtool.h:194
disc_info::last_track_l
uint8_t last_track_l
Definition: cdrwtool.h:132
write_blocks
int write_blocks(int fd, unsigned char *buffer, int lba, int blocks)
Definition: cdrwtool.c:302
disc_info::lead_out_m
uint8_t lead_out_m
Definition: cdrwtool.h:154
PACKET_BLOCK
#define PACKET_BLOCK
Definition: cdrwtool.h:53
close_track
int close_track(int fd, unsigned int track)
Definition: cdrwtool.c:528
read_track_info
int read_track_info(int fd, track_info_t *ti, int trackno)
Definition: cdrwtool.c:486
be32_to_cpu
#define be32_to_cpu(x)
Definition: cdrwtool.h:106
cdrw_disc
Definition: cdrwtool.h:74
disc_info::disc_type
uint8_t disc_type
Definition: cdrwtool.h:144
USE_IMMED
#define USE_IMMED
Definition: cdrwtool.h:39
track_info::data_mode
uint8_t data_mode
Definition: cdrwtool.h:176
progress
static int progress
Definition: cdrwtool.c:42
WAIT_PC
#define WAIT_PC
Definition: cdrwtool.h:29
disc_info::lead_in_m
uint8_t lead_in_m
Definition: cdrwtool.h:150
track_info::track_mode
uint8_t track_mode
Definition: cdrwtool.h:171
wait_cmd
int wait_cmd(int fd, struct cdrom_generic_command *cgc, unsigned char *buf, int dir, int timeout)
Definition: cdrwtool.c:76
disc_info::disc_id
uint32_t disc_id
Definition: cdrwtool.h:148
write_params_t::fpacket
unsigned char fpacket
Definition: cdrwtool.h:66
disc_info::erasable
unsigned char erasable
Definition: cdrwtool.h:118
disc_info::length
uint16_t length
Definition: cdrwtool.h:115
cdrw_disc::reserve_track
unsigned int reserve_track
Definition: cdrwtool.h:90
disc_info::first_track_m
uint8_t first_track_m
Definition: cdrwtool.h:146
disc_info::first_track_l
uint8_t first_track_l
Definition: cdrwtool.h:131
PAGE_CURRENT
#define PAGE_CURRENT
Definition: cdrwtool.h:41
write_params_t::ls_v
unsigned char ls_v
Definition: cdrwtool.h:64
cdrw_disc::buffer
unsigned int buffer
Definition: cdrwtool.h:89
print_disc_info
void print_disc_info(disc_info_t *di)
Definition: cdrwtool.c:655
dump_sense
void dump_sense(unsigned char *cdb, struct request_sense *sense)
Definition: cdrwtool.c:59
read_disc_info
int read_disc_info(int fd, disc_info_t *di)
Definition: cdrwtool.c:456
read_buffer_cap
int read_buffer_cap(int fd, struct cdrw_disc *disc)
Definition: cdrwtool.c:570
cdrw_disc::offset
unsigned long offset
Definition: cdrwtool.h:77
mode_sense
int mode_sense(int fd, unsigned char *buffer, int page, char pc, int size)
Definition: cdrwtool.c:163
msf_to_lba
int msf_to_lba(int m, int s, int f)
Definition: cdrwtool.c:44
WAIT_BLANK
#define WAIT_BLANK
Definition: cdrwtool.h:31
cdrom_open_check
int cdrom_open_check(int fd)
Definition: cdrwtool.c:623
write_params_t::data_block
unsigned char data_block
Definition: cdrwtool.h:68
track_info::next_writable
uint32_t next_writable
Definition: cdrwtool.h:195
cdrw_disc::packet_size
unsigned char packet_size
Definition: cdrwtool.h:82
track_info::session_number_m
uint8_t session_number_m
Definition: cdrwtool.h:201
cdrw_disc::speed
unsigned char speed
Definition: cdrwtool.h:88
print_disc_track_info
int print_disc_track_info(int fd)
Definition: cdrwtool.c:706
track_info::nwa_v
uint8_t nwa_v
Definition: cdrwtool.h:179
cdrw_init_disc
void cdrw_init_disc(struct cdrw_disc *disc)
Definition: cdrwtool.c:769
sigfd
int sigfd
Definition: cdrwtool.c:101
print_completion_info
void print_completion_info(int fd)
Definition: cdrwtool.c:134
disc_info
Definition: cdrwtool.h:114
disc_info::lead_out_f
uint8_t lead_out_f
Definition: cdrwtool.h:156
cdrw_disc::filename
char filename[NAME_MAX]
Definition: cdrwtool.h:76
cdrw_disc::write_type
unsigned char write_type
Definition: cdrwtool.h:84
disc_info::opc_entries
uint8_t opc_entries
Definition: cdrwtool.h:159
hexdump
void hexdump(const void *buffer, int size)
Definition: cdrwtool.c:49
blank_disc
int blank_disc(int fd, int type)
Definition: cdrwtool.c:392
track_info::packet
uint8_t packet
Definition: cdrwtool.h:174
disc_info::border
unsigned char border
Definition: cdrwtool.h:119
close_session
int close_session(int fd, unsigned int track)
Definition: cdrwtool.c:549
CDROM_BLOCK
#define CDROM_BLOCK
Definition: cdrwtool.h:52
sig_progress
void sig_progress(int sig)
Definition: cdrwtool.c:103
disc_info::status
unsigned char status
Definition: cdrwtool.h:120
PAGE_DEFAULT
#define PAGE_DEFAULT
Definition: cdrwtool.h:43
reserve_track
int reserve_track(int fd, struct cdrw_disc *disc)
Definition: cdrwtool.c:507
track_info::session_number_l
uint8_t session_number_l
Definition: cdrwtool.h:165
print_params
void print_params(write_params_t *wp)
Definition: cdrwtool.c:759
format_disc
int format_disc(int fd, struct cdrw_disc *disc)
Definition: cdrwtool.c:412
disc_info::n_first_track
uint8_t n_first_track
Definition: cdrwtool.h:129
write_params_t::packet_size
unsigned long packet_size
Definition: cdrwtool.h:71
track_info::rt
uint8_t rt
Definition: cdrwtool.h:172
track_info::track_number_l
uint8_t track_number_l
Definition: cdrwtool.h:164
write_params_t
Definition: cdrwtool.h:62
WAIT_SYNC
#define WAIT_SYNC
Definition: cdrwtool.h:30
disc_info::lead_in_f
uint8_t lead_in_f
Definition: cdrwtool.h:152
sync_cache
int sync_cache(int fd)
Definition: cdrwtool.c:292
cdrw_disc::fpacket
unsigned char fpacket
Definition: cdrwtool.h:81
track_info::blank
uint8_t blank
Definition: cdrwtool.h:173
cdrom_close
void cdrom_close(int fd)
Definition: cdrwtool.c:614
write_params_t::track_mode
unsigned char track_mode
Definition: cdrwtool.h:67
track_info::copy
uint8_t copy
Definition: cdrwtool.h:170
disc_info::n_sessions_m
uint8_t n_sessions_m
Definition: cdrwtool.h:145
track_info::track_size
uint32_t track_size
Definition: cdrwtool.h:198
be16_to_cpu
#define be16_to_cpu(x)
Definition: cdrwtool.h:99
disc_info::n_sessions_l
uint8_t n_sessions_l
Definition: cdrwtool.h:130
DEFAULT_SPEED
#define DEFAULT_SPEED
Definition: cdrwtool.h:60
track_info::last_recorded
uint32_t last_recorded
Definition: cdrwtool.h:199
disc_info::lead_in_s
uint8_t lead_in_s
Definition: cdrwtool.h:151
make_write_page
void make_write_page(write_params_t *w, struct cdrw_disc *disc)
Definition: cdrwtool.c:734
track_info::lra_v
uint8_t lra_v
Definition: cdrwtool.h:178
disc_info::dbc_v
unsigned char dbc_v
Definition: cdrwtool.h:135
get_write_mode
int get_write_mode(int fd, write_params_t *w)
Definition: cdrwtool.c:242
disc_info::did_v
unsigned char did_v
Definition: cdrwtool.h:134
set_write_mode
int set_write_mode(int fd, write_params_t *w)
Definition: cdrwtool.c:176
disc_info::lead_out_s
uint8_t lead_out_s
Definition: cdrwtool.h:155
set_cd_speed
int set_cd_speed(int fd, int speed)
Definition: cdrwtool.c:594
disc_info::uru
unsigned char uru
Definition: cdrwtool.h:136
print_track_info
void print_track_info(track_info_t *ti)
Definition: cdrwtool.c:683
write_params_t::border
unsigned char border
Definition: cdrwtool.h:65
track_info::free_blocks
uint32_t free_blocks
Definition: cdrwtool.h:196
write_params_t::link_size
unsigned char link_size
Definition: cdrwtool.h:69
track_info
Definition: cdrwtool.h:162
track_info::packet_size
uint32_t packet_size
Definition: cdrwtool.h:197
mode_select
int mode_select(int fd, unsigned char *buffer, int len)
Definition: cdrwtool.c:150
write_params_t::session_format
unsigned char session_format
Definition: cdrwtool.h:70
track_info::fp
uint8_t fp
Definition: cdrwtool.h:175
BLANK_FULL
#define BLANK_FULL
Definition: cdrwtool.h:46
cdrwtool.h
cdrw_disc::link_size
unsigned char link_size
Definition: cdrwtool.h:83
WRITE_MODE1
#define WRITE_MODE1
Definition: cdrwtool.h:49
WRITE_MODE2
#define WRITE_MODE2
Definition: cdrwtool.h:50
write_file
int write_file(int fd, struct cdrw_disc *disc)
Definition: cdrwtool.c:323
ti
struct cdrom_trackinfo ti
Definition: wrudf-cdrw.c:50
disc_info::last_track_m
uint8_t last_track_m
Definition: cdrwtool.h:147