1141cc406Sopenharmony_ci/*
2141cc406Sopenharmony_ci  Mutex implementation for SnapScan backend
3141cc406Sopenharmony_ci
4141cc406Sopenharmony_ci  Copyright (C) 2000, 2004 Henrik Johansson, Oliver Schwartz
5141cc406Sopenharmony_ci
6141cc406Sopenharmony_ci  This program is free software; you can redistribute it and/or
7141cc406Sopenharmony_ci  modify it under the terms of the GNU General Public License as
8141cc406Sopenharmony_ci  published by the Free Software Foundation; either version 2 of the
9141cc406Sopenharmony_ci  License, or (at your option) any later version.
10141cc406Sopenharmony_ci
11141cc406Sopenharmony_ci  This program is distributed in the hope that it will be useful, but
12141cc406Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
13141cc406Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14141cc406Sopenharmony_ci  General Public License for more details.
15141cc406Sopenharmony_ci
16141cc406Sopenharmony_ci  You should have received a copy of the GNU General Public License
17141cc406Sopenharmony_ci  along with this program.  If not, see <https://www.gnu.org/licenses/>.
18141cc406Sopenharmony_ci
19141cc406Sopenharmony_ci  As a special exception, the authors of SANE give permission for
20141cc406Sopenharmony_ci  additional uses of the libraries contained in this release of SANE.
21141cc406Sopenharmony_ci
22141cc406Sopenharmony_ci  The exception is that, if you link a SANE library with other files
23141cc406Sopenharmony_ci  to produce an executable, this does not by itself cause the
24141cc406Sopenharmony_ci  resulting executable to be covered by the GNU General Public
25141cc406Sopenharmony_ci  License.  Your use of that executable is in no way restricted on
26141cc406Sopenharmony_ci  account of linking the SANE library code into it.
27141cc406Sopenharmony_ci
28141cc406Sopenharmony_ci  This exception does not, however, invalidate any other reasons why
29141cc406Sopenharmony_ci  the executable file might be covered by the GNU General Public
30141cc406Sopenharmony_ci  License.
31141cc406Sopenharmony_ci
32141cc406Sopenharmony_ci  If you submit changes to SANE to the maintainers to be included in
33141cc406Sopenharmony_ci  a subsequent release, you agree by submitting the changes that
34141cc406Sopenharmony_ci  those changes may be distributed with this exception intact.
35141cc406Sopenharmony_ci
36141cc406Sopenharmony_ci  If you write modifications of your own for SANE, it is your choice
37141cc406Sopenharmony_ci  whether to permit this exception to apply to your modifications.
38141cc406Sopenharmony_ci  If you do not wish that, delete this exception notice.*/
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ci#if defined __BEOS__
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ci#include <OS.h>
43141cc406Sopenharmony_ci#define snapscan_mutex_t sem_id
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_cistatic int snapscani_mutex_open(snapscan_mutex_t* a_sem, const char* dev __sane_unused__)
46141cc406Sopenharmony_ci{
47141cc406Sopenharmony_ci    *a_sem = create_sem(1, "snapscan_mutex");
48141cc406Sopenharmony_ci    return 1;
49141cc406Sopenharmony_ci}
50141cc406Sopenharmony_ci
51141cc406Sopenharmony_cistatic void snapscani_mutex_close(snapscan_mutex_t* a_sem)
52141cc406Sopenharmony_ci{
53141cc406Sopenharmony_ci    delete_sem(*a_sem);
54141cc406Sopenharmony_ci}
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_cistatic void snapscani_mutex_lock(snapscan_mutex_t* a_sem)
57141cc406Sopenharmony_ci{
58141cc406Sopenharmony_ci    acquire_sem(*a_sem);
59141cc406Sopenharmony_ci}
60141cc406Sopenharmony_ci
61141cc406Sopenharmony_cistatic void snapscani_mutex_unlock(snapscan_mutex_t* a_sem)
62141cc406Sopenharmony_ci{
63141cc406Sopenharmony_ci    release_sem(*a_sem);
64141cc406Sopenharmony_ci}
65141cc406Sopenharmony_ci
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_ci
68141cc406Sopenharmony_ci#elif defined USE_PTHREAD || defined HAVE_OS2_H
69141cc406Sopenharmony_ci
70141cc406Sopenharmony_ci#include <pthread.h>
71141cc406Sopenharmony_ci#define snapscan_mutex_t pthread_mutex_t
72141cc406Sopenharmony_ci
73141cc406Sopenharmony_cistatic int snapscani_mutex_open(snapscan_mutex_t* sem_id, const char* dev __sane_unused__)
74141cc406Sopenharmony_ci{
75141cc406Sopenharmony_ci    pthread_mutex_init(sem_id, NULL);
76141cc406Sopenharmony_ci    return 1;
77141cc406Sopenharmony_ci}
78141cc406Sopenharmony_ci
79141cc406Sopenharmony_cistatic void snapscani_mutex_close(snapscan_mutex_t* sem_id)
80141cc406Sopenharmony_ci{
81141cc406Sopenharmony_ci    pthread_mutex_destroy(sem_id);
82141cc406Sopenharmony_ci}
83141cc406Sopenharmony_ci
84141cc406Sopenharmony_cistatic void snapscani_mutex_lock(snapscan_mutex_t* sem_id)
85141cc406Sopenharmony_ci{
86141cc406Sopenharmony_ci    pthread_mutex_lock(sem_id);
87141cc406Sopenharmony_ci}
88141cc406Sopenharmony_ci
89141cc406Sopenharmony_cistatic void snapscani_mutex_unlock(snapscan_mutex_t* sem_id)
90141cc406Sopenharmony_ci{
91141cc406Sopenharmony_ci    pthread_mutex_unlock(sem_id);
92141cc406Sopenharmony_ci}
93141cc406Sopenharmony_ci
94141cc406Sopenharmony_ci#else /* defined USE_PTHREAD || defined HAVE_OS2_H */
95141cc406Sopenharmony_ci
96141cc406Sopenharmony_ci#include <sys/ipc.h>
97141cc406Sopenharmony_ci#include <sys/sem.h>
98141cc406Sopenharmony_ci#include <sys/types.h>
99141cc406Sopenharmony_ci#include <unistd.h>
100141cc406Sopenharmony_ci
101141cc406Sopenharmony_ci#define snapscan_mutex_t int
102141cc406Sopenharmony_ci
103141cc406Sopenharmony_ci/* check for union semun */
104141cc406Sopenharmony_ci#if defined(HAVE_UNION_SEMUN)
105141cc406Sopenharmony_ci/* union semun is defined by including <sys/sem.h> */
106141cc406Sopenharmony_ci#else
107141cc406Sopenharmony_ci/* according to X/OPEN we have to define it ourselves */
108141cc406Sopenharmony_ciunion semun {
109141cc406Sopenharmony_ci   int val;                    /* value for SETVAL */
110141cc406Sopenharmony_ci   struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
111141cc406Sopenharmony_ci   unsigned short int *array;  /* array for GETALL, SETALL */
112141cc406Sopenharmony_ci   struct seminfo *__buf;      /* buffer for IPC_INFO */
113141cc406Sopenharmony_ci};
114141cc406Sopenharmony_ci#endif /* defined HAVE_UNION_SEMUN */
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_cistatic struct sembuf sem_wait = { 0, -1, 0 };
117141cc406Sopenharmony_cistatic struct sembuf sem_signal = { 0, 1, 0 };
118141cc406Sopenharmony_ci
119141cc406Sopenharmony_cistatic unsigned int snapscani_bernstein(const unsigned char* str)
120141cc406Sopenharmony_ci{
121141cc406Sopenharmony_ci    unsigned int hash = 5381; /* some arbitrary number */
122141cc406Sopenharmony_ci    int c;
123141cc406Sopenharmony_ci
124141cc406Sopenharmony_ci    while (*str)
125141cc406Sopenharmony_ci    {
126141cc406Sopenharmony_ci        c = *str++;
127141cc406Sopenharmony_ci        hash = ((hash << 5) + hash) + c;
128141cc406Sopenharmony_ci    }
129141cc406Sopenharmony_ci    return hash;
130141cc406Sopenharmony_ci}
131141cc406Sopenharmony_ci
132141cc406Sopenharmony_cistatic int snapscani_mutex_open(snapscan_mutex_t* sem_id, const char* dev)
133141cc406Sopenharmony_ci{
134141cc406Sopenharmony_ci    static const char *me = "snapscani_mutex_open";
135141cc406Sopenharmony_ci    key_t ipc_key = -1;
136141cc406Sopenharmony_ci
137141cc406Sopenharmony_ci    if (strstr(dev, "libusb:") == dev)
138141cc406Sopenharmony_ci    {
139141cc406Sopenharmony_ci        key_t ipc_key = (key_t) snapscani_bernstein((const unsigned char*) dev+7);
140141cc406Sopenharmony_ci	DBG (DL_INFO, "%s: using IPC key 0x%08x for device %s\n",
141141cc406Sopenharmony_ci	     me, ipc_key, dev);
142141cc406Sopenharmony_ci    }
143141cc406Sopenharmony_ci    else
144141cc406Sopenharmony_ci    {
145141cc406Sopenharmony_ci      ipc_key = ftok(dev, 0x12);
146141cc406Sopenharmony_ci
147141cc406Sopenharmony_ci	if (ipc_key == -1)
148141cc406Sopenharmony_ci	{
149141cc406Sopenharmony_ci	  DBG (DL_MAJOR_ERROR, "%s: could not obtain IPC key for device %s: %s\n", me, dev, strerror(errno));
150141cc406Sopenharmony_ci	    return 0;
151141cc406Sopenharmony_ci	}
152141cc406Sopenharmony_ci    }
153141cc406Sopenharmony_ci
154141cc406Sopenharmony_ci    *sem_id = semget( ipc_key, 1, IPC_CREAT | 0660 );
155141cc406Sopenharmony_ci    if (*sem_id == -1)
156141cc406Sopenharmony_ci    {
157141cc406Sopenharmony_ci        DBG (DL_MAJOR_ERROR, "%s: semget failed: %s\n", me, strerror(errno));
158141cc406Sopenharmony_ci	return 0;
159141cc406Sopenharmony_ci    }
160141cc406Sopenharmony_ci
161141cc406Sopenharmony_ci    semop(*sem_id, &sem_signal, 1);
162141cc406Sopenharmony_ci    return 1;
163141cc406Sopenharmony_ci}
164141cc406Sopenharmony_ci
165141cc406Sopenharmony_cistatic void snapscani_mutex_close(snapscan_mutex_t* sem_id)
166141cc406Sopenharmony_ci{
167141cc406Sopenharmony_ci    static union semun dummy_semun_arg;
168141cc406Sopenharmony_ci    semctl(*sem_id, 0, IPC_RMID, dummy_semun_arg);
169141cc406Sopenharmony_ci}
170141cc406Sopenharmony_ci
171141cc406Sopenharmony_cistatic void snapscani_mutex_lock(snapscan_mutex_t* sem_id)
172141cc406Sopenharmony_ci{
173141cc406Sopenharmony_ci    semop(*sem_id, &sem_wait, 1);
174141cc406Sopenharmony_ci}
175141cc406Sopenharmony_ci
176141cc406Sopenharmony_cistatic void snapscani_mutex_unlock(snapscan_mutex_t* sem_id)
177141cc406Sopenharmony_ci{
178141cc406Sopenharmony_ci    semop(*sem_id, &sem_signal, 1);
179141cc406Sopenharmony_ci}
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_ci#endif /* defined USE_PTHREAD || defined HAVE_OS2_H */
182