1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2019 Touboul Nathane 4141cc406Sopenharmony_ci Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com> 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci SANE is free software; you can redistribute it and/or modify it under 9141cc406Sopenharmony_ci the terms of the GNU General Public License as published by the Free 10141cc406Sopenharmony_ci Software Foundation; either version 3 of the License, or (at your 11141cc406Sopenharmony_ci option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci SANE is distributed in the hope that it will be useful, but WITHOUT 14141cc406Sopenharmony_ci ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15141cc406Sopenharmony_ci FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16141cc406Sopenharmony_ci for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with sane; see the file COPYING. 20141cc406Sopenharmony_ci If not, see <https://www.gnu.org/licenses/>. 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci This file implements a SANE backend for eSCL scanners. */ 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 25141cc406Sopenharmony_ci#include "../include/sane/config.h" 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci#include "escl.h" 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci#include <stdio.h> 30141cc406Sopenharmony_ci#include <stdlib.h> 31141cc406Sopenharmony_ci#include <string.h> 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci/** 36141cc406Sopenharmony_ci * \fn static size_t write_callback(void *str, size_t size, size_t nmemb, void *userp) 37141cc406Sopenharmony_ci * \brief Callback function that writes the image scanned into the temporary file. 38141cc406Sopenharmony_ci * 39141cc406Sopenharmony_ci * \return to_write (the result of the fwrite function) 40141cc406Sopenharmony_ci */ 41141cc406Sopenharmony_cistatic size_t 42141cc406Sopenharmony_ciwrite_callback(void *str, size_t size, size_t nmemb, void *userp) 43141cc406Sopenharmony_ci{ 44141cc406Sopenharmony_ci capabilities_t *scanner = (capabilities_t *)userp; 45141cc406Sopenharmony_ci size_t to_write = fwrite(str, size, nmemb, scanner->tmp); 46141cc406Sopenharmony_ci scanner->real_read += to_write; 47141cc406Sopenharmony_ci return (to_write); 48141cc406Sopenharmony_ci} 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci/** 51141cc406Sopenharmony_ci * \fn SANE_Status escl_scan(capabilities_t *scanner, const ESCL_Device *device, char *result) 52141cc406Sopenharmony_ci * \brief Function that, after recovering the 'new job', scans the image writed in the 53141cc406Sopenharmony_ci * temporary file, using curl. 54141cc406Sopenharmony_ci * This function is called in the 'sane_start' function and it's the equivalent of 55141cc406Sopenharmony_ci * the following curl command : "curl -s http(s)://'ip:'port'/eSCL/ScanJobs/'new job'/NextDocument > image.jpg". 56141cc406Sopenharmony_ci * 57141cc406Sopenharmony_ci * \return status (if everything is OK, status = SANE_STATUS_GOOD, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL) 58141cc406Sopenharmony_ci */ 59141cc406Sopenharmony_ciSANE_Status 60141cc406Sopenharmony_ciescl_scan(capabilities_t *scanner, const ESCL_Device *device, char *scanJob, char *result) 61141cc406Sopenharmony_ci{ 62141cc406Sopenharmony_ci CURL *curl_handle = NULL; 63141cc406Sopenharmony_ci const char *scan_jobs = "/eSCL/"; 64141cc406Sopenharmony_ci const char *scanner_start = "/NextDocument"; 65141cc406Sopenharmony_ci char scan_cmd[PATH_MAX] = { 0 }; 66141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci if (device == NULL) 69141cc406Sopenharmony_ci return (SANE_STATUS_NO_MEM); 70141cc406Sopenharmony_ci scanner->real_read = 0; 71141cc406Sopenharmony_ci curl_handle = curl_easy_init(); 72141cc406Sopenharmony_ci if (curl_handle != NULL) { 73141cc406Sopenharmony_ci snprintf(scan_cmd, sizeof(scan_cmd), "%s%s%s%s", 74141cc406Sopenharmony_ci scan_jobs, scanJob, result, scanner_start); 75141cc406Sopenharmony_ci escl_curl_url(curl_handle, device, scan_cmd); 76141cc406Sopenharmony_ci curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback); 77141cc406Sopenharmony_ci curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); 78141cc406Sopenharmony_ci curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 3L); 79141cc406Sopenharmony_ci if (scanner->tmp) 80141cc406Sopenharmony_ci fclose(scanner->tmp); 81141cc406Sopenharmony_ci scanner->tmp = tmpfile(); 82141cc406Sopenharmony_ci if (scanner->tmp != NULL) { 83141cc406Sopenharmony_ci curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, scanner); 84141cc406Sopenharmony_ci CURLcode res = curl_easy_perform(curl_handle); 85141cc406Sopenharmony_ci if (res != CURLE_OK) { 86141cc406Sopenharmony_ci DBG( 1, "Unable to scan: %s\n", curl_easy_strerror(res)); 87141cc406Sopenharmony_ci scanner->real_read = 0; 88141cc406Sopenharmony_ci fclose(scanner->tmp); 89141cc406Sopenharmony_ci scanner->tmp = NULL; 90141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 91141cc406Sopenharmony_ci goto cleanup; 92141cc406Sopenharmony_ci } 93141cc406Sopenharmony_ci fseek(scanner->tmp, 0, SEEK_SET); 94141cc406Sopenharmony_ci } 95141cc406Sopenharmony_ci else 96141cc406Sopenharmony_ci status = SANE_STATUS_NO_MEM; 97141cc406Sopenharmony_cicleanup: 98141cc406Sopenharmony_ci curl_easy_cleanup(curl_handle); 99141cc406Sopenharmony_ci } 100141cc406Sopenharmony_ci DBG(10, "eSCL scan : [%s]\treal read (%ld)\n", sane_strstatus(status), scanner->real_read); 101141cc406Sopenharmony_ci if (scanner->real_read == 0) 102141cc406Sopenharmony_ci { 103141cc406Sopenharmony_ci fclose(scanner->tmp); 104141cc406Sopenharmony_ci scanner->tmp = NULL; 105141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 106141cc406Sopenharmony_ci } 107141cc406Sopenharmony_ci return (status); 108141cc406Sopenharmony_ci} 109