/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ #include #include #include #include #include #include #include #include "sector.h" #include "libburn.h" #include "drive.h" #include "transport.h" #include "message.h" #include "crc.h" #include "debug.h" #include "init.h" #include "lec.h" #include "toc.h" #include "util.h" #include "sg.h" #include "read.h" #include "options.h" void burn_disc_read(struct burn_drive *d, const struct burn_read_opts *o) { #if 0 int i, end, maxsects, finish; int seclen; int drive_lba; unsigned short crc; unsigned char fakesub[96]; struct buffer page; int speed; assert((o->version & 0xfffff000) == (OPTIONS_VERSION & 0xfffff000)); assert(!d->busy); assert(d->toc->valid); assert(o->datafd != -1); /* XXX not sure this is a good idea. copy it? */ /* XXX also, we have duplicated data now, do we remove the fds from struct drive, or only store a subset of the _opts structs in drives */ /* set the speed on the drive */ speed = o->speed > 0 ? o->speed : d->mdata->max_read_speed; d->set_speed(d, speed, 0); d->params.retries = o->hardware_error_retries; d->send_parameters(d, o); d->cancel = 0; d->busy = BURN_DRIVE_READING; d->currsession = 0; /* drive_lba = 232000; d->currtrack = 18; */ d->currtrack = 0; drive_lba = 0; /* XXX removal of this line obviously breaks * d->track_end = burn_track_end(d, d->currsession, d->currtrack);*/ printf("track ends at %d\n", d->track_end); page.sectors = 0; page.bytes = 0; if (o->subfd != -1) { memset(fakesub, 0xFF, 12); memset(fakesub + 12, 0, 84); fakesub[13] = 1; fakesub[14] = 1; fakesub[20] = 2; fakesub[12] = (d->toc->toc_entry[0].control << 4) + d->toc->toc_entry[0].adr; crc = crc_ccitt(fakesub + 12, 10); fakesub[22] = crc >> 8; fakesub[23] = crc & 0xFF; write(o->subfd, fakesub, 96); } while (1) { seclen = burn_sector_length_read(d, o); burn_print(12, "received %d blocks\n", page.sectors); for (i = 0; i < page.sectors; i++) { burn_packet_process(d, page.data + seclen * i, o); d->track_end--; drive_lba++; } if ((d->cancel) || (drive_lba == LAST_SESSION_END(d))) { burn_print(1, "finished or cancelled\n"); d->busy = BURN_DRIVE_IDLE; if (!d->cancel) d->toc->complete = 1; return; } /* XXX: removal of this line obviously breaks * end = burn_track_end(d, d->currsession, d->currtrack); */ if (drive_lba == end) { d->currtrack++; if (d->currtrack > d->toc->session[d->currsession].lasttrack) { d->currsession++; burn_print(12, "session switch to %d\n", d->currsession); burn_print(12, "skipping a lead out\n"); drive_lba = CURRENT_SESSION_START(d); burn_print(12, "new lba %d\n", drive_lba); /* XXX more of the same end = burn_track_end(d, d->currsession, d->currtrack); */ } burn_print(12, "track switch to %d\n", d->currtrack); } page.sectors = 0; page.bytes = 0; maxsects = BUFFER_SIZE / seclen; finish = end - drive_lba; d->track_end = finish; page.sectors = (finish < maxsects) ? finish : maxsects; printf("reading %d sectors from %d\n", page.sectors, drive_lba); d->read_sectors(d, drive_lba, page.sectors, o, &page); printf("Read %d\n", page.sectors); } #endif } int burn_sector_length_read(struct burn_drive *d, const struct burn_read_opts *o) { int dlen = 2352; int data; /*XXX how do we handle this crap now?*/ /* data = d->toc->track[d->currtrack].toc_entry->control & 4;*/ data = 1; if (o->report_recovered_errors) dlen += 294; if ((o->subcodes_data) && data) dlen += 96; if ((o->subcodes_audio) && !data) dlen += 96; return dlen; } static int bitcount(unsigned char *data, int n) { int i, j, count = 0; unsigned char tem; for (i = 0; i < n; i++) { tem = data[i]; for (j = 0; j < 8; j++) { count += tem & 1; tem >>= 1; } } return count; } void burn_packet_process(struct burn_drive *d, unsigned char *data, const struct burn_read_opts *o) { unsigned char sub[96]; unsigned short crc; int ptr = 2352, i, j, code, fb; int audio = 1; if (o->c2errors) { fb = bitcount(data + ptr, 294); if (fb) { burn_print(1, "%d damaged bits\n", bitcount(data + ptr, 294)); burn_print(1, "sending error on %s %s\n", d->idata->vendor, d->idata->product); /* XXX send a burn_message! burn_message_error(d, something); */ } ptr += 294; } /* if (d->toc->track[d->currtrack].mode == BURN_MODE_UNINITIALIZED) { if ((d->toc->track[d->currtrack].toc_entry->control & 4) == 0) d->toc->track[d->currtrack].mode = BURN_MODE_AUDIO; else switch (data[15]) { case 0: d->toc->track[d->currtrack].mode = BURN_MODE0; break; case 1: d->toc->track[d->currtrack].mode = BURN_MODE1; break; case 2: d->toc->track[d->currtrack].mode = BURN_MODE2_FORMLESS; break; } } */ if ((audio && o->subcodes_audio) || (!audio && o->subcodes_data)) { memset(sub, 0, sizeof(sub)); for (i = 0; i < 12; i++) { for (j = 0; j < 8; j++) { for (code = 0; code < 8; code++) { sub[code * 12 + i] <<= 1; if (data[ptr + j + i * 8] & (1 << (7 - code))) sub[code * 12 + i]++; } } } crc = (*(sub + 22) << 8) + *(sub + 23); if (crc != crc_ccitt(sub + 12, 10)) { burn_print(1, "sending error on %s %s\n", d->idata->vendor, d->idata->product); /* e = burn_error(); e->drive = d; */ burn_print(1, "crc mismatch in Q\n"); } /* else process_q(d, sub + 12); */ /* if (o->subfd != -1) write(o->subfd, sub, 96); */ } /* if ((d->track_end <= 150) && (drive_lba + 150 < CURRENT_SESSION_END(d)) && (TOC_ENTRY(d->toc, d->currtrack).control == 4) && (TOC_ENTRY(d->toc, d->currtrack + 1).control == 0)) { burn_print(12, "pregap : %d\n", d->track_end); write(o->binfd, zeros, 2352); #warning XXX WHERE ARE MY SUBCODES } else *//* write(o->datafd, data, 2352); */ } /* so yeah, when you uncomment these, make them write zeros insted of crap static void write_empty_sector(int fd) { char sec[2352]; burn_print(1, "writing an 'empty' sector\n"); write(fd, sec, 2352); } static void write_empty_subcode(int fd) { char sub[96]; write(fd, sub, 96); } static void flipq(unsigned char *sub) { *(sub + 12 + 10) = ~*(sub + 12 + 10); *(sub + 12 + 11) = ~*(sub + 12 + 11); } */