Пример #1
0
static ssize_t dtlk_read(struct file *file, char __user *buf,
			 size_t count, loff_t * ppos)
{
	unsigned int minor = iminor(file->f_path.dentry->d_inode);
	char ch;
	int i = 0, retries;

	TRACE_TEXT("(dtlk_read");
	/*  printk("DoubleTalk PC - dtlk_read()\n"); */

	if (minor != DTLK_MINOR || !dtlk_has_indexing)
		return -EINVAL;

	for (retries = 0; retries < loops_per_jiffy; retries++) {
		while (i < count && dtlk_readable()) {
			ch = dtlk_read_lpc();
			/*        printk("dtlk_read() reads 0x%02x\n", ch); */
			if (put_user(ch, buf++))
				return -EFAULT;
			i++;
		}
		if (i)
			return i;
		if (file->f_flags & O_NONBLOCK)
			break;
		msleep_interruptible(100);
	}
	if (retries == loops_per_jiffy)
		printk(KERN_ERR "dtlk_read times out\n");
	TRACE_RET;
	return -EAGAIN;
}
Пример #2
0
static char dtlk_read_tts(void)
{
	int portval, retries = 0;
	char ch;
	TRACE_TEXT("(dtlk_read_tts");

	/* verify DT is ready, read char, wait for ACK */
	do {
		portval = inb_p(dtlk_port_tts);
	} while ((portval & TTS_READABLE) == 0 &&
		 retries++ < DTLK_MAX_RETRIES);
	if (retries > DTLK_MAX_RETRIES)
		printk(KERN_ERR "dtlk_read_tts() timeout\n");

	ch = inb_p(dtlk_port_tts);	/* input from TTS port */
	ch &= 0x7f;
	outb_p(ch, dtlk_port_tts);

	retries = 0;
	do {
		portval = inb_p(dtlk_port_tts);
	} while ((portval & TTS_READABLE) != 0 &&
		 retries++ < DTLK_MAX_RETRIES);
	if (retries > DTLK_MAX_RETRIES)
		printk(KERN_ERR "dtlk_read_tts() timeout\n");

	TRACE_RET;
	return ch;
}
Пример #3
0
static long dtlk_ioctl(struct file *file,
		       unsigned int cmd,
		       unsigned long arg)
{
	char __user *argp = (char __user *)arg;
	struct dtlk_settings *sp;
	char portval;
	TRACE_TEXT(" dtlk_ioctl");

	switch (cmd) {

	case DTLK_INTERROGATE:
		mutex_lock(&dtlk_mutex);
		sp = dtlk_interrogate();
		mutex_unlock(&dtlk_mutex);
		if (copy_to_user(argp, sp, sizeof(struct dtlk_settings)))
			return -EINVAL;
		return 0;

	case DTLK_STATUS:
		portval = inb_p(dtlk_port_tts);
		return put_user(portval, argp);

	default:
		return -EINVAL;
	}
}
Пример #4
0
static unsigned int dtlk_poll(struct file *file, poll_table * wait)
{
	int mask = 0;
	unsigned long expires;

	TRACE_TEXT(" dtlk_poll");
	/*
	   static long int j;
	   printk(".");
	   printk("<%ld>", jiffies-j);
	   j=jiffies;
	 */
	poll_wait(file, &dtlk_process_list, wait);

	if (dtlk_has_indexing && dtlk_readable()) {
	        del_timer(&dtlk_timer);
		mask = POLLIN | POLLRDNORM;
	}
	if (dtlk_writeable()) {
	        del_timer(&dtlk_timer);
		mask |= POLLOUT | POLLWRNORM;
	}
	/* there are no exception conditions */

	/* There won't be any interrupts, so we set a timer instead. */
	expires = jiffies + 3*HZ / 100;
	mod_timer(&dtlk_timer, expires);

	return mask;
}
Пример #5
0
static int dtlk_ioctl(struct inode *inode,
                      struct file *file,
                      unsigned int cmd,
                      unsigned long arg)
{
    struct dtlk_settings *sp;
    char portval;
    TRACE_TEXT(" dtlk_ioctl");

    switch (cmd) {

    case DTLK_INTERROGATE:
        sp = dtlk_interrogate();
        if (copy_to_user((char *) arg, (char *) sp,
                         sizeof(struct dtlk_settings)))
            return -EINVAL;
        return 0;

    case DTLK_STATUS:
        portval = inb_p(dtlk_port_tts);
        return put_user(portval, (char *) arg);

    default:
        return -EINVAL;
    }
}
Пример #6
0
/* write n bytes to tts port */
static char dtlk_write_bytes(const char *buf, int n)
{
	char val = 0;
	/*  printk("dtlk_write_bytes(\"%-*s\", %d)\n", n, buf, n); */
	TRACE_TEXT("(dtlk_write_bytes");
	while (n-- > 0)
		val = dtlk_write_tts(*buf++);
	TRACE_RET;
	return val;
}
Пример #7
0
/* interrogate the DoubleTalk PC and return its settings */
static struct dtlk_settings *dtlk_interrogate(void)
{
	unsigned char *t;
	static char buf[sizeof(struct dtlk_settings) + 1];
	int total, i;
	static struct dtlk_settings status;
	TRACE_TEXT("(dtlk_interrogate");
	dtlk_write_bytes("\030\001?", 3);
	for (total = 0, i = 0; i < 50; i++) {
		buf[total] = dtlk_read_tts();
		if (total > 2 && buf[total] == 0x7f)
			break;
		if (total < sizeof(struct dtlk_settings))
			total++;
	}
	/*
	   if (i==50) printk("interrogate() read overrun\n");
	   for (i=0; i<sizeof(buf); i++)
	   printk(" %02x", buf[i]);
	   printk("\n");
	 */
	t = buf;
	status.serial_number = t[0] + t[1] * 256; /* serial number is
						     little endian */
	t += 2;

	i = 0;
	while (*t != '\r') {
		status.rom_version[i] = *t;
		if (i < sizeof(status.rom_version) - 1)
			i++;
		t++;
	}
	status.rom_version[i] = 0;
	t++;

	status.mode = *t++;
	status.punc_level = *t++;
	status.formant_freq = *t++;
	status.pitch = *t++;
	status.speed = *t++;
	status.volume = *t++;
	status.tone = *t++;
	status.expression = *t++;
	status.ext_dict_loaded = *t++;
	status.ext_dict_status = *t++;
	status.free_ram = *t++;
	status.articulation = *t++;
	status.reverb = *t++;
	status.eob = *t++;
	status.has_indexing = dtlk_has_indexing;
	TRACE_RET;
	return &status;
}
Пример #8
0
static int dtlk_open(struct inode *inode, struct file *file)
{
    TRACE_TEXT("(dtlk_open");

    switch (MINOR(inode->i_rdev)) {
    case DTLK_MINOR:
        if (dtlk_busy)
            return -EBUSY;
        return 0;

    default:
        return -ENXIO;
    }
}
Пример #9
0
/* Note that nobody ever sets dtlk_busy... */
static int dtlk_open(struct inode *inode, struct file *file)
{
	TRACE_TEXT("(dtlk_open");

	nonseekable_open(inode, file);
	switch (iminor(inode)) {
	case DTLK_MINOR:
		if (dtlk_busy)
			return -EBUSY;
		return nonseekable_open(inode, file);

	default:
		return -ENXIO;
	}
}
Пример #10
0
static int dtlk_release(struct inode *inode, struct file *file)
{
	TRACE_TEXT("(dtlk_release");

	switch (iminor(inode)) {
	case DTLK_MINOR:
		break;

	default:
		break;
	}
	TRACE_RET;
	
	del_timer_sync(&dtlk_timer);

	return 0;
}
Пример #11
0
static int dtlk_release(struct inode *inode, struct file *file)
{
    TRACE_TEXT("(dtlk_release");

    switch (MINOR(inode->i_rdev)) {
    case DTLK_MINOR:
        break;

    default:
        break;
    }
    TRACE_RET;

    lock_kernel();
    del_timer(&dtlk_timer);
    unlock_kernel();

    return 0;
}
Пример #12
0
static char dtlk_read_lpc(void)
{
	int retries = 0;
	char ch;
	TRACE_TEXT("(dtlk_read_lpc");

	/* no need to test -- this is only called when the port is readable */

	ch = inb_p(dtlk_port_lpc);	/* input from LPC port */

	outb_p(0xff, dtlk_port_lpc);

	/* acknowledging a read takes 3-4
	   usec.  Here, we wait up to 20 usec
	   for the acknowledgement */
	retries = (loops_per_jiffy * 20) / (1000000/HZ);
	while (inb_p(dtlk_port_lpc) != 0x7f && --retries > 0);
	if (retries == 0)
		printk(KERN_ERR "dtlk_read_lpc() timeout\n");

	TRACE_RET;
	return ch;
}
Пример #13
0
static ssize_t dtlk_read(struct file *file, char __user *buf,
			 size_t count, loff_t * ppos)
{
	unsigned int minor = iminor(file->f_path.dentry->d_inode);
	char ch;
	int i = 0, retries;

	TRACE_TEXT("(dtlk_read");
#ifdef CONFIG_DEBUG_PRINTK
	/*  printk("DoubleTalk PC - dtlk_read()\n"); */
#else
	/*  ;
#endif

	if (minor != DTLK_MINOR || !dtlk_has_indexing)
		return -EINVAL;

	for (retries = 0; retries < loops_per_jiffy; retries++) {
		while (i < count && dtlk_readable()) {
			ch = dtlk_read_lpc();
#ifdef CONFIG_DEBUG_PRINTK
			/*        printk("dtlk_read() reads 0x%02x\n", ch); */
#else
			/*        ;
#endif
			if (put_user(ch, buf++))
				return -EFAULT;
			i++;
		}
		if (i)
			return i;
		if (file->f_flags & O_NONBLOCK)
			break;
		msleep_interruptible(100);
	}
	if (retries == loops_per_jiffy)
		printk(KERN_ERR "dtlk_read times out\n");
	TRACE_RET;
	return -EAGAIN;
}

static ssize_t dtlk_write(struct file *file, const char __user *buf,
			  size_t count, loff_t * ppos)
{
	int i = 0, retries = 0, ch;

	TRACE_TEXT("(dtlk_write");
#ifdef TRACING
#ifdef CONFIG_DEBUG_PRINTK
	printk(" \"");
#else
	;
#endif
	{
		int i, ch;
		for (i = 0; i < count; i++) {
			if (get_user(ch, buf + i))
				return -EFAULT;
			if (' ' <= ch && ch <= '~')
#ifdef CONFIG_DEBUG_PRINTK
				printk("%c", ch);
#else
				;
#endif
			else
#ifdef CONFIG_DEBUG_PRINTK
				printk("\\%03o", ch);
#else
				;
#endif
		}
#ifdef CONFIG_DEBUG_PRINTK
		printk("\"");
#else
		;
#endif
	}
#endif

	if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR)
		return -EINVAL;

	while (1) {
		while (i < count && !get_user(ch, buf) &&
		       (ch == DTLK_CLEAR || dtlk_writeable())) {
			dtlk_write_tts(ch);
			buf++;
			i++;
			if (i % 5 == 0)
				/* We yield our time until scheduled
				   again.  This reduces the transfer
				   rate to 500 bytes/sec, but that's
				   still enough to keep up with the
				   speech synthesizer. */
				msleep_interruptible(1);
			else {
				/* the RDY bit goes zero 2-3 usec
				   after writing, and goes 1 again
				   180-190 usec later.  Here, we wait
				   up to 250 usec for the RDY bit to
				   go nonzero. */
				for (retries = 0;
Пример #14
0
static void dtlk_timer_tick(unsigned long data)
{
	TRACE_TEXT(" dtlk_timer_tick");
	wake_up_interruptible(&dtlk_process_list);
}
Пример #15
0
static ssize_t dtlk_write(struct file *file, const char __user *buf,
			  size_t count, loff_t * ppos)
{
	int i = 0, retries = 0, ch;

	TRACE_TEXT("(dtlk_write");
#ifdef TRACING
	printk(" \"");
	{
		int i, ch;
		for (i = 0; i < count; i++) {
			if (get_user(ch, buf + i))
				return -EFAULT;
			if (' ' <= ch && ch <= '~')
				printk("%c", ch);
			else
				printk("\\%03o", ch);
		}
		printk("\"");
	}
#endif

	if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR)
		return -EINVAL;

	while (1) {
		while (i < count && !get_user(ch, buf) &&
		       (ch == DTLK_CLEAR || dtlk_writeable())) {
			dtlk_write_tts(ch);
			buf++;
			i++;
			if (i % 5 == 0)
				/* We yield our time until scheduled
				   again.  This reduces the transfer
				   rate to 500 bytes/sec, but that's
				   still enough to keep up with the
				   speech synthesizer. */
				msleep_interruptible(1);
			else {
				/* the RDY bit goes zero 2-3 usec
				   after writing, and goes 1 again
				   180-190 usec later.  Here, we wait
				   up to 250 usec for the RDY bit to
				   go nonzero. */
				for (retries = 0;
				     retries < loops_per_jiffy / (4000/HZ);
				     retries++)
					if (inb_p(dtlk_port_tts) &
					    TTS_WRITABLE)
						break;
			}
			retries = 0;
		}
		if (i == count)
			return i;
		if (file->f_flags & O_NONBLOCK)
			break;

		msleep_interruptible(1);

		if (++retries > 10 * HZ) { /* wait no more than 10 sec
					      from last write */
			printk("dtlk: write timeout.  "
			       "inb_p(dtlk_port_tts) = 0x%02x\n",
			       inb_p(dtlk_port_tts));
			TRACE_RET;
			return -EBUSY;
		}
	}
	TRACE_RET;
	return -EAGAIN;
}
Пример #16
0
static void dtlk_timer_tick(struct timer_list *unused)
{
	TRACE_TEXT(" dtlk_timer_tick");
	wake_up_interruptible(&dtlk_process_list);
}