• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
66 struct 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 */
78 union 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  */
115 static void
shm_channel_fd_safe_close(int * fd_var)116 shm_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 
125 static SANE_Status
shm_channel_fd_set_close_on_exec(int fd)126 shm_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
140 static SANE_Status
141 shm_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  */
169 SANE_Status
shm_channel_new(SANE_Int buf_size,SANE_Int buf_count,Shm_Channel ** shm_channel_return)170 shm_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  */
295 SANE_Status
shm_channel_free(Shm_Channel * shm_channel)296 shm_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  */
327 SANE_Status
shm_channel_writer_init(Shm_Channel * shm_channel)328 shm_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  */
358 SANE_Status
shm_channel_writer_get_buffer(Shm_Channel * shm_channel,SANE_Int * buffer_id_return,SANE_Byte ** buffer_addr_return)359 shm_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  */
402 SANE_Status
shm_channel_writer_put_buffer(Shm_Channel * shm_channel,SANE_Int buffer_id,SANE_Int buffer_bytes)403 shm_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  */
435 SANE_Status
shm_channel_writer_close(Shm_Channel * shm_channel)436 shm_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  */
453 SANE_Status
shm_channel_reader_init(Shm_Channel * shm_channel)454 shm_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  */
480 SANE_Status
481 shm_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  */
503 SANE_Status
504 shm_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  */
524 SANE_Status
shm_channel_reader_start(Shm_Channel * shm_channel)525 shm_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  */
576 SANE_Status
shm_channel_reader_get_buffer(Shm_Channel * shm_channel,SANE_Int * buffer_id_return,SANE_Byte ** buffer_addr_return,SANE_Int * buffer_bytes_return)577 shm_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  */
630 SANE_Status
shm_channel_reader_put_buffer(Shm_Channel * shm_channel,SANE_Int buffer_id)631 shm_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  */
661 SANE_Status
662 shm_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