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