blob: eb1403ba6f2640d65bca5f8f203031dc78709ff0 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LORGNETTE_SANE_DEVICE_H_
#define LORGNETTE_SANE_DEVICE_H_
#include <cstdint>
#include <cstdio>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include <brillo/errors/error.h>
#include <lorgnette/proto_bindings/lorgnette_service.pb.h>
#include <sane/sane.h>
#include "lorgnette/image_readers/image_reader.h"
#include "lorgnette/scan_parameters.h"
namespace lorgnette {
struct ValidOptionValues {
std::vector<uint32_t> resolutions;
std::vector<DocumentSource> sources;
std::vector<std::string> color_modes;
};
// This class represents an active connection to a scanning device.
// At most 1 active connection to a particular device is allowed at once.
// This class is thread-compatible, but not thread-safe.
class SaneDevice {
public:
virtual ~SaneDevice() {}
virtual std::optional<ValidOptionValues> GetValidOptionValues(
brillo::ErrorPtr* error) = 0;
virtual std::optional<int> GetScanResolution(brillo::ErrorPtr* error) = 0;
virtual bool SetScanResolution(brillo::ErrorPtr* error, int resolution) = 0;
virtual std::optional<std::string> GetDocumentSource(
brillo::ErrorPtr* error) = 0;
virtual bool SetDocumentSource(brillo::ErrorPtr* error,
const std::string& source_name) = 0;
virtual std::optional<ColorMode> GetColorMode(brillo::ErrorPtr* error) = 0;
virtual bool SetColorMode(brillo::ErrorPtr* error, ColorMode color_mode) = 0;
virtual bool SetScanRegion(brillo::ErrorPtr* error,
const ScanRegion& region) = 0;
virtual std::optional<ScannerConfig> GetCurrentConfig(
brillo::ErrorPtr* error) = 0;
virtual SANE_Status StartScan(brillo::ErrorPtr* error) = 0;
virtual SANE_Status GetScanParameters(brillo::ErrorPtr* error,
ScanParameters* params) = 0;
// PrepareImageReader() sets up an ImageReader to encode data read from the
// SANE backend into `format` and write it to `out_file`. If `expected_lines`
// is not NULL, it will be populated with the number of lines declared by the
// backend's GetScanParameters() result.
//
// This function must be called after StartScan() and before
// ReadEncodedData().
//
// Returns SANE_STATUS_GOOD if this object is ready to read encoded data from
// the scanner.
virtual SANE_Status PrepareImageReader(brillo::ErrorPtr* error,
ImageFormat format,
FILE* out_file,
size_t* expected_lines);
// ReadScanData() reads the next chunk of up to `count` bytes of raw SANE
// frame data into `buf`. If `read_out` is not NULL, it will be set to the
// number of bytes actually ready. Note that `read_out` can be 0 if no data
// was available when this function was called. Returns the SANE status from
// the underlying sane_read() call.
virtual SANE_Status ReadScanData(brillo::ErrorPtr* error,
uint8_t* buf,
size_t count,
size_t* read_out) = 0;
// ReadEncodedData reads a chunk of data from the SANE backend into an
// internal buffer, encodes as many complete lines as possible, and writes the
// result to the file set up with PrepareImageReader(). `encoded_bytes` will
// be set to the number of bytes written to the file, and `lines_read` will be
// set to the number of complete lines encoded. Any of the statuses returned
// by ReadScanData() can be returned; in addition, SANE_STATUS_IO_ERROR will
// be returned if there are errors encoding data or writing to the file.
virtual SANE_Status ReadEncodedData(brillo::ErrorPtr* error,
size_t* encoded_bytes,
size_t* lines_read);
// This function is thread-safe.
virtual bool CancelScan(brillo::ErrorPtr* error) = 0;
// SetOption attempts to set the value referenced by `option`. If needed, it
// will reload all the SANE options. The return value will be
// SANE_STATUS_GOOD if everything succeeded. Otherwise SetOption can return
// the error from setting the option or an error from reloading options.
virtual SANE_Status SetOption(brillo::ErrorPtr* error,
const ScannerOption& option) = 0;
// MIME types for image formats that can be returned from this scanner.
std::vector<std::string> GetSupportedFormats() const;
std::optional<std::string> GetCurrentJob() const;
protected:
void StartJob();
void EndJob();
private:
std::optional<std::string> current_job_;
std::optional<ScanParameters> scan_params_;
std::unique_ptr<ImageReader> image_reader_;
std::vector<uint8_t> image_buffer_;
size_t buffer_used_ = 0;
size_t completed_lines_ = 0;
};
} // namespace lorgnette
#endif // LORGNETTE_SANE_DEVICE_H_