1141cc406Sopenharmony_ci/* 2141cc406Sopenharmony_ci * epsonds-net.c - SANE library for Epson scanners. 3141cc406Sopenharmony_ci * 4141cc406Sopenharmony_ci * Copyright (C) 2006-2016 Tower Technologies 5141cc406Sopenharmony_ci * Author: Alessandro Zummo <a.zummo@towertech.it> 6141cc406Sopenharmony_ci * 7141cc406Sopenharmony_ci * This file is part of the SANE package. 8141cc406Sopenharmony_ci * 9141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or 10141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as 11141cc406Sopenharmony_ci * published by the Free Software Foundation, version 2. 12141cc406Sopenharmony_ci */ 13141cc406Sopenharmony_ci 14141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 15141cc406Sopenharmony_ci 16141cc406Sopenharmony_ci#include "sane/config.h" 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci#ifdef HAVE_SYS_SELECT_H 19141cc406Sopenharmony_ci#include <sys/select.h> 20141cc406Sopenharmony_ci#endif 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci#include "sane/sane.h" 23141cc406Sopenharmony_ci#include "sane/saneopts.h" 24141cc406Sopenharmony_ci#include "sane/sanei_tcp.h" 25141cc406Sopenharmony_ci#include "sane/sanei_config.h" 26141cc406Sopenharmony_ci#include "sane/sanei_backend.h" 27141cc406Sopenharmony_ci 28141cc406Sopenharmony_ci#include "epsonds.h" 29141cc406Sopenharmony_ci#include "epsonds-net.h" 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci#include "byteorder.h" 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci#include "sane/sanei_debug.h" 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_cistatic ssize_t 37141cc406Sopenharmony_ciepsonds_net_read_raw(epsonds_scanner *s, unsigned char *buf, ssize_t wanted, 38141cc406Sopenharmony_ci SANE_Status *status) 39141cc406Sopenharmony_ci{ 40141cc406Sopenharmony_ci DBG(15, "%s: wanted: %ld\n", __func__, wanted); 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci if (wanted == 0) 43141cc406Sopenharmony_ci { 44141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 45141cc406Sopenharmony_ci return 0; 46141cc406Sopenharmony_ci } 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci int ready; 49141cc406Sopenharmony_ci ssize_t read = -1; 50141cc406Sopenharmony_ci fd_set readable; 51141cc406Sopenharmony_ci struct timeval tv; 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci tv.tv_sec = 10; 54141cc406Sopenharmony_ci tv.tv_usec = 0; 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci FD_ZERO(&readable); 57141cc406Sopenharmony_ci FD_SET(s->fd, &readable); 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci ready = select(s->fd + 1, &readable, NULL, NULL, &tv); 60141cc406Sopenharmony_ci if (ready > 0) { 61141cc406Sopenharmony_ci read = sanei_tcp_read(s->fd, buf, wanted); 62141cc406Sopenharmony_ci } else { 63141cc406Sopenharmony_ci DBG(15, "%s: select failed: %d\n", __func__, ready); 64141cc406Sopenharmony_ci } 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_ci if (read < wanted) { 69141cc406Sopenharmony_ci *status = SANE_STATUS_IO_ERROR; 70141cc406Sopenharmony_ci } 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci return read; 73141cc406Sopenharmony_ci} 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_cistatic ssize_t 76141cc406Sopenharmony_ciepsonds_net_read_buf(epsonds_scanner *s, unsigned char *buf, ssize_t wanted, 77141cc406Sopenharmony_ci SANE_Status * status) 78141cc406Sopenharmony_ci{ 79141cc406Sopenharmony_ci ssize_t read = 0; 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci DBG(23, "%s: reading up to %lu from buffer at %p, %lu available\n", 82141cc406Sopenharmony_ci __func__, (u_long) wanted, (void *) s->netptr, (u_long) s->netlen); 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci if ((size_t) wanted > s->netlen) { 85141cc406Sopenharmony_ci *status = SANE_STATUS_IO_ERROR; 86141cc406Sopenharmony_ci wanted = s->netlen; 87141cc406Sopenharmony_ci } 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci memcpy(buf, s->netptr, wanted); 90141cc406Sopenharmony_ci read = wanted; 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci s->netptr += read; 93141cc406Sopenharmony_ci s->netlen -= read; 94141cc406Sopenharmony_ci 95141cc406Sopenharmony_ci if (s->netlen == 0) { 96141cc406Sopenharmony_ci DBG(23, "%s: freeing %p\n", __func__, (void *) s->netbuf); 97141cc406Sopenharmony_ci free(s->netbuf); 98141cc406Sopenharmony_ci s->netbuf = s->netptr = NULL; 99141cc406Sopenharmony_ci s->netlen = 0; 100141cc406Sopenharmony_ci } 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ci return read; 103141cc406Sopenharmony_ci} 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_cissize_t 106141cc406Sopenharmony_ciepsonds_net_read(epsonds_scanner *s, unsigned char *buf, ssize_t wanted, 107141cc406Sopenharmony_ci SANE_Status * status) 108141cc406Sopenharmony_ci{ 109141cc406Sopenharmony_ci if (wanted < 0) { 110141cc406Sopenharmony_ci *status = SANE_STATUS_INVAL; 111141cc406Sopenharmony_ci return 0; 112141cc406Sopenharmony_ci } 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci size_t size; 115141cc406Sopenharmony_ci ssize_t read = 0; 116141cc406Sopenharmony_ci unsigned char header[12]; 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci /* read from remainder of buffer */ 119141cc406Sopenharmony_ci if (s->netptr) { 120141cc406Sopenharmony_ci return epsonds_net_read_buf(s, buf, wanted, status); 121141cc406Sopenharmony_ci } 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci /* receive net header */ 124141cc406Sopenharmony_ci read = epsonds_net_read_raw(s, header, 12, status); 125141cc406Sopenharmony_ci if (read != 12) { 126141cc406Sopenharmony_ci return 0; 127141cc406Sopenharmony_ci } 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_ci /* validate header */ 130141cc406Sopenharmony_ci if (header[0] != 'I' || header[1] != 'S') { 131141cc406Sopenharmony_ci DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]); 132141cc406Sopenharmony_ci *status = SANE_STATUS_IO_ERROR; 133141cc406Sopenharmony_ci return 0; 134141cc406Sopenharmony_ci } 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_ci /* parse payload size */ 137141cc406Sopenharmony_ci size = be32atoh(&header[6]); 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 140141cc406Sopenharmony_ci 141141cc406Sopenharmony_ci if (!s->netbuf) { 142141cc406Sopenharmony_ci DBG(15, "%s: direct read\n", __func__); 143141cc406Sopenharmony_ci DBG(23, "%s: wanted = %lu, available = %lu\n", __func__, 144141cc406Sopenharmony_ci (u_long) wanted, (u_long) size); 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci if ((size_t) wanted > size) { 147141cc406Sopenharmony_ci wanted = size; 148141cc406Sopenharmony_ci } 149141cc406Sopenharmony_ci 150141cc406Sopenharmony_ci read = epsonds_net_read_raw(s, buf, wanted, status); 151141cc406Sopenharmony_ci } else { 152141cc406Sopenharmony_ci DBG(15, "%s: buffered read\n", __func__); 153141cc406Sopenharmony_ci DBG(23, "%s: bufferable = %lu, available = %lu\n", __func__, 154141cc406Sopenharmony_ci (u_long) s->netlen, (u_long) size); 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci if (s->netlen > size) { 157141cc406Sopenharmony_ci s->netlen = size; 158141cc406Sopenharmony_ci } 159141cc406Sopenharmony_ci 160141cc406Sopenharmony_ci /* fill buffer */ 161141cc406Sopenharmony_ci read = epsonds_net_read_raw(s, s->netbuf, s->netlen, status); 162141cc406Sopenharmony_ci s->netptr = s->netbuf; 163141cc406Sopenharmony_ci s->netlen = (read > 0 ? read : 0); 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_ci /* copy wanted part */ 166141cc406Sopenharmony_ci read = epsonds_net_read_buf(s, buf, wanted, status); 167141cc406Sopenharmony_ci } 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci return read; 170141cc406Sopenharmony_ci} 171141cc406Sopenharmony_ci 172141cc406Sopenharmony_ciSANE_Status 173141cc406Sopenharmony_ciepsonds_net_request_read(epsonds_scanner *s, size_t len) 174141cc406Sopenharmony_ci{ 175141cc406Sopenharmony_ci SANE_Status status; 176141cc406Sopenharmony_ci epsonds_net_write(s, 0x2000, NULL, 0, len, &status); 177141cc406Sopenharmony_ci return status; 178141cc406Sopenharmony_ci} 179141cc406Sopenharmony_ci 180141cc406Sopenharmony_cisize_t 181141cc406Sopenharmony_ciepsonds_net_write(epsonds_scanner *s, unsigned int cmd, const unsigned char *buf, 182141cc406Sopenharmony_ci size_t buf_size, size_t reply_len, SANE_Status *status) 183141cc406Sopenharmony_ci{ 184141cc406Sopenharmony_ci unsigned char *h1, *h2; 185141cc406Sopenharmony_ci unsigned char *packet = malloc(12 + 8); 186141cc406Sopenharmony_ci 187141cc406Sopenharmony_ci if (!packet) { 188141cc406Sopenharmony_ci *status = SANE_STATUS_NO_MEM; 189141cc406Sopenharmony_ci return 0; 190141cc406Sopenharmony_ci } 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci h1 = packet; // packet header 193141cc406Sopenharmony_ci h2 = packet + 12; // data header 194141cc406Sopenharmony_ci 195141cc406Sopenharmony_ci if (reply_len) { 196141cc406Sopenharmony_ci if (s->netbuf) { 197141cc406Sopenharmony_ci DBG(23, "%s, freeing %p, %ld bytes unprocessed\n", 198141cc406Sopenharmony_ci __func__, (void *) s->netbuf, (u_long) s->netlen); 199141cc406Sopenharmony_ci free(s->netbuf); 200141cc406Sopenharmony_ci s->netbuf = s->netptr = NULL; 201141cc406Sopenharmony_ci s->netlen = 0; 202141cc406Sopenharmony_ci } 203141cc406Sopenharmony_ci s->netbuf = malloc(reply_len); 204141cc406Sopenharmony_ci if (!s->netbuf) { 205141cc406Sopenharmony_ci free(packet); 206141cc406Sopenharmony_ci *status = SANE_STATUS_NO_MEM; 207141cc406Sopenharmony_ci return 0; 208141cc406Sopenharmony_ci } 209141cc406Sopenharmony_ci s->netlen = reply_len; 210141cc406Sopenharmony_ci DBG(24, "%s: allocated %lu bytes at %p\n", __func__, 211141cc406Sopenharmony_ci (u_long) s->netlen, (void *) s->netbuf); 212141cc406Sopenharmony_ci } 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci DBG(24, "%s: cmd = %04x, buf = %p, buf_size = %lu, reply_len = %lu\n", 215141cc406Sopenharmony_ci __func__, cmd, (void *) buf, (u_long) buf_size, (u_long) reply_len); 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci memset(h1, 0x00, 12); 218141cc406Sopenharmony_ci memset(h2, 0x00, 8); 219141cc406Sopenharmony_ci 220141cc406Sopenharmony_ci h1[0] = 'I'; 221141cc406Sopenharmony_ci h1[1] = 'S'; 222141cc406Sopenharmony_ci 223141cc406Sopenharmony_ci h1[2] = cmd >> 8; // packet type 224141cc406Sopenharmony_ci h1[3] = cmd; // data type 225141cc406Sopenharmony_ci 226141cc406Sopenharmony_ci h1[4] = 0x00; 227141cc406Sopenharmony_ci h1[5] = 0x0C; // data offset 228141cc406Sopenharmony_ci 229141cc406Sopenharmony_ci DBG(24, "H1[0]: %02x %02x %02x %02x\n", h1[0], h1[1], h1[2], h1[3]); 230141cc406Sopenharmony_ci 231141cc406Sopenharmony_ci // 0x20 passthru 232141cc406Sopenharmony_ci // 0x21 job control 233141cc406Sopenharmony_ci 234141cc406Sopenharmony_ci if (buf_size) { 235141cc406Sopenharmony_ci htobe32a(&h1[6], buf_size); 236141cc406Sopenharmony_ci } 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci if((cmd >> 8) == 0x20) { 239141cc406Sopenharmony_ci 240141cc406Sopenharmony_ci htobe32a(&h1[6], buf_size + 8); // data size (data header + payload) 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ci htobe32a(&h2[0], buf_size); // payload size 243141cc406Sopenharmony_ci htobe32a(&h2[4], reply_len); // expected answer size 244141cc406Sopenharmony_ci 245141cc406Sopenharmony_ci DBG(24, "H1[6]: %02x %02x %02x %02x (%lu)\n", h1[6], h1[7], h1[8], h1[9], (u_long) (buf_size + 8)); 246141cc406Sopenharmony_ci DBG(24, "H2[0]: %02x %02x %02x %02x (%lu)\n", h2[0], h2[1], h2[2], h2[3], (u_long) buf_size); 247141cc406Sopenharmony_ci DBG(24, "H2[4]: %02x %02x %02x %02x (%lu)\n", h2[4], h2[5], h2[6], h2[7], (u_long) reply_len); 248141cc406Sopenharmony_ci } 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci if ((cmd >> 8) == 0x20 && (buf_size || reply_len)) { 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ci // send header + data header 253141cc406Sopenharmony_ci sanei_tcp_write(s->fd, packet, 12 + 8); 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci } else { 256141cc406Sopenharmony_ci sanei_tcp_write(s->fd, packet, 12); 257141cc406Sopenharmony_ci } 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci // send payload 260141cc406Sopenharmony_ci if (buf_size) 261141cc406Sopenharmony_ci sanei_tcp_write(s->fd, buf, buf_size); 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci free(packet); 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_ci *status = SANE_STATUS_GOOD; 266141cc406Sopenharmony_ci return buf_size; 267141cc406Sopenharmony_ci} 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ciSANE_Status 270141cc406Sopenharmony_ciepsonds_net_lock(struct epsonds_scanner *s) 271141cc406Sopenharmony_ci{ 272141cc406Sopenharmony_ci SANE_Status status; 273141cc406Sopenharmony_ci unsigned char buf[7] = "\x01\xa0\x04\x00\x00\x01\x2c"; 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci DBG(1, "%s\n", __func__); 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci epsonds_net_write(s, 0x2100, buf, 7, 0, &status); 278141cc406Sopenharmony_ci epsonds_net_read(s, buf, 1, &status); 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci // buf[0] should be ACK, 0x06 281141cc406Sopenharmony_ci 282141cc406Sopenharmony_ci return status; 283141cc406Sopenharmony_ci} 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ciSANE_Status 286141cc406Sopenharmony_ciepsonds_net_unlock(struct epsonds_scanner *s) 287141cc406Sopenharmony_ci{ 288141cc406Sopenharmony_ci SANE_Status status; 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci DBG(1, "%s\n", __func__); 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci epsonds_net_write(s, 0x2101, NULL, 0, 0, &status); 293141cc406Sopenharmony_ci/* epsonds_net_read(s, buf, 1, &status); */ 294141cc406Sopenharmony_ci return status; 295141cc406Sopenharmony_ci} 296141cc406Sopenharmony_ci#if WITH_AVAHI 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci#include <assert.h> 299141cc406Sopenharmony_ci#include <stdio.h> 300141cc406Sopenharmony_ci#include <stdlib.h> 301141cc406Sopenharmony_ci#include <string.h> 302141cc406Sopenharmony_ci#include <avahi-client/lookup.h> 303141cc406Sopenharmony_ci#include <avahi-common/error.h> 304141cc406Sopenharmony_ci#include <avahi-common/simple-watch.h> 305141cc406Sopenharmony_ci#include <sys/time.h> 306141cc406Sopenharmony_ci#include <errno.h> 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_cistatic AvahiSimplePoll *simple_poll = NULL; 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_cistatic struct timeval borowseEndTime; 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_cistatic int resolvedCount = 0; 313141cc406Sopenharmony_cistatic int browsedCount = 0; 314141cc406Sopenharmony_cistatic int waitResolver = 0; 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_citypedef struct { 317141cc406Sopenharmony_ci AvahiClient* client; 318141cc406Sopenharmony_ci Device_Found_CallBack callBack; 319141cc406Sopenharmony_ci}EDSAvahiUserData; 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_cistatic int my_avahi_simple_poll_loop(AvahiSimplePoll *s) { 322141cc406Sopenharmony_ci struct timeval currentTime; 323141cc406Sopenharmony_ci 324141cc406Sopenharmony_ci for (;;) 325141cc406Sopenharmony_ci { 326141cc406Sopenharmony_ci int r = avahi_simple_poll_iterate(s, 1); 327141cc406Sopenharmony_ci if (r != 0) 328141cc406Sopenharmony_ci { 329141cc406Sopenharmony_ci if (r >= 0 || errno != EINTR) 330141cc406Sopenharmony_ci { 331141cc406Sopenharmony_ci DBG(10, "my_avahi_simple_poll_loop end\n"); 332141cc406Sopenharmony_ci return r; 333141cc406Sopenharmony_ci } 334141cc406Sopenharmony_ci } 335141cc406Sopenharmony_ci 336141cc406Sopenharmony_ci if (waitResolver) { 337141cc406Sopenharmony_ci gettimeofday(¤tTime, NULL); 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci if ((currentTime.tv_sec - borowseEndTime.tv_sec) >= 3) 340141cc406Sopenharmony_ci { 341141cc406Sopenharmony_ci avahi_simple_poll_quit(simple_poll); 342141cc406Sopenharmony_ci DBG(10, "resolve timeout\n"); 343141cc406Sopenharmony_ci return 0; 344141cc406Sopenharmony_ci } 345141cc406Sopenharmony_ci } 346141cc406Sopenharmony_ci } 347141cc406Sopenharmony_ci} 348141cc406Sopenharmony_ci 349141cc406Sopenharmony_cistatic void 350141cc406Sopenharmony_ciepsonds_resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interface, 351141cc406Sopenharmony_ci AVAHI_GCC_UNUSED AvahiProtocol protocol, 352141cc406Sopenharmony_ci AvahiResolverEvent event, const char *name, 353141cc406Sopenharmony_ci const char *type, 354141cc406Sopenharmony_ci const char *domain, 355141cc406Sopenharmony_ci const char *host_name, 356141cc406Sopenharmony_ci const AvahiAddress *address, uint16_t port, AvahiStringList *txt, 357141cc406Sopenharmony_ci AvahiLookupResultFlags flags, 358141cc406Sopenharmony_ci void *userdata) 359141cc406Sopenharmony_ci{ 360141cc406Sopenharmony_ci // unused parameter 361141cc406Sopenharmony_ci (void)r; 362141cc406Sopenharmony_ci (void)type; 363141cc406Sopenharmony_ci (void)domain; 364141cc406Sopenharmony_ci (void)host_name; 365141cc406Sopenharmony_ci (void)port; 366141cc406Sopenharmony_ci (void)flags; 367141cc406Sopenharmony_ci EDSAvahiUserData* data = userdata; 368141cc406Sopenharmony_ci char ipAddr[AVAHI_ADDRESS_STR_MAX]; 369141cc406Sopenharmony_ci 370141cc406Sopenharmony_ci DBG(10, "epsonds_searchDevices resolve_callback\n"); 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci resolvedCount++; 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ci switch (event) { 376141cc406Sopenharmony_ci case AVAHI_RESOLVER_FAILURE: 377141cc406Sopenharmony_ci break; 378141cc406Sopenharmony_ci case AVAHI_RESOLVER_FOUND: 379141cc406Sopenharmony_ci avahi_address_snprint(ipAddr, sizeof(ipAddr), address); 380141cc406Sopenharmony_ci DBG(10, "epsonds_searchDevices name = %s \n", name); 381141cc406Sopenharmony_ci if (strlen(name) > 7) 382141cc406Sopenharmony_ci { 383141cc406Sopenharmony_ci if (strncmp(name, "EPSON", 5) == 0) 384141cc406Sopenharmony_ci { 385141cc406Sopenharmony_ci while(txt != NULL) 386141cc406Sopenharmony_ci { 387141cc406Sopenharmony_ci char* text = (char*)avahi_string_list_get_text(txt); 388141cc406Sopenharmony_ci DBG(10, "avahi string = %s\n", text); 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci if (strlen(text) > 4 && strncmp(text, "mdl=", 4) == 0) 391141cc406Sopenharmony_ci { 392141cc406Sopenharmony_ci if (data->callBack) 393141cc406Sopenharmony_ci { 394141cc406Sopenharmony_ci data->callBack(&text[4], ipAddr); 395141cc406Sopenharmony_ci break; 396141cc406Sopenharmony_ci } 397141cc406Sopenharmony_ci } 398141cc406Sopenharmony_ci txt = avahi_string_list_get_next(txt); 399141cc406Sopenharmony_ci } 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci } 402141cc406Sopenharmony_ci } 403141cc406Sopenharmony_ci break; 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci} 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_cistatic void 408141cc406Sopenharmony_cibrowse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, 409141cc406Sopenharmony_ci AvahiProtocol protocol, AvahiBrowserEvent event, 410141cc406Sopenharmony_ci const char *name, const char *type, 411141cc406Sopenharmony_ci const char *domain, 412141cc406Sopenharmony_ci AvahiLookupResultFlags flags, 413141cc406Sopenharmony_ci void* userdata) 414141cc406Sopenharmony_ci{ 415141cc406Sopenharmony_ci DBG(10, "browse_callback event = %d\n", event); 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci //unused parameter 418141cc406Sopenharmony_ci (void)b; 419141cc406Sopenharmony_ci (void)flags; 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci EDSAvahiUserData *data = userdata; 422141cc406Sopenharmony_ci switch (event) { 423141cc406Sopenharmony_ci case AVAHI_BROWSER_FAILURE: 424141cc406Sopenharmony_ci avahi_simple_poll_quit(simple_poll); 425141cc406Sopenharmony_ci return; 426141cc406Sopenharmony_ci case AVAHI_BROWSER_NEW: 427141cc406Sopenharmony_ci DBG(10, "browse_callback name = %s\n", name); 428141cc406Sopenharmony_ci browsedCount++; 429141cc406Sopenharmony_ci if (!(avahi_service_resolver_new(data->client, interface, protocol, name, 430141cc406Sopenharmony_ci type, domain, 431141cc406Sopenharmony_ci AVAHI_PROTO_UNSPEC, 0, 432141cc406Sopenharmony_ci epsonds_resolve_callback, data))) 433141cc406Sopenharmony_ci { 434141cc406Sopenharmony_ci DBG(10, "avahi_service_resolver_new fails\n"); 435141cc406Sopenharmony_ci break; 436141cc406Sopenharmony_ci } 437141cc406Sopenharmony_ci case AVAHI_BROWSER_REMOVE: 438141cc406Sopenharmony_ci break; 439141cc406Sopenharmony_ci case AVAHI_BROWSER_ALL_FOR_NOW: 440141cc406Sopenharmony_ci DBG(10, "AVAHI_BROWSER_ALL_FOR_NOW\n"); 441141cc406Sopenharmony_ci gettimeofday(&borowseEndTime, NULL); 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci if (browsedCount > resolvedCount) 444141cc406Sopenharmony_ci { 445141cc406Sopenharmony_ci DBG(10, "WAIT RESOLVER\n"); 446141cc406Sopenharmony_ci waitResolver = 1; 447141cc406Sopenharmony_ci }else{ 448141cc406Sopenharmony_ci DBG(10, "QUIT POLL\n"); 449141cc406Sopenharmony_ci avahi_simple_poll_quit(simple_poll); 450141cc406Sopenharmony_ci } 451141cc406Sopenharmony_ci break; 452141cc406Sopenharmony_ci case AVAHI_BROWSER_CACHE_EXHAUSTED: 453141cc406Sopenharmony_ci DBG(10, "AVAHI_BROWSER_CACHE_EXHAUSTED\n"); 454141cc406Sopenharmony_ci break; 455141cc406Sopenharmony_ci } 456141cc406Sopenharmony_ci} 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_cistatic void 459141cc406Sopenharmony_ciclient_callback(AvahiClient *c, AvahiClientState state, 460141cc406Sopenharmony_ci AVAHI_GCC_UNUSED void *userdata) 461141cc406Sopenharmony_ci{ 462141cc406Sopenharmony_ci assert(c); 463141cc406Sopenharmony_ci if (state == AVAHI_CLIENT_FAILURE) 464141cc406Sopenharmony_ci avahi_simple_poll_quit(simple_poll); 465141cc406Sopenharmony_ci} 466141cc406Sopenharmony_ci 467141cc406Sopenharmony_ciSANE_Status epsonds_searchDevices(Device_Found_CallBack deviceFoundCallBack) 468141cc406Sopenharmony_ci{ 469141cc406Sopenharmony_ci int result = SANE_STATUS_GOOD; 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci AvahiClient *client = NULL; 472141cc406Sopenharmony_ci AvahiServiceBrowser *sb = NULL; 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci EDSAvahiUserData data; 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci resolvedCount = 0; 477141cc406Sopenharmony_ci browsedCount = 0; 478141cc406Sopenharmony_ci waitResolver = 0; 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci int error = 0; 482141cc406Sopenharmony_ci DBG(10, "epsonds_searchDevices\n"); 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ci if (!(simple_poll = avahi_simple_poll_new())) { 485141cc406Sopenharmony_ci DBG(10, "avahi_simple_poll_new failed\n"); 486141cc406Sopenharmony_ci result = SANE_STATUS_INVAL; 487141cc406Sopenharmony_ci goto fail; 488141cc406Sopenharmony_ci } 489141cc406Sopenharmony_ci client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, 490141cc406Sopenharmony_ci client_callback, NULL, &error); 491141cc406Sopenharmony_ci if (!client) { 492141cc406Sopenharmony_ci DBG(10, "avahi_client_new failed %s\n", avahi_strerror(error)); 493141cc406Sopenharmony_ci result = SANE_STATUS_INVAL; 494141cc406Sopenharmony_ci goto fail; 495141cc406Sopenharmony_ci } 496141cc406Sopenharmony_ci data.client = client; 497141cc406Sopenharmony_ci data.callBack = deviceFoundCallBack; 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, 500141cc406Sopenharmony_ci AVAHI_PROTO_UNSPEC, "_scanner._tcp", 501141cc406Sopenharmony_ci NULL, 0, browse_callback, &data))) { 502141cc406Sopenharmony_ci DBG(10, "avahi_service_browser_new failed: %s\n", 503141cc406Sopenharmony_ci avahi_strerror(avahi_client_errno(client))); 504141cc406Sopenharmony_ci result = SANE_STATUS_INVAL; 505141cc406Sopenharmony_ci goto fail; 506141cc406Sopenharmony_ci } 507141cc406Sopenharmony_ci my_avahi_simple_poll_loop(simple_poll); 508141cc406Sopenharmony_cifail: 509141cc406Sopenharmony_ci if (sb) 510141cc406Sopenharmony_ci avahi_service_browser_free(sb); 511141cc406Sopenharmony_ci if (client) 512141cc406Sopenharmony_ci avahi_client_free(client); 513141cc406Sopenharmony_ci if (simple_poll) 514141cc406Sopenharmony_ci avahi_simple_poll_free(simple_poll); 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci DBG(10, "epsonds_searchDevices fin\n"); 517141cc406Sopenharmony_ci 518141cc406Sopenharmony_ci return result; 519141cc406Sopenharmony_ci} 520141cc406Sopenharmony_ci#endif 521