[sane-devel] RFC: proposal for an improved sanei_scsi library

abel deuring a.deuring@satzbau-gmbh.de
Sun, 08 Dec 2002 17:51:17 +0100


This is a multi-part message in MIME format.
--------------040005050005000808080300
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Henning Meier-Geinitz wrote:
>>Well, there is indeed not urgent need to change the interface for Sane1. 
>>But there were a few situations where I wished I had a somewhat cleaner 
>>interface at hand for Sane 1 ;) And it would not be difficult to write a 
>>compatibility layer for the current interface. But if Sane2 development 
>>is taking off soon, work on Sane1 would of course be useless.
> 
> 
> I hope It won't take too long to finish the core points of SANE2.

Sounds promising.

> 
> 
>>A SCSI device returns a status byte for every command, giving coarse 
>>information about the result of the command (GOOD/CHECK 
>>CONDITION/CONDITION MET/BUSY etc). A detailed description can be found 
>>in the SCSI2 draft, ftp://ftp.t10.org/t10/drafts/s2/s2-r10l.pdf , 
>>section 7.3. The SCSI reference manuals for the scanners should describe 
>>it too.
> 
> 
> SCSI reference manual for a scanner? Haha. Never seen such a beast.
> Either it's labeled "top secret" or it's written in Chinese. At least
> for "my" backends. :-)

Well, to be fair, some vendors are more helpful. I needed just one phone 
call to get the docs from Sharp; Fujitsu has many docs available at 
least on their European website; Epson publishes even some of their 
source code.

> For the status value, yes, but not for sb, as this is a buffer. All
> the other buffer pointers use void*. 

changed. See attachment.

>>>>* @param scsi_status the status returned by the device. 
>>>>*           xxx what about the situation, that the command has not been
>>>>*           issued, or other situations, where no status information
>>>>*           is available? Can this situation be detected for all supported
>>>>*           OSes? If that is possible, we should add another parameter 
>>>>which
>>>>*	     signals "SCSI status available"
>>>
>>>
>>>Maybe use the return value to flag this. I.e. i/o error: scsi_status
>>>has some meaning, invalid arg: something different went wrong.
>>
>>I don't like to put more semantics into the return status, But we could 
>>add another int* parameter which signals, if *scsi_status contains a 
>>valid value.
> 
> 
> Or use an int instead of a byte. -1 is "not applicable".

Sounds reasonable.

Abel



--------------040005050005000808080300
Content-Type: text/plain;
 name="sanei_scsi.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="sanei_scsi.h"

/** Find SCSI devices.
 *
 * Find each SCSI device that matches the pattern specified by the
 * arguments.  String arguments can be "omitted" by passing NULL,
 * integer arguments can be "omitted" by passing -1.
 *
 *   Example: vendor="HP" model=NULL, type=NULL, bus=3, id=-1, lun=-1 would
 *          attach all HP devices on SCSI bus 3.
 *
 * @param vendor vendor field of the SCSI INQUIRY data
 * @param model  model field of the SCSI INQUIRY data
 * @param type   type of the device. Should be "scanner" or "processor"
 * @param bus    number of the SCSI bus (for certain OSes, this field
 *               corresponds to the host adapter number)
 * @param channel channel of a bus/host adapter
 * @param id     SCSI ID
 * @param lun    SCSI LUN
 * @param attach callback invoked once for each device
 * @param dev real devicename (passed to attach callback)
 *
 */ 
extern void sanei2_scsi_find_devices (const char *vendor, const char *model,
				     const char *type,
				     int bus, int channel, int id, int lun,
				     SANE_Status (*attach) (const char *dev));


/** Open a SCSI device
 *
 * Opens a SCSI device by its device filename and returns a file descriptor.
 * The function tries to allocate a buffer of the size given by *buffersize.
 * If sanei2_scsi_open returns successfully, *buffersize contains the
 * available buffer size. This value may be both smaller or larger than the
 * value requested by the backend; it can even be zero. The backend must not
 * try to issue SCSI command with data blocks larger than given by the
 * value of *buffersize. The backend must decide, if it got enough buffer
 * memory to work.
 *
 * Note that the value of *buffersize may differ for different files and
 * even for consecutive calls for the same file.
 *
 * @param devicename name of the devicefile, e.g. "/dev/sg0"
 * @param fd file descriptor
 * @param timeout is the timeout in seconds for SCSI commands. The function
 *        may set *timeout to another value, if the requested timeout
 *	  could not be set.
 * @param buffersize size of the SCSI request buffer (in bytes)
 * 
 * @return 
 * - SANE_STATUS_GOOD - on success
 * - SANE_STATUS_ACCESS_DENIED - if the file couldn't be accessed due to
 *   permissions
 * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory)
 * - SANE_STATUS_INVAL - if the filename was invalid or an unknown error occured
 *
 */
extern SANE_Status sanei2_scsi_open (
       const char * device_name, int * fd,
       int *timeout, int *buffersize);

/** Macros for the parameter direction of sanei2_scsi_req_enter and sanei2_scsi_cmd
 *
 * @param SANEI_SCSI_DXFER_NONE  no data transfer
 * @param SANEI_SCSI_DXFER_TO_DEVICE data is sent to the device
 * @param SANEI_SCSI__DXFER_FROM_DEVICE data is received from the device
 */

#define SANEI_SCSI_DXFER_NONE 0
#define SANEI_SCSI_DXFER_TO_DEVICE 1
#define SANEI_SCSI__DXFER_FROM_DEVICE 2

/** Enqueue SCSI command
 *
 * One or more scsi commands can be enqueued by calling sanei2_scsi_req_enter().
 *
 * NOTE: Some systems may not support multiple outstanding commands.  On such
 * systems, sanei2_scsi_req_enter() may block.  In other words, it is not proper
 * to assume that enter() is a non-blocking routine.
 *
 * @param fd file descriptor
 * @param cmd pointer to SCSI command
 * @param cmd_size size of the command
 * @param buffer pointer to the buffer with data to be sent to / received from
 *        the scanner
 * @param buffer_size size of the data buffer
 * @param direction direction of the data transfer.
 * @param idp pointer to a void* that uniquely identifies the entered request
 * @return
 * - SANE_STATUS_GOOD - on success
 * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver
 * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory)
 * - SANE_STATUS_INVAL - if a locking or an unknown error occured
 * - SANE_STATUS_DEVICE_BUSY  - the SCSI command could not be issued; try
 *                       again later
 */
extern SANE_Status sanei2_scsi_req_enter (int fd,
					 const void * cmd, size_t cmd_size,
					 const void * buffer, size_t buffer_size,
					 int direction, void **idp);

/** Wait for SCSI command
 *
 * Wait for the completion of the SCSI command with id ID.  
 *
 * @param id id used in sanei2_scsi_req_enter()
 * @param sb pointer to a SANE_Byte array, where the SCSI sense data may be
 *           stored. The caller must allocate the necessary memory.
 *	     The parameter may be NULL.
 * @param sblen the length of the sense buffer allocated by the caller.
 *           On return, *sblen contains the number of bytes copied to the
 *	     sense buffer
 * @param scsi_status the status returned by the device. 
 *           A value of -1 means that no status data from the device is 
 *           available, e.g., because the command could not be sent
 *           to the device.
 *
 * @return
 * - SANE_STATUS_GOOD - on success
 * - SANE_STATUS_DEVICE_BUSY - if the device is busy (try again later)
 * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver
*/
extern SANE_Status sanei2_scsi_req_wait (void *id, u_int_8 *sb, size_t *sblen,
                                        int *scsi_status);

/** Send SCSI command
 *
 * This is a convenience function that is equivalent to a pair of
 * sanei2_scsi_req_enter()/sanei2_scsi_req_wait() calls.
 *
 * @param fd file descriptor
 * @param cmd pointer to SCSI command
 * @param cmd_size size of the command
 * @param buffer pointer to the buffer with data to be sent to / received from
          the scanner
 * @param buffer_size size of the data buffer
 * @param direction direction of the data transfer. Allowed value:
 *	  - SANE_SCSI_DXFER_NONE  no data transfer
 *        - SANE_SCSI_DXFER_TO_DEVICE data is sent to the device
 *	  - SANE_SCSI_DXFER_FROM_DEVICE data is received from the device
 * @param sb pointer to a SANE_Byte array, where the SCSI sense data may be
 *           stored. The caller must allocate the necessary memory.
 *	     The parameter may be NULL.
 * @param sblen the length of the sense buffer allocated by the caller.
 *           On return, *sblen contains the number of bytes copied to the
 *	     sense buffer
 * @param scsi_status the status returned by the device. 
 * @param scsi_status_valid If *scsi_status_valid is non-zero, *scsi_status
 *	     contains valid information; if it is zero, *scsi_status is 
 *           invalid.
 *
 * @return
 * - SANE_STATUS_GOOD - on success
 * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver
 * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory)
 * - SANE_STATUS_INVAL - if a locking or an unknown error occured
 * - SANE_STATUS_DEVICE_BUSY  - the SCSI command could not be issued; try
 *                       again later
 */
extern SANE_Status sanei2_scsi_cmd (int fd,
				   const void * cmd, size_t cmd_size,
				   const void * buffer, size_t buffer_size,
				   int direction, SANE_Byte *sb, size_t *sblen,
				   SANE_Byte *scsi_status);

/** Flush queue for handle
 *
 * Flush all SCSI commands pending for one handle
 *
 * @param fd file descriptor
 *
 */
extern void sanei2_scsi_req_flush_all (int fd);

/** Close a SCSI device
 *
 * @param fd file descriptor
 *
 */
extern void sanei2_scsi_close (int fd);

--------------040005050005000808080300--