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