1c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs/* 2c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * This is the DECtalk PC speakup driver 3c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 4c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Some constants from DEC's DOS driver: 5c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Copyright (c) by Digital Equipment Corp. 6c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 7c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 386BSD DECtalk PC driver: 8c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Copyright (c) 1996 Brian Buhrow <buhrow@lothlorien.nfbcal.org> 9c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 10c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Linux DECtalk PC driver: 11c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Copyright (c) 1997 Nicolas Pitre <nico@cam.org> 12c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 13c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * speakup DECtalk PC Internal driver: 14c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Copyright (c) 2003 David Borowski <david575@golden.net> 15c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 16c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * All rights reserved. 17c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 18c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * This program is free software; you can redistribute it and/or modify 19c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * it under the terms of the GNU General Public License as published by 20c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * the Free Software Foundation; either version 2 of the License, or 21c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * (at your option) any later version. 22c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 23c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * This program is distributed in the hope that it will be useful, 24c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * but WITHOUT ANY WARRANTY; without even the implied warranty of 25c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * GNU General Public License for more details. 27c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * 28c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * You should have received a copy of the GNU General Public License 29c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * along with this program; if not, write to the Free Software 30c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 31c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs */ 32c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#include <linux/jiffies.h> 33c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#include <linux/sched.h> 34c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#include <linux/timer.h> 35c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#include <linux/kthread.h> 36c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 37c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#include "spk_priv.h" 38c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#include "speakup.h" 39c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 40c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODULE_init 0x0dec /* module in boot code */ 41c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODULE_self_test 0x8800 /* module in self-test */ 42c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODULE_reset 0xffff /* reinit the whole module */ 43c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 44c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODE_mask 0xf000 /* mode bits in high nibble */ 45c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODE_null 0x0000 46c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODE_test 0x2000 /* in testing mode */ 47c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODE_status 0x8000 48c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_int 0x0001 /* running in interrupt mode */ 49c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_tr_char 0x0002 /* character data to transmit */ 50c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_rr_char 0x0004 /* ready to receive char data */ 51c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_cmd_ready 0x0008 /* ready to accept commands */ 52c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_dma_ready 0x0010 /* dma command ready */ 53c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_digitized 0x0020 /* spc in digitized mode */ 54c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_new_index 0x0040 /* new last index ready */ 55c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_new_status 0x0080 /* new status posted */ 56c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_dma_state 0x0100 /* dma state toggle */ 57c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_index_valid 0x0200 /* indexs are valid */ 58c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_flushing 0x0400 /* flush in progress */ 59c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define STAT_self_test 0x0800 /* module in self test */ 60c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODE_ready 0xc000 /* module ready for next phase */ 61c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define READY_boot 0x0000 62c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define READY_kernel 0x0001 63c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define MODE_error 0xf000 64c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 65c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_mask 0xf000 /* mask for command nibble */ 66c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_null 0x0000 /* post status */ 67c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_control 0x1000 /* hard control command */ 68c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_mask 0x0F00 /* mask off control nibble */ 6983414d528d2f97d6574c14afb892879c11bbcc7cJustin P. Mattock#define CTRL_data 0x00FF /* mask to get data byte */ 70c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_null 0x0000 /* null control */ 71c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_vol_up 0x0100 /* increase volume */ 72c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_vol_down 0x0200 /* decrease volume */ 73c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_vol_set 0x0300 /* set volume */ 74c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_pause 0x0400 /* pause spc */ 75c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_resume 0x0500 /* resume spc clock */ 76c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_resume_spc 0x0001 /* resume spc soft pause */ 77c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_flush 0x0600 /* flush all buffers */ 78c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_int_enable 0x0700 /* enable status change ints */ 79c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_buff_free 0x0800 /* buffer remain count */ 80c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_buff_used 0x0900 /* buffer in use */ 81c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_speech 0x0a00 /* immediate speech change */ 82c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_SP_voice 0x0001 /* voice change */ 83c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_SP_rate 0x0002 /* rate change */ 84c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_SP_comma 0x0003 /* comma pause change */ 85c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_SP_period 0x0004 /* period pause change */ 86c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_SP_rate_delta 0x0005 /* delta rate change */ 87c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_SP_get_param 0x0006 /* return the desired parameter */ 88c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_last_index 0x0b00 /* get last index spoken */ 89c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_io_priority 0x0c00 /* change i/o priority */ 90c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_free_mem 0x0d00 /* get free paragraphs on module */ 91c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CTRL_get_lang 0x0e00 /* return bit mask of loaded 92c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * languages */ 93c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_test 0x2000 /* self-test request */ 94c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_mask 0x0F00 /* isolate test field */ 95c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_null 0x0000 /* no test requested */ 96c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_isa_int 0x0100 /* assert isa irq */ 97c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_echo 0x0200 /* make data in == data out */ 98c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_seg 0x0300 /* set peek/poke segment */ 99c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_off 0x0400 /* set peek/poke offset */ 100c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_peek 0x0500 /* data out == *peek */ 101c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_poke 0x0600 /* *peek == data in */ 102c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define TEST_sub_code 0x00FF /* user defined test sub codes */ 103c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_id 0x3000 /* return software id */ 104c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define ID_null 0x0000 /* null id */ 105c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define ID_kernel 0x0100 /* kernel code executing */ 106c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define ID_boot 0x0200 /* boot code executing */ 107c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_dma 0x4000 /* force a dma start */ 108c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_reset 0x5000 /* reset module status */ 109c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_sync 0x6000 /* kernel sync command */ 110c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_char_in 0x7000 /* single character send */ 111c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_char_out 0x8000 /* single character get */ 112c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CHAR_count_1 0x0100 /* one char in cmd_low */ 113c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CHAR_count_2 0x0200 /* the second in data_low */ 114c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CHAR_count_3 0x0300 /* the third in data_high */ 115c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_spc_mode 0x9000 /* change spc mode */ 116c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_spc_to_text 0x0100 /* set to text mode */ 117c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_spc_to_digit 0x0200 /* set to digital mode */ 118c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_spc_rate 0x0400 /* change spc data rate */ 119c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define CMD_error 0xf000 /* severe error */ 120c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 121c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsenum { PRIMARY_DIC = 0, USER_DIC, COMMAND_DIC, ABBREV_DIC }; 122c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 123c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DMA_single_in 0x01 124c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DMA_single_out 0x02 125c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DMA_buff_in 0x03 126c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DMA_buff_out 0x04 127c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DMA_control 0x05 128c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DT_MEM_ALLOC 0x03 129c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DT_SET_DIC 0x04 130c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DT_START_TASK 0x05 131c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DT_LOAD_MEM 0x06 132c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DT_READ_MEM 0x07 133c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DT_DIGITAL_IN 0x08 134c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DMA_sync 0x06 135c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DMA_sync_char 0x07 136c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 137c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define DRV_VERSION "2.12" 138c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define PROCSPEECH 0x0b 139c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs#define SYNTH_IO_EXTENT 8 140c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 141c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int synth_probe(struct spk_synth *synth); 142c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void dtpc_release(void); 143c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic const char *synth_immediate(struct spk_synth *synth, const char *buf); 144c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void do_catch_up(struct spk_synth *synth); 145c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void synth_flush(struct spk_synth *synth); 146c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 147c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int synth_portlist[] = { 0x340, 0x350, 0x240, 0x250, 0 }; 148c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int in_escape, is_flushing; 149c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int dt_stat, dma_state; 150c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 151c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct var_t vars[] = { 152227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { CAPS_START, .u.s = {"[:dv ap 200]" } }, 153227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { CAPS_STOP, .u.s = {"[:dv ap 100]" } }, 154227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { RATE, .u.n = {"[:ra %d]", 9, 0, 18, 150, 25, NULL } }, 155227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { PITCH, .u.n = {"[:dv ap %d]", 80, 0, 100, 20, 0, NULL } }, 156227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { VOL, .u.n = {"[:vo se %d]", 5, 0, 9, 5, 10, NULL } }, 157227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { PUNCT, .u.n = {"[:pu %c]", 0, 0, 2, 0, 0, "nsa" } }, 158227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { VOICE, .u.n = {"[:n%c]", 0, 0, 9, 0, 0, "phfdburwkv" } }, 159227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon { DIRECT, .u.n = {NULL, 0, 0, 1, 0, 0, NULL } }, 160c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs V_LAST_VAR 161c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs}; 162c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 163c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs/* 164c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * These attributes will appear in /sys/accessibility/speakup/decpc. 165c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs */ 166c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute caps_start_attribute = 167d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(caps_start, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 168c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute caps_stop_attribute = 169d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(caps_stop, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 170c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute pitch_attribute = 171d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(pitch, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 172c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute punct_attribute = 173d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(punct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 174c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute rate_attribute = 175d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(rate, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 176c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute voice_attribute = 177d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(voice, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 178c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute vol_attribute = 179d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(vol, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 180c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 181c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute delay_time_attribute = 18222c9bcad859d5c969289b3b37084a96c621f8f2cRusty Russell __ATTR(delay_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 183c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute direct_attribute = 184d901aaa723a7ea4601b0984534dde70adc81a38cRusty Russell __ATTR(direct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 185c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute full_time_attribute = 18622c9bcad859d5c969289b3b37084a96c621f8f2cRusty Russell __ATTR(full_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 187c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute jiffy_delta_attribute = 18822c9bcad859d5c969289b3b37084a96c621f8f2cRusty Russell __ATTR(jiffy_delta, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 189c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct kobj_attribute trigger_time_attribute = 19022c9bcad859d5c969289b3b37084a96c621f8f2cRusty Russell __ATTR(trigger_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); 191c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 192c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs/* 193c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * Create a group of attributes so that we can create and destroy them all 194c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs * at once. 195c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs */ 196c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct attribute *synth_attrs[] = { 197c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &caps_start_attribute.attr, 198c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &caps_stop_attribute.attr, 199c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &pitch_attribute.attr, 200c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &punct_attribute.attr, 201c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &rate_attribute.attr, 202c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &voice_attribute.attr, 203c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &vol_attribute.attr, 204c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &delay_time_attribute.attr, 205c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &direct_attribute.attr, 206c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &full_time_attribute.attr, 207c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &jiffy_delta_attribute.attr, 208c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs &trigger_time_attribute.attr, 209c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs NULL, /* need to NULL terminate the list of attributes */ 210c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs}; 211c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 212c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic struct spk_synth synth_dec_pc = { 213c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .name = "decpc", 214c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .version = DRV_VERSION, 215c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .long_name = "Dectalk PC", 216c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .init = "[:pe -380]", 217c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .procspeech = PROCSPEECH, 218c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .delay = 500, 219c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .trigger = 50, 220c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .jiffies = 50, 221c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .full = 1000, 222c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .flags = SF_DEC, 223c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .startup = SYNTH_START, 224c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .checkval = SYNTH_CHECK, 225c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .vars = vars, 226c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .probe = synth_probe, 227c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .release = dtpc_release, 228c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .synth_immediate = synth_immediate, 229c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .catch_up = do_catch_up, 230c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .flush = synth_flush, 231c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .is_alive = spk_synth_is_alive_nop, 232c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .synth_adjust = NULL, 233c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .read_buff_add = NULL, 234c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .get_index = NULL, 235c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .indexing = { 236c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .command = NULL, 237c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .lowindex = 0, 238c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .highindex = 0, 239c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .currindex = 0, 240c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs }, 241c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .attributes = { 242c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .attrs = synth_attrs, 243c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs .name = "decpc", 244c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs }, 245c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs}; 246c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 247c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int dt_getstatus(void) 248c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 249c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_stat = inb_p(speakup_info.port_tts) | 250c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs (inb_p(speakup_info.port_tts + 1) << 8); 251c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return dt_stat; 252c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 253c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 254c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void dt_sendcmd(u_int cmd) 255c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 256c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(cmd & 0xFF, speakup_info.port_tts); 257c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p((cmd >> 8) & 0xFF, speakup_info.port_tts+1); 258c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 259c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 260c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int dt_waitbit(int bit) 261c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 262c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int timeout = 100; 2638e69a8110686572a4b88d006faa8c3c759c4c261Domagoj Trsan 264c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs while (--timeout > 0) { 265c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if ((dt_getstatus() & bit) == bit) 266c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 1; 267c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs udelay(50); 268c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 269c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 0; 270c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 271c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 272c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int dt_wait_dma(void) 273c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 274c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int timeout = 100, state = dma_state; 2758e69a8110686572a4b88d006faa8c3c759c4c261Domagoj Trsan 276c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!dt_waitbit(STAT_dma_ready)) 277c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 0; 278c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs while (--timeout > 0) { 279c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if ((dt_getstatus()&STAT_dma_state) == state) 280c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 1; 281c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs udelay(50); 282c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 283c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dma_state = dt_getstatus() & STAT_dma_state; 284c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 1; 285c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 286c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 287c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int dt_ctrl(u_int cmd) 288c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 289c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int timeout = 10; 2908e69a8110686572a4b88d006faa8c3c759c4c261Domagoj Trsan 291c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!dt_waitbit(STAT_cmd_ready)) 292c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return -1; 293c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(0, speakup_info.port_tts+2); 294c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(0, speakup_info.port_tts+3); 295c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_getstatus(); 296c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_sendcmd(CMD_control|cmd); 297c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(0, speakup_info.port_tts+6); 298c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs while (dt_getstatus() & STAT_cmd_ready) { 299c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs udelay(20); 300c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (--timeout == 0) 301c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs break; 302c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 303c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_sendcmd(CMD_null); 304c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 0; 305c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 306c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 307c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void synth_flush(struct spk_synth *synth) 308c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 309c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int timeout = 10; 3108e69a8110686572a4b88d006faa8c3c759c4c261Domagoj Trsan 311c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (is_flushing) 312c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return; 313c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs is_flushing = 4; 314c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs in_escape = 0; 315c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs while (dt_ctrl(CTRL_flush)) { 316c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (--timeout == 0) 317c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs break; 318c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsudelay(50); 319c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 320c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs for (timeout = 0; timeout < 10; timeout++) { 321c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (dt_waitbit(STAT_dma_ready)) 322c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs break; 323c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsudelay(50); 324c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 325c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(DMA_sync, speakup_info.port_tts+4); 326c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(0, speakup_info.port_tts+4); 327c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs udelay(100); 328c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs for (timeout = 0; timeout < 10; timeout++) { 329c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!(dt_getstatus() & STAT_flushing)) 330c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs break; 331c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsudelay(50); 332c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 333c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dma_state = dt_getstatus() & STAT_dma_state; 334c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dma_state ^= STAT_dma_state; 335c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs is_flushing = 0; 336c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 337c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 338c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int dt_sendchar(char ch) 339c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 340c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!dt_wait_dma()) 341c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return -1; 342c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!(dt_stat & STAT_rr_char)) 343c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return -2; 344c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(DMA_single_in, speakup_info.port_tts+4); 345c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs outb_p(ch, speakup_info.port_tts+4); 346c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dma_state ^= STAT_dma_state; 347c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 0; 348c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 349c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 350c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int testkernel(void) 351c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 352c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int status = 0; 3538e69a8110686572a4b88d006faa8c3c759c4c261Domagoj Trsan 354c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (dt_getstatus() == 0xffff) { 355c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs status = -1; 356c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs goto oops; 357c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 358c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_sendcmd(CMD_sync); 359c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!dt_waitbit(STAT_cmd_ready)) 360c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs status = -2; 361c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs else if (dt_stat&0x8000) 362c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 0; 363c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs else if (dt_stat == 0x0dec) 364c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs pr_warn("dec_pc at 0x%x, software not loaded\n", 365c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs speakup_info.port_tts); 366c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs status = -3; 367c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsoops: synth_release_region(speakup_info.port_tts, SYNTH_IO_EXTENT); 368c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs speakup_info.port_tts = 0; 369c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return status; 370c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 371c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 372c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void do_catch_up(struct spk_synth *synth) 373c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 374c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs u_char ch; 375227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon static u_char last; 376c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs unsigned long flags; 377c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs unsigned long jiff_max; 378c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs struct var_t *jiffy_delta; 379c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs struct var_t *delay_time; 380c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int jiffy_delta_val; 381c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int delay_time_val; 382c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 383ca2beaf84d9678c12b17d92623f0e90829d6ca13Samuel Thibault jiffy_delta = spk_get_var(JIFFY); 384ca2beaf84d9678c12b17d92623f0e90829d6ca13Samuel Thibault delay_time = spk_get_var(DELAY); 3854d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_lock_irqsave(&speakup_info.spinlock, flags); 386c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs jiffy_delta_val = jiffy_delta->u.n.value; 3874d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_unlock_irqrestore(&speakup_info.spinlock, flags); 388c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs jiff_max = jiffies + jiffy_delta_val; 389c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 390c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs while (!kthread_should_stop()) { 3914d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_lock_irqsave(&speakup_info.spinlock, flags); 392c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (speakup_info.flushing) { 393c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs speakup_info.flushing = 0; 3944d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_unlock_irqrestore(&speakup_info.spinlock, flags); 395c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs synth->flush(synth); 396c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs continue; 397c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 398c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (synth_buffer_empty()) { 3994d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_unlock_irqrestore(&speakup_info.spinlock, flags); 400c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs break; 401c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 402c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs ch = synth_buffer_peek(); 403c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs set_current_state(TASK_INTERRUPTIBLE); 404c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs delay_time_val = delay_time->u.n.value; 4054d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_unlock_irqrestore(&speakup_info.spinlock, flags); 406c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (ch == '\n') 407c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs ch = 0x0D; 408c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (dt_sendchar(ch)) { 409c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs schedule_timeout(msecs_to_jiffies(delay_time_val)); 410c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs continue; 411c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 412c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs set_current_state(TASK_RUNNING); 4134d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_lock_irqsave(&speakup_info.spinlock, flags); 414c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs synth_buffer_getc(); 4154d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_unlock_irqrestore(&speakup_info.spinlock, flags); 416c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (ch == '[') 417c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs in_escape = 1; 418c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs else if (ch == ']') 419c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs in_escape = 0; 420c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs else if (ch <= SPACE) { 421c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!in_escape && strchr(",.!?;:", last)) 422c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_sendchar(PROCSPEECH); 42389021ecc8364e727a24b0683a74515c8ddf308dbTapasweni Pathak if (time_after_eq(jiffies, jiff_max)) { 424c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!in_escape) 425c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_sendchar(PROCSPEECH); 4264d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_lock_irqsave(&speakup_info.spinlock, flags); 427c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs jiffy_delta_val = jiffy_delta->u.n.value; 428c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs delay_time_val = delay_time->u.n.value; 4294d888b292a6a6e249f3960b3f9673e178c87aacaWilliam Hubbs spin_unlock_irqrestore(&speakup_info.spinlock, flags); 430227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon schedule_timeout(msecs_to_jiffies 431227e18d6b62550dafb822de2f3d673e3791a13e0Christopher Brannon (delay_time_val)); 432c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs jiff_max = jiffies + jiffy_delta_val; 433c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 434c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 435c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs last = ch; 436c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs ch = 0; 437c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 438c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (!in_escape) 439c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs dt_sendchar(PROCSPEECH); 440c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 441c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 442c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic const char *synth_immediate(struct spk_synth *synth, const char *buf) 443c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 444c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs u_char ch; 4458e69a8110686572a4b88d006faa8c3c759c4c261Domagoj Trsan 446c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs while ((ch = *buf)) { 447c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (ch == '\n') 448c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs ch = PROCSPEECH; 449c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (dt_sendchar(ch)) 450c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return buf; 451c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs buf++; 452c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 4536eb178cebb5b380377033a972a9803adb5a58edeSachin Kamat return NULL; 454c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 455c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 456c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int synth_probe(struct spk_synth *synth) 457c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 458c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs int i = 0, failed = 0; 4598e69a8110686572a4b88d006faa8c3c759c4c261Domagoj Trsan 460c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs pr_info("Probing for %s.\n", synth->long_name); 461c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs for (i = 0; synth_portlist[i]; i++) { 462c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (synth_request_region(synth_portlist[i], SYNTH_IO_EXTENT)) { 463c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs pr_warn("request_region: failed with 0x%x, %d\n", 464c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs synth_portlist[i], SYNTH_IO_EXTENT); 465c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs continue; 466c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 467c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs speakup_info.port_tts = synth_portlist[i]; 468c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs failed = testkernel(); 469c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (failed == 0) 470c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs break; 471c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 472c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (failed) { 473c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs pr_info("%s: not found\n", synth->long_name); 474c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return -ENODEV; 475c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs } 476c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs pr_info("%s: %03x-%03x, Driver Version %s,\n", synth->long_name, 477c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs speakup_info.port_tts, speakup_info.port_tts + 7, 478c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs synth->version); 479c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs synth->alive = 1; 480c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return 0; 481c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 482c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 483c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void dtpc_release(void) 484c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 485c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs if (speakup_info.port_tts) 486c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs synth_release_region(speakup_info.port_tts, SYNTH_IO_EXTENT); 487c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs speakup_info.port_tts = 0; 488c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 489c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 490c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsmodule_param_named(start, synth_dec_pc.startup, short, S_IRUGO); 491c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 492c6e3fd22cd538365bfeb82997d5b89562e077d42William HubbsMODULE_PARM_DESC(start, "Start the synthesizer once it is loaded."); 493c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 494c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic int __init decpc_init(void) 495c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 496c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs return synth_add(&synth_dec_pc); 497c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 498c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 499c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsstatic void __exit decpc_exit(void) 500c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs{ 501c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs synth_remove(&synth_dec_pc); 502c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs} 503c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 504c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsmodule_init(decpc_init); 505c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbsmodule_exit(decpc_exit); 506c6e3fd22cd538365bfeb82997d5b89562e077d42William HubbsMODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>"); 507c6e3fd22cd538365bfeb82997d5b89562e077d42William HubbsMODULE_AUTHOR("David Borowski"); 508c6e3fd22cd538365bfeb82997d5b89562e077d42William HubbsMODULE_DESCRIPTION("Speakup support for DECtalk PC synthesizers"); 509c6e3fd22cd538365bfeb82997d5b89562e077d42William HubbsMODULE_LICENSE("GPL"); 510c6e3fd22cd538365bfeb82997d5b89562e077d42William HubbsMODULE_VERSION(DRV_VERSION); 511c6e3fd22cd538365bfeb82997d5b89562e077d42William Hubbs 512