1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 1997 Geoffrey T. Dairiki 3141cc406Sopenharmony_ci This file is part of the SANE package. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 19141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 22141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 23141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 24141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 25141cc406Sopenharmony_ci account of linking the SANE library code into it. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 28141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 29141cc406Sopenharmony_ci License. 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 32141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 33141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 36141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 37141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci This file is part of a SANE backend for HP Scanners supporting 40141cc406Sopenharmony_ci HP Scanner Control Language (SCL). 41141cc406Sopenharmony_ci*/ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* #define STUBS 44141cc406Sopenharmony_ciextern int sanei_debug_hp; */ 45141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci#include "../include/sane/config.h" 48141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci#include "../include/lassert.h" 51141cc406Sopenharmony_ci#include <string.h> 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci#include <sys/types.h> 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci#include "hp.h" 56141cc406Sopenharmony_ci#include "hp-option.h" 57141cc406Sopenharmony_ci#include "hp-accessor.h" 58141cc406Sopenharmony_ci#include "hp-device.h" 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci#define DATA_SIZE_INCREMENT (1024) 61141cc406Sopenharmony_ci 62141cc406Sopenharmony_ci/* 63141cc406Sopenharmony_ci * class HpData 64141cc406Sopenharmony_ci */ 65141cc406Sopenharmony_cistruct hp_data_s 66141cc406Sopenharmony_ci{ 67141cc406Sopenharmony_ci hp_byte_t * buf; 68141cc406Sopenharmony_ci size_t bufsiz; 69141cc406Sopenharmony_ci size_t length; 70141cc406Sopenharmony_ci hp_bool_t frozen; 71141cc406Sopenharmony_ci}; 72141cc406Sopenharmony_ci 73141cc406Sopenharmony_ci 74141cc406Sopenharmony_cistatic void 75141cc406Sopenharmony_cihp_data_resize (HpData this, size_t newsize) 76141cc406Sopenharmony_ci{ 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci if (this->bufsiz != newsize) 79141cc406Sopenharmony_ci { 80141cc406Sopenharmony_ci assert(!this->frozen); 81141cc406Sopenharmony_ci this->buf = sanei_hp_realloc(this->buf, newsize); 82141cc406Sopenharmony_ci assert(this->buf); 83141cc406Sopenharmony_ci this->bufsiz = newsize; 84141cc406Sopenharmony_ci } 85141cc406Sopenharmony_ci} 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_cistatic void 88141cc406Sopenharmony_cihp_data_freeze (HpData this) 89141cc406Sopenharmony_ci{ 90141cc406Sopenharmony_ci hp_data_resize(this, this->length); 91141cc406Sopenharmony_ci this->frozen = 1; 92141cc406Sopenharmony_ci} 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_cistatic size_t 95141cc406Sopenharmony_cihp_data_alloc (HpData this, size_t sz) 96141cc406Sopenharmony_ci{ 97141cc406Sopenharmony_ci size_t newsize = this->bufsiz; 98141cc406Sopenharmony_ci size_t offset = this->length; 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_ci /* 101141cc406Sopenharmony_ci * mike@easysw.com: 102141cc406Sopenharmony_ci * 103141cc406Sopenharmony_ci * The following code is REQUIRED so that pointers, etc. aren't 104141cc406Sopenharmony_ci * misaligned. This causes MAJOR problems on all SPARC, ALPHA, 105141cc406Sopenharmony_ci * and MIPS processors, and possibly others. 106141cc406Sopenharmony_ci * 107141cc406Sopenharmony_ci * The workaround is to ensure that all allocations are in multiples 108141cc406Sopenharmony_ci * of 8 bytes. 109141cc406Sopenharmony_ci */ 110141cc406Sopenharmony_ci sz = (sz + sizeof (long) - 1) & ~(sizeof (long) - 1); 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci while (newsize < this->length + sz) 113141cc406Sopenharmony_ci newsize += DATA_SIZE_INCREMENT; 114141cc406Sopenharmony_ci hp_data_resize(this, newsize); 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci this->length += sz; 117141cc406Sopenharmony_ci return offset; 118141cc406Sopenharmony_ci} 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_cistatic void * 121141cc406Sopenharmony_cihp_data_data (HpData this, size_t offset) 122141cc406Sopenharmony_ci{ 123141cc406Sopenharmony_ci assert(offset < this->length); 124141cc406Sopenharmony_ci return (char *)this->buf + offset; 125141cc406Sopenharmony_ci} 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ciHpData 128141cc406Sopenharmony_cisanei_hp_data_new (void) 129141cc406Sopenharmony_ci{ 130141cc406Sopenharmony_ci return sanei_hp_allocz(sizeof(struct hp_data_s)); 131141cc406Sopenharmony_ci} 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ciHpData 134141cc406Sopenharmony_cisanei_hp_data_dup (HpData orig) 135141cc406Sopenharmony_ci{ 136141cc406Sopenharmony_ci HpData new; 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci hp_data_freeze(orig); 139141cc406Sopenharmony_ci if (!( new = sanei_hp_memdup(orig, sizeof(*orig)) )) 140141cc406Sopenharmony_ci return 0; 141141cc406Sopenharmony_ci if (!(new->buf = sanei_hp_memdup(orig->buf, orig->bufsiz))) 142141cc406Sopenharmony_ci { 143141cc406Sopenharmony_ci sanei_hp_free(new); 144141cc406Sopenharmony_ci return 0; 145141cc406Sopenharmony_ci } 146141cc406Sopenharmony_ci return new; 147141cc406Sopenharmony_ci} 148141cc406Sopenharmony_ci 149141cc406Sopenharmony_civoid 150141cc406Sopenharmony_cisanei_hp_data_destroy (HpData this) 151141cc406Sopenharmony_ci{ 152141cc406Sopenharmony_ci sanei_hp_free(this->buf); 153141cc406Sopenharmony_ci sanei_hp_free(this); 154141cc406Sopenharmony_ci} 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci/* 158141cc406Sopenharmony_ci * class HpAccessor 159141cc406Sopenharmony_ci */ 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_citypedef const struct hp_accessor_type_s * HpAccessorType; 162141cc406Sopenharmony_citypedef struct hp_accessor_s * _HpAccessor; 163141cc406Sopenharmony_ci 164141cc406Sopenharmony_cistruct hp_accessor_s 165141cc406Sopenharmony_ci{ 166141cc406Sopenharmony_ci HpAccessorType type; 167141cc406Sopenharmony_ci size_t data_offset; 168141cc406Sopenharmony_ci size_t data_size; 169141cc406Sopenharmony_ci}; 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_cistruct hp_accessor_type_s 172141cc406Sopenharmony_ci{ 173141cc406Sopenharmony_ci SANE_Status (*get)(HpAccessor this, HpData data, void * valp); 174141cc406Sopenharmony_ci SANE_Status (*set)(HpAccessor this, HpData data, void * valp); 175141cc406Sopenharmony_ci int (*getint)(HpAccessor this, HpData data); 176141cc406Sopenharmony_ci void (*setint)(HpAccessor this, HpData data, int val); 177141cc406Sopenharmony_ci}; 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ciSANE_Status 180141cc406Sopenharmony_cisanei_hp_accessor_get (HpAccessor this, HpData data, void * valp) 181141cc406Sopenharmony_ci{ 182141cc406Sopenharmony_ci if (!this->type->get) 183141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 184141cc406Sopenharmony_ci return (*this->type->get)(this, data, valp); 185141cc406Sopenharmony_ci} 186141cc406Sopenharmony_ci 187141cc406Sopenharmony_ciSANE_Status 188141cc406Sopenharmony_cisanei_hp_accessor_set (HpAccessor this, HpData data, void * valp) 189141cc406Sopenharmony_ci{ 190141cc406Sopenharmony_ci if (!this->type->set) 191141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 192141cc406Sopenharmony_ci return (*this->type->set)(this, data, valp); 193141cc406Sopenharmony_ci} 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ciint 196141cc406Sopenharmony_cisanei_hp_accessor_getint (HpAccessor this, HpData data) 197141cc406Sopenharmony_ci{ 198141cc406Sopenharmony_ci assert (this->type->getint); 199141cc406Sopenharmony_ci return (*this->type->getint)(this, data); 200141cc406Sopenharmony_ci} 201141cc406Sopenharmony_ci 202141cc406Sopenharmony_civoid 203141cc406Sopenharmony_cisanei_hp_accessor_setint (HpAccessor this, HpData data, int val) 204141cc406Sopenharmony_ci{ 205141cc406Sopenharmony_ci assert (this->type->setint); 206141cc406Sopenharmony_ci (*this->type->setint)(this, data, val); 207141cc406Sopenharmony_ci} 208141cc406Sopenharmony_ci 209141cc406Sopenharmony_ciconst void * 210141cc406Sopenharmony_cisanei_hp_accessor_data (HpAccessor this, HpData data) 211141cc406Sopenharmony_ci{ 212141cc406Sopenharmony_ci return hp_data_data(data, this->data_offset); 213141cc406Sopenharmony_ci} 214141cc406Sopenharmony_ci 215141cc406Sopenharmony_civoid * 216141cc406Sopenharmony_cisanei__hp_accessor_data (HpAccessor this, HpData data) 217141cc406Sopenharmony_ci{ 218141cc406Sopenharmony_ci return hp_data_data(data, this->data_offset); 219141cc406Sopenharmony_ci} 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_cisize_t 222141cc406Sopenharmony_cisanei_hp_accessor_size (HpAccessor this) 223141cc406Sopenharmony_ci{ 224141cc406Sopenharmony_ci return this->data_size; 225141cc406Sopenharmony_ci} 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ciHpAccessor 228141cc406Sopenharmony_cisanei_hp_accessor_new (HpData data, size_t sz) 229141cc406Sopenharmony_ci{ 230141cc406Sopenharmony_ci static const struct hp_accessor_type_s type = { 231141cc406Sopenharmony_ci 0, 0, 0, 0 232141cc406Sopenharmony_ci }; 233141cc406Sopenharmony_ci _HpAccessor new = sanei_hp_alloc(sizeof(*new)); 234141cc406Sopenharmony_ci new->type = &type; 235141cc406Sopenharmony_ci new->data_offset = hp_data_alloc(data, new->data_size = sz); 236141cc406Sopenharmony_ci return new; 237141cc406Sopenharmony_ci} 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci 240141cc406Sopenharmony_ci/* 241141cc406Sopenharmony_ci * class HpAccessorInt 242141cc406Sopenharmony_ci */ 243141cc406Sopenharmony_ci 244141cc406Sopenharmony_ci#define hp_accessor_int_s hp_accessor_s 245141cc406Sopenharmony_ci 246141cc406Sopenharmony_citypedef const struct hp_accessor_int_s * HpAccessorInt; 247141cc406Sopenharmony_citypedef struct hp_accessor_int_s * _HpAccessorInt; 248141cc406Sopenharmony_ci 249141cc406Sopenharmony_cistatic SANE_Status 250141cc406Sopenharmony_cihp_accessor_int_get (HpAccessor this, HpData data, void * valp) 251141cc406Sopenharmony_ci{ 252141cc406Sopenharmony_ci *(SANE_Int*)valp = *(int *)hp_data_data(data, this->data_offset); 253141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 254141cc406Sopenharmony_ci} 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_cistatic SANE_Status 257141cc406Sopenharmony_cihp_accessor_int_set (HpAccessor this, HpData data, void * valp) 258141cc406Sopenharmony_ci{ 259141cc406Sopenharmony_ci *(int *)hp_data_data(data, this->data_offset) = *(SANE_Int*)valp; 260141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 261141cc406Sopenharmony_ci} 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_cistatic int 264141cc406Sopenharmony_cihp_accessor_int_getint (HpAccessor this, HpData data) 265141cc406Sopenharmony_ci{ 266141cc406Sopenharmony_ci return *(int *)hp_data_data(data, this->data_offset); 267141cc406Sopenharmony_ci} 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_cistatic void 270141cc406Sopenharmony_cihp_accessor_int_setint (HpAccessor this, HpData data, int val) 271141cc406Sopenharmony_ci{ 272141cc406Sopenharmony_ci *(int *)hp_data_data(data, this->data_offset) = val; 273141cc406Sopenharmony_ci} 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ciHpAccessor 276141cc406Sopenharmony_cisanei_hp_accessor_int_new (HpData data) 277141cc406Sopenharmony_ci{ 278141cc406Sopenharmony_ci static const struct hp_accessor_type_s type = { 279141cc406Sopenharmony_ci hp_accessor_int_get, hp_accessor_int_set, 280141cc406Sopenharmony_ci hp_accessor_int_getint, hp_accessor_int_setint 281141cc406Sopenharmony_ci }; 282141cc406Sopenharmony_ci _HpAccessorInt new = sanei_hp_alloc(sizeof(*new)); 283141cc406Sopenharmony_ci new->type = &type; 284141cc406Sopenharmony_ci new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int)); 285141cc406Sopenharmony_ci return (HpAccessor)new; 286141cc406Sopenharmony_ci} 287141cc406Sopenharmony_ci 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci/* 290141cc406Sopenharmony_ci * class HpAccessorBool 291141cc406Sopenharmony_ci */ 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_ci#define hp_accessor_bool_s hp_accessor_s 294141cc406Sopenharmony_ci 295141cc406Sopenharmony_citypedef const struct hp_accessor_bool_s * HpAccessorBool; 296141cc406Sopenharmony_citypedef struct hp_accessor_bool_s * _HpAccessorBool; 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_cistatic SANE_Status 299141cc406Sopenharmony_cihp_accessor_bool_get (HpAccessor this, HpData data, void * valp) 300141cc406Sopenharmony_ci{ 301141cc406Sopenharmony_ci int val = *(int *)hp_data_data(data, this->data_offset); 302141cc406Sopenharmony_ci *(SANE_Bool*)valp = val ? SANE_TRUE : SANE_FALSE; 303141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 304141cc406Sopenharmony_ci} 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_cistatic SANE_Status 307141cc406Sopenharmony_cihp_accessor_bool_set (HpAccessor this, HpData data, void * valp) 308141cc406Sopenharmony_ci{ 309141cc406Sopenharmony_ci int * datap = hp_data_data(data, this->data_offset); 310141cc406Sopenharmony_ci *datap = *(SANE_Bool*)valp == SANE_FALSE ? 0 : 1; 311141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 312141cc406Sopenharmony_ci} 313141cc406Sopenharmony_ci 314141cc406Sopenharmony_ciHpAccessor 315141cc406Sopenharmony_cisanei_hp_accessor_bool_new (HpData data) 316141cc406Sopenharmony_ci{ 317141cc406Sopenharmony_ci static const struct hp_accessor_type_s type = { 318141cc406Sopenharmony_ci hp_accessor_bool_get, hp_accessor_bool_set, 319141cc406Sopenharmony_ci hp_accessor_int_getint, hp_accessor_int_setint 320141cc406Sopenharmony_ci }; 321141cc406Sopenharmony_ci _HpAccessorBool new = sanei_hp_alloc(sizeof(*new)); 322141cc406Sopenharmony_ci new->type = &type; 323141cc406Sopenharmony_ci new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int)); 324141cc406Sopenharmony_ci return (HpAccessor)new; 325141cc406Sopenharmony_ci} 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci/* 329141cc406Sopenharmony_ci * class HpAccessorFixed 330141cc406Sopenharmony_ci */ 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci#define hp_accessor_fixed_s hp_accessor_s 333141cc406Sopenharmony_ci 334141cc406Sopenharmony_citypedef const struct hp_accessor_fixed_s * HpAccessorFixed; 335141cc406Sopenharmony_citypedef struct hp_accessor_fixed_s * _HpAccessorFixed; 336141cc406Sopenharmony_ci 337141cc406Sopenharmony_cistatic SANE_Status 338141cc406Sopenharmony_cihp_accessor_fixed_get (HpAccessor this, HpData data, void * valp) 339141cc406Sopenharmony_ci{ 340141cc406Sopenharmony_ci *(SANE_Fixed*)valp = *(SANE_Fixed *)hp_data_data(data, this->data_offset); 341141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 342141cc406Sopenharmony_ci} 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_cistatic SANE_Status 345141cc406Sopenharmony_cihp_accessor_fixed_set (HpAccessor this, HpData data, void * valp) 346141cc406Sopenharmony_ci{ 347141cc406Sopenharmony_ci *(SANE_Fixed *)hp_data_data(data, this->data_offset) = *(SANE_Fixed*)valp; 348141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 349141cc406Sopenharmony_ci} 350141cc406Sopenharmony_ci 351141cc406Sopenharmony_ciHpAccessor 352141cc406Sopenharmony_cisanei_hp_accessor_fixed_new (HpData data) 353141cc406Sopenharmony_ci{ 354141cc406Sopenharmony_ci static const struct hp_accessor_type_s type = { 355141cc406Sopenharmony_ci hp_accessor_fixed_get, hp_accessor_fixed_set, 0, 0 356141cc406Sopenharmony_ci }; 357141cc406Sopenharmony_ci _HpAccessorFixed new = sanei_hp_alloc(sizeof(*new)); 358141cc406Sopenharmony_ci new->type = &type; 359141cc406Sopenharmony_ci new->data_offset = hp_data_alloc(data, new->data_size = sizeof(SANE_Fixed)); 360141cc406Sopenharmony_ci return (HpAccessor)new; 361141cc406Sopenharmony_ci} 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci 364141cc406Sopenharmony_ci/* 365141cc406Sopenharmony_ci * class HpAccessorChoice 366141cc406Sopenharmony_ci */ 367141cc406Sopenharmony_ci 368141cc406Sopenharmony_citypedef struct hp_accessor_choice_s * _HpAccessorChoice; 369141cc406Sopenharmony_ci 370141cc406Sopenharmony_cistruct hp_accessor_choice_s 371141cc406Sopenharmony_ci{ 372141cc406Sopenharmony_ci HpAccessorType type; 373141cc406Sopenharmony_ci size_t data_offset; 374141cc406Sopenharmony_ci size_t data_size; 375141cc406Sopenharmony_ci 376141cc406Sopenharmony_ci HpChoice choices; 377141cc406Sopenharmony_ci SANE_String_Const * strlist; 378141cc406Sopenharmony_ci}; 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_cistatic SANE_Status 381141cc406Sopenharmony_cihp_accessor_choice_get (HpAccessor this, HpData data, void * valp) 382141cc406Sopenharmony_ci{ 383141cc406Sopenharmony_ci HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset); 384141cc406Sopenharmony_ci strcpy(valp, choice->name); 385141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 386141cc406Sopenharmony_ci} 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_cistatic SANE_Status 389141cc406Sopenharmony_cihp_accessor_choice_set (HpAccessor _this, HpData data, void * valp) 390141cc406Sopenharmony_ci{ 391141cc406Sopenharmony_ci HpAccessorChoice this = (HpAccessorChoice)_this; 392141cc406Sopenharmony_ci HpChoice choice; 393141cc406Sopenharmony_ci SANE_String_Const * strlist = this->strlist; 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci for (choice = this->choices; choice; choice = choice->next) 396141cc406Sopenharmony_ci { 397141cc406Sopenharmony_ci /* Skip choices which aren't in strlist. */ 398141cc406Sopenharmony_ci if (!*strlist || strcmp(*strlist, choice->name) != 0) 399141cc406Sopenharmony_ci continue; 400141cc406Sopenharmony_ci strlist++; 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci if (strcmp((const char *)valp, choice->name) == 0) 403141cc406Sopenharmony_ci { 404141cc406Sopenharmony_ci *(HpChoice *)hp_data_data(data, this->data_offset) = choice; 405141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 406141cc406Sopenharmony_ci } 407141cc406Sopenharmony_ci } 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 410141cc406Sopenharmony_ci} 411141cc406Sopenharmony_ci 412141cc406Sopenharmony_cistatic int 413141cc406Sopenharmony_cihp_accessor_choice_getint (HpAccessor this, HpData data) 414141cc406Sopenharmony_ci{ 415141cc406Sopenharmony_ci HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset); 416141cc406Sopenharmony_ci return choice->val; 417141cc406Sopenharmony_ci} 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_cistatic void 420141cc406Sopenharmony_cihp_accessor_choice_setint (HpAccessor _this, HpData data, int val) 421141cc406Sopenharmony_ci{ 422141cc406Sopenharmony_ci HpAccessorChoice this = (HpAccessorChoice)_this; 423141cc406Sopenharmony_ci HpChoice choice; 424141cc406Sopenharmony_ci HpChoice first_choice = 0; 425141cc406Sopenharmony_ci SANE_String_Const * strlist = this->strlist; 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci for (choice = this->choices; choice; choice = choice->next) 428141cc406Sopenharmony_ci { 429141cc406Sopenharmony_ci /* Skip choices which aren't in strlist. */ 430141cc406Sopenharmony_ci if (!*strlist || strcmp(*strlist, choice->name) != 0) 431141cc406Sopenharmony_ci continue; 432141cc406Sopenharmony_ci strlist++; 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci if (!first_choice) 435141cc406Sopenharmony_ci first_choice = choice; /* First enabled choice */ 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci if (choice->val == val) 438141cc406Sopenharmony_ci { 439141cc406Sopenharmony_ci *(HpChoice *)hp_data_data(data, this->data_offset) = choice; 440141cc406Sopenharmony_ci return; 441141cc406Sopenharmony_ci } 442141cc406Sopenharmony_ci } 443141cc406Sopenharmony_ci 444141cc406Sopenharmony_ci if (first_choice) 445141cc406Sopenharmony_ci *(HpChoice *)hp_data_data(data, this->data_offset) = first_choice; 446141cc406Sopenharmony_ci else 447141cc406Sopenharmony_ci assert(!"No choices to choose from?"); 448141cc406Sopenharmony_ci} 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ciSANE_Int 451141cc406Sopenharmony_cisanei_hp_accessor_choice_maxsize (HpAccessorChoice this) 452141cc406Sopenharmony_ci{ 453141cc406Sopenharmony_ci HpChoice choice; 454141cc406Sopenharmony_ci SANE_Int size = 0; 455141cc406Sopenharmony_ci 456141cc406Sopenharmony_ci for (choice = this->choices; choice; choice = choice->next) 457141cc406Sopenharmony_ci if ((SANE_Int)strlen(choice->name) >= size) 458141cc406Sopenharmony_ci size = strlen(choice->name) + 1; 459141cc406Sopenharmony_ci return size; 460141cc406Sopenharmony_ci} 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ciSANE_String_Const * 463141cc406Sopenharmony_cisanei_hp_accessor_choice_strlist (HpAccessorChoice this, 464141cc406Sopenharmony_ci HpOptSet optset, HpData data, 465141cc406Sopenharmony_ci const HpDeviceInfo *info) 466141cc406Sopenharmony_ci{ 467141cc406Sopenharmony_ci if (optset) 468141cc406Sopenharmony_ci { 469141cc406Sopenharmony_ci int old_val = hp_accessor_choice_getint((HpAccessor)this, data); 470141cc406Sopenharmony_ci HpChoice choice; 471141cc406Sopenharmony_ci size_t count = 0; 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci for (choice = this->choices; choice; choice = choice->next) 474141cc406Sopenharmony_ci if (sanei_hp_choice_isEnabled(choice, optset, data, info)) 475141cc406Sopenharmony_ci this->strlist[count++] = choice->name; 476141cc406Sopenharmony_ci this->strlist[count] = 0; 477141cc406Sopenharmony_ci 478141cc406Sopenharmony_ci hp_accessor_choice_setint((HpAccessor)this, data, old_val); 479141cc406Sopenharmony_ci } 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci return this->strlist; 482141cc406Sopenharmony_ci} 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ciHpAccessor 485141cc406Sopenharmony_cisanei_hp_accessor_choice_new (HpData data, HpChoice choices, 486141cc406Sopenharmony_ci hp_bool_t may_change) 487141cc406Sopenharmony_ci{ 488141cc406Sopenharmony_ci static const struct hp_accessor_type_s type = { 489141cc406Sopenharmony_ci hp_accessor_choice_get, hp_accessor_choice_set, 490141cc406Sopenharmony_ci hp_accessor_choice_getint, hp_accessor_choice_setint 491141cc406Sopenharmony_ci }; 492141cc406Sopenharmony_ci HpChoice choice; 493141cc406Sopenharmony_ci size_t count = 0; 494141cc406Sopenharmony_ci _HpAccessorChoice this; 495141cc406Sopenharmony_ci 496141cc406Sopenharmony_ci if ( may_change ) data->frozen = 0; 497141cc406Sopenharmony_ci 498141cc406Sopenharmony_ci for (choice = choices; choice; choice = choice->next) 499141cc406Sopenharmony_ci count++; 500141cc406Sopenharmony_ci this = sanei_hp_alloc(sizeof(*this) + (count+1) * sizeof(*this->strlist)); 501141cc406Sopenharmony_ci if (!this) 502141cc406Sopenharmony_ci return 0; 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci this->type = &type; 505141cc406Sopenharmony_ci this->data_offset = hp_data_alloc(data, this->data_size = sizeof(HpChoice)); 506141cc406Sopenharmony_ci this->choices = choices; 507141cc406Sopenharmony_ci this->strlist = (SANE_String_Const *)(this + 1); 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_ci count = 0; 510141cc406Sopenharmony_ci for (choice = this->choices; choice; choice = choice->next) 511141cc406Sopenharmony_ci this->strlist[count++] = choice->name; 512141cc406Sopenharmony_ci this->strlist[count] = 0; 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci return (HpAccessor)this; 515141cc406Sopenharmony_ci} 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci/* 518141cc406Sopenharmony_ci * class HpAccessorVector 519141cc406Sopenharmony_ci */ 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_citypedef struct hp_accessor_vector_s * _HpAccessorVector; 522141cc406Sopenharmony_ci 523141cc406Sopenharmony_cistruct hp_accessor_vector_s 524141cc406Sopenharmony_ci{ 525141cc406Sopenharmony_ci HpAccessorType type; 526141cc406Sopenharmony_ci size_t data_offset; 527141cc406Sopenharmony_ci size_t data_size; 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci unsigned short mask; 530141cc406Sopenharmony_ci unsigned short length; 531141cc406Sopenharmony_ci unsigned short offset; 532141cc406Sopenharmony_ci short stride; 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci unsigned short (*unscale)(HpAccessorVector this, SANE_Fixed fval); 535141cc406Sopenharmony_ci SANE_Fixed (*scale)(HpAccessorVector this, unsigned short val); 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci SANE_Fixed fmin; 538141cc406Sopenharmony_ci SANE_Fixed fmax; 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci}; 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_ciunsigned 543141cc406Sopenharmony_cisanei_hp_accessor_vector_length (HpAccessorVector this) 544141cc406Sopenharmony_ci{ 545141cc406Sopenharmony_ci return this->length; 546141cc406Sopenharmony_ci} 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ciSANE_Fixed 549141cc406Sopenharmony_cisanei_hp_accessor_vector_minval (HpAccessorVector this) 550141cc406Sopenharmony_ci{ 551141cc406Sopenharmony_ci return this->fmin; 552141cc406Sopenharmony_ci} 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_ciSANE_Fixed 555141cc406Sopenharmony_cisanei_hp_accessor_vector_maxval (HpAccessorVector this) 556141cc406Sopenharmony_ci{ 557141cc406Sopenharmony_ci return this->fmax; 558141cc406Sopenharmony_ci} 559141cc406Sopenharmony_ci 560141cc406Sopenharmony_cistatic unsigned short 561141cc406Sopenharmony_ci_v_get (HpAccessorVector this, const unsigned char * data) 562141cc406Sopenharmony_ci{ 563141cc406Sopenharmony_ci unsigned short val; 564141cc406Sopenharmony_ci 565141cc406Sopenharmony_ci if (this->mask <= 255) 566141cc406Sopenharmony_ci val = data[0]; 567141cc406Sopenharmony_ci else 568141cc406Sopenharmony_ci#ifndef NotOrig 569141cc406Sopenharmony_ci val = (data[0] << 8) + data[1]; 570141cc406Sopenharmony_ci#else 571141cc406Sopenharmony_ci val = (data[1] << 8) + data[0]; 572141cc406Sopenharmony_ci#endif 573141cc406Sopenharmony_ci 574141cc406Sopenharmony_ci return val & this->mask; 575141cc406Sopenharmony_ci} 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_cistatic void 578141cc406Sopenharmony_ci_v_set (HpAccessorVector this, unsigned char * data, unsigned short val) 579141cc406Sopenharmony_ci{ 580141cc406Sopenharmony_ci val &= this->mask; 581141cc406Sopenharmony_ci 582141cc406Sopenharmony_ci if (this->mask <= 255) 583141cc406Sopenharmony_ci { 584141cc406Sopenharmony_ci data[0] = (unsigned char)val; 585141cc406Sopenharmony_ci } 586141cc406Sopenharmony_ci else 587141cc406Sopenharmony_ci { 588141cc406Sopenharmony_ci#ifndef NotOrig 589141cc406Sopenharmony_ci data[1] = (unsigned char)val; 590141cc406Sopenharmony_ci data[0] = (unsigned char)(val >> 8); 591141cc406Sopenharmony_ci#else 592141cc406Sopenharmony_ci data[0] = (unsigned char)val; 593141cc406Sopenharmony_ci data[1] = (unsigned char)(val >> 8); 594141cc406Sopenharmony_ci#endif 595141cc406Sopenharmony_ci } 596141cc406Sopenharmony_ci} 597141cc406Sopenharmony_ci 598141cc406Sopenharmony_cistatic SANE_Status 599141cc406Sopenharmony_cihp_accessor_vector_get (HpAccessor _this, HpData d, void * valp) 600141cc406Sopenharmony_ci{ 601141cc406Sopenharmony_ci HpAccessorVector this = (HpAccessorVector)_this; 602141cc406Sopenharmony_ci SANE_Fixed * ptr = valp; 603141cc406Sopenharmony_ci const SANE_Fixed * end = ptr + this->length; 604141cc406Sopenharmony_ci const unsigned char * data = hp_data_data(d, this->data_offset); 605141cc406Sopenharmony_ci 606141cc406Sopenharmony_ci data += this->offset; 607141cc406Sopenharmony_ci 608141cc406Sopenharmony_ci while (ptr < end) 609141cc406Sopenharmony_ci { 610141cc406Sopenharmony_ci *ptr++ = (*this->scale)(this, _v_get(this, data)); 611141cc406Sopenharmony_ci data += this->stride; 612141cc406Sopenharmony_ci } 613141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 614141cc406Sopenharmony_ci} 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_cistatic SANE_Status 617141cc406Sopenharmony_cihp_accessor_vector_set (HpAccessor _this, HpData d, void * valp) 618141cc406Sopenharmony_ci{ 619141cc406Sopenharmony_ci HpAccessorVector this = (HpAccessorVector)_this; 620141cc406Sopenharmony_ci SANE_Fixed * ptr = valp; 621141cc406Sopenharmony_ci const SANE_Fixed * end = ptr + this->length; 622141cc406Sopenharmony_ci unsigned char * data = hp_data_data(d, this->data_offset); 623141cc406Sopenharmony_ci 624141cc406Sopenharmony_ci data += this->offset; 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci while (ptr < end) 627141cc406Sopenharmony_ci { 628141cc406Sopenharmony_ci if (*ptr < this->fmin) 629141cc406Sopenharmony_ci *ptr = this->fmin; 630141cc406Sopenharmony_ci if (*ptr > this->fmax) 631141cc406Sopenharmony_ci *ptr = this->fmax; 632141cc406Sopenharmony_ci 633141cc406Sopenharmony_ci _v_set(this, data, (*this->unscale)(this, *ptr++)); 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci data += this->stride; 636141cc406Sopenharmony_ci } 637141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 638141cc406Sopenharmony_ci} 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_cistatic unsigned short 641141cc406Sopenharmony_ci_vector_unscale (HpAccessorVector this, SANE_Fixed fval) 642141cc406Sopenharmony_ci{ 643141cc406Sopenharmony_ci unsigned short max_val = this->mask; 644141cc406Sopenharmony_ci return (fval * max_val + SANE_FIX(0.5)) / SANE_FIX(1.0); 645141cc406Sopenharmony_ci} 646141cc406Sopenharmony_ci 647141cc406Sopenharmony_cistatic SANE_Fixed 648141cc406Sopenharmony_ci_vector_scale (HpAccessorVector this, unsigned short val) 649141cc406Sopenharmony_ci{ 650141cc406Sopenharmony_ci unsigned short max_val = this->mask; 651141cc406Sopenharmony_ci return (SANE_FIX(1.0) * val + max_val / 2) / max_val; 652141cc406Sopenharmony_ci} 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ciHpAccessor 655141cc406Sopenharmony_cisanei_hp_accessor_vector_new (HpData data, unsigned length, unsigned depth) 656141cc406Sopenharmony_ci{ 657141cc406Sopenharmony_ci static const struct hp_accessor_type_s type = { 658141cc406Sopenharmony_ci hp_accessor_vector_get, hp_accessor_vector_set, 0, 0 659141cc406Sopenharmony_ci }; 660141cc406Sopenharmony_ci unsigned width = depth > 8 ? 2 : 1; 661141cc406Sopenharmony_ci _HpAccessorVector new = sanei_hp_alloc(sizeof(*new)); 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci if (!new) 664141cc406Sopenharmony_ci return 0; 665141cc406Sopenharmony_ci 666141cc406Sopenharmony_ci assert(depth > 0 && depth <= 16); 667141cc406Sopenharmony_ci assert(length > 0); 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci new->type = &type; 670141cc406Sopenharmony_ci new->data_size = length * width; 671141cc406Sopenharmony_ci new->data_offset = hp_data_alloc(data, new->data_size); 672141cc406Sopenharmony_ci 673141cc406Sopenharmony_ci new->mask = ((unsigned)1 << depth) - 1; 674141cc406Sopenharmony_ci new->length = length; 675141cc406Sopenharmony_ci new->offset = 0; 676141cc406Sopenharmony_ci new->stride = width; 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci new->scale = _vector_scale; 679141cc406Sopenharmony_ci new->unscale = _vector_unscale; 680141cc406Sopenharmony_ci 681141cc406Sopenharmony_ci new->fmin = SANE_FIX(0.0); 682141cc406Sopenharmony_ci new->fmax = SANE_FIX(1.0); 683141cc406Sopenharmony_ci 684141cc406Sopenharmony_ci return (HpAccessor)new; 685141cc406Sopenharmony_ci} 686141cc406Sopenharmony_ci 687141cc406Sopenharmony_cistatic unsigned short 688141cc406Sopenharmony_ci_gamma_vector_unscale (HpAccessorVector __sane_unused__ this, SANE_Fixed fval) 689141cc406Sopenharmony_ci{ 690141cc406Sopenharmony_ci unsigned short unscaled = fval / SANE_FIX(1.0); 691141cc406Sopenharmony_ci if (unscaled > 255) unscaled = 255; 692141cc406Sopenharmony_ci unscaled = 255 - unscaled; /* Don't know why. But this is how it works. */ 693141cc406Sopenharmony_ci 694141cc406Sopenharmony_ci return unscaled; 695141cc406Sopenharmony_ci} 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_cistatic SANE_Fixed 698141cc406Sopenharmony_ci_gamma_vector_scale (HpAccessorVector __sane_unused__ this, unsigned short val) 699141cc406Sopenharmony_ci{ 700141cc406Sopenharmony_ci SANE_Fixed scaled; 701141cc406Sopenharmony_ci val = 255-val; /* Don't know why. But this is how it works. */ 702141cc406Sopenharmony_ci scaled = val * SANE_FIX(1.0); 703141cc406Sopenharmony_ci 704141cc406Sopenharmony_ci return scaled; 705141cc406Sopenharmony_ci} 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ciHpAccessor 708141cc406Sopenharmony_cisanei_hp_accessor_gamma_vector_new (HpData data, unsigned length, 709141cc406Sopenharmony_ci unsigned depth) 710141cc406Sopenharmony_ci{ 711141cc406Sopenharmony_ci _HpAccessorVector this = 712141cc406Sopenharmony_ci ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) ); 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci if (!this) 716141cc406Sopenharmony_ci return 0; 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci this->offset += this->stride * (this->length - 1); 719141cc406Sopenharmony_ci this->stride = -this->stride; 720141cc406Sopenharmony_ci 721141cc406Sopenharmony_ci this->scale = _gamma_vector_scale; 722141cc406Sopenharmony_ci this->unscale = _gamma_vector_unscale; 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci this->fmin = SANE_FIX(0.0); 725141cc406Sopenharmony_ci this->fmax = SANE_FIX(255.0); 726141cc406Sopenharmony_ci 727141cc406Sopenharmony_ci return (HpAccessor)this; 728141cc406Sopenharmony_ci} 729141cc406Sopenharmony_ci 730141cc406Sopenharmony_cistatic unsigned short 731141cc406Sopenharmony_ci_matrix_vector_unscale (HpAccessorVector this, SANE_Fixed fval) 732141cc406Sopenharmony_ci{ 733141cc406Sopenharmony_ci unsigned short max_val = this->mask >> 1; 734141cc406Sopenharmony_ci unsigned short sign_bit = this->mask & ~max_val; 735141cc406Sopenharmony_ci unsigned short sign = 0; 736141cc406Sopenharmony_ci 737141cc406Sopenharmony_ci if (fval == SANE_FIX(1.0)) 738141cc406Sopenharmony_ci return sign_bit; 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_ci if (fval < 0) 741141cc406Sopenharmony_ci { 742141cc406Sopenharmony_ci sign = sign_bit; 743141cc406Sopenharmony_ci fval = -fval; 744141cc406Sopenharmony_ci } 745141cc406Sopenharmony_ci return sign | ((fval * max_val + this->fmax / 2) / this->fmax); 746141cc406Sopenharmony_ci} 747141cc406Sopenharmony_ci 748141cc406Sopenharmony_cistatic SANE_Fixed 749141cc406Sopenharmony_ci_matrix_vector_scale (HpAccessorVector this, unsigned short val) 750141cc406Sopenharmony_ci{ 751141cc406Sopenharmony_ci unsigned short max_val = this->mask >> 1; 752141cc406Sopenharmony_ci unsigned short sign_bit = this->mask & ~max_val; 753141cc406Sopenharmony_ci SANE_Fixed fval; 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_ci if (val == sign_bit) 756141cc406Sopenharmony_ci return SANE_FIX(1.0); 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_ci fval = (this->fmax * (val & max_val) + max_val / 2) / max_val; 759141cc406Sopenharmony_ci 760141cc406Sopenharmony_ci if ((val & sign_bit) != 0) 761141cc406Sopenharmony_ci fval = -fval; 762141cc406Sopenharmony_ci 763141cc406Sopenharmony_ci return fval; 764141cc406Sopenharmony_ci} 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ciHpAccessor 767141cc406Sopenharmony_cisanei_hp_accessor_matrix_vector_new (HpData data, unsigned length, 768141cc406Sopenharmony_ci unsigned depth) 769141cc406Sopenharmony_ci{ 770141cc406Sopenharmony_ci _HpAccessorVector this = 771141cc406Sopenharmony_ci ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) ); 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci if (!this) 774141cc406Sopenharmony_ci return 0; 775141cc406Sopenharmony_ci 776141cc406Sopenharmony_ci this->scale = _matrix_vector_scale; 777141cc406Sopenharmony_ci this->unscale = _matrix_vector_unscale; 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci this->fmax = depth == 10 ? SANE_FIX(4.0) : SANE_FIX(2.0); 780141cc406Sopenharmony_ci this->fmax *= (this->mask >> 1); 781141cc406Sopenharmony_ci this->fmax >>= (depth - 1); 782141cc406Sopenharmony_ci this->fmin = - this->fmax; 783141cc406Sopenharmony_ci 784141cc406Sopenharmony_ci return (HpAccessor)this; 785141cc406Sopenharmony_ci} 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ciHpAccessor 788141cc406Sopenharmony_cisanei_hp_accessor_subvector_new (HpAccessorVector super, 789141cc406Sopenharmony_ci unsigned nchan, unsigned chan) 790141cc406Sopenharmony_ci{ 791141cc406Sopenharmony_ci _HpAccessorVector this = sanei_hp_memdup(super, sizeof(*this)); 792141cc406Sopenharmony_ci 793141cc406Sopenharmony_ci if (!this) 794141cc406Sopenharmony_ci return 0; 795141cc406Sopenharmony_ci 796141cc406Sopenharmony_ci assert(chan < nchan); 797141cc406Sopenharmony_ci assert(this->length % nchan == 0); 798141cc406Sopenharmony_ci 799141cc406Sopenharmony_ci this->length /= nchan; 800141cc406Sopenharmony_ci 801141cc406Sopenharmony_ci if (this->stride < 0) 802141cc406Sopenharmony_ci this->offset += (nchan - chan - 1) * this->stride; 803141cc406Sopenharmony_ci else 804141cc406Sopenharmony_ci this->offset += chan * this->stride; 805141cc406Sopenharmony_ci 806141cc406Sopenharmony_ci this->stride *= nchan; 807141cc406Sopenharmony_ci 808141cc406Sopenharmony_ci return (HpAccessor)this; 809141cc406Sopenharmony_ci} 810141cc406Sopenharmony_ci 811141cc406Sopenharmony_ci/* 812141cc406Sopenharmony_ci * class HpAccessorGeometry 813141cc406Sopenharmony_ci */ 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_citypedef const struct hp_accessor_geometry_s * HpAccessorGeometry; 816141cc406Sopenharmony_citypedef struct hp_accessor_geometry_s * _HpAccessorGeometry; 817141cc406Sopenharmony_ci 818141cc406Sopenharmony_cistruct hp_accessor_geometry_s 819141cc406Sopenharmony_ci{ 820141cc406Sopenharmony_ci HpAccessorType type; 821141cc406Sopenharmony_ci size_t data_offset; 822141cc406Sopenharmony_ci size_t data_size; 823141cc406Sopenharmony_ci 824141cc406Sopenharmony_ci HpAccessor this; 825141cc406Sopenharmony_ci HpAccessor other; 826141cc406Sopenharmony_ci hp_bool_t is_br; 827141cc406Sopenharmony_ci HpAccessor resolution; 828141cc406Sopenharmony_ci}; 829141cc406Sopenharmony_ci 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_cistatic SANE_Status 832141cc406Sopenharmony_cihp_accessor_geometry_set (HpAccessor _this, HpData data, void * _valp) 833141cc406Sopenharmony_ci{ 834141cc406Sopenharmony_ci HpAccessorGeometry this = (HpAccessorGeometry)_this; 835141cc406Sopenharmony_ci SANE_Fixed * valp = _valp; 836141cc406Sopenharmony_ci SANE_Fixed limit; 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci sanei_hp_accessor_get(this->other, data, &limit); 839141cc406Sopenharmony_ci if (this->is_br ? *valp < limit : *valp > limit) 840141cc406Sopenharmony_ci *valp = limit; 841141cc406Sopenharmony_ci return sanei_hp_accessor_set(this->this, data, valp); 842141cc406Sopenharmony_ci} 843141cc406Sopenharmony_ci 844141cc406Sopenharmony_cistatic int 845141cc406Sopenharmony_ci_to_devpixels (SANE_Fixed val_mm, SANE_Fixed mm_per_pix) 846141cc406Sopenharmony_ci{ 847141cc406Sopenharmony_ci assert(val_mm >= 0); 848141cc406Sopenharmony_ci return (val_mm + mm_per_pix / 2) / mm_per_pix; 849141cc406Sopenharmony_ci} 850141cc406Sopenharmony_ci 851141cc406Sopenharmony_cistatic int 852141cc406Sopenharmony_cihp_accessor_geometry_getint (HpAccessor _this, HpData data) 853141cc406Sopenharmony_ci{ 854141cc406Sopenharmony_ci HpAccessorGeometry this = (HpAccessorGeometry)_this; 855141cc406Sopenharmony_ci SANE_Fixed this_val, other_val; 856141cc406Sopenharmony_ci int res = sanei_hp_accessor_getint(this->resolution, 857141cc406Sopenharmony_ci data); 858141cc406Sopenharmony_ci SANE_Fixed mm_per_pix = (SANE_FIX(MM_PER_INCH) + res / 2) / res; 859141cc406Sopenharmony_ci 860141cc406Sopenharmony_ci assert(res > 0); 861141cc406Sopenharmony_ci sanei_hp_accessor_get(this->this, data, &this_val); 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci if (this->is_br) 864141cc406Sopenharmony_ci { 865141cc406Sopenharmony_ci /* Convert to extent. */ 866141cc406Sopenharmony_ci sanei_hp_accessor_get(this->other, data, &other_val); 867141cc406Sopenharmony_ci assert(this_val >= other_val && other_val >= 0); 868141cc406Sopenharmony_ci return (_to_devpixels(this_val, mm_per_pix) 869141cc406Sopenharmony_ci - _to_devpixels(other_val, mm_per_pix) + 1); 870141cc406Sopenharmony_ci } 871141cc406Sopenharmony_ci return _to_devpixels(this_val, mm_per_pix); 872141cc406Sopenharmony_ci} 873141cc406Sopenharmony_ci 874141cc406Sopenharmony_ci/* 875141cc406Sopenharmony_ci * we should implement hp_accessor_geometry_setint, but we don't 876141cc406Sopenharmony_ci * need it yet... 877141cc406Sopenharmony_ci */ 878141cc406Sopenharmony_ci 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ciHpAccessor 881141cc406Sopenharmony_cisanei_hp_accessor_geometry_new (HpAccessor val, HpAccessor lim, hp_bool_t is_br, 882141cc406Sopenharmony_ci HpAccessor resolution) 883141cc406Sopenharmony_ci{ 884141cc406Sopenharmony_ci static const struct hp_accessor_type_s type = { 885141cc406Sopenharmony_ci hp_accessor_fixed_get, hp_accessor_geometry_set, 886141cc406Sopenharmony_ci hp_accessor_geometry_getint, 0 887141cc406Sopenharmony_ci }; 888141cc406Sopenharmony_ci _HpAccessorGeometry new = sanei_hp_alloc(sizeof(*new)); 889141cc406Sopenharmony_ci 890141cc406Sopenharmony_ci new->type = &type; 891141cc406Sopenharmony_ci new->data_offset = val->data_offset; 892141cc406Sopenharmony_ci new->data_size = val->data_size; 893141cc406Sopenharmony_ci 894141cc406Sopenharmony_ci new->this = val; 895141cc406Sopenharmony_ci new->other = lim; 896141cc406Sopenharmony_ci new->is_br = is_br; 897141cc406Sopenharmony_ci new->resolution = resolution; 898141cc406Sopenharmony_ci 899141cc406Sopenharmony_ci return (HpAccessor)new; 900141cc406Sopenharmony_ci} 901