Newer
Older
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
/** @file dev.c
* @brief This implements a charcter device interface.
*
* Copyright (C) 2011-2012 GSI Helmholtz Centre for Heavy Ion Research GmbH
*
* The transport carries a port for accepting inbound connections.
* Passive devices are created for inbound connections.
*
* @author Wesley W. Terpstra <w.terpstra@gsi.de>
*
* @bug None!
*
*******************************************************************************
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************
*/
#define ETHERBONE_IMPL
#ifndef __WIN32
#include "dev.h"
#include "transport.h"
#include "../glue/strncasecmp.h"
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
static void eb_dev_set_blocking(int fdes, int block) {
int flags;
flags = fcntl(fdes, F_GETFL, 0);
fcntl(fdes, F_SETFL, flags | (block?0:O_NONBLOCK));
}
static int eb_dev_ewouldblock() {
return (errno == EAGAIN || errno == EWOULDBLOCK);
}
eb_status_t eb_dev_open(struct eb_transport* transportp, const char* port) {
/* noop */
return EB_OK;
}
void eb_dev_close(struct eb_transport* transportp) {
/* noop */
}
eb_status_t eb_dev_connect(struct eb_transport* transportp, struct eb_link* linkp, const char* address) {
struct eb_dev_link* link;
const char* devname;
char devpath[256];
int fdes;
link = (struct eb_dev_link*)linkp;
if (eb_strncasecmp(address, "dev/", 4))
return EB_ADDRESS;
devname = address + 4;
if (strlen(devname) > 200)
return EB_ADDRESS;
strcpy(devpath, "/dev/");
strncat(devpath, devname, sizeof(devpath)-8);
if ((fdes = open(devpath, O_BINARY | O_RDWR)) == -1) {
return EB_FAIL;
}
link->fdes = fdes;
return EB_OK;
}
void eb_dev_disconnect(struct eb_transport* transport, struct eb_link* linkp) {
struct eb_dev_link* link;
link = (struct eb_dev_link*)linkp;
close(link->fdes);
}
void eb_dev_fdes(struct eb_transport* transportp, struct eb_link* linkp, eb_user_data_t data, eb_descriptor_callback_t cb) {
struct eb_dev_link* link;
if (linkp) {
link = (struct eb_dev_link*)linkp;
(*cb)(data, link->fdes);
}
}
int eb_dev_accept(struct eb_transport* transportp, struct eb_link* result_linkp, eb_user_data_t data, eb_descriptor_callback_t ready) {
/* Dev does not make child connections */
return 0;
}
int eb_dev_poll(struct eb_transport* transportp, struct eb_link* linkp, eb_user_data_t data, eb_descriptor_callback_t ready, uint8_t* buf, int len) {
struct eb_dev_link* link;
int result;
if (linkp == 0) return 0;
link = (struct eb_dev_link*)linkp;
/* Should we check? */
if (!(*ready)(data, link->fdes))
return 0;
/* Set non-blocking */
eb_dev_set_blocking(link->fdes, 0);
result = read(link->fdes, (char*)buf, len);
if (result == -1 && eb_dev_ewouldblock()) return 0;
if (result == 0) return -1;
return result;
}
int eb_dev_recv(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len) {
struct eb_dev_link* link;
int result;
if (linkp == 0) return 0;
link = (struct eb_dev_link*)linkp;
/* Set blocking */
eb_dev_set_blocking(link->fdes, 1);
result = read(link->fdes, buf, len);
/* EAGAIN impossible on blocking read */
if (result == 0) return -1;
return result;
}
void eb_dev_send(struct eb_transport* transportp, struct eb_link* linkp, const uint8_t* buf, int len) {
struct eb_dev_link* link;
/* linkp == 0 impossible if poll == 0 returns 0 */
link = (struct eb_dev_link*)linkp;
/* Set blocking */
eb_dev_set_blocking(link->fdes, 1);
write(link->fdes, buf, len);
}
void eb_dev_send_buffer(struct eb_transport* transportp, struct eb_link* linkp, int on) {
/* noop */
}
#endif