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