18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/kthread.h> 38c2ecf20Sopenharmony_ci#include <linux/wait.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include "spk_types.h" 68c2ecf20Sopenharmony_ci#include "speakup.h" 78c2ecf20Sopenharmony_ci#include "spk_priv.h" 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ciDECLARE_WAIT_QUEUE_HEAD(speakup_event); 108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(speakup_event); 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ciint speakup_thread(void *data) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci unsigned long flags; 158c2ecf20Sopenharmony_ci int should_break; 168c2ecf20Sopenharmony_ci struct bleep our_sound; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci our_sound.active = 0; 198c2ecf20Sopenharmony_ci our_sound.freq = 0; 208c2ecf20Sopenharmony_ci our_sound.jiffies = 0; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci mutex_lock(&spk_mutex); 238c2ecf20Sopenharmony_ci while (1) { 248c2ecf20Sopenharmony_ci DEFINE_WAIT(wait); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci while (1) { 278c2ecf20Sopenharmony_ci spin_lock_irqsave(&speakup_info.spinlock, flags); 288c2ecf20Sopenharmony_ci our_sound = spk_unprocessed_sound; 298c2ecf20Sopenharmony_ci spk_unprocessed_sound.active = 0; 308c2ecf20Sopenharmony_ci prepare_to_wait(&speakup_event, &wait, 318c2ecf20Sopenharmony_ci TASK_INTERRUPTIBLE); 328c2ecf20Sopenharmony_ci should_break = kthread_should_stop() || 338c2ecf20Sopenharmony_ci our_sound.active || 348c2ecf20Sopenharmony_ci (synth && synth->catch_up && synth->alive && 358c2ecf20Sopenharmony_ci (speakup_info.flushing || 368c2ecf20Sopenharmony_ci !synth_buffer_empty())); 378c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&speakup_info.spinlock, flags); 388c2ecf20Sopenharmony_ci if (should_break) 398c2ecf20Sopenharmony_ci break; 408c2ecf20Sopenharmony_ci mutex_unlock(&spk_mutex); 418c2ecf20Sopenharmony_ci schedule(); 428c2ecf20Sopenharmony_ci mutex_lock(&spk_mutex); 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci finish_wait(&speakup_event, &wait); 458c2ecf20Sopenharmony_ci if (kthread_should_stop()) 468c2ecf20Sopenharmony_ci break; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (our_sound.active) 498c2ecf20Sopenharmony_ci kd_mksound(our_sound.freq, our_sound.jiffies); 508c2ecf20Sopenharmony_ci if (synth && synth->catch_up && synth->alive) { 518c2ecf20Sopenharmony_ci /* 528c2ecf20Sopenharmony_ci * It is up to the callee to take the lock, so that it 538c2ecf20Sopenharmony_ci * can sleep whenever it likes 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci synth->catch_up(synth); 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci speakup_start_ttys(); 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci mutex_unlock(&spk_mutex); 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci} 63