lorgnette: Add SaneGetParameters to SaneClient

Add SaneGetParameters to the SaneClient interface, and add a real and
a fake implementation. For now, SaneClientImpl will reject scan parameters
that use the separate color plane formats (SANE_FRAME_{RED,GREEN,BLUE}).

BUG=b:155327782
TEST=builds

Change-Id: Iaf42fd6e3c5b2d4917c8aa13e29dde49356b80fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2173453
Tested-by: Fletcher Woodruff <fletcherw@chromium.org>
Commit-Queue: Fletcher Woodruff <fletcherw@chromium.org>
Reviewed-by: Benjamin Gordon <bmgordon@chromium.org>
diff --git a/lorgnette/sane_client.h b/lorgnette/sane_client.h
index dc41d4f..4987aa8 100644
--- a/lorgnette/sane_client.h
+++ b/lorgnette/sane_client.h
@@ -15,6 +15,18 @@
 
 namespace lorgnette {
 
+enum FrameFormat {
+  kGrayscale,
+  kRGB,
+};
+
+struct ScanParameters {
+  FrameFormat format;
+  int pixels_per_line;
+  int lines;
+  int depth;
+};
+
 // 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.
@@ -26,6 +38,8 @@
   virtual bool SetScanMode(brillo::ErrorPtr* error,
                            const std::string& scan_mode) = 0;
   virtual bool StartScan(brillo::ErrorPtr* error) = 0;
+  virtual bool GetScanParameters(brillo::ErrorPtr* error,
+                                 ScanParameters* parameters) = 0;
   virtual bool ReadScanData(brillo::ErrorPtr* error,
                             uint8_t* buf,
                             size_t count,
diff --git a/lorgnette/sane_client_fake.cc b/lorgnette/sane_client_fake.cc
index 9f100b5..ee17d2d 100644
--- a/lorgnette/sane_client_fake.cc
+++ b/lorgnette/sane_client_fake.cc
@@ -86,6 +86,15 @@
   return true;
 }
 
+bool SaneDeviceFake::GetScanParameters(brillo::ErrorPtr* error,
+                                       ScanParameters* parameters) {
+  if (!parameters || !params_.has_value())
+    return false;
+
+  *parameters = params_.value();
+  return true;
+}
+
 bool SaneDeviceFake::ReadScanData(brillo::ErrorPtr*,
                                   uint8_t* buf,
                                   size_t count,
@@ -114,6 +123,11 @@
   start_scan_result_ = result;
 }
 
+void SaneDeviceFake::SetScanParameters(
+    const base::Optional<ScanParameters>& params) {
+  params_ = params;
+}
+
 void SaneDeviceFake::SetReadScanDataResult(bool result) {
   read_scan_data_result_ = result;
 }
diff --git a/lorgnette/sane_client_fake.h b/lorgnette/sane_client_fake.h
index e12261b..58fbf91 100644
--- a/lorgnette/sane_client_fake.h
+++ b/lorgnette/sane_client_fake.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include <base/optional.h>
 #include <base/synchronization/lock.h>
 
 #include "lorgnette/manager.h"
@@ -53,12 +54,15 @@
   bool SetScanMode(brillo::ErrorPtr* error,
                    const std::string& scan_mode) override;
   bool StartScan(brillo::ErrorPtr* error) override;
+  bool GetScanParameters(brillo::ErrorPtr* error,
+                         ScanParameters* parameters) override;
   bool ReadScanData(brillo::ErrorPtr* error,
                     uint8_t* buf,
                     size_t count,
                     size_t* read_out) override;
 
   void SetStartScanResult(bool result);
+  void SetScanParameters(const base::Optional<ScanParameters>& params);
   void SetReadScanDataResult(bool result);
   void SetScanData(const std::vector<uint8_t>& scan_data);
 
@@ -66,6 +70,7 @@
   bool start_scan_result_;
   bool read_scan_data_result_;
   bool scan_running_;
+  base::Optional<ScanParameters> params_;
   std::vector<uint8_t> scan_data_;
   size_t scan_data_offset_;
 };
diff --git a/lorgnette/sane_client_impl.cc b/lorgnette/sane_client_impl.cc
index 8144798..72277b1 100644
--- a/lorgnette/sane_client_impl.cc
+++ b/lorgnette/sane_client_impl.cc
@@ -176,6 +176,50 @@
   return true;
 }
 
+bool SaneDeviceImpl::GetScanParameters(brillo::ErrorPtr* error,
+                                       ScanParameters* parameters) {
+  if (!handle_) {
+    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
+                         kManagerServiceError, "No scanner connected");
+    return false;
+  }
+
+  if (!parameters) {
+    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
+                         kManagerServiceError,
+                         "'parameters' pointer cannot be null");
+    return false;
+  }
+
+  SANE_Parameters params;
+  SANE_Status status = sane_get_parameters(handle_, &params);
+  if (status != SANE_STATUS_GOOD) {
+    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
+                         kManagerServiceError,
+                         "Failed to read scan parameters");
+    return false;
+  }
+
+  switch (params.format) {
+    case SANE_FRAME_GRAY:
+      parameters->format = kGrayscale;
+      break;
+    case SANE_FRAME_RGB:
+      parameters->format = kRGB;
+      break;
+    default:
+      brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
+                           kManagerServiceError,
+                           "Unsupported scan frame format");
+      return false;
+  }
+
+  parameters->pixels_per_line = params.pixels_per_line;
+  parameters->lines = params.lines;
+  parameters->depth = params.depth;
+  return true;
+}
+
 bool SaneDeviceImpl::ReadScanData(brillo::ErrorPtr* error,
                                   uint8_t* buf,
                                   size_t count,
diff --git a/lorgnette/sane_client_impl.h b/lorgnette/sane_client_impl.h
index cafca0d..3abff9f 100644
--- a/lorgnette/sane_client_impl.h
+++ b/lorgnette/sane_client_impl.h
@@ -53,6 +53,8 @@
   bool SetScanMode(brillo::ErrorPtr* error,
                    const std::string& scan_mode) override;
   bool StartScan(brillo::ErrorPtr* error) override;
+  bool GetScanParameters(brillo::ErrorPtr* error,
+                         ScanParameters* parameters) override;
   bool ReadScanData(brillo::ErrorPtr* error,
                     uint8_t* buf,
                     size_t count,