1 /*------------------------------------------------------------------------
2 * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
3 *
4 * This file is part of the ZBar Bar Code Reader.
5 *
6 * The ZBar Bar Code Reader is free software; you can redistribute it
7 * and/or modify it under the terms of the GNU Lesser Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * The ZBar Bar Code Reader is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser Public License
17 * along with the ZBar Bar Code Reader; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301 USA
20 *
21 * http://sourceforge.net/projects/zbar
22 *------------------------------------------------------------------------*/
23 #ifndef _PROCESSOR_POSIX_H_
24 #define _PROCESSOR_POSIX_H_
25
26 #include "processor.h"
27
28 #ifdef HAVE_POLL_H
29 # include <poll.h>
30 #endif
31
32 #ifdef HAVE_POLL_H
33 typedef int (poll_handler_t)(zbar_processor_t*, int);
34
35 /* poll information */
36 typedef struct poll_desc_s {
37 int num; /* number of descriptors */
38 struct pollfd *fds; /* poll descriptors */
39 poll_handler_t **handlers; /* poll handlers */
40 } poll_desc_t;
41 #endif
42
43 struct processor_state_s {
44 #ifdef HAVE_POLL_H
45 poll_desc_t polling; /* polling registration */
46 poll_desc_t thr_polling; /* thread copy */
47 #endif
48 int kick_fds[2]; /* poll kicker */
49 poll_handler_t *pre_poll_handler; /* special case */
50 };
51
52
53 #ifdef HAVE_POLL_H
alloc_polls(volatile poll_desc_t * p)54 static inline int alloc_polls (volatile poll_desc_t *p)
55 {
56 p->fds = realloc(p->fds, p->num * sizeof(struct pollfd));
57 p->handlers = realloc(p->handlers, p->num * sizeof(poll_handler_t*));
58 /* FIXME should check for ENOMEM */
59 return(0);
60 }
61
add_poll(zbar_processor_t * proc,int fd,poll_handler_t * handler)62 static inline int add_poll (zbar_processor_t *proc,
63 int fd,
64 poll_handler_t *handler)
65 {
66 processor_state_t *state = proc->state;
67
68 _zbar_mutex_lock(&proc->mutex);
69
70 poll_desc_t *polling = &state->polling;
71 unsigned i = polling->num++;
72 zprintf(5, "[%d] fd=%d handler=%p\n", i, fd, handler);
73 if(!alloc_polls(polling)) {
74 memset(&polling->fds[i], 0, sizeof(struct pollfd));
75 polling->fds[i].fd = fd;
76 polling->fds[i].events = POLLIN;
77 polling->handlers[i] = handler;
78 }
79 else
80 i = -1;
81
82 _zbar_mutex_unlock(&proc->mutex);
83
84 if(proc->input_thread.started) {
85 assert(state->kick_fds[1] >= 0);
86 if(write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)) < 0)
87 return(-1);
88 }
89 else if(!proc->threaded) {
90 state->thr_polling.num = polling->num;
91 state->thr_polling.fds = polling->fds;
92 state->thr_polling.handlers = polling->handlers;
93 }
94 return(i);
95 }
96
remove_poll(zbar_processor_t * proc,int fd)97 static inline int remove_poll (zbar_processor_t *proc,
98 int fd)
99 {
100 processor_state_t *state = proc->state;
101
102 _zbar_mutex_lock(&proc->mutex);
103
104 poll_desc_t *polling = &state->polling;
105 int i;
106 for(i = polling->num - 1; i >= 0; i--)
107 if(polling->fds[i].fd == fd)
108 break;
109 zprintf(5, "[%d] fd=%d n=%d\n", i, fd, polling->num);
110
111 if(i >= 0) {
112 if(i + 1 < polling->num) {
113 int n = polling->num - i - 1;
114 memmove(&polling->fds[i], &polling->fds[i + 1],
115 n * sizeof(struct pollfd));
116 memmove(&polling->handlers[i], &polling->handlers[i + 1],
117 n * sizeof(poll_handler_t));
118 }
119 polling->num--;
120 i = alloc_polls(polling);
121 }
122
123 _zbar_mutex_unlock(&proc->mutex);
124
125 if(proc->input_thread.started) {
126 if(write(state->kick_fds[1], &i /* unused */, sizeof(unsigned)) < 0)
127 return(-1);
128 }
129 else if(!proc->threaded) {
130 state->thr_polling.num = polling->num;
131 state->thr_polling.fds = polling->fds;
132 state->thr_polling.handlers = polling->handlers;
133 }
134 return(i);
135 }
136 #endif
137
138 #endif
139