/* xmlreader.c --
* Copyright (C) 2010 SEIKO EPSON CORPORATION
*
* License: GPLv2+|iscan
* Authors: SEIKO EPSON CORPORATION
*
* This file is part of the SANE backend distributed with Image Scan!
*
* Image Scan!'s SANE backend is free software.
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation;
* either version 2 of the License or at your option any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You ought to have received a copy of the GNU General Public License
* along with this package. If not, see .
*
*
* Linking Image Scan!'s SANE backend statically or dynamically with
* other modules is making a combined work based on this SANE backend.
* Thus, the terms and conditions of the GNU General Public License
* cover the whole combination.
*
* As a special exception, the copyright holders of Image Scan!'s SANE
* backend give you permission to link Image Scan!'s SANE backend with
* SANE frontends that communicate with Image Scan!'s SANE backend
* solely through the SANE Application Programming Interface,
* regardless of the license terms of these SANE frontends, and to
* copy and distribute the resulting combined work under terms of your
* choice, provided that every copy of the combined work is
* accompanied by a complete copy of the source code of Image Scan!'s
* SANE backend (the version of Image Scan!'s SANE backend used to
* produce the combined work), being distributed under the terms of
* the GNU General Public License plus this exception. An independent
* module is a module which is not derived from or based on Image
* Scan!'s SANE backend.
*
* As a special exception, the copyright holders of Image Scan!'s SANE
* backend give you permission to link Image Scan!'s SANE backend with
* independent modules that communicate with Image Scan!'s SANE
* backend solely through the "Interpreter" interface, regardless of
* the license terms of these independent modules, and to copy and
* distribute the resulting combined work under terms of your choice,
* provided that every copy of the combined work is accompanied by a
* complete copy of the source code of Image Scan!'s SANE backend (the
* version of Image Scan!'s SANE backend used to produce the combined
* work), being distributed under the terms of the GNU General Public
* License plus this exception. An independent module is a module
* which is not derived from or based on Image Scan!'s SANE backend.
*
* Note that people who make modified versions of Image Scan!'s SANE
* backend are not obligated to grant special exceptions for their
* modified versions; it is their choice whether to do so. The GNU
* General Public License gives permission to release a modified
* version without this exception; this exception also makes it
* possible to release a modified version which carries forward this
* exception.
*/
#include
#include
#include
#include
#include
#include "utils.h"
#include "get-infofile.h"
#include "xmlreader.h"
typedef struct devices{
char *firmware;
char *overseas;
char *japan;
}devices, *devicePtr;
typedef struct commands{
char *command_type;
char *command_level;
}commands, *commandPtr;
static void default_profile_set(double color_profile[9]);
static void parseCommand(xmlNodePtr cur, scan_command_t* command);
static unsigned char parseStatus(char *status, char *name);
char *
parseDevices(xmlNodePtr cur, char *name){
devicePtr ret;
char *region = NULL;
char *result = NULL;
log_call();
ret = t_calloc (1, devices);
if(ret == NULL){
err_major("out of memory");
return NULL;
}
cur = cur->xmlChildrenNode;
while (cur != NULL) {
if (!xmlStrcmp(cur->name, (const xmlChar *) "firmware")) {
if(ret->firmware == NULL && strcmp(name, FIRMWARE) == 0){
ret->firmware = (char *)xmlGetProp(cur, (const xmlChar *) "name");
result = strdup(ret->firmware);
if(!ret->firmware){
delete (ret);
return NULL;
}
break;
}
}else if (!xmlStrcmp(cur->name, (const xmlChar *) "model")) {
region = (char *)xmlGetProp(cur, (const xmlChar *) "region");
if(region && strcmp(name, MODEL_JAPAN) == 0){
if(strcmp(name, MODEL_JAPAN) == 0 && strcasecmp(region, "Japan") == 0){
ret->japan = (char *)xmlGetProp(cur, (const xmlChar *) "name");
result = strdup(ret->japan);
delete (ret->japan);
if(!result || isspace(result[0]) != 0 || strlen(result) == 0){
delete (result);
delete (ret);
delete (region);
result = NULL;
err_minor("Model has no Name.");
}
}
break;
}else if(!region && strcmp(name, MODEL_OVERSEAS) == 0){
ret->overseas = (char *)xmlGetProp(cur, (const xmlChar *) "name");
result = strdup(ret->overseas);
delete(ret->overseas);
if(!result || isspace(result[0]) != 0 || strlen(result) == 0){
delete (result);
delete (ret);
delete (region);
result = NULL;
err_minor("Model has no Name.");
}
break;
}
delete (region);
}
cur = cur->next;
}
delete (region);
delete (ret);
return result;
}
EpsonScanHard
parseProfiles(xmlNodePtr cur){
EpsonScanHard ret;
int i, j;
char *tmp;
char pmat[9][3] = {"rr", "rg", "rb",
"gr", "gg", "gb",
"br", "bg", "bb"};
char *profile_type;
xmlNodePtr curtmp;
log_call();
ret = t_calloc (1, EpsonScanHardRec);
if(ret == NULL){
err_major("out of memory");
return NULL;
}
/*add default value*/
for(i = 0; i < 4; i++){
default_profile_set(ret->color_profile[i]);
}
cur = curtmp = cur->xmlChildrenNode;
while(cur != NULL){
if ((!xmlStrcmp(cur->name, (const xmlChar *) "profile"))){
curtmp = cur;
profile_type = (char *)xmlGetProp(cur, (const xmlChar *) "type");
if(strcmp(profile_type, "reflective") == 0){
i = 0;
}else if(strcmp(profile_type, "color negative") == 0){
i = 1;
}else if(strcmp(profile_type, "monochrome negative") == 0){
i = 2;
}else if(strcmp(profile_type, "positive") == 0){
i = 3;
}else {
err_minor("profile of the wrong type.");
delete (profile_type);
delete (ret);
return NULL;
}
delete (profile_type);
j = 0;
cur = cur->xmlChildrenNode;
while(cur != NULL){
if(!xmlStrcmp(cur->name, (const xmlChar *)pmat[j])){
tmp = (char*)xmlGetProp(cur, (const xmlChar *) "value");
ret->color_profile[i][j] = atof(tmp);
delete (tmp);
j++;
}
cur = cur->next;
}
if(j != 9){
err_minor("Value that is not sufficient exists.");
default_profile_set(ret->color_profile[i]);
}
}
cur = curtmp;
cur = curtmp = cur->next;
}
return ret;
}
static
void default_profile_set(double color_profile[9]){
/*default value is assigned*/
const double default_profile[9] =
{1.0000, 0.0000, 0.0000,
0.0000, 1.0000, 0.0000,
0.0000, 0.0000, 1.0000} ;
int j;
for(j = 0; j < 9; j++){
color_profile[j] = default_profile[j];
}
}
scan_command_t *
parseCommands_set(xmlNodePtr cur){
commandPtr ret;
scan_command_t* command;
log_call();
command = t_calloc (1, scan_command_t);
if(command == NULL){
err_major("out of memory");
return NULL;
}
/*default value*/
command->set_focus_position = 0xFF;
command->feed = 0xFF;
command->eject = 0xFF;
command->lock = false;
command->unlock = false;
ret = t_calloc (1, commands);
if(ret == NULL){
err_major("out of memory");
delete (command);
return NULL;
}
ret->command_type = (char *)xmlGetProp(cur, (const xmlChar *) "type");
ret->command_level = (char *)xmlGetProp(cur, (const xmlChar *) "level");
cur = cur->xmlChildrenNode;
while(cur != NULL){
if ((!xmlStrcmp(cur->name, (const xmlChar *) "command"))){
parseCommand(cur, command);
}
cur = cur->next;
}
delete (ret->command_type);
delete (ret->command_level);
delete (ret);
return command;
}
static void
parseCommand(xmlNodePtr cur, scan_command_t* command)
{
char *tmp;
char *status = NULL;
status = (char *)xmlGetProp(cur, (const xmlChar *) "status");
if((tmp = (char *)xmlGetProp(cur, (const xmlChar *) "name")) != NULL){
if(strcmp(tmp, "set_focus_position") == 0){
command->set_focus_position = parseStatus(status, "set_focus_position");
}else if(strcmp(tmp, "feed") == 0){
command->feed = parseStatus(status, "feed");
}else if(strcmp(tmp, "eject") == 0){
command->eject = parseStatus(status, "eject");
}else if(strcmp(tmp, "lock") == 0){
command->lock = true;
if(status && strcmp(status, "disable") == 0) command->lock = false;
}else if(strcmp(tmp, "unlock") == 0){
command->unlock = true;
if(status && strcmp(status, "disable") == 0) command->unlock = false;
}
delete (tmp);
delete (status);
}
}
static unsigned char
parseStatus(char *status, char *name)
{
unsigned char value;
if(!status || strcmp(status, "enabled") == 0){/*enabled*/
if(strcmp(name, "set_focus_position") == 0) value = 0x70;
else if(strcmp(name, "feed") == 0) value = 0x19;
else if(strcmp(name, "eject") == 0) value = 0x0C;
else value = 0;
}else if(strcmp(status, "disabled") == 0){
value = 0;
}else{
value = 0;
}
return value;
}
capability_data_t*
parseCapabilities(xmlNodePtr cur)
{
capability_data_t *capabilities;
char *tmp;
char *endp;
log_call();
capabilities = t_calloc (1, capability_data_t);
if(capabilities == NULL){
err_major("out of memory");
return NULL;
}
cur = cur->xmlChildrenNode;
while(cur != NULL){
if ((!xmlStrcmp(cur->name, (const xmlChar *) "scan-area"))){
endp = tmp = (char *)xmlGetProp(cur, (const xmlChar *) "width");
capabilities->width = strtol(tmp, &endp, 10);
if(endp == tmp) capabilities->width = -1;
if(*endp != '\0')
err_minor("ignoring trailing garbage (%s)", endp);
delete (tmp);
endp = tmp = (char *)xmlGetProp(cur, (const xmlChar *) "height");
capabilities->height = strtol(tmp, &endp, 10);
if(endp == tmp) capabilities->height = -1;
if(*endp != '\0')
err_minor("ignoring trailing garbage (%s)", endp);
delete (tmp);
endp = tmp = (char *)xmlGetProp(cur, (const xmlChar *) "base");
capabilities->base = strtol(tmp, &endp, 10);
if(endp == tmp) capabilities->base = 1;
if(*endp != '\0')
err_minor("ignoring trailing garbage (%s)", endp);
delete (tmp);
}
cur = cur->next;
}
return capabilities;
}