"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/libburn/sector.c" (30 Jan 2021, 22872 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sector.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.5.2_vs_1.5.4.

    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 #include <stdio.h>
   13 
   14 /* ts A61010 */
   15 /* #include <a ssert.h> */
   16 
   17 #include <unistd.h>
   18 #include <string.h>
   19 #include "error.h"
   20 #include "options.h"
   21 #include "transport.h"
   22 #include "libburn.h"
   23 #include "drive.h"
   24 #include "sector.h"
   25 #include "crc.h"
   26 #include "debug.h"
   27 #include "toc.h"
   28 #include "write.h"
   29 
   30 #include "libdax_msgs.h"
   31 extern struct libdax_msgs *libdax_messenger;
   32 
   33 #include "ecma130ab.h"
   34 
   35 
   36 #ifdef Libburn_log_in_and_out_streaM
   37 /* ts A61031 */
   38 #include <sys/types.h>
   39 #include <sys/stat.h>
   40 #include <fcntl.h>
   41 #endif /* Libburn_log_in_and_out_streaM */
   42 
   43 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
   44 #ifndef O_BINARY
   45 #define O_BINARY 0
   46 #endif
   47 
   48 /*static unsigned char isrc[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";*/
   49 
   50 #define sector_common(X) d->alba++; d->rlba X;
   51 
   52 static void uncook_subs(unsigned char *dest, unsigned char *source)
   53 {
   54     int i, j, code;
   55 
   56     memset(dest, 0, 96);
   57 
   58     for (i = 0; i < 12; i++) {
   59         for (j = 0; j < 8; j++) {
   60             for (code = 0; code < 8; code++) {
   61                 if (source[code * 12 + i] & 0x80)
   62                     dest[j + i * 8] |= (1 << (7 - code));
   63                 source[code * 12 + i] <<= 1;
   64             }
   65         }
   66     }
   67 }
   68 
   69 /* @return >=0 : valid , <0 invalid */
   70 int sector_get_outmode(enum burn_write_types write_type,
   71             enum burn_block_types block_type)
   72 {
   73     /* ts A61103 : extended SAO condition to TAO */
   74     if (write_type == BURN_WRITE_SAO || write_type == BURN_WRITE_TAO)
   75         return 0;
   76     else
   77         switch (block_type) {
   78         case BURN_BLOCK_RAW0:
   79             return BURN_MODE_RAW;
   80         case BURN_BLOCK_RAW16:
   81             return BURN_MODE_RAW | BURN_SUBCODE_P16;
   82         case BURN_BLOCK_RAW96P:
   83             return BURN_MODE_RAW | BURN_SUBCODE_P96;
   84         case BURN_BLOCK_RAW96R:
   85             return BURN_MODE_RAW | BURN_SUBCODE_R96;
   86         case BURN_BLOCK_MODE1:
   87             return BURN_MODE1;
   88         default:
   89             return -1;
   90         }
   91 
   92     /* ts A61007 : now handled in burn_write_opts_set_write_type() */
   93     /* a ssert(0); */   /* return BURN_MODE_UNIMPLEMENTED :) */
   94 }
   95 
   96 /* 0 means "same as inmode" */
   97 static int get_outmode(struct burn_write_opts *o)
   98 {
   99     /* ts A61007 */
  100     return sector_get_outmode(o->write_type, o->block_type);
  101 
  102     /* -1 is prevented by check in burn_write_opts_set_write_type() */
  103     /* a ssert(0); */       /* return BURN_MODE_UNIMPLEMENTED :) */
  104 }
  105 
  106 
  107 static void get_bytes(struct burn_track *track, int count, unsigned char *data)
  108 {
  109     int valid, shortage, curr, i, tr;
  110 
  111 #ifdef Libburn_log_in_and_out_streaM 
  112         /* ts A61031 */
  113         static int tee_fd= -1;
  114         if(tee_fd==-1)
  115                 tee_fd= open("/tmp/libburn_sg_readin",
  116                 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
  117                 S_IRUSR | S_IWUSR);
  118 #endif /* Libburn_log_in_and_out_streaM */
  119 
  120 
  121 /* no track pointer means we're just generating 0s */
  122     if (!track) {
  123         memset(data, 0, count);
  124         return;
  125     }
  126 
  127 /* first we use up any offset */
  128     valid = track->offset - track->offsetcount;
  129     if (valid > count)
  130         valid = count;
  131 
  132     if (valid) {
  133         track->offsetcount += valid;
  134         memset(data, 0, valid);
  135     }
  136     shortage = count - valid;
  137 
  138     if (!shortage)
  139         goto ex;
  140 
  141 /* Next we use source data */
  142     curr = valid;
  143     if (!track->eos) {
  144         if (track->source->read != NULL)
  145             valid = track->source->read(track->source,
  146                         data + curr, count - curr);
  147         else
  148             valid = track->source->read_xt(track->source,
  149                         data + curr, count - curr);
  150     } else valid = 0;
  151 
  152     if (valid <= 0) { /* ts A61031 : extended from (valid == -1) */
  153         track->eos = 1;
  154         valid = 0;
  155     }
  156     track->sourcecount += valid;
  157 
  158 #ifdef Libburn_log_in_and_out_streaM
  159     /* ts A61031 */
  160         if(tee_fd!=-1 && valid>0) {
  161                 write(tee_fd, data + curr, valid);
  162         }
  163 #endif /* Libburn_log_in_and_out_streaM */
  164 
  165     curr += valid;
  166     shortage = count - curr;
  167 
  168     if (!shortage)
  169         goto ex;
  170 
  171 /* Before going to the next track, we run through any tail */
  172 
  173     valid = track->tail - track->tailcount;
  174     if (valid > count - curr)
  175         valid = count - curr;
  176 
  177     if (valid) {
  178         track->tailcount += valid;
  179         memset(data + curr, 0, valid);
  180     }
  181     curr += valid;
  182     shortage -= valid;
  183 
  184     if (!shortage)
  185         goto ex;
  186 
  187     /* ts A61031 - B10103 */
  188     if (shortage >= count)
  189         track->track_data_done = 1;
  190     if (track->end_on_premature_eoi && shortage >= count &&
  191         !track->open_ended) {
  192         char msg[80];
  193         off_t missing, inp_block_size, track_blocks;
  194 
  195         inp_block_size = burn_sector_length(track->mode);
  196         track_blocks = burn_track_get_sectors_2(track, 1);
  197         missing = track_blocks * inp_block_size - track->sourcecount;
  198         sprintf(msg,
  199               "Premature end of input encountered. Missing: %.f bytes",
  200               (double) missing);
  201         libdax_msgs_submit(libdax_messenger, -1, 0x00020180,
  202                 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
  203                 msg, 0,0);
  204         /* Memorize that premature end of input happened */
  205         track->end_on_premature_eoi = 2;
  206     }
  207     if (track->open_ended || track->end_on_premature_eoi)
  208         goto ex;
  209 
  210 /* If we're still short, and there's a "next" pointer, we pull from that.
  211    if that depletes, we'll just fill with 0s.
  212 */
  213     if (track->source->next) {
  214         struct burn_source *src;
  215         printf("pulling from next track\n");
  216         src = track->source->next;
  217         valid = src->read(src, data + curr, shortage);
  218         if (valid > 0) {
  219             shortage -= valid;
  220             curr += valid;
  221         }
  222     }
  223 ex:;
  224     /* ts A61024 : general finalizing processing */ 
  225     if(shortage)
  226         memset(data + curr, 0, shortage); /* this is old icculus.org */
  227     if (track->swap_source_bytes == 1) {
  228         for (i = 1; i < count; i += 2) {
  229             tr = data[i];
  230             data[i] = data[i-1];
  231             data[i-1] = tr;
  232         }
  233     }
  234 }
  235 
  236 
  237 /* ts B20113 : outsourced from get_sector() */
  238 int sector_write_buffer(struct burn_drive *d, 
  239             struct burn_track *track, int flag)
  240 {
  241     int err, i;
  242     struct buffer *out;
  243 
  244     out = d->buffer;
  245     if (out->sectors <= 0)
  246         return 2;
  247     err = d->write(d, d->nwa, out);
  248     if (err == BE_CANCELLED)
  249         return 0;
  250 
  251     /* ts A61101 */
  252     if(track != NULL) {
  253         track->writecount += out->bytes;
  254         track->written_sectors += out->sectors;
  255 
  256         /* Determine current index */
  257         for (i = d->progress.index; i + 1 < track->indices; i++) {
  258             if (track->index[i + 1] > d->nwa + out->sectors)
  259         break;
  260             d->progress.index = i + 1;
  261         }
  262     }
  263     /* ts A61119 */
  264     d->progress.buffered_bytes += out->bytes;
  265 
  266     d->nwa += out->sectors;
  267     out->bytes = 0;
  268     out->sectors = 0;
  269     return 1;
  270 }
  271 
  272 
  273 /* ts A61009 : seems to hand out sector start pointer in opts->drive->buffer
  274         and to count hand outs as well as reserved bytes */
  275 /* ts A61101 : added parameter track for counting written bytes */
  276 static unsigned char *get_sector(struct burn_write_opts *opts, 
  277                 struct burn_track *track, int inmode)
  278 {
  279     struct burn_drive *d = opts->drive;
  280     struct buffer *out = d->buffer;
  281     int outmode, seclen, write_ret;
  282     unsigned char *ret;
  283 
  284     outmode = get_outmode(opts);
  285     if (outmode == 0)
  286         outmode = inmode;
  287 
  288     /* ts A61009 : react on eventual failure of burn_sector_length()
  289             (should not happen if API tested properly).
  290             Ensures out->bytes >= out->sectors  */
  291     seclen = burn_sector_length(outmode);
  292     if (seclen <= 0)
  293         return NULL;
  294     seclen += burn_subcode_length(outmode);
  295 
  296     /* ts A61219 : opts->obs is eventually a 32k trigger for DVD */
  297     /* (there is enough buffer size reserve for track->cdxa_conversion) */
  298     if (out->bytes + seclen > BUFFER_SIZE ||
  299         (opts->obs > 0 && out->bytes + seclen > opts->obs)) {
  300         write_ret = sector_write_buffer(d, track, 0);
  301         if (write_ret <= 0)
  302             return NULL;
  303     }
  304     ret = out->data + out->bytes;
  305     out->bytes += seclen;
  306     out->sectors++;
  307 
  308     return ret;
  309 }
  310 
  311 /* ts A61031 */
  312 /* Revoke the counting of the most recent sector handed out by get_sector() */
  313 static void unget_sector(struct burn_write_opts *opts, int inmode)
  314 {
  315     struct burn_drive *d = opts->drive;
  316     struct buffer *out = d->buffer;
  317     int outmode;
  318     int seclen;
  319 
  320     outmode = get_outmode(opts);
  321     if (outmode == 0)
  322         outmode = inmode;
  323 
  324     /* ts A61009 : react on eventual failure of burn_sector_length()
  325             (should not happen if API tested properly).
  326             Ensures out->bytes >= out->sectors  */
  327     seclen = burn_sector_length(outmode);
  328     if (seclen <= 0)
  329         return;
  330     seclen += burn_subcode_length(outmode);
  331 
  332     out->bytes -= seclen;
  333     out->sectors--;
  334 }
  335 
  336 
  337 /* either inmode == outmode, or outmode == raw.  anything else is bad news */
  338 /* ts A61010 : changed type to int in order to propagate said bad news */
  339 /** @return 1 is ok, <= 0 is failure */
  340 static int convert_data(struct burn_write_opts *o, struct burn_track *track,
  341              int inmode, unsigned char *data)
  342 {
  343     int outlen, inlen;
  344     int offset = -1;
  345     int outmode;
  346 
  347     outmode = get_outmode(o);
  348     if (outmode == 0)
  349         outmode = inmode;
  350 
  351     outlen = burn_sector_length(outmode);
  352     inlen = burn_sector_length(inmode);
  353 
  354     /* ts A61010 */
  355     /* a ssert(outlen >= inlen); */
  356     if (outlen < inlen || outlen < 0 || inlen < 0)
  357         return 0;
  358 
  359     if ((outmode & BURN_MODE_BITS) == (inmode & BURN_MODE_BITS)) {
  360         /* see MMC-5 4.2.3.8.5.3 Block Format for Mode 2 form 1 Data
  361                     Table 24  Mode 2 Formed Sector Sub-header Format */
  362         if (track != NULL)
  363             if (track->cdxa_conversion == 1)
  364                 inlen += 8;
  365 
  366         get_bytes(track, inlen, data);
  367 
  368         if (track != NULL)
  369             if (track->cdxa_conversion == 1)
  370                 memmove(data, data + 8, inlen - 8);
  371         return 1;
  372     }
  373 
  374     /* ts A61010 */
  375     /* a ssert(outmode & BURN_MODE_RAW); */
  376     if (!(outmode & BURN_MODE_RAW))
  377         return 0;
  378 
  379     if (inmode & BURN_MODE1)
  380         offset = 16;
  381     if (inmode & BURN_MODE_RAW)
  382         offset = 0;
  383     if (inmode & BURN_AUDIO)
  384         offset = 0;
  385 
  386     /* ts A61010 */
  387     /* a ssert(offset != -1); */
  388     if (offset == -1)
  389         return 0;
  390 
  391     get_bytes(track, inlen, data + offset);
  392     return 1;
  393 }
  394 
  395 static void convert_subs(struct burn_write_opts *o, int inmode,
  396              unsigned char *subs, unsigned char *sector)
  397 {
  398     unsigned char *out;
  399     int outmode;
  400 
  401     outmode = get_outmode(o);
  402     if (outmode == 0)
  403         outmode = inmode;
  404     sector += burn_sector_length(outmode);
  405 /* XXX for sao with subs, we'd need something else... */
  406 
  407     switch (o->block_type) {
  408     case BURN_BLOCK_RAW96R:
  409         uncook_subs(sector, subs);
  410         break;
  411 
  412     case BURN_BLOCK_RAW16:
  413         memcpy(sector, subs + 12, 12);
  414         out = sector + 12;
  415         out[0] = 0;
  416         out[1] = 0;
  417         out[2] = 0;
  418 /*XXX find a better way to deal with partially damaged P channels*/
  419         if (subs[2] != 0)
  420             out[3] = 0x80;
  421         else
  422             out[3] = 0;
  423         out = sector + 10;
  424 
  425         out[0] = ~out[0];
  426         out[1] = ~out[1];
  427         break;
  428     /* ts A61119 : to silence compiler warnings */
  429     default:;
  430     }
  431 }
  432 
  433 static void subcode_toc(struct burn_drive *d, int mode, unsigned char *data)
  434 {
  435     unsigned char *q;
  436     int track;
  437     int crc;
  438     int min, sec, frame;
  439 
  440     track = d->toc_temp / 3;
  441     memset(data, 0, 96);
  442     q = data + 12;
  443 
  444     burn_lba_to_msf(d->rlba, &min, &sec, &frame);
  445 /*XXX track numbers are BCD
  446 a0 - 1st track ctrl
  447 a1 - last track ctrl
  448 a2 - lout ctrl
  449 */
  450     q[0] = (d->toc_entry[track].control << 4) + 1;
  451     q[1] = 0;
  452     if (d->toc_entry[track].point < 100)
  453         q[2] = dec_to_bcd(d->toc_entry[track].point);
  454     else
  455         q[2] = d->toc_entry[track].point;
  456     q[3] = dec_to_bcd(min);
  457     q[4] = dec_to_bcd(sec);
  458     q[5] = dec_to_bcd(frame);
  459     q[6] = 0;
  460     q[7] = dec_to_bcd(d->toc_entry[track].pmin);
  461     q[8] = dec_to_bcd(d->toc_entry[track].psec);
  462     q[9] = dec_to_bcd(d->toc_entry[track].pframe);
  463 
  464 #ifdef Libburn_no_crc_C
  465     crc = 0; /* dummy */
  466 #else
  467     crc = crc_ccitt(q, 10);
  468 #endif
  469 
  470     q[10] = crc >> 8;
  471     q[11] = crc & 0xFF;
  472     d->toc_temp++;
  473     d->toc_temp %= (d->toc_entries * 3);
  474 }
  475 
  476 int sector_toc(struct burn_write_opts *o, int mode)
  477 {
  478     struct burn_drive *d = o->drive;
  479     unsigned char *data;
  480     unsigned char subs[96];
  481 
  482     data = get_sector(o, NULL, mode);
  483     if (data == NULL)
  484         return 0;
  485     /* ts A61010 */
  486     if (convert_data(o, NULL, mode, data) <= 0)
  487         return 0;
  488     subcode_toc(d, mode, subs);
  489     convert_subs(o, mode, subs, data);
  490     if (sector_headers(o, data, mode, 1) <= 0)
  491         return 0;
  492     sector_common(++)
  493     return 1;
  494 }
  495 
  496 int sector_pregap(struct burn_write_opts *o,
  497            unsigned char tno, unsigned char control, int mode)
  498 {
  499     struct burn_drive *d = o->drive;
  500     unsigned char *data;
  501     unsigned char subs[96];
  502 
  503     data = get_sector(o, NULL, mode);
  504     if (data == NULL)
  505         return 0;
  506     /* ts A61010 */
  507     if (convert_data(o, NULL, mode, data) <= 0)
  508         return 0;
  509     subcode_user(o, subs, tno, control, 0, NULL, 1);
  510     convert_subs(o, mode, subs, data);
  511     if (sector_headers(o, data, mode, 0) <= 0)
  512         return 0;
  513     sector_common(--)
  514     return 1;
  515 }
  516 
  517 int sector_postgap(struct burn_write_opts *o,
  518             unsigned char tno, unsigned char control, int mode)
  519 {
  520     struct burn_drive *d = o->drive;
  521     unsigned char subs[96];
  522     unsigned char *data;
  523 
  524     data = get_sector(o, NULL, mode);
  525     if (data == NULL)
  526         return 0;
  527     /* ts A61010 */
  528     if (convert_data(o, NULL, mode, data) <= 0)
  529         return 0;
  530 /* use last index in track */
  531     subcode_user(o, subs, tno, control, 1, NULL, 1);
  532     convert_subs(o, mode, subs, data);
  533     if (sector_headers(o, data, mode, 0) <= 0)
  534         return 0;
  535     sector_common(++)
  536     return 1;
  537 }
  538 
  539 static void subcode_lout(struct burn_write_opts *o, unsigned char control,
  540              unsigned char *data)
  541 {
  542     struct burn_drive *d = o->drive;
  543     unsigned char *q;
  544     int crc;
  545     int rmin, min, rsec, sec, rframe, frame;
  546 
  547     memset(data, 0, 96);
  548     q = data + 12;
  549 
  550     burn_lba_to_msf(d->alba, &min, &sec, &frame);
  551     burn_lba_to_msf(d->rlba, &rmin, &rsec, &rframe);
  552 
  553     if (((rmin == 0) && (rsec == 0) && (rframe == 0)) ||
  554         ((rsec >= 2) && !((rframe / 19) % 2)))
  555         memset(data, 0xFF, 12);
  556     q[0] = (control << 4) + 1;
  557     q[1] = 0xAA;
  558     q[2] = 0x01;
  559     q[3] = dec_to_bcd(rmin);
  560     q[4] = dec_to_bcd(rsec);
  561     q[5] = dec_to_bcd(rframe);
  562     q[6] = 0;
  563     q[7] = dec_to_bcd(min);
  564     q[8] = dec_to_bcd(sec);
  565     q[9] = dec_to_bcd(frame);
  566 
  567 #ifdef Libburn_no_crc_C
  568     crc = 0; /* dummy */
  569 #else
  570     crc = crc_ccitt(q, 10);
  571 #endif
  572 
  573     q[10] = crc >> 8;
  574     q[11] = crc & 0xFF;
  575 }
  576 
  577 static char char_to_isrc(char c)
  578 {
  579     if (c >= '0' && c <= '9')
  580         return c - '0';
  581     if (c >= 'A' && c <= 'Z')
  582         return 0x11 + (c - 'A');
  583     if (c >= 'a' && c <= 'z')
  584         return 0x11 + (c - 'a');
  585 
  586     /* ts A61008 : obsoleted by test in burn_track_set_isrc() */
  587     /* a ssert(0); */
  588     return 0;
  589 }
  590 
  591 void subcode_user(struct burn_write_opts *o, unsigned char *subcodes,
  592           unsigned char tno, unsigned char control,
  593           unsigned char indx, struct isrc *isrc, int psub)
  594 {
  595     struct burn_drive *d = o->drive;
  596     unsigned char *p, *q;
  597     int crc;
  598     int m, s, f, c, qmode;  /* 1, 2 or 3 */
  599 
  600     memset(subcodes, 0, 96);
  601 
  602     p = subcodes;
  603     if ((tno == 1) && (d->rlba == -150))
  604         memset(p, 0xFF, 12);
  605 
  606     if (psub)
  607         memset(p, 0xFF, 12);
  608     q = subcodes + 12;
  609 
  610     qmode = 1;
  611     /* every 1 in 10 we can do something different */
  612     if (d->rlba % 10 == 0) {
  613         /* each of these can occur 1 in 100 */
  614         if ((d->rlba / 10) % 10 == 0) {
  615             if (o->has_mediacatalog)
  616                 qmode = 2;
  617         } else if ((d->rlba / 10) % 10 == 1) {
  618             if (isrc && isrc->has_isrc)
  619                 qmode = 3;
  620         }
  621     }
  622 
  623     /* ts A61010 : this cannot happen. Assert for fun ? */
  624     /* a ssert(qmode == 1 || qmode == 2 || qmode == 3); */
  625 
  626     switch (qmode) {
  627     case 1:
  628         q[1] = dec_to_bcd(tno); /* track number */
  629         q[2] = dec_to_bcd(indx);    /* index XXX read this shit
  630                            from the track array */
  631         burn_lba_to_msf(d->rlba, &m, &s, &f);
  632         q[3] = dec_to_bcd(m);   /* rel min */
  633         q[4] = dec_to_bcd(s);   /* rel sec */
  634         q[5] = dec_to_bcd(f);   /* rel frame */
  635         q[6] = 0;   /* zero */
  636         burn_lba_to_msf(d->alba, &m, &s, &f);
  637         q[7] = dec_to_bcd(m);   /* abs min */
  638         q[8] = dec_to_bcd(s);   /* abs sec */
  639         q[9] = dec_to_bcd(f);   /* abs frame */
  640         break;
  641     case 2:
  642         /* media catalog number */
  643         q[1] = (o->mediacatalog[0] << 4) + o->mediacatalog[1];
  644         q[2] = (o->mediacatalog[2] << 4) + o->mediacatalog[3];
  645         q[3] = (o->mediacatalog[4] << 4) + o->mediacatalog[5];
  646         q[4] = (o->mediacatalog[6] << 4) + o->mediacatalog[7];
  647         q[5] = (o->mediacatalog[8] << 4) + o->mediacatalog[9];
  648         q[6] = (o->mediacatalog[10] << 4) + o->mediacatalog[11];
  649         q[7] = o->mediacatalog[12] << 4;
  650 
  651         q[8] = 0;
  652         burn_lba_to_msf(d->alba, &m, &s, &f);
  653         q[9] = dec_to_bcd(f);   /* abs frame */
  654         break;
  655     case 3:
  656         c = char_to_isrc(isrc->country[0]);
  657         /* top 6 bits of [1] is the first country code */
  658         q[1] = c << 2;
  659         c = char_to_isrc(isrc->country[1]);
  660         /* bottom 2 bits of [1] is part of the second country code */
  661         q[1] += (c >> 4);
  662         /* top 4 bits if [2] is the rest of the second country code */
  663         q[2] = c << 4;
  664 
  665         c = char_to_isrc(isrc->owner[0]);
  666         /* bottom 4 bits of [2] is part of the first owner code */
  667         q[2] += (c >> 2);
  668         /* top 2 bits of [3] is the rest of the first owner code */
  669         q[3] = c << 6;
  670         c = char_to_isrc(isrc->owner[1]);
  671         /* bottom 6 bits of [3] is the entire second owner code */
  672         q[3] += c;
  673         c = char_to_isrc(isrc->owner[2]);
  674         /* top 6 bits of [4] are the third owner code */
  675         q[4] = c << 2;
  676 
  677         /* [5] is the year in 2 BCD numbers */
  678         q[5] = dec_to_bcd(isrc->year % 100);
  679         /* [6] is the first 2 digits in the serial */
  680         q[6] = dec_to_bcd(isrc->serial % 100);
  681         /* [7] is the next 2 digits in the serial */
  682         q[7] = dec_to_bcd((isrc->serial / 100) % 100);
  683         /* the top 4 bits of [8] is the last serial digit, the rest is 
  684            zeros */
  685         q[8] = dec_to_bcd((isrc->serial / 10000) % 10) << 4;
  686         burn_lba_to_msf(d->alba, &m, &s, &f);
  687         q[9] = dec_to_bcd(f);   /* abs frame */
  688         break;
  689     }
  690     q[0] = (control << 4) + qmode;
  691 
  692 
  693 #ifdef Libburn_no_crc_C
  694     crc = 0; /* dummy */
  695 #else
  696     crc = crc_ccitt(q, 10);
  697 #endif
  698 
  699     q[10] = crc >> 8;
  700     q[11] = crc & 0xff;
  701 }
  702 
  703 int sector_lout(struct burn_write_opts *o, unsigned char control, int mode)
  704 {
  705     struct burn_drive *d = o->drive;
  706     unsigned char subs[96];
  707     unsigned char *data;
  708 
  709     data = get_sector(o, NULL, mode);
  710     if (!data)
  711         return 0;
  712     /* ts A61010 */
  713     if (convert_data(o, NULL, mode, data) <= 0)
  714         return 0;
  715     subcode_lout(o, control, subs);
  716     convert_subs(o, mode, subs, data);
  717     if (sector_headers(o, data, mode, 0) <= 0)
  718         return 0;
  719     sector_common(++)
  720     return 1;
  721 }
  722 
  723 int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
  724 {
  725     struct burn_drive *d = o->drive;
  726     unsigned char subs[96];
  727     unsigned char *data;
  728 
  729     data = get_sector(o, t, t->mode);
  730     if (data == NULL)
  731         return 0;
  732     /* ts A61010 */
  733     if (convert_data(o, t, t->mode, data) <= 0)
  734         return 0;
  735 
  736     /* ts A61031 */
  737     if ((t->open_ended || t->end_on_premature_eoi) && t->track_data_done) {
  738         unget_sector(o, t->mode);
  739         return 2;
  740     }
  741 
  742     /* ts A61219 : allow track without .entry */
  743     if (t->entry == NULL)
  744         ;
  745     else if (!t->source->read_sub)
  746         subcode_user(o, subs, t->entry->point,
  747                  t->entry->control, 1, &t->isrc, psub);
  748     else if (!t->source->read_sub(t->source, subs, 96))
  749         subcode_user(o, subs, t->entry->point,
  750                  t->entry->control, 1, &t->isrc, psub);
  751     convert_subs(o, t->mode, subs, data);
  752 
  753     if (sector_headers(o, data, t->mode, 0) <= 0)
  754         return 0;
  755     sector_common(++)
  756     return 1;
  757 }
  758 
  759 int burn_msf_to_lba(int m, int s, int f)
  760 {
  761     if (m < 90)
  762         return (m * 60 + s) * 75 + f - 150;
  763     else
  764         return (m * 60 + s) * 75 + f - 450150;
  765 }
  766 
  767 void burn_lba_to_msf(int lba, int *m, int *s, int *f)
  768 {
  769     if (lba >= -150) {
  770         *m = (lba + 150) / (60 * 75);
  771         *s = (lba + 150 - *m * 60 * 75) / 75;
  772         *f = lba + 150 - *m * 60 * 75 - *s * 75;
  773     } else {
  774         *m = (lba + 450150) / (60 * 75);
  775         *s = (lba + 450150 - *m * 60 * 75) / 75;
  776         *f = lba + 450150 - *m * 60 * 75 - *s * 75;
  777     }
  778 }
  779 
  780 int dec_to_bcd(int d)
  781 {
  782     int top, bottom;
  783 
  784     top = d / 10;
  785     bottom = d - (top * 10);
  786     return (top << 4) + bottom;
  787 }
  788 
  789 int sector_headers_is_ok(struct burn_write_opts *o, int mode)
  790 {
  791     if (mode & BURN_AUDIO)  /* no headers for "audio" */
  792         return 1;
  793     if (o->write_type == BURN_WRITE_SAO)
  794         return 1;
  795 
  796     /* ts A61031 */
  797     if (o->write_type == BURN_WRITE_TAO)
  798         return 1;
  799 
  800     if (mode & BURN_MODE1)
  801         return 2;
  802     return 0;
  803 }
  804 
  805 /* ts A90830 : changed return type to int
  806    @return 0= failure
  807            1= success
  808 */
  809 int sector_headers(struct burn_write_opts *o, unsigned char *out,
  810             int mode, int leadin)
  811 {
  812 
  813 #ifdef Libburn_ecma130ab_includeD
  814 
  815     struct burn_drive *d = o->drive;
  816     unsigned int crc;
  817     int min, sec, frame;
  818     int modebyte = -1;
  819     int ret;
  820 
  821     ret = sector_headers_is_ok(o, mode);
  822     if (ret != 2)
  823         return !!ret;
  824     modebyte = 1;
  825 
  826     out[0] = 0;
  827     memset(out + 1, 0xFF, 10);  /* sync */
  828     out[11] = 0;
  829 
  830     if (leadin) {
  831         burn_lba_to_msf(d->rlba, &min, &sec, &frame);
  832         out[12] = dec_to_bcd(min) + 0xA0;
  833         out[13] = dec_to_bcd(sec);
  834         out[14] = dec_to_bcd(frame);
  835         out[15] = modebyte;
  836     } else {
  837         burn_lba_to_msf(d->alba, &min, &sec, &frame);
  838         out[12] = dec_to_bcd(min);
  839         out[13] = dec_to_bcd(sec);
  840         out[14] = dec_to_bcd(frame);
  841         out[15] = modebyte;
  842     }
  843     if (mode & BURN_MODE1) {
  844 
  845 #ifdef Libburn_no_crc_C
  846         crc = 0; /* dummy */
  847 #else
  848         crc = crc_32(out, 2064);
  849 #endif
  850 
  851         out[2064] = crc & 0xFF;
  852         crc >>= 8;
  853         out[2065] = crc & 0xFF;
  854         crc >>= 8;
  855         out[2066] = crc & 0xFF;
  856         crc >>= 8;
  857         out[2067] = crc & 0xFF;
  858     }
  859     if (mode & BURN_MODE1) {
  860         memset(out + 2068, 0, 8);
  861         burn_rspc_parity_p(out);
  862         burn_rspc_parity_q(out);
  863     }
  864     burn_ecma130_scramble(out);
  865     return 1;
  866 
  867 #else /* Libburn_ecma130ab_includeD */
  868 
  869     int ret;
  870 
  871     ret = sector_headers_is_ok(o, mode);
  872     if (ret != 2)
  873         return (!! ret);
  874 
  875     /* ts A90830 : lec.c is copied from cdrdao.
  876        I have no idea yet how lec.c implements the Reed-Solomon encoding
  877        which is described in ECMA-130 for CD-ROM.
  878        So this got removed for now.
  879     */
  880     libdax_msgs_submit(libdax_messenger, o->drive->global_index,
  881                 0x0002010a,
  882                 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
  883                 "Raw CD write modes are not supported", 0, 0);
  884     return 0;
  885 
  886 #endif /* ! Libburn_ecma130ab_includeD */
  887 
  888 }
  889 
  890 #if 0
  891 void process_q(struct burn_drive *d, unsigned char *q)
  892 {
  893     unsigned char i[5];
  894     int mode;
  895 
  896     mode = q[0] & 0xF;
  897 /*      burn_print(12, "mode: %d : ", mode);*/
  898     switch (mode) {
  899     case 1:
  900 /*              burn_print(12, "tno = %d : ", q[1]);
  901                 burn_print(12, "index = %d\n", q[2]);
  902 */
  903         /* q[1] is the track number (starting at 1) q[2] is the index
  904            number (starting at 0) */
  905 #warning this is totally bogus
  906         if (q[1] - 1 > 99)
  907             break;
  908         if (q[2] > d->toc->track[q[1] - 1].indices) {
  909             burn_print(12, "new index at %d\n", d->alba);
  910             d->toc->track[q[1] - 1].index[q[2]] = d->alba;
  911             d->toc->track[q[1] - 1].indices++;
  912         }
  913         break;
  914     case 2:
  915         /* XXX do not ignore these */
  916         break;
  917     case 3:
  918 /*              burn_print(12, "ISRC data in mode 3 q\n");*/
  919         i[0] = isrc[(q[1] << 2) >> 2];
  920 /*              burn_print(12, "0x%x 0x%x 0x%x 0x%x 0x%x\n", q[1], q[2], q[3], q[4], q[5]);
  921                 burn_print(12, "ISRC - %c%c%c%c%c\n", i[0], i[1], i[2], i[3], i[4]);
  922 */
  923         break;
  924     default:
  925 
  926         /* ts A61009 : if reactivated then without Assert */
  927         a ssert(0);
  928     }
  929 }
  930 #endif
  931 
  932 /* this needs more info.  subs in the data? control/adr? */
  933 
  934 /* ts A61119 : One should not use unofficial compiler extensions.
  935    >>> Some day this function needs to be implemented. At least for now
  936        the result does not match the "mode" of cdrecord -toc.
  937  */
  938 /*
  939 #warning sector_identify needs to be written
  940 */
  941 int sector_identify(unsigned char *data)
  942 {
  943 
  944 /*
  945     burn_ecma130_scramble(data);
  946 check mode byte for 1 or 2
  947 test parity to see if it's a valid sector
  948 if invalid, return BURN_MODE_AUDIO;
  949 else return mode byte  (what about mode 2 formless?  heh)
  950 */
  951 
  952     return BURN_MODE1;
  953 }