void tcp_dev_close (struct device *dev) { if (!dev) return; DBG (3, "%s: closing dev %p\n", __FUNCTION__, (void *)dev); /* finish all operations */ if (dev->scanning) { dev->cancel = 1; /* flush READ_IMAGE data */ if (dev->reading) sane_read(dev, NULL, 1, NULL); /* send cancel if not sent before */ if (dev->state != SANE_STATUS_CANCELLED) ret_cancel(dev, 0); } sanei_tcp_close(dev->dn); dev->dn = -1; }
/* 1: image is acquired, 0: error or non_blocking mode */ static int dev_acquire(struct device *dev) { if (!dev_cmd_wait(dev, CMD_READ)) return dev->state; dev->state = SANE_STATUS_GOOD; dev->vertical = dev->res[0x08] << 8 | dev->res[0x09]; dev->horizontal = dev->res[0x0a] << 8 | dev->res[0x0b]; dev->blocklen = dev->res[4] << 24 | dev->res[5] << 16 | dev->res[6] << 8 | dev->res[7]; dev->final_block = (dev->res[3] == MSG_END_BLOCK)? 1 : 0; dev->pixels_per_line = dev->horizontal; dev->bytes_per_line = dev->horizontal; if (dev->composition == MODE_RGB24) dev->bytes_per_line *= 3; else if (dev->composition == MODE_LINEART || dev->composition == MODE_HALFTONE) dev->pixels_per_line *= 8; DBG (4, "acquiring, size per band v: %d, h: %d, %sblock: %d, slack: %d\n", dev->vertical, dev->horizontal, dev->final_block? "last " : "", dev->blocklen, dev->blocklen - (dev->vertical * dev->bytes_per_line)); if (dev->bytes_per_line > DATASIZE) { DBG (1, "%s: unsupported line size: %d bytes > %d\n", __FUNCTION__, dev->bytes_per_line, DATASIZE); return ret_cancel(dev, SANE_STATUS_NO_MEM); } dev->reading = 0; /* need to issue READ_IMAGE */ dev->dataindex = 0; dev->datalen = 0; dev->dataoff = 0; return 1; }
static int cancelled(struct device *dev) { if (dev->cancel) return ret_cancel(dev, 1); return 0; }
SANE_Status sane_start (SANE_Handle h) { struct device *dev = h; DBG (3, "%s: %p\n", __FUNCTION__, h); dev->cancel = 0; dev->scanning = 0; dev->total_img_size = 0; dev->total_out_size = 0; dev->total_data_size = 0; dev->blocks = 0; if (!dev->reserved) { if (!dev_cmd_wait(dev, CMD_RESERVE_UNIT)) return dev->state; dev->reserved++; } if (!dev_set_window(dev) || (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY)) return dev_stop(dev); if (!dev_cmd_wait(dev, CMD_OBJECT_POSITION)) return dev_stop(dev); if (!dev_cmd(dev, CMD_READ) || (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY)) return dev_stop(dev); dev->scanning = 1; dev->final_block = 0; dev->blocklen = 0; dev->pixels_per_line = 0; dev->bytes_per_line = 0; dev->ulines = 0; set_parameters(dev); if (!dev->data && !(dev->data = malloc(DATASIZE))) return ret_cancel(dev, SANE_STATUS_NO_MEM); if (!dev_acquire(dev)) return dev->state; /* make sure to have dev->para <= of real size */ if (dev->para.pixels_per_line > dev->pixels_per_line) { dev->para.pixels_per_line = dev->pixels_per_line; dev->para.bytes_per_line = dev->pixels_per_line; } if (dev->composition == MODE_RGB24) dev->para.bytes_per_line = dev->para.pixels_per_line * 3; else if (dev->composition == MODE_LINEART || dev->composition == MODE_HALFTONE) { dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8; dev->para.pixels_per_line = dev->para.bytes_per_line * 8; } else { dev->para.bytes_per_line = dev->para.pixels_per_line; } dev->total_img_size = dev->para.bytes_per_line * dev->para.lines; return SANE_STATUS_GOOD; }
SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * lenp) { SANE_Status status; struct device *dev = h; DBG (3, "%s: %p, %p, %d, %p\n", __FUNCTION__, h, buf, maxlen, (void *)lenp); if (lenp) *lenp = 0; if (!dev) return SANE_STATUS_INVAL; if (!dev->scanning) return SANE_STATUS_EOF; /* if there is no data to read or output from buffer */ if (!dev->blocklen && dev->datalen <= PADDING_SIZE) { /* and we don't need to acquire next block */ if (dev->final_block) { int slack = dev->total_img_size - dev->total_out_size; /* but we may need to fill slack */ if (buf && lenp && slack > 0) { *lenp = fill_slack(dev, buf, maxlen); dev->total_out_size += *lenp; DBG (9, "<> slack: %d, filled: %d, maxlen %d\n", slack, *lenp, maxlen); return SANE_STATUS_GOOD; } else if (slack < 0) { /* this will never happen */ DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size); } /* that's all */ dev_stop(dev); return SANE_STATUS_EOF; } /* queue next image block */ if (!dev_acquire(dev)) return dev->state; } if (!dev->reading) { if (cancelled(dev)) return dev->state; DBG (5, "READ_IMAGE\n"); if (!dev_cmd(dev, CMD_READ_IMAGE)) return SANE_STATUS_IO_ERROR; dev->reading++; dev->ulines += dev->vertical; dev->y_off = dev->ulines - dev->vertical; dev->total_data_size += dev->blocklen; dev->blocks++; } do { size_t datalen; int clrlen; /* cleared lines len */ int olen; /* output len */ /* read as much data into the buffer */ datalen = DATAROOM(dev) & USB_BLOCK_MASK; while (datalen && dev->blocklen) { SANE_Byte *rbuf = dev->data + DATATAIL(dev); DBG (9, "<> request len: %lu, [%d, %d; %d]\n", (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen); if ((status = dev->io->dev_request(dev, NULL, 0, rbuf, &datalen)) != SANE_STATUS_GOOD) return status; dev->datalen += datalen; dev->blocklen -= datalen; DBG (9, "<> got %lu, [%d, %d; %d]\n", (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen); if (dev->blocklen < 0) return ret_cancel(dev, SANE_STATUS_IO_ERROR); datalen = DATAROOM(dev) & USB_BLOCK_MASK; } if (buf && lenp) { /* read mode */ /* copy will do minimal of valid data */ if (dev->para.format == SANE_FRAME_RGB && dev->line_order) clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen); else clrlen = copy_plain_trim(dev, buf, maxlen, &olen); dev->datalen -= clrlen; dev->dataoff = (dev->dataoff + clrlen) & DATAMASK; buf += olen; maxlen -= olen; *lenp += olen; dev->total_out_size += olen; DBG (9, "<> olen: %d, clrlen: %d, blocklen: %d/%d, maxlen %d (%d %d %d)\n", olen, clrlen, dev->blocklen, dev->datalen, maxlen, dev->dataindex / dev->bytes_per_line + dev->y_off, dev->y_off, dev->para.lines); /* slack beyond last line */ if (dev->dataindex / dev->bytes_per_line + dev->y_off >= dev->para.lines) { dev->datalen = 0; dev->dataoff = 0; } if (!clrlen || maxlen <= 0) break; } else { /* flush mode */ dev->datalen = 0; dev->dataoff = 0; } } while (dev->blocklen); if (lenp) DBG (9, " ==> %d\n", *lenp); return SANE_STATUS_GOOD; }