1/* sane - Scanner Access Now Easy.
2
3   Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
4
5   This file is part of the SANE package.
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
20   As a special exception, the authors of SANE give permission for
21   additional uses of the libraries contained in this release of SANE.
22
23   The exception is that, if you link a SANE library with other files
24   to produce an executable, this does not by itself cause the
25   resulting executable to be covered by the GNU General Public
26   License.  Your use of that executable is in no way restricted on
27   account of linking the SANE library code into it.
28
29   This exception does not, however, invalidate any other reasons why
30   the executable file might be covered by the GNU General Public
31   License.
32
33   If you submit changes to SANE to the maintainers to be included in
34   a subsequent release, you agree by submitting the changes that
35   those changes may be distributed with this exception intact.
36
37   If you write modifications of your own for SANE, it is your choice
38   whether to permit this exception to apply to your modifications.
39   If you do not wish that, delete this exception notice.
40*/
41
42/** @file
43 * @brief Shared memory channel implementation.
44 */
45
46#include "gt68xx_shm_channel.h"
47
48#include <sys/types.h>
49#include <sys/ipc.h>
50#include <sys/shm.h>
51#include <unistd.h>
52#include <fcntl.h>
53#include <errno.h>
54
55#ifndef SHM_R
56#define SHM_R 0
57#endif
58
59#ifndef SHM_W
60#define SHM_W 0
61#endif
62
63/** Shared memory channel.
64 *
65 */
66struct Shm_Channel
67{
68  SANE_Int buf_size;			/**< Size of each buffer */
69  SANE_Int buf_count;			/**< Number of buffers */
70  void *shm_area;			/**< Address of shared memory area */
71  SANE_Byte **buffers;			/**< Array of pointers to buffers */
72  SANE_Int *buffer_bytes;		/**< Array of buffer byte counts */
73  int writer_put_pipe[2];		/**< Notification pipe from writer */
74  int reader_put_pipe[2];		/**< Notification pipe from reader */
75};
76
77/** Dummy union to find out the needed alignment */
78union Shm_Channel_Align
79{
80  int i;
81  long l;
82  void *ptr;
83  void (*func_ptr) (void);
84  double d;
85};
86
87/** Check if shm_channel is valid */
88#define SHM_CHANNEL_CHECK(shm_channel, func_name)               \
89  do {                                                          \
90    if ((shm_channel) == NULL)                                  \
91      {                                                         \
92        DBG (3, "%s: BUG: shm_channel==NULL\n", (func_name));   \
93        return SANE_STATUS_INVAL;                               \
94      }                                                         \
95  } while (SANE_FALSE)
96
97/** Alignment for shared memory contents */
98#define SHM_CHANNEL_ALIGNMENT   (sizeof (union Shm_Channel_Align))
99
100/** Align the given size up to a multiple of the given alignment */
101#define SHM_CHANNEL_ROUND_UP(size, align) \
102  ( ((size) % (align)) ? ((size)/(align) + 1)*(align) : (size) )
103
104/** Align the size using SHM_CHANNEL_ALIGNMENT */
105#define SHM_CHANNEL_ALIGN(size) \
106  SHM_CHANNEL_ROUND_UP((size_t) (size), SHM_CHANNEL_ALIGNMENT)
107
108/** Close a file descriptor if it is currently open.
109 *
110 * This function checks if the file descriptor is not -1, and sets it to -1
111 * after close (so that it will not be closed twice).
112 *
113 * @param fd_var Pointer to a variable holding the file descriptor.
114 */
115static void
116shm_channel_fd_safe_close (int *fd_var)
117{
118  if (*fd_var != -1)
119    {
120      close (*fd_var);
121      *fd_var = -1;
122    }
123}
124
125static SANE_Status
126shm_channel_fd_set_close_on_exec (int fd)
127{
128  long value;
129
130  value = fcntl (fd, F_GETFD, 0L);
131  if (value == -1)
132    return SANE_STATUS_IO_ERROR;
133  if (fcntl (fd, F_SETFD, value | FD_CLOEXEC) == -1)
134    return SANE_STATUS_IO_ERROR;
135
136  return SANE_STATUS_GOOD;
137}
138
139#if 0
140static SANE_Status
141shm_channel_fd_set_non_blocking (int fd, SANE_Bool non_blocking)
142{
143  long value;
144
145  value = fcntl (fd, F_GETFL, 0L);
146  if (value == -1)
147    return SANE_STATUS_IO_ERROR;
148
149  if (non_blocking)
150    value |= O_NONBLOCK;
151  else
152    value &= ~O_NONBLOCK;
153
154  if (fcntl (fd, F_SETFL, value) == -1)
155    return SANE_STATUS_IO_ERROR;
156
157  return SANE_STATUS_GOOD;
158}
159#endif
160
161/** Create a new shared memory channel.
162 *
163 * This function should be called before the fork to set up the shared memory.
164 *
165 * @param buf_size  Size of each shared memory buffer in bytes.
166 * @param buf_count Number of shared memory buffers (up to 255).
167 * @param shm_channel_return Returned shared memory channel object.
168 */
169SANE_Status
170shm_channel_new (SANE_Int buf_size,
171		 SANE_Int buf_count, Shm_Channel ** shm_channel_return)
172{
173  Shm_Channel *shm_channel;
174  void *shm_area;
175  SANE_Byte *shm_data;
176  int shm_buffer_bytes_size, shm_buffer_size;
177  int shm_size;
178  int shm_id;
179  int i;
180
181  if (buf_size <= 0)
182    {
183      DBG (3, "shm_channel_new: invalid buf_size=%d\n", buf_size);
184      return SANE_STATUS_INVAL;
185    }
186  if (buf_count <= 0 || buf_count > 255)
187    {
188      DBG (3, "shm_channel_new: invalid buf_count=%d\n", buf_count);
189      return SANE_STATUS_INVAL;
190    }
191  if (!shm_channel_return)
192    {
193      DBG (3, "shm_channel_new: BUG: shm_channel_return==NULL\n");
194      return SANE_STATUS_INVAL;
195    }
196
197  *shm_channel_return = NULL;
198
199  shm_channel = (Shm_Channel *) malloc (sizeof (Shm_Channel));
200  if (!shm_channel)
201    {
202      DBG (3, "shm_channel_new: no memory for Shm_Channel\n");
203      return SANE_STATUS_NO_MEM;
204    }
205
206  shm_channel->buf_size = buf_size;
207  shm_channel->buf_count = buf_count;
208  shm_channel->shm_area = NULL;
209  shm_channel->buffers = NULL;
210  shm_channel->buffer_bytes = NULL;
211  shm_channel->writer_put_pipe[0] = shm_channel->writer_put_pipe[1] = -1;
212  shm_channel->reader_put_pipe[0] = shm_channel->reader_put_pipe[1] = -1;
213
214  shm_channel->buffers =
215    (SANE_Byte **) malloc (sizeof (SANE_Byte *) * buf_count);
216  if (!shm_channel->buffers)
217    {
218      DBG (3, "shm_channel_new: no memory for buffer pointers\n");
219      shm_channel_free (shm_channel);
220      return SANE_STATUS_NO_MEM;
221    }
222
223  if (pipe (shm_channel->writer_put_pipe) == -1)
224    {
225      DBG (3, "shm_channel_new: cannot create writer put pipe: %s\n",
226	   strerror (errno));
227      shm_channel_free (shm_channel);
228      return SANE_STATUS_NO_MEM;
229    }
230
231  if (pipe (shm_channel->reader_put_pipe) == -1)
232    {
233      DBG (3, "shm_channel_new: cannot create reader put pipe: %s\n",
234	   strerror (errno));
235      shm_channel_free (shm_channel);
236      return SANE_STATUS_NO_MEM;
237    }
238
239  shm_channel_fd_set_close_on_exec (shm_channel->reader_put_pipe[0]);
240  shm_channel_fd_set_close_on_exec (shm_channel->reader_put_pipe[1]);
241  shm_channel_fd_set_close_on_exec (shm_channel->writer_put_pipe[0]);
242  shm_channel_fd_set_close_on_exec (shm_channel->writer_put_pipe[1]);
243
244  shm_buffer_bytes_size = SHM_CHANNEL_ALIGN (sizeof (SANE_Int) * buf_count);
245  shm_buffer_size = SHM_CHANNEL_ALIGN (buf_size);
246  shm_size = shm_buffer_bytes_size + buf_count * shm_buffer_size;
247
248  shm_id = shmget (IPC_PRIVATE, shm_size, IPC_CREAT | SHM_R | SHM_W);
249  if (shm_id == -1)
250    {
251      DBG (3, "shm_channel_new: cannot create shared memory segment: %s\n",
252	   strerror (errno));
253      shm_channel_free (shm_channel);
254      return SANE_STATUS_NO_MEM;
255    }
256
257  shm_area = shmat (shm_id, NULL, 0);
258  if (shm_area == (void *) -1)
259    {
260      DBG (3, "shm_channel_new: cannot attach to shared memory segment: %s\n",
261	   strerror (errno));
262      shmctl (shm_id, IPC_RMID, NULL);
263      shm_channel_free (shm_channel);
264      return SANE_STATUS_NO_MEM;
265    }
266
267  if (shmctl (shm_id, IPC_RMID, NULL) == -1)
268    {
269      DBG (3, "shm_channel_new: cannot remove shared memory segment id: %s\n",
270	   strerror (errno));
271      shmdt (shm_area);
272      shmctl (shm_id, IPC_RMID, NULL);
273      shm_channel_free (shm_channel);
274      return SANE_STATUS_NO_MEM;
275    }
276
277  shm_channel->shm_area = shm_area;
278
279  shm_channel->buffer_bytes = (SANE_Int *) shm_area;
280  shm_data = ((SANE_Byte *) shm_area) + shm_buffer_bytes_size;
281  for (i = 0; i < shm_channel->buf_count; ++i)
282    {
283      shm_channel->buffers[i] = shm_data;
284      shm_data += shm_buffer_size;
285    }
286
287  *shm_channel_return = shm_channel;
288  return SANE_STATUS_GOOD;
289}
290
291/** Close the shared memory channel and release associated resources.
292 *
293 * @param shm_channel Shared memory channel object.
294 */
295SANE_Status
296shm_channel_free (Shm_Channel * shm_channel)
297{
298  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_free");
299
300  if (shm_channel->shm_area)
301    {
302      shmdt (shm_channel->shm_area);
303      shm_channel->shm_area = NULL;
304    }
305
306  if (shm_channel->buffers)
307    {
308      free (shm_channel->buffers);
309      shm_channel->buffers = NULL;
310    }
311
312  shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[0]);
313  shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]);
314  shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[0]);
315  shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]);
316
317  return SANE_STATUS_GOOD;
318}
319
320/** Initialize the shared memory channel in the writer process.
321 *
322 * This function should be called after the fork in the process which will
323 * write data to the channel.
324 *
325 * @param shm_channel Shared memory channel object.
326 */
327SANE_Status
328shm_channel_writer_init (Shm_Channel * shm_channel)
329{
330  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_init");
331
332  shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[0]);
333  shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]);
334
335  return SANE_STATUS_GOOD;
336}
337
338/** Get a free shared memory buffer for writing.
339 *
340 * This function may block waiting for a free buffer (if the reader process
341 * does not process the data fast enough).
342 *
343 * After successful call to this function the writer process should fill the
344 * buffer with the data and pass the buffer identifier from @a buffer_id_return
345 * to shm_channel_writer_put_buffer() to give the buffer to the reader process.
346 *
347 * @param shm_channel Shared memory channel object.
348 * @param buffer_id_return Returned buffer identifier.
349 * @param buffer_addr_return Returned buffer address.
350 *
351 * @return
352 * - SANE_STATUS_GOOD - a free buffer was available (or became available after
353 *   waiting for it); @a buffer_id_return and @a buffer_addr_return are filled
354 *   with valid values.
355 * - SANE_STATUS_EOF - the reader process has closed its half of the channel.
356 * - SANE_STATUS_IO_ERROR - an I/O error occurred.
357 */
358SANE_Status
359shm_channel_writer_get_buffer (Shm_Channel * shm_channel,
360			       SANE_Int * buffer_id_return,
361			       SANE_Byte ** buffer_addr_return)
362{
363  SANE_Byte buf_index;
364  int bytes_read;
365
366  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_get_buffer");
367
368  do
369    bytes_read = read (shm_channel->reader_put_pipe[0], &buf_index, 1);
370  while (bytes_read == -1 && errno == EINTR);
371
372  if (bytes_read == 1)
373    {
374      SANE_Int index = buf_index;
375      if (index < shm_channel->buf_count)
376	{
377	  *buffer_id_return = index;
378	  *buffer_addr_return = shm_channel->buffers[index];
379	  return SANE_STATUS_GOOD;
380	}
381    }
382
383  *buffer_id_return = -1;
384  *buffer_addr_return = NULL;
385  if (bytes_read == 0)
386    return SANE_STATUS_EOF;
387  else
388    return SANE_STATUS_IO_ERROR;
389}
390
391/** Pass a filled shared memory buffer to the reader process.
392 *
393 * @param shm_channel Shared memory channel object.
394 * @param buffer_id Buffer identifier from shm_channel_writer_put_buffer().
395 * @param buffer_bytes Number of data bytes in the buffer.
396 *
397 * @return
398 * - SANE_STATUS_GOOD - the buffer was successfully queued.
399 * - SANE_STATUS_IO_ERROR - the reader process has closed its half of the
400 *   channel, or another I/O error occurred.
401 */
402SANE_Status
403shm_channel_writer_put_buffer (Shm_Channel * shm_channel,
404			       SANE_Int buffer_id, SANE_Int buffer_bytes)
405{
406  SANE_Byte buf_index;
407  int bytes_written;
408
409  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_put_buffer");
410
411  if (buffer_id < 0 || buffer_id >= shm_channel->buf_count)
412    {
413      DBG (3, "shm_channel_writer_put_buffer: BUG: buffer_id=%d\n",
414	   buffer_id);
415      return SANE_STATUS_INVAL;
416    }
417
418  shm_channel->buffer_bytes[buffer_id] = buffer_bytes;
419
420  buf_index = (SANE_Byte) buffer_id;
421  do
422    bytes_written = write (shm_channel->writer_put_pipe[1], &buf_index, 1);
423  while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR));
424
425  if (bytes_written == 1)
426    return SANE_STATUS_GOOD;
427  else
428    return SANE_STATUS_IO_ERROR;
429}
430
431/** Close the writing half of the shared memory channel.
432 *
433 * @param shm_channel Shared memory channel object.
434 */
435SANE_Status
436shm_channel_writer_close (Shm_Channel * shm_channel)
437{
438  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_close");
439
440  shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]);
441
442  return SANE_STATUS_GOOD;
443}
444
445
446/** Initialize the shared memory channel in the reader process.
447 *
448 * This function should be called after the fork in the process which will
449 * read data from the channel.
450 *
451 * @param shm_channel Shared memory channel object.
452 */
453SANE_Status
454shm_channel_reader_init (Shm_Channel * shm_channel)
455{
456  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_init");
457
458  shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]);
459
460  /* Don't close reader_put_pipe[0] here.  Otherwise, if the channel writer
461   * process dies early, this process might get SIGPIPE - and I don't want to
462   * mess with signals in the main process. */
463  /* shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[0]); */
464
465  return SANE_STATUS_GOOD;
466}
467
468#if 0
469/** Set non-blocking or blocking mode for the reading half of the shared memory
470 * channel.
471 *
472 * @param shm_channel Shared memory channel object.
473 * @param non_blocking SANE_TRUE to make the channel non-blocking, SANE_FALSE
474 * to set blocking mode.
475 *
476 * @return
477 * - SANE_STATUS_GOOD - the requested mode was set successfully.
478 * - SANE_STATUS_IO_ERROR - error setting the requested mode.
479 */
480SANE_Status
481shm_channel_reader_set_io_mode (Shm_Channel * shm_channel,
482				SANE_Bool non_blocking)
483{
484  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_set_io_mode");
485
486  return shm_channel_fd_set_non_blocking (shm_channel->writer_put_pipe[0],
487					  non_blocking);
488}
489
490/** Get the file descriptor which will signal when some data is available in
491 * the shared memory channel.
492 *
493 * The returned file descriptor can be used in select() or poll().  When one of
494 * these functions signals that the file descriptor is ready for reading,
495 * shm_channel_reader_get_buffer() should return some data without blocking.
496 *
497 * @param shm_channel Shared memory channel object.
498 * @param fd_return The returned file descriptor.
499 *
500 * @return
501 * - SANE_STATUS_GOOD - the file descriptor was returned.
502 */
503SANE_Status
504shm_channel_reader_get_select_fd (Shm_Channel * shm_channel,
505				  SANE_Int * fd_return)
506{
507  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_get_select_fd");
508
509  *fd_return = shm_channel->writer_put_pipe[0];
510
511  return SANE_STATUS_GOOD;
512}
513#endif
514
515/** Start reading from the shared memory channel.
516 *
517 * A newly initialized shared memory channel is stopped - the writer process
518 * will block on shm_channel_writer_get_buffer().  This function will pass all
519 * available buffers to the writer process, starting the transfer through the
520 * channel.
521 *
522 * @param shm_channel Shared memory channel object.
523 */
524SANE_Status
525shm_channel_reader_start (Shm_Channel * shm_channel)
526{
527  int i, bytes_written;
528  SANE_Byte buffer_id;
529
530  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_start");
531
532  for (i = 0; i < shm_channel->buf_count; ++i)
533    {
534      buffer_id = i;
535      do
536	bytes_written =
537	  write (shm_channel->reader_put_pipe[1], &buffer_id, 1);
538      while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR));
539
540      if (bytes_written == -1)
541	{
542	  DBG (3, "shm_channel_reader_start: write error at buffer %d: %s\n",
543	       i, strerror (errno));
544	  return SANE_STATUS_IO_ERROR;
545	}
546    }
547
548  return SANE_STATUS_GOOD;
549}
550
551/** Get the next shared memory buffer passed from the writer process.
552 *
553 * If the channel was not set to non-blocking mode, this function will block
554 * until the data buffer arrives from the writer process.  In non-blocking mode
555 * this function will place NULL in @a *buffer_addr_return and return
556 * SANE_STATUS_GOOD if a buffer is not available immediately.
557 *
558 * After successful completion of this function (return value is
559 * SANE_STATUS_GOOD and @a *buffer_addr_return is not NULL) the reader process
560 * should process the data in the buffer and then call
561 * shm_channel_reader_put_buffer() to release the buffer.
562 *
563 * @param shm_channel Shared memory channel object.
564 * @param buffer_id_return Returned buffer identifier.
565 * @param buffer_addr_return Returned buffer address.
566 * @param buffer_bytes_return Returned number of data bytes in the buffer.
567 *
568 * @return
569 * - SANE_STATUS_GOOD - no error.  If the channel was in non-blocking mode, @a
570 *   *buffer_id_return may be NULL, indicating that no data was available.
571 *   Otherwise, @a *buffer_id_return, @a *buffer_addr_return and @a
572 *   *buffer_bytes return are filled with valid values.
573 * - SANE_STATUS_EOF - the writer process has closed its half of the channel.
574 * - SANE_STATUS_IO_ERROR - an I/O error occurred.
575 */
576SANE_Status
577shm_channel_reader_get_buffer (Shm_Channel * shm_channel,
578			       SANE_Int * buffer_id_return,
579			       SANE_Byte ** buffer_addr_return,
580			       SANE_Int * buffer_bytes_return)
581{
582  SANE_Byte buf_index;
583  int bytes_read;
584
585  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_get_buffer");
586
587  do
588    bytes_read = read (shm_channel->writer_put_pipe[0], &buf_index, 1);
589  while (bytes_read == -1 && errno == EINTR);
590
591  if (bytes_read == 1)
592    {
593      SANE_Int index = buf_index;
594      if (index < shm_channel->buf_count)
595	{
596	  *buffer_id_return = index;
597	  *buffer_addr_return = shm_channel->buffers[index];
598	  *buffer_bytes_return = shm_channel->buffer_bytes[index];
599	  return SANE_STATUS_GOOD;
600	}
601    }
602
603  *buffer_id_return = -1;
604  *buffer_addr_return = NULL;
605  *buffer_bytes_return = 0;
606  if (bytes_read == 0)
607    return SANE_STATUS_EOF;
608  else
609    return SANE_STATUS_IO_ERROR;
610}
611
612/** Release a shared memory buffer received by the reader process.
613 *
614 * This function must be called after shm_channel_reader_get_buffer() to
615 * release the buffer and make it available for transferring the next portion
616 * of data.
617 *
618 * After calling this function the reader process must not access the buffer
619 * contents; any data which may be needed later should be copied into some
620 * other place beforehand.
621 *
622 * @param shm_channel Shared memory channel object.
623 * @param buffer_id Buffer identifier from shm_channel_reader_get_buffer().
624 *
625 * @return
626 * - SANE_STATUS_GOOD - the buffer was successfully released.
627 * - SANE_STATUS_IO_ERROR - the writer process has closed its half of the
628 *   channel, or an unexpected I/O error occurred.
629 */
630SANE_Status
631shm_channel_reader_put_buffer (Shm_Channel * shm_channel, SANE_Int buffer_id)
632{
633  SANE_Byte buf_index;
634  int bytes_written;
635
636  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_put_buffer");
637
638  if (buffer_id < 0 || buffer_id >= shm_channel->buf_count)
639    {
640      DBG (3, "shm_channel_reader_put_buffer: BUG: buffer_id=%d\n",
641	   buffer_id);
642      return SANE_STATUS_INVAL;
643    }
644
645  buf_index = (SANE_Byte) buffer_id;
646  do
647    bytes_written = write (shm_channel->reader_put_pipe[1], &buf_index, 1);
648  while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR));
649
650  if (bytes_written == 1)
651    return SANE_STATUS_GOOD;
652  else
653    return SANE_STATUS_IO_ERROR;
654}
655
656#if 0
657/** Close the reading half of the shared memory channel.
658 *
659 * @param shm_channel Shared memory channel object.
660 */
661SANE_Status
662shm_channel_reader_close (Shm_Channel * shm_channel)
663{
664  SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_close");
665
666  shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]);
667
668  return SANE_STATUS_GOOD;
669}
670#endif
671/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
672