Skip to content

Commit

Permalink
Update: Implement scanner-driver.c for PAPPL
Browse files Browse the repository at this point in the history
This commit introduces a new file scanner-driver.c that contains the
implementation of functions related to the scanner driver.

Signed-off-by: Akarshan Kapoor <data.akarshan@icloud.com>
  • Loading branch information
Kappuccino111 committed Jul 4, 2024
1 parent d84e01f commit 4078698
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 24 deletions.
3 changes: 3 additions & 0 deletions pappl/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

include ../Makedefs

CFLAGS += $(shell pkg-config --cflags libxml-2.0)
LDFLAGS += $(shell pkg-config --libs libxml-2.0)

BASEOBJS = \
client.o \
Expand Down Expand Up @@ -46,6 +48,7 @@ BASEOBJS = \
printer-webif.o \
resource.o \
scanner-accessors.o\
scanner-driver.o \
snmp.o \
subscription.o \
subscription-ipp.o \
Expand Down
10 changes: 4 additions & 6 deletions pappl/scanner-accessors.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ papplScannerCloseDevice(
{
scanner->device_in_use = false;

if (scanner->state != PAPPL_SSTATE_PROCESSING)
if (scanner->state != ESCL_SSTATE_PROCESSING)
{
papplDeviceClose(scanner->device);
scanner->device = NULL;
Expand Down Expand Up @@ -396,7 +396,7 @@ escl_sstate_t // O - "scanner-state" value
papplScannerGetState(
pappl_scanner_t *scanner) // I - Scanner
{
return (scanner ? scanner->state : PAPPL_SSTATE_STOPPED);
return (scanner ? scanner->state : ESCL_SSTATE_STOPPED);
}


Expand Down Expand Up @@ -519,7 +519,7 @@ papplScannerPause(
if (scanner->processing_job)
scanner->is_stopped = true;
else
scanner->state = PAPPL_SSTATE_STOPPED;
scanner->state = ESCL_SSTATE_STOPPED;

// _papplSystemAddEventNoLock(scanner->system, scanner, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED | PAPPL_EVENT_PRINTER_STOPPED, NULL);
printf("Scanner State Changed and Scanner Paused\n");
Expand All @@ -543,7 +543,7 @@ papplScannerResume(
_papplRWLockWrite(scanner);

scanner->is_stopped = false;
scanner->state = PAPPL_SSTATE_IDLE;
scanner->state = ESCL_SSTATE_IDLE;

// _papplSystemAddEventNoLock(scanner->system, scanner, NULL, PAPPL_EVENT_PRINTER_STATE_CHANGED, "Resumed scanner.");
printf("Scanner State Changed and Scanner Resumed \n");
Expand Down Expand Up @@ -780,5 +780,3 @@ papplScannerSetReasons(

_papplRWUnlock(scanner);
}


206 changes: 206 additions & 0 deletions pappl/scanner-driver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
//
// Printer driver functions for the Printer Application Framework
//
// Copyright © 2020-2024 by Michael R Sweet.
//
// Licensed under Apache License v2.0. See the file "LICENSE" for more
// information.
//

#include "scanner-private.h"
#include "system-private.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
//
// Local functions...
//

// Declare the capability structure and the callback function
typedef struct {
char make_and_model[256];
const char *document_formats_supported[PAPPL_MAX_FORMATS];
pappl_sc_color_mode_t color_modes_supported[PAPPL_MAX_COLOR_MODES];
int resolutions[MAX_RESOLUTIONS];
pappl_sc_input_source_t input_sources_supported[PAPPL_MAX_SOURCES];
bool duplex_supported;
float max_scan_area[2];
} capability_t;

capability_t *capability_cb(pappl_scanner_t *scanner);
const char *pappl_sc_color_mode_str(pappl_sc_color_mode_t mode);
const char *pappl_sc_input_source_str(pappl_sc_input_source_t source);

//
// 'papplScannerGetDriverName()' - Get the driver name for a scanner.
//
// This function returns the driver name for the scanner.
//

const char * // O - Driver name or `NULL` for none
papplScannerGetDriverName(
pappl_scanner_t *scanner) // I - Scanner
{
return (scanner ? scanner->driver_name : NULL);
}

//
// 'papplScannerGetDriverData()' - Get the current scan driver data.
//
// This function copies the current scan driver data.
//

pappl_sc_driver_data_t * // O - Driver data or `NULL` if none
papplScannerGetDriverData(
pappl_scanner_t *scanner, // I - Scanner
pappl_sc_driver_data_t *data) // I - Pointer to driver data structure to fill
{
if (!scanner || !scanner->driver_name || !data)
{
if (data)
_papplScannerInitDriverData(scanner, data);

return (NULL);
}
memcpy(data, &scanner->driver_data, sizeof(pappl_sc_driver_data_t));

return (data);
}

//
// '_papplScannerInitDriverData()' - Initialize a scan driver data structure.
//

void
_papplScannerInitDriverData(
pappl_scanner_t *scanner, // I - Scanner
pappl_sc_driver_data_t *d) // I - Driver data
{
capability_t *capability = capability_cb(scanner);
if (capability)
{
strncpy(d->make_and_model, capability->make_and_model, sizeof(d->make_and_model) - 1);
d->make_and_model[sizeof(d->make_and_model) - 1] = '\0'; // Ensure null-termination

for (int i = 0; i < PAPPL_MAX_FORMATS && capability->document_formats_supported[i]; i++)
{
d->document_formats_supported[i] = capability->document_formats_supported[i];
}

for (int i = 0; i < PAPPL_MAX_COLOR_MODES && capability->color_modes_supported[i]; i++)
{
d->color_modes_supported[i] = capability->color_modes_supported[i];
}

for (int i = 0; i < MAX_RESOLUTIONS && capability->resolutions[i]; i++)
{
d->resolutions[i] = capability->resolutions[i];
}

for (int i = 0; i < PAPPL_MAX_SOURCES && capability->input_sources_supported[i]; i++)
{
d->input_sources_supported[i] = capability->input_sources_supported[i];
}

d->duplex_supported = capability->duplex_supported;

d->max_scan_area[0] = capability->max_scan_area[0];
d->max_scan_area[1] = capability->max_scan_area[1];

}
}

//
// 'papplScannerSetDriverData()' - Set the driver data.
//
// This function validates and sets the driver data.
//
//

bool // O - `true` on success, `false` on failure
papplScannerSetDriverData(
pappl_scanner_t *scanner, // I - Scanner
pappl_sc_driver_data_t *data) // I - Driver data
{
if (!scanner || !data)
return (false);

_papplRWLockWrite(scanner);

memcpy(&scanner->driver_data, data, sizeof(scanner->driver_data));

_papplRWUnlock(scanner);

return (true);
}

xmlDocPtr make_escl_attr(pappl_scanner_t *scanner)
{
xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "eSCL");
xmlDocSetRootElement(doc, root_node);

capability_t *capability = capability_cb(scanner);
if (!capability) {
return doc;
}

xmlNewChild(root_node, NULL, BAD_CAST "MakeAndModel", BAD_CAST capability->make_and_model);

xmlNodePtr formats_node = xmlNewChild(root_node, NULL, BAD_CAST "DocumentFormatsSupported", NULL);
for (int i = 0; i < PAPPL_MAX_FORMATS && capability->document_formats_supported[i]; i++) {
xmlNewChild(formats_node, NULL, BAD_CAST "Format", BAD_CAST capability->document_formats_supported[i]);
}


xmlNodePtr color_modes_node = xmlNewChild(root_node, NULL, BAD_CAST "ColorModesSupported", NULL);
for (int i = 0; i < PAPPL_MAX_COLOR_MODES && capability->color_modes_supported[i]; i++) {
xmlNewChild(color_modes_node, NULL, BAD_CAST "ColorMode", BAD_CAST pappl_sc_color_mode_str(capability->color_modes_supported[i]));
}

xmlNodePtr resolutions_node = xmlNewChild(root_node, NULL, BAD_CAST "Resolutions", NULL);
for (int i = 0; i < MAX_RESOLUTIONS && capability->resolutions[i]; i++) {
char resolution_str[10];
snprintf(resolution_str, sizeof(resolution_str), "%d", capability->resolutions[i]);
xmlNewChild(resolutions_node, NULL, BAD_CAST "Resolution", BAD_CAST resolution_str);
}

xmlNodePtr input_sources_node = xmlNewChild(root_node, NULL, BAD_CAST "InputSourcesSupported", NULL);
for (int i = 0; i < PAPPL_MAX_SOURCES && capability->input_sources_supported[i]; i++) {
xmlNewChild(input_sources_node, NULL, BAD_CAST "InputSource", BAD_CAST pappl_sc_input_source_str(capability->input_sources_supported[i]));
}

xmlNewChild(root_node, NULL, BAD_CAST "DuplexSupported", BAD_CAST (capability->duplex_supported ? "true" : "false"));

xmlNodePtr max_scan_area_node = xmlNewChild(root_node, NULL, BAD_CAST "MaxScanArea", NULL);
char max_scan_width[10], max_scan_height[10];
snprintf(max_scan_width, sizeof(max_scan_width), "%.2f", capability->max_scan_area[0]);
snprintf(max_scan_height, sizeof(max_scan_height), "%.2f", capability->max_scan_area[1]);
xmlNewChild(max_scan_area_node, NULL, BAD_CAST "Width", BAD_CAST max_scan_width);
xmlNewChild(max_scan_area_node, NULL, BAD_CAST "Height", BAD_CAST max_scan_height);

return doc;
}

const char *pappl_sc_color_mode_str(pappl_sc_color_mode_t mode) {
switch (mode) {
case PAPPL_BLACKANDWHITE1:
return "BlackAndWhite";
case PAPPL_GRAYSCALE8:
return "Grayscale";
case PAPPL_RGB24:
return "RGB";
default:
return "Unknown";
}
}

const char *pappl_sc_input_source_str(pappl_sc_input_source_t source) {
switch (source) {
case PAPPL_FLATBED:
return "Flatbed";
case PAPPL_ADF:
return "ADF";
default:
return "Unknown";
}
}
17 changes: 8 additions & 9 deletions pappl/scanner-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# define _PAPPL_SCANNER_PRIVATE_H_
# include "dnssd-private.h"
# include "scanner.h" // Changed to Scanner.h
# include "printer.h" // Check later
# include "log.h"
# ifdef __APPLE__
# include <sys/param.h>
Expand All @@ -36,19 +35,19 @@

struct _pappl_scanner_s // Scanner data
{
pthread_rwlock_t rwlock; // Reader/writer lock
pthread_rwlock_t rwlock; // Reader/writer lock
pappl_system_t *system; // Containing system
int scanner_id; // "scanner-id" value
char *name, // "scanner-name" value
*dns_sd_name, // "scanner-dns-sd-name" value
*location, // "scanner-location" value
*geo_location, // "scanner-geo-location" value (geo: URI)
*organization, // "scanner-organization" value
*org_unit; // "scanner-organizational-unit" value
pappl_contact_t contact; // "scanner-contact" value
*location, // "scanner-location" value
*geo_location, // "scanner-geo-location" value (geo: URI)
*organization, // "scanner-organization" value
*org_unit; // "scanner-organizational-unit" value
pappl_contact_t contact; // "scanner-contact" value
char *resource; // Resource path of scanner
size_t resourcelen; // Length of resource path
char *uriname; // Name for URLs
char *uriname; // Name for URLs
escl_sstate_t state; // "scanner-state" value --> Replacement for ipp_pstate_t
pappl_sreason_t state_reasons; // "scanner-state-reasons" values --> Replacement for pappl_preason_t
time_t state_time; // "scanner-state-change-time" value
Expand Down Expand Up @@ -83,7 +82,7 @@ struct _pappl_scanner_s // Scanner data
//

extern void _papplScannerDelete(pappl_scanner_t *scanner) _PAPPL_PRIVATE;
extern void _papplScannerInitDriverData(pappl_sc_driver_data_t *d) _PAPPL_PRIVATE;
extern void _papplScannerInitDriverData(pappl_scanner_t *scanner, pappl_sc_driver_data_t *d) _PAPPL_PRIVATE;
extern bool _papplScannerIsAuthorized(pappl_client_t *client) _PAPPL_PRIVATE;
extern void _papplScannerProcessESCL(pappl_client_t *client) _PAPPL_PRIVATE;
extern bool _papplScannerRegisterDNSSDNoLock(pappl_scanner_t *scanner) _PAPPL_PRIVATE;
Expand Down
20 changes: 11 additions & 9 deletions pappl/scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,23 @@ extern "C" {
#define PAPPL_MAX_SOURCES 2 // MOST scanners offer two input sources: Flatbed and ADF
#define PAPPL_MAX_COLOR_SPACES 2 // Common color spaces like sRGB and AdobeRGB
#define PAPPL_MAX_MEDIA_TYPES 5 // Various media types like Plain, Photo, Card, etc.
#define MAX_RESOLUTIONS 5

//
// Constants...
//

typedef enum
typedef enum
{
PAPPL_SSTATE_IDLE, // Scanner is idle
PAPPL_SSTATE_PROCESSING, // Scanner is busy with some job or activity
PAPPL_SSTATE_TESTING, // Scanner is calibrating, preparing the unit
PAPPL_SSTATE_STOPPED, // Scanner stopped due to an error condition
PAPPL_SSTATE_DOWN // Scanner is unavailable
ESCL_SSTATE_IDLE, // Scanner is idle
ESCL_SSTATE_PROCESSING, // Scanner is busy with some job or activity
ESCL_SSTATE_TESTING, // Scanner is calibrating, preparing the unit
ESCL_SSTATE_STOPPED, // Scanner stopped due to an error condition
ESCL_SSTATE_DOWN // Scanner is unavailable
} escl_sstate_t;

typedef enum
// Update in the future to include more reasons
typedef enum
{
PAPPL_SREASON_NONE = 0x0000, // 'none', no error, scanner is ready
PAPPL_SREASON_IDLE = 0x0001, // 'idle', scanner is idle
Expand All @@ -63,7 +65,7 @@ typedef enum {
//
// Callback functions...
//
typedef void (*pappl_sc_capabilities_cb_t)(pappl_scanner_t *scanner, pappl_sc_driver_data_t *data); // Callback for getting scanner capabilities
typedef void (*pappl_sc_capabilities_cb_t)(pappl_scanner_t *scanner); // Callback for getting scanner capabilities
typedef void (*pappl_sc_job_create_cb_t)(pappl_job_t *job, pappl_sc_options_t *options, pappl_device_t *device); // Callback for creating a scan job
typedef void (*pappl_sc_job_delete_cb_t)(pappl_job_t *job); // Callback for deleting a scan job
typedef bool (*pappl_sc_data_cb_t)(pappl_job_t *job, pappl_device_t *device, void *buffer, size_t bufsize); // Callback for getting scan data
Expand Down Expand Up @@ -113,7 +115,7 @@ typedef struct pappl_sc_driver_data_s
char make_and_model[128]; // Make and model of the scanner
const char *document_formats_supported[PAPPL_MAX_FORMATS]; // Supported document formats (JPEG, PDF, TIFF)
pappl_sc_color_mode_t color_modes_supported[PAPPL_MAX_COLOR_MODES]; // Supported color modes (BlackAndWhite1, Grayscale8, RGB24)
int max_resolution; // Maximum optical resolution in DPI
int resolutions[MAX_RESOLUTIONS]; // All optical resolution in DPI
pappl_sc_input_source_t input_sources_supported[PAPPL_MAX_SOURCES]; // Supported input sources (Platen, Feeder)
bool duplex_supported; // Duplex (double-sided) scanning support
const char *color_spaces_supported[PAPPL_MAX_COLOR_SPACES]; // Supported color spaces (sRGB, AdobeRGB)
Expand Down

0 comments on commit 4078698

Please sign in to comment.