version 0.5.0_alpha
git-svn-id: svn://db.shs.com.ru/pip@8 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Class for write binary data to logfile, and read or playback this data
|
||||
Copyright (C) 2014 Andrey Bychkov work.a.b@yandex.ru
|
||||
Copyright (C) 2015 Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Class for write binary data to logfile, and read or playback this data
|
||||
Copyright (C) 2014 Andrey Bychkov work.a.b@yandex.ru
|
||||
Copyright (C) 2015 Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Config parser
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Configuration parser and writer
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -29,28 +29,28 @@
|
||||
Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) {return getValue(vname, PIString(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) {return getValue(vname, def.join("%|%"), exists);} \
|
||||
Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) {return getValue(vname, PIString::fromBool(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exists = 0) {return getValue(vname, ltos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) {return getValue(vname, ultos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exists = 0) {return getValue(vname, ftos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) {return getValue(vname, dtos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
\
|
||||
Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) const {return getValue(vname, PIString(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) const {return getValue(vname, def.join("%|%"), exists);} \
|
||||
Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) const {return getValue(vname, PIString::fromBool(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exists = 0) const {return getValue(vname, ltos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) const {return getValue(vname, ultos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exists = 0) const {return getValue(vname, ftos(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, dtos(def), exists);}
|
||||
Entry & getValue(const PIString & vname, const short def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const int def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const long def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const float def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} \
|
||||
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);}
|
||||
|
||||
class PIP_EXPORT PIConfig
|
||||
{
|
||||
@@ -170,37 +170,37 @@ public:
|
||||
Entry & setValue(const char * value) {setValue(PIString(value)); setType("s"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "b"
|
||||
Entry & setValue(const bool value) {setValue(btos(value)); setType("b"); return *this;}
|
||||
Entry & setValue(const bool value) {setValue(PIString::fromBool(value)); setType("b"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "s"
|
||||
Entry & setValue(const char value) {setValue(PIString(1, value)); setType("s"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const short value) {setValue(itos(value)); setType("n"); return *this;}
|
||||
Entry & setValue(const short value) {setValue(PIString::fromNumber(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const int value) {setValue(itos(value)); setType("n"); return *this;}
|
||||
Entry & setValue(const int value) {setValue(PIString::fromNumber(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const long value) {setValue(ltos(value)); setType("n"); return *this;}
|
||||
Entry & setValue(const long value) {setValue(PIString::fromNumber(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const uchar value) {setValue(uitos(value)); setType("n"); return *this;}
|
||||
Entry & setValue(const uchar value) {setValue(PIString::fromNumber(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const ushort value) {setValue(uitos(value)); setType("n"); return *this;}
|
||||
Entry & setValue(const ushort value) {setValue(PIString::fromNumber(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const uint value) {setValue(uitos(value)); setType("n"); return *this;}
|
||||
Entry & setValue(const uint value) {setValue(PIString::fromNumber(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "n"
|
||||
Entry & setValue(const ulong value) {setValue(ultos(value)); setType("n"); return *this;}
|
||||
Entry & setValue(const ulong value) {setValue(PIString::fromNumber(value)); setType("n"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "f"
|
||||
Entry & setValue(const float value) {setValue(ftos(value)); setType("f"); return *this;}
|
||||
Entry & setValue(const float value) {setValue(PIString::fromNumber(value)); setType("f"); return *this;}
|
||||
|
||||
//! Set value to "value" and returns this. Type is set to "f"
|
||||
Entry & setValue(const double value) {setValue(dtos(value)); setType("f"); return *this;}
|
||||
Entry & setValue(const double value) {setValue(PIString::fromNumber(value)); setType("f"); return *this;}
|
||||
|
||||
|
||||
/** \brief Returns entry with name "vname" and default value "def"
|
||||
@@ -303,8 +303,8 @@ public:
|
||||
bool entryExists(const Entry * e, const PIString & name) const;
|
||||
void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;}
|
||||
void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;}
|
||||
void coutt(std::ostream & s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << endl; else cout << p << _name << endl; piForeachC (Entry * i, _children) i->coutt(s, nl);}
|
||||
void piCoutt(PICout s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << NewLine; else cout << p << _name << endl; piForeachC (Entry * i, _children) i->piCoutt(s, nl);}
|
||||
void coutt(std::ostream & s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << std::endl; else std::cout << p << _name << std::endl; piForeachC (Entry * i, _children) i->coutt(s, nl);}
|
||||
void piCoutt(PICout s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << PICoutManipulators::NewLine; else std::cout << p << _name << std::endl; piForeachC (Entry * i, _children) i->piCoutt(s, nl);}
|
||||
void deleteBranch() {piForeach (Entry * i, _children) {i->deleteBranch(); delete i;}}
|
||||
|
||||
static Entry _empty;
|
||||
@@ -390,34 +390,34 @@ public:
|
||||
void setValue(const PIString & name, const char * value, bool write = true) {setValue(name, PIString(value), "s", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "b" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const bool value, bool write = true) {setValue(name, btos(value), "b", write);}
|
||||
void setValue(const PIString & name, const bool value, bool write = true) {setValue(name, PIString::fromBool(value), "b", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const short value, bool write = true) {setValue(name, itos(value), "n", write);}
|
||||
void setValue(const PIString & name, const short value, bool write = true) {setValue(name, PIString::fromNumber(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const int value, bool write = true) {setValue(name, itos(value), "n", write);}
|
||||
void setValue(const PIString & name, const int value, bool write = true) {setValue(name, PIString::fromNumber(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const long value, bool write = true) {setValue(name, ltos(value), "n", write);}
|
||||
void setValue(const PIString & name, const long value, bool write = true) {setValue(name, PIString::fromNumber(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const uchar value, bool write = true) {setValue(name, uitos(value), "n", write);}
|
||||
void setValue(const PIString & name, const uchar value, bool write = true) {setValue(name, PIString::fromNumber(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const ushort value, bool write = true) {setValue(name, uitos(value), "n", write);}
|
||||
void setValue(const PIString & name, const ushort value, bool write = true) {setValue(name, PIString::fromNumber(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const uint value, bool write = true) {setValue(name, uitos(value), "n", write);}
|
||||
void setValue(const PIString & name, const uint value, bool write = true) {setValue(name, PIString::fromNumber(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const ulong value, bool write = true) {setValue(name, ultos(value), "n", write);}
|
||||
void setValue(const PIString & name, const ulong value, bool write = true) {setValue(name, PIString::fromNumber(value), "n", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const float value, bool write = true) {setValue(name, ftos(value), "f", write);}
|
||||
void setValue(const PIString & name, const float value, bool write = true) {setValue(name, PIString::fromNumber(value), "f", write);}
|
||||
|
||||
//! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists
|
||||
void setValue(const PIString & name, const double value, bool write = true) {setValue(name, dtos(value), "f", write);}
|
||||
void setValue(const PIString & name, const double value, bool write = true) {setValue(name, PIString::fromNumber(value), "f", write);}
|
||||
|
||||
//! Returns root entry
|
||||
Entry & rootEntry() {return root;}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Complex I/O point
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Complex I/O point
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Speed and quality in/out diagnostics
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Speed and quality in/out diagnostics
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Directory
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -217,8 +217,13 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
|
||||
# else
|
||||
const_cast<char*>(p.data()), 0
|
||||
# endif
|
||||
, 0, versionsort);
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
, 0,
|
||||
# ifdef MAC_OS
|
||||
alphasort);
|
||||
# else
|
||||
versionsort);
|
||||
# endif
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
l << PIFile::fileInfo(dp + PIString(list[i]->d_name));
|
||||
delete list[i];
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Directory
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Ethernet, UDP/TCP Broadcast/Multicast
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -19,16 +19,32 @@
|
||||
|
||||
#include "piethernet.h"
|
||||
#include "piconfig.h"
|
||||
#include "pisysteminfo.h"
|
||||
#ifdef QNX
|
||||
# include <net/if_dl.h>
|
||||
# include <hw/nicinfo.h>
|
||||
# include <sys/dcmd_io-net.h>
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
# include <io.h>
|
||||
# include <winsock2.h>
|
||||
# include <iphlpapi.h>
|
||||
# include <psapi.h>
|
||||
# include <ws2tcpip.h>
|
||||
# define ip_mreqn ip_mreq
|
||||
# define imr_address imr_interface
|
||||
#else
|
||||
# include <fcntl.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <sys/socket.h>
|
||||
# include <net/if.h>
|
||||
# ifndef ANDROID
|
||||
# include <ifaddrs.h>
|
||||
# endif
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/** \class PIEthernet
|
||||
@@ -51,9 +67,23 @@
|
||||
*
|
||||
* */
|
||||
|
||||
#ifndef WINDOWS
|
||||
PIString getSockAddr(sockaddr * s) {
|
||||
return s == 0 ? PIString() : PIString(inet_ntoa(((sockaddr_in*)s)->sin_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
REGISTER_DEVICE(PIEthernet);
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PIEthernet)
|
||||
sockaddr_in addr_;
|
||||
sockaddr_in saddr_;
|
||||
sockaddr_in raddr_;
|
||||
PRIVATE_DEFINITION_END(PIEthernet)
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) {
|
||||
construct();
|
||||
setType(UDP);
|
||||
@@ -140,11 +170,45 @@ bool PIEthernet::init() {
|
||||
|
||||
|
||||
void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
|
||||
//piCout << "parse" << ipp;
|
||||
if (ip != 0) *ip = ipp.left(ipp.find(":"));
|
||||
if (port != 0) *port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt();
|
||||
}
|
||||
|
||||
|
||||
PIString PIEthernet::macFromBytes(const PIByteArray & mac) {
|
||||
PIString r;
|
||||
for (int i = 0; i < mac.size_s(); ++i) {
|
||||
r += PIString::fromNumber(mac[i], 16).expandLeftTo(2, '0');
|
||||
if (i < mac.size_s() - 1) r += ":";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIEthernet::macToBytes(const PIString & mac) {
|
||||
PIByteArray r;
|
||||
PIStringList sl = mac.split(":");
|
||||
piForeachC (PIString & i, sl)
|
||||
r << uchar(i.toInt(16));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
PIString PIEthernet::applyMask(const PIString & ip, const PIString & mask) {
|
||||
struct in_addr ia;
|
||||
ia.s_addr = inet_addr(ip.data()) & inet_addr(mask.data());
|
||||
return PIString(inet_ntoa(ia));
|
||||
}
|
||||
|
||||
|
||||
PIString PIEthernet::getBroadcast(const PIString & ip, const PIString & mask) {
|
||||
struct in_addr ia;
|
||||
ia.s_addr = inet_addr(ip.data()) | ~inet_addr(mask.data());
|
||||
return PIString(inet_ntoa(ia));
|
||||
}
|
||||
|
||||
|
||||
bool PIEthernet::openDevice() {
|
||||
if (connected_) return true;
|
||||
init();
|
||||
@@ -154,18 +218,18 @@ bool PIEthernet::openDevice() {
|
||||
connecting_ = true;
|
||||
if (type() != UDP || mode() == PIIODevice::WriteOnly)
|
||||
return true;
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_port = htons(port_);
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PIFlags<Parameters> params = parameters();
|
||||
if (params[PIEthernet::Broadcast]) addr_.sin_addr.s_addr = INADDR_ANY;
|
||||
else addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
if (params[PIEthernet::Broadcast]) PRIVATE->addr_.sin_addr.s_addr = INADDR_ANY;
|
||||
else PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
|
||||
#endif
|
||||
//piCout << "bind to" << (params[PIEthernet::Broadcast] ? "255.255.255.255" : ip_) << ":" << port_ << " ...";
|
||||
int tries = 0;
|
||||
while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) {
|
||||
while ((bind(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 10)) {
|
||||
init();
|
||||
tries++;
|
||||
}
|
||||
@@ -328,16 +392,16 @@ bool PIEthernet::connect() {
|
||||
connecting_ = true;
|
||||
return true;
|
||||
/*if (sock == -1) return false;
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
memset(addr_, 0, sizeof(*addr_));
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect to " << ip << ":" << port_;
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
connected_ = (::connect(sock, (sockaddr * )addr_, sizeof(*addr_)) == 0);
|
||||
if (!connected_)
|
||||
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
opened_ = connected_;
|
||||
@@ -363,16 +427,16 @@ bool PIEthernet::listen(bool threaded) {
|
||||
}
|
||||
listen_threaded = server_bounded = false;
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
opened_ = false;
|
||||
int tries = 0;
|
||||
while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) {
|
||||
while ((bind(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 10)) {
|
||||
init();
|
||||
tries++;
|
||||
}
|
||||
@@ -413,16 +477,16 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
return rs;
|
||||
case TCP_Client:
|
||||
if (connecting_) {
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect to " << ip_ << ":" << port_ << "...";
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
connected_ = (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == 0);
|
||||
//piCoutObj << "connect to " << ip_ << ":" << port_ << connected_;
|
||||
if (!connected_)
|
||||
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
@@ -459,12 +523,12 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
if (rs > 0) received(read_to, rs);
|
||||
return rs;
|
||||
case UDP:
|
||||
memset(&raddr_, 0, sizeof(raddr_));
|
||||
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&raddr_);
|
||||
memset(&PRIVATE->raddr_, 0, sizeof(PRIVATE->raddr_));
|
||||
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&PRIVATE->raddr_);
|
||||
//piCout << "eth" << path() << "read return" << rs << errorString();
|
||||
if (rs > 0) {
|
||||
port_r = ntohs(raddr_.sin_port);
|
||||
ip_r = inet_ntoa(raddr_.sin_addr);
|
||||
port_r = ntohs(PRIVATE->raddr_.sin_port);
|
||||
ip_r = inet_ntoa(PRIVATE->raddr_.sin_addr);
|
||||
//piCout << "received from" << lastReadAddress();
|
||||
received(read_to, rs);
|
||||
}
|
||||
@@ -487,15 +551,15 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
int ret = 0;
|
||||
switch (type()) {
|
||||
case TCP_SingleTCP:
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_port = htons(port_s);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
PRIVATE->addr_.sin_port = htons(port_s);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "...";
|
||||
if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) {
|
||||
if (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) != 0) {
|
||||
//piCoutObj << "Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
|
||||
msleep(1);
|
||||
return -1;
|
||||
@@ -507,25 +571,25 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
init();
|
||||
return ret;
|
||||
case UDP:
|
||||
saddr_.sin_port = htons(port_s);
|
||||
/*if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
else*/ saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
saddr_.sin_family = AF_INET;
|
||||
PRIVATE->saddr_.sin_port = htons(port_s);
|
||||
/*if (params[PIEthernet::Broadcast]) PRIVATE->saddr_.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
else*/ PRIVATE->saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
PRIVATE->saddr_.sin_family = AF_INET;
|
||||
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << "socket" << sock_s << max_size << "bytes ...";
|
||||
return ethSendto(sock_s, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
return ethSendto(sock_s, data, max_size, 0, (sockaddr * )&PRIVATE->saddr_, sizeof(PRIVATE->saddr_));
|
||||
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok";
|
||||
case TCP_Client:
|
||||
if (connecting_) {
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect to " << ip << ":" << port_;
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
connected_ = (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == 0);
|
||||
if (!connected_)
|
||||
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
opened_ = connected_;
|
||||
@@ -892,7 +956,6 @@ int PIEthernet::ethErrorCore() {
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Ethernet, UDP/TCP Broadcast/Multicast
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -25,7 +25,8 @@
|
||||
|
||||
#include "pitimer.h"
|
||||
#include "piiodevice.h"
|
||||
#include "piprocess.h"
|
||||
|
||||
class sockaddr;
|
||||
|
||||
class PIP_EXPORT PIEthernet: public PIIODevice
|
||||
{
|
||||
@@ -34,7 +35,7 @@ class PIP_EXPORT PIEthernet: public PIIODevice
|
||||
public:
|
||||
|
||||
//! Contructs UDP %PIEthernet with empty read address
|
||||
PIEthernet();
|
||||
explicit PIEthernet();
|
||||
|
||||
//! \brief Type of %PIEthernet
|
||||
enum PIP_EXPORT Type {
|
||||
@@ -54,7 +55,7 @@ public:
|
||||
};
|
||||
|
||||
//! Contructs %PIEthernet with type "type", read address "ip_port" and parameters "params"
|
||||
PIEthernet(Type type, const PIString & ip_port = PIString(), const PIFlags<Parameters> params = 0);
|
||||
explicit PIEthernet(Type type, const PIString & ip_port = PIString(), const PIFlags<Parameters> params = 0);
|
||||
|
||||
virtual ~PIEthernet();
|
||||
|
||||
@@ -324,10 +325,10 @@ public:
|
||||
static PIStringList allAddresses();
|
||||
|
||||
static void parseAddress(const PIString & ipp, PIString * ip, int * port);
|
||||
static PIString macFromBytes(const PIByteArray & mac) {PIString r; for (int i = 0; i < mac.size_s(); ++i) {r += PIString::fromNumber(mac[i], 16).expandLeftTo(2, '0'); if (i < mac.size_s() - 1) r += ":";} return r;}
|
||||
static PIByteArray macToBytes(const PIString & mac) {PIByteArray r; PIStringList sl = mac.split(":"); piForeachC (PIString & i, sl) r << uchar(i.toInt(16)); return r;}
|
||||
static PIString applyMask(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) & inet_addr(mask.data()); return PIString(inet_ntoa(ia));}
|
||||
static PIString getBroadcast(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) | ~inet_addr(mask.data()); return PIString(inet_ntoa(ia));}
|
||||
static PIString macFromBytes(const PIByteArray & mac);
|
||||
static PIByteArray macToBytes(const PIString & mac);
|
||||
static PIString applyMask(const PIString & ip, const PIString & mask);
|
||||
static PIString getBroadcast(const PIString & ip, const PIString & mask);
|
||||
|
||||
//! \events
|
||||
//! \{
|
||||
@@ -369,7 +370,7 @@ public:
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
PIEthernet(int sock, PIString ip_port);
|
||||
explicit PIEthernet(int sock, PIString ip_port);
|
||||
|
||||
void propertyChanged(const PIString & name);
|
||||
|
||||
@@ -388,15 +389,11 @@ protected:
|
||||
void applyTimeouts();
|
||||
void applyTimeout(int fd, int opt, double ms);
|
||||
void applyOptInt(int level, int opt, int val);
|
||||
#ifndef WINDOWS
|
||||
static PIString getSockAddr(sockaddr * s) {return s == 0 ? PIString() : PIString(inet_ntoa(((sockaddr_in*)s)->sin_addr));}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
PRIVATE_DECLARATION
|
||||
int sock, sock_s, wrote;
|
||||
mutable int port_, port_s, port_c, port_r;
|
||||
bool connected_, connecting_, listen_threaded, server_bounded;
|
||||
sockaddr_in addr_, saddr_, raddr_;
|
||||
mutable PIString ip_, ip_s, ip_c, ip_r;
|
||||
PIThread server_thread_;
|
||||
PIVector<PIEthernet * > clients_;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
File
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -32,6 +32,9 @@
|
||||
# define S_IFBLK 0x08
|
||||
# define S_IFCHR 0x10
|
||||
# define S_IFSOCK 0x20
|
||||
#else
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
#define S_IFHDN 0x40
|
||||
#ifdef QNX
|
||||
@@ -294,10 +297,17 @@ PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
|
||||
_stat_call_(path.data(), &fs);
|
||||
int mode = fs.st_mode;
|
||||
ret.size = fs.st_size;
|
||||
ret.id_user = fs.st_uid;
|
||||
ret.id_user = fs.st_uid;
|
||||
ret.id_group = fs.st_gid;
|
||||
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.st_atim.tv_sec, fs.st_atim.tv_nsec));
|
||||
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.st_mtim.tv_sec, fs.st_mtim.tv_nsec));
|
||||
#ifdef MAC_OS
|
||||
# define ATIME st_atimespec
|
||||
# define MTIME st_ctimespec
|
||||
#else
|
||||
# define ATIME st_atim
|
||||
# define MTIME st_mtim
|
||||
#endif
|
||||
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.ATIME.tv_sec, fs.ATIME.tv_nsec));
|
||||
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.MTIME.tv_sec, fs.MTIME.tv_nsec));
|
||||
ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR);
|
||||
ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP);
|
||||
ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
File
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -24,7 +24,7 @@
|
||||
#define PIFILE_H
|
||||
|
||||
#include "piiodevice.h"
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
class PIP_EXPORT PIFile: public PIIODevice
|
||||
{
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
int precision() const {return prec_;}
|
||||
|
||||
//! Set float numbers write precision to "prec_" digits
|
||||
void setPrecision(int prec) {prec_ = prec; if (prec_ >= 0) prec_str = "." + itos(prec_); else prec_str = "";}
|
||||
void setPrecision(int prec) {prec_ = prec; if (prec_ >= 0) prec_str = "." + PIString::fromNumber(prec_); else prec_str = "";}
|
||||
|
||||
|
||||
//! Read from file to "read_to" no more than "max_size" and return readed bytes count
|
||||
@@ -206,9 +206,9 @@ public:
|
||||
//! Write to file text representation of "v"
|
||||
PIFile & operator <<(ullong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%llu", v); return *this;}
|
||||
//! Write to file text representation of "v" with precision \a precision()
|
||||
PIFile & operator <<(float v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;}
|
||||
PIFile & operator <<(float v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "f").data(), v); return *this;}
|
||||
//! Write to file text representation of "v" with precision \a precision()
|
||||
PIFile & operator <<(double v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;}
|
||||
PIFile & operator <<(double v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "lf").data(), v); return *this;}
|
||||
|
||||
|
||||
//! Read from file text representation of "v"
|
||||
@@ -292,7 +292,7 @@ private:
|
||||
|
||||
FILE * fd;
|
||||
int ret, prec_;
|
||||
string prec_str;
|
||||
PIString prec_str;
|
||||
|
||||
};
|
||||
|
||||
@@ -301,7 +301,7 @@ inline PICout operator <<(PICout s, const PIFile::FileInfo & v) {
|
||||
s << "FileInfo(\"" << v.path << "\", " << PIString::readableSize(v.size) << ", "
|
||||
<< v.perm_user.toString() << " " << v.perm_group.toString() << " " << v.perm_other.toString() << ", "
|
||||
<< v.time_access.toString() << ", " << v.time_modification.toString()
|
||||
<< ", 0x" << Hex << v.flags << ")";
|
||||
<< ", 0x" << PICoutManipulators::Hex << v.flags << ")";
|
||||
s.restoreControl();
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ PIFileTransfer::PIFileTransfer(): crc(standardCRC_16()) {
|
||||
header.version = PIFILETRANSFER_VERSION;
|
||||
header.session_id = 0;
|
||||
dir = PIDir::current();
|
||||
fileinfo_size = sizeof(EntryInfo) + sizeof(PIByteArray) + 100;
|
||||
fileinfo_size = sizeof(EntryInfo) + sizeof(FilePart) + 100;
|
||||
min_packet_size = sizeof(PacketHeader) + sizeof(uint) + fileinfo_size;
|
||||
is_sending = is_receiving = false;
|
||||
bytes_file_all = bytes_file_cur = bytes_total_all = bytes_total_cur = 0;
|
||||
@@ -26,16 +26,33 @@ PIFileTransfer::~PIFileTransfer() {
|
||||
|
||||
|
||||
bool PIFileTransfer::send(const PIString & file) {
|
||||
return sendFiles(PIVector<PIFile::FileInfo>() << PIFile::fileInfo(file));
|
||||
PIVector<PIFile::FileInfo> ce = dir.entries();
|
||||
PIFile::FileInfo e;
|
||||
e.path = "";
|
||||
for (int i = 0; i < ce.size_s(); i++) {
|
||||
if (ce[i].path == file) e = ce[i];
|
||||
}
|
||||
if (e.path != "") return sendFiles(PIVector<PIFile::FileInfo>() << e);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PIFileTransfer::send(PIVector<PIFile::FileInfo> entries) {
|
||||
PIVector<PIFile::FileInfo> allEntries;
|
||||
PIVector<PIFile::FileInfo> ce;
|
||||
PISet<PIString> names;
|
||||
for (int i = 0; i < entries.size_s(); i++) {
|
||||
allEntries << entries[i];
|
||||
ce.clear();
|
||||
if (entries[i].isDir())
|
||||
allEntries << PIDir::allEntries(dir.absolutePath() + dir.separator + entries[i].path);
|
||||
ce = PIDir::allEntries(dir.absolutePath() + dir.separator + entries[i].path);
|
||||
for (int k = 0; k < ce.size_s(); k++) ce[k].path = entries[i].path + dir.separator + ce[k].path;
|
||||
ce.push_front(entries[i]);
|
||||
for (int j = 0; j < ce.size_s(); j++) {
|
||||
if (names.contains(ce[j].path)) continue;
|
||||
allEntries << ce[j];
|
||||
//piCout << ce[j].path;
|
||||
names << ce[j].path;
|
||||
}
|
||||
}
|
||||
return sendFiles(allEntries);
|
||||
}
|
||||
@@ -146,12 +163,6 @@ void PIFileTransfer::received(PIByteArray & ba) {
|
||||
|
||||
|
||||
bool PIFileTransfer::sendFiles(PIVector<PIFile::FileInfo> files) {
|
||||
PIStringList names;
|
||||
for(int i=0; i<files.size_s(); i++) {
|
||||
files[i].path = dir.relative(files[i].path);
|
||||
if (names.contains(files[i].path)) {files.remove(i); i--;}
|
||||
else names << files[i].path;
|
||||
}
|
||||
// piCoutObj << "prepare to send" << files.size() << "files";
|
||||
break_ = false;
|
||||
is_sending = true;
|
||||
@@ -247,7 +258,7 @@ void PIFileTransfer::buildSession(PIVector<PIFile::FileInfo> files) {
|
||||
fi.fstart = fs;
|
||||
fi.fsize = piMinll(fi.entry.size - fs, max_packet_size - min_packet_size);
|
||||
lfi << fi;
|
||||
cur_size += fi.fsize + sizeof(PIByteArray);
|
||||
cur_size += fi.fsize + sizeof(FilePart);
|
||||
if (fi.part_index != fi.parts) {
|
||||
session << lfi;
|
||||
lfi.clear();
|
||||
|
||||
@@ -16,6 +16,22 @@ public:
|
||||
enum ReplyCode {Unknown = 0, Success, Invalid, Break};
|
||||
enum PacketType {pt_Data = 1, pt_Reply, pt_SendRequest};//, pt_SendResult};
|
||||
|
||||
struct EntryInfo {
|
||||
EntryInfo() {
|
||||
fstart = fsize = 0;
|
||||
parts = part_index = 0;
|
||||
}
|
||||
PIFile::FileInfo entry;
|
||||
llong fstart;
|
||||
llong fsize;
|
||||
uint parts;
|
||||
uint part_index;
|
||||
};
|
||||
|
||||
struct FilePart {
|
||||
uint index;
|
||||
PIByteArray data;
|
||||
};
|
||||
|
||||
struct PacketHeader {
|
||||
union {
|
||||
@@ -34,25 +50,6 @@ public:
|
||||
}
|
||||
// uint crc;
|
||||
};
|
||||
|
||||
struct PartHeader {
|
||||
uint id;
|
||||
uint total_size;
|
||||
uint part_start;
|
||||
uint part_size;
|
||||
};
|
||||
|
||||
struct EntryInfo {
|
||||
EntryInfo() {
|
||||
fstart = fsize = 0;
|
||||
parts = part_index = 0;
|
||||
}
|
||||
PIFile::FileInfo entry;
|
||||
llong fstart;
|
||||
llong fsize;
|
||||
uint parts;
|
||||
uint part_index;
|
||||
};
|
||||
|
||||
//bool send(const PIFile & file);
|
||||
bool send(const PIString & file);
|
||||
@@ -126,8 +123,6 @@ private:
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::PacketHeader & v) {s << v.raw_sig << v.type << v.session_id << v.id; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIFileTransfer::PacketHeader & v) {s >> v.raw_sig >> v.type >> v.session_id >> v.id; return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::PartHeader & v) {s << v.id << v.total_size << v.part_start << v.part_size; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIFileTransfer::PartHeader & v) {s >> v.id >> v.total_size >> v.part_start >> v.part_size; return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::EntryInfo & v) {s << v.entry.path << v.entry.size << v.entry.time_modification << v.entry.time_access << int(v.entry.flags)
|
||||
<< v.entry.id_user << v.entry.id_group << v.fstart; return s;}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Abstract input/output device
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Abstract input/output device
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PIIODevice wrapper around PIString
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PIIODevice wrapper around PIString
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Multiprotocol
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Packets extractor
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Packets extractor
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Peer - named I/O ethernet node
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -133,7 +133,7 @@ void PIPeer::initMBcasts(PIStringList al) {
|
||||
PIString nm;
|
||||
al << _PIPEER_MULTICAST_IP;
|
||||
piForeachC (PIString & a, al) {
|
||||
piCout << "mcast try" << a;
|
||||
//piCout << "mcast try" << a;
|
||||
ce = new PIEthernet();
|
||||
ce->setDebug(false);
|
||||
ce->setName("__S__PIPeer_mcast_eth_" + a);
|
||||
@@ -156,7 +156,7 @@ void PIPeer::initMBcasts(PIStringList al) {
|
||||
ce->setSendAddress(PIEthernet::getBroadcast(a, nm), _PIPEER_BROADCAST_PORT);
|
||||
ce->setReadAddress(a, _PIPEER_BROADCAST_PORT);
|
||||
//piCout << "mc BC try" << a << nm << ce->sendIP();
|
||||
piCout << "bcast try" << a << nm;
|
||||
//piCout << "bcast try" << a << nm;
|
||||
eths_bcast << ce;
|
||||
CONNECTU(ce, threadedReadEvent, this, mbcastRead);
|
||||
ce->startThreadedRead();
|
||||
@@ -171,7 +171,7 @@ void PIPeer::initMBcasts(PIStringList al) {
|
||||
eth_lo.setSendIP("127.0.0.1");
|
||||
CONNECTU(ð_lo, threadedReadEvent, this, mbcastRead);
|
||||
eth_lo.startThreadedRead();
|
||||
piCout << "lo binded to" << eth_lo.readAddress();
|
||||
//piCout << "lo binded to" << eth_lo.readAddress();
|
||||
//piCout << "add eth" << ta;
|
||||
break;
|
||||
}
|
||||
@@ -335,55 +335,63 @@ bool PIPeer::mbcastRead(uchar * data, int size) {
|
||||
ba >> type;
|
||||
if (type <= 0 || type >= 4) return true;
|
||||
PeerInfo pi;
|
||||
const PeerInfo * rpi = 0;
|
||||
PIVector<PeerInfo> rpeers;
|
||||
ba >> pi.name;
|
||||
//piCout << "read type" << type << "from" << pi.name;
|
||||
if (pi.name == self_info.name) return true;
|
||||
PIMutexLocker locker(mc_mutex);
|
||||
diag_s.received(size);
|
||||
const PeerInfo * rpi = 0;
|
||||
bool ch = false;
|
||||
PIVector<PeerInfo> rpeers;
|
||||
//piCout << "analyz ...";
|
||||
switch (type) {
|
||||
case 1: // new peer
|
||||
//piCout << "new peer packet ...";
|
||||
if (hasPeer(pi.name)) break;
|
||||
ba >> pi;
|
||||
pi.sync = 0;
|
||||
if (pi.dist == 0) {
|
||||
pi.addNeighbour(self_info.name);
|
||||
self_info.addNeighbour(pi.name);
|
||||
peers_mutex.lock();
|
||||
if (hasPeer(pi.name)) {
|
||||
ba >> pi;
|
||||
pi.sync = 0;
|
||||
if (pi.dist == 0) {
|
||||
pi.addNeighbour(self_info.name);
|
||||
self_info.addNeighbour(pi.name);
|
||||
}
|
||||
peers << pi;
|
||||
findNearestAddresses();
|
||||
piCoutObj << "new peer \"" << pi.name << "\"" << " dist " << pi.dist;
|
||||
pi.dist++;
|
||||
sendSelfInfo();
|
||||
sendPeerInfo(pi);
|
||||
peerConnected(pi.name);
|
||||
peerConnectedEvent(pi.name);
|
||||
//piCout << "new peer packet ok";
|
||||
}
|
||||
peers << pi;
|
||||
piCoutObj << "new peer \"" << pi.name << "\"" << " dist " << pi.dist;
|
||||
pi.dist++;
|
||||
sendSelfInfo();
|
||||
sendPeerInfo(pi);
|
||||
findNearestAddresses();
|
||||
peerConnected(pi.name);
|
||||
peerConnectedEvent(pi.name);
|
||||
//piCout << "new peer packet ok";
|
||||
peers_mutex.unlock();
|
||||
break;
|
||||
case 2: // remove peer
|
||||
//piCout << "remove peer packet ..." << pi.name;
|
||||
peers_mutex.lock();
|
||||
rpi = getPeerByName(pi.name);
|
||||
if (!rpi) break;
|
||||
dist = rpi->dist;
|
||||
addToRemoved(*rpi);
|
||||
removePeer(pi.name);
|
||||
piCoutObj << "remove peer \"" << pi.name << "\"";
|
||||
if (dist == 0)
|
||||
self_info.removeNeighbour(pi.name);
|
||||
sendPeerRemove(pi.name);
|
||||
findNearestAddresses();
|
||||
peerDisconnected(pi.name);
|
||||
peerDisconnectedEvent(pi.name);
|
||||
//piCout << "remove peer packet ok";
|
||||
if (rpi) {
|
||||
dist = rpi->dist;
|
||||
addToRemoved(*rpi);
|
||||
removePeer(pi.name);
|
||||
piCoutObj << "remove peer \"" << pi.name << "\"";
|
||||
if (dist == 0)
|
||||
self_info.removeNeighbour(pi.name);
|
||||
sendPeerRemove(pi.name);
|
||||
findNearestAddresses();
|
||||
peerDisconnected(pi.name);
|
||||
peerDisconnectedEvent(pi.name);
|
||||
//piCout << "remove peer packet ok";
|
||||
}
|
||||
peers_mutex.unlock();
|
||||
break;
|
||||
case 3: // sync peers
|
||||
//piCout << "sync packet ...";
|
||||
ba >> pi >> rpeers;
|
||||
rpeers << pi;
|
||||
//piCoutObj << "rec sync " << rpeers.size_s() << " peers";
|
||||
peers_mutex.lock();
|
||||
piForeach (PeerInfo & rpeer, rpeers) {
|
||||
//piCout << " to sync " << rpeer.name;
|
||||
if (rpeer.name == self_info.name) continue;
|
||||
@@ -416,12 +424,14 @@ bool PIPeer::mbcastRead(uchar * data, int size) {
|
||||
if (exist || isRemoved(rpeer)) continue;
|
||||
rpeer.dist++;
|
||||
peers << rpeer;
|
||||
findNearestAddresses();
|
||||
ch = true;
|
||||
peerConnected(rpeer.name);
|
||||
peerConnectedEvent(rpeer.name);
|
||||
}
|
||||
//piCout << "***";
|
||||
//piCout << self_info.name << self_info.neighbours;
|
||||
if (ch)
|
||||
findNearestAddresses();
|
||||
piForeach (PeerInfo & i, peers) {
|
||||
if (i.dist == 0) {
|
||||
self_info.addNeighbour(i.name);
|
||||
@@ -429,6 +439,7 @@ bool PIPeer::mbcastRead(uchar * data, int size) {
|
||||
}
|
||||
//piCout << i.name << i.neighbours;
|
||||
}
|
||||
peers_mutex.unlock();
|
||||
//piCoutObj << "after sync " << peers.size_s() << " peers";
|
||||
break;
|
||||
}
|
||||
@@ -514,6 +525,7 @@ void PIPeer::syncPeers() {
|
||||
PIMutexLocker locker(eth_mutex);
|
||||
PIString pn;
|
||||
bool change = false;
|
||||
peers_mutex.lock();
|
||||
for (uint i = 0; i < peers.size(); ++i) {
|
||||
PeerInfo & cp(peers[i]);
|
||||
if (cp.sync > 3 && cp.dist == 0) {
|
||||
@@ -539,6 +551,7 @@ void PIPeer::syncPeers() {
|
||||
self_info.time = PISystemTime::current();
|
||||
PIByteArray ba;
|
||||
ba << int(3) << self_info.name << self_info << peers;
|
||||
peers_mutex.unlock();
|
||||
sendMBcast(ba);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Peer - named I/O ethernet node, forming self-organized peering network
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
@@ -162,7 +162,7 @@ private:
|
||||
PIVector<PIEthernet * > eths_traffic, eths_mcast, eths_bcast;
|
||||
PIEthernet eth_send, eth_lo;
|
||||
PITimer timer;
|
||||
PIMutex mc_mutex, eth_mutex;
|
||||
PIMutex mc_mutex, eth_mutex, peers_mutex;
|
||||
|
||||
PeerInfo self_info;
|
||||
PIVector<PeerInfo> peers;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Protocol, input/output channel (COM, UDP)
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Protocol, input/output channel (COM, UDP)
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
|
||||
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
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "pipacketextractor.h"
|
||||
#include "pitimer.h"
|
||||
#include "piconfig.h"
|
||||
#include "pifile.h"
|
||||
#include "math.h"
|
||||
|
||||
class PIProtocol;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
COM
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
|
||||
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
|
||||
@@ -20,6 +20,72 @@
|
||||
#include "piserial.h"
|
||||
#include "piconfig.h"
|
||||
#include "pidir.h"
|
||||
#include <errno.h>
|
||||
#ifdef WINDOWS
|
||||
# include <winreg.h>
|
||||
# define TIOCM_LE 1
|
||||
# define TIOCM_DTR 4
|
||||
# define TIOCM_RTS 7
|
||||
# define TIOCM_CTS 8
|
||||
# define TIOCM_ST 3
|
||||
# define TIOCM_SR 2
|
||||
# define TIOCM_CAR 1
|
||||
# define TIOCM_RNG 9
|
||||
# define TIOCM_DSR 6
|
||||
# define B50 50
|
||||
# define B75 75
|
||||
# define B110 110
|
||||
# define B300 300
|
||||
# define B600 600
|
||||
# define B1200 1200
|
||||
# define B2400 2400
|
||||
# define B4800 4800
|
||||
# define B9600 9600
|
||||
# define B14400 14400
|
||||
# define B19200 19200
|
||||
# define B38400 38400
|
||||
# define B57600 57600
|
||||
# define B115200 115200
|
||||
# define B128000 128000
|
||||
# define B256000 256000
|
||||
# define B1500000 1500000
|
||||
# define B2000000 2000000
|
||||
# define B2500000 2500000
|
||||
# define B3000000 3000000
|
||||
# define B3500000 3500000
|
||||
# define B4000000 4000000
|
||||
#else
|
||||
# include <termios.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/ioctl.h>
|
||||
# ifndef B50
|
||||
# define B50 0000001
|
||||
# endif
|
||||
# ifndef B75
|
||||
# define B75 0000002
|
||||
# endif
|
||||
# ifndef B1500000
|
||||
# define B1500000 0010012
|
||||
# endif
|
||||
# ifndef B2000000
|
||||
# define B2000000 0010013
|
||||
# endif
|
||||
# ifndef B2500000
|
||||
# define B2500000 0010014
|
||||
# endif
|
||||
# ifndef B3000000
|
||||
# define B3000000 0010015
|
||||
# endif
|
||||
# ifndef B3500000
|
||||
# define B3500000 0010016
|
||||
# endif
|
||||
# ifndef B4000000
|
||||
# define B4000000 0010017
|
||||
# endif
|
||||
#endif
|
||||
#ifndef CRTSCTS
|
||||
# define CRTSCTS 020000000000
|
||||
#endif
|
||||
|
||||
|
||||
/*! \class PISerial
|
||||
@@ -35,6 +101,18 @@
|
||||
REGISTER_DEVICE(PISerial);
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PISerial)
|
||||
#ifdef WINDOWS
|
||||
DCB desc, sdesc;
|
||||
void * hCom;
|
||||
DWORD readed, mask;
|
||||
#else
|
||||
termios desc, sdesc;
|
||||
uint readed;
|
||||
#endif
|
||||
PRIVATE_DEFINITION_END(PISerial)
|
||||
|
||||
|
||||
PISerial::PISerial(): PIIODevice("", ReadWrite) {
|
||||
_init();
|
||||
}
|
||||
@@ -54,15 +132,14 @@ PISerial::~PISerial() {
|
||||
|
||||
|
||||
void PISerial::_init() {
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->hCom = 0;
|
||||
#endif
|
||||
fd = -1;
|
||||
piMonitor.serials++;
|
||||
setPriority(piHigh);
|
||||
block_read = true;
|
||||
block_read = block_write = true;
|
||||
vtime = 1;
|
||||
#ifdef WINDOWS
|
||||
block_write = true;
|
||||
hCom = 0;
|
||||
#endif
|
||||
setParameters(0);
|
||||
setSpeed(S115200);
|
||||
setDataBitsCount(8);
|
||||
@@ -122,6 +199,26 @@ bool PISerial::isPin(int number) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PISerial::setLE(bool on) {return setBit(TIOCM_LE, on, "LE");}
|
||||
bool PISerial::setDTR(bool on) {return setBit(TIOCM_DTR, on, "DTR");}
|
||||
bool PISerial::setRTS(bool on) {return setBit(TIOCM_RTS, on, "RTS");}
|
||||
bool PISerial::setCTS(bool on) {return setBit(TIOCM_CTS, on, "CTS");}
|
||||
bool PISerial::setST(bool on) {return setBit(TIOCM_ST, on, "ST");}
|
||||
bool PISerial::setSR(bool on) {return setBit(TIOCM_SR, on, "SR");}
|
||||
bool PISerial::setCAR(bool on) {return setBit(TIOCM_CAR, on, "CAR");}
|
||||
bool PISerial::setRNG(bool on) {return setBit(TIOCM_RNG, on, "RNG");}
|
||||
bool PISerial::setDSR(bool on) {return setBit(TIOCM_DSR, on, "DSR");}
|
||||
|
||||
bool PISerial::isLE() const {return isBit(TIOCM_LE, "LE");}
|
||||
bool PISerial::isDTR() const {return isBit(TIOCM_DTR, "DTR");}
|
||||
bool PISerial::isRTS() const {return isBit(TIOCM_RTS, "RTS");}
|
||||
bool PISerial::isCTS() const {return isBit(TIOCM_CTS, "CTS");}
|
||||
bool PISerial::isST() const {return isBit(TIOCM_ST, "ST");}
|
||||
bool PISerial::isSR() const {return isBit(TIOCM_SR, "SR");}
|
||||
bool PISerial::isCAR() const {return isBit(TIOCM_CAR, "CAR");}
|
||||
bool PISerial::isRNG() const {return isBit(TIOCM_RNG, "RNG");}
|
||||
bool PISerial::isDSR() const {return isBit(TIOCM_DSR, "DSR");}
|
||||
|
||||
|
||||
bool PISerial::setBit(int bit, bool on, const PIString & bname) {
|
||||
#ifndef WINDOWS
|
||||
@@ -158,6 +255,13 @@ bool PISerial::isBit(int bit, const PIString & bname) const {
|
||||
}
|
||||
|
||||
|
||||
void PISerial::flush() {
|
||||
#ifndef WINDOWS
|
||||
if (fd != -1) tcflush(fd, TCIOFLUSH);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::closeDevice() {
|
||||
if (!isInitialized()) return true;
|
||||
if (isRunning()) {
|
||||
@@ -166,12 +270,12 @@ bool PISerial::closeDevice() {
|
||||
}
|
||||
if (fd != -1) {
|
||||
#ifdef WINDOWS
|
||||
SetCommState(hCom, &sdesc);
|
||||
SetCommMask(hCom, mask);
|
||||
CloseHandle(hCom);
|
||||
hCom = 0;
|
||||
SetCommState(PRIVATE->hCom, &PRIVATE->sdesc);
|
||||
SetCommMask(PRIVATE->hCom, PRIVATE->mask);
|
||||
CloseHandle(PRIVATE->hCom);
|
||||
PRIVATE->hCom = 0;
|
||||
#else
|
||||
tcsetattr(fd, TCSANOW, &sdesc);
|
||||
tcsetattr(fd, TCSANOW, &PRIVATE->sdesc);
|
||||
::close(fd);
|
||||
#endif
|
||||
fd = -1;
|
||||
@@ -351,8 +455,8 @@ bool PISerial::openDevice() {
|
||||
if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;}
|
||||
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
|
||||
PIString wp = "//./" + path();
|
||||
hCom = CreateFileA(wp.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
if (hCom == INVALID_HANDLE_VALUE) {
|
||||
PRIVATE->hCom = CreateFileA(wp.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
if (PRIVATE->hCom == INVALID_HANDLE_VALUE) {
|
||||
piCoutObj << "Unable to open \"" << path() << "\"";
|
||||
fd = -1;
|
||||
return false;
|
||||
@@ -371,8 +475,8 @@ bool PISerial::openDevice() {
|
||||
piCoutObj << "Unable to open \"" << path() << "\"";
|
||||
return false;
|
||||
}
|
||||
tcgetattr(fd, &desc);
|
||||
sdesc = desc;
|
||||
tcgetattr(fd, &PRIVATE->desc);
|
||||
PRIVATE->sdesc = PRIVATE->desc;
|
||||
//piCoutObj << "Initialized " << path_;
|
||||
#endif
|
||||
applySettings();
|
||||
@@ -389,58 +493,58 @@ void PISerial::applySettings() {
|
||||
times.ReadTotalTimeoutMultiplier = block_read ? 0 : MAXDWORD;
|
||||
times.WriteTotalTimeoutConstant = 0;
|
||||
times.WriteTotalTimeoutMultiplier = block_write ? 0 : 1;
|
||||
if (SetCommTimeouts(hCom, ×) == -1)
|
||||
if (SetCommTimeouts(PRIVATE->hCom, ×) == -1)
|
||||
piCoutObj << "Unable to set timeouts for \"" << path() << "\"";
|
||||
GetCommMask(hCom, &mask);
|
||||
SetCommMask(hCom, EV_RXCHAR);
|
||||
GetCommState(hCom, &sdesc);
|
||||
desc = sdesc;
|
||||
desc.DCBlength = sizeof(desc);
|
||||
desc.BaudRate = convertSpeed(outSpeed());
|
||||
GetCommMask(PRIVATE->hCom, &PRIVATE->mask);
|
||||
SetCommMask(PRIVATE->hCom, EV_RXCHAR);
|
||||
GetCommState(PRIVATE->hCom, &PRIVATE->sdesc);
|
||||
PRIVATE->desc = PRIVATE->sdesc;
|
||||
PRIVATE->desc.DCBlength = sizeof(PRIVATE->desc);
|
||||
PRIVATE->desc.BaudRate = convertSpeed(outSpeed());
|
||||
if (dataBitsCount() >= 5 && dataBitsCount() <= 8)
|
||||
desc.ByteSize = dataBitsCount();
|
||||
PRIVATE->desc.ByteSize = dataBitsCount();
|
||||
else
|
||||
desc.ByteSize = 8;
|
||||
PRIVATE->desc.ByteSize = 8;
|
||||
PIFlags<Parameters> params = parameters();
|
||||
if (params[PISerial::ParityControl]) {
|
||||
desc.fParity = 1;
|
||||
desc.Parity = params[PISerial::ParityOdd] ? 1 : 2;
|
||||
PRIVATE->desc.fParity = 1;
|
||||
PRIVATE->desc.Parity = params[PISerial::ParityOdd] ? 1 : 2;
|
||||
}
|
||||
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
|
||||
if (SetCommState(hCom, &desc) == -1) {
|
||||
PRIVATE->desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
|
||||
if (SetCommState(PRIVATE->hCom, &PRIVATE->desc) == -1) {
|
||||
piCoutObj << "Unable to set comm state for \"" << path() << "\"";
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (fd == -1) return;
|
||||
tcgetattr(fd, &desc);
|
||||
desc.c_oflag = desc.c_lflag = desc.c_cflag = 0;
|
||||
desc.c_iflag = IGNBRK;
|
||||
desc.c_cflag = CLOCAL | HUPCL;
|
||||
tcgetattr(fd, &PRIVATE->desc);
|
||||
PRIVATE->desc.c_oflag = PRIVATE->desc.c_lflag = PRIVATE->desc.c_cflag = 0;
|
||||
PRIVATE->desc.c_iflag = IGNBRK;
|
||||
PRIVATE->desc.c_cflag = CLOCAL | HUPCL;
|
||||
switch (dataBitsCount()) {
|
||||
case 5: desc.c_cflag |= (CSIZE & CS5); break;
|
||||
case 6: desc.c_cflag |= (CSIZE & CS6); break;
|
||||
case 7: desc.c_cflag |= (CSIZE & CS7); break;
|
||||
case 8: default: desc.c_cflag |= (CSIZE & CS8); break;
|
||||
case 5: PRIVATE->desc.c_cflag |= (CSIZE & CS5); break;
|
||||
case 6: PRIVATE->desc.c_cflag |= (CSIZE & CS6); break;
|
||||
case 7: PRIVATE->desc.c_cflag |= (CSIZE & CS7); break;
|
||||
case 8: default: PRIVATE->desc.c_cflag |= (CSIZE & CS8); break;
|
||||
};
|
||||
if (isReadable()) desc.c_cflag |= CREAD;
|
||||
if (isReadable()) PRIVATE->desc.c_cflag |= CREAD;
|
||||
PIFlags<Parameters> params = parameters();
|
||||
if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB;
|
||||
if (params[PISerial::TwoStopBits]) PRIVATE->desc.c_cflag |= CSTOPB;
|
||||
if (params[PISerial::ParityControl]) {
|
||||
desc.c_iflag |= INPCK;
|
||||
desc.c_cflag |= PARENB;
|
||||
if (params[PISerial::ParityOdd]) desc.c_cflag |= PARODD;
|
||||
PRIVATE->desc.c_iflag |= INPCK;
|
||||
PRIVATE->desc.c_cflag |= PARENB;
|
||||
if (params[PISerial::ParityOdd]) PRIVATE->desc.c_cflag |= PARODD;
|
||||
}
|
||||
desc.c_cc[VMIN] = 1;
|
||||
desc.c_cc[VTIME] = vtime;
|
||||
PRIVATE->desc.c_cc[VMIN] = 1;
|
||||
PRIVATE->desc.c_cc[VTIME] = vtime;
|
||||
|
||||
cfsetispeed(&desc, convertSpeed(inSpeed()));
|
||||
cfsetospeed(&desc, convertSpeed(outSpeed()));
|
||||
cfsetispeed(&PRIVATE->desc, convertSpeed(inSpeed()));
|
||||
cfsetospeed(&PRIVATE->desc, convertSpeed(outSpeed()));
|
||||
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
fcntl(fd, F_SETFL, block_read ? 0 : O_NONBLOCK);
|
||||
|
||||
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
|
||||
if(tcsetattr(fd, TCSANOW, &PRIVATE->desc) < 0) {
|
||||
piCoutObj << "Can`t set attributes for \"" << path() << "\"";
|
||||
return;
|
||||
}
|
||||
@@ -457,7 +561,7 @@ void PISerial::setReadIsBlocking(bool yes) {
|
||||
times.ReadTotalTimeoutMultiplier = block_read ? 0 : MAXDWORD;
|
||||
times.WriteTotalTimeoutConstant = 0;
|
||||
times.WriteTotalTimeoutMultiplier = block_write ? 0 : 1;
|
||||
if (isOpened()) SetCommTimeouts(hCom, ×);
|
||||
if (isOpened()) SetCommTimeouts(PRIVATE->hCom, ×);
|
||||
#else
|
||||
if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK);
|
||||
#endif
|
||||
@@ -472,9 +576,9 @@ void PISerial::setReadIsBlocking(bool yes) {
|
||||
int PISerial::read(void * read_to, int max_size) {
|
||||
#ifdef WINDOWS
|
||||
if (!canRead()) return -1;
|
||||
WaitCommEvent(hCom, 0, 0);
|
||||
ReadFile(hCom, read_to, max_size, &readed, 0);
|
||||
return readed;
|
||||
WaitCommEvent(PRIVATE->hCom, 0, 0);
|
||||
ReadFile(PRIVATE->hCom, read_to, max_size, &PRIVATE->readed, 0);
|
||||
return PRIVATE->readed;
|
||||
#else
|
||||
if (!canRead()) return -1;
|
||||
return ::read(fd, read_to, max_size);
|
||||
@@ -494,7 +598,7 @@ int PISerial::write(const void * data, int max_size, bool wait) {
|
||||
setReadIsBlocking(block_read);
|
||||
}
|
||||
DWORD wrote;
|
||||
WriteFile(hCom, data, max_size, &wrote, 0);
|
||||
WriteFile(PRIVATE->hCom, data, max_size, &wrote, 0);
|
||||
#else
|
||||
int wrote;
|
||||
wrote = ::write(fd, data, max_size);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
COM
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
|
||||
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
|
||||
@@ -25,71 +25,6 @@
|
||||
|
||||
#include "pitimer.h"
|
||||
#include "piiodevice.h"
|
||||
#ifndef WINDOWS
|
||||
# include <termios.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/ioctl.h>
|
||||
# ifndef B50
|
||||
# define B50 0000001
|
||||
# endif
|
||||
# ifndef B75
|
||||
# define B75 0000002
|
||||
# endif
|
||||
# ifndef B1500000
|
||||
# define B1500000 0010012
|
||||
# endif
|
||||
# ifndef B2000000
|
||||
# define B2000000 0010013
|
||||
# endif
|
||||
# ifndef B2500000
|
||||
# define B2500000 0010014
|
||||
# endif
|
||||
# ifndef B3000000
|
||||
# define B3000000 0010015
|
||||
# endif
|
||||
# ifndef B3500000
|
||||
# define B3500000 0010016
|
||||
# endif
|
||||
# ifndef B4000000
|
||||
# define B4000000 0010017
|
||||
# endif
|
||||
#else
|
||||
# define TIOCM_LE 1
|
||||
# define TIOCM_DTR 4
|
||||
# define TIOCM_RTS 7
|
||||
# define TIOCM_CTS 8
|
||||
# define TIOCM_ST 3
|
||||
# define TIOCM_SR 2
|
||||
# define TIOCM_CAR 1
|
||||
# define TIOCM_RNG 9
|
||||
# define TIOCM_DSR 6
|
||||
# define B50 50
|
||||
# define B75 75
|
||||
# define B110 110
|
||||
# define B300 300
|
||||
# define B600 600
|
||||
# define B1200 1200
|
||||
# define B2400 2400
|
||||
# define B4800 4800
|
||||
# define B9600 9600
|
||||
# define B14400 14400
|
||||
# define B19200 19200
|
||||
# define B38400 38400
|
||||
# define B57600 57600
|
||||
# define B115200 115200
|
||||
# define B128000 128000
|
||||
# define B256000 256000
|
||||
# define B1500000 1500000
|
||||
# define B2000000 2000000
|
||||
# define B2500000 2500000
|
||||
# define B3000000 3000000
|
||||
# define B3500000 3500000
|
||||
# define B4000000 4000000
|
||||
#endif
|
||||
#ifndef CRTSCTS
|
||||
# define CRTSCTS 020000000000
|
||||
#endif
|
||||
|
||||
|
||||
class PIP_EXPORT PISerial: public PIIODevice
|
||||
{
|
||||
@@ -97,7 +32,7 @@ class PIP_EXPORT PISerial: public PIIODevice
|
||||
public:
|
||||
|
||||
//! Contructs an empty %PISerial
|
||||
PISerial();
|
||||
explicit PISerial();
|
||||
|
||||
//! \brief Parameters of PISerial
|
||||
enum Parameters {
|
||||
@@ -130,7 +65,7 @@ public:
|
||||
};
|
||||
|
||||
//! Contructs %PISerial with device name "device", speed "speed" and parameters "params"
|
||||
PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags<PISerial::Parameters> params = 0);
|
||||
explicit PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags<PISerial::Parameters> params = 0);
|
||||
|
||||
~PISerial();
|
||||
|
||||
@@ -174,25 +109,25 @@ public:
|
||||
//! Returns pin number "number" logic level. Valid numbers range is from 1 to 9
|
||||
bool isPin(int number) const;
|
||||
|
||||
bool setLE(bool on) {return setBit(TIOCM_LE, on, "LE");} // useless function, just formally
|
||||
bool setDTR(bool on) {return setBit(TIOCM_DTR, on, "DTR");}
|
||||
bool setRTS(bool on) {return setBit(TIOCM_RTS, on, "RTS");}
|
||||
bool setCTS(bool on) {return setBit(TIOCM_CTS, on, "CTS");} // useless function, just formally
|
||||
bool setST(bool on) {return setBit(TIOCM_ST, on, "ST");} // useless function, just formally
|
||||
bool setSR(bool on) {return setBit(TIOCM_SR, on, "SR");} // useless function, just formally
|
||||
bool setCAR(bool on) {return setBit(TIOCM_CAR, on, "CAR");} // useless function, just formally
|
||||
bool setRNG(bool on) {return setBit(TIOCM_RNG, on, "RNG");} // useless function, just formally
|
||||
bool setDSR(bool on) {return setBit(TIOCM_DSR, on, "DSR");} // useless function, just formally
|
||||
bool setLE(bool on); // useless function, just formally
|
||||
bool setDTR(bool on);
|
||||
bool setRTS(bool on);
|
||||
bool setCTS(bool on); // useless function, just formally
|
||||
bool setST(bool on); // useless function, just formally
|
||||
bool setSR(bool on); // useless function, just formally
|
||||
bool setCAR(bool on); // useless function, just formally
|
||||
bool setRNG(bool on); // useless function, just formally
|
||||
bool setDSR(bool on); // useless function, just formally
|
||||
|
||||
bool isLE() const {return isBit(TIOCM_LE, "LE");}
|
||||
bool isDTR() const {return isBit(TIOCM_DTR, "DTR");}
|
||||
bool isRTS() const {return isBit(TIOCM_RTS, "RTS");}
|
||||
bool isCTS() const {return isBit(TIOCM_CTS, "CTS");}
|
||||
bool isST() const {return isBit(TIOCM_ST, "ST");}
|
||||
bool isSR() const {return isBit(TIOCM_SR, "SR");}
|
||||
bool isCAR() const {return isBit(TIOCM_CAR, "CAR");}
|
||||
bool isRNG() const {return isBit(TIOCM_RNG, "RNG");}
|
||||
bool isDSR() const {return isBit(TIOCM_DSR, "DSR");}
|
||||
bool isLE() const;
|
||||
bool isDTR() const;
|
||||
bool isRTS() const;
|
||||
bool isCTS() const;
|
||||
bool isST() const;
|
||||
bool isSR() const;
|
||||
bool isCAR() const;
|
||||
bool isRNG() const;
|
||||
bool isDSR() const;
|
||||
|
||||
void setVTime(int t) {vtime = t; applySettings();}
|
||||
|
||||
@@ -214,11 +149,8 @@ public:
|
||||
|
||||
|
||||
//! Discard all buffered input and output data
|
||||
void flush() {
|
||||
#ifndef WINDOWS
|
||||
if (fd != -1) tcflush(fd, TCIOFLUSH);
|
||||
#endif
|
||||
}
|
||||
void flush();
|
||||
|
||||
|
||||
int read(void * read_to, int max_size);
|
||||
bool read(void * read_to, int max_size, double timeout_ms);
|
||||
@@ -292,17 +224,9 @@ protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
|
||||
#ifdef WINDOWS
|
||||
DCB desc, sdesc;
|
||||
void * hCom;
|
||||
DWORD readed, mask;
|
||||
bool block_write;
|
||||
#else
|
||||
termios desc, sdesc;
|
||||
uint readed;
|
||||
#endif
|
||||
PRIVATE_DECLARATION
|
||||
int fd, vtime;
|
||||
bool block_read;
|
||||
bool block_read, block_write;
|
||||
PITimeMeasurer tm_;
|
||||
|
||||
};
|
||||
|
||||
@@ -348,41 +348,41 @@ void PIUSB::flush() {
|
||||
|
||||
PICout operator<<(PICout s, const PIUSB::Endpoint & v) {
|
||||
s.setControl(0, true);
|
||||
s << NewLine << "{" << NewLine;
|
||||
s << PICoutManipulators::NewLine << "{" << PICoutManipulators::NewLine;
|
||||
if (v.isNull())
|
||||
s << " " << "Null Endpoint";
|
||||
else {
|
||||
s << " " << "Address: " << v.address << NewLine;
|
||||
s << " " << "Attributes: " << v.attributes << NewLine;
|
||||
s << " " << "Direction: " << (v.direction == PIUSB::Endpoint::Write ? "Write" : "Read") << NewLine;
|
||||
s << " " << "Address: " << v.address << PICoutManipulators::NewLine;
|
||||
s << " " << "Attributes: " << v.attributes << PICoutManipulators::NewLine;
|
||||
s << " " << "Direction: " << (v.direction == PIUSB::Endpoint::Write ? "Write" : "Read") << PICoutManipulators::NewLine;
|
||||
s << " " << "Transfer Type: ";
|
||||
switch (v.transfer_type) {
|
||||
case PIUSB::Endpoint::Control: s << "Control" << NewLine; break;
|
||||
case PIUSB::Endpoint::Bulk: s << "Bulk" << NewLine; break;
|
||||
case PIUSB::Endpoint::Interrupt: s << "Interrupt" << NewLine; break;
|
||||
case PIUSB::Endpoint::Isochronous: s << "Isochronous" << NewLine; break;
|
||||
case PIUSB::Endpoint::Control: s << "Control" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::Bulk: s << "Bulk" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::Interrupt: s << "Interrupt" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::Isochronous: s << "Isochronous" << PICoutManipulators::NewLine; break;
|
||||
default: break;
|
||||
}
|
||||
if (v.transfer_type == PIUSB::Endpoint::Isochronous) {
|
||||
s << " " << "Synchronisation Type: ";
|
||||
switch (v.synchronisation_type) {
|
||||
case PIUSB::Endpoint::NoSynchonisation: s << "No Synchonisation" << NewLine; break;
|
||||
case PIUSB::Endpoint::Asynchronous: s << "Asynchronous" << NewLine; break;
|
||||
case PIUSB::Endpoint::Adaptive: s << "Adaptive" << NewLine; break;
|
||||
case PIUSB::Endpoint::Synchronous: s << "Synchronous" << NewLine; break;
|
||||
case PIUSB::Endpoint::NoSynchonisation: s << "No Synchonisation" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::Asynchronous: s << "Asynchronous" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::Adaptive: s << "Adaptive" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::Synchronous: s << "Synchronous" << PICoutManipulators::NewLine; break;
|
||||
default: break;
|
||||
}
|
||||
s << " " << "Usage Type: ";
|
||||
switch (v.usage_type) {
|
||||
case PIUSB::Endpoint::DataEndpoint: s << "Data Endpoint" << NewLine; break;
|
||||
case PIUSB::Endpoint::FeedbackEndpoint: s << "Feedback Endpoint" << NewLine; break;
|
||||
case PIUSB::Endpoint::ExplicitFeedbackDataEndpoint: s << "Explicit Feedback Data Endpoint" << NewLine; break;
|
||||
case PIUSB::Endpoint::DataEndpoint: s << "Data Endpoint" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::FeedbackEndpoint: s << "Feedback Endpoint" << PICoutManipulators::NewLine; break;
|
||||
case PIUSB::Endpoint::ExplicitFeedbackDataEndpoint: s << "Explicit Feedback Data Endpoint" << PICoutManipulators::NewLine; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
s << " " << "Max Packet Size: " << v.max_packet_size << NewLine;
|
||||
s << " " << "Max Packet Size: " << v.max_packet_size << PICoutManipulators::NewLine;
|
||||
}
|
||||
s << "}" << NewLine;
|
||||
s << "}" << PICoutManipulators::NewLine;
|
||||
s.restoreControl();
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
USB, based on libusb
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user