buffers.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/console.h>
  3. #include <linux/types.h>
  4. #include <linux/wait.h>
  5. #include "speakup.h"
  6. #include "spk_priv.h"
  7. #define SYNTH_BUF_SIZE 8192 /* currently 8K bytes */
  8. static u16 synth_buffer[SYNTH_BUF_SIZE]; /* guess what this is for! */
  9. static u16 *buff_in = synth_buffer;
  10. static u16 *buff_out = synth_buffer;
  11. static u16 *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1;
  12. /* These try to throttle applications by stopping the TTYs
  13. * Note: we need to make sure that we will restart them eventually, which is
  14. * usually not possible to do from the notifiers. TODO: it should be possible
  15. * starting from linux 2.6.26.
  16. *
  17. * So we only stop when we know alive == 1 (else we discard the data anyway),
  18. * and the alive synth will eventually call start_ttys from the thread context.
  19. */
  20. void speakup_start_ttys(void)
  21. {
  22. int i;
  23. for (i = 0; i < MAX_NR_CONSOLES; i++) {
  24. if (speakup_console[i] && speakup_console[i]->tty_stopped)
  25. continue;
  26. if (vc_cons[i].d && vc_cons[i].d->port.tty)
  27. start_tty(vc_cons[i].d->port.tty);
  28. }
  29. }
  30. EXPORT_SYMBOL_GPL(speakup_start_ttys);
  31. static void speakup_stop_ttys(void)
  32. {
  33. int i;
  34. for (i = 0; i < MAX_NR_CONSOLES; i++)
  35. if (vc_cons[i].d && vc_cons[i].d->port.tty)
  36. stop_tty(vc_cons[i].d->port.tty);
  37. }
  38. static int synth_buffer_free(void)
  39. {
  40. int chars_free;
  41. if (buff_in >= buff_out)
  42. chars_free = SYNTH_BUF_SIZE - (buff_in - buff_out);
  43. else
  44. chars_free = buff_out - buff_in;
  45. return chars_free;
  46. }
  47. int synth_buffer_empty(void)
  48. {
  49. return (buff_in == buff_out);
  50. }
  51. EXPORT_SYMBOL_GPL(synth_buffer_empty);
  52. void synth_buffer_add(u16 ch)
  53. {
  54. if (!synth->alive) {
  55. /* This makes sure that we won't stop TTYs if there is no synth
  56. * to restart them
  57. */
  58. return;
  59. }
  60. if (synth_buffer_free() <= 100) {
  61. synth_start();
  62. speakup_stop_ttys();
  63. }
  64. if (synth_buffer_free() <= 1)
  65. return;
  66. *buff_in++ = ch;
  67. if (buff_in > buffer_end)
  68. buff_in = synth_buffer;
  69. /* We have written something to the speech synthesis, so we are not
  70. * paused any more.
  71. */
  72. spk_paused = false;
  73. }
  74. u16 synth_buffer_getc(void)
  75. {
  76. u16 ch;
  77. if (buff_out == buff_in)
  78. return 0;
  79. ch = *buff_out++;
  80. if (buff_out > buffer_end)
  81. buff_out = synth_buffer;
  82. return ch;
  83. }
  84. EXPORT_SYMBOL_GPL(synth_buffer_getc);
  85. u16 synth_buffer_peek(void)
  86. {
  87. if (buff_out == buff_in)
  88. return 0;
  89. return *buff_out;
  90. }
  91. EXPORT_SYMBOL_GPL(synth_buffer_peek);
  92. void synth_buffer_skip_nonlatin1(void)
  93. {
  94. while (buff_out != buff_in) {
  95. if (*buff_out < 0x100)
  96. return;
  97. buff_out++;
  98. if (buff_out > buffer_end)
  99. buff_out = synth_buffer;
  100. }
  101. }
  102. EXPORT_SYMBOL_GPL(synth_buffer_skip_nonlatin1);
  103. void synth_buffer_clear(void)
  104. {
  105. buff_in = synth_buffer;
  106. buff_out = synth_buffer;
  107. }
  108. EXPORT_SYMBOL_GPL(synth_buffer_clear);