Skip to content
Snippets Groups Projects
Commit d91ad6c1 authored by Micah Elizabeth Scott's avatar Micah Elizabeth Scott
Browse files

New untested libusb-to-libev bridge

parent 09d363e6
No related branches found
No related tags found
No related merge requests found
...@@ -11,6 +11,7 @@ TARGET := fcserver ...@@ -11,6 +11,7 @@ TARGET := fcserver
CPP_FILES = \ CPP_FILES = \
main.cpp \ main.cpp \
opcsink.cpp \ opcsink.cpp \
libusbev.cpp \
fcserver.cpp fcserver.cpp
# CPPFLAGS = compiler options for C and C++ # CPPFLAGS = compiler options for C and C++
......
...@@ -34,7 +34,8 @@ FCServer::FCServer(rapidjson::Document &config) ...@@ -34,7 +34,8 @@ FCServer::FCServer(rapidjson::Document &config)
mDevices(config["devices"]), mDevices(config["devices"]),
mVerbose(config["verbose"].IsTrue()), mVerbose(config["verbose"].IsTrue()),
mListenAddr(0), mListenAddr(0),
mOPCSink(opcCallback, this, mVerbose) mOPCSink(opcCallback, this, mVerbose),
mUSB(0)
{ {
/* /*
* Parse the listen [host, port] list. * Parse the listen [host, port] list.
...@@ -81,6 +82,17 @@ FCServer::~FCServer() ...@@ -81,6 +82,17 @@ FCServer::~FCServer()
void FCServer::start(struct ev_loop *loop) void FCServer::start(struct ev_loop *loop)
{ {
mOPCSink.start(loop, mListenAddr); mOPCSink.start(loop, mListenAddr);
startUSB(loop);
}
void FCServer::startUSB(struct ev_loop *loop)
{
if (libusb_init(&mUSB)) {
std::clog << "Error initializing USB library!\n";
return;
}
mUSBEvent.init(mUSB, loop);
} }
void FCServer::opcCallback(OPCSink::Message &msg, void *context) void FCServer::opcCallback(OPCSink::Message &msg, void *context)
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#pragma once #pragma once
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "opcsink.h" #include "opcsink.h"
#include "libusbev.h"
#include <libusb.h>
#include <sstream> #include <sstream>
#include <ev.h> #include <ev.h>
#include <netinet/in.h> #include <netinet/in.h>
...@@ -53,5 +55,9 @@ private: ...@@ -53,5 +55,9 @@ private:
struct addrinfo *mListenAddr; struct addrinfo *mListenAddr;
OPCSink mOPCSink; OPCSink mOPCSink;
libusb_context *mUSB;
LibUSBEventBridge mUSBEvent;
static void opcCallback(OPCSink::Message &msg, void *context); static void opcCallback(OPCSink::Message &msg, void *context);
void startUSB(struct ev_loop *loop);
}; };
/*
* Glue for using libusb with libev
*
* Copyright (c) 2013 Micah Elizabeth Scott
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libusbev.h"
#include "util.h"
#include <stdlib.h>
#include <poll.h>
void LibUSBEventBridge::cbEvent(struct ev_loop *loop, ev_io *io, int revents)
{
Watcher *w = container_of(io, Watcher, io);
LibUSBEventBridge *self = w->self;
// Handle pending USB events without blocking
struct timeval tvZero = { 0, 0 };
libusb_handle_events_timeout(self->mCtx, &tvZero);
}
void LibUSBEventBridge::cbAdded(int fd, short events, void *user_data)
{
LibUSBEventBridge *self = static_cast<LibUSBEventBridge*>(user_data);
Watcher *w = new Watcher();
ev_io_init(&w->io, cbEvent, fd,
((events & POLLIN) ? EV_READ : 0) |
((events & POLLOUT) ? EV_WRITE : 0));
self->mWatchers[fd] = w;
ev_io_start(self->mLoop, &w->io);
}
void LibUSBEventBridge::cbRemoved(int fd, void *user_data)
{
LibUSBEventBridge *self = static_cast<LibUSBEventBridge*>(user_data);
Watcher *w = self->mWatchers[fd];
ev_io_stop(self->mLoop, &w->io);
self->mWatchers.erase(fd);
}
void LibUSBEventBridge::init(struct libusb_context *ctx, struct ev_loop *loop)
{
mCtx = ctx;
mLoop = loop;
// Handle FDs that are already registered
const struct libusb_pollfd **fds = libusb_get_pollfds(ctx);
for (const struct libusb_pollfd **i = fds; *i; ++i) {
cbAdded((*i)->fd, (*i)->events, this);
}
free(fds);
// Get notified when future callbacks are added
libusb_set_pollfd_notifiers(ctx, cbAdded, cbRemoved, this);
}
/*
* Glue for using libusb with libev
*
* Copyright (c) 2013 Micah Elizabeth Scott
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <ev.h>
#include <libusb.h>
#include <map>
class LibUSBEventBridge
{
public:
// Call after libusb_init
void init(struct libusb_context *ctx, struct ev_loop *loop);
private:
struct Watcher {
ev_io io;
LibUSBEventBridge *self;
};
struct libusb_context *mCtx;
struct ev_loop *mLoop;
std::map<int, Watcher*> mWatchers;
static void cbEvent(struct ev_loop *loop, ev_io *io, int revents);
static void cbAdded(int fd, short events, void *user_data);
static void cbRemoved(int fd, void *user_data);
};
...@@ -23,8 +23,12 @@ ...@@ -23,8 +23,12 @@
#pragma once #pragma once
#define offsetof(st, m) __builtin_offsetof(st, m) #ifndef offsetof
# define offsetof(st, m) __builtin_offsetof(st, m)
#endif
#define container_of(ptr, type, member) ({ \ #ifndef container_of
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ # define container_of(ptr, type, member) ({ \
(type *)( (char *)__mptr - offsetof(type,member) );}) const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment