Skip to content
Snippets Groups Projects
Commit 96f9f61a authored by Wesley W. Terpstra's avatar Wesley W. Terpstra
Browse files

Added support for character devices, like the PCIe wishbone bridge.

parent 2cec3943
Branches
Tags
No related merge requests found
......@@ -29,6 +29,7 @@ TRANSPORT = transport/posix-ip.c \
transport/posix-udp.c \
transport/posix-tcp.c \
transport/tunnel.c \
transport/dev.c \
transport/transports.c \
transport/run.c
endif
......
/** @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
/** @file dev.h
* @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/>.
*******************************************************************************
*/
#ifndef EB_DEV_H
#define EB_DEV_H
#include "../transport/transport.h"
#define EB_DEV_MTU 0
EB_PRIVATE eb_status_t eb_dev_open(struct eb_transport* transport, const char* port);
EB_PRIVATE void eb_dev_close(struct eb_transport* transport);
EB_PRIVATE eb_status_t eb_dev_connect(struct eb_transport* transport, struct eb_link* link, const char* address);
EB_PRIVATE void eb_dev_disconnect(struct eb_transport* transport, struct eb_link* link);
EB_PRIVATE void eb_dev_fdes(struct eb_transport*, struct eb_link* link, eb_user_data_t data, eb_descriptor_callback_t cb);
EB_PRIVATE int eb_dev_accept(struct eb_transport*, struct eb_link* result_link, eb_user_data_t data, eb_descriptor_callback_t ready);
EB_PRIVATE 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);
EB_PRIVATE int eb_dev_recv(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
EB_PRIVATE void eb_dev_send(struct eb_transport* transportp, struct eb_link* linkp, const uint8_t* buf, int len);
EB_PRIVATE void eb_dev_send_buffer(struct eb_transport* transportp, struct eb_link* linkp, int on);
struct eb_dev_transport {
/* Contents must fit in 9 bytes */
};
struct eb_dev_link {
/* Contents must fit in 12 bytes */
int fdes;
};
#endif
......@@ -32,8 +32,24 @@
#include "posix-udp.h"
#include "posix-tcp.h"
#include "tunnel.h"
#include "dev.h"
struct eb_transport_ops eb_transports[] = {
#ifndef __WIN32
{
EB_DEV_MTU,
eb_dev_open,
eb_dev_close,
eb_dev_connect,
eb_dev_disconnect,
eb_dev_fdes,
eb_dev_accept,
eb_dev_poll,
eb_dev_recv,
eb_dev_send,
eb_dev_send_buffer
},
#endif
{
EB_POSIX_UDP_MTU,
eb_posix_udp_open,
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment