Re: The calibration function for CanoScanFB620S

From: abel deuring (a.deuring@satzbau-gmbh.de)
Date: Fri Dec 08 2000 - 13:05:25 PST

  • Next message: Henning Meier-Geinitz: "Re: xscanimage"

    Hi Mitsuru,

    > I tried to write the Calibration function as follows.
    > Are they correct ?

    They are in general correct -- but they _might_ be one problem: The
    command code 0xc1, 0xc2 and so on are "vendor specific", meaning that
    they are not part of the SCSI standard. And here, the function
    sanei_scsi_cmd has a serious problem: The SCSI command itself and data
    is placed into _one_ buffer. The SCSI command consists of the first 6,
    10 or 12 bytes of the buffer; the remaining part of the of the buffer is
    the data to be sent to the scanner. On the way "down to the SCSI bus",
    these two parts - command block and data block - must be separated. For
    most operating systems, this is done in sanei_scsi.c, function
    sanei_scsi_cmd; for older versions of the Linux SG driver, it is done by
    the SG driver.

    The problem is in any case, that either the SG driver or sanei_scsi_cmd
    must "guess" the command length. This works fine for well standardized
    commands, but the guess was wrong for the "set adf mode" command (0xd4)
    and the "get scan mode" command (0xd5) for Canon scanners. For the old
    SG driver, Manuel Panea suggested a patch to the SG driver, but of
    course that did not help for other operatiing systems. Therefore, I
    introduced the function sanei_scsi_cmd2 (and sanei_scsi_req_enter2 --
    but this funtion is not used in the Canon backend), which allows to use
    separate buffers for the command and the data, and which allows to
    declare explicitly the command length.

    Therefore, if your functions return only some error, you should consider
    to use sanei_scsi_cmd2. Below are the suggsted modifications, assuming
    that all SCSI commands you are using are 6 byte commands.

    The function sanei_scsi_cmd2 has the following parameters:

            sanei_scsi_cmd2(fd, const void* cmd, size_t cmd_size,
                            const void* src, size_t src_size,
                            void* dst, size_t* dst_size)

            fd is the file descriptor
            cmd points to the SCSI command block (6 or 10 or 12 bytes)
            cmd_size gives the command length (6 or 10 or 12)
            src points to a data block to be sent to the scanner
            src_size gives the length of the data block to be sent
            dst points to a buffer that will store the data returned by the scanner
            dst_size gives on entry to the function the epected size of the data
                     returned by the scanner; on return it contains the number of
                    bytes actually returned.

    A SCSI command can either send data to the device or it can receive data
    from the device. Thus, it should not happen that both dst and src are
    non-zero. Practically:

            src dst result
            0 0 no data transfer
            non-zero 0 send data to the scanner
            0 non-zero receive data from the scanner
            non-zero non-zero forbidden

    > for canon-scsi.c
    (that's the correct place, I think)

    > ===================================================================
    > static SANE_Status
    > reset_scanner (int fd)
    > {
    > static u_char cmd[10];
    > int status;
    > DBG (31, ">> reset_scanner\n");
    >
    > memset (cmd, 0, sizeof (cmd));
    > cmd[0] = 0xc1;
    > status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
        status = sanei_scsi_cmd2(fd, cmd, sizeof (cmd), 0, 0, 0, 0);

    Perhaps you need to try the function above with "static u_char cmd[6];"
    or with "static u_char cmd[12];" Or you can try

        status = sanei_scsi_cmd2(fd, cmd, 6, 0, 0, 0, 0);

    >
    > DBG (31, "<< reset_scanner\n");
    > return (status);
    > }
    >
    > static SANE_Status
    > execute_calibration (int fd)
    > {
    > static u_char cmd[6 + 2];
    > int status;
    > DBG (31, ">> execute_calibration\n");
    > memset (cmd, 0, sizeof (cmd));
    > cmd[0] = 0xc2;
    > cmd[4] = 2;
    > status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
    > DBG (31, "<< execute_calibration\n");
    > return (status);
    > }

    With sanei_scsi_cmd2, this function might be:

     static SANE_Status
     execute_calibration (int fd)
     {
       static u_char cmd[6]; /* or 10 or 12... */
       u_char data[2];
       int status;
       DBG (31, ">> execute_calibration\n");
       memset (cmd, 0, sizeof (cmd));
       memset (data, 0, sizeof (data));
       cmd[0] = 0xc2;
       cmd[4] = 2;
       status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), data, sizeof(data),
    0, 0);
       DBG (31, "<< execute_calibration\n");
       return (status);
     }

    >
    > static SANE_Status
    > get_calibration_status (int fd, void *buf, size_t *buf_size)
    > {
    > static u_char cmd[6]; /* or 10 or 12 */
    > int status;
    > DBG (31, ">> get_calibration_status\n");
    > memset (cmd, 0, sizeof (cmd));
    > cmd[0] = 0xc3;
    > cmd[4] = 2;
    > status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size);
    Try
        status = sanei_scsi_cmd2(fd, cmd, sizeof (cmd), 0, 0, buf,
    buf_size);

    > DBG (31, "<< get_calibration_status\n");
    > return (status);
    > }
    >
    > static SANE_Status
    > get_switch_status (int fd, void *buf, size_t *buf_size)
    > {
    > static u_char cmd[6]; /* or 10 or 12 ?? */
    > int status;
    > DBG (31, ">> get_switch_status\n");
    > memset (cmd, 0, sizeof (cmd));
    > cmd[0] = 0xc4;
    > cmd[4] = 2;
    > status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size);
    Try
        status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), 0, 0, buf,
    buf_size);

    > DBG (31, "<< get_switch_status\n");
    > return (status);
    > }

    The call to the calibration functions should happen in sane_start, I
    think. The idea of calibration is to compensate changing illumination
    conditions. Especially after switching on the scanner, the lamp needs
    some time to heat up into a "stable" state. Before the lamp stabilizes,
    the spectral distribution of the emitted light may change. Thus, it is
    probably best to do the calibration immediately before a scan starts.

    > ===================================================================
    >
    > for canon.c or canon-sane.c
    > ===================================================================
    > status = reset_scanner(s->fd);
    > if (status != SANE_STATUS_GOOD)
    > {
    > DBG (1, "attach: RESET SCANNER failed\n");
    > sanei_scsi_close (s->fd);
    > s->fd = -1;
    > }
    >
    > status = execute_calibration(s->fd);
    > if (status != SANE_STATUS_GOOD)
    > {
    > DBG (1, "attach: EXECUTE CALIBRATION failed\n");
    > sanei_scsi_close (s->fd);
    > s->fd = -1;
    > }
    >
    > DBG (3, "sane_start: sending GET CALIBRATION STATUS\n");
    > memset (ebuf, 0, sizeof (ebuf));
    > buf_size = sizeof (ebuf);
    > status = get_calibration_status (s->fd, ebuf, &buf_size);
    > if (status != SANE_STATUS_GOOD)
    > {
    > DBG (1, "sane_start: GET CALIBRATION STATUS failed\n");
    > sanei_scsi_close (s->fd);
    > return (SANE_STATUS_INVAL);
    > }
    >
    > DBG (3, "sane_start: sending GET SWITCH STATUS\n");
    > memset (ebuf, 0, sizeof (ebuf));
    > buf_size = sizeof (ebuf);
    > status = get_switch_status (s->fd, ebuf, &buf_size);
    > if (status != SANE_STATUS_GOOD)
    > {
    > DBG (1, "sane_start: GET SWITCH STATUS failed\n");
    > sanei_scsi_close (s->fd);
    > return (SANE_STATUS_INVAL);
    > }

    bye
    Abel

    --
    Source code, list archive, and docs: http://www.mostang.com/sane/
    To unsubscribe: echo unsubscribe sane-devel | mail majordomo@mostang.com
    



    This archive was generated by hypermail 2b29 : Fri Dec 08 2000 - 11:58:44 PST