18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Unified handling of special chars. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2001 68c2ecf20Sopenharmony_ci * Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/stddef.h> 118c2ecf20Sopenharmony_ci#include <asm/errno.h> 128c2ecf20Sopenharmony_ci#include <linux/sysrq.h> 138c2ecf20Sopenharmony_ci#include <linux/ctype.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "ctrlchar.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#ifdef CONFIG_MAGIC_SYSRQ 188c2ecf20Sopenharmony_cistatic struct sysrq_work ctrlchar_sysrq; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic void 218c2ecf20Sopenharmony_cictrlchar_handle_sysrq(struct work_struct *work) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct sysrq_work *sysrq = container_of(work, struct sysrq_work, work); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci handle_sysrq(sysrq->key); 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_civoid schedule_sysrq_work(struct sysrq_work *sw) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci INIT_WORK(&sw->work, ctrlchar_handle_sysrq); 318c2ecf20Sopenharmony_ci schedule_work(&sw->work); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci#endif 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/** 378c2ecf20Sopenharmony_ci * Check for special chars at start of input. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * @param buf Console input buffer. 408c2ecf20Sopenharmony_ci * @param len Length of valid data in buffer. 418c2ecf20Sopenharmony_ci * @param tty The tty struct for this console. 428c2ecf20Sopenharmony_ci * @return CTRLCHAR_NONE, if nothing matched, 438c2ecf20Sopenharmony_ci * CTRLCHAR_SYSRQ, if sysrq was encountered 448c2ecf20Sopenharmony_ci * otherwise char to be inserted logically or'ed 458c2ecf20Sopenharmony_ci * with CTRLCHAR_CTRL 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ciunsigned int 488c2ecf20Sopenharmony_cictrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci if ((len < 2) || (len > 3)) 518c2ecf20Sopenharmony_ci return CTRLCHAR_NONE; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* hat is 0xb1 in codepage 037 (US etc.) and thus */ 548c2ecf20Sopenharmony_ci /* converted to 0x5e in ascii ('^') */ 558c2ecf20Sopenharmony_ci if ((buf[0] != '^') && (buf[0] != '\252')) 568c2ecf20Sopenharmony_ci return CTRLCHAR_NONE; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#ifdef CONFIG_MAGIC_SYSRQ 598c2ecf20Sopenharmony_ci /* racy */ 608c2ecf20Sopenharmony_ci if (len == 3 && buf[1] == '-') { 618c2ecf20Sopenharmony_ci ctrlchar_sysrq.key = buf[2]; 628c2ecf20Sopenharmony_ci schedule_sysrq_work(&ctrlchar_sysrq); 638c2ecf20Sopenharmony_ci return CTRLCHAR_SYSRQ; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci#endif 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci if (len != 2) 688c2ecf20Sopenharmony_ci return CTRLCHAR_NONE; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci switch (tolower(buf[1])) { 718c2ecf20Sopenharmony_ci case 'c': 728c2ecf20Sopenharmony_ci return INTR_CHAR(tty) | CTRLCHAR_CTRL; 738c2ecf20Sopenharmony_ci case 'd': 748c2ecf20Sopenharmony_ci return EOF_CHAR(tty) | CTRLCHAR_CTRL; 758c2ecf20Sopenharmony_ci case 'z': 768c2ecf20Sopenharmony_ci return SUSP_CHAR(tty) | CTRLCHAR_CTRL; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci return CTRLCHAR_NONE; 798c2ecf20Sopenharmony_ci} 80