File: linux_ioports.c

package info (click to toggle)
libticables3 3.9.6-10
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 3,656 kB
  • ctags: 2,184
  • sloc: ansic: 15,996; sh: 9,298; makefile: 526; yacc: 288; awk: 145; sed: 16
file content (175 lines) | stat: -rw-r--r-- 4,404 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* Hey EMACS -*- linux-c -*- */
/* $Id: linux_ioports.c 899 2005-03-14 09:41:20Z roms $ */

/*  libticables - Ti Link Cable library, a part of the TiLP project
 *  Copyright (C) 1999-2004  Romain Lievin
 *  Copyright (c) 2002, Kevin Kofler for the __MINGW32__ & __GNUC__ extensions.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * This unit manages direct low-level I/O operations depending on a
 * I/O method.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#if defined(__I386__) && defined(HAVE_SYS_PERM_H)
#include <sys/perm.h>
#endif
#if defined(__I386__) && defined(HAVE_SYS_IO_H)
#include <sys/io.h>
#elif defined(__I386__) && defined(HAVE_ASM_IO_H)
#include <asm/io.h>
#endif

#include "gettext.h"

#include "cabl_err.h"
#include "externs.h"
#include "printl.h"

/* Variables */

static int dev_fd;	// TTY handle for Linux ioctl calls (API)
static int tty_use = 0;	// open TTY just once

/* Function pointers */

int (*io_rd) (unsigned int addr);
void (*io_wr) (unsigned int addr, int data);

/* I/O thru assembly code */

static int linux_asm_read_io(unsigned int addr)
{
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
	return inb(addr);
#else
	return 0;
#endif
}

static void linux_asm_write_io(unsigned int addr, int data)
{
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
	outb(data, addr);
#endif
}


/* I/O thru ioctl() calls */

static int linux_ioctl_read_io(unsigned int addr)
{
#ifdef HAVE_TERMIOS_H
	unsigned int flags;

  	if (ioctl(dev_fd, TIOCMGET, &flags) == -1) {
    		printl1(2, _("ioctl failed in linux_ioctl_read_io !\n"));
    		return ERR_IOCTL;
  	}

  	return (flags & TIOCM_CTS ? 1 : 0) | (flags & TIOCM_DSR ? 2 : 0);
#endif
}

static void linux_ioctl_write_io(unsigned int address, int data)
{
#ifdef HAVE_TERMIOS_H
	unsigned int flags = 0;

  	flags |= (data & 2) ? TIOCM_RTS : 0;
  	flags |= (data & 1) ? TIOCM_DTR : 0;
  	if (ioctl(dev_fd, TIOCMSET, &flags) == -1) {
    		printl1(2, _("ioctl failed in linux_ioctl_write_io !\n"));
    		//return ERR_IOCTL;
  	}
#endif
}

/* Functions used for initializing the I/O routines */

int io_open(unsigned long from, unsigned long num)
{
	if (method & IOM_ASM) {
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
    		io_rd = linux_asm_read_io;
    		io_wr = linux_asm_write_io;

		return (ioperm(from, num, 1) ? ERR_ROOT : 0);
#else
		return ERR_ROOT;
#endif
	}
  	else if (method & IOM_IOCTL) {
		struct termios termset;

    		if (tty_use)
      			return 0;

		if ((dev_fd = open(io_device, O_RDWR | O_SYNC)) == -1) {
      			if(errno == EACCES)
      				printl1(2, _("unable to open this serial port: %s (wrong permissions).\n"), io_device);
      			else
      				printl1(2, _("unable to open this serial port: %s\n"), io_device);
      			return ERR_OPEN_SER_DEV;
    		}

    		tcgetattr(dev_fd, &termset);
    		cfmakeraw(&termset);

    		io_rd = linux_ioctl_read_io;
    		io_wr = linux_ioctl_write_io;

    		tty_use++;
	} else {
		printl1(2, "bad argument (invalid method).\n");
                return ERR_ILLEGAL_ARG;
	}

	return 0;
}

int io_close(unsigned long from, unsigned long num)
{
	if (method & IOM_ASM) {
#if defined(__I386__) && defined(HAVE_ASM_IO_H) && defined(HAVE_SYS_PERM_H)
    		return (ioperm(from, num, 0) ? ERR_ROOT : 0);
#else
		return 0;
#endif
    	}
    	else if (method & IOM_IOCTL) {
    		if (tty_use) {
      			close(dev_fd);
      			tty_use--;
    		}
	} else {
                printl1(2, "bad argument (invalid method).\n");
                return ERR_ILLEGAL_ARG;
        }
	
	return 0;
}