static int iclass_scan (pixma_t * s) { int error, n; iclass_t *mf = (iclass_t *) s->subdriver; uint8_t *buf, ignore; unsigned buf_len, ignore2; if (mf->state != state_idle) return PIXMA_EBUSY; /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } mf->raw_width = ALIGN_SUP (s->param->w, 32); PDBG (pixma_dbg (3, "raw_width = %u\n", mf->raw_width)); n = IMAGE_BLOCK_SIZE / s->param->line_size + 1; buf_len = (n + 1) * s->param->line_size + IMAGE_BLOCK_SIZE; if (buf_len > mf->buf_len) { buf = (uint8_t *) realloc (mf->buf, buf_len); if (!buf) return PIXMA_ENOMEM; mf->buf = buf; mf->buf_len = buf_len; } mf->lineptr = mf->buf; mf->blkptr = mf->buf + n * s->param->line_size; mf->blk_len = 0; error = step1 (s); if (error >= 0 && (s->param->adf_pageid == 0 || mf->generation == 1)) { /* single sheet or first sheet from ADF */ PDBG (pixma_dbg (3, "*iclass_scan***** start scanning *****\n")); error = start_session (s); if (error >= 0) mf->state = state_scanning; if (error >= 0) error = select_source (s); } else if (error >= 0) { /* next sheet from ADF */ PDBG (pixma_dbg (3, "*iclass_scan***** scan next sheet from ADF *****\n")); mf->state = state_scanning; } if (error >= 0) error = send_scan_param (s); if (error >= 0) error = request_image_block (s, 0, &ignore, &ignore2, &ignore, &ignore2); if (error < 0) { iclass_finish_scan (s); return error; } mf->last_block = 0; return 0; }
static int mp730_open (pixma_t * s) { mp730_t *mp; uint8_t *buf; mp = (mp730_t *) calloc (1, sizeof (*mp)); if (!mp) return PIXMA_ENOMEM; buf = (uint8_t *) malloc (CMDBUF_SIZE); if (!buf) { free (mp); return PIXMA_ENOMEM; } s->subdriver = mp; mp->state = state_idle; mp->cb.buf = buf; mp->cb.size = CMDBUF_SIZE; mp->cb.res_header_len = 2; mp->cb.cmd_header_len = 10; mp->cb.cmd_len_field_ofs = 7; PDBG (pixma_dbg (3, "Trying to clear the interrupt buffer...\n")); if (handle_interrupt (s, 200) == 0) { PDBG (pixma_dbg (3, " no packets in buffer\n")); } return 0; }
static int step1 (pixma_t * s) { int error, tmo; error = activate (s, 0); if (error < 0) return error; error = query_status (s); if (error < 0) return error; if (s->param->source == PIXMA_SOURCE_ADF && !has_paper (s)) return PIXMA_ENO_PAPER; error = activate_cs (s, 0); /*SIM*/ if (error < 0) return error; error = activate_cs (s, 0x20); if (error < 0) return error; tmo = 60; error = calibrate_cs (s); while (error == PIXMA_EBUSY && --tmo >= 0) { if (s->cancel) return PIXMA_ECANCELED; PDBG (pixma_dbg (2, "Scanner is busy. Timed out in %d sec.\n", tmo + 1)); pixma_sleep (1000000); error = calibrate_cs (s); } return error; }
static SANE_Status map_error (int error) { if (error >= 0) return SANE_STATUS_GOOD; switch (error) { case PIXMA_ENOMEM: return SANE_STATUS_NO_MEM; case PIXMA_ECANCELED: return SANE_STATUS_CANCELLED; case PIXMA_EBUSY: return SANE_STATUS_DEVICE_BUSY; case PIXMA_EINVAL: return SANE_STATUS_INVAL; case PIXMA_EACCES: return SANE_STATUS_ACCESS_DENIED; case PIXMA_EPAPER_JAMMED: return SANE_STATUS_JAMMED; case PIXMA_ENO_PAPER: return SANE_STATUS_NO_DOCS; case PIXMA_ECOVER_OPEN: return SANE_STATUS_COVER_OPEN; case PIXMA_ENOTSUP: return SANE_STATUS_UNSUPPORTED; case PIXMA_EPROTO: case PIXMA_ENODEV: case PIXMA_EIO: case PIXMA_ETIMEDOUT: return SANE_STATUS_IO_ERROR; } PDBG (pixma_dbg (1, "BUG: unmapped error %d\n", error)); return SANE_STATUS_IO_ERROR; }
static int handle_interrupt (pixma_t * s, int timeout) { int error; uint8_t intr[16]; error = pixma_wait_interrupt (s->io, intr, sizeof (intr), timeout); if (error == PIXMA_ETIMEDOUT) return 0; if (error < 0) return error; if (error != 16) { PDBG (pixma_dbg (1, "WARNING: unexpected interrupt packet length %d\n", error)); return PIXMA_EPROTO; } if (intr[10] & 0x40) send_time (s); if (intr[12] & 0x40) query_status (s); if (intr[15] & 1) s->events = PIXMA_EV_BUTTON2; /* b/w scan */ if (intr[15] & 2) s->events = PIXMA_EV_BUTTON1; /* color scan */ return 1; }
static void workaround_first_command (pixma_t * s) { /* FIXME: Send a dummy command because the device doesn't response to the first command that is sent directly after the USB interface has been set up. Why? USB isn't set up properly? */ uint8_t cmd[10]; int error; if (s->cfg->pid == MP750_PID) return; /* MP750 doesn't have this problem(?) */ PDBG (pixma_dbg (1, "Work-around for the problem: device doesn't response to the first command.\n")); memset (cmd, 0, sizeof (cmd)); pixma_set_be16 (cmd_calibrate, cmd); error = pixma_write (s->io, cmd, 10); if (error != 10) { if (error < 0) { PDBG (pixma_dbg (1, " Sending a dummy command failed: %s\n", pixma_strerror (error))); } else { PDBG (pixma_dbg (1, " Sending a dummy command failed: count = %d\n", error)); } return; } error = pixma_read (s->io, cmd, sizeof (cmd)); if (error >= 0) { PDBG (pixma_dbg (1, " Got %d bytes response from a dummy command.\n", error)); } else { PDBG (pixma_dbg (1, " Reading response of a dummy command failed: %s\n", pixma_strerror (error))); } }
static int send_time (pixma_t * s) { /* TODO: implement send_time() */ UNUSED (s); PDBG (pixma_dbg (3, "send_time() is not yet implemented.\n")); return 0; }
static void mp730_finish_scan (pixma_t * s) { int error, aborted = 0; mp730_t *mp = (mp730_t *) s->subdriver; switch (mp->state) { case state_transfering: drain_bulk_in (s); /* fall through */ case state_scanning: case state_warmup: aborted = 1; error = abort_session (s); if (error < 0) PDBG (pixma_dbg (1, "WARNING:abort_session() failed %s\n", pixma_strerror (error))); /* fall through */ case state_finished: query_status (s); query_status (s); activate (s, 0); if (! aborted && s->cfg->pid == IR1020_PID) { error = abort_session (s); if (error < 0) { PDBG (pixma_dbg (1, "WARNING:abort_session() failed %s\n", pixma_strerror (error))); query_status (s); query_status (s); activate (s, 0); } } mp->buf = mp->lbuf = mp->imgbuf = NULL; mp->state = state_idle; /* fall through */ case state_idle: break; } }
static void iclass_finish_scan (pixma_t * s) { int error; iclass_t *mf = (iclass_t *) s->subdriver; switch (mf->state) { /* fall through */ case state_warmup: case state_scanning: error = abort_session (s); if (error < 0) PDBG (pixma_dbg (1, "WARNING:abort_session() failed %s\n", pixma_strerror (error))); /* fall through */ case state_finished: query_status (s); query_status (s); if (mf->generation == 1) { /* activate only seen for generation 1 scanners */ activate (s, 0); query_status (s); } /* 0x38 = last block and ADF empty * 0x28 = last block and Paper in ADF */ if (mf->last_block==0x38 /* ADF empty */ || (mf->generation == 1 && mf->last_block == 0x28)) /* generation 1 scanner or Paper in ADF */ { PDBG (pixma_dbg (3, "*iclass_finish_scan***** abort session *****\n")); abort_session (s); } else PDBG (pixma_dbg (3, "*iclass_finish_scan***** wait for next page from ADF *****\n")); mf->state = state_idle; /* fall through */ case state_idle: break; } }
static int iclass_open (pixma_t * s) { iclass_t *mf; uint8_t *buf; mf = (iclass_t *) calloc (1, sizeof (*mf)); if (!mf) return PIXMA_ENOMEM; buf = (uint8_t *) malloc (CMDBUF_SIZE); if (!buf) { free (mf); return PIXMA_ENOMEM; } s->subdriver = mf; mf->state = state_idle; mf->cb.buf = buf; mf->cb.size = CMDBUF_SIZE; mf->cb.res_header_len = 2; mf->cb.cmd_header_len = 10; mf->cb.cmd_len_field_ofs = 7; /* set generation = 2 for new multifunctionals * some new scanners use generation 1 protocol */ mf->generation = (s->cfg->pid >= MF8030_PID && s->cfg->pid != MF8200_PID && s->cfg->pid != MF8500_PID) ? 2 : 1; PDBG (pixma_dbg (3, "*iclass_open***** This is a generation %d scanner. *****\n", mf->generation)); PDBG (pixma_dbg (3, "Trying to clear the interrupt buffer...\n")); if (handle_interrupt (s, 200) == 0) { PDBG (pixma_dbg (3, " no packets in buffer\n")); } return 0; }
static void find_scanners (void) { unsigned i, nscanners; cleanup_device_list (); nscanners = pixma_find_scanners (conf_devices); PDBG (pixma_dbg (3, "pixma_find_scanners() found %u devices\n", nscanners)); dev_list = (const SANE_Device **) calloc (nscanners + 1, sizeof (*dev_list)); if (!dev_list) return; for (i = 0; i != nscanners; i++) { SANE_Device *sdev = (SANE_Device *) calloc (1, sizeof (*sdev)); char *name, *model; if (!sdev) goto nomem; name = strdup (pixma_get_device_id (i)); model = strdup (pixma_get_device_model (i)); if (!name || !model) { free (name); free (model); free (sdev); goto nomem; } sdev->name = name; sdev->model = model; sdev->vendor = vendor_str; sdev->type = type_str; dev_list[i] = sdev; } /* dev_list is already NULL terminated by calloc(). */ return; nomem: PDBG (pixma_dbg (1, "WARNING:not enough memory for device list\n")); return; }
static int query_status (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_status, 0, 12); error = pixma_exec (s, &mp->cb); if (error >= 0) { memcpy (mp->current_status, data, 12); PDBG (pixma_dbg (3, "Current status: paper=%u cal=%u lamp=%u\n", data[1], data[8], data[7])); } return error; }
static int mp730_scan (pixma_t * s) { int error, n; mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *buf; if (mp->state != state_idle) return PIXMA_EBUSY; /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } mp->raw_width = calc_raw_width (s, s->param); PDBG (pixma_dbg (3, "raw_width = %u\n", mp->raw_width)); n = IMAGE_BLOCK_SIZE / s->param->line_size + 1; buf = (uint8_t *) malloc ((n + 1) * s->param->line_size + IMAGE_BLOCK_SIZE); if (!buf) return PIXMA_ENOMEM; mp->buf = buf; mp->lbuf = buf; mp->imgbuf = buf + n * s->param->line_size; mp->imgbuf_len = 0; error = step1 (s); if (error >= 0) error = start_session (s); if (error >= 0) mp->state = state_scanning; if (error >= 0) error = select_source (s); if (error >= 0) error = send_scan_param (s); if (error < 0) { mp730_finish_scan (s); return error; } mp->last_block = 0; return 0; }
static int read_image_block (pixma_t * s, uint8_t * data) { int count, temp; count = pixma_read (s->io, data, IMAGE_BLOCK_SIZE); if (count < 0) return count; if (count == IMAGE_BLOCK_SIZE) { int error = pixma_read (s->io, &temp, 0); if (error < 0) { PDBG (pixma_dbg (1, "WARNING: reading zero-length packet failed %d\n", error)); } } return count; }
static int send_time (pixma_t * s) { /* Why does a scanner need a time? */ time_t now; struct tm *t; uint8_t *data; mp730_t *mp = (mp730_t *) s->subdriver; data = pixma_newcmd (&mp->cb, cmd_time, 20, 0); pixma_get_time (&now, NULL); t = localtime (&now); snprintf ((char *) data, 16, "%02d/%02d/%02d %02d:%02d", t->tm_year % 100, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min); PDBG (pixma_dbg (3, "Sending time: '%s'\n", (char *) data)); return pixma_exec (s, &mp->cb); }
static int request_image_block (pixma_t * s, unsigned flag, uint8_t * info, unsigned * size, uint8_t * data, unsigned * datalen) { iclass_t *mf = (iclass_t *) s->subdriver; int error; unsigned expected_len; const int hlen = 2 + 6; memset (mf->cb.buf, 0, 11); pixma_set_be16 (((mf->generation >= 2) ? cmd_read_image2 : cmd_read_image), mf->cb.buf); mf->cb.buf[8] = flag; mf->cb.buf[10] = 0x06; expected_len = (mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) ? 512 : hlen; mf->cb.reslen = pixma_cmd_transaction (s, mf->cb.buf, 11, mf->cb.buf, expected_len); if (mf->cb.reslen >= hlen) { *info = mf->cb.buf[2]; *size = pixma_get_be16 (mf->cb.buf + 6); /* 16bit size */ error = 0; if (mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) { /* 32bit size */ *datalen = mf->cb.reslen - hlen; *size = (*datalen + hlen == 512) ? pixma_get_be32 (mf->cb.buf + 4) - *datalen : 0; memcpy (data, mf->cb.buf + hlen, *datalen); } PDBG (pixma_dbg (11, "*request_image_block***** size = %u *****\n", *size)); } else { error = PIXMA_EPROTO; } return error; }
static int handle_interrupt (pixma_t * s, int timeout) { uint8_t buf[16]; int len; len = pixma_wait_interrupt (s->io, buf, sizeof (buf), timeout); if (len == PIXMA_ETIMEDOUT) return 0; if (len < 0) return len; if (len != 16) { PDBG (pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } if (buf[12] & 0x40) query_status (s); if (buf[15] & 1) s->events = PIXMA_EV_BUTTON1; return 1; }
static int mp750_scan (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; int error; uint8_t *buf; unsigned size, dpi, spare; dpi = s->param->ydpi; /* add a stripe shift for 2400dpi */ mp->stripe_shift = (dpi == 2400) ? 4 : 0; if (mp->state != state_idle) return PIXMA_EBUSY; /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } /* if (s->param->channels == 1) mp->raw_width = ALIGN_SUP (s->param->w, 12); else mp->raw_width = ALIGN_SUP (s->param->w, 4);*/ /* change to use CCD grayscale mode --- why does this give segmentation error at runtime in mp750_check_param? */ if ((s->param->channels == 3) || (is_ccd_grayscale (s))) mp->raw_width = ALIGN_SUP (s->param->w, 4); else mp->raw_width = ALIGN_SUP (s->param->w, 12); /* not sure about MP750, but there is no need for aligning at 12 for the MP760/770, MP780/790 since always use CCD color mode */ /* modify for stripe shift */ spare = 2 * calc_component_shifting (s) + 2 * mp->stripe_shift; /* FIXME: or maybe (2*... + 1)? */ mp->raw_height = s->param->h + spare; PDBG (pixma_dbg (3, "raw_width=%u raw_height=%u dpi=%u\n", mp->raw_width, mp->raw_height, dpi)); /* PDBG (pixma_dbg (4, "line_size=%"PRIu64"\n",s->param->line_size)); */ mp->line_size = get_cis_ccd_line_size (s); /* scanner hardware line_size multiplied by 3 for CCD grayscale */ size = 8 + 2 * IMAGE_BLOCK_SIZE + spare * mp->line_size; buf = (uint8_t *) malloc (size); if (!buf) return PIXMA_ENOMEM; mp->buf = buf; mp->rawimg = buf; mp->imgbuf_ofs = spare * mp->line_size; mp->imgcol = mp->rawimg + IMAGE_BLOCK_SIZE + 8; /* added to make rgb->gray */ mp->img = mp->rawimg + IMAGE_BLOCK_SIZE + 8; mp->imgbuf_len = IMAGE_BLOCK_SIZE + mp->imgbuf_ofs; mp->rawimg_left = 0; mp->last_block_size = 0; mp->shifted_bytes = -(int) mp->imgbuf_ofs; error = step1 (s); if (error >= 0) error = start_session (s); if (error >= 0) mp->state = state_warmup; if (error >= 0) error = select_source (s); if (error >= 0) error = send_scan_param (s); if (error < 0) { mp750_finish_scan (s); return error; } return 0; }
static int mp730_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { int error, n; mp730_t *mp = (mp730_t *) s->subdriver; unsigned block_size, bytes_received; uint8_t header[16]; do { do { if (s->cancel) return PIXMA_ECANCELED; if (mp->last_block) /* end of image */ return 0; error = read_image_block (s, header, mp->imgbuf + mp->imgbuf_len); if (error < 0) return error; bytes_received = error; block_size = pixma_get_be16 (header + 4); mp->last_block = ((header[2] & 0x28) == 0x28); if (mp->last_block) { /* end of image */ mp->state = state_finished; } if ((header[2] & ~0x38) != 0) { PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n")); PDBG (pixma_hexdump (1, header, 16)); } PASSERT (bytes_received == block_size); if (block_size == 0) { /* no image data at this moment. */ /*pixma_sleep(100000); *//* FIXME: too short, too long? */ handle_interrupt (s, 100); } } while (block_size == 0); /* TODO: simplify! */ mp->imgbuf_len += bytes_received; n = mp->imgbuf_len / s->param->line_size; /* n = number of full lines (rows) we have in the buffer. */ if (n != 0) { if (s->param->channels != 1 && s->cfg->pid != MF5730_PID && s->cfg->pid != MF5750_PID && s->cfg->pid != MF5770_PID && s->cfg->pid != MF3110_PID && s->cfg->pid != IR1020_PID) { /* color, and not an MF57x0 nor MF3110 */ pack_rgb (mp->imgbuf, n, mp->raw_width, mp->lbuf); } else /* grayscale/lineart or MF57x0 or MF3110 */ memcpy (mp->lbuf, mp->imgbuf, n * s->param->line_size); block_size = n * s->param->line_size; mp->imgbuf_len -= block_size; memcpy (mp->imgbuf, mp->imgbuf + block_size, mp->imgbuf_len); } } while (n == 0); ib->rptr = mp->lbuf; ib->rend = mp->lbuf + block_size; return ib->rend - ib->rptr; }
static int iclass_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { int error, n; iclass_t *mf = (iclass_t *) s->subdriver; unsigned block_size, lines_size, first_block_size; uint8_t info; /* * 1. send a block request cmd (d4 20 00... 04 00 06) * 2. examine the response for block size and/or end-of-scan flag * 3. read the block one chunk at a time * 4. repeat until have enough to process >=1 lines */ do { do { if (s->cancel) return PIXMA_ECANCELED; if (mf->last_block) { /* end of image */ mf->state = state_finished; return 0; } first_block_size = 0; error = request_image_block (s, 4, &info, &block_size, mf->blkptr + mf->blk_len, &first_block_size); /* add current block to remainder of previous */ mf->blk_len += first_block_size; if (error < 0) { /* NOTE: seen in traffic logs but don't know the meaning. */ read_error_info (s, NULL, 0); if (error == PIXMA_ECANCELED) return error; } /* info: 0x28 = end; 0x38 = end + ADF empty */ mf->last_block = info & 0x38; if ((info & ~0x38) != 0) { PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n")); PDBG (pixma_hexdump (1, &info, 1)); } if (block_size == 0) { /* no image data at this moment. */ /*pixma_sleep(100000); *//* FIXME: too short, too long? */ handle_interrupt (s, 100); } } while (block_size == 0 && first_block_size == 0); error = read_image_block (s, mf->blkptr + mf->blk_len, block_size); block_size = error; if (error < 0) return error; /* add current block to remainder of previous */ mf->blk_len += block_size; /* n = number of full lines (rows) we have in the buffer. */ n = mf->blk_len / s->param->line_size; if (n != 0) { if (s->param->channels != 1 && s->cfg->pid != MF3010_PID && s->cfg->pid != MF4410_PID && s->cfg->pid != MF4770_PID && s->cfg->pid != MF4550_PID && s->cfg->pid != MF4600_PID && s->cfg->pid != MF6500_PID && s->cfg->pid != MF8030_PID) { /* color and not MF46xx or MF65xx */ pack_rgb (mf->blkptr, n, mf->raw_width, mf->lineptr); } else { /* grayscale */ memcpy (mf->lineptr, mf->blkptr, n * s->param->line_size); } lines_size = n * s->param->line_size; /* cull remainder and shift left */ mf->blk_len -= lines_size; memcpy (mf->blkptr, mf->blkptr + lines_size, mf->blk_len); } } while (n == 0); /* output full lines, keep partial lines for next block */ ib->rptr = mf->lineptr; ib->rend = mf->lineptr + lines_size; return ib->rend - ib->rptr; }
static int mp750_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { mp750_t *mp = (mp750_t *) s->subdriver; int error; uint8_t info; unsigned block_size, bytes_received, n; int shift[3], base_shift; int c; c = ((is_ccd_grayscale (s)) ? 3 : s->param->channels) * s->param->depth / 8; /* single-byte or double-byte data */ if (mp->state == state_warmup) { int tmo = 60; query_status (s); check_status (s); /*SIM*/ while (!is_calibrated (s) && --tmo >= 0) { if (s->cancel) return PIXMA_ECANCELED; if (handle_interrupt (s, 1000) > 0) { block_size = 0; error = request_image_block (s, &block_size, &info); /*SIM*/ if (error < 0) return error; } } if (tmo < 0) { PDBG (pixma_dbg (1, "WARNING: Timed out waiting for calibration\n")); return PIXMA_ETIMEDOUT; } pixma_sleep (100000); query_status (s); if (is_warming_up (s) || !is_calibrated (s)) { PDBG (pixma_dbg (1, "WARNING: Wrong status: wup=%d cal=%d\n", is_warming_up (s), is_calibrated (s))); return PIXMA_EPROTO; } block_size = 0; request_image_block (s, &block_size, &info); /*SIM*/ mp->state = state_scanning; mp->last_block = 0; } /* TODO: Move to other place, values are constant. */ base_shift = calc_component_shifting (s) * mp->line_size; if (s->param->source == PIXMA_SOURCE_ADF) { shift[0] = 0; shift[1] = -base_shift; shift[2] = -2 * base_shift; } else { shift[0] = -2 * base_shift; shift[1] = -base_shift; shift[2] = 0; } do { if (mp->last_block_size > 0) { block_size = mp->imgbuf_len - mp->last_block_size; memcpy (mp->img, mp->img + mp->last_block_size, block_size); } do { if (s->cancel) return PIXMA_ECANCELED; if (mp->last_block) { /* end of image */ info = mp->last_block; if (info != 0x38) { query_status (s); /*SIM*/ while ((info & 0x28) != 0x28) { pixma_sleep (10000); error = request_image_block2 (s, &info); if (s->cancel) return PIXMA_ECANCELED; /* FIXME: Is it safe to cancel here? */ if (error < 0) return error; } } mp->needs_abort = (info != 0x38); mp->last_block = info; mp->state = state_finished; return 0; } check_status (s); /*SIM*/ while (handle_interrupt (s, 1) > 0); /*SIM*/ block_size = IMAGE_BLOCK_SIZE; error = request_image_block (s, &block_size, &info); if (error < 0) { if (error == PIXMA_ECANCELED) read_error_info (s, NULL, 0); return error; } mp->last_block = info; if ((info & ~0x38) != 0) { PDBG (pixma_dbg (1, "WARNING: Unknown info byte %x\n", info)); } if (block_size == 0) { /* no image data at this moment. */ pixma_sleep (10000); } } while (block_size == 0); error = read_image_block (s, mp->rawimg + mp->rawimg_left); if (error < 0) { mp->state = state_transfering; return error; } bytes_received = error; PASSERT (bytes_received == block_size); /* TODO: simplify! */ mp->rawimg_left += bytes_received; n = mp->rawimg_left / 3; /* n = number of pixels in the buffer? */ /* Color to Grayscale converion for CCD sensor */ if (is_ccd_grayscale (s)) { shift_rgb (mp->rawimg, n, shift[0], shift[1], shift[2], mp->stripe_shift, mp->line_size, mp->imgcol + mp->imgbuf_ofs); /* dst: img, src: imgcol */ rgb_to_gray (mp->img, mp->imgcol, n, c); /* cropping occurs later? */ PDBG (pixma_dbg (4, "*fill_buffer: did grayscale conversion \n")); } /* Color image processing */ else { shift_rgb (mp->rawimg, n, shift[0], shift[1], shift[2], mp->stripe_shift, mp->line_size, mp->img + mp->imgbuf_ofs); PDBG (pixma_dbg (4, "*fill_buffer: no grayscale conversion---keep color \n")); } /* entering remaining unprocessed bytes after last complete pixel into mp->rawimg buffer -- no influence on mp->img */ n *= 3; mp->shifted_bytes += n; mp->rawimg_left -= n; /* rawimg_left = 0, 1 or 2 bytes left in the buffer. */ mp->last_block_size = n; memcpy (mp->rawimg, mp->rawimg + n, mp->rawimg_left); } while (mp->shifted_bytes <= 0); if ((unsigned) mp->shifted_bytes < mp->last_block_size) { if (is_ccd_grayscale (s)) ib->rptr = mp->img + mp->last_block_size/3 - mp->shifted_bytes/3; /* testing---works OK */ else ib->rptr = mp->img + mp->last_block_size - mp->shifted_bytes; } else ib->rptr = mp->img; if (is_ccd_grayscale (s)) ib->rend = mp->img + mp->last_block_size/3; /* testing---works OK */ else ib->rend = mp->img + mp->last_block_size; return ib->rend - ib->rptr; }
static int step1 (pixma_t * s) { int error, tmo; error = query_status (s); if (error < 0) return error; if ((s->param->source == PIXMA_SOURCE_ADF || s->param->source == PIXMA_SOURCE_ADFDUP) && !has_paper (s)) return PIXMA_ENO_PAPER; if (has_ccd_sensor (s)) { switch (s->cfg->pid) { case MF5730_PID: case MF5750_PID: case MF5770_PID: /* MF57x0: Wait 10 sec before starting for 1st page only */ if (s->param->adf_pageid == 0) { tmo = 10; /* like Windows driver, 10 sec CCD calibration ? */ while (--tmo >= 0) { error = handle_interrupt (s, 1000); \ if (s->cancel) \ return PIXMA_ECANCELED; \ if (error != PIXMA_ECANCELED && error < 0) \ return error; PDBG (pixma_dbg (2, "CCD Calibration ends in %d sec.\n", tmo)); } } break; default: break; } activate (s, 0); error = calibrate (s); switch (s->cfg->pid) { case MF5730_PID: case MF5750_PID: case MF5770_PID: /* MF57x0: calibration returns PIXMA_STATUS_FAILED */ if (error == PIXMA_ECANCELED) error = read_error_info (s, NULL, 0); break; default: break; } } if (error >= 0) error = activate (s, 0); if (error >= 0) error = activate (s, 4); return error; }
static int handle_interrupt (pixma_t * s, int timeout) { uint8_t buf[16]; int len; len = pixma_wait_interrupt (s->io, buf, sizeof (buf), timeout); if (len == PIXMA_ETIMEDOUT) return 0; if (len < 0) return len; switch (s->cfg->pid) { case MP360_PID: case MP370_PID: case MP375R_PID: case MP390_PID: case MF5730_PID: case MF5750_PID: case MF5770_PID: case MF3110_PID: case IR1020_PID: if (len != 16) { PDBG (pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } if (buf[12] & 0x40) query_status (s); if (buf[10] & 0x40) send_time (s); /* FIXME: following is unverified! */ if (buf[15] & 1) s->events = PIXMA_EV_BUTTON2; /* b/w scan */ if (buf[15] & 2) s->events = PIXMA_EV_BUTTON1; /* color scan */ break; case MP700_PID: case MP730_PID: case MP710_PID: case MP740_PID: if (len != 8) { PDBG (pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } if (buf[7] & 0x10) s->events = PIXMA_EV_BUTTON1; if (buf[5] & 8) send_time (s); break; default: PDBG (pixma_dbg (1, "WARNING:unknown interrupt, please report!\n")); PDBG (pixma_hexdump (1, buf, len)); } return 1; }