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
|
// Copyright 2014 Jeff Epler
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#include <errno.h>
#include <fcntl.h>
#include <linux/ppdev.h>
#include <map>
#include <rtapi.h>
#include <rtapi_parport.h>
#include "rtapi_uspace.hh"
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
struct portinfo {
int port_id;
unsigned short base;
unsigned short base_hi;
};
typedef std::map<unsigned short, portinfo> ParportMap;
static ParportMap parports;
static void map_parports() {
for(int i=0; i<16; i++) {
const char path_template[] = "/proc/sys/dev/parport/parport%d/base-addr";
char path[sizeof(path_template)]; // noting that we stop before 100, so it'll fit
snprintf(path, sizeof(path), path_template, i);
FILE *f = fopen(path, "r");
if(!f) {
if(errno != ENOENT)
rtapi_print_msg(RTAPI_MSG_ERR, "fopen(%s): %s\n", path, strerror(errno));
continue;
}
struct portinfo pi;
pi.port_id = i;
if(fscanf(f, "%hd %hd", &pi.base, &pi.base_hi) != 2) {
rtapi_print_msg(RTAPI_MSG_ERR, "Failed to parse base-addr for port #%d\n", i);
fclose(f);
continue;
}
fclose(f);
parports[i] = pi;
parports[pi.base] = pi;
}
}
int rtapi_parport_get(const char *mod_name, rtapi_parport_t *port, unsigned short base, unsigned short base_hi, unsigned int modes) {
WITH_ROOT;
memset(port, 0, sizeof(*port));
port->fd = -1;
if(parports.empty()) map_parports();
ParportMap::iterator pi = parports.find(base);
if(pi == parports.end()) {
if(base < 16){
rtapi_print_msg(RTAPI_MSG_ERR, "Linux parallel port %d not found\n", base);
return -ENOENT;}
rtapi_print_msg(RTAPI_MSG_ERR, "No parport registered at 0x%x. "
"This is not always an error. Continuing.\n", base);
port->base = base;
port->base_hi = base_hi;
return 0;
} else {
port->base = pi->second.base;
port->base_hi = pi->second.base_hi;
const char port_template[] = "/dev/parport%d";
char port_path[sizeof(port_template)];
snprintf(port_path, sizeof(port_path), port_template, pi->second.port_id);
port->fd = open(port_path, O_RDWR);
if(port->fd < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "open(%s): %s\n", port_path, strerror(errno));
return -errno;
}
if(ioctl(port->fd, PPCLAIM) < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "ioctl(%s, PPCLAIM): %s\n", port_path, strerror(errno));
close(port->fd);
port->fd = -1;
return -errno;
}
int ppmodes = ~0;
if(ioctl(port->fd, PPGETMODES, &modes) < 0) {
rtapi_print_msg(RTAPI_MSG_WARN, "ioctl(%s, PPGETMODES): %s\n", port_path, strerror(errno));
}
if((modes & ppmodes) != modes)
{
rtapi_print_msg(RTAPI_MSG_WARN,
"PARPORT: linux parport %s does not support mode %x.\n"
"PARPORT: continuing anyway.\n",
port_path, modes);
}
}
return 0;
}
void rtapi_parport_release(rtapi_parport_t *port) {
close(port->fd);
port->fd = -1;
}
|