/* * will take care of adding mode header and any extra bytes at the end. */ int set_mode_page(int fd, uchar_t *buffer) { int ret; uchar_t *buf; uint_t total, p_len; p_len = buffer[1] + 2; total = p_len + 8; buf = (uchar_t *)my_zalloc(total); (void) memcpy(&buf[8], buffer, p_len); if (debug) { int i; (void) printf("MODE: ["); for (i = 0; i < p_len; i++) { (void) printf("0x%02x ", (uchar_t)buffer[i]); } (void) printf("]\n"); } ret = mode_select(fd, total, buf); free(buf); return (ret); }
/*** Sélection de la liste d'index en gravage TAO ***/ int philips_set_index_list( unsigned long * index ) { unsigned char MSParm[ 255 ] = {0}; unsigned int num; num = 1; while( index[num] ) num++; if( num > 49 ) num = 49; MSParm[ 0 ] = 0x24; /* Subcode Increment Index Page */ MSParm[ 1 ] = 197/*num*4 + 1*/; MSParm[ 2 ] = num; memcpy( MSParm + 3, index, num * sizeof( index[0] ) ); return mode_select( 0, 0, current_device->BlockSize, MSParm, 199/*num*4 + 3*/ ); }
/* Réglage de la vitesse du graveur, du mode d'emulation et de la taille de bloc */ int philips_set_speed( int write, int wdummy, int read, int scrambled ) { static char MSParm[ 8 ] = { 0x23, /* Page de sélection de la vitesse */ 0x06, /* Taille de la page de paramètres */ 0, /* Vitesse d'écriture */ 0, /* Emulation d'écriture */ 0, /* Vitesse de lecture */ 0, 0, /* Réservé */ 0 }; /* Read Scrambled */ MSParm[ 2 ] = write; MSParm[ 3 ] = wdummy; MSParm[ 4 ] = read; MSParm[ 7 ] = scrambled ? 0x80 : 0; return mode_select( 0, 0, current_device->BlockSize, MSParm, 8 ); }
SANE_Status sane_start (SANE_Handle handle) { char *mode_str; Ibm_Scanner *s = handle; SANE_Status status; struct ibm_window_data wbuf; struct measurements_units_page mup; DBG (11, ">> sane_start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return (status); } mode_str = s->val[OPT_MODE].s; s->xres = s->val[OPT_X_RESOLUTION].w; s->yres = s->val[OPT_Y_RESOLUTION].w; s->ulx = s->val[OPT_TL_X].w; s->uly = s->val[OPT_TL_Y].w; s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w; s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w; s->brightness = s->val[OPT_BRIGHTNESS].w; s->contrast = s->val[OPT_CONTRAST].w; s->bpp = s->params.depth; if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->image_composition = IBM_BINARY_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { s->image_composition = IBM_DITHERED_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0) { s->image_composition = IBM_GRAYSCALE; } memset (&wbuf, 0, sizeof (wbuf)); /* next line commented out by mf */ /* _lto2b(sizeof(wbuf) - 8, wbuf.len); */ /* next line by mf */ _lto2b(IBM_WINDOW_DATA_SIZE, wbuf.len); /* size=320 */ _lto2b(s->xres, wbuf.x_res); _lto2b(s->yres, wbuf.y_res); _lto4b(s->ulx, wbuf.x_org); _lto4b(s->uly, wbuf.y_org); _lto4b(s->width, wbuf.width); _lto4b(s->length, wbuf.length); wbuf.image_comp = s->image_composition; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME) { if (wbuf.image_comp == IBM_GRAYSCALE) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x80; /* it was 0x90 */ if (wbuf.image_comp == IBM_DITHERED_MONOCHROME) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10; wbuf.brightness = 256 - (SANE_Byte) s->brightness; /* if (is50) wbuf.contrast = (SANE_Byte) s->contrast; else */ wbuf.contrast = 256 - (SANE_Byte) s->contrast; } else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */ { wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00; wbuf.brightness = (SANE_Byte) s->brightness; wbuf.contrast = (SANE_Byte) s->contrast; } wbuf.threshold = 0; wbuf.bits_per_pixel = s->bpp; wbuf.halftone_code = 2; /* diithering */ wbuf.halftone_id = 0x0A; /* 8x8 Bayer pattenr */ wbuf.pad_type = 3; wbuf.bit_ordering[0] = 0; wbuf.bit_ordering[1] = 7; /* modified by mf (it was 3) */ DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending SET WINDOW\n"); status = set_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (11, "sane_start: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending MODE SELECT\n"); memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); /* next lines by mf */ mup.adf_page_code = 0x26; mup.adf_parameter_length = 6; if (s->adf_state == ADF_ARMED) mup.adf_control = 1; else mup.adf_control = 0; /* end lines by mf */ status = mode_select (s->fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); return (SANE_STATUS_INVAL); } status = trigger_scan (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); /* next line introduced not to freeze xscanimage */ do_cancel(s); return status; } /* Wait for scanner to become ready to transmit data */ status = ibm_wait_ready (s); if (status != SANE_STATUS_GOOD) { DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status)); return (status); } s->bytes_to_read = s->params.bytes_per_line * s->params.lines; DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w); s->scanning = SANE_TRUE; DBG (11, "<< sane_start\n"); return (SANE_STATUS_GOOD); }
static SANE_Status attach (const char *devnam, Ibm_Device ** devp) { SANE_Status status; Ibm_Device *dev; int fd; struct inquiry_data ibuf; struct measurements_units_page mup; struct ibm_window_data wbuf; size_t buf_size; char *str; DBG (11, ">> attach\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } DBG (3, "attach: opening %s\n", devnam); status = sanei_scsi_open (devnam, &fd, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } DBG (3, "attach: sending INQUIRY\n"); memset (&ibuf, 0, sizeof (ibuf)); buf_size = sizeof(ibuf); /* next line by mf */ ibuf.byte2 = 2; status = inquiry (fd, &ibuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } if (ibuf.devtype != 6) { DBG (1, "attach: device \"%s\" is not a scanner\n", devnam); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } if (!( (strncmp ((char *)ibuf.vendor, "IBM", 3) ==0 && strncmp ((char *)ibuf.product, "2456", 4) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS420", 5) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS410", 5) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS430", 5) == 0) )) { DBG (1, "attach: device \"%s\" doesn't look like a scanner I know\n", devnam); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } /* * Causes a problem with RICOH IS420 * Ignore this function ... seems to work ok * Suggested to George Murphy [email protected] by henning */ if (strncmp((char *)ibuf.vendor, "RICOH", 5) != 0 && strncmp((char *)ibuf.product, "IS420", 5) != 0) { DBG (3, "attach: sending OBJECT POSITION\n"); status = object_position (fd, OBJECT_POSITION_UNLOAD); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: OBJECT POSTITION failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } } memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); #if 0 DBG (3, "attach: sending MODE SELECT\n"); status = mode_select (fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif #if 0 DBG (3, "attach: sending MODE SENSE\n"); memset (&mup, 0, sizeof (mup)); status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif DBG (3, "attach: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET_WINDOW failed %d\n", status); sanei_scsi_close (fd); DBG (11, "<< attach\n"); return (SANE_STATUS_INVAL); } sanei_scsi_close (fd); dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devnam); dev->sane.vendor = "IBM"; str = malloc (16 + 1); memset (str, 0, sizeof (str)); strncpy (str, (char *)ibuf.product, sizeof(ibuf.product)); strncpy (str + sizeof(ibuf.revision), (char *)ibuf.revision, sizeof(ibuf.revision)); str[sizeof(ibuf.product) + sizeof(ibuf.revision)] = '\0'; dev->sane.model = str; dev->sane.type = "flatbed scanner"; DBG (5, "dev->sane.name = %s\n", dev->sane.name); DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor); DBG (5, "dev->sane.model = %s\n", dev->sane.model); DBG (5, "dev->sane.type = %s\n", dev->sane.type); dev->info.xres_default = _2btol(wbuf.x_res); dev->info.yres_default = _2btol(wbuf.y_res); dev->info.image_mode_default = wbuf.image_comp; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ /* I should make this into an option */ if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME) { dev->info.brightness_default = 256 - wbuf.brightness; /* if (is50) dev->info.contrast_default = wbuf.contrast; else */ dev->info.contrast_default = 256 - wbuf.contrast; } else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */ { dev->info.brightness_default = wbuf.brightness; dev->info.contrast_default = wbuf.contrast; } /* da rivedere dev->info.adf_default = wbuf.adf_state; */ dev->info.adf_default = ADF_UNUSED; dev->info.adf_default = IBM_PAPER_USER_DEFINED; #if 1 dev->info.bmu = mup.bmu; dev->info.mud = _2btol(mup.mud); if (dev->info.mud == 0) { /* The Ricoh says it uses points as default Basic Measurement Unit */ /* but gives a Measurement Unit Divisor of zero */ /* So, we set it to the default (SCSI-standard) of 1200 */ /* with BMU in inches, i.e. 1200 points equal 1 inch */ dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; } #else dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; #endif DBG (5, "xres_default=%d\n", dev->info.xres_default); DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max); DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min); DBG (5, "yres_default=%d\n", dev->info.yres_default); DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max); DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min); DBG (5, "x_range.max=%d\n", dev->info.x_range.max); DBG (5, "y_range.max=%d\n", dev->info.y_range.max); DBG (5, "image_mode=%d\n", dev->info.image_mode_default); DBG (5, "brightness=%d\n", dev->info.brightness_default); DBG (5, "contrast=%d\n", dev->info.contrast_default); DBG (5, "adf_state=%d\n", dev->info.adf_default); DBG (5, "bmu=%d\n", dev->info.bmu); DBG (5, "mud=%d\n", dev->info.mud); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (11, "<< attach\n"); return (SANE_STATUS_GOOD); }
SANE_Status sane_start (SANE_Handle handle) { Tamarack_Scanner *s = handle; SANE_Status status; int fds[2]; /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; if (s->fd < 0) { /* translate options into s->mode for convenient access: */ s->mode = make_mode (s->val[OPT_MODE].s); if (s->mode == TRUECOLOR) { if (s->val[OPT_PREVIEW].w && s->val[OPT_GRAY_PREVIEW].w) { /* Force gray-scale mode when previewing. */ s->mode = GREYSCALE; s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.last_frame = SANE_TRUE; } } status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "open: open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return status; } } status = wait_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG(1, "open: wait_ready() failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = scan_area_and_windows (s); if (status != SANE_STATUS_GOOD) { DBG(1, "open: set scan area command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = mode_select (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; s->scanning = SANE_TRUE; status = start_scan (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = get_image_status (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; s->line = 0; if (pipe (fds) < 0) return SANE_STATUS_IO_ERROR; s->pipe = fds[0]; s->reader_pipe = fds[1]; s->reader_pid = sanei_thread_begin (reader_process, (void *) s); if (sanei_thread_is_forked()) close (s->reader_pipe); return SANE_STATUS_GOOD; stop_scanner_and_return: do_cancel (s); return status; }
static void mode_edit(int fd, int page, int edit, int argc, char *argv[]) { int i; u_char data[255]; u_char *mode_pars; struct mode_header { u_char mdl; /* Mode data length */ u_char medium_type; u_char dev_spec_par; u_char bdl; /* Block descriptor length */ }; struct mode_page_header { u_char page_code; u_char page_length; }; struct mode_header *mh; struct mode_page_header *mph; char *fmt = mode_lookup(page); if (!fmt && verbose) { fprintf(stderr, "No mode data base entry in \"%s\" for page %d; binary %s only.\n", mode_db, page, (edit ? "edit" : "display")); } if (edit) { if (!fmt) { fprintf(stderr, "Sorry: can't edit without a format.\n"); exit(1); } if (pagectl != 0 && pagectl != 3) { fprintf(stderr, "It only makes sense to edit page 0 (current) or page 3 (saved values)\n"); exit(1); } verbose = 1; mode_sense(fd, data, sizeof(data), 1, page); mh = (struct mode_header *)data; mph = (struct mode_page_header *) (((char *)mh) + sizeof(*mh) + mh->bdl); mode_pars = (char *)mph + sizeof(*mph); edit_init(); scsireq_buff_decode_visit(mode_pars, mh->mdl, fmt, edit_check, 0); mode_sense(fd, data, sizeof(data), 0, page); edit_rewind(); scsireq_buff_decode_visit(mode_pars, mh->mdl, fmt, edit_defaults, 0); edit_rewind(); scsireq_buff_decode_visit(mode_pars, mh->mdl, fmt, edit_report, 0); fclose(edit_file); if (editit(edit_name) == -1 && errno != ECHILD) err(1, "edit %s", edit_name); if ((edit_file = fopen(edit_name, "r")) == NULL) err(1, "open %s", edit_name); edit_rewind(); scsireq_buff_encode_visit(mode_pars, mh->mdl, fmt, edit_get, 0); /* Eliminate block descriptors: */ bcopy((char *)mph, ((char *)mh) + sizeof(*mh), sizeof(*mph) + mph->page_length); mh->bdl = 0; mph = (struct mode_page_header *) (((char *)mh) + sizeof(*mh)); mode_pars = ((char *)mph) + 2; #if 0 /* Turn this on to see what you're sending to the * device: */ edit_rewind(); scsireq_buff_decode_visit(mode_pars, mh->mdl, fmt, arg_put, 0); #endif edit_done(); /* Make it permanent if pageselect is three. */ mph->page_code &= ~0xC0; /* Clear PS and RESERVED */ mh->mdl = 0; /* Reserved for mode select */ mode_select(fd, (char *)mh, sizeof(*mh) + mh->bdl + sizeof(*mph) + mph->page_length, (pagectl == 3)); exit(0); } mode_sense(fd, data, sizeof(data), pagectl, page); /* Skip over the block descriptors. */ mh = (struct mode_header *)data; mph = (struct mode_page_header *)(((char *)mh) + sizeof(*mh) + mh->bdl); mode_pars = (char *)mph + sizeof(*mph); if (!fmt) { for (i = 0; i < mh->mdl; i++) { printf("%02x%c",mode_pars[i], (((i + 1) % 8) == 0) ? '\n' : ' '); } putc('\n', stdout); } else { verbose = 1; scsireq_buff_decode_visit(mode_pars, mh->mdl, fmt, arg_put, 0); } }
// Start Of Program - this is where we setup everything before getting into the main loop void main(void) { // Oscillator setup OSCCON = 0b11100000; // device enters idle on Sleep(), 8Mhz Clock, OSCTUNE = 0b00000000; // Internal oscillator low freq comes from 31Khz clock from LFINTOSC, PLL disabled // Analog / Digital pins setup ANSEL = 0b00000000; // disable all analog inputs (make them all digital) must do this! ANSELH = 0b00000000; // disable all analog inputs (make them all digital) must do this! // Tristate setup TRISA = 0b00000011; TRISB = 0b11111110; TRISC = 0b00000000; TRISD = 0b00000000; TRISE = 0b00000000; // configure TIMER2: // prescaler 16, period register for 1ms, timer stopped T2CON = 0b00000010; TMR2 = 0; PR2 = _XTAL_FREQ / 1000 / 16 / 4; // initialize subsystems btn_init(); init_all(); // disable INT1, config for raising endge INT1IE = 0; INTEDG1 = 1; // enable interrupts TMR2IE = 1; // TIMER2 interrupt PEIE = 1; // peripheral interrupt GIE = 1; // global interrupt enable // start TIMER2 TMR2ON = 1; // main loop while (true) { off_flag = false; // go to idle and wait for timer Sleep(); // read button inputs btn_update(); // check for commands check_select(); check_off(); check_idle(); // execute mode task switch (mode) { case modeSelect: mode_select(); break; case modeSparkle: sparkle_leds(); break; case modeShiftReg: shiftreg_task(); break; case modeLightTest: led_group(LED_ALL, true); break; case modePOV: povmsg_task(); break; case modeBinDice: case modeDecDice: dice_task(mode == modeDecDice); break; case modeGame: game_task(); break; case mode4BitLogic: logic_4bit_task(); break; default: logic_task(); flipflop_task(); counter_task(mode == modeGrayCnt); } if (off_flag) { switch_off(); } } }
int main(int argc, char **argv) { iso_primary_descriptor_type ipd; char *dev = default_dev; char vendor[9],model[17],rev[5]; unsigned char reply[1024]; char tmpstr[255]; int replylen=sizeof(reply); int trackno = 0; int info_only = 0; unsigned char *buffer; int buffersize = READBLOCKS*BLOCKSIZE; int start,stop,imagesize=0,tracksize=0; int counter = 0; long readsize = 0; long imagesize_bytes = 0; int drive_block_size, init_bsize; int force_mode = 0; int scanbus_mode = 0; int dump_start, dump_count; MD5_CTX *MD5; char digest[16],digest_text[33]; int md5_mode = 0; int opt_index = 0; int audio_track = 0; int readblocksize = BLOCKSIZE; int file_format = AF_FILE_AIFFC; #ifdef IRIX CDPARSER *cdp = CDcreateparser(); CDFRAME cdframe; #endif int dev_type; int i,c,o; int len; int start_time,cur_time,kbps; if (rcsid); MD5 = malloc(sizeof(MD5_CTX)); buffer=(unsigned char*)malloc(READBLOCKS*AUDIOBLOCKSIZE); if (!buffer || !MD5) die("No memory"); if (argc<2) die("parameter(s) missing\n" "Try '%s --help' for more information.\n",PRGNAME); /* parse command line parameters */ while(1) { if ((c=getopt_long(argc,argv,"SMmvhid:",long_options,&opt_index)) == -1) break; switch (c) { case 'a': file_format=AF_FILE_AIFF; break; case 'A': file_format=AF_FILE_AIFFC; break; case 'v': verbose_mode=1; break; case 'h': p_usage(); break; case 'd': dev=strdup(optarg); break; case 't': if (sscanf(optarg,"%d",&trackno)!=1) trackno=0; break; case 'i': info_only=1; break; case 'c': if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2) die("invalid parameters"); dump_mode=1; break; #ifdef IRIX case 'C': if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2) die("invalid parameters"); dump_mode=2; break; #endif case 'f': if (sscanf(optarg,"%d",&force_mode)!=1) die("invalid parameters"); if (force_mode<1 || force_mode >2) { die("invalid parameters"); } break; case 'm': md5_mode=1; break; case 'M': md5_mode=2; break; case 's': audio_mode=1; break; case 'S': scanbus_mode=1; break; case 'V': printf(PRGNAME " " VERSION " " HOST_TYPE "\nCopyright (c) Timo Kokkonen, 1997-1998.\n\n"); exit(0); break; case '?': break; default: die("error parsing parameters"); } } if (!info_only) { if (md5_mode==2) outfile=fopen("/dev/null","w"); else outfile=fopen(argv[optind],"w"); if (!outfile) { if (argv[optind]) die("cannot open output file '%s'",argv[optind]); info_only=1; } } printf("readiso(9660) " VERSION "\n"); /* open the scsi device */ if (scsi_open(dev)) die("error opening scsi device '%s'",dev); if (scanbus_mode) { printf("\n"); scan_bus(); exit(0); } memset(reply,0,sizeof(reply)); if ((dev_type=inquiry(vendor,model,rev))<0) die("error accessing scsi device"); if (verbose_mode) { printf("device: %s\n",dev); printf("Vendor: %s\nModel: %s\nRevision: %s\n",vendor,model,rev); } if ( (dev_type&0x1f) != 0x5 ) { die("Device doesn't seem to be a CD-ROM!"); } #ifdef IRIX if (strcmp(vendor,"TOSHIBA")) { warn("NOTE! Audio track reading probably not supported on this device.\n"); } #endif test_ready(); if (test_ready()!=0) { sleep(2); if (test_ready()!=0) die("device not ready"); } fprintf(stderr,"Initializing...\n"); if (audio_mode) { #ifdef IRIX audioport=ALopenport("readiso","w",0); if (!audioport) { warn("Cannot initialize audio."); audio_mode=0; } #else audio_mode=0; #endif } #ifdef IRIX /* Make sure we get sane underflow exception handling */ sigfpe_[_UNDERFL].repls = _ZERO; handle_sigfpes(_ON, _EN_UNDERFL, NULL, _ABORT_ON_ERROR, NULL); #endif /* set_removable(1); */ #if 0 replylen=255; if (mode_sense10(reply,&replylen)==0) { printf("replylen=%d blocks=%d blocklen=%d\n",replylen, V3(&reply[8+1]),V3(&reply[8+5])); PRINT_BUF(reply,replylen); } replylen=255; /* sizeof(reply); */ if (mode_sense(reply,&replylen)==0) { printf("replylen=%d blocks=%d blocklen=%d\n",replylen, V3(&reply[4+1]),V3(&reply[4+5])); PRINT_BUF(reply,replylen); } #endif if (dump_mode==2) init_bsize=AUDIOBLOCKSIZE; else init_bsize=BLOCKSIZE; start_stop(0); if ( (drive_block_size=get_block_size()) < 0 ) { warn("cannot get current block size"); drive_block_size=init_bsize; } if (drive_block_size != init_bsize) { mode_select(init_bsize,(dump_mode==2?0x82:0x00)); drive_block_size=get_block_size(); if (drive_block_size!=init_bsize) warn("cannot set drive block size."); } start_stop(1); if (dump_mode && !info_only) { #ifdef IRIX CDFRAME buf; if (dump_mode==2) { if (cdp) { CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0); } else die("No audioparser"); } #endif fprintf(stderr,"Dumping %d sector(s) starting from LBA=%d\n", dump_count,dump_start); for (i=dump_start;i<dump_start+dump_count;i++) { len=buffersize; read_10(i,1,buffer,&len); if (len<init_bsize) break; #ifdef IRIX if (dump_mode==2) { memcpy(&buf,buffer,CDDA_BLOCKSIZE); CDparseframe(cdp,&buf); } #endif fwrite(buffer,len,1,outfile); fprintf(stderr,"."); } fprintf(stderr,"\ndone.\n"); goto quit; } fprintf(stderr,"Reading disc TOC..."); replylen=sizeof(reply); read_toc(reply,&replylen,verbose_mode); printf("\n"); if (trackno==0) { /* try to find first data track */ for (i=0;i<(reply[3]-reply[2]+1);i++) { o=4+i*8; if (reply[o+1]&DATA_TRACK) { trackno=i+1; break; } } if (trackno==0) die("No data track(s) found."); } fprintf(stderr,"Reading track %d...\n",trackno); if ( (trackno < reply[2]) || (trackno > reply[3]) ) die("Invalid track specified."); if ( ((reply[(trackno-1)*8+4+1]&DATA_TRACK)==0) ) { fprintf(stderr,"Not a data track.\n"); mode_select(AUDIOBLOCKSIZE,0x82); if (mode_sense(reply,&replylen)!=0) die("cannot get sense data"); drive_block_size=V3(&reply[9]); fprintf(stderr,"Selecting CD-DA mode, output file format: %s\n", file_format==AF_FILE_AIFFC?"AIFFC":"AIFF"); audio_track=1; } else { audio_track=0; } start=V4(&reply[(trackno-1)*8+4+4]); stop=V4(&reply[(trackno)*8+4+4]); tracksize=abs(stop-start); /* if (verbose_mode) printf("Start LBA=%d\nStop LBA=%d\n",start,stop); */ len=buffersize; read_10(start-0,1,buffer,&len); /* PRINT_BUF(buffer,32); */ if (!audio_track) { /* read the iso9660 primary descriptor */ fprintf(stderr,"Reading ISO9660 primary descriptor...\n"); len=buffersize; read_10(start+16,1,buffer,&len); if (len<sizeof(ipd)) die("cannot read iso9660 primary descriptor."); memcpy(&ipd,buffer,sizeof(ipd)); imagesize=ISONUM(ipd.volume_space_size); /* we should really check here if we really got a valid primary descriptor or not... */ if ( (imagesize>(stop-start)) || (imagesize<1) ) { fprintf(stderr,"\aInvalid ISO primary descriptor!!!\n"); if (!info_only) fprintf(stderr,"Copying entire track to image file.\n"); force_mode=2; } if (force_mode==1) {} /* use size from ISO primary descriptor */ else if (force_mode==2) imagesize=tracksize; /* use size from TOC */ else { if ( ( (tracksize-imagesize) > MAX_DIFF_ALLOWED ) || ( imagesize > tracksize ) ) { fprintf(stderr,"ISO primary descriptor has suspicious volume size" " (%d blocks)\n",imagesize); imagesize=tracksize; fprintf(stderr, "Using track size from TOC record (%d blocks) instead.\n", imagesize); fprintf(stderr, "(option -f can be used to override this behaviour.)\n"); } } imagesize_bytes=imagesize*BLOCKSIZE; if (verbose_mode||info_only) { printf("ISO9660 image info:\n"); printf("Type: %02xh\n",ipd.type[0]); ISOGETSTR(tmpstr,ipd.id,5); printf("ID: %s\n",tmpstr); printf("Version: %u\n",ipd.version[0]); ISOGETSTR(tmpstr,ipd.system_id,32); printf("System id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.volume_id,32); printf("Volume id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.volume_set_id,128); if (strlen(tmpstr)>0) printf("Volume set id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.publisher_id,128); if (strlen(tmpstr)>0) printf("Publisher id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.preparer_id,128); if (strlen(tmpstr)>0) printf("Preparer id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.application_id,128); if (strlen(tmpstr)>0) printf("Application id: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.creation_date); printf("Creation date: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.modification_date); if (!NULLISODATE(ipd.modification_date)) printf("Modification date: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.expiration_date); if (!NULLISODATE(ipd.expiration_date)) printf("Expiration date: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.effective_date); if (!NULLISODATE(ipd.effective_date)) printf("Effective date: %s\n",tmpstr); printf("Image size: %02d:%02d:%02d, %d blocks (%ld bytes)\n", LBA_MIN(ISONUM(ipd.volume_space_size)), LBA_SEC(ISONUM(ipd.volume_space_size)), LBA_FRM(ISONUM(ipd.volume_space_size)), ISONUM(ipd.volume_space_size), (long)ISONUM(ipd.volume_space_size)*BLOCKSIZE ); printf("Track size: %02d:%02d:%02d, %d blocks (%ld bytes)\n", LBA_MIN(tracksize), LBA_SEC(tracksize), LBA_FRM(tracksize), tracksize, (long)tracksize*BLOCKSIZE ); } } else { #ifdef IRIX /* if reading audio track */ imagesize=tracksize; imagesize_bytes=imagesize*CDDA_DATASIZE; buffersize = READBLOCKS*AUDIOBLOCKSIZE; readblocksize = AUDIOBLOCKSIZE; if (cdp) { CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0); } else die("No audioparser"); fclose(outfile); aiffsetup=AFnewfilesetup(); AFinitrate(aiffsetup,AF_DEFAULT_TRACK,44100.0); /* 44.1 kHz */ AFinitfilefmt(aiffsetup,file_format); /* set file format */ AFinitchannels(aiffsetup,AF_DEFAULT_TRACK,2); /* stereo */ AFinitsampfmt(aiffsetup,AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP,16); /* 16bit */ aiffoutfile=AFopenfile(argv[optind],"w",aiffsetup); if (!aiffoutfile) die("Cannot open target file (%s).",argv[optind]); #endif } /* read the image */ if (md5_mode) MD5Init(MD5); if (!info_only) { start_time=(int)time(NULL); fprintf(stderr,"Reading %s (%ldMb)...\n", audio_track?"audio track":"ISO9660 image", imagesize_bytes/(1024*1024)); do { len=buffersize; if(readsize/readblocksize+READBLOCKS>imagesize) { read_10(start+counter,imagesize-readsize/readblocksize,buffer,&len); } else read_10(start+counter,READBLOCKS,buffer,&len); if ((counter%(1024*1024/readblocksize))<READBLOCKS) { cur_time=(int)time(NULL); if ((cur_time-start_time)>0) { kbps=(readsize/1024)/(cur_time-start_time); } else { kbps=0; } fprintf(stderr,"%3dM of %dM read. (%d kb/s) \r", counter/512,imagesize/512,kbps); } counter+=READBLOCKS; readsize+=len; if (!audio_track) { fwrite(buffer,len,1,outfile); } else { #ifdef IRIX /* audio track */ for(i=0;i<(len/CDDA_BLOCKSIZE);i++) { CDparseframe(cdp,(CDFRAME*)&buffer[i*CDDA_BLOCKSIZE]); } #endif } if (md5_mode) MD5Update(MD5,buffer,(readsize>imagesize_bytes? len-(readsize-imagesize_bytes):len) ); } while (len==readblocksize*READBLOCKS&&readsize<imagesize*readblocksize); fprintf(stderr,"\n"); if (!audio_track) { if (readsize > imagesize_bytes) ftruncate(fileno(outfile),imagesize_bytes); if (readsize < imagesize_bytes) fprintf(stderr,"Image not complete!\n"); else fprintf(stderr,"Image complete.\n"); fclose(outfile); } else { #ifdef IRIX AFclosefile(aiffoutfile); #endif } } if (md5_mode && !info_only) { MD5Final((unsigned char*)digest,MD5); md2str((unsigned char*)digest,digest_text); fprintf(stderr,"MD5 (%s) = %s\n",(md5_mode==2?"'image'":argv[optind]), digest_text); } quit: start_stop(0); /* set_removable(1); */ /* close the scsi device */ scsi_close(); return 0; }