Refactor for a central include directory

This commit is contained in:
Paul Hollinsky
2018-10-22 11:52:34 -04:00
parent 12451def11
commit 8e6b0d0b0e
127 changed files with 263 additions and 265 deletions
+17
View File
@@ -0,0 +1,17 @@
#ifndef __COMMAND_H_
#define __COMMAND_H_
namespace icsneo {
enum class Command : uint8_t {
EnableNetworkCommunication = 0x07,
RequestSerialNumber = 0xA1,
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
GetSettings = 0xA5, // Previously known as RED_CMD_READ_BAUD_REQ
SaveSettings = 0xA6,
SetDefaultSettings = 0xA8 // Follow up with SaveSettings to write to EEPROM
};
}
#endif
@@ -0,0 +1,69 @@
#ifndef __COMMUNICATION_H_
#define __COMMUNICATION_H_
#include "icsneo/communication/icommunication.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/packet.h"
#include "icsneo/communication/message/callback/messagecallback.h"
#include "icsneo/communication/message/serialnumbermessage.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/encoder.h"
#include "icsneo/communication/decoder.h"
#include <memory>
#include <vector>
#include <atomic>
#include <thread>
#include <queue>
#include <map>
namespace icsneo {
class Communication {
public:
Communication(
std::unique_ptr<ICommunication> com,
std::shared_ptr<Packetizer> p,
std::unique_ptr<Encoder> e,
std::unique_ptr<Decoder> md) : packetizer(p), encoder(std::move(e)), decoder(std::move(md)), impl(std::move(com)) {}
virtual ~Communication() { close(); }
bool open();
bool close();
virtual void spawnThreads();
virtual void joinThreads();
bool rawWrite(const std::vector<uint8_t>& bytes) { return impl->write(bytes); }
virtual bool sendPacket(std::vector<uint8_t>& bytes);
virtual bool sendCommand(Command cmd, bool boolean) { return sendCommand(cmd, std::vector<uint8_t>({ (uint8_t)boolean })); }
virtual bool sendCommand(Command cmd, std::vector<uint8_t> arguments = {});
bool getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
std::shared_ptr<SerialNumberMessage> getSerialNumberSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
int addMessageCallback(const MessageCallback& cb);
bool removeMessageCallback(int id);
std::shared_ptr<Message> waitForMessageSync(MessageFilter f = MessageFilter(), std::chrono::milliseconds timeout = std::chrono::milliseconds(50)) {
return waitForMessageSync(std::make_shared<MessageFilter>(f), timeout);
}
std::shared_ptr<Message> waitForMessageSync(std::shared_ptr<MessageFilter> f, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
std::shared_ptr<Packetizer> packetizer; // Ownership is shared with the encoder
std::unique_ptr<Encoder> encoder;
std::unique_ptr<Decoder> decoder;
protected:
std::unique_ptr<ICommunication> impl;
static int messageCallbackIDCounter;
std::map<int, MessageCallback> messageCallbacks;
std::atomic<bool> closing{false};
private:
bool isOpen = false;
std::thread readTaskThread;
void readTask();
};
}
#endif
+97
View File
@@ -0,0 +1,97 @@
#ifndef __DECODER_H_
#define __DECODER_H_
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/message/canmessage.h"
#include "icsneo/communication/packet.h"
#include "icsneo/communication/network.h"
#include <queue>
#include <vector>
#include <memory>
#pragma pack(push, 1)
namespace icsneo {
class Decoder {
public:
static uint64_t GetUInt64FromLEBytes(uint8_t* bytes);
bool decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet);
private:
typedef uint16_t icscm_bitfield;
struct HardwareCANPacket {
struct {
icscm_bitfield IDE : 1;
icscm_bitfield SRR : 1;
icscm_bitfield SID : 11;
icscm_bitfield EDL : 1;
icscm_bitfield BRS : 1;
icscm_bitfield ESI : 1;
} header;
struct {
icscm_bitfield EID : 12;
icscm_bitfield TXMSG : 1;
icscm_bitfield TXAborted : 1;
icscm_bitfield TXLostArb : 1;
icscm_bitfield TXError : 1;
} eid;
struct {
icscm_bitfield DLC : 4;
icscm_bitfield RB0 : 1;
icscm_bitfield IVRIF : 1;
icscm_bitfield HVEnable : 1;// must be cleared before passing into CAN driver
icscm_bitfield ExtendedNetworkIndexBit : 1;//DO NOT CLOBBER THIS
icscm_bitfield RB1 : 1;
icscm_bitfield RTR : 1;
icscm_bitfield EID2 : 6;
} dlc;
unsigned char data[8];
uint16_t stats;
struct {
uint64_t TS : 60;
uint64_t : 3; // Reserved for future status bits
uint64_t IsExtended : 1;
} timestamp;
};
union CoreMiniStatusBits_t {
struct {
unsigned just_reset : 1;
unsigned com_enabled : 1;
unsigned cm_is_running : 1;
unsigned cm_checksum_failed : 1;
unsigned cm_license_failed : 1;
unsigned cm_version_mismatch : 1;
unsigned cm_boot_off : 1;
unsigned hardware_failure : 1;//to check SRAM failure (for now)
unsigned isPassiveConnect : 1;///< Always zero. Set to one when neoVI connection is passive,i.e. no async traffic
unsigned usbComEnabled : 1;///< Set to one when USB Host PC has enabled communication.
unsigned linuxComEnabled : 1;///< Set to one when Android (Linux) has enabled communication.
unsigned cm_too_big : 1;
unsigned hidUsbState : 1;
unsigned fpgaUsbState : 1;
unsigned reserved : 2;
};
uint32_t dword;
};
struct HardwareResetStatusPacket {
uint16_t main_loop_time_25ns;
uint16_t max_main_loop_time_25ns;
CoreMiniStatusBits_t status;
uint8_t histo[6];//!< Can hold histogram performance data.
uint16_t spi1Kbps;//!< Spi1's kbps throughput.
uint16_t initBits;//!< Bitfield with init states of drivers, 1 is succes, 0 is fail.
uint16_t cpuMipsH;
uint16_t cpuMipsL;
uint16_t busVoltage;
uint16_t deviceTemperature;
};
};
}
#pragma pack(pop)
#endif
+34
View File
@@ -0,0 +1,34 @@
#ifndef __ENCODER_H_
#define __ENCODER_H_
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/message/canmessage.h"
#include "icsneo/communication/packet.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/packetizer.h"
#include <queue>
#include <vector>
#include <memory>
#pragma pack(push, 1)
namespace icsneo {
class Encoder {
public:
Encoder(std::shared_ptr<Packetizer> packetizerInstance) : packetizer(packetizerInstance) {}
bool encode(std::vector<uint8_t>& result, const std::shared_ptr<Message>& message);
bool encode(std::vector<uint8_t>& result, Command cmd, bool boolean) { return encode(result, cmd, std::vector<uint8_t>({ (uint8_t)boolean })); }
bool encode(std::vector<uint8_t>& result, Command cmd, std::vector<uint8_t> arguments = {});
bool supportCANFD = false;
private:
std::shared_ptr<Packetizer> packetizer;
};
}
#pragma pack(pop)
#endif
@@ -0,0 +1,43 @@
#ifndef __ICOMMUNICATION_H_
#define __ICOMMUNICATION_H_
#include <vector>
#include <chrono>
#include <atomic>
#include <thread>
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
namespace icsneo {
class ICommunication {
public:
virtual ~ICommunication() {}
virtual bool open() = 0;
virtual bool isOpen() = 0;
virtual bool close() = 0;
virtual bool read(std::vector<uint8_t>& bytes, size_t limit = 0);
virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0);
virtual bool write(const std::vector<uint8_t>& bytes);
protected:
class WriteOperation {
public:
WriteOperation() {}
WriteOperation(std::vector<uint8_t> b) { bytes = b; }
std::vector<uint8_t> bytes;
};
enum IOTaskState {
LAUNCH,
WAIT
};
virtual void readTask() = 0;
virtual void writeTask() = 0;
moodycamel::BlockingConcurrentQueue<uint8_t> readQueue;
moodycamel::BlockingConcurrentQueue<WriteOperation> writeQueue;
std::thread readThread, writeThread;
std::atomic<bool> closing{false};
};
}
#endif
@@ -0,0 +1,23 @@
#ifndef __CANMESSAGECALLBACK_H_
#define __CANMESSAGECALLBACK_H_
#include "icsneo/communication/message/callback/messagecallback.h"
#include "icsneo/communication/message/canmessage.h"
#include "icsneo/communication/message/filter/canmessagefilter.h"
#include <memory>
namespace icsneo {
class CANMessageCallback : public MessageCallback {
public:
CANMessageCallback(fn_messageCallback cb, std::shared_ptr<CANMessageFilter> f) : MessageCallback(cb, f) {}
CANMessageCallback(fn_messageCallback cb, CANMessageFilter f = CANMessageFilter()) : MessageCallback(cb, std::make_shared<CANMessageFilter>(f)) {}
// Allow the filter to be placed first if the user wants (maybe in the case of a lambda)
CANMessageCallback(std::shared_ptr<CANMessageFilter> f, fn_messageCallback cb) : MessageCallback(cb, f) {}
CANMessageCallback(CANMessageFilter f, fn_messageCallback cb) : MessageCallback(cb, std::make_shared<CANMessageFilter>(f)) {}
};
};
#endif
@@ -0,0 +1,23 @@
#ifndef __MAIN51MESSAGECALLBACK_H_
#define __MAIN51MESSAGECALLBACK_H_
#include "icsneo/communication/message/callback/messagecallback.h"
#include "icsneo/communication/message/main51message.h"
#include "icsneo/communication/message/filter/main51messagefilter.h"
#include <memory>
namespace icsneo {
class Main51MessageCallback : public MessageCallback {
public:
Main51MessageCallback(fn_messageCallback cb, std::shared_ptr<Main51MessageFilter> f) : MessageCallback(cb, f) {}
Main51MessageCallback(fn_messageCallback cb, Main51MessageFilter f = Main51MessageFilter()) : MessageCallback(cb, std::make_shared<Main51MessageFilter>(f)) {}
// Allow the filter to be placed first if the user wants (maybe in the case of a lambda)
Main51MessageCallback(std::shared_ptr<Main51MessageFilter> f, fn_messageCallback cb) : MessageCallback(cb, f) {}
Main51MessageCallback(Main51MessageFilter f, fn_messageCallback cb) : MessageCallback(cb, std::make_shared<Main51MessageFilter>(f)) {}
};
};
#endif
@@ -0,0 +1,38 @@
#ifndef __MESSAGECALLBACK_H_
#define __MESSAGECALLBACK_H_
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/message/filter/messagefilter.h"
#include <memory>
#include <functional>
namespace icsneo {
class MessageCallback {
public:
typedef std::function< void( std::shared_ptr<Message> ) > fn_messageCallback;
MessageCallback(fn_messageCallback cb, std::shared_ptr<MessageFilter> f) : callback(cb), filter(f) {}
MessageCallback(fn_messageCallback cb, MessageFilter f = MessageFilter()) : callback(cb), filter(std::make_shared<MessageFilter>(f)) {}
// Allow the filter to be placed first if the user wants (maybe in the case of a lambda)
MessageCallback(std::shared_ptr<MessageFilter> f, fn_messageCallback cb) : callback(cb), filter(f) {}
MessageCallback(MessageFilter f, fn_messageCallback cb) : callback(cb), filter(std::make_shared<MessageFilter>(f)) {}
virtual bool callIfMatch(const std::shared_ptr<Message>& message) const {
bool ret = filter->match(message);
if(ret)
callback(message);
return ret;
}
const MessageFilter& getFilter() const { return *filter; }
const fn_messageCallback& getCallback() const { return callback; }
protected:
fn_messageCallback callback;
std::shared_ptr<MessageFilter> filter;
};
}
#endif
@@ -0,0 +1,20 @@
#ifndef __CANMESSAGE_H_
#define __CANMESSAGE_H_
#include "icsneo/communication/message/message.h"
namespace icsneo {
class CANMessage : public Message {
public:
uint32_t arbid;
uint8_t dlcOnWire;
bool isRemote = false;
bool isExtended = false;
bool isCANFD = false;
bool baudrateSwitch = false; // CAN FD only
};
}
#endif
@@ -0,0 +1,38 @@
#ifndef __CANMESSAGEFILTER_H_
#define __CANMESSAGEFILTER_H_
#include "icsneo/communication/message/filter/messagefilter.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/message/canmessage.h"
#include <memory>
namespace icsneo {
class CANMessageFilter : public MessageFilter {
public:
CANMessageFilter() : MessageFilter(Network::Type::CAN), arbid(INVALID_ARBID) {}
CANMessageFilter(uint32_t arbid) : MessageFilter(Network::Type::CAN), arbid(arbid) {}
bool match(const std::shared_ptr<Message>& message) const {
if(!MessageFilter::match(message))
return false;
const auto canMessage = std::dynamic_pointer_cast<CANMessage>(message);
if(canMessage == nullptr || !matchArbID(canMessage->arbid))
return false;
return true;
}
private:
static constexpr uint32_t INVALID_ARBID = 0xffffffff;
uint32_t arbid;
bool matchArbID(uint32_t marbid) const {
if(arbid == INVALID_ARBID)
return true;
return arbid == marbid;
}
};
};
#endif
@@ -0,0 +1,46 @@
#ifndef __MAIN51MESSAGEFILTER_H_
#define __MAIN51MESSAGEFILTER_H_
#include "icsneo/communication/message/filter/messagefilter.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/communication.h"
#include "icsneo/communication/message/main51message.h"
#include <memory>
#include <iostream>
namespace icsneo {
class Main51MessageFilter : public MessageFilter {
public:
Main51MessageFilter() : MessageFilter(Network::NetID::Main51), command(INVALID_COMMAND) {}
Main51MessageFilter(Command command) : MessageFilter(Network::NetID::Main51), command(command) {}
bool match(const std::shared_ptr<Message>& message) const {
if(!MessageFilter::match(message)) {
//std::cout << "message filter did not match base for " << message->network << std::endl;
return false;
}
const auto main51Message = std::dynamic_pointer_cast<Main51Message>(message);
if(!main51Message)
std::cout << "could not upcast " << message->network << std::endl;
if(main51Message == nullptr || !matchCommand(main51Message->command)) {
if(main51Message)
std::cout << "Could not match command " << (int)(command) << " to " << (int)(main51Message->command) << std::endl;
return false;
}
return true;
}
private:
static constexpr Command INVALID_COMMAND = (Command)0xff;
Command command;
bool matchCommand(Command mcommand) const {
if(command == INVALID_COMMAND)
return true;
return command == mcommand;
}
};
}
#endif
@@ -0,0 +1,45 @@
#ifndef __MESSAGEFILTER_H_
#define __MESSAGEFILTER_H_
#include "icsneo/communication/network.h"
#include "icsneo/communication/message/message.h"
#include <memory>
namespace icsneo {
class MessageFilter {
public:
MessageFilter() {}
MessageFilter(Network::Type type) : type(type) {}
MessageFilter(Network::NetID netid) : netid(netid) {}
virtual ~MessageFilter() {}
// When getting "all" types of messages, include the ones marked as "internal only"
bool includeInternalInAny = false;
virtual bool match(const std::shared_ptr<Message>& message) const {
if(!matchType(message->network.getType()))
return false;
if(!matchNetID(message->network.getNetID()))
return false;
return true;
}
private:
Network::Type type = Network::Type::Any;
bool matchType(Network::Type mtype) const {
if(type == Network::Type::Any && (mtype != Network::Type::Internal || includeInternalInAny))
return true;
return type == mtype;
}
Network::NetID netid = Network::NetID::Any;
bool matchNetID(Network::NetID mnetid) const {
if(netid == Network::NetID::Any)
return true;
return netid == mnetid;
}
};
}
#endif
@@ -0,0 +1,17 @@
#ifndef __MAIN51MESSAGE_H_
#define __MAIN51MESSAGE_H_
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/communication.h"
namespace icsneo {
class Main51Message : public Message {
public:
virtual ~Main51Message() = default;
Command command;
};
}
#endif
@@ -0,0 +1,19 @@
#ifndef __MESSAGE_H_
#define __MESSAGE_H_
#include "icsneo/communication/network.h"
#include <vector>
namespace icsneo {
class Message {
public:
virtual ~Message() = default;
Network network;
std::vector<uint8_t> data;
uint64_t timestamp;
};
}
#endif
@@ -0,0 +1,135 @@
#ifndef __NEOMESSAGE_H_
#define __NEOMESSAGE_H_
#include <stdint.h>
#include <stddef.h>
#pragma pack(push, 1)
typedef union {
struct {
uint32_t globalError : 1;
uint32_t transmitMessage : 1;
uint32_t extendedFrame : 1;
uint32_t remoteFrame : 1;
uint32_t crcError : 1;
uint32_t canErrorPassive : 1;
uint32_t incompleteFrame : 1;
uint32_t lostArbitration : 1;
uint32_t undefinedError : 1;
uint32_t canBusOff : 1;
uint32_t canErrorWarning : 1;
uint32_t canBusShortedPlus : 1;
uint32_t canBusShortedGround : 1;
uint32_t checksumError : 1;
uint32_t badMessageBitTimeError : 1;
uint32_t ifrData : 1;
uint32_t hardwareCommError : 1;
uint32_t expectedLengthError : 1;
uint32_t incomingNoMatch : 1;
uint32_t statusBreak : 1;
uint32_t avsiRecOverflow : 1;
uint32_t testTrigger : 1;
uint32_t audioComment : 1;
uint32_t gpsData : 1;
uint32_t analogDigitalInput : 1;
uint32_t textComment : 1;
uint32_t networkMessageType : 1;
uint32_t vsiTXUnderrun : 1;
uint32_t vsiIFRCRCBit : 1;
uint32_t initMessage : 1;
//uint32_t highSpeedMessage : 1; // Occupies the same space as flexraySecondStartupFrame
uint32_t flexraySecondStartupFrame : 1;
uint32_t extended : 1;
// ~~~ End of bitfield 1 ~~~
uint32_t hasValue : 1;
uint32_t valueIsBoolean : 1;
uint32_t highVoltage : 1;
uint32_t longMessage : 1;
uint32_t : 12;
uint32_t globalChange : 1;
uint32_t errorFrame : 1;
uint32_t : 2;
uint32_t endOfLongMessage : 1;
uint32_t linErrorRXBreakNotZero : 1;
uint32_t linErrorRXBreakTooShort : 1;
uint32_t linErrorRXSyncNot55 : 1;
uint32_t linErrorRXDataGreaterEight : 1;
uint32_t linErrorTXRXMismatch : 1;
uint32_t linErrorMessageIDParity : 1;
//isoFrameError
uint32_t linSyncFrameError : 1;
//isoOverflowError
uint32_t linIDFrameError : 1;
//isoParityError
uint32_t linSlaveByteError : 1;
uint32_t rxTimeoutError : 1;
uint32_t linNoSlaveData : 1;
// mostPacketData
// mostStatus
// mostLowLevel
// mostControlData
// mostMHPUserData
// mostMHPControlData
// mostI2SDump
// mostTooShort
// most50
// most150
// mostChangedParameter
// ethernetCRCError
// ethernetFrameTooShort
// ethernetFCSAvailable
// ~~~ End of bitfield 2 ~~~
//uint32_t linJustBreakSync : 1;
//uint32_t linSlaveDataTooShort : 1;
//uint32_t linOnlyUpdateSlaveTableOnce : 1;
uint32_t canfdESI : 1;
uint32_t canfdIDE : 1;
uint32_t canfdRTR : 1;
uint32_t canfdFDF : 1;
uint32_t canfdBRS : 1;
};
uint32_t statusBitfield[4];
} neomessage_statusbitfield_t;
typedef struct {
neomessage_statusbitfield_t status;
uint64_t timestamp;
const uint8_t* data;
size_t length;
uint8_t header[4];
uint16_t netid;
uint8_t type;
uint8_t reserved[9];
} neomessage_t;
// Any time you add another neomessage_*_t type, make sure to add it to the static_asserts below!
typedef struct {
neomessage_statusbitfield_t status;
uint64_t timestamp;
const uint8_t* data;
size_t length;
uint32_t arbid;
uint16_t netid;
uint8_t type;
uint8_t dlcOnWire;
char reserved[8];
} neomessage_can_t;
#pragma pack(pop)
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include <memory>
static_assert(sizeof(neomessage_can_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size!");
namespace icsneo {
neomessage_t CreateNeoMessage(const std::shared_ptr<Message> message);
std::shared_ptr<Message> CreateMessageFromNeoMessage(const neomessage_t* neomessage);
}
#endif
#endif
@@ -0,0 +1,35 @@
#ifndef __RESETSTATUSMESSAGE_H_
#define __RESETSTATUSMESSAGE_H_
#include "icsneo/communication/message/main51message.h"
#include "icsneo/communication/command.h"
#include <string>
namespace icsneo {
class ResetStatusMessage : public Message {
public:
ResetStatusMessage() : Message() {}
virtual ~ResetStatusMessage() = default;
uint16_t mainLoopTime;
uint16_t maxMainLoopTime;
bool justReset;
bool comEnabled;
bool cmRunning;
bool cmChecksumFailed;
bool cmLicenseFailed;
bool cmVersionMismatch;
bool cmBootOff;
bool hardwareFailure;
bool usbComEnabled;
bool linuxComEnabled;
bool cmTooBig;
bool hidUsbState;
bool fpgaUsbState;
uint16_t busVoltage;
uint16_t deviceTemperature;
};
}
#endif
@@ -0,0 +1,24 @@
#ifndef __SERIALNUMBERMESSAGE_H_
#define __SERIALNUMBERMESSAGE_H_
#include "icsneo/communication/message/main51message.h"
#include "icsneo/communication/command.h"
#include <string>
namespace icsneo {
// The response for Command::RequestSerialNumber
class SerialNumberMessage : public Main51Message {
public:
SerialNumberMessage() : Main51Message() { command = Command::RequestSerialNumber; }
virtual ~SerialNumberMessage() = default;
std::string deviceSerial;
uint8_t macAddress[6]; // This might be all zeros even if `hasMacAddress` is true
bool hasMacAddress = false; // The message might not actually be long enough to contain a MAC address, in which case we mark this
uint8_t pcbSerial[16];
bool hasPCBSerial = false;
};
}
#endif
@@ -0,0 +1,108 @@
#ifndef __MULTICHANNELCOMMUNICATION_H_
#define __MULTICHANNELCOMMUNICATION_H_
#include "icsneo/communication/communication.h"
#include "icsneo/communication/icommunication.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/encoder.h"
namespace icsneo {
class MultiChannelCommunication : public Communication {
public:
MultiChannelCommunication(
std::unique_ptr<ICommunication> com,
std::shared_ptr<Packetizer> p,
std::unique_ptr<Encoder> e,
std::unique_ptr<Decoder> md) : Communication(std::move(com), p, std::move(e), std::move(md)) {}
void spawnThreads() override;
void joinThreads() override;
bool sendPacket(std::vector<uint8_t>& bytes) override;
protected:
bool preprocessPacket(std::deque<uint8_t>& usbReadFifo);
private:
enum class CommandType : uint8_t {
PlasmaReadRequest = 0x10, // Status read request to HSC
PlasmaStatusResponse = 0x11, // Status response by HSC
HostPC_to_Vnet1 = 0x20, // Host PC data to Vnet module-1
Vnet1_to_HostPC = 0x21, // Vnet module-1 data to host PC
HostPC_to_Vnet2 = 0x30, // Host PC data to Vnet module-2
Vnet2_to_HostPC = 0x31, // Vnet module-2 data to host PC
HostPC_to_Vnet3 = 0x40, // Host PC data to Vnet module-3
Vnet3_to_HostPC = 0x41, // Vnet module-3 data to host PC
HostPC_to_SDCC1 = 0x50, // Host PC data to write to SDCC-1
HostPC_from_SDCC1 = 0x51, // Host PC wants data read from SDCC-1
SDCC1_to_HostPC = 0x52, // SDCC-1 data to host PC
HostPC_to_SDCC2 = 0x60, // Host PC data to write to SDCC-2
HostPC_from_SDCC2 = 0x61, // Host PC wants data read from SDCC-2
SDCC2_to_HostPC = 0x62, // SDCC-2 data to host PC
PC_to_LSOC = 0x70, // Host PC data to LSOCC
LSOCC_to_PC = 0x71, // LSOCC data to host PC
HostPC_to_Microblaze = 0x80, // Host PC data to microblaze processor
Microblaze_to_HostPC = 0x81 // Microblaze processor data to host PC
};
static bool CommandTypeIsValid(CommandType cmd) {
switch(cmd) {
case CommandType::PlasmaReadRequest:
case CommandType::PlasmaStatusResponse:
case CommandType::HostPC_to_Vnet1:
case CommandType::Vnet1_to_HostPC:
case CommandType::HostPC_to_Vnet2:
case CommandType::Vnet2_to_HostPC:
case CommandType::HostPC_to_Vnet3:
case CommandType::Vnet3_to_HostPC:
case CommandType::HostPC_to_SDCC1:
case CommandType::HostPC_from_SDCC1:
case CommandType::SDCC1_to_HostPC:
case CommandType::HostPC_to_SDCC2:
case CommandType::HostPC_from_SDCC2:
case CommandType::SDCC2_to_HostPC:
case CommandType::PC_to_LSOC:
case CommandType::LSOCC_to_PC:
case CommandType::HostPC_to_Microblaze:
case CommandType::Microblaze_to_HostPC:
return true;
default:
return false;
}
}
static bool CommandTypeHasAddress(CommandType cmd) {
// Check CommandTypeIsValid before this, you will get false on an invalid command
switch(cmd) {
case CommandType::SDCC1_to_HostPC:
case CommandType::SDCC2_to_HostPC:
return true;
default:
return false;
}
}
static uint16_t CommandTypeDefinesLength(CommandType cmd) {
// Check CommandTypeIsValid before this, you will get 0 on an invalid command
switch(cmd) {
case CommandType::PlasmaStatusResponse:
return 2;
default:
return 0; // Length is defined by following bytes in message
}
}
enum class PreprocessState {
SearchForCommand,
ParseAddress,
ParseLength,
GetData
};
PreprocessState state = PreprocessState::SearchForCommand;
uint16_t currentCommandLength;
CommandType currentCommandType;
size_t currentReadIndex = 0;
std::thread mainChannelReadThread;
void readTask();
};
}
#endif
+415
View File
@@ -0,0 +1,415 @@
#ifndef __NETWORKID_H_
#define __NETWORKID_H_
#include <cstdint>
#include <ostream>
namespace icsneo {
class Network {
public:
enum class NetID : uint16_t {
Device = 0,
HSCAN = 1,
MSCAN = 2,
SWCAN = 3,
LSFTCAN = 4,
FordSCP = 5,
J1708 = 6,
Aux = 7,
J1850VPW = 8,
ISO = 9,
ISOPIC = 10,
Main51 = 11,
RED = 12,
SCI = 13,
ISO2 = 14,
ISO14230 = 15,
LIN = 16,
OP_Ethernet1 = 17,
OP_Ethernet2 = 18,
OP_Ethernet3 = 19,
// START Device Command Returns
// When we send a command, the device returns on one of these, depending on command
RED_EXT_MEMORYREAD = 20,
RED_INT_MEMORYREAD = 21,
RED_DFLASH_READ = 22,
RED_SDCARD_READ = 23,
CAN_ERRBITS = 24,
RED_DFLASH_WRITE_DONE = 25,
RED_WAVE_CAN1_LOGICAL = 26,
RED_WAVE_CAN2_LOGICAL = 27,
RED_WAVE_LIN1_LOGICAL = 28,
RED_WAVE_LIN2_LOGICAL = 29,
RED_WAVE_LIN1_ANALOG = 30,
RED_WAVE_LIN2_ANALOG = 31,
RED_WAVE_MISC_ANALOG = 32,
RED_WAVE_MISCDIO2_LOGICAL = 33,
RED_NETWORK_COM_ENABLE_EX = 34,
RED_NEOVI_NETWORK = 35,
RED_READ_BAUD_SETTINGS = 36,
RED_OLDFORMAT = 37,
RED_SCOPE_CAPTURE = 38,
RED_HARDWARE_EXCEP = 39,
RED_GET_RTC = 40,
// END Device Command Returns
ISO3 = 41,
HSCAN2 = 42,
HSCAN3 = 44,
OP_Ethernet4 = 45,
OP_Ethernet5 = 46,
ISO4 = 47,
LIN2 = 48,
LIN3 = 49,
LIN4 = 50,
// MOST = 51, Old and unused
RED_App_Error = 52,
CGI = 53,
Reset_Status = 54,
FB_Status = 55,
App_Signal_Status = 56,
Read_Datalink_Cm_Tx_Msg = 57,
Read_Datalink_Cm_Rx_Msg = 58,
Logging_Overflow = 59,
Read_Settings_Ex = 60,
HSCAN4 = 61,
HSCAN5 = 62,
RS232 = 63,
UART = 64,
UART2 = 65,
UART3 = 66,
UART4 = 67,
SWCAN2 = 68,
Ethernet_DAQ = 69,
Data_To_Host = 70,
TextAPI_To_Host = 71,
OP_Ethernet6 = 73,
Red_VBat = 74,
OP_Ethernet7 = 75,
OP_Ethernet8 = 76,
OP_Ethernet9 = 77,
OP_Ethernet10 = 78,
OP_Ethernet11 = 79,
FlexRay1a = 80,
FlexRay1b = 81,
FlexRay2a = 82,
FlexRay2b = 83,
LIN5 = 84,
FlexRay = 85,
FlexRay2 = 86,
OP_Ethernet12 = 87,
MOST25 = 90,
MOST50 = 91,
MOST150 = 92,
Ethernet = 93,
GMFSA = 94,
TCP = 95,
HSCAN6 = 96,
HSCAN7 = 97,
LIN6 = 98,
LSFTCAN2 = 99,
HW_COM_Latency_Test = 512,
Device_Status = 513,
Any = 0xfffe, // Never actually set as type, but used as flag for filtering
Invalid = 0xffff
};
enum class Type {
Invalid,
Internal, // Used for statuses that don't actually need to be transferred to the client application
CAN,
LIN,
FlexRay,
MOST,
Ethernet,
Other,
Any // Never actually set as type, but used as flag for filtering
};
static const char* GetTypeString(Type type) {
switch(type) {
case Type::CAN:
return "CAN";
case Type::LIN:
return "LIN";
case Type::FlexRay:
return "FlexRay";
case Type::MOST:
return "MOST";
case Type::Other:
return "Other";
case Type::Internal:
return "Internal";
case Type::Invalid:
default:
return "Invalid Type";
}
}
static Type GetTypeOfNetID(NetID netid) {
switch(netid) {
case NetID::HSCAN:
case NetID::MSCAN:
case NetID::SWCAN:
case NetID::LSFTCAN:
case NetID::HSCAN2:
case NetID::HSCAN3:
case NetID::HSCAN4:
case NetID::HSCAN5:
case NetID::SWCAN2:
case NetID::HSCAN6:
case NetID::HSCAN7:
case NetID::LSFTCAN2:
return Type::CAN;
case NetID::LIN:
case NetID::LIN2:
case NetID::LIN3:
case NetID::LIN4:
case NetID::LIN5:
case NetID::LIN6:
return Type::LIN;
case NetID::FlexRay:
case NetID::FlexRay1a:
case NetID::FlexRay1b:
case NetID::FlexRay2:
case NetID::FlexRay2a:
case NetID::FlexRay2b:
return Type::FlexRay;
case NetID::MOST25:
case NetID::MOST50:
case NetID::MOST150:
return Type::MOST;
case NetID::RED:
case NetID::Reset_Status:
case NetID::Device_Status:
return Type::Internal;
case NetID::Invalid:
case NetID::Any:
return Type::Invalid;
default:
return Type::Other;
}
}
static const char* GetNetIDString(NetID netid) {
switch(netid) {
case NetID::Device:
return "Device";
case NetID::HSCAN:
return "HSCAN";
case NetID::MSCAN:
return "MSCAN";
case NetID::SWCAN:
return "SWCAN";
case NetID::LSFTCAN:
return "LSFTCAN";
case NetID::FordSCP:
return "FordSCP";
case NetID::J1708:
return "J1708";
case NetID::Aux:
return "Aux";
case NetID::J1850VPW:
return "J1850 VPW";
case NetID::ISO:
return "ISO";
case NetID::ISOPIC:
return "ISOPIC";
case NetID::Main51:
return "Main51";
case NetID::RED:
return "RED";
case NetID::SCI:
return "SCI";
case NetID::ISO2:
return "ISO 2";
case NetID::ISO14230:
return "ISO 14230";
case NetID::LIN:
return "LIN";
case NetID::OP_Ethernet1:
return "Ethernet 1";
case NetID::OP_Ethernet2:
return "Ethernet 2";
case NetID::OP_Ethernet3:
return "Ethernet 3";
case NetID::RED_EXT_MEMORYREAD:
return "RED_EXT_MEMORYREAD";
case NetID::RED_INT_MEMORYREAD:
return "RED_INT_MEMORYREAD";
case NetID::RED_DFLASH_READ:
return "RED_DFLASH_READ";
case NetID::RED_SDCARD_READ:
return "RED_SDCARD_READ";
case NetID::CAN_ERRBITS:
return "CAN_ERRBITS";
case NetID::RED_DFLASH_WRITE_DONE:
return "RED_DFLASH_WRITE_DONE";
case NetID::RED_WAVE_CAN1_LOGICAL:
return "RED_WAVE_CAN1_LOGICAL";
case NetID::RED_WAVE_CAN2_LOGICAL:
return "RED_WAVE_CAN2_LOGICAL";
case NetID::RED_WAVE_LIN1_LOGICAL:
return "RED_WAVE_LIN1_LOGICAL";
case NetID::RED_WAVE_LIN2_LOGICAL:
return "RED_WAVE_LIN2_LOGICAL";
case NetID::RED_WAVE_LIN1_ANALOG:
return "RED_WAVE_LIN1_ANALOG";
case NetID::RED_WAVE_LIN2_ANALOG:
return "RED_WAVE_LIN2_ANALOG";
case NetID::RED_WAVE_MISC_ANALOG:
return "RED_WAVE_MISC_ANALOG";
case NetID::RED_WAVE_MISCDIO2_LOGICAL:
return "RED_WAVE_MISCDIO2_LOGICAL";
case NetID::RED_NETWORK_COM_ENABLE_EX:
return "RED_NETWORK_COM_ENABLE_EX";
case NetID::RED_NEOVI_NETWORK:
return "RED_NEOVI_NETWORK";
case NetID::RED_READ_BAUD_SETTINGS:
return "RED_READ_BAUD_SETTINGS";
case NetID::RED_OLDFORMAT:
return "RED_OLDFORMAT";
case NetID::RED_SCOPE_CAPTURE:
return "RED_SCOPE_CAPTURE";
case NetID::RED_HARDWARE_EXCEP:
return "RED_HARDWARE_EXCEP";
case NetID::RED_GET_RTC:
return "RED_GET_RTC";
case NetID::ISO3:
return "ISO 3";
case NetID::HSCAN2:
return "HSCAN 2";
case NetID::HSCAN3:
return "HSCAN 3";
case NetID::OP_Ethernet4:
return "Ethernet 4";
case NetID::OP_Ethernet5:
return "Ethernet 5";
case NetID::ISO4:
return "ISO 4";
case NetID::LIN2:
return "LIN 2";
case NetID::LIN3:
return "LIN 3";
case NetID::LIN4:
return "LIN 4";
case NetID::RED_App_Error:
return "App Error";
case NetID::CGI:
return "CGI";
case NetID::Reset_Status:
return "Reset Status";
case NetID::FB_Status:
return "FB Status";
case NetID::App_Signal_Status:
return "App Signal Status";
case NetID::Read_Datalink_Cm_Tx_Msg:
return "Read Datalink Cm Tx Msg";
case NetID::Read_Datalink_Cm_Rx_Msg:
return "Read Datalink Cm Rx Msg";
case NetID::Logging_Overflow:
return "Logging Overflow";
case NetID::Read_Settings_Ex:
return "Read Settings Ex";
case NetID::HSCAN4:
return "HSCAN 4";
case NetID::HSCAN5:
return "HSCAN 5";
case NetID::RS232:
return "RS232";
case NetID::UART:
return "UART";
case NetID::UART2:
return "UART 2";
case NetID::UART3:
return "UART 3";
case NetID::UART4:
return "UART 4";
case NetID::SWCAN2:
return "SWCAN 2";
case NetID::Ethernet_DAQ:
return "Ethernet DAQ";
case NetID::Data_To_Host:
return "Data To Host";
case NetID::TextAPI_To_Host:
return "TextAPI To Host";
case NetID::OP_Ethernet6:
return "Ethernet 6";
case NetID::Red_VBat:
return "Red VBat";
case NetID::OP_Ethernet7:
return "Ethernet 7";
case NetID::OP_Ethernet8:
return "Ethernet 8";
case NetID::OP_Ethernet9:
return "Ethernet 9";
case NetID::OP_Ethernet10:
return "Ethernet 10";
case NetID::OP_Ethernet11:
return "Ethernet 11";
case NetID::FlexRay1a:
return "FlexRay 1a";
case NetID::FlexRay1b:
return "FlexRay 1b";
case NetID::FlexRay2a:
return "FlexRay 2a";
case NetID::FlexRay2b:
return "FlexRay 2b";
case NetID::LIN5:
return "LIN 5";
case NetID::FlexRay:
return "FlexRay";
case NetID::FlexRay2:
return "FlexRay 2";
case NetID::OP_Ethernet12:
return "Ethernet 12";
case NetID::MOST25:
return "MOST25";
case NetID::MOST50:
return "MOST50";
case NetID::MOST150:
return "MOST150";
case NetID::Ethernet:
return "Ethernet";
case NetID::GMFSA:
return "GMFSA";
case NetID::TCP:
return "TCP";
case NetID::HSCAN6:
return "HSCAN 6";
case NetID::HSCAN7:
return "HSCAN 7";
case NetID::LIN6:
return "LIN 6";
case NetID::LSFTCAN2:
return "LSFTCAN 2";
case NetID::HW_COM_Latency_Test:
return "HW COM Latency Test";
case NetID::Device_Status:
return "Device Status";
case NetID::Invalid:
default:
return "Invalid Network";
}
}
Network() { setValue(NetID::Invalid); }
Network(uint16_t netid) { setValue((NetID)netid); }
Network(NetID netid) { setValue(netid); }
NetID getNetID() const { return value; }
Type getType() const { return type; }
friend std::ostream& operator<<(std::ostream& os, const Network& network) {
os << GetNetIDString(network.getNetID());
return os;
}
private:
NetID value; // Always use setValue so that value and type stay in sync
Type type;
void setValue(NetID id) {
value = id;
type = GetTypeOfNetID(value);
}
};
}
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef __PACKET_H_
#define __PACKET_H_
#include "icsneo/communication/network.h"
#include <vector>
#include <stdint.h>
namespace icsneo {
class Packet {
public:
Network network;
std::vector<uint8_t> data;
};
}
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef __PACKETIZER_H_
#define __PACKETIZER_H_
#include "icsneo/communication/packet.h"
#include <queue>
#include <vector>
#include <memory>
namespace icsneo {
class Packetizer {
public:
static uint8_t ICSChecksum(const std::vector<uint8_t>& data);
std::vector<uint8_t>& packetWrap(std::vector<uint8_t>& data, bool shortFormat);
bool input(const std::vector<uint8_t>& bytes);
std::vector<std::shared_ptr<Packet>> output();
bool disableChecksum = false; // Even for short packets
bool align16bit = true; // Not needed for Gigalog, Galaxy, etc and newer
private:
enum class ReadState {
SearchForHeader,
ParseHeader,
ParseLongStylePacketHeader,
GetData
};
ReadState state = ReadState::SearchForHeader;
int currentIndex = 0;
int packetLength = 0;
int headerSize = 0;
bool checksum = false;
bool gotGoodPackets = false; // Tracks whether we've ever gotten a good packet
Packet packet;
std::deque<uint8_t> bytes;
std::vector<std::shared_ptr<Packet>> processedPackets;
};
}
#endif
+93
View File
@@ -0,0 +1,93 @@
#ifndef __DEVICE_H__
#define __DEVICE_H__
#include <vector>
#include <memory>
#include <cstring>
#include "icsneo/device/neodevice.h"
#include "icsneo/device/idevicesettings.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/communication/communication.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/encoder.h"
#include "icsneo/communication/decoder.h"
#include "icsneo/communication/message/resetstatusmessage.h"
#include "icsneo/third-party/concurrentqueue/concurrentqueue.h"
namespace icsneo {
class Device {
public:
Device(neodevice_t neodevice = { 0 }) {
data = neodevice;
data.device = this;
}
virtual ~Device() {
disableMessagePolling();
close();
}
static std::string SerialNumToString(uint32_t serial);
static uint32_t SerialStringToNum(const std::string& serial);
static bool SerialStringIsNumeric(const std::string& serial);
DeviceType getType() const { return DeviceType(data.type); }
uint16_t getProductId() const { return productId; }
std::string getSerial() const { return data.serial; }
uint32_t getSerialNumber() const { return Device::SerialStringToNum(getSerial()); }
const neodevice_t& getNeoDevice() const { return data; }
virtual bool open();
virtual bool close();
virtual bool isOnline() const { return online; }
virtual bool goOnline();
virtual bool goOffline();
// Message polling related functions
void enableMessagePolling();
bool disableMessagePolling();
std::vector<std::shared_ptr<Message>> getMessages();
bool getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit = 0);
size_t getCurrentMessageCount() { return pollingContainer.size_approx(); }
size_t getPollingMessageLimit() { return pollingMessageLimit; }
void setPollingMessageLimit(size_t newSize) {
pollingMessageLimit = newSize;
enforcePollingMessageLimit();
}
bool transmit(std::shared_ptr<Message> message);
bool transmit(std::vector<std::shared_ptr<Message>> messages);
void handleInternalMessage(std::shared_ptr<Message> message);
std::unique_ptr<IDeviceSettings> settings;
protected:
uint16_t productId = 0;
bool online = false;
int messagePollingCallbackID = 0;
int internalHandlerCallbackID = 0;
std::shared_ptr<Communication> com;
neodevice_t& getWritableNeoDevice() { return data; }
private:
neodevice_t data;
std::shared_ptr<ResetStatusMessage> latestResetStatus;
enum class LEDState : uint8_t {
Offline = 0x04,
CoreMiniRunning = 0x08, // This should override "offline" if the CoreMini is running
Online = 0x10
};
LEDState ledState;
void updateLEDState();
size_t pollingMessageLimit = 20000;
moodycamel::ConcurrentQueue<std::shared_ptr<Message>> pollingContainer;
void enforcePollingMessageLimit();
};
}
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef __DEVICEFINDER_H_
#define __DEVICEFINDER_H_
#include "icsneo/device/device.h"
#include <vector>
#include <memory>
namespace icsneo {
class DeviceFinder {
public:
static std::vector<std::shared_ptr<Device>> FindAll();
};
}
#endif
+164
View File
@@ -0,0 +1,164 @@
#ifndef __DEVICETYPE_H_
#define __DEVICETYPE_H_
// Hold the length of the longest name, so that C applications can allocate memory accordingly
// Currently the longest is "Intrepid Ethernet Evaluation Board"
#define DEVICE_TYPE_LONGEST_NAME (35 + 1) // Add 1 so that if someone forgets, they still have space for null terminator
#ifndef __cplusplus
#include <stdint.h>
typedef uint32_t devicetype_t;
#else
#include <ostream>
#include <cstdint>
typedef uint32_t devicetype_t;
namespace icsneo {
class DeviceType {
public:
// This enum used to be a bitfield, but has since become an enum as we have more than 32 devices
enum Enum : devicetype_t {
Unknown = (0x00000000),
BLUE = (0x00000001),
ECU_AVB = (0x00000002),
RADSupermoon = (0x00000003),
DW_VCAN = (0x00000004),
RADMoon2 = (0x00000005),
RADGigalog = (0x00000006),
VCAN4_1 = (0x00000007),
FIRE = (0x00000008),
RADPluto = (0x00000009),
VCAN4_2EL = (0x0000000a),
RADIO_CANHUB = (0x0000000b),
VCAN3 = (0x00000010),
RED = (0x00000040),
ECU = (0x00000080),
IEVB = (0x00000100),
Pendant = (0x00000200),
OBD2_PRO = (0x00000400),
ECUChip_UART = (0x00000800),
PLASMA = (0x00001000),
DONT_REUSE0 = (0x00002000), // Previously FIRE_VNET
NEOAnalog = (0x00004000),
CT_OBD = (0x00008000),
DONT_REUSE1 = (0x00010000), // Previously PLASMA_1_12
DONT_REUSE2 = (0x00020000), // Previously PLASMA_1_13
ION = (0x00040000),
RADStar = (0x00080000),
DONT_REUSE3 = (0x00100000), // Previously ION3
VCAN4_4 = (0x00200000),
VCAN4_2 = (0x00400000),
CMProbe = (0x00800000),
EEVB = (0x01000000),
VCANrf = (0x02000000),
FIRE2 = (0x04000000),
Flex = (0x08000000),
RADGalaxy = (0x10000000),
RADStar2 = (0x20000000),
VividCAN = (0x40000000),
OBD2_SIM = (0x80000000)
};
static const char* GetDeviceTypeString(DeviceType::Enum type) {
// Adding something? Make sure you update DEVICE_TYPE_LONGEST_NAME at the top!
switch(type) {
case Unknown:
return "Unknown";
case BLUE:
return "neoVI BLUE";
case ECU_AVB:
return "neoECU AVB";
case RADSupermoon:
return "RADSupermoon";
case DW_VCAN:
return "DW_VCAN";
case RADMoon2:
return "RADMoon 2";
case RADGigalog:
return "RADGigalog";
case VCAN4_1:
return "ValueCAN 4-1";
case FIRE:
return "neoVI FIRE";
case RADPluto:
return "RADPluto";
case VCAN4_2EL:
return "ValueCAN 4-2EL";
case RADIO_CANHUB:
return "RADIO_CANHUB";
case VCAN3:
return "ValueCAN 3";
case RED:
return "neoVI RED";
case ECU:
return "neoECU";
case IEVB:
return "IEVB";
case Pendant:
return "Pendant";
case OBD2_PRO:
return "neoOBD2 PRO";
case ECUChip_UART:
return "neoECU Chip UART";
case PLASMA:
return "neoVI PLASMA";
case NEOAnalog:
return "NEOAnalog";
case CT_OBD:
return "CT_OBD";
case ION:
return "neoVI ION";
case RADStar:
return "RADStar";
case VCAN4_4:
return "ValueCAN 4-4";
case VCAN4_2:
return "ValueCAN 4-2";
case CMProbe:
return "CMProbe";
case EEVB:
return "Intrepid Ethernet Evaluation Board";
case VCANrf:
return "ValueCAN.rf";
case FIRE2:
return "neoVI FIRE 2";
case Flex:
return "neoVI Flex";
case RADGalaxy:
return "RADGalaxy";
case RADStar2:
return "RADStar 2";
case VividCAN:
return "VividCAN";
case OBD2_SIM:
return "neoOBD2-SIM";
case DONT_REUSE0:
case DONT_REUSE1:
case DONT_REUSE2:
case DONT_REUSE3:
// Intentionally don't use default so that the compiler throws a warning when something is added
return "Unknown neoVI";
}
return "Unknown neoVI";
}
DeviceType() { value = DeviceType::Enum::Unknown; }
DeviceType(devicetype_t netid) { value = (DeviceType::Enum)netid; }
DeviceType(DeviceType::Enum netid) { value = netid; }
DeviceType::Enum getDeviceType() const { return value; }
std::string toString() const { return GetDeviceTypeString(getDeviceType()); }
friend std::ostream& operator<<(std::ostream& os, const DeviceType& type) {
os << type.toString().c_str();
return os;
}
private:
DeviceType::Enum value;
};
}
#endif // __cplusplus
#endif
+318
View File
@@ -0,0 +1,318 @@
#ifndef __IDEVICESETTINGS_H_
#define __IDEVICESETTINGS_H_
#include <stdint.h>
#pragma pack(push, 2)
/* SetBaudrate in CAN_SETTINGS */
enum
{
AUTO,
USE_TQ
};
/* Baudrate in CAN_SETTINGS/CANFD_SETTINGS */
enum
{
BPS20,
BPS33,
BPS50,
BPS62,
BPS83,
BPS100,
BPS125,
BPS250,
BPS500,
BPS800,
BPS1000,
BPS666,
BPS2000,
BPS4000,
CAN_BPS5000,
CAN_BPS6667,
CAN_BPS8000,
CAN_BPS10000,
};
/* Mode in CAN_SETTINGS */
enum
{
NORMAL = 0,
DISABLE = 1,
LOOPBACK = 2,
LISTEN_ONLY = 3,
LISTEN_ALL = 7
};
typedef struct
{
uint8_t Mode;
uint8_t SetBaudrate;
uint8_t Baudrate;
uint8_t transceiver_mode;
uint8_t TqSeg1;
uint8_t TqSeg2;
uint8_t TqProp;
uint8_t TqSync;
uint16_t BRP;
uint8_t auto_baud;
uint8_t innerFrameDelay25us;
} CAN_SETTINGS;
#define CAN_SETTINGS_SIZE 12
/* FDMode in CANFD_SETTINGS */
enum
{
NO_CANFD,
CANFD_ENABLED,
CANFD_BRS_ENABLED,
CANFD_ENABLED_ISO,
CANFD_BRS_ENABLED_ISO
};
typedef struct _CANFD_SETTINGS
{
uint8_t FDMode; /* mode, secondary baudrate for canfd */
uint8_t FDBaudrate;
uint8_t FDTqSeg1;
uint8_t FDTqSeg2;
uint8_t FDTqProp;
uint8_t FDTqSync;
uint16_t FDBRP;
uint8_t FDTDC;
uint8_t reserved;
} CANFD_SETTINGS;
#define CANFD_SETTINGS_SIZE 10
typedef struct ETHERNET_SETTINGS_t
{
uint8_t duplex; /* 0 = half, 1 = full */
uint8_t link_speed;
uint8_t auto_neg;
uint8_t led_mode;
uint8_t rsvd[4];
} ETHERNET_SETTINGS;
#define ETHERNET_SETTINGS_SIZE 8
typedef struct
{
uint8_t MasterEnable;
uint8_t SlaveEnable;
uint8_t MasterNetwork;
uint8_t SlaveNetwork;
} TIMESYNC_ICSHARDWARE_SETTINGS;
#define TIMESYNC_ICSHARDWARE_SETTINGS_SIZE 4
typedef struct _STextAPISettings
{
uint32_t can1_tx_id;
uint32_t can1_rx_id;
union {
struct sCAN1Options
{
unsigned bExtended : 1;
unsigned : 15;
};
uint32_t DWord;
} can1_options;
uint32_t can2_tx_id;
uint32_t can2_rx_id;
union {
struct sCAN2Options
{
unsigned bExtended : 1;
unsigned : 15;
};
uint32_t DWord;
} can2_options;
uint32_t network_enables;
uint32_t can3_tx_id;
uint32_t can3_rx_id;
union {
struct sCAN3Options
{
unsigned bExtended : 1;
unsigned : 15;
};
uint32_t DWord;
} can3_options;
uint32_t can4_tx_id;
uint32_t can4_rx_id;
union {
struct sCAN4Options
{
unsigned bExtended : 1;
unsigned : 15;
};
uint32_t DWord;
} can4_options;
uint32_t reserved[5];
} STextAPISettings;
#define STextAPISettings_SIZE 72
/* high_speed_auto_switch in SWCAN_SETTINGS */
enum
{
SWCAN_AUTOSWITCH_DISABLED,
SWCAN_AUTOSWITCH_NO_RESISTOR,
SWCAN_AUTOSWITCH_WITH_RESISTOR,
SWCAN_AUTOSWITCH_DISABLED_RESISTOR_ENABLED
};
typedef struct
{
uint8_t Mode;
uint8_t SetBaudrate;
uint8_t Baudrate;
uint8_t transceiver_mode;
uint8_t TqSeg1;
uint8_t TqSeg2;
uint8_t TqProp;
uint8_t TqSync;
uint16_t BRP;
uint16_t high_speed_auto_switch;
uint8_t auto_baud;
uint8_t RESERVED;
} SWCAN_SETTINGS;
#define SWCAN_SETTINGS_SIZE 14
/* Baudrate in LIN_SETTINGS / ISO9141_KEYWORD2000_SETTINGS / UART_SETTINGS */
enum
{
BPS5000,
BPS10400,
BPS33333,
BPS50000,
BPS62500,
BPS71429,
BPS83333,
BPS100000,
BPS117647
};
/* MasterResistor in LIN_SETTINGS */
enum
{
RESISTOR_ON,
RESISTOR_OFF
};
/* Mode in LIN_SETTINGS */
enum
{
SLEEP_MODE,
SLOW_MODE,
NORMAL_MODE,
FAST_MODE
};
typedef struct _LIN_SETTINGS
{
uint32_t Baudrate; /* New products since FIREVNETEP should rely on this only */
uint16_t spbrg; /* Precompiled to be 40Mhz/Baudrate/16 - 1. Only used in neoVI FIRE/FIREVNET(4dw) */
uint8_t brgh; /* Must be zero */
uint8_t numBitsDelay;
uint8_t MasterResistor;
uint8_t Mode;
} LIN_SETTINGS;
#define LIN_SETTINGS_SIZE 10
typedef struct
{
uint16_t time_500us;
uint16_t k;
uint16_t l;
} ISO9141_KEYWORD2000__INIT_STEP;
#define ISO9141_KEYWORD2000__INIT_STEP_SIZE 6
typedef struct
{
uint32_t Baudrate;
uint16_t spbrg;
uint16_t brgh;
ISO9141_KEYWORD2000__INIT_STEP init_steps[16];
uint8_t init_step_count;
uint16_t p2_500us;
uint16_t p3_500us;
uint16_t p4_500us;
uint16_t chksum_enabled;
} ISO9141_KEYWORD2000_SETTINGS;
#define ISO9141_KEYWORD2000_SETTINGS_SIZE 114
typedef struct _UART_SETTINGS
{
uint16_t Baudrate;
uint16_t spbrg;
uint16_t brgh;
uint16_t parity;
uint16_t stop_bits;
uint8_t flow_control; /* 0- off, 1 - Simple CTS RTS */
uint8_t reserved_1;
union abcd {
uint32_t bOptions;
struct _sOptions
{
unsigned invert_tx : 1;
unsigned invert_rx : 1;
unsigned half_duplex : 1;
unsigned reserved_bits : 13;
unsigned reserved_bits2 : 16;
} sOptions;
};
} UART_SETTINGS;
#define UART_SETTINGS_SIZE 16
#pragma pack(pop)
#ifdef __cplusplus
#include "icsneo/communication/communication.h"
#include <iostream>
namespace icsneo {
class IDeviceSettings {
public:
static constexpr uint16_t GS_VERSION = 5;
static uint16_t CalculateGSChecksum(const std::vector<uint8_t>& settings);
IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), structSize(size) {}
virtual ~IDeviceSettings() {}
bool ok() { return settingsLoaded; }
bool refresh(bool ignoreChecksum = false); // Get from device
// Send to device, if temporary device keeps settings in volatile RAM until power cycle, otherwise saved to EEPROM
bool apply(bool temporary = false);
bool applyDefaults(bool temporary = false);
virtual bool setBaudrateFor(Network net, uint32_t baudrate);
virtual CAN_SETTINGS* getCANSettingsFor(Network net) { (void)net; return nullptr; }
virtual CANFD_SETTINGS* getCANFDSettingsFor(Network net) { (void)net; return nullptr; }
void* getRawStructurePointer() { return settings.data(); }
template<typename T> T* getStructurePointer() { return static_cast<T*>((void*)settings.data()); }
template<typename T> T getStructureCopy() { return *getStructurePointer<T>(); }
template<typename T> bool setStructure(const T& newStructure);
uint8_t getEnumValueForBaudrate(uint32_t baudrate);
bool readonly = false;
protected:
std::shared_ptr<Communication> com;
size_t structSize;
bool settingsLoaded = false;
std::vector<uint8_t> settings;
};
}
#endif // __cplusplus
#endif
+32
View File
@@ -0,0 +1,32 @@
#ifndef __NEODEVICE_H_
#define __NEODEVICE_H_
#include <stdint.h>
#include "icsneo/device/devicetype.h"
#ifdef __cplusplus
// A forward declaration is needed as there is a circular dependency
namespace icsneo {
class Device;
}
typedef icsneo::Device* devicehandle_t;
#else
typedef void* devicehandle_t;
#endif
typedef int32_t neodevice_handle_t;
#pragma pack(push, 1)
typedef struct {
devicehandle_t device; // Pointer back to the C++ device object
neodevice_handle_t handle; // Handle for use by the underlying driver
devicetype_t type;
char serial[7];
} neodevice_t;
#pragma pack(pop)
#endif
@@ -0,0 +1,37 @@
#ifndef __NEOOBD2PRO_H_
#define __NEOOBD2PRO_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/stm32.h"
namespace icsneo {
class NeoOBD2PRO : public Device {
public:
// Serial numbers are NP****
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::OBD2_PRO;
static constexpr const uint16_t PRODUCT_ID = 0x1103;
NeoOBD2PRO(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new STM32(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<NeoOBD2PRO>(neodevice));
return found;
}
};
}
#endif
@@ -0,0 +1,37 @@
#ifndef __NEOOBD2SIM_H_
#define __NEOOBD2SIM_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/stm32.h"
namespace icsneo {
class NeoOBD2SIM : public Device {
public:
// Serial numbers are OS****
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::OBD2_SIM;
static constexpr const uint16_t PRODUCT_ID = 0x1100;
NeoOBD2SIM(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new STM32(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<NeoOBD2SIM>(neodevice));
return found;
}
};
}
#endif
@@ -0,0 +1,60 @@
#ifndef __NEOVIFIRE_H_
#define __NEOVIFIRE_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class NeoVIFIRE : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::FIRE;
static constexpr const uint16_t PRODUCT_ID = 0x0701;
NeoVIFIRE(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new FTDI(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
enum class Mode : char {
Application = 'A',
Bootloader = 'B'
};
bool goOnline() {
// Enter mode is only needed on very old FIRE devices, will be ignored by newer devices
if(!enterMode(Mode::Application))
return false;
return Device::goOnline();
}
bool enterMode(Mode mode) {
// Included for compatibility with bootloaders on very old FIRE devices
// Mode will be a uppercase char like 'A'
if(!com->rawWrite({ (uint8_t)mode }))
return false;
// We then expect to see that same mode back in lowercase
// This won't happen in the case of new devices, though, so we assume it worked
return true;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<NeoVIFIRE>(neodevice));
return found;
}
};
}
#endif
@@ -0,0 +1,30 @@
#ifndef __NEOVIFIRE2_H_
#define __NEOVIFIRE2_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class NeoVIFIRE2 : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::FIRE2;
static constexpr const char* SERIAL_START = "CY";
NeoVIFIRE2(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
}
protected:
static std::shared_ptr<Communication> MakeCommunication(std::unique_ptr<ICommunication> transport) {
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
encoder->supportCANFD = true;
auto decoder = std::unique_ptr<Decoder>(new Decoder());
return std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
}
};
}
#endif
@@ -0,0 +1,57 @@
#ifndef __NEOVIFIRE2ETH_H_
#define __NEOVIFIRE2ETH_H_
#include "icsneo/device/neovifire2/neovifire2.h"
#include "icsneo/platform/pcap.h"
#include "icsneo/device/neovifire2/neovifire2settings.h"
#include <memory>
namespace icsneo {
class NeoVIFIRE2ETH : public NeoVIFIRE2 {
public:
static constexpr const uint16_t PRODUCT_ID = 0x0004;
NeoVIFIRE2ETH(neodevice_t neodevice) : NeoVIFIRE2(neodevice) {
com = MakeCommunicaiton(std::unique_ptr<ICommunication>(new PCAP(getWritableNeoDevice())));
settings = std::unique_ptr<IDeviceSettings>(new NeoVIFIRE2Settings(com));
settings->readonly = true;
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : PCAP::FindAll()) {
auto packetizer = std::make_shared<Packetizer>();
auto decoder = std::unique_ptr<Decoder>(new Decoder());
for(auto& payload : foundDev.discoveryPackets)
packetizer->input(payload);
for(auto& packet : packetizer->output()) {
std::shared_ptr<Message> msg;
if(!decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->network.getNetID() != Network::NetID::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a FIRE 2
foundDev.device.serial[sn->deviceSerial.copy(foundDev.device.serial, sizeof(foundDev.device.serial))] = '\0';
found.push_back(std::make_shared<NeoVIFIRE2ETH>(foundDev.device));
break;
}
}
return found;
}
};
}
#endif
@@ -0,0 +1,147 @@
#ifndef __NEOVIFIRE2SETTINGS_H_
#define __NEOVIFIRE2SETTINGS_H_
#include <stdint.h>
#include "icsneo/device/idevicesettings.h"
#ifdef __cplusplus
namespace icsneo {
#endif
#pragma pack(push, 2)
typedef struct {
uint16_t perf_en;
CAN_SETTINGS can1;
CANFD_SETTINGS canfd1;
CAN_SETTINGS can2;
CANFD_SETTINGS canfd2;
CAN_SETTINGS can3;
CANFD_SETTINGS canfd3;
CAN_SETTINGS can4;
CANFD_SETTINGS canfd4;
CAN_SETTINGS can5;
CANFD_SETTINGS canfd5;
CAN_SETTINGS can6;
CANFD_SETTINGS canfd6;
CAN_SETTINGS can7;
CANFD_SETTINGS canfd7;
CAN_SETTINGS can8;
CANFD_SETTINGS canfd8;
/* Native CAN are either LS1/LS2 or SW1/SW2 */
SWCAN_SETTINGS swcan1;
uint16_t network_enables;
SWCAN_SETTINGS swcan2;
uint16_t network_enables_2;
CAN_SETTINGS lsftcan1;
CAN_SETTINGS lsftcan2;
LIN_SETTINGS lin1;
uint16_t misc_io_initial_ddr;
LIN_SETTINGS lin2;
uint16_t misc_io_initial_latch;
LIN_SETTINGS lin3;
uint16_t misc_io_report_period;
LIN_SETTINGS lin4;
uint16_t misc_io_on_report_events;
LIN_SETTINGS lin5;
uint16_t misc_io_analog_enable;
uint16_t ain_sample_period;
uint16_t ain_threshold;
uint32_t pwr_man_timeout;
uint16_t pwr_man_enable;
uint16_t network_enabled_on_boot;
uint16_t iso15765_separation_time_offset;
uint16_t iso_9141_kwp_enable_reserved;
ISO9141_KEYWORD2000_SETTINGS iso9141_kwp_settings_1;
uint16_t iso_parity_1;
ISO9141_KEYWORD2000_SETTINGS iso9141_kwp_settings_2;
uint16_t iso_parity_2;
ISO9141_KEYWORD2000_SETTINGS iso9141_kwp_settings_3;
uint16_t iso_parity_3;
ISO9141_KEYWORD2000_SETTINGS iso9141_kwp_settings_4;
uint16_t iso_parity_4;
uint16_t iso_msg_termination_1;
uint16_t iso_msg_termination_2;
uint16_t iso_msg_termination_3;
uint16_t iso_msg_termination_4;
uint16_t idle_wakeup_network_enables_1;
uint16_t idle_wakeup_network_enables_2;
/* reserved for HSCAN6/7, LSFT2, etc.. */
uint16_t network_enables_3;
uint16_t idle_wakeup_network_enables_3;
uint16_t can_switch_mode;
STextAPISettings text_api;
uint64_t termination_enables;
LIN_SETTINGS lin6;
ETHERNET_SETTINGS ethernet;
uint16_t slaveVnetA;
uint16_t slaveVnetB;
struct {
uint32_t disableUsbCheckOnBoot : 1;
uint32_t enableLatencyTest : 1;
uint32_t busMessagesToAndroid : 1;
uint32_t enablePcEthernetComm : 1;
uint32_t enableDefaultLogger : 1;
uint32_t enableDefaultUpload : 1;
uint32_t reserved : 26;
} flags;
uint16_t digitalIoThresholdTicks;
uint16_t digitalIoThresholdEnable;
TIMESYNC_ICSHARDWARE_SETTINGS timeSync;
} neovifire2_settings_t;
#pragma pack(pop)
#ifdef __cplusplus
#include <iostream>
class NeoVIFIRE2Settings : public IDeviceSettings {
public:
NeoVIFIRE2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire2_settings_t)) {}
CAN_SETTINGS* getCANSettingsFor(Network net) override {
auto cfg = getStructurePointer<neovifire2_settings_t>();
switch(net.getNetID()) {
case Network::NetID::HSCAN:
return &(cfg->can1);
case Network::NetID::MSCAN:
return &(cfg->can2);
case Network::NetID::HSCAN2:
return &(cfg->can3);
case Network::NetID::HSCAN3:
return &(cfg->can4);
case Network::NetID::HSCAN4:
return &(cfg->can5);
case Network::NetID::HSCAN5:
return &(cfg->can6);
case Network::NetID::HSCAN6:
return &(cfg->can7);
case Network::NetID::HSCAN7:
return &(cfg->can8);
default:
return nullptr;
}
}
// CANFD_SETTINGS* getCANFDSettingsFor(Network net) override { return nullptr; }
};
}
#endif // __cplusplus
#endif
@@ -0,0 +1,31 @@
#ifndef __NEOVIFIRE2USB_H_
#define __NEOVIFIRE2USB_H_
#include "icsneo/device/neovifire2/neovifire2.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/device/neovifire2/neovifire2settings.h"
namespace icsneo {
class NeoVIFIRE2USB : public NeoVIFIRE2 {
public:
static constexpr const uint16_t PRODUCT_ID = 0x1000;
NeoVIFIRE2USB(neodevice_t neodevice) : NeoVIFIRE2(neodevice) {
com = MakeCommunication(std::unique_ptr<ICommunication>(new FTDI(getWritableNeoDevice())));
settings = std::unique_ptr<IDeviceSettings>(new NeoVIFIRE2Settings(com));
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<NeoVIFIRE2USB>(neodevice));
return found;
}
};
}
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef __NEOVIION_H_
#define __NEOVIION_H_
#include "icsneo/device/plasion/plasion.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class NeoVIION : public Plasion {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::ION;
static constexpr const uint16_t PRODUCT_ID = 0x0901;
NeoVIION(neodevice_t neodevice) : Plasion(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<NeoVIION>(neodevice));
return found;
}
};
}
#endif
@@ -0,0 +1,31 @@
#ifndef __NEOVIPLASMA_H_
#define __NEOVIPLASMA_H_
#include "icsneo/device/plasion/plasion.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class NeoVIPLASMA : public Plasion {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::PLASMA;
static constexpr const uint16_t PRODUCT_ID = 0x0801;
NeoVIPLASMA(neodevice_t neodevice) : Plasion(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<NeoVIPLASMA>(neodevice));
return found;
}
};
}
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef __PLASION_H_
#define __PLASION_H_
#include "icsneo/device/device.h"
#include "icsneo/communication/multichannelcommunication.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class Plasion : public Device {
public:
Plasion(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new FTDI(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<MultiChannelCommunication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
}
};
}
#endif
@@ -0,0 +1,72 @@
#ifndef __RADGALAXY_H_
#define __RADGALAXY_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/pcap.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
namespace icsneo {
class RADGalaxy : public Device {
public:
// Serial numbers start with RG
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADGalaxy;
static constexpr const uint16_t PRODUCT_ID = 0x0003;
static constexpr const char* SERIAL_START = "RG";
static std::shared_ptr<Packetizer> MakePacketizer() {
auto packetizer = std::make_shared<Packetizer>();
packetizer->disableChecksum = true;
packetizer->align16bit = false;
return packetizer;
}
RADGalaxy(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new PCAP(getWritableNeoDevice()));
auto packetizer = MakePacketizer();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : PCAP::FindAll()) {
auto packetizer = MakePacketizer();
auto decoder = std::unique_ptr<Decoder>(new Decoder());
for(auto& payload : foundDev.discoveryPackets)
packetizer->input(payload);
for(auto& packet : packetizer->output()) {
std::shared_ptr<Message> msg;
if(!decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->network.getNetID() != Network::NetID::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a RADGalaxy
foundDev.device.serial[sn->deviceSerial.copy(foundDev.device.serial, sizeof(foundDev.device.serial))] = '\0';
found.push_back(std::make_shared<RADGalaxy>(foundDev.device));
break;
}
}
return found;
}
};
}
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef __RADSTAR2_H_
#define __RADSTAR2_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
namespace icsneo {
class RADStar2 : public Device {
public:
// Serial numbers start with RS
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADStar2;
static constexpr const uint16_t PRODUCT_ID = 0x0005;
static constexpr const char* SERIAL_START = "RS";
RADStar2(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
};
}
#endif
@@ -0,0 +1,65 @@
#ifndef __RADSTAR2ETH_H_
#define __RADSTAR2ETH_H_
#include "icsneo/device/radstar2/radstar2.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/message/serialnumbermessage.h"
#include "icsneo/platform/pcap.h"
namespace icsneo {
class RADStar2ETH : public RADStar2 {
public:
static std::shared_ptr<Packetizer> MakePacketizer() {
auto packetizer = std::make_shared<Packetizer>();
packetizer->disableChecksum = true;
packetizer->align16bit = false;
return packetizer;
}
// Serial numbers start with RS
RADStar2ETH(neodevice_t neodevice) : RADStar2(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new PCAP(getWritableNeoDevice()));
auto packetizer = MakePacketizer();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : PCAP::FindAll()) {
auto packetizer = MakePacketizer();
auto decoder = std::unique_ptr<Decoder>(new Decoder());
for(auto& payload : foundDev.discoveryPackets)
packetizer->input(payload);
for(auto& packet : packetizer->output()) {
std::shared_ptr<Message> msg;
if(!decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->network.getNetID() != Network::NetID::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a RADStar2
foundDev.device.serial[sn->deviceSerial.copy(foundDev.device.serial, sizeof(foundDev.device.serial))] = '\0';
found.push_back(std::make_shared<RADStar2ETH>(foundDev.device));
break;
}
}
return found;
}
};
}
#endif
@@ -0,0 +1,32 @@
#ifndef __RADSTAR2USB_H_
#define __RADSTAR2USB_H_
#include "icsneo/device/radstar2/radstar2.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class RADStar2USB : public RADStar2 {
public:
// Serial numbers start with RS
RADStar2USB(neodevice_t neodevice) : RADStar2(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new FTDI(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<RADStar2USB>(neodevice));
return found;
}
};
}
#endif
@@ -0,0 +1,38 @@
#ifndef __RADSUPERMOON_H_
#define __RADSUPERMOON_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class RADSupermoon : public Device {
public:
// Serial numbers start with VV
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADSupermoon;
static constexpr const uint16_t PRODUCT_ID = 0x1201;
RADSupermoon(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new FTDI(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
// RSM does not connect at all yet (needs FTDI D3xx driver, not the 2xx compatible one)
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<RADSupermoon>(neodevice));
return found;
}
};
}
#endif
@@ -0,0 +1,36 @@
#ifndef __VALUECAN3_H_
#define __VALUECAN3_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class ValueCAN3 : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN3;
static constexpr const uint16_t PRODUCT_ID = 0x0601;
ValueCAN3(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new FTDI(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<ValueCAN3>(neodevice));
return found;
}
};
}
#endif
@@ -0,0 +1,21 @@
#ifndef __VALUECAN4_1_2_SETTINGS_H_
#define __VALUECAN4_1_2_SETTINGS_H_
#include "icsneo/device/idevicesettings.h"
#include "icsneo/device/valuecan4/settings/valuecan4settings.h"
#ifdef __cplusplus
namespace icsneo {
class ValueCAN4_1_2Settings : public IDeviceSettings {
public:
ValueCAN4_1_2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_1_2_settings_t)) {}
// We do not override getCANSettingsFor or getCANFDSettingsFor here because they will be device specific
};
}
#endif // __cplusplus
#endif
@@ -0,0 +1,29 @@
#ifndef __VALUECAN4_1_SETTINGS_H_
#define __VALUECAN4_1_SETTINGS_H_
#include "icsneo/device/valuecan4/settings/valuecan4-1-2settings.h"
#ifdef __cplusplus
namespace icsneo {
class ValueCAN4_1Settings : public ValueCAN4_1_2Settings {
public:
ValueCAN4_1Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
CAN_SETTINGS* getCANSettingsFor(Network net) override {
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
switch(net.getNetID()) {
case Network::NetID::HSCAN:
return &(cfg->can1);
default:
return nullptr;
}
}
// CANFD_SETTINGS* getCANFDSettingsFor(Network net) override { return nullptr; }
};
}
#endif // __cplusplus
#endif
@@ -0,0 +1,36 @@
#ifndef __VALUECAN4_2EL_SETTINGS_H_
#define __VALUECAN4_2EL_SETTINGS_H_
#include "icsneo/device/idevicesettings.h"
#include "icsneo/device/valuecan4/settings/valuecan4-4-2elsettings.h"
#ifdef __cplusplus
namespace icsneo {
class ValueCAN4_2ELSettings : public ValueCAN4_4_2ELSettings {
public:
ValueCAN4_2ELSettings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
CAN_SETTINGS* getCANSettingsFor(Network net) override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
switch(net.getNetID()) {
case Network::NetID::HSCAN:
return &(cfg->can1);
case Network::NetID::HSCAN2:
return &(cfg->can2);
case Network::NetID::HSCAN3:
return &(cfg->can3);
case Network::NetID::HSCAN4:
return &(cfg->can4);
default:
return nullptr;
}
}
// CANFD_SETTINGS* getCANFDSettingsFor(Network net) override { return nullptr; }
};
}
#endif // __cplusplus
#endif
@@ -0,0 +1,31 @@
#ifndef __VALUECAN4_2_SETTINGS_H_
#define __VALUECAN4_2_SETTINGS_H_
#include "icsneo/device/valuecan4/settings/valuecan4-1-2settings.h"
#ifdef __cplusplus
namespace icsneo {
class ValueCAN4_2Settings : public ValueCAN4_1_2Settings {
public:
ValueCAN4_2Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
CAN_SETTINGS* getCANSettingsFor(Network net) override {
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
switch(net.getNetID()) {
case Network::NetID::HSCAN:
return &(cfg->can1);
case Network::NetID::HSCAN2:
return &(cfg->can2);
default:
return nullptr;
}
}
// CANFD_SETTINGS* getCANFDSettingsFor(Network net) override { return nullptr; }
};
}
#endif // __cplusplus
#endif
@@ -0,0 +1,21 @@
#ifndef __VALUECAN4_4_2EL_SETTINGS_H_
#define __VALUECAN4_4_2EL_SETTINGS_H_
#include "icsneo/device/idevicesettings.h"
#include "icsneo/device/valuecan4/settings/valuecan4settings.h"
#ifdef __cplusplus
namespace icsneo {
class ValueCAN4_4_2ELSettings : public IDeviceSettings {
public:
ValueCAN4_4_2ELSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_4_2el_settings_t)) {}
// We do not override getCANSettingsFor, getCANFDSettingsFor, or getEthernetSettingsFor here because they will be device specific
};
}
#endif // __cplusplus
#endif
@@ -0,0 +1,36 @@
#ifndef __VALUECAN4_4_SETTINGS_H_
#define __VALUECAN4_4_SETTINGS_H_
#include "icsneo/device/idevicesettings.h"
#include "icsneo/device/valuecan4/settings/valuecan4-4-2elsettings.h"
#ifdef __cplusplus
namespace icsneo {
class ValueCAN4_4Settings : public ValueCAN4_4_2ELSettings {
public:
ValueCAN4_4Settings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
CAN_SETTINGS* getCANSettingsFor(Network net) override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
switch(net.getNetID()) {
case Network::NetID::HSCAN:
return &(cfg->can1);
case Network::NetID::HSCAN2:
return &(cfg->can2);
case Network::NetID::HSCAN3:
return &(cfg->can3);
case Network::NetID::HSCAN4:
return &(cfg->can4);
default:
return nullptr;
}
}
// CANFD_SETTINGS* getCANFDSettingsFor(Network net) override { return nullptr; }
};
}
#endif // __cplusplus
#endif
@@ -0,0 +1,86 @@
#ifndef __VALUECAN4_SETTINGS_H_
#define __VALUECAN4_SETTINGS_H_
#include <stdint.h>
#include "icsneo/device/idevicesettings.h"
#ifdef __cplusplus
namespace icsneo {
#endif
// This is where the actual settings structures for all the ValueCAN 4 line live
// ValueCAN 4-1 and 4-2 share a structure, and 4-4 shares with 4-2EL
#pragma pack(push, 2)
typedef struct {
/* Performance Test */
uint16_t perf_en;
CAN_SETTINGS can1;
CANFD_SETTINGS canfd1;
CAN_SETTINGS can2;
CANFD_SETTINGS canfd2;
uint64_t network_enables;
uint64_t termination_enables;
uint32_t pwr_man_timeout;
uint16_t pwr_man_enable;
uint16_t network_enabled_on_boot;
/* ISO15765-2 Transport Layer */
int16_t iso15765_separation_time_offset;
STextAPISettings text_api;
struct
{
uint32_t disableUsbCheckOnBoot : 1;
uint32_t enableLatencyTest : 1;
uint32_t reserved : 30;
} flags;
} valuecan4_1_2_settings_t, valuecan4_1_settings_t, valuecan4_2_settings_t;
typedef struct {
uint16_t perf_en;
CAN_SETTINGS can1;
CANFD_SETTINGS canfd1;
CAN_SETTINGS can2;
CANFD_SETTINGS canfd2;
CAN_SETTINGS can3;
CANFD_SETTINGS canfd3;
CAN_SETTINGS can4;
CANFD_SETTINGS canfd4;
uint16_t network_enables;
uint16_t network_enables_2;
LIN_SETTINGS lin1;
uint16_t network_enabled_on_boot;
int16_t iso15765_separation_time_offset;
uint16_t iso_9141_kwp_enable_reserved;
ISO9141_KEYWORD2000_SETTINGS iso9141_kwp_settings_1;
uint16_t iso_parity_1;
uint16_t iso_msg_termination_1;
uint16_t network_enables_3;
STextAPISettings text_api;
uint64_t termination_enables;
ETHERNET_SETTINGS ethernet;
struct
{
uint32_t enableLatencyTest : 1;
uint32_t enablePcEthernetComm : 1;
uint32_t reserved : 30;
} flags;
uint16_t pwr_man_enable;
uint16_t pwr_man_timeout;
} valuecan4_4_2el_settings_t, valuecan4_4_settings_t, valuecan4_2el_settings_t;
#pragma pack(pop)
#ifdef __cplusplus
} // End of namespace
#endif // __cplusplus
#endif
@@ -0,0 +1,35 @@
#ifndef __VALUECAN4_1_H_
#define __VALUECAN4_1_H_
#include "icsneo/device/valuecan4/valuecan4.h"
#include "icsneo/device/valuecan4/settings/valuecan4-1settings.h"
#include <string>
namespace icsneo {
class ValueCAN4_1 : public ValueCAN4 {
public:
// Serial numbers start with V1 for 4-1
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_1;
ValueCAN4_1(neodevice_t neodevice) : ValueCAN4(neodevice) {
com = MakeCommunication(getWritableNeoDevice());
com->encoder->supportCANFD = false; // VCAN 4-1 does not support CAN FD
settings = std::unique_ptr<IDeviceSettings>(new ValueCAN4_1Settings(com));
getWritableNeoDevice().type = DEVICE_TYPE;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == "V1")
found.push_back(std::make_shared<ValueCAN4_1>(neodevice));
}
return found;
}
};
}
#endif
@@ -0,0 +1,34 @@
#ifndef __VALUECAN4_2_H_
#define __VALUECAN4_2_H_
#include "icsneo/device/valuecan4/valuecan4.h"
#include "icsneo/device/valuecan4/settings/valuecan4-2settings.h"
#include <string>
namespace icsneo {
class ValueCAN4_2 : public ValueCAN4 {
public:
// Serial numbers start with V2 for 4-2
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_2;
ValueCAN4_2(neodevice_t neodevice) : ValueCAN4(neodevice) {
com = MakeCommunication(getWritableNeoDevice());
settings = std::unique_ptr<IDeviceSettings>(new ValueCAN4_2Settings(com));
getWritableNeoDevice().type = DEVICE_TYPE;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == "V2")
found.push_back(std::make_shared<ValueCAN4_2>(neodevice));
}
return found;
}
};
}
#endif
@@ -0,0 +1,34 @@
#ifndef __VALUECAN4_2EL_H_
#define __VALUECAN4_2EL_H_
#include "icsneo/device/valuecan4/valuecan4.h"
#include "icsneo/device/valuecan4/settings/valuecan4-2elsettings.h"
#include <string>
namespace icsneo {
class ValueCAN4_2EL : public ValueCAN4 {
public:
// Serial numbers start with VE for 4-2EL
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_2EL;
ValueCAN4_2EL(neodevice_t neodevice) : ValueCAN4(neodevice) {
com = MakeCommunication(getWritableNeoDevice());
settings = std::unique_ptr<IDeviceSettings>(new ValueCAN4_2ELSettings(com));
getWritableNeoDevice().type = DEVICE_TYPE;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == "VE")
found.push_back(std::make_shared<ValueCAN4_2EL>(neodevice));
}
return found;
}
};
}
#endif
@@ -0,0 +1,34 @@
#ifndef __VALUECAN4_4_H_
#define __VALUECAN4_4_H_
#include "icsneo/device/valuecan4/valuecan4.h"
#include "icsneo/device/valuecan4/settings/valuecan4-4settings.h"
#include <string>
namespace icsneo {
class ValueCAN4_4 : public ValueCAN4 {
public:
// Serial numbers start with V4 for 4-4
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_4;
ValueCAN4_4(neodevice_t neodevice) : ValueCAN4(neodevice) {
com = MakeCommunication(getWritableNeoDevice());
settings = std::unique_ptr<IDeviceSettings>(new ValueCAN4_4Settings(com));
getWritableNeoDevice().type = DEVICE_TYPE;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == "V4")
found.push_back(std::make_shared<ValueCAN4_4>(neodevice));
}
return found;
}
};
}
#endif
@@ -0,0 +1,30 @@
#ifndef __VALUECAN4_H_
#define __VALUECAN4_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/stm32.h"
namespace icsneo {
class ValueCAN4 : public Device {
public:
static constexpr const uint16_t PRODUCT_ID = 0x1101;
ValueCAN4(neodevice_t neodevice) : Device(neodevice) {
productId = PRODUCT_ID;
}
protected:
static std::shared_ptr<Communication> MakeCommunication(neodevice_t& nd) {
auto transport = std::unique_ptr<ICommunication>(new STM32(nd));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
encoder->supportCANFD = true;
auto decoder = std::unique_ptr<Decoder>(new Decoder());
return std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
}
};
}
#endif
+39
View File
@@ -0,0 +1,39 @@
#ifndef __VIVIDCAN_H_
#define __VIVIDCAN_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/stm32.h"
namespace icsneo {
class VividCAN : public Device {
public:
// Serial numbers start with VV
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VividCAN;
static constexpr const uint16_t PRODUCT_ID = 0x1102;
VividCAN(neodevice_t neodevice) : Device(neodevice) {
auto transport = std::unique_ptr<ICommunication>(new STM32(getWritableNeoDevice()));
auto packetizer = std::make_shared<Packetizer>();
auto encoder = std::unique_ptr<Encoder>(new Encoder(packetizer));
auto decoder = std::unique_ptr<Decoder>(new Decoder());
com = std::make_shared<Communication>(std::move(transport), packetizer, std::move(encoder), std::move(decoder));
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
bool goOnline() { return false; }
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(PRODUCT_ID))
found.push_back(std::make_shared<VividCAN>(neodevice));
return found;
}
};
}
#endif
File diff suppressed because it is too large Load Diff
+194
View File
@@ -0,0 +1,194 @@
#ifndef __ICSNEOC_H_
#define __ICSNEOC_H_
#include <stddef.h>
#include "icsneo/device/neodevice.h" // For neodevice_t
#include "icsneo/communication/message/neomessage.h" // For neomessage_t and friends
#include "icsneo/platform/dynamiclib.h" // Dynamic library loading and exporting
#ifndef ICSNEOC_DYNAMICLOAD
#ifdef __cplusplus
extern "C" {
#endif
extern void DLLExport icsneo_findAllDevices(neodevice_t* devices, size_t* count);
extern void DLLExport icsneo_freeUnconnectedDevices();
extern bool DLLExport icsneo_serialNumToString(uint32_t num, char* str, size_t* count);
extern uint32_t DLLExport icsneo_serialStringToNum(const char* str);
extern bool DLLExport icsneo_isValidNeoDevice(const neodevice_t* device);
extern bool DLLExport icsneo_openDevice(const neodevice_t* device);
extern bool DLLExport icsneo_closeDevice(const neodevice_t* device);
extern bool DLLExport icsneo_goOnline(const neodevice_t* device);
extern bool DLLExport icsneo_goOffline(const neodevice_t* device);
extern bool DLLExport icsneo_isOnline(const neodevice_t* device);
extern bool DLLExport icsneo_enableMessagePolling(const neodevice_t* device);
extern bool DLLExport icsneo_disableMessagePolling(const neodevice_t* device);
extern bool DLLExport icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_t* items);
extern size_t DLLExport icsneo_getPollingMessageLimit(const neodevice_t* device);
extern bool DLLExport icsneo_setPollingMessageLimit(const neodevice_t* device, size_t newLimit);
extern bool DLLExport icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLength);
extern bool DLLExport icsneo_settingsRefresh(const neodevice_t* device);
extern bool DLLExport icsneo_settingsApply(const neodevice_t* device);
extern bool DLLExport icsneo_settingsApplyTemporary(const neodevice_t* device);
extern bool DLLExport icsneo_settingsApplyDefaults(const neodevice_t* device);
extern bool DLLExport icsneo_settingsApplyDefaultsTemporary(const neodevice_t* device);
extern bool DLLExport icsneo_setBaudrate(const neodevice_t* device, uint16_t netid, uint32_t newBaudrate);
extern bool DLLExport icsneo_transmit(const neodevice_t* device, const neomessage_t* message);
extern bool DLLExport icsneo_transmitMessages(const neodevice_t* device, const neomessage_t* messages, size_t count);
#ifdef __cplusplus
} // extern "C"
#endif
#else // ICSNEOC_DYNAMICLOAD
typedef void(*fn_icsneo_findAllDevices)(neodevice_t* devices, size_t* count);
fn_icsneo_findAllDevices icsneo_findAllDevices;
typedef void(*fn_icsneo_freeUnconnectedDevices)();
fn_icsneo_freeUnconnectedDevices icsneo_freeUnconnectedDevices;
typedef bool(*fn_icsneo_serialNumToString)(uint32_t num, char* str, size_t* count);
fn_icsneo_serialNumToString icsneo_serialNumToString;
typedef uint32_t(*fn_icsneo_serialStringToNum)(const char* str);
fn_icsneo_serialStringToNum icsneo_serialStringToNum;
typedef bool(*fn_icsneo_isValidNeoDevice)(const neodevice_t* device);
fn_icsneo_isValidNeoDevice icsneo_isValidNeoDevice;
typedef bool(*fn_icsneo_openDevice)(const neodevice_t* device);
fn_icsneo_openDevice icsneo_openDevice;
typedef bool(*fn_icsneo_closeDevice)(const neodevice_t* device);
fn_icsneo_closeDevice icsneo_closeDevice;
typedef bool(*fn_icsneo_goOnline)(const neodevice_t* device);
fn_icsneo_goOnline icsneo_goOnline;
typedef bool(*fn_icsneo_goOffline)(const neodevice_t* device);
fn_icsneo_goOffline icsneo_goOffline;
typedef bool(*fn_icsneo_isOnline)(const neodevice_t* device);
fn_icsneo_isOnline icsneo_isOnline;
typedef bool(*fn_icsneo_enableMessagePolling)(const neodevice_t* device);
fn_icsneo_enableMessagePolling icsneo_enableMessagePolling;
typedef bool(*fn_icsneo_disableMessagePolling)(const neodevice_t* device);
fn_icsneo_disableMessagePolling icsneo_disableMessagePolling;
typedef bool(*fn_icsneo_getMessages)(const neodevice_t* device, neomessage_t* messages, size_t* items);
fn_icsneo_getMessages icsneo_getMessages;
typedef size_t(*fn_icsneo_getPollingMessageLimit)(const neodevice_t* device);
fn_icsneo_getPollingMessageLimit icsneo_getPollingMessageLimit;
typedef bool(*fn_icsneo_setPollingMessageLimit)(const neodevice_t* device, size_t newLimit);
fn_icsneo_setPollingMessageLimit icsneo_setPollingMessageLimit;
typedef bool(*fn_icsneo_getProductName)(const neodevice_t* device, char* str, size_t* maxLength);
fn_icsneo_getProductName icsneo_getProductName;
typedef bool(*fn_icsneo_settingsRefresh)(const neodevice_t* device);
fn_icsneo_settingsRefresh icsneo_settingsRefresh;
typedef bool(*fn_icsneo_settingsApply)(const neodevice_t* device);
fn_icsneo_settingsApply icsneo_settingsApply;
typedef bool(*fn_icsneo_settingsApplyTemporary)(const neodevice_t* device);
fn_icsneo_settingsApplyTemporary icsneo_settingsApplyTemporary;
typedef bool(*fn_icsneo_settingsApplyDefaults)(const neodevice_t* device);
fn_icsneo_settingsApplyDefaults icsneo_settingsApplyDefaults;
typedef bool(*fn_icsneo_settingsApplyDefaultsTemporary)(const neodevice_t* device);
fn_icsneo_settingsApplyDefaultsTemporary icsneo_settingsApplyDefaultsTemporary;
typedef bool(*fn_icsneo_setBaudrate)(const neodevice_t* device, uint16_t netid, uint32_t newBaudrate);
fn_icsneo_setBaudrate icsneo_setBaudrate;
typedef bool(*fn_icsneo_transmit)(const neodevice_t* device, const neomessage_t* message);
fn_icsneo_transmit icsneo_transmit;
typedef bool(*fn_icsneo_transmitMessages)(const neodevice_t* device, const neomessage_t* messages, size_t count);
fn_icsneo_transmitMessages icsneo_transmitMessages;
#define ICSNEO_IMPORT(func) func = (fn_##func)icsneo_dynamicLibraryGetFunction(icsneo_libraryHandle, #func)
#define ICSNEO_IMPORTASSERT(func) if((ICSNEO_IMPORT(func)) == NULL) return 3
void* icsneo_libraryHandle = NULL;
bool icsneo_initialized = false;
bool icsneo_destroyed = false;
int icsneo_init() {
icsneo_destroyed = false;
if(icsneo_initialized)
return 1;
icsneo_libraryHandle = icsneo_dynamicLibraryLoad();
if(icsneo_libraryHandle == NULL)
return 2;
ICSNEO_IMPORTASSERT(icsneo_findAllDevices);
ICSNEO_IMPORTASSERT(icsneo_freeUnconnectedDevices);
ICSNEO_IMPORTASSERT(icsneo_serialNumToString);
ICSNEO_IMPORTASSERT(icsneo_serialStringToNum);
ICSNEO_IMPORTASSERT(icsneo_isValidNeoDevice);
ICSNEO_IMPORTASSERT(icsneo_openDevice);
ICSNEO_IMPORTASSERT(icsneo_closeDevice);
ICSNEO_IMPORTASSERT(icsneo_goOnline);
ICSNEO_IMPORTASSERT(icsneo_goOffline);
ICSNEO_IMPORTASSERT(icsneo_isOnline);
ICSNEO_IMPORTASSERT(icsneo_enableMessagePolling);
ICSNEO_IMPORTASSERT(icsneo_disableMessagePolling);
ICSNEO_IMPORTASSERT(icsneo_getMessages);
ICSNEO_IMPORTASSERT(icsneo_getPollingMessageLimit);
ICSNEO_IMPORTASSERT(icsneo_setPollingMessageLimit);
ICSNEO_IMPORTASSERT(icsneo_getProductName);
ICSNEO_IMPORTASSERT(icsneo_settingsRefresh);
ICSNEO_IMPORTASSERT(icsneo_settingsApply);
ICSNEO_IMPORTASSERT(icsneo_settingsApplyTemporary);
ICSNEO_IMPORTASSERT(icsneo_settingsApplyDefaults);
ICSNEO_IMPORTASSERT(icsneo_settingsApplyDefaultsTemporary);
ICSNEO_IMPORTASSERT(icsneo_setBaudrate);
ICSNEO_IMPORTASSERT(icsneo_transmit);
ICSNEO_IMPORTASSERT(icsneo_transmitMessages);
icsneo_initialized = true;
return 0;
}
bool icsneo_close() ICSNEO_DESTRUCTOR {
icsneo_initialized = false;
if(icsneo_destroyed)
return true;
return icsneo_destroyed = icsneo_dynamicLibraryClose(icsneo_libraryHandle);
}
#endif // ICSNEOC_DYNAMICLOAD
#endif // __ICSNEOC_H_
+15
View File
@@ -0,0 +1,15 @@
#ifndef __ICSNEOCPP_H_
#define __ICSNEOCPP_H_
#include <vector>
#include <memory>
#include "icsneo/device/device.h"
namespace icsneo {
std::vector<std::shared_ptr<Device>> FindAllDevices();
}
#endif
+101
View File
@@ -0,0 +1,101 @@
#ifndef __ICSNEOLEGACY_H_
#define __ICSNEOLEGACY_H_
#include "icsneo/platform/dynamiclib.h" // Dynamic library loading and exporting
#include "icsneo/platform/tchar.h"
#include <stdint.h>
typedef uint8_t byte; // Typedef helper for the following include
#include "icsneo/icsnVC40.h" // Definitions for structs
#ifdef __cplusplus
extern "C" {
#endif
//Basic Functions
extern int DLLExport icsneoFindNeoDevices(unsigned long DeviceTypes, NeoDevice* pNeoDevice, int* pNumDevices);
extern int DLLExport icsneoOpenNeoDevice(NeoDevice* pNeoDevice, void** hObject, unsigned char* bNetworkIDs, int bConfigRead, int bSyncToPC);
extern int DLLExport icsneoClosePort(void* hObject, int* pNumberOfErrors);
extern void DLLExport icsneoFreeObject(void* hObject);
extern int DLLExport icsneoSerialNumberToString(unsigned long serial, char* data, unsigned long data_size);
//Message Functions
extern int DLLExport icsneoGetMessages(void* hObject, icsSpyMessage* pMsg, int* pNumberOfMessages, int* pNumberOfErrors);
extern int DLLExport icsneoTxMessages(void* hObject, icsSpyMessage* pMsg, int lNetworkID, int lNumMessages);
extern int DLLExport icsneoTxMessagesEx(void* hObject,icsSpyMessage* pMsg, unsigned int lNetworkID, unsigned int lNumMessages, unsigned int* NumTxed, unsigned int zero2);
extern int DLLExport icsneoWaitForRxMessagesWithTimeOut(void* hObject, unsigned int iTimeOut);
extern int DLLExport icsneoEnableNetworkRXQueue(void* hObject, int iEnable);
extern int DLLExport icsneoGetTimeStampForMsg(void* hObject, icsSpyMessage* pMsg, double* pTimeStamp);
extern void DLLExport icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus, int*lTxStatus, int*lRxStatus);
extern void DLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter, icsSpyMessage* pTxMsg,
int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent);
//Device Functions
extern int DLLExport icsneoGetConfiguration(void* hObject, unsigned char* pData, int* lNumBytes);
extern int DLLExport icsneoSendConfiguration(void* hObject, unsigned char* pData, int lNumBytes);
extern int DLLExport icsneoGetFireSettings(void* hObject, SFireSettings* pSettings, int iNumBytes);
extern int DLLExport icsneoSetFireSettings(void* hObject, SFireSettings* pSettings, int iNumBytes, int bSaveToEEPROM);
extern int DLLExport icsneoGetVCAN3Settings(void* hObject, SVCAN3Settings* pSettings, int iNumBytes);
extern int DLLExport icsneoSetVCAN3Settings(void* hObject, SVCAN3Settings* pSettings, int iNumBytes, int bSaveToEEPROM);
extern int DLLExport icsneoGetFire2Settings(void* hObject, SFire2Settings* pSettings, int iNumBytes);
extern int DLLExport icsneoSetFire2Settings(void* hObject, SFire2Settings* pSettings, int iNumBytes, int bSaveToEEPROM);
extern int DLLExport icsneoGetVCANRFSettings(void* hObject, SVCANRFSettings* pSettings, int iNumBytes);
extern int DLLExport icsneoSetVCANRFSettings(void* hObject, SVCANRFSettings* pSettings, int iNumBytes, int bSaveToEEPROM);
extern int DLLExport icsneoGetVCAN412Settings(void* hObject, SVCAN412Settings* pSettings, int iNumBytes);
extern int DLLExport icsneoSetVCAN412Settings(void* hObject, SVCAN412Settings* pSettings, int iNumBytes, int bSaveToEEPROM);
extern int DLLExport icsneoGetRADGalaxySettings(void* hObject, SRADGalaxySettings* pSettings, int iNumBytes);
extern int DLLExport icsneoSetRADGalaxySettings(void* hObject, SRADGalaxySettings* pSettings, int iNumBytes, int bSaveToEEPROM);
extern int DLLExport icsneoGetRADStar2Settings(void* hObject, SRADStar2Settings* pSettings, int iNumBytes);
extern int DLLExport icsneoSetRADStar2Settings(void* hObject, SRADStar2Settings* pSettings, int iNumBytes, int bSaveToEEPROM);
extern int DLLExport icsneoSetBitRate(void* hObject, int BitRate, int NetworkID);
extern int DLLExport icsneoGetDeviceParameters(void* hObject, char* pParameter, char* pValues, short ValuesLength);
extern int DLLExport icsneoSetDeviceParameters(void* hObject, char* pParmValue, int* pErrorIndex, int bSaveToEEPROM);
//Error Functions
extern int DLLExport icsneoGetLastAPIError(void* hObject, unsigned long* pErrorNumber);
extern int DLLExport icsneoGetErrorMessages(void* hObject, int* pErrorMsgs, int* pNumberOfErrors);
extern int DLLExport icsneoGetErrorInfo(int lErrorNumber, TCHAR*szErrorDescriptionShort, TCHAR*szErrorDescriptionLong, int* lMaxLengthShort, int* lMaxLengthLong,int* lErrorSeverity,int* lRestartNeeded);
//ISO15765-2 Functions
extern int DLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks);
extern int DLLExport icsneoISO15765_DisableNetworks(void* hObject);
extern int DLLExport icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stCM_ISO157652_TxMessage* pMsg, unsigned long ulBlockingTimeout);
extern int DLLExport icsneoISO15765_ReceiveMessage(void* hObject,int ulNetworkID, stCM_ISO157652_RxMessage* pMsg);
//General Utility Functions
extern int DLLExport icsneoValidateHObject(void* hObject);
extern int DLLExport icsneoGetDLLVersion(void);
extern int DLLExport icsneoGetSerialNumber(void* hObject, unsigned int*iSerialNumber);
extern int DLLExport icsneoStartSockServer(void* hObject, int iPort);
extern int DLLExport icsneoStopSockServer(void* hObject);
//CoreMini Script functions
extern int DLLExport icsneoScriptStart(void* hObject, int iLocation);
extern int DLLExport icsneoScriptStop(void* hObject);
extern int DLLExport icsneoScriptLoad(void* hObject, const unsigned char* bin, unsigned long len_bytes, int iLocation);
extern int DLLExport icsneoScriptClear(void* hObject, int iLocation);
extern int DLLExport icsneoScriptStartFBlock(void* hObject,unsigned int fb_index);
extern int DLLExport icsneoScriptGetFBlockStatus(void* hObject, unsigned int fb_index, int* piRunStatus);
extern int DLLExport icsneoScriptStopFBlock(void* hObject,unsigned int fb_index);
extern int DLLExport icsneoScriptGetScriptStatus(void* hObject, int* piStatus);
extern int DLLExport icsneoScriptReadAppSignal(void* hObject, unsigned int iIndex, double*dValue);
extern int DLLExport icsneoScriptWriteAppSignal(void* hObject, unsigned int iIndex, double dValue);
//Deprecated (but still suppored in the DLL)
extern int DLLExport icsneoOpenPortEx(void* lPortNumber, int lPortType, int lDriverType, int lIPAddressMSB, int lIPAddressLSBOrBaudRate, int bConfigRead, unsigned char* bNetworkID, int* hObject);
extern int DLLExport icsneoOpenPort(int lPortNumber, int lPortType, int lDriverType, unsigned char* bNetworkID, unsigned char* bSCPIDs, int* hObject);
extern int DLLExport icsneoEnableNetworkCom(void* hObject, int Enable);
extern int DLLExport icsneoFindAllCOMDevices(int lDriverType, int lGetSerialNumbers, int lStopAtFirst, int lUSBCommOnly, int* p_lDeviceTypes, int* p_lComPorts, int* p_lSerialNumbers, int*lNumDevices);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef __DEVICES_H_
#define __DEVICES_H_
#if defined _WIN32
#include "icsneo/platform/windows/devices.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/devices.h"
#else
#error "This platform is not supported by the devices driver, please add a definition!"
#endif
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef __DYNAMICLIB_H_
#define __DYNAMICLIB_H_
#if defined _WIN32
#include "icsneo/platform/windows/dynamiclib.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/dynamiclib.h"
#else
#warning "This platform is not supported by the dynamic library driver"
#endif
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef __FTDI_H_
#define __FTDI_H_
#define INTREPID_USB_VENDOR_ID (0x093c)
#if defined _WIN32
#include "icsneo/platform/windows/ftdi.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/ftdi.h"
#else
#warning "This platform is not supported by the FTDI driver"
#endif
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef __PCAP_H_
#define __PCAP_H_
#if defined _WIN32
#include "icsneo/platform/windows/pcap.h"
// #elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
// #include "icsneo/platform/posix/ftdi.h"
#else
#warning "This platform is not supported by the PCAP driver"
#endif
#endif
@@ -0,0 +1,6 @@
#ifndef __DYNAMICLIB_DARWIN_H_
#define __DYNAMICLIB_DARWIN_H_
#define icsneo_dynamicLibraryLoad() dlopen("/Users/paulywog/Code/icsneonext/build/libicsneoc.dylib", RTLD_LAZY)
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef __DEVICES_POSIX_H_
#define __DEVICES_POSIX_H_
#include "icsneo/device/neoobd2pro/neoobd2pro.h"
#include "icsneo/device/neoobd2sim/neoobd2sim.h"
#include "icsneo/device/neovifire/neovifire.h"
//#include "icsneo/device/neovifire2/neovifire2eth.h" Ethernet not yet supported
#include "icsneo/device/neovifire2/neovifire2usb.h"
#include "icsneo/device/plasion/neoviion.h"
#include "icsneo/device/plasion/neoviplasma.h"
//#include "icsneo/device/radgalaxy/radgalaxy.h" Ethernet not yet supported
//#include "icsneo/device/radstar2/radstar2eth.h" Ethernet not yet supported
#include "icsneo/device/radstar2/radstar2usb.h"
#include "icsneo/device/radsupermoon/radsupermoon.h"
#include "icsneo/device/valuecan3/valuecan3.h"
#include "icsneo/device/valuecan4/valuecan4-1.h"
#include "icsneo/device/valuecan4/valuecan4-2.h"
#include "icsneo/device/valuecan4/valuecan4-2el.h"
#include "icsneo/device/valuecan4/valuecan4-4.h"
#include "icsneo/device/vividcan/vividcan.h"
#endif
@@ -0,0 +1,24 @@
#ifndef __DYNAMICLIB_POSIX_H_
#define __DYNAMICLIB_POSIX_H_
#include <dlfcn.h>
#ifdef __APPLE__
#include "icsneo/platform/posix/darwin/dynamiclib.h"
#else
#include "icsneo/platform/posix/linux/dynamiclib.h"
#endif
// Nothing special is needed to export
#define DLLExport
// #ifndef ICSNEO_NO_AUTO_DESTRUCT
// #define ICSNEO_DESTRUCTOR __attribute__((destructor));
// #else
#define ICSNEO_DESTRUCTOR
// #endif
#define icsneo_dynamicLibraryGetFunction(handle, func) dlsym(handle, func)
#define icsneo_dynamicLibraryClose(handle) (dlclose(handle) == 0)
#endif
+51
View File
@@ -0,0 +1,51 @@
#ifndef __FTDI_POSIX_H_
#define __FTDI_POSIX_H_
#include <vector>
#include <memory>
#include <string>
#include <atomic>
#include <ftdi.hpp>
#include "icsneo/device/neodevice.h"
#include "icsneo/communication/icommunication.h"
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
namespace icsneo {
class FTDI : public ICommunication {
public:
static constexpr neodevice_handle_t INVALID_HANDLE = 0x7fffffff; // int32_t max value
static std::vector<neodevice_t> FindByProduct(int product);
static bool IsHandleValid(neodevice_handle_t handle);
FTDI(neodevice_t& forDevice);
~FTDI() { close(); }
bool open();
bool close();
bool isOpen() { return ftdiDevice.is_open(); }
private:
static Ftdi::Context context;
static neodevice_handle_t handleCounter;
class FTDIDevice : public Ftdi::Context {
public:
FTDIDevice() {}
FTDIDevice(const Ftdi::Context &x) : Ftdi::Context(x) {
handle = handleCounter++;
}
neodevice_handle_t handle = INVALID_HANDLE;
};
static std::vector<FTDIDevice> searchResultDevices;
static bool GetDeviceForHandle(neodevice_handle_t handle, FTDIDevice& device);
void readTask();
void writeTask();
bool openable; // Set to false in the constructor if the object has not been found in searchResultDevices
neodevice_t& device;
FTDIDevice ftdiDevice;
};
}
#endif
@@ -0,0 +1,6 @@
#ifndef __DYNAMICLIB_LINUX_H_
#define __DYNAMICLIB_LINUX_H_
#define icsneo_dynamicLibraryLoad() dlopen("libicsneoc.so", RTLD_LAZY)
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef __STM32_POSIX_H_
#define __STM32_POSIX_H_
#include "icsneo/communication/icommunication.h"
#include "icsneo/device/neodevice.h"
#include <chrono>
#include <stdint.h>
namespace icsneo {
class STM32 : public ICommunication {
public:
STM32(neodevice_t& forDevice) : device(forDevice) {}
static std::vector<neodevice_t> FindByProduct(int product);
bool open();
bool isOpen();
bool close();
private:
neodevice_t& device;
int fd = -1;
static constexpr neodevice_handle_t HANDLE_OFFSET = 10;
void readTask();
void writeTask();
};
}
#endif
+6
View File
@@ -0,0 +1,6 @@
#ifndef __TCHAR_POSIX_H_
#define __TCHAR_POSIX_H_
typedef char TCHAR;
#endif
+10
View File
@@ -0,0 +1,10 @@
#ifndef __REGISTRY_H_
#define __REGISTRY_H_
#if defined _WIN32
#include "icsneo/platform/windows/registry.h"
#else
#warning "This platform is not supported by the registry driver"
#endif
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef __STM32_H_
#define __STM32_H_
#define INTREPID_USB_VENDOR_ID (0x093c)
#if defined _WIN32
#include "icsneo/platform/windows/stm32.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/stm32.h"
#else
#warning "This platform is not supported by the STM32 driver"
#endif
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef __TCHAR_H_
#define __TCHAR_H_
#if defined _WIN32
// Windows does not need a TCHAR definition, as it is natively defined
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/tchar.h"
#else
#warning "Please add a definition for this platform's equivalent to TCHAR"
#endif
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef __DEVICES_WINDOWS_H_
#define __DEVICES_WINDOWS_H_
#include "icsneo/device/neoobd2pro/neoobd2pro.h"
#include "icsneo/device/neoobd2sim/neoobd2sim.h"
#include "icsneo/device/neovifire/neovifire.h"
#include "icsneo/device/neovifire2/neovifire2eth.h"
#include "icsneo/device/neovifire2/neovifire2usb.h"
#include "icsneo/device/plasion/neoviion.h"
#include "icsneo/device/plasion/neoviplasma.h"
#include "icsneo/device/radgalaxy/radgalaxy.h"
#include "icsneo/device/radstar2/radstar2eth.h"
#include "icsneo/device/radstar2/radstar2usb.h"
#include "icsneo/device/radsupermoon/radsupermoon.h"
#include "icsneo/device/valuecan3/valuecan3.h"
#include "icsneo/device/valuecan4/valuecan4-1.h"
#include "icsneo/device/valuecan4/valuecan4-2.h"
#include "icsneo/device/valuecan4/valuecan4-2el.h"
#include "icsneo/device/valuecan4/valuecan4-4.h"
#include "icsneo/device/vividcan/vividcan.h"
#endif
@@ -0,0 +1,19 @@
#ifndef __DYNAMICLIB_WINDOWS_H_
#define __DYNAMICLIB_WINDOWS_H_
#include <Windows.h>
#ifdef ICSNEOC_MAKEDLL
#define DLLExport __declspec(dllexport)
#else
#define DLLExport __declspec(dllimport)
#endif
// MSVC does not have the ability to specify a destructor
#define ICSNEO_DESTRUCTOR
#define icsneo_dynamicLibraryLoad() LoadLibrary(L"C:\\Users\\Phollinsky\\Code\\icsneonext\\build\\icsneoc.dll")
#define icsneo_dynamicLibraryGetFunction(handle, func) GetProcAddress((HMODULE) handle, func)
#define icsneo_dynamicLibraryClose(handle) FreeLibrary((HMODULE) handle)
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef __FTDI_WINDOWS_H_
#define __FTDI_WINDOWS_H_
#include "icsneo/platform/windows/vcp.h"
namespace icsneo {
class FTDI : public VCP {
public:
FTDI(neodevice_t& forDevice) : VCP(forDevice) {}
static std::vector<neodevice_t> FindByProduct(int product) { return VCP::FindByProduct(product, L"serenum"); }
};
}
#endif
@@ -0,0 +1,58 @@
#ifndef __PCAPDLL_WINDOWS_H_
#define __PCAPDLL_WINDOWS_H_
#include <Windows.h>
#include <winsock2.h>
#include <pcap.h>
#include <memory>
namespace icsneo {
// Helper loader for the PCAP DLL
class PCAPDLL {
public:
// The first time we use the DLL we keep it in here and it won't get freed until the user unloads us (for speed reasons)
static std::shared_ptr<PCAPDLL> lazyLoadHolder;
static bool lazyLoaded;
// Functions
typedef int(__cdecl* PCAPFINDDEVICE)(char* source, struct pcap_rmtauth* auth, pcap_if_t** alldevs, char* errbuf);
typedef pcap_t*(__cdecl* PCAPOPEN)(const char* source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth* auth, char* errbuf);
typedef void(__cdecl* PCAPFREEDEVS)(pcap_if_t* alldevsp);
typedef void(__cdecl* PCAPCLOSE)(pcap_t* p);
typedef int(__cdecl* PCAPSTATS)(pcap_t* p, struct pcap_stat* ps);
typedef int(__cdecl* PCAPNEXTEX)(pcap_t* p, struct pcap_pkthdr** pkt_header, const u_char** pkt_data);
typedef int(__cdecl* PCAPSENDPACKET)(pcap_t* p, const u_char* buf, int size);
// typedef pcap_send_queue*(__cdecl* PCAPSENDQUEUEALLOC)(u_int memsize);
// typedef int(__cdecl* PCAPSENDQUEUEQUEUE)(pcap_send_queue* queue, const struct pcap_pkthdr* pkt_header, const u_char* pkt_data);
// typedef void(__cdecl* PCAPSENDQUEUEDESTROY)(pcap_send_queue* queue);
// typedef u_int(__cdecl* PCAPSENDQUEUETRANSMIT)(pcap_t* p, pcap_send_queue* queue, int sync);
typedef int(__cdecl* PCAPDATALINK)(pcap_t* p);
typedef int(__cdecl* PCAPCREATESRCSTR)(char* source, int type, const char* host, const char* port, const char* name, char* errbuf);
typedef int(__cdecl* PCAPSETBUFF)(pcap_t* p, int dim);
PCAPFINDDEVICE findalldevs_ex;
PCAPOPEN open;
PCAPFREEDEVS freealldevs;
PCAPCLOSE close;
PCAPSTATS stats;
PCAPNEXTEX next_ex;
PCAPSENDPACKET sendpacket;
// PCAPSENDQUEUEALLOC sendqueue_alloc;
// PCAPSENDQUEUEQUEUE sendqueue_queue;
// PCAPSENDQUEUEDESTROY sendqueue_destroy;
// PCAPSENDQUEUETRANSMIT sendqueue_transmit;
PCAPDATALINK datalink;
PCAPCREATESRCSTR createsrcstr;
PCAPSETBUFF setbuff;
PCAPDLL();
~PCAPDLL() { closeDLL(); }
bool ok() const { return dll != nullptr; }
private:
HINSTANCE dll;
void closeDLL();
};
}
#endif
+76
View File
@@ -0,0 +1,76 @@
#ifndef __PCAP_WINDOWS_H_
#define __PCAP_WINDOWS_H_
#include "icsneo/platform/windows/internal/pcapdll.h"
#include "icsneo/device/neodevice.h"
#include "icsneo/communication/icommunication.h"
#include <string>
namespace icsneo {
class PCAP : public ICommunication {
public:
class PCAPFoundDevice {
public:
neodevice_t device;
std::vector<std::vector<uint8_t>> discoveryPackets;
};
static std::vector<PCAPFoundDevice> FindAll();
static std::string GetEthDevSerialFromMacAddress(uint8_t product, uint16_t macSerial);
static bool IsHandleValid(neodevice_handle_t handle);
PCAP(neodevice_t& forDevice);
bool open();
bool isOpen();
bool close();
private:
PCAPDLL pcap;
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };
neodevice_t& device;
uint8_t deviceMAC[6];
bool openable = true;
void readTask();
void writeTask();
class NetworkInterface {
public:
uint8_t uuid;
uint8_t macAddress[8];
std::string nameFromWinPCAP;
std::string nameFromWin32API;
std::string descriptionFromWinPCAP;
std::string descriptionFromWin32API;
std::string friendlyNameFromWin32API;
std::string fullName;
pcap_t* fp = nullptr;
pcap_stat stats;
};
static std::vector<NetworkInterface> knownInterfaces;
NetworkInterface interface;
class EthernetPacket {
public: // Don't worry about endian when setting fields, this is all taken care of in getBytestream
EthernetPacket() {};
EthernetPacket(const std::vector<uint8_t>& bytestream);
EthernetPacket(const uint8_t* data, size_t size);
int loadBytestream(const std::vector<uint8_t>& bytestream);
std::vector<uint8_t> getBytestream() const;
uint8_t errorWhileDecodingFromBytestream = 0; // Not part of final bytestream, only for checking the result of the constructor
uint8_t destMAC[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t srcMAC[6] = { 0x00, 0xFC, 0x70, 0xFF, 0xFF, 0xFF };
uint16_t etherType = 0xCAB1; // Big endian, Should be 0xCAB1 or 0xCAB2
uint32_t icsEthernetHeader = 0xAAAA5555; // Big endian, Should be 0xAAAA5555
// At this point in the packet, there is a 16-bit payload size, little endian
// This is calculated from payload size in getBytestream
uint16_t packetNumber = 0;
bool firstPiece = true; // These booleans make up a 16-bit bitfield, packetInfo
bool lastPiece = true;
bool bufferHalfFull = false;
std::vector<uint8_t> payload;
};
};
}
#endif
@@ -0,0 +1,33 @@
#ifndef __REGISTRY_WINDOWS_H_
#define __REGISTRY_WINDOWS_H_
#include <Windows.h>
#include <string>
namespace icsneo {
class Registry {
public:
// Get string value
static bool Get(std::wstring path, std::wstring key, std::wstring& value);
static bool Get(std::string path, std::string key, std::string& value);
// Get DWORD value
static bool Get(std::wstring path, std::wstring key, uint32_t& value);
static bool Get(std::string path, std::string key, uint32_t& value);
private:
class Key {
public:
Key(std::wstring path, bool readwrite = false);
~Key();
HKEY GetKey() { return key; }
bool IsOpen() { return key != nullptr; }
private:
HKEY key;
};
};
}
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef __STM32_WINDOWS_H_
#define __STM32_WINDOWS_H_
#include "icsneo/platform/windows/vcp.h"
namespace icsneo {
class STM32 : public VCP {
public:
STM32(neodevice_t& forDevice) : VCP(forDevice) {}
static std::vector<neodevice_t> FindByProduct(int product) { return VCP::FindByProduct(product, L"usbser"); }
};
}
#endif
+48
View File
@@ -0,0 +1,48 @@
#ifndef __VCP_WINDOWS_H_
#define __VCP_WINDOWS_H_
#include <vector>
#include <string>
#include <thread>
#include <atomic>
#include <chrono>
#include <Windows.h>
#include "icsneo/device/neodevice.h"
#include "icsneo/communication/icommunication.h"
namespace icsneo {
// Virtual COM Port Communication
class VCP : public ICommunication {
public:
static std::vector<neodevice_t> FindByProduct(int product, wchar_t* driverName);
static bool IsHandleValid(neodevice_handle_t handle);
typedef void(*fn_boolCallback)(bool success);
VCP(neodevice_t& forDevice) : device(forDevice) {
overlappedRead.hEvent = INVALID_HANDLE_VALUE;
overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
overlappedWait.hEvent = INVALID_HANDLE_VALUE;
}
~VCP() { close(); }
bool open() { return open(false); }
void openAsync(fn_boolCallback callback);
bool close();
bool isOpen() { return handle != INVALID_HANDLE_VALUE; }
private:
bool open(bool fromAsync);
bool opening = false;
neodevice_t& device;
HANDLE handle = INVALID_HANDLE_VALUE;
OVERLAPPED overlappedRead = {};
OVERLAPPED overlappedWrite = {};
OVERLAPPED overlappedWait = {};
std::vector<std::shared_ptr<std::thread>> threads;
void readTask();
void writeTask();
};
}
#endif
@@ -0,0 +1,26 @@
*.ipch
*.suo
*.user
*.sdf
*.opensdf
*.exe
*.pdb
*.vs
*.VC.db
build/bin/
build/*.log
build/msvc14/*.log
build/msvc14/obj/
build/msvc12/*.log
build/msvc12/obj/
build/msvc11/*.log
build/msvc11/obj/
build/xcode/build/
tests/fuzztests/fuzztests.log
benchmarks/benchmarks.log
tests/CDSChecker/*.o
tests/CDSChecker/*.log
tests/CDSChecker/model-checker/
tests/relacy/freelist.exe
tests/relacy/spmchash.exe
tests/relacy/log.txt
+61
View File
@@ -0,0 +1,61 @@
This license file applies to everything in this repository except that which
is explicitly annotated as being written by other authors, i.e. the Boost
queue (included in the benchmarks for comparison), Intel's TBB library (ditto),
the CDSChecker tool (used for verification), the Relacy model checker (ditto),
and Jeff Preshing's semaphore implementation (used in the blocking queue) which
has a zlib license (embedded in blockingconcurrentqueue.h).
---
Simplified BSD License:
Copyright (c) 2013-2016, Cameron Desrochers.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
I have also chosen to dual-license under the Boost Software License as an alternative to
the Simplified BSD license above:
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+486
View File
@@ -0,0 +1,486 @@
# moodycamel::ConcurrentQueue<T>
An industrial-strength lock-free queue for C++.
Note: If all you need is a single-producer, single-consumer queue, I have [one of those too][spsc].
## Features
- Knock-your-socks-off [blazing fast performance][benchmarks].
- Single-header implementation. Just drop it in your project.
- Fully thread-safe lock-free queue. Use concurrently from any number of threads.
- C++11 implementation -- elements are moved (instead of copied) where possible.
- Templated, obviating the need to deal exclusively with pointers -- memory is managed for you.
- No artificial limitations on element types or maximum count.
- Memory can be allocated once up-front, or dynamically as needed.
- Fully portable (no assembly; all is done through standard C++11 primitives).
- Supports super-fast bulk operations.
- Includes a low-overhead blocking version (BlockingConcurrentQueue).
- Exception safe.
## Reasons to use
There are not that many full-fledged lock-free queues for C++. Boost has one, but it's limited to objects with trivial
assignment operators and trivial destructors, for example.
Intel's TBB queue isn't lock-free, and requires trivial constructors too.
There're many academic papers that implement lock-free queues in C++, but usable source code is
hard to find, and tests even more so.
This queue not only has less limitations than others (for the most part), but [it's also faster][benchmarks].
It's been fairly well-tested, and offers advanced features like **bulk enqueueing/dequeueing**
(which, with my new design, is much faster than one element at a time, approaching and even surpassing
the speed of a non-concurrent queue even under heavy contention).
In short, there was a lock-free queue shaped hole in the C++ open-source universe, and I set out
to fill it with the fastest, most complete, and well-tested design and implementation I could.
The result is `moodycamel::ConcurrentQueue` :-)
## Reasons *not* to use
The fastest synchronization of all is the kind that never takes place. Fundamentally,
concurrent data structures require some synchronization, and that takes time. Every effort
was made, of course, to minimize the overhead, but if you can avoid sharing data between
threads, do so!
Why use concurrent data structures at all, then? Because they're gosh darn convenient! (And, indeed,
sometimes sharing data concurrently is unavoidable.)
My queue is **not linearizable** (see the next section on high-level design). The foundations of
its design assume that producers are independent; if this is not the case, and your producers
co-ordinate amongst themselves in some fashion, be aware that the elements won't necessarily
come out of the queue in the same order they were put in *relative to the ordering formed by that co-ordination*
(but they will still come out in the order they were put in by any *individual* producer). If this affects
your use case, you may be better off with another implementation; either way, it's an important limitation
to be aware of.
My queue is also **not NUMA aware**, and does a lot of memory re-use internally, meaning it probably doesn't
scale particularly well on NUMA architectures; however, I don't know of any other lock-free queue that *is*
NUMA aware (except for [SALSA][salsa], which is very cool, but has no publicly available implementation that I know of).
Finally, the queue is **not sequentially consistent**; there *is* a happens-before relationship between when an element is put
in the queue and when it comes out, but other things (such as pumping the queue until it's empty) require more thought
to get right in all eventualities, because explicit memory ordering may have to be done to get the desired effect. In other words,
it can sometimes be difficult to use the queue correctly. This is why it's a good idea to follow the [samples][samples.md] where possible.
On the other hand, the upside of this lack of sequential consistency is better performance.
## High-level design
Elements are stored internally using contiguous blocks instead of linked lists for better performance.
The queue is made up of a collection of sub-queues, one for each producer. When a consumer
wants to dequeue an element, it checks all the sub-queues until it finds one that's not empty.
All of this is largely transparent to the user of the queue, however -- it mostly just works<sup>TM</sup>.
One particular consequence of this design, however, (which seems to be non-intuitive) is that if two producers
enqueue at the same time, there is no defined ordering between the elements when they're later dequeued.
Normally this is fine, because even with a fully linearizable queue there'd be a race between the producer
threads and so you couldn't rely on the ordering anyway. However, if for some reason you do extra explicit synchronization
between the two producer threads yourself, thus defining a total order between enqueue operations, you might expect
that the elements would come out in the same total order, which is a guarantee my queue does not offer. At that
point, though, there semantically aren't really two separate producers, but rather one that happens to be spread
across multiple threads. In this case, you can still establish a total ordering with my queue by creating
a single producer token, and using that from both threads to enqueue (taking care to synchronize access to the token,
of course, but there was already extra synchronization involved anyway).
I've written a more detailed [overview of the internal design][blog], as well as [the full
nitty-gritty details of the design][design], on my blog. Finally, the
[source][source] itself is available for perusal for those interested in its implementation.
## Basic use
The entire queue's implementation is contained in **one header**, [`concurrentqueue.h`][concurrentqueue.h].
Simply download and include that to use the queue. The blocking version is in a separate header,
[`blockingconcurrentqueue.h`][blockingconcurrentqueue.h], that depends on the first.
The implementation makes use of certain key C++11 features, so it requires a fairly recent compiler
(e.g. VS2012+ or g++ 4.8; note that g++ 4.6 has a known bug with `std::atomic` and is thus not supported).
The algorithm implementations themselves are platform independent.
Use it like you would any other templated queue, with the exception that you can use
it from many threads at once :-)
Simple example:
#include "concurrentqueue.h"
moodycamel::ConcurrentQueue<int> q;
q.enqueue(25);
int item;
bool found = q.try_dequeue(item);
assert(found && item == 25);
Description of basic methods:
- `ConcurrentQueue(size_t initialSizeEstimate)`
Constructor which optionally accepts an estimate of the number of elements the queue will hold
- `enqueue(T&& item)`
Enqueues one item, allocating extra space if necessary
- `try_enqueue(T&& item)`
Enqueues one item, but only if enough memory is already allocated
- `try_dequeue(T& item)`
Dequeues one item, returning true if an item was found or false if the queue appeared empty
Note that it is up to the user to ensure that the queue object is completely constructed before
being used by any other threads (this includes making the memory effects of construction
visible, possibly via a memory barrier). Similarly, it's important that all threads have
finished using the queue (and the memory effects have fully propagated) before it is
destructed.
There's usually two versions of each method, one "explicit" version that takes a user-allocated per-producer or
per-consumer token, and one "implicit" version that works without tokens. Using the explicit methods is almost
always faster (though not necessarily by a huge factor). Apart from performance, the primary distinction between them
is their sub-queue allocation behaviour for enqueue operations: Using the implicit enqueue methods causes an
automatically-allocated thread-local producer sub-queue to be allocated (it is marked for reuse once the thread exits).
Explicit producers, on the other hand, are tied directly to their tokens' lifetimes (and are also recycled as needed).
Full API (pseudocode):
# Allocates more memory if necessary
enqueue(item) : bool
enqueue(prod_token, item) : bool
enqueue_bulk(item_first, count) : bool
enqueue_bulk(prod_token, item_first, count) : bool
# Fails if not enough memory to enqueue
try_enqueue(item) : bool
try_enqueue(prod_token, item) : bool
try_enqueue_bulk(item_first, count) : bool
try_enqueue_bulk(prod_token, item_first, count) : bool
# Attempts to dequeue from the queue (never allocates)
try_dequeue(item&) : bool
try_dequeue(cons_token, item&) : bool
try_dequeue_bulk(item_first, max) : size_t
try_dequeue_bulk(cons_token, item_first, max) : size_t
# If you happen to know which producer you want to dequeue from
try_dequeue_from_producer(prod_token, item&) : bool
try_dequeue_bulk_from_producer(prod_token, item_first, max) : size_t
# A not-necessarily-accurate count of the total number of elements
size_approx() : size_t
## Blocking version
As mentioned above, a full blocking wrapper of the queue is provided that adds
`wait_dequeue` and `wait_dequeue_bulk` methods in addition to the regular interface.
This wrapper is extremely low-overhead, but slightly less fast than the non-blocking
queue (due to the necessary bookkeeping involving a lightweight semaphore).
There are also timed versions that allow a timeout to be specified (either in microseconds
or with a `std::chrono` object).
The only major caveat with the blocking version is that you must be careful not to
destroy the queue while somebody is waiting on it. This generally means you need to
know for certain that another element is going to come along before you call one of
the blocking methods. (To be fair, the non-blocking version cannot be destroyed while
in use either, but it can be easier to coordinate the cleanup.)
Blocking example:
#include "blockingconcurrentqueue.h"
moodycamel::BlockingConcurrentQueue<int> q;
std::thread producer([&]() {
for (int i = 0; i != 100; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(i % 10));
q.enqueue(i);
}
});
std::thread consumer([&]() {
for (int i = 0; i != 100; ++i) {
int item;
q.wait_dequeue(item);
assert(item == i);
if (q.wait_dequeue_timed(item, std::chrono::milliseconds(5))) {
++i;
assert(item == i);
}
}
});
producer.join();
consumer.join();
assert(q.size_approx() == 0);
## Advanced features
#### Tokens
The queue can take advantage of extra per-producer and per-consumer storage if
it's available to speed up its operations. This takes the form of "tokens":
You can create a consumer token and/or a producer token for each thread or task
(tokens themselves are not thread-safe), and use the methods that accept a token
as their first parameter:
moodycamel::ConcurrentQueue<int> q;
moodycamel::ProducerToken ptok(q);
q.enqueue(ptok, 17);
moodycamel::ConsumerToken ctok(q);
int item;
q.try_dequeue(ctok, item);
assert(item == 17);
If you happen to know which producer you want to consume from (e.g. in
a single-producer, multi-consumer scenario), you can use the `try_dequeue_from_producer`
methods, which accept a producer token instead of a consumer token, and cut some overhead.
Note that tokens work with the blocking version of the queue too.
When producing or consuming many elements, the most efficient way is to:
1. Use the bulk methods of the queue with tokens
2. Failing that, use the bulk methods without tokens
3. Failing that, use the single-item methods with tokens
4. Failing that, use the single-item methods without tokens
Having said that, don't create tokens willy-nilly -- ideally there would be
one token (of each kind) per thread. The queue will work with what it is
given, but it performs best when used with tokens.
Note that tokens aren't actually tied to any given thread; it's not technically
required that they be local to the thread, only that they be used by a single
producer/consumer at a time.
#### Bulk operations
Thanks to the [novel design][blog] of the queue, it's just as easy to enqueue/dequeue multiple
items as it is to do one at a time. This means that overhead can be cut drastically for
bulk operations. Example syntax:
moodycamel::ConcurrentQueue<int> q;
int items[] = { 1, 2, 3, 4, 5 };
q.enqueue_bulk(items, 5);
int results[5]; // Could also be any iterator
size_t count = q.try_dequeue_bulk(results, 5);
for (size_t i = 0; i != count; ++i) {
assert(results[i] == items[i]);
}
#### Preallocation (correctly using `try_enqueue`)
`try_enqueue`, unlike just plain `enqueue`, will never allocate memory. If there's not enough room in the
queue, it simply returns false. The key to using this method properly, then, is to ensure enough space is
pre-allocated for your desired maximum element count.
The constructor accepts a count of the number of elements that it should reserve space for. Because the
queue works with blocks of elements, however, and not individual elements themselves, the value to pass
in order to obtain an effective number of pre-allocated element slots is non-obvious.
First, be aware that the count passed is rounded up to the next multiple of the block size. Note that the
default block size is 32 (this can be changed via the traits). Second, once a slot in a block has been
enqueued to, that slot cannot be re-used until the rest of the block has completely been completely filled
up and then completely emptied. This affects the number of blocks you need in order to account for the
overhead of partially-filled blocks. Third, each producer (whether implicit or explicit) claims and recycles
blocks in a different manner, which again affects the number of blocks you need to account for a desired number of
usable slots.
Suppose you want the queue to be able to hold at least `N` elements at any given time. Without delving too
deep into the rather arcane implementation details, here are some simple formulas for the number of elements
to request for pre-allocation in such a case. Note the division is intended to be arithmetic division and not
integer division (in order for `ceil()` to work).
For explicit producers (using tokens to enqueue):
(ceil(N / BLOCK_SIZE) + 1) * MAX_NUM_PRODUCERS * BLOCK_SIZE
For implicit producers (no tokens):
(ceil(N / BLOCK_SIZE) - 1 + 2 * MAX_NUM_PRODUCERS) * BLOCK_SIZE
When using mixed producer types:
((ceil(N / BLOCK_SIZE) - 1) * (MAX_EXPLICIT_PRODUCERS + 1) + 2 * (MAX_IMPLICIT_PRODUCERS + MAX_EXPLICIT_PRODUCERS)) * BLOCK_SIZE
If these formulas seem rather inconvenient, you can use the constructor overload that accepts the minimum
number of elements (`N`) and the maximum number of explicit and implicit producers directly, and let it do the
computation for you.
Finally, it's important to note that because the queue is only eventually consistent and takes advantage of
weak memory ordering for speed, there's always a possibility that under contention `try_enqueue` will fail
even if the queue is correctly pre-sized for the desired number of elements. (e.g. A given thread may think that
the queue's full even when that's no longer the case.) So no matter what, you still need to handle the failure
case (perhaps looping until it succeeds), unless you don't mind dropping elements.
#### Exception safety
The queue is exception safe, and will never become corrupted if used with a type that may throw exceptions.
The queue itself never throws any exceptions (operations fail gracefully (return false) if memory allocation
fails instead of throwing `std::bad_alloc`).
It is important to note that the guarantees of exception safety only hold if the element type never throws
from its destructor, and that any iterators passed into the queue (for bulk operations) never throw either.
Note that in particular this means `std::back_inserter` iterators must be used with care, since the vector
being inserted into may need to allocate and throw a `std::bad_alloc` exception from inside the iterator;
so be sure to reserve enough capacity in the target container first if you do this.
The guarantees are presently as follows:
- Enqueue operations are rolled back completely if an exception is thrown from an element's constructor.
For bulk enqueue operations, this means that elements are copied instead of moved (in order to avoid
having only some of the objects be moved in the event of an exception). Non-bulk enqueues always use
the move constructor if one is available.
- If the assignment operator throws during a dequeue operation (both single and bulk), the element(s) are
considered dequeued regardless. In such a case, the dequeued elements are all properly destructed before
the exception is propagated, but there's no way to get the elements themselves back.
- Any exception that is thrown is propagated up the call stack, at which point the queue is in a consistent
state.
Note: If any of your type's copy constructors/move constructors/assignment operators don't throw, be sure
to annotate them with `noexcept`; this will avoid the exception-checking overhead in the queue where possible
(even with zero-cost exceptions, there's still a code size impact that has to be taken into account).
#### Traits
The queue also supports a traits template argument which defines various types, constants,
and the memory allocation and deallocation functions that are to be used by the queue. The typical pattern
to providing your own traits is to create a class that inherits from the default traits
and override only the values you wish to change. Example:
struct MyTraits : public moodycamel::ConcurrentQueueDefaultTraits
{
static const size_t BLOCK_SIZE = 256; // Use bigger blocks
};
moodycamel::ConcurrentQueue<int, MyTraits> q;
#### How to dequeue types without calling the constructor
The normal way to dequeue an item is to pass in an existing object by reference, which
is then assigned to internally by the queue (using the move-assignment operator if possible).
This can pose a problem for types that are
expensive to construct or don't have a default constructor; fortunately, there is a simple
workaround: Create a wrapper class that copies the memory contents of the object when it
is assigned by the queue (a poor man's move, essentially). Note that this only works if
the object contains no internal pointers. Example:
struct MyObjectMover {
inline void operator=(MyObject&& obj)
{
std::memcpy(data, &obj, sizeof(MyObject));
// TODO: Cleanup obj so that when it's destructed by the queue
// it doesn't corrupt the data of the object we just moved it into
}
inline MyObject& obj() { return *reinterpret_cast<MyObject*>(data); }
private:
align(alignof(MyObject)) char data[sizeof(MyObject)];
};
A less dodgy alternative, if moves are cheap but default construction is not, is to use a
wrapper that defers construction until the object is assigned, enabling use of the move
constructor:
struct MyObjectMover {
inline void operator=(MyObject&& x) {
new (data) MyObject(std::move(x));
created = true;
}
inline MyObject& obj() {
assert(created);
return *reinterpret_cast<MyObject*>(data);
}
~MyObjectMover() {
if (created)
obj().~MyObject();
}
private:
align(alignof(MyObject)) char data[sizeof(MyObject)];
bool created = false;
};
## Samples
There are some more detailed samples [here][samples.md]. The source of
the [unit tests][unittest-src] and [benchmarks][benchmark-src] are available for reference as well.
## Benchmarks
See my blog post for some [benchmark results][benchmarks] (including versus `boost::lockfree::queue` and `tbb::concurrent_queue`),
or run the benchmarks yourself (requires MinGW and certain GnuWin32 utilities to build on Windows, or a recent
g++ on Linux):
cd build
make benchmarks
bin/benchmarks
The short version of the benchmarks is that it's so fast (especially the bulk methods), that if you're actually
using the queue to *do* anything, the queue won't be your bottleneck.
## Tests (and bugs)
I've written quite a few unit tests as well as a randomized long-running fuzz tester. I also ran the
core queue algorithm through the [CDSChecker][cdschecker] C++11 memory model model checker. Some of the
inner algorithms were tested separately using the [Relacy][relacy] model checker, and full integration
tests were also performed with Relacy.
I've tested
on Linux (Fedora 19) and Windows (7), but only on x86 processors so far (Intel and AMD). The code was
written to be platform-independent, however, and should work across all processors and OSes.
Due to the complexity of the implementation and the difficult-to-test nature of lock-free code in general,
there may still be bugs. If anyone is seeing buggy behaviour, I'd like to hear about it! (Especially if
a unit test for it can be cooked up.) Just open an issue on GitHub.
## License
I'm releasing the source of this repository (with the exception of third-party code, i.e. the Boost queue
(used in the benchmarks for comparison), Intel's TBB library (ditto), CDSChecker, Relacy, and Jeff Preshing's
cross-platform semaphore, which all have their own licenses)
under a simplified BSD license. I'm also dual-licensing under the Boost Software License.
See the [LICENSE.md][license] file for more details.
Note that lock-free programming is a patent minefield, and this code may very
well violate a pending patent (I haven't looked), though it does not to my present knowledge.
I did design and implement this queue from scratch.
## Diving into the code
If you're interested in the source code itself, it helps to have a rough idea of how it's laid out. This
section attempts to describe that.
The queue is formed of several basic parts (listed here in roughly the order they appear in the source). There's the
helper functions (e.g. for rounding to a power of 2). There's the default traits of the queue, which contain the
constants and malloc/free functions used by the queue. There's the producer and consumer tokens. Then there's the queue's
public API itself, starting with the constructor, destructor, and swap/assignment methods. There's the public enqueue methods,
which are all wrappers around a small set of private enqueue methods found later on. There's the dequeue methods, which are
defined inline and are relatively straightforward.
Then there's all the main internal data structures. First, there's a lock-free free list, used for recycling spent blocks (elements
are enqueued to blocks internally). Then there's the block structure itself, which has two different ways of tracking whether
it's fully emptied or not (remember, given two parallel consumers, there's no way to know which one will finish first) depending on where it's used.
Then there's a small base class for the two types of internal SPMC producer queues (one for explicit producers that holds onto memory
but attempts to be faster, and one for implicit ones which attempt to recycle more memory back into the parent but is a little slower).
The explicit producer is defined first, then the implicit one. They both contain the same general four methods: One to enqueue, one to
dequeue, one to enqueue in bulk, and one to dequeue in bulk. (Obviously they have constructors and destructors too, and helper methods.)
The main difference between them is how the block handling is done (they both use the same blocks, but in different ways, and map indices
to them in different ways).
Finally, there's the miscellaneous internal methods: There's the ones that handle the initial block pool (populated when the queue is constructed),
and an abstract block pool that comprises the initial pool and any blocks on the free list. There's ones that handle the producer list
(a lock-free add-only linked list of all the producers in the system). There's ones that handle the implicit producer lookup table (which
is really a sort of specialized TLS lookup). And then there's some helper methods for allocating and freeing objects, and the data members
of the queue itself, followed lastly by the free-standing swap functions.
[blog]: http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++
[design]: http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue
[samples.md]: https://github.com/cameron314/concurrentqueue/blob/master/samples.md
[source]: https://github.com/cameron314/concurrentqueue
[concurrentqueue.h]: https://github.com/cameron314/concurrentqueue/blob/master/concurrentqueue.h
[blockingconcurrentqueue.h]: https://github.com/cameron314/concurrentqueue/blob/master/blockingconcurrentqueue.h
[unittest-src]: https://github.com/cameron314/concurrentqueue/tree/master/tests/unittests
[benchmarks]: http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++#benchmarks
[benchmark-src]: https://github.com/cameron314/concurrentqueue/tree/master/benchmarks
[license]: https://github.com/cameron314/concurrentqueue/blob/master/LICENSE.md
[cdschecker]: http://demsky.eecs.uci.edu/c11modelchecker.html
[relacy]: http://www.1024cores.net/home/relacy-race-detector
[spsc]: https://github.com/cameron314/readerwriterqueue
[salsa]: http://webee.technion.ac.il/~idish/ftp/spaa049-gidron.pdf
@@ -0,0 +1,981 @@
// Provides an efficient blocking version of moodycamel::ConcurrentQueue.
// ©2015-2016 Cameron Desrochers. Distributed under the terms of the simplified
// BSD license, available at the top of concurrentqueue.h.
// Uses Jeff Preshing's semaphore implementation (under the terms of its
// separate zlib license, embedded below).
#pragma once
#include "concurrentqueue.h"
#include <type_traits>
#include <cerrno>
#include <memory>
#include <chrono>
#include <ctime>
#if defined(_WIN32)
// Avoid including windows.h in a header; we only need a handful of
// items, so we'll redeclare them here (this is relatively safe since
// the API generally has to remain stable between Windows versions).
// I know this is an ugly hack but it still beats polluting the global
// namespace with thousands of generic names or adding a .cpp for nothing.
extern "C" {
struct _SECURITY_ATTRIBUTES;
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName);
__declspec(dllimport) int __stdcall CloseHandle(void* hObject);
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount);
}
#elif defined(__MACH__)
#include <mach/mach.h>
#elif defined(__unix__)
#include <semaphore.h>
#endif
namespace moodycamel
{
namespace details
{
// Code in the mpmc_sema namespace below is an adaptation of Jeff Preshing's
// portable + lightweight semaphore implementations, originally from
// https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h
// LICENSE:
// Copyright (c) 2015 Jeff Preshing
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgement in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
namespace mpmc_sema
{
#if defined(_WIN32)
class Semaphore
{
private:
void* m_hSema;
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
const long maxLong = 0x7fffffff;
m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr);
}
~Semaphore()
{
CloseHandle(m_hSema);
}
void wait()
{
const unsigned long infinite = 0xffffffff;
WaitForSingleObject(m_hSema, infinite);
}
bool try_wait()
{
const unsigned long RC_WAIT_TIMEOUT = 0x00000102;
return WaitForSingleObject(m_hSema, 0) != RC_WAIT_TIMEOUT;
}
bool timed_wait(std::uint64_t usecs)
{
const unsigned long RC_WAIT_TIMEOUT = 0x00000102;
return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) != RC_WAIT_TIMEOUT;
}
void signal(int count = 1)
{
ReleaseSemaphore(m_hSema, count, nullptr);
}
};
#elif defined(__MACH__)
//---------------------------------------------------------
// Semaphore (Apple iOS and OSX)
// Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html
//---------------------------------------------------------
class Semaphore
{
private:
semaphore_t m_sema;
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
}
~Semaphore()
{
semaphore_destroy(mach_task_self(), m_sema);
}
void wait()
{
semaphore_wait(m_sema);
}
bool try_wait()
{
return timed_wait(0);
}
bool timed_wait(std::uint64_t timeout_usecs)
{
mach_timespec_t ts;
ts.tv_sec = static_cast<unsigned int>(timeout_usecs / 1000000);
ts.tv_nsec = (timeout_usecs % 1000000) * 1000;
// added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html
kern_return_t rc = semaphore_timedwait(m_sema, ts);
return rc != KERN_OPERATION_TIMED_OUT && rc != KERN_ABORTED;
}
void signal()
{
semaphore_signal(m_sema);
}
void signal(int count)
{
while (count-- > 0)
{
semaphore_signal(m_sema);
}
}
};
#elif defined(__unix__)
//---------------------------------------------------------
// Semaphore (POSIX, Linux)
//---------------------------------------------------------
class Semaphore
{
private:
sem_t m_sema;
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
sem_init(&m_sema, 0, initialCount);
}
~Semaphore()
{
sem_destroy(&m_sema);
}
void wait()
{
// http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error
int rc;
do {
rc = sem_wait(&m_sema);
} while (rc == -1 && errno == EINTR);
}
bool try_wait()
{
int rc;
do {
rc = sem_trywait(&m_sema);
} while (rc == -1 && errno == EINTR);
return !(rc == -1 && errno == EAGAIN);
}
bool timed_wait(std::uint64_t usecs)
{
struct timespec ts;
const int usecs_in_1_sec = 1000000;
const int nsecs_in_1_sec = 1000000000;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += usecs / usecs_in_1_sec;
ts.tv_nsec += (usecs % usecs_in_1_sec) * 1000;
// sem_timedwait bombs if you have more than 1e9 in tv_nsec
// so we have to clean things up before passing it in
if (ts.tv_nsec >= nsecs_in_1_sec) {
ts.tv_nsec -= nsecs_in_1_sec;
++ts.tv_sec;
}
int rc;
do {
rc = sem_timedwait(&m_sema, &ts);
} while (rc == -1 && errno == EINTR);
return !(rc == -1 && errno == ETIMEDOUT);
}
void signal()
{
sem_post(&m_sema);
}
void signal(int count)
{
while (count-- > 0)
{
sem_post(&m_sema);
}
}
};
#else
#error Unsupported platform! (No semaphore wrapper available)
#endif
//---------------------------------------------------------
// LightweightSemaphore
//---------------------------------------------------------
class LightweightSemaphore
{
public:
typedef std::make_signed<std::size_t>::type ssize_t;
private:
std::atomic<ssize_t> m_count;
Semaphore m_sema;
bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)
{
ssize_t oldCount;
// Is there a better way to set the initial spin count?
// If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC,
// as threads start hitting the kernel semaphore.
int spin = 10000;
while (--spin >= 0)
{
oldCount = m_count.load(std::memory_order_relaxed);
if ((oldCount > 0) && m_count.compare_exchange_strong(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
return true;
std::atomic_signal_fence(std::memory_order_acquire); // Prevent the compiler from collapsing the loop.
}
oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
if (oldCount > 0)
return true;
if (timeout_usecs < 0)
{
m_sema.wait();
return true;
}
if (m_sema.timed_wait((std::uint64_t)timeout_usecs))
return true;
// At this point, we've timed out waiting for the semaphore, but the
// count is still decremented indicating we may still be waiting on
// it. So we have to re-adjust the count, but only if the semaphore
// wasn't signaled enough times for us too since then. If it was, we
// need to release the semaphore too.
while (true)
{
oldCount = m_count.load(std::memory_order_acquire);
if (oldCount >= 0 && m_sema.try_wait())
return true;
if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
return false;
}
}
ssize_t waitManyWithPartialSpinning(ssize_t max, std::int64_t timeout_usecs = -1)
{
assert(max > 0);
ssize_t oldCount;
int spin = 10000;
while (--spin >= 0)
{
oldCount = m_count.load(std::memory_order_relaxed);
if (oldCount > 0)
{
ssize_t newCount = oldCount > max ? oldCount - max : 0;
if (m_count.compare_exchange_strong(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
return oldCount - newCount;
}
std::atomic_signal_fence(std::memory_order_acquire);
}
oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
if (oldCount <= 0)
{
if (timeout_usecs < 0)
m_sema.wait();
else if (!m_sema.timed_wait((std::uint64_t)timeout_usecs))
{
while (true)
{
oldCount = m_count.load(std::memory_order_acquire);
if (oldCount >= 0 && m_sema.try_wait())
break;
if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
return 0;
}
}
}
if (max > 1)
return 1 + tryWaitMany(max - 1);
return 1;
}
public:
LightweightSemaphore(ssize_t initialCount = 0) : m_count(initialCount)
{
assert(initialCount >= 0);
}
bool tryWait()
{
ssize_t oldCount = m_count.load(std::memory_order_relaxed);
while (oldCount > 0)
{
if (m_count.compare_exchange_weak(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
return true;
}
return false;
}
void wait()
{
if (!tryWait())
waitWithPartialSpinning();
}
bool wait(std::int64_t timeout_usecs)
{
return tryWait() || waitWithPartialSpinning(timeout_usecs);
}
// Acquires between 0 and (greedily) max, inclusive
ssize_t tryWaitMany(ssize_t max)
{
assert(max >= 0);
ssize_t oldCount = m_count.load(std::memory_order_relaxed);
while (oldCount > 0)
{
ssize_t newCount = oldCount > max ? oldCount - max : 0;
if (m_count.compare_exchange_weak(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
return oldCount - newCount;
}
return 0;
}
// Acquires at least one, and (greedily) at most max
ssize_t waitMany(ssize_t max, std::int64_t timeout_usecs)
{
assert(max >= 0);
ssize_t result = tryWaitMany(max);
if (result == 0 && max > 0)
result = waitManyWithPartialSpinning(max, timeout_usecs);
return result;
}
ssize_t waitMany(ssize_t max)
{
ssize_t result = waitMany(max, -1);
assert(result > 0);
return result;
}
void signal(ssize_t count = 1)
{
assert(count >= 0);
ssize_t oldCount = m_count.fetch_add(count, std::memory_order_release);
ssize_t toRelease = -oldCount < count ? -oldCount : count;
if (toRelease > 0)
{
m_sema.signal((int)toRelease);
}
}
ssize_t availableApprox() const
{
ssize_t count = m_count.load(std::memory_order_relaxed);
return count > 0 ? count : 0;
}
};
} // end namespace mpmc_sema
} // end namespace details
// This is a blocking version of the queue. It has an almost identical interface to
// the normal non-blocking version, with the addition of various wait_dequeue() methods
// and the removal of producer-specific dequeue methods.
template<typename T, typename Traits = ConcurrentQueueDefaultTraits>
class BlockingConcurrentQueue
{
private:
typedef ::moodycamel::ConcurrentQueue<T, Traits> ConcurrentQueue;
typedef details::mpmc_sema::LightweightSemaphore LightweightSemaphore;
public:
typedef typename ConcurrentQueue::producer_token_t producer_token_t;
typedef typename ConcurrentQueue::consumer_token_t consumer_token_t;
typedef typename ConcurrentQueue::index_t index_t;
typedef typename ConcurrentQueue::size_t size_t;
typedef typename std::make_signed<size_t>::type ssize_t;
static const size_t BLOCK_SIZE = ConcurrentQueue::BLOCK_SIZE;
static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = ConcurrentQueue::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD;
static const size_t EXPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::EXPLICIT_INITIAL_INDEX_SIZE;
static const size_t IMPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::IMPLICIT_INITIAL_INDEX_SIZE;
static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = ConcurrentQueue::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE;
static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = ConcurrentQueue::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE;
static const size_t MAX_SUBQUEUE_SIZE = ConcurrentQueue::MAX_SUBQUEUE_SIZE;
public:
// Creates a queue with at least `capacity` element slots; note that the
// actual number of elements that can be inserted without additional memory
// allocation depends on the number of producers and the block size (e.g. if
// the block size is equal to `capacity`, only a single block will be allocated
// up-front, which means only a single producer will be able to enqueue elements
// without an extra allocation -- blocks aren't shared between producers).
// This method is not thread safe -- it is up to the user to ensure that the
// queue is fully constructed before it starts being used by other threads (this
// includes making the memory effects of construction visible, possibly with a
// memory barrier).
explicit BlockingConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE)
: inner(capacity), sema(create<LightweightSemaphore>(), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)
{
assert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member");
if (!sema) {
MOODYCAMEL_THROW(std::bad_alloc());
}
}
BlockingConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers)
: inner(minCapacity, maxExplicitProducers, maxImplicitProducers), sema(create<LightweightSemaphore>(), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)
{
assert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member");
if (!sema) {
MOODYCAMEL_THROW(std::bad_alloc());
}
}
// Disable copying and copy assignment
BlockingConcurrentQueue(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
BlockingConcurrentQueue& operator=(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
// Moving is supported, but note that it is *not* a thread-safe operation.
// Nobody can use the queue while it's being moved, and the memory effects
// of that move must be propagated to other threads before they can use it.
// Note: When a queue is moved, its tokens are still valid but can only be
// used with the destination queue (i.e. semantically they are moved along
// with the queue itself).
BlockingConcurrentQueue(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT
: inner(std::move(other.inner)), sema(std::move(other.sema))
{ }
inline BlockingConcurrentQueue& operator=(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT
{
return swap_internal(other);
}
// Swaps this queue's state with the other's. Not thread-safe.
// Swapping two queues does not invalidate their tokens, however
// the tokens that were created for one queue must be used with
// only the swapped queue (i.e. the tokens are tied to the
// queue's movable state, not the object itself).
inline void swap(BlockingConcurrentQueue& other) MOODYCAMEL_NOEXCEPT
{
swap_internal(other);
}
private:
BlockingConcurrentQueue& swap_internal(BlockingConcurrentQueue& other)
{
if (this == &other) {
return *this;
}
inner.swap(other.inner);
sema.swap(other.sema);
return *this;
}
public:
// Enqueues a single item (by copying it).
// Allocates memory if required. Only fails if memory allocation fails (or implicit
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,
// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(T const& item)
{
if ((details::likely)(inner.enqueue(item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible).
// Allocates memory if required. Only fails if memory allocation fails (or implicit
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,
// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(T&& item)
{
if ((details::likely)(inner.enqueue(std::move(item)))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by copying it) using an explicit producer token.
// Allocates memory if required. Only fails if memory allocation fails (or
// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(producer_token_t const& token, T const& item)
{
if ((details::likely)(inner.enqueue(token, item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible) using an explicit producer token.
// Allocates memory if required. Only fails if memory allocation fails (or
// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Thread-safe.
inline bool enqueue(producer_token_t const& token, T&& item)
{
if ((details::likely)(inner.enqueue(token, std::move(item)))) {
sema->signal();
return true;
}
return false;
}
// Enqueues several items.
// Allocates memory if required. Only fails if memory allocation fails (or
// implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE
// is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Note: Use std::make_move_iterator if the elements should be moved instead of copied.
// Thread-safe.
template<typename It>
inline bool enqueue_bulk(It itemFirst, size_t count)
{
if ((details::likely)(inner.enqueue_bulk(std::forward<It>(itemFirst), count))) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Enqueues several items using an explicit producer token.
// Allocates memory if required. Only fails if memory allocation fails
// (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
// Note: Use std::make_move_iterator if the elements should be moved
// instead of copied.
// Thread-safe.
template<typename It>
inline bool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)
{
if ((details::likely)(inner.enqueue_bulk(token, std::forward<It>(itemFirst), count))) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Enqueues a single item (by copying it).
// Does not allocate memory. Fails if not enough room to enqueue (or implicit
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE
// is 0).
// Thread-safe.
inline bool try_enqueue(T const& item)
{
if (inner.try_enqueue(item)) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible).
// Does not allocate memory (except for one-time implicit producer).
// Fails if not enough room to enqueue (or implicit production is
// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).
// Thread-safe.
inline bool try_enqueue(T&& item)
{
if (inner.try_enqueue(std::move(item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by copying it) using an explicit producer token.
// Does not allocate memory. Fails if not enough room to enqueue.
// Thread-safe.
inline bool try_enqueue(producer_token_t const& token, T const& item)
{
if (inner.try_enqueue(token, item)) {
sema->signal();
return true;
}
return false;
}
// Enqueues a single item (by moving it, if possible) using an explicit producer token.
// Does not allocate memory. Fails if not enough room to enqueue.
// Thread-safe.
inline bool try_enqueue(producer_token_t const& token, T&& item)
{
if (inner.try_enqueue(token, std::move(item))) {
sema->signal();
return true;
}
return false;
}
// Enqueues several items.
// Does not allocate memory (except for one-time implicit producer).
// Fails if not enough room to enqueue (or implicit production is
// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).
// Note: Use std::make_move_iterator if the elements should be moved
// instead of copied.
// Thread-safe.
template<typename It>
inline bool try_enqueue_bulk(It itemFirst, size_t count)
{
if (inner.try_enqueue_bulk(std::forward<It>(itemFirst), count)) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Enqueues several items using an explicit producer token.
// Does not allocate memory. Fails if not enough room to enqueue.
// Note: Use std::make_move_iterator if the elements should be moved
// instead of copied.
// Thread-safe.
template<typename It>
inline bool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)
{
if (inner.try_enqueue_bulk(token, std::forward<It>(itemFirst), count)) {
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
return true;
}
return false;
}
// Attempts to dequeue from the queue.
// Returns false if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename U>
inline bool try_dequeue(U& item)
{
if (sema->tryWait()) {
while (!inner.try_dequeue(item)) {
continue;
}
return true;
}
return false;
}
// Attempts to dequeue from the queue using an explicit consumer token.
// Returns false if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename U>
inline bool try_dequeue(consumer_token_t& token, U& item)
{
if (sema->tryWait()) {
while (!inner.try_dequeue(token, item)) {
continue;
}
return true;
}
return false;
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued.
// Returns 0 if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename It>
inline size_t try_dequeue_bulk(It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued.
// Returns 0 if all producer streams appeared empty at the time they
// were checked (so, the queue is likely but not guaranteed to be empty).
// Never allocates. Thread-safe.
template<typename It>
inline size_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
}
return count;
}
// Blocks the current thread until there's something to dequeue, then
// dequeues it.
// Never allocates. Thread-safe.
template<typename U>
inline void wait_dequeue(U& item)
{
sema->wait();
while (!inner.try_dequeue(item)) {
continue;
}
}
// Blocks the current thread until either there's something to dequeue
// or the timeout (specified in microseconds) expires. Returns false
// without setting `item` if the timeout expires, otherwise assigns
// to `item` and returns true.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue.
// Never allocates. Thread-safe.
template<typename U>
inline bool wait_dequeue_timed(U& item, std::int64_t timeout_usecs)
{
if (!sema->wait(timeout_usecs)) {
return false;
}
while (!inner.try_dequeue(item)) {
continue;
}
return true;
}
// Blocks the current thread until either there's something to dequeue
// or the timeout expires. Returns false without setting `item` if the
// timeout expires, otherwise assigns to `item` and returns true.
// Never allocates. Thread-safe.
template<typename U, typename Rep, typename Period>
inline bool wait_dequeue_timed(U& item, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_timed(item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Blocks the current thread until there's something to dequeue, then
// dequeues it using an explicit consumer token.
// Never allocates. Thread-safe.
template<typename U>
inline void wait_dequeue(consumer_token_t& token, U& item)
{
sema->wait();
while (!inner.try_dequeue(token, item)) {
continue;
}
}
// Blocks the current thread until either there's something to dequeue
// or the timeout (specified in microseconds) expires. Returns false
// without setting `item` if the timeout expires, otherwise assigns
// to `item` and returns true.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue.
// Never allocates. Thread-safe.
template<typename U>
inline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::int64_t timeout_usecs)
{
if (!sema->wait(timeout_usecs)) {
return false;
}
while (!inner.try_dequeue(token, item)) {
continue;
}
return true;
}
// Blocks the current thread until either there's something to dequeue
// or the timeout expires. Returns false without setting `item` if the
// timeout expires, otherwise assigns to `item` and returns true.
// Never allocates. Thread-safe.
template<typename U, typename Rep, typename Period>
inline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_timed(token, item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued, which will
// always be at least one (this method blocks until the queue
// is non-empty) and at most max.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk(It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue_bulk.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::int64_t timeout_usecs)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Never allocates. Thread-safe.
template<typename It, typename Rep, typename Period>
inline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_bulk_timed<It&>(itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued, which will
// always be at least one (this method blocks until the queue
// is non-empty) and at most max.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Using a negative timeout indicates an indefinite timeout,
// and is thus functionally equivalent to calling wait_dequeue_bulk.
// Never allocates. Thread-safe.
template<typename It>
inline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::int64_t timeout_usecs)
{
size_t count = 0;
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);
while (count != max) {
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
}
return count;
}
// Attempts to dequeue several elements from the queue using an explicit consumer token.
// Returns the number of items actually dequeued, which can
// be 0 if the timeout expires while waiting for elements,
// and at most max.
// Never allocates. Thread-safe.
template<typename It, typename Rep, typename Period>
inline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)
{
return wait_dequeue_bulk_timed<It&>(token, itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
}
// Returns an estimate of the total number of elements currently in the queue. This
// estimate is only accurate if the queue has completely stabilized before it is called
// (i.e. all enqueue and dequeue operations have completed and their memory effects are
// visible on the calling thread, and no further operations start while this method is
// being called).
// Thread-safe.
inline size_t size_approx() const
{
return (size_t)sema->availableApprox();
}
// Returns true if the underlying atomic variables used by
// the queue are lock-free (they should be on most platforms).
// Thread-safe.
static bool is_lock_free()
{
return ConcurrentQueue::is_lock_free();
}
private:
template<typename U>
static inline U* create()
{
auto p = (Traits::malloc)(sizeof(U));
return p != nullptr ? new (p) U : nullptr;
}
template<typename U, typename A1>
static inline U* create(A1&& a1)
{
auto p = (Traits::malloc)(sizeof(U));
return p != nullptr ? new (p) U(std::forward<A1>(a1)) : nullptr;
}
template<typename U>
static inline void destroy(U* p)
{
if (p != nullptr) {
p->~U();
}
(Traits::free)(p);
}
private:
ConcurrentQueue inner;
std::unique_ptr<LightweightSemaphore, void (*)(LightweightSemaphore*)> sema;
};
template<typename T, typename Traits>
inline void swap(BlockingConcurrentQueue<T, Traits>& a, BlockingConcurrentQueue<T, Traits>& b) MOODYCAMEL_NOEXCEPT
{
a.swap(b);
}
} // end namespace moodycamel
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
#pragma once
//#define MCDBGQ_TRACKMEM 1
//#define MCDBGQ_NOLOCKFREE_FREELIST 1
//#define MCDBGQ_USEDEBUGFREELIST 1
//#define MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX 1
//#define MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH 1
#if defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
namespace moodycamel { namespace debug {
struct DebugMutex {
DebugMutex() { InitializeCriticalSectionAndSpinCount(&cs, 0x400); }
~DebugMutex() { DeleteCriticalSection(&cs); }
void lock() { EnterCriticalSection(&cs); }
void unlock() { LeaveCriticalSection(&cs); }
private:
CRITICAL_SECTION cs;
};
} }
#else
#include <mutex>
namespace moodycamel { namespace debug {
struct DebugMutex {
void lock() { m.lock(); }
void unlock() { m.unlock(); }
private:
std::mutex m;
};
} }
#define
#endif
namespace moodycamel { namespace debug {
struct DebugLock {
explicit DebugLock(DebugMutex& mutex)
: mutex(mutex)
{
mutex.lock();
}
~DebugLock()
{
mutex.unlock();
}
private:
DebugMutex& mutex;
};
template<typename N>
struct DebugFreeList {
DebugFreeList() : head(nullptr) { }
DebugFreeList(DebugFreeList&& other) : head(other.head) { other.head = nullptr; }
void swap(DebugFreeList& other) { std::swap(head, other.head); }
inline void add(N* node)
{
DebugLock lock(mutex);
node->freeListNext = head;
head = node;
}
inline N* try_get()
{
DebugLock lock(mutex);
if (head == nullptr) {
return nullptr;
}
auto prevHead = head;
head = head->freeListNext;
return prevHead;
}
N* head_unsafe() const { return head; }
private:
N* head;
DebugMutex mutex;
};
} }
+375
View File
@@ -0,0 +1,375 @@
# Samples for moodycamel::ConcurrentQueue
Here are some example usage scenarios with sample code. Note that most
use the simplest version of each available method for demonstration purposes,
but they can all be adapted to use tokens and/or the corresponding bulk methods for
extra speed.
## Hello queue
ConcurrentQueue<int> q;
for (int i = 0; i != 123; ++i)
q.enqueue(i);
int item;
for (int i = 0; i != 123; ++i) {
q.try_dequeue(item);
assert(item == i);
}
## Hello concurrency
Basic example of how to use the queue from multiple threads, with no
particular goal (i.e. it does nothing, but in an instructive way).
ConcurrentQueue<int> q;
int dequeued[100] = { 0 };
std::thread threads[20];
// Producers
for (int i = 0; i != 10; ++i) {
threads[i] = std::thread([&](int i) {
for (int j = 0; j != 10; ++j) {
q.enqueue(i * 10 + j);
}
}, i);
}
// Consumers
for (int i = 10; i != 20; ++i) {
threads[i] = std::thread([&]() {
int item;
for (int j = 0; j != 20; ++j) {
if (q.try_dequeue(item)) {
++dequeued[item];
}
}
});
}
// Wait for all threads
for (int i = 0; i != 20; ++i) {
threads[i].join();
}
// Collect any leftovers (could be some if e.g. consumers finish before producers)
int item;
while (q.try_dequeue(item)) {
++dequeued[item];
}
// Make sure everything went in and came back out!
for (int i = 0; i != 100; ++i) {
assert(dequeued[i] == 1);
}
## Bulk up
Same as previous example, but runs faster.
ConcurrentQueue<int> q;
int dequeued[100] = { 0 };
std::thread threads[20];
// Producers
for (int i = 0; i != 10; ++i) {
threads[i] = std::thread([&](int i) {
int items[10];
for (int j = 0; j != 10; ++j) {
items[j] = i * 10 + j;
}
q.enqueue_bulk(items, 10);
}, i);
}
// Consumers
for (int i = 10; i != 20; ++i) {
threads[i] = std::thread([&]() {
int items[20];
for (std::size_t count = q.try_dequeue_bulk(items, 20); count != 0; --count) {
++dequeued[items[count - 1]];
}
});
}
// Wait for all threads
for (int i = 0; i != 20; ++i) {
threads[i].join();
}
// Collect any leftovers (could be some if e.g. consumers finish before producers)
int items[10];
std::size_t count;
while ((count = q.try_dequeue_bulk(items, 10)) != 0) {
for (std::size_t i = 0; i != count; ++i) {
++dequeued[items[i]];
}
}
// Make sure everything went in and came back out!
for (int i = 0; i != 100; ++i) {
assert(dequeued[i] == 1);
}
## Producer/consumer model (simultaneous)
In this model, one set of threads is producing items,
and the other is consuming them concurrently until all of
them have been consumed. The counters are required to
ensure that all items eventually get consumed.
ConcurrentQueue<Item> q;
const int ProducerCount = 8;
const int ConsumerCount = 8;
std::thread producers[ProducerCount];
std::thread consumers[ConsumerCount];
std::atomic<int> doneProducers(0);
std::atomic<int> doneConsumers(0);
for (int i = 0; i != ProducerCount; ++i) {
producers[i] = std::thread([&]() {
while (produce) {
q.enqueue(produceItem());
}
doneProducers.fetch_add(1, std::memory_order_release);
});
}
for (int i = 0; i != ConsumerCount; ++i) {
consumers[i] = std::thread([&]() {
Item item;
bool itemsLeft;
do {
// It's important to fence (if the producers have finished) *before* dequeueing
itemsLeft = doneProducers.load(std::memory_order_acquire) != ProducerCount;
while (q.try_dequeue(item)) {
itemsLeft = true;
consumeItem(item);
}
} while (itemsLeft || doneConsumers.fetch_add(1, std::memory_order_acq_rel) + 1 == ConsumerCount);
// The condition above is a bit tricky, but it's necessary to ensure that the
// last consumer sees the memory effects of all the other consumers before it
// calls try_dequeue for the last time
});
}
for (int i = 0; i != ProducerCount; ++i) {
producers[i].join();
}
for (int i = 0; i != ConsumerCount; ++i) {
consumers[i].join();
}
## Producer/consumer model (simultaneous, blocking)
The blocking version is different, since either the number of elements being produced needs
to be known ahead of time, or some other coordination is required to tell the consumers when
to stop calling wait_dequeue (not shown here). This is necessary because otherwise a consumer
could end up blocking forever -- and destroying a queue while a consumer is blocking on it leads
to undefined behaviour.
BlockingConcurrentQueue<Item> q;
const int ProducerCount = 8;
const int ConsumerCount = 8;
std::thread producers[ProducerCount];
std::thread consumers[ConsumerCount];
std::atomic<int> promisedElementsRemaining(ProducerCount * 1000);
for (int i = 0; i != ProducerCount; ++i) {
producers[i] = std::thread([&]() {
for (int j = 0; j != 1000; ++j) {
q.enqueue(produceItem());
}
});
}
for (int i = 0; i != ConsumerCount; ++i) {
consumers[i] = std::thread([&]() {
Item item;
while (promisedElementsRemaining.fetch_sub(1, std::memory_order_relaxed)) {
q.wait_dequeue(item);
consumeItem(item);
}
});
}
for (int i = 0; i != ProducerCount; ++i) {
producers[i].join();
}
for (int i = 0; i != ConsumerCount; ++i) {
consumers[i].join();
}
## Producer/consumer model (separate stages)
ConcurrentQueue<Item> q;
// Production stage
std::thread threads[8];
for (int i = 0; i != 8; ++i) {
threads[i] = std::thread([&]() {
while (produce) {
q.enqueue(produceItem());
}
});
}
for (int i = 0; i != 8; ++i) {
threads[i].join();
}
// Consumption stage
std::atomic<int> doneConsumers(0);
for (int i = 0; i != 8; ++i) {
threads[i] = std::thread([&]() {
Item item;
do {
while (q.try_dequeue(item)) {
consumeItem(item);
}
// Loop again one last time if we're the last producer (with the acquired
// memory effects of the other producers):
} while (doneConsumers.fetch_add(1, std::memory_order_acq_rel) + 1 == 8);
});
}
for (int i = 0; i != 8; ++i) {
threads[i].join();
}
Note that there's no point trying to use the blocking queue with this model, since
there's no need to use the `wait` methods (all the elements are produced before any
are consumed), and hence the complexity would be the same but with additional overhead.
## Object pool
If you don't know what threads will be using the queue in advance,
you can't really declare any long-term tokens. The obvious solution
is to use the implicit methods (that don't take any tokens):
// A pool of 'Something' objects that can be safely accessed
// from any thread
class SomethingPool
{
public:
Something getSomething()
{
Something obj;
queue.try_dequeue(obj);
// If the dequeue succeeded, obj will be an object from the
// thread pool, otherwise it will be the default-constructed
// object as declared above
return obj;
}
void recycleSomething(Something&& obj)
{
queue.enqueue(std::move(obj));
}
};
## Threadpool task queue
BlockingConcurrentQueue<Task> q;
// To create a task from any thread:
q.enqueue(...);
// On threadpool threads:
Task task;
while (true) {
q.wait_dequeue(task);
// Process task...
}
## Multithreaded game loop
BlockingConcurrentQueue<Task> q;
std::atomic<int> pendingTasks(0);
// On threadpool threads:
Task task;
while (true) {
q.wait_dequeue(task);
// Process task...
pendingTasks.fetch_add(-1, std::memory_order_release);
}
// Whenever a new task needs to be processed for the frame:
pendingTasks.fetch_add(1, std::memory_order_release);
q.enqueue(...);
// To wait for all the frame's tasks to complete before rendering:
while (pendingTasks.load(std::memory_order_acquire) != 0)
continue;
// Alternatively you could help out the thread pool while waiting:
while (pendingTasks.load(std::memory_order_acquire) != 0) {
if (!q.try_dequeue(task)) {
continue;
}
// Process task...
pendingTasks.fetch_add(-1, std::memory_order_release);
}
## Pump until empty
This might be useful if, for example, you want to process any remaining items
in the queue before it's destroyed. Note that it is your responsibility
to ensure that the memory effects of any enqueue operations you wish to see on
the dequeue thread are visible (i.e. if you're waiting for a certain set of elements,
you need to use memory fences to ensure that those elements are visible to the dequeue
thread after they've been enqueued).
ConcurrentQueue<Item> q;
// Single-threaded pumping:
Item item;
while (q.try_dequeue(item)) {
// Process item...
}
// q is guaranteed to be empty here, unless there is another thread enqueueing still or
// there was another thread dequeueing at one point and its memory effects have not
// yet been propagated to this thread.
// Multi-threaded pumping:
std::thread threads[8];
std::atomic<int> doneConsumers(0);
for (int i = 0; i != 8; ++i) {
threads[i] = std::thread([&]() {
Item item;
do {
while (q.try_dequeue(item)) {
// Process item...
}
} while (doneConsumers.fetch_add(1, std::memory_order_acq_rel) + 1 == 8);
// If there are still enqueue operations happening on other threads,
// then the queue may not be empty at this point. However, if all enqueue
// operations completed before we finished pumping (and the propagation of
// their memory effects too), and all dequeue operations apart from those
// our threads did above completed before we finished pumping (and the
// propagation of their memory effects too), then the queue is guaranteed
// to be empty at this point.
});
}
for (int i = 0; i != 8; ++i) {
threads[i].join();
}
## Wait for a queue to become empty (without dequeueing)
You can't (robustly) :-) However, you can set up your own atomic counter and
poll that instead (see the game loop example). If you're satisfied with merely an estimate, you can use
`size_approx()`. Note that `size_approx()` may return 0 even if the queue is
not completely empty, unless the queue has already stabilized first (no threads
are enqueueing or dequeueing, and all memory effects of any previous operations
have been propagated to the thread before it calls `size_approx()`).
+359
View File
@@ -0,0 +1,359 @@
/*
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2007 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @ingroup packetapi
* @{
*/
/** @defgroup packet32h Packet.dll definitions and data structures
* Packet32.h contains the data structures and the definitions used by packet.dll.
* The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included
* by the applications that use the functions of this library
* @{
*/
#ifndef __PACKET32
#define __PACKET32
#include <winsock2.h>
#ifdef HAVE_AIRPCAP_API
#include <airpcap.h>
#else
#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)
#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_
typedef struct _AirpcapHandle *PAirpcapHandle;
#endif /* AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ */
#endif /* HAVE_AIRPCAP_API */
#ifdef HAVE_DAG_API
#include <dagc.h>
#endif /* HAVE_DAG_API */
// Working modes
#define PACKET_MODE_CAPT 0x0 ///< Capture mode
#define PACKET_MODE_STAT 0x1 ///< Statistical mode
#define PACKET_MODE_MON 0x2 ///< Monitoring mode
#define PACKET_MODE_DUMP 0x10 ///< Dump mode
#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode
/// Alignment macro. Defines the alignment size.
#define Packet_ALIGNMENT sizeof(int)
/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT.
#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
#define NdisMediumNull -1 ///< Custom linktype: NDIS doesn't provide an equivalent
#define NdisMediumCHDLC -2 ///< Custom linktype: NDIS doesn't provide an equivalent
#define NdisMediumPPPSerial -3 ///< Custom linktype: NDIS doesn't provide an equivalent
#define NdisMediumBare80211 -4 ///< Custom linktype: NDIS doesn't provide an equivalent
#define NdisMediumRadio80211 -5 ///< Custom linktype: NDIS doesn't provide an equivalent
#define NdisMediumPpi -6 ///< Custom linktype: NDIS doesn't provide an equivalent
// Loopback behaviour definitions
#define NPF_DISABLE_LOOPBACK 1 ///< Drop the packets sent by the NPF driver
#define NPF_ENABLE_LOOPBACK 2 ///< Capture the packets sent by the NPF driver
/*!
\brief Network type structure.
This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.
*/
typedef struct NetType
{
UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)
ULONGLONG LinkSpeed; ///< The speed of the network in bits per second
}NetType;
//some definitions stolen from libpcap
#ifndef BPF_MAJOR_VERSION
/*!
\brief A BPF pseudo-assembly program.
The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet.
*/
struct bpf_program
{
UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.
struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program.
};
/*!
\brief A single BPF pseudo-instruction.
bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
*/
struct bpf_insn
{
USHORT code; ///< Instruction type and addressing mode.
UCHAR jt; ///< Jump if true
UCHAR jf; ///< Jump if false
int k; ///< Generic field used for various purposes.
};
/*!
\brief Structure that contains a couple of statistics values on the current capture.
It is used by packet.dll to return statistics about a capture session.
*/
struct bpf_stat
{
UINT bs_recv; ///< Number of packets that the driver received from the network adapter
///< from the beginning of the current capture. This value includes the packets
///< lost by the driver.
UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
///< Basically, a packet is lost when the the buffer of the driver is full.
///< In this situation the packet cannot be stored and the driver rejects it.
UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
///< thus reach the application.
};
/*!
\brief Packet header.
This structure defines the header associated with every packet delivered to the application.
*/
struct bpf_hdr
{
struct timeval bh_tstamp; ///< The timestamp associated with the captured packet.
///< It is stored in a TimeVal structure.
UINT bh_caplen; ///< Length of captured portion. The captured portion <b>can be different</b>
///< from the original packet, because it is possible (with a proper filter)
///< to instruct the driver to capture only a portion of the packets.
UINT bh_datalen; ///< Original length of packet
USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases,
///< a padding could be added between the end of this structure and the packet
///< data for performance reasons. This filed can be used to retrieve the actual data
///< of the packet.
};
/*!
\brief Dump packet header.
This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().
It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a
packet in a dump file. This makes straightforward sending WinPcap dump files to the network.
*/
struct dump_bpf_hdr{
struct timeval ts; ///< Time stamp of the packet
UINT caplen; ///< Length of captured portion. The captured portion can smaller than the
///< the original packet, because it is possible (with a proper filter) to
///< instruct the driver to capture only a portion of the packets.
UINT len; ///< Length of the original packet (off wire).
};
#endif
struct bpf_stat;
#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices
#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links
#define NMAX_PACKET 65535
/*!
\brief Addresses of a network adapter.
This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with
an adapter.
*/
typedef struct npf_if_addr {
struct sockaddr_storage IPAddress; ///< IP address.
struct sockaddr_storage SubnetMask; ///< Netmask for that address.
struct sockaddr_storage Broadcast; ///< Broadcast address.
}npf_if_addr;
#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API.
#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API.
#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter
#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter, and it's managed by WANPACKET
#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card
#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file
#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones.
#define INFO_FLAG_AIRPCAP_CARD 16 ///< Flag for ADAPTER_INFO: this is an airpcap card
#define INFO_FLAG_NPFIM_DEVICE 32
/*!
\brief Describes an opened network adapter.
This structure is the most important for the functioning of packet.dll, but the great part of its fields
should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters
*/
typedef struct _ADAPTER {
HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver.
CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.
int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated
///< on the wire.
HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter.
///< It can be passed to standard Win32 functions (like WaitForSingleObject
///< or WaitForMultipleObjects) to wait until the driver's buffer contains some
///< data. It is particularly useful in GUI applications that need to wait
///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()
///< function can be used to define the minimum amount of data in the kernel buffer
///< that will cause the event to be signalled.
UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and
///< ReadEvent will be signaled, also if no packets were captured
CHAR Name[ADAPTER_NAME_LENGTH];
PWAN_ADAPTER pWanAdapter;
UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
#ifdef HAVE_AIRPCAP_API
PAirpcapHandle AirpcapAd;
#endif // HAVE_AIRPCAP_API
#ifdef HAVE_NPFIM_API
void* NpfImHandle;
#endif // HAVE_NPFIM_API
#ifdef HAVE_DAG_API
dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter
PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card
struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure
unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry
DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps).
#endif // HAVE_DAG_API
} ADAPTER, *LPADAPTER;
/*!
\brief Structure that contains a group of packets coming from the driver.
This structure defines the header associated with every packet delivered to the application.
*/
typedef struct _PACKET {
HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications.
OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications.
PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for
///< details about the organization of the data in this buffer
UINT Length; ///< Length of the buffer
DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data
///< received by the last call to PacketReceivePacket()
BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications.
} PACKET, *LPPACKET;
/*!
\brief Structure containing an OID request.
It is used by the PacketRequest() function to send an OID to the interface card driver.
It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address,
the list of the multicast groups defined on it, and so on.
*/
struct _PACKET_OID_DATA {
ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
///< for a complete list of valid codes.
ULONG Length; ///< Length of the data field
UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
///< from the adapter.
};
typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @}
*/
/*
BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName,
CHAR *Value,
UINT *pValueLen,
CHAR *DefaultVal);
BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName,
WCHAR *Value,
UINT *pValueLen,
WCHAR *DefaultVal);
*/
//---------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//---------------------------------------------------------------------------
PCHAR PacketGetVersion();
PCHAR PacketGetDriverVersion();
BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes);
BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites);
BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);
BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);
BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);
BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior);
INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen);
BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);
BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);
BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);
BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);
LPADAPTER PacketOpenAdapter(PCHAR AdapterName);
BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
LPPACKET PacketAllocatePacket(void);
VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);
VOID PacketFreePacket(LPPACKET lpPacket);
BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);
BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);
BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize);
BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);
BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData);
HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);
BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);
BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);
BOOL PacketStopDriver();
VOID PacketCloseAdapter(LPADAPTER lpAdapter);
BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength);
BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags);
PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject);
//
// Used by PacketStartOemEx
//
#define PACKET_START_OEM_NO_NETMON 0x00000001
#ifdef __cplusplus
}
#endif
#endif //__PACKET32
+113
View File
@@ -0,0 +1,113 @@
/*
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __WIN32_EXTENSIONS_H__
#define __WIN32_EXTENSIONS_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Definitions */
/*!
\brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit().
*/
struct pcap_send_queue
{
u_int maxlen; ///< Maximum size of the the queue, in bytes. This variable contains the size of the buffer field.
u_int len; ///< Current size of the queue, in bytes.
char *buffer; ///< Buffer containing the packets to be sent.
};
typedef struct pcap_send_queue pcap_send_queue;
/*!
\brief This typedef is a support for the pcap_get_airpcap_handle() function
*/
#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)
#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_
typedef struct _AirpcapHandle *PAirpcapHandle;
#endif
#define BPF_MEM_EX_IMM 0xc0
#define BPF_MEM_EX_IND 0xe0
/*used for ST*/
#define BPF_MEM_EX 0xc0
#define BPF_TME 0x08
#define BPF_LOOKUP 0x90
#define BPF_EXECUTE 0xa0
#define BPF_INIT 0xb0
#define BPF_VALIDATE 0xc0
#define BPF_SET_ACTIVE 0xd0
#define BPF_RESET 0xe0
#define BPF_SET_MEMORY 0x80
#define BPF_GET_REGISTER_VALUE 0x70
#define BPF_SET_REGISTER_VALUE 0x60
#define BPF_SET_WORKING 0x50
#define BPF_SET_ACTIVE_READ 0x40
#define BPF_SET_AUTODELETION 0x30
#define BPF_SEPARATION 0xff
/* Prototypes */
pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
void pcap_sendqueue_destroy(pcap_send_queue* queue);
int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);
HANDLE pcap_getevent(pcap_t *p);
struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);
int pcap_setuserbuffer(pcap_t *p, int size);
int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks);
int pcap_live_dump_ended(pcap_t *p, int sync);
int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data);
int pcap_start_oem(char* err_str, int flags);
PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p);
#ifdef __cplusplus
}
#endif
#endif //__WIN32_EXTENSIONS_H__
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright (C) 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BITTYPES_H
#define _BITTYPES_H
#ifndef HAVE_U_INT8_T
#if SIZEOF_CHAR == 1
typedef unsigned char u_int8_t;
typedef signed char int8_t;
#elif SIZEOF_INT == 1
typedef unsigned int u_int8_t;
typedef signed int int8_t;
#else /* XXX */
#error "there's no appropriate type for u_int8_t"
#endif
#define HAVE_U_INT8_T 1
#define HAVE_INT8_T 1
#endif /* HAVE_U_INT8_T */
#ifndef HAVE_U_INT16_T
#if SIZEOF_SHORT == 2
typedef unsigned short u_int16_t;
typedef signed short int16_t;
#elif SIZEOF_INT == 2
typedef unsigned int u_int16_t;
typedef signed int int16_t;
#elif SIZEOF_CHAR == 2
typedef unsigned char u_int16_t;
typedef signed char int16_t;
#else /* XXX */
#error "there's no appropriate type for u_int16_t"
#endif
#define HAVE_U_INT16_T 1
#define HAVE_INT16_T 1
#endif /* HAVE_U_INT16_T */
#ifndef HAVE_U_INT32_T
#if SIZEOF_INT == 4
typedef unsigned int u_int32_t;
typedef signed int int32_t;
#elif SIZEOF_LONG == 4
typedef unsigned long u_int32_t;
typedef signed long int32_t;
#elif SIZEOF_SHORT == 4
typedef unsigned short u_int32_t;
typedef signed short int32_t;
#else /* XXX */
#error "there's no appropriate type for u_int32_t"
#endif
#define HAVE_U_INT32_T 1
#define HAVE_INT32_T 1
#endif /* HAVE_U_INT32_T */
#ifndef HAVE_U_INT64_T
#if SIZEOF_LONG_LONG == 8
typedef unsigned long long u_int64_t;
typedef long long int64_t;
#elif defined(_MSC_EXTENSIONS)
typedef unsigned _int64 u_int64_t;
typedef _int64 int64_t;
#elif SIZEOF_INT == 8
typedef unsigned int u_int64_t;
#elif SIZEOF_LONG == 8
typedef unsigned long u_int64_t;
#elif SIZEOF_SHORT == 8
typedef unsigned short u_int64_t;
#else /* XXX */
#error "there's no appropriate type for u_int64_t"
#endif
#endif /* HAVE_U_INT64_T */
#ifndef PRId64
#ifdef _MSC_EXTENSIONS
#define PRId64 "I64d"
#else /* _MSC_EXTENSIONS */
#define PRId64 "lld"
#endif /* _MSC_EXTENSIONS */
#endif /* PRId64 */
#ifndef PRIo64
#ifdef _MSC_EXTENSIONS
#define PRIo64 "I64o"
#else /* _MSC_EXTENSIONS */
#define PRIo64 "llo"
#endif /* _MSC_EXTENSIONS */
#endif /* PRIo64 */
#ifndef PRIx64
#ifdef _MSC_EXTENSIONS
#define PRIx64 "I64x"
#else /* _MSC_EXTENSIONS */
#define PRIx64 "llx"
#endif /* _MSC_EXTENSIONS */
#endif /* PRIx64 */
#ifndef PRIu64
#ifdef _MSC_EXTENSIONS
#define PRIu64 "I64u"
#else /* _MSC_EXTENSIONS */
#define PRIu64 "llu"
#endif /* _MSC_EXTENSIONS */
#endif /* PRIu64 */
#endif /* _BITTYPES_H */
+163
View File
@@ -0,0 +1,163 @@
/*
* Copyright (c) 1993, 1994, 1997
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#) $Header: /tcpdump/master/libpcap/Win32/Include/ip6_misc.h,v 1.5 2006-01-22 18:02:18 gianluca Exp $ (LBL)
*/
/*
* This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows
*/
#include <winsock2.h>
#include <ws2tcpip.h>
#ifndef __MINGW32__
#define IN_MULTICAST(a) IN_CLASSD(a)
#endif
#define IN_EXPERIMENTAL(a) ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000)
#define IN_LOOPBACKNET 127
#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
/* IPv6 address */
struct in6_addr
{
union
{
u_int8_t u6_addr8[16];
u_int16_t u6_addr16[8];
u_int32_t u6_addr32[4];
} in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
#define s6_addr64 in6_u.u6_addr64
};
#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
#endif /* __MINGW32__ */
#if (defined _MSC_VER) || (defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF))
typedef unsigned short sa_family_t;
#endif
#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
#define __SOCKADDR_COMMON(sa_prefix) \
sa_family_t sa_prefix##family
/* Ditto, for IPv6. */
struct sockaddr_in6
{
__SOCKADDR_COMMON (sin6_);
u_int16_t sin6_port; /* Transport layer port # */
u_int32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
};
#define IN6_IS_ADDR_V4MAPPED(a) \
((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
(((u_int32_t *) (a))[2] == htonl (0xffff)))
#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
#define IN6_IS_ADDR_LINKLOCAL(a) \
((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
#define IN6_IS_ADDR_LOOPBACK(a) \
(((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
#endif /* __MINGW32__ */
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
#define nd_rd_type nd_rd_hdr.icmp6_type
#define nd_rd_code nd_rd_hdr.icmp6_code
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
/*
* IPV6 extension headers
*/
#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */
#define IPPROTO_IPV6 41 /* IPv6 header. */
#define IPPROTO_ROUTING 43 /* IPv6 routing header */
#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
#define IPPROTO_ESP 50 /* encapsulating security payload */
#define IPPROTO_AH 51 /* authentication header */
#define IPPROTO_ICMPV6 58 /* ICMPv6 */
#define IPPROTO_NONE 59 /* IPv6 no next header */
#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */
#define IPPROTO_PIM 103 /* Protocol Independent Multicast. */
#define IPV6_RTHDR_TYPE_0 0
/* Option types and related macros */
#define IP6OPT_PAD1 0x00 /* 00 0 00000 */
#define IP6OPT_PADN 0x01 /* 00 0 00001 */
#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */
#define IP6OPT_JUMBO_LEN 6
#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */
#define IP6OPT_RTALERT_LEN 4
#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */
#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */
#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */
#define IP6OPT_MINLEN 2
#define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */
#define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */
#define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */
#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */
#define IP6OPT_EID 0x8a /* 10 0 01010 */
#define IP6OPT_TYPE(o) ((o) & 0xC0)
#define IP6OPT_TYPE_SKIP 0x00
#define IP6OPT_TYPE_DISCARD 0x40
#define IP6OPT_TYPE_FORCEICMP 0x80
#define IP6OPT_TYPE_ICMP 0xC0
#define IP6OPT_MUTABLE 0x20
#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
#ifndef EAI_ADDRFAMILY
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
#endif
#endif /* __MINGW32__ */
+47
View File
@@ -0,0 +1,47 @@
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.50 2007/04/01 21:43:55 guy Exp $ (LBL)
*/
/*
* For backwards compatibility.
*
* Note to OS vendors: do NOT get rid of this file! Some applications
* might expect to be able to include <pcap-bpf.h>.
*/
#include <pcap/bpf.h>
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (c) 1994, 1996
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.13 2006/10/04 18:13:32 guy Exp $ (LBL)
*/
/*
* For backwards compatibility.
*
* Note to OS vendors: do NOT get rid of this file! Some applications
* might expect to be able to include <pcap-namedb.h>.
*/
#include <pcap/namedb.h>
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL)
*/
#define SIZEOF_CHAR 1
#define SIZEOF_SHORT 2
#define SIZEOF_INT 4
#ifndef _MSC_EXTENSIONS
#define SIZEOF_LONG_LONG 8
#endif
/*
* Avoids a compiler warning in case this was already defined
* (someone defined _WINSOCKAPI_ when including 'windows.h', in order
* to prevent it from including 'winsock.h')
*/
#ifdef _WINSOCKAPI_
#undef _WINSOCKAPI_
#endif
#include <winsock2.h>
#include <fcntl.h>
#include "bittypes.h"
#include <time.h>
#include <io.h>
#ifndef __MINGW32__
#include "IP6_misc.h"
#endif
#define caddr_t char*
#if _MSC_VER < 1500
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strdup _strdup
#endif
//#define inline __inline
#ifdef __MINGW32__
#include <stdint.h>
#else /*__MINGW32__*/
/* MSVC compiler */
#ifndef _UINTPTR_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 uintptr_t;
#else
typedef _W64 unsigned int uintptr_t;
#endif
#define _UINTPTR_T_DEFINED
#endif
#ifndef _INTPTR_T_DEFINED
#ifdef _WIN64
typedef __int64 intptr_t;
#else
typedef _W64 int intptr_t;
#endif
#define _INTPTR_T_DEFINED
#endif
#endif /*__MINGW32__*/
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006/10/04 18:09:22 guy Exp $ (LBL)
*/
/*
* For backwards compatibility.
*
* Note to OS vendors: do NOT get rid of this file! Many applications
* expect to be able to include <pcap.h>, and at least some of them
* go through contortions in their configure scripts to try to detect
* OSes that have "helpfully" moved pcap.h to <pcap/pcap.h> without
* leaving behind a <pcap.h> file.
*/
#include <pcap/pcap.h>
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2006 Paolo Abeni (Italy)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* bluetooth data struct
* By Paolo Abeni <paolo.abeni@email.it>
*
* @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007/09/22 02:10:17 guy Exp $
*/
#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
#define _PCAP_BLUETOOTH_STRUCTS_H__
/*
* Header prepended libpcap to each bluetooth h:4 frame.
* fields are in network byte order
*/
typedef struct _pcap_bluetooth_h4_header {
u_int32_t direction; /* if first bit is set direction is incoming */
} pcap_bluetooth_h4_header;
#endif
+934
View File
@@ -0,0 +1,934 @@
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)bpf.h 7.1 (Berkeley) 5/7/91
*
* @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.8 2008-09-22 20:16:01 guy Exp $ (LBL)
*/
/*
* This is libpcap's cut-down version of bpf.h; it includes only
* the stuff needed for the code generator and the userland BPF
* interpreter, and the libpcap APIs for setting filters, etc..
*
* "pcap-bpf.c" will include the native OS version, as it deals with
* the OS's BPF implementation.
*
* XXX - should this all just be moved to "pcap.h"?
*/
#ifndef BPF_MAJOR_VERSION
#ifdef __cplusplus
extern "C" {
#endif
/* BSD style release date */
#define BPF_RELEASE 199606
#ifdef MSDOS /* must be 32-bit */
typedef long bpf_int32;
typedef unsigned long bpf_u_int32;
#else
typedef int bpf_int32;
typedef u_int bpf_u_int32;
#endif
/*
* Alignment macros. BPF_WORDALIGN rounds up to the next
* even multiple of BPF_ALIGNMENT.
*/
#ifndef __NetBSD__
#define BPF_ALIGNMENT sizeof(bpf_int32)
#else
#define BPF_ALIGNMENT sizeof(long)
#endif
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
#define BPF_MAXBUFSIZE 0x8000
#define BPF_MINBUFSIZE 32
/*
* Structure for "pcap_compile()", "pcap_setfilter()", etc..
*/
struct bpf_program {
u_int bf_len;
struct bpf_insn *bf_insns;
};
/*
* Struct return by BIOCVERSION. This represents the version number of
* the filter language described by the instruction encodings below.
* bpf understands a program iff kernel_major == filter_major &&
* kernel_minor >= filter_minor, that is, if the value returned by the
* running kernel has the same major number and a minor number equal
* equal to or less than the filter being downloaded. Otherwise, the
* results are undefined, meaning an error may be returned or packets
* may be accepted haphazardly.
* It has nothing to do with the source code version.
*/
struct bpf_version {
u_short bv_major;
u_short bv_minor;
};
/* Current version number of filter architecture. */
#define BPF_MAJOR_VERSION 1
#define BPF_MINOR_VERSION 1
/*
* Data-link level type codes.
*
* Do *NOT* add new values to this list without asking
* "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run
* the risk of using a value that's already being used for some other
* purpose, and of having tools that read libpcap-format captures not
* being able to handle captures with your new DLT_ value, with no hope
* that they will ever be changed to do so (as that would destroy their
* ability to read captures using that value for that other purpose).
*/
/*
* These are the types that are the same on all platforms, and that
* have been defined by <net/bpf.h> for ages.
*/
#define DLT_NULL 0 /* BSD loopback encapsulation */
#define DLT_EN10MB 1 /* Ethernet (10Mb) */
#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
#define DLT_AX25 3 /* Amateur Radio AX.25 */
#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
#define DLT_CHAOS 5 /* Chaos */
#define DLT_IEEE802 6 /* 802.5 Token Ring */
#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
#define DLT_SLIP 8 /* Serial Line IP */
#define DLT_PPP 9 /* Point-to-point Protocol */
#define DLT_FDDI 10 /* FDDI */
/*
* These are types that are different on some platforms, and that
* have been defined by <net/bpf.h> for ages. We use #ifdefs to
* detect the BSDs that define them differently from the traditional
* libpcap <net/bpf.h>
*
* XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
* but I don't know what the right #define is for BSD/OS.
*/
#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
#ifdef __OpenBSD__
#define DLT_RAW 14 /* raw IP */
#else
#define DLT_RAW 12 /* raw IP */
#endif
/*
* Given that the only OS that currently generates BSD/OS SLIP or PPP
* is, well, BSD/OS, arguably everybody should have chosen its values
* for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
* didn't. So it goes.
*/
#if defined(__NetBSD__) || defined(__FreeBSD__)
#ifndef DLT_SLIP_BSDOS
#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
#endif
#else
#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
#endif
/*
* 17 is used for DLT_OLD_PFLOG in OpenBSD;
* OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
* 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
*/
#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
/*
* Apparently Redback uses this for its SmartEdge 400/800. I hope
* nobody else decided to use it, too.
*/
#define DLT_REDBACK_SMARTEDGE 32
/*
* These values are defined by NetBSD; other platforms should refrain from
* using them for other purposes, so that NetBSD savefiles with link
* types of 50 or 51 can be read as this type on all platforms.
*/
#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
/*
* The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
* a link-layer type of 99 for the tcpdump it supplies. The link-layer
* header has 6 bytes of unknown data, something that appears to be an
* Ethernet type, and 36 bytes that appear to be 0 in at least one capture
* I've seen.
*/
#define DLT_SYMANTEC_FIREWALL 99
/*
* Values between 100 and 103 are used in capture file headers as
* link-layer types corresponding to DLT_ types that differ
* between platforms; don't use those values for new DLT_ new types.
*/
/*
* This value was defined by libpcap 0.5; platforms that have defined
* it with a different value should define it here with that value -
* a link type of 104 in a save file will be mapped to DLT_C_HDLC,
* whatever value that happens to be, so programs will correctly
* handle files with that link type regardless of the value of
* DLT_C_HDLC.
*
* The name DLT_C_HDLC was used by BSD/OS; we use that name for source
* compatibility with programs written for BSD/OS.
*
* libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
* for source compatibility with programs written for libpcap 0.5.
*/
#define DLT_C_HDLC 104 /* Cisco HDLC */
#define DLT_CHDLC DLT_C_HDLC
#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
/*
* 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
* except when it isn't. (I.e., sometimes it's just raw IP, and
* sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
* so that we don't have to worry about the link-layer header.)
*/
/*
* Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
* with other values.
* DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
* (DLCI, etc.).
*/
#define DLT_FRELAY 107
/*
* OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
* that the AF_ type in the link-layer header is in network byte order.
*
* DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
* we don't use 12 for it in OSes other than OpenBSD.
*/
#ifdef __OpenBSD__
#define DLT_LOOP 12
#else
#define DLT_LOOP 108
#endif
/*
* Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
* DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
* than OpenBSD.
*/
#ifdef __OpenBSD__
#define DLT_ENC 13
#else
#define DLT_ENC 109
#endif
/*
* Values between 110 and 112 are reserved for use in capture file headers
* as link-layer types corresponding to DLT_ types that might differ
* between platforms; don't use those values for new DLT_ types
* other than the corresponding DLT_ types.
*/
/*
* This is for Linux cooked sockets.
*/
#define DLT_LINUX_SLL 113
/*
* Apple LocalTalk hardware.
*/
#define DLT_LTALK 114
/*
* Acorn Econet.
*/
#define DLT_ECONET 115
/*
* Reserved for use with OpenBSD ipfilter.
*/
#define DLT_IPFILTER 116
/*
* OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
* in SuSE 6.3, so we can't use 17 for it in capture-file headers.
*
* XXX: is there a conflict with DLT_PFSYNC 18 as well?
*/
#ifdef __OpenBSD__
#define DLT_OLD_PFLOG 17
#define DLT_PFSYNC 18
#endif
#define DLT_PFLOG 117
/*
* Registered for Cisco-internal use.
*/
#define DLT_CISCO_IOS 118
/*
* For 802.11 cards using the Prism II chips, with a link-layer
* header including Prism monitor mode information plus an 802.11
* header.
*/
#define DLT_PRISM_HEADER 119
/*
* Reserved for Aironet 802.11 cards, with an Aironet link-layer header
* (see Doug Ambrisko's FreeBSD patches).
*/
#define DLT_AIRONET_HEADER 120
/*
* Reserved for Siemens HiPath HDLC.
*/
#define DLT_HHDLC 121
/*
* This is for RFC 2625 IP-over-Fibre Channel.
*
* This is not for use with raw Fibre Channel, where the link-layer
* header starts with a Fibre Channel frame header; it's for IP-over-FC,
* where the link-layer header starts with an RFC 2625 Network_Header
* field.
*/
#define DLT_IP_OVER_FC 122
/*
* This is for Full Frontal ATM on Solaris with SunATM, with a
* pseudo-header followed by an AALn PDU.
*
* There may be other forms of Full Frontal ATM on other OSes,
* with different pseudo-headers.
*
* If ATM software returns a pseudo-header with VPI/VCI information
* (and, ideally, packet type information, e.g. signalling, ILMI,
* LANE, LLC-multiplexed traffic, etc.), it should not use
* DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
* and the like don't have to infer the presence or absence of a
* pseudo-header and the form of the pseudo-header.
*/
#define DLT_SUNATM 123 /* Solaris+SunATM */
/*
* Reserved as per request from Kent Dahlgren <kent@praesum.com>
* for private use.
*/
#define DLT_RIO 124 /* RapidIO */
#define DLT_PCI_EXP 125 /* PCI Express */
#define DLT_AURORA 126 /* Xilinx Aurora link layer */
/*
* Header for 802.11 plus a number of bits of link-layer information
* including radio information, used by some recent BSD drivers as
* well as the madwifi Atheros driver for Linux.
*/
#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
/*
* Reserved for the TZSP encapsulation, as per request from
* Chris Waters <chris.waters@networkchemistry.com>
* TZSP is a generic encapsulation for any other link type,
* which includes a means to include meta-information
* with the packet, e.g. signal strength and channel
* for 802.11 packets.
*/
#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
/*
* BSD's ARCNET headers have the source host, destination host,
* and type at the beginning of the packet; that's what's handed
* up to userland via BPF.
*
* Linux's ARCNET headers, however, have a 2-byte offset field
* between the host IDs and the type; that's what's handed up
* to userland via PF_PACKET sockets.
*
* We therefore have to have separate DLT_ values for them.
*/
#define DLT_ARCNET_LINUX 129 /* ARCNET */
/*
* Juniper-private data link types, as per request from
* Hannes Gredler <hannes@juniper.net>. The DLT_s are used
* for passing on chassis-internal metainformation such as
* QOS profiles, etc..
*/
#define DLT_JUNIPER_MLPPP 130
#define DLT_JUNIPER_MLFR 131
#define DLT_JUNIPER_ES 132
#define DLT_JUNIPER_GGSN 133
#define DLT_JUNIPER_MFR 134
#define DLT_JUNIPER_ATM2 135
#define DLT_JUNIPER_SERVICES 136
#define DLT_JUNIPER_ATM1 137
/*
* Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
* <dieter@apple.com>. The header that's presented is an Ethernet-like
* header:
*
* #define FIREWIRE_EUI64_LEN 8
* struct firewire_header {
* u_char firewire_dhost[FIREWIRE_EUI64_LEN];
* u_char firewire_shost[FIREWIRE_EUI64_LEN];
* u_short firewire_type;
* };
*
* with "firewire_type" being an Ethernet type value, rather than,
* for example, raw GASP frames being handed up.
*/
#define DLT_APPLE_IP_OVER_IEEE1394 138
/*
* Various SS7 encapsulations, as per a request from Jeff Morriss
* <jeff.morriss[AT]ulticom.com> and subsequent discussions.
*/
#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
#define DLT_MTP2 140 /* MTP2, without pseudo-header */
#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
/*
* DOCSIS MAC frames.
*/
#define DLT_DOCSIS 143
/*
* Linux-IrDA packets. Protocol defined at http://www.irda.org.
* Those packets include IrLAP headers and above (IrLMP...), but
* don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
* framing can be handled by the hardware and depend on the bitrate.
* This is exactly the format you would get capturing on a Linux-IrDA
* interface (irdaX), but not on a raw serial port.
* Note the capture is done in "Linux-cooked" mode, so each packet include
* a fake packet header (struct sll_header). This is because IrDA packet
* decoding is dependant on the direction of the packet (incomming or
* outgoing).
* When/if other platform implement IrDA capture, we may revisit the
* issue and define a real DLT_IRDA...
* Jean II
*/
#define DLT_LINUX_IRDA 144
/*
* Reserved for IBM SP switch and IBM Next Federation switch.
*/
#define DLT_IBM_SP 145
#define DLT_IBM_SN 146
/*
* Reserved for private use. If you have some link-layer header type
* that you want to use within your organization, with the capture files
* using that link-layer header type not ever be sent outside your
* organization, you can use these values.
*
* No libpcap release will use these for any purpose, nor will any
* tcpdump release use them, either.
*
* Do *NOT* use these in capture files that you expect anybody not using
* your private versions of capture-file-reading tools to read; in
* particular, do *NOT* use them in products, otherwise you may find that
* people won't be able to use tcpdump, or snort, or Ethereal, or... to
* read capture files from your firewall/intrusion detection/traffic
* monitoring/etc. appliance, or whatever product uses that DLT_ value,
* and you may also find that the developers of those applications will
* not accept patches to let them read those files.
*
* Also, do not use them if somebody might send you a capture using them
* for *their* private type and tools using them for *your* private type
* would have to read them.
*
* Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
* as per the comment above, and use the type you're given.
*/
#define DLT_USER0 147
#define DLT_USER1 148
#define DLT_USER2 149
#define DLT_USER3 150
#define DLT_USER4 151
#define DLT_USER5 152
#define DLT_USER6 153
#define DLT_USER7 154
#define DLT_USER8 155
#define DLT_USER9 156
#define DLT_USER10 157
#define DLT_USER11 158
#define DLT_USER12 159
#define DLT_USER13 160
#define DLT_USER14 161
#define DLT_USER15 162
/*
* For future use with 802.11 captures - defined by AbsoluteValue
* Systems to store a number of bits of link-layer information
* including radio information:
*
* http://www.shaftnet.org/~pizza/software/capturefrm.txt
*
* but it might be used by some non-AVS drivers now or in the
* future.
*/
#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <hannes@juniper.net>. The DLT_s are used
* for passing on chassis-internal metainformation such as
* QOS profiles, etc..
*/
#define DLT_JUNIPER_MONITOR 164
/*
* Reserved for BACnet MS/TP.
*/
#define DLT_BACNET_MS_TP 165
/*
* Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
*
* This is used in some OSes to allow a kernel socket filter to distinguish
* between incoming and outgoing packets, on a socket intended to
* supply pppd with outgoing packets so it can do dial-on-demand and
* hangup-on-lack-of-demand; incoming packets are filtered out so they
* don't cause pppd to hold the connection up (you don't want random
* input packets such as port scans, packets from old lost connections,
* etc. to force the connection to stay up).
*
* The first byte of the PPP header (0xff03) is modified to accomodate
* the direction - 0x00 = IN, 0x01 = OUT.
*/
#define DLT_PPP_PPPD 166
/*
* Names for backwards compatibility with older versions of some PPP
* software; new software should use DLT_PPP_PPPD.
*/
#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <hannes@juniper.net>. The DLT_s are used
* for passing on chassis-internal metainformation such as
* QOS profiles, cookies, etc..
*/
#define DLT_JUNIPER_PPPOE 167
#define DLT_JUNIPER_PPPOE_ATM 168
#define DLT_GPRS_LLC 169 /* GPRS LLC */
#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
/*
* Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
* monitoring equipment.
*/
#define DLT_GCOM_T1E1 172
#define DLT_GCOM_SERIAL 173
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <hannes@juniper.net>. The DLT_ is used
* for internal communication to Physical Interface Cards (PIC)
*/
#define DLT_JUNIPER_PIC_PEER 174
/*
* Link types requested by Gregor Maier <gregor@endace.com> of Endace
* Measurement Systems. They add an ERF header (see
* http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
* the link-layer header.
*/
#define DLT_ERF_ETH 175 /* Ethernet */
#define DLT_ERF_POS 176 /* Packet-over-SONET */
/*
* Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
* for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
* includes additional information before the LAPD header, so it's
* not necessarily a generic LAPD header.
*/
#define DLT_LINUX_LAPD 177
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <hannes@juniper.net>.
* The DLT_ are used for prepending meta-information
* like interface index, interface name
* before standard Ethernet, PPP, Frelay & C-HDLC Frames
*/
#define DLT_JUNIPER_ETHER 178
#define DLT_JUNIPER_PPP 179
#define DLT_JUNIPER_FRELAY 180
#define DLT_JUNIPER_CHDLC 181
/*
* Multi Link Frame Relay (FRF.16)
*/
#define DLT_MFR 182
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <hannes@juniper.net>.
* The DLT_ is used for internal communication with a
* voice Adapter Card (PIC)
*/
#define DLT_JUNIPER_VP 183
/*
* Arinc 429 frames.
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
* Every frame contains a 32bit A429 label.
* More documentation on Arinc 429 can be found at
* http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
*/
#define DLT_A429 184
/*
* Arinc 653 Interpartition Communication messages.
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
* Please refer to the A653-1 standard for more information.
*/
#define DLT_A653_ICM 185
/*
* USB packets, beginning with a USB setup header; requested by
* Paolo Abeni <paolo.abeni@email.it>.
*/
#define DLT_USB 186
/*
* Bluetooth HCI UART transport layer (part H:4); requested by
* Paolo Abeni.
*/
#define DLT_BLUETOOTH_HCI_H4 187
/*
* IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
* <cruz_petagay@bah.com>.
*/
#define DLT_IEEE802_16_MAC_CPS 188
/*
* USB packets, beginning with a Linux USB header; requested by
* Paolo Abeni <paolo.abeni@email.it>.
*/
#define DLT_USB_LINUX 189
/*
* Controller Area Network (CAN) v. 2.0B packets.
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
* Used to dump CAN packets coming from a CAN Vector board.
* More documentation on the CAN v2.0B frames can be found at
* http://www.can-cia.org/downloads/?269
*/
#define DLT_CAN20B 190
/*
* IEEE 802.15.4, with address fields padded, as is done by Linux
* drivers; requested by Juergen Schimmer.
*/
#define DLT_IEEE802_15_4_LINUX 191
/*
* Per Packet Information encapsulated packets.
* DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
*/
#define DLT_PPI 192
/*
* Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
* requested by Charles Clancy.
*/
#define DLT_IEEE802_16_MAC_CPS_RADIO 193
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <hannes@juniper.net>.
* The DLT_ is used for internal communication with a
* integrated service module (ISM).
*/
#define DLT_JUNIPER_ISM 194
/*
* IEEE 802.15.4, exactly as it appears in the spec (no padding, no
* nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
*/
#define DLT_IEEE802_15_4 195
/*
* Various link-layer types, with a pseudo-header, for SITA
* (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
*/
#define DLT_SITA 196
/*
* Various link-layer types, with a pseudo-header, for Endace DAG cards;
* encapsulates Endace ERF records. Requested by Stephen Donnelly
* <stephen@endace.com>.
*/
#define DLT_ERF 197
/*
* Special header prepended to Ethernet packets when capturing from a
* u10 Networks board. Requested by Phil Mulholland
* <phil@u10networks.com>.
*/
#define DLT_RAIF1 198
/*
* IPMB packet for IPMI, beginning with the I2C slave address, followed
* by the netFn and LUN, etc.. Requested by Chanthy Toeung
* <chanthy.toeung@ca.kontron.com>.
*/
#define DLT_IPMB 199
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <hannes@juniper.net>.
* The DLT_ is used for capturing data on a secure tunnel interface.
*/
#define DLT_JUNIPER_ST 200
/*
* Bluetooth HCI UART transport layer (part H:4), with pseudo-header
* that includes direction information; requested by Paolo Abeni.
*/
#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
/*
* AX.25 packet with a 1-byte KISS header; see
*
* http://www.ax25.net/kiss.htm
*
* as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
*/
#define DLT_AX25_KISS 202
/*
* LAPD packets from an ISDN channel, starting with the address field,
* with no pseudo-header.
* Requested by Varuna De Silva <varunax@gmail.com>.
*/
#define DLT_LAPD 203
/*
* Variants of various link-layer headers, with a one-byte direction
* pseudo-header prepended - zero means "received by this host",
* non-zero (any non-zero value) means "sent by this host" - as per
* Will Barker <w.barker@zen.co.uk>.
*/
#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
#define DLT_LAPB_WITH_DIR 207 /* LAPB */
/*
* 208 is reserved for an as-yet-unspecified proprietary link-layer
* type, as requested by Will Barker.
*/
/*
* IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
* <avn@pigeonpoint.com>.
*/
#define DLT_IPMB_LINUX 209
/*
* FlexRay automotive bus - http://www.flexray.com/ - as requested
* by Hannes Kaelber <hannes.kaelber@x2e.de>.
*/
#define DLT_FLEXRAY 210
/*
* Media Oriented Systems Transport (MOST) bus for multimedia
* transport - http://www.mostcooperation.com/ - as requested
* by Hannes Kaelber <hannes.kaelber@x2e.de>.
*/
#define DLT_MOST 211
/*
* Local Interconnect Network (LIN) bus for vehicle networks -
* http://www.lin-subbus.org/ - as requested by Hannes Kaelber
* <hannes.kaelber@x2e.de>.
*/
#define DLT_LIN 212
/*
* X2E-private data link type used for serial line capture,
* as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
*/
#define DLT_X2E_SERIAL 213
/*
* X2E-private data link type used for the Xoraya data logger
* family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
*/
#define DLT_X2E_XORAYA 214
/*
* IEEE 802.15.4, exactly as it appears in the spec (no padding, no
* nothing), but with the PHY-level data for non-ASK PHYs (4 octets
* of 0 as preamble, one octet of SFD, one octet of frame length+
* reserved bit, and then the MAC-layer data, starting with the
* frame control field).
*
* Requested by Max Filippov <jcmvbkbc@gmail.com>.
*/
#define DLT_IEEE802_15_4_NONASK_PHY 215
/*
* DLT and savefile link type values are split into a class and
* a member of that class. A class value of 0 indicates a regular
* DLT_/LINKTYPE_ value.
*/
#define DLT_CLASS(x) ((x) & 0x03ff0000)
/*
* NetBSD-specific generic "raw" link type. The class value indicates
* that this is the generic raw type, and the lower 16 bits are the
* address family we're dealing with. Those values are NetBSD-specific;
* do not assume that they correspond to AF_ values for your operating
* system.
*/
#define DLT_CLASS_NETBSD_RAWAF 0x02240000
#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
/*
* The instruction encodings.
*/
/* instruction classes */
#define BPF_CLASS(code) ((code) & 0x07)
#define BPF_LD 0x00
#define BPF_LDX 0x01
#define BPF_ST 0x02
#define BPF_STX 0x03
#define BPF_ALU 0x04
#define BPF_JMP 0x05
#define BPF_RET 0x06
#define BPF_MISC 0x07
/* ld/ldx fields */
#define BPF_SIZE(code) ((code) & 0x18)
#define BPF_W 0x00
#define BPF_H 0x08
#define BPF_B 0x10
#define BPF_MODE(code) ((code) & 0xe0)
#define BPF_IMM 0x00
#define BPF_ABS 0x20
#define BPF_IND 0x40
#define BPF_MEM 0x60
#define BPF_LEN 0x80
#define BPF_MSH 0xa0
/* alu/jmp fields */
#define BPF_OP(code) ((code) & 0xf0)
#define BPF_ADD 0x00
#define BPF_SUB 0x10
#define BPF_MUL 0x20
#define BPF_DIV 0x30
#define BPF_OR 0x40
#define BPF_AND 0x50
#define BPF_LSH 0x60
#define BPF_RSH 0x70
#define BPF_NEG 0x80
#define BPF_JA 0x00
#define BPF_JEQ 0x10
#define BPF_JGT 0x20
#define BPF_JGE 0x30
#define BPF_JSET 0x40
#define BPF_SRC(code) ((code) & 0x08)
#define BPF_K 0x00
#define BPF_X 0x08
/* ret - BPF_K and BPF_X also apply */
#define BPF_RVAL(code) ((code) & 0x18)
#define BPF_A 0x10
/* misc */
#define BPF_MISCOP(code) ((code) & 0xf8)
#define BPF_TAX 0x00
#define BPF_TXA 0x80
/*
* The instruction data structure.
*/
struct bpf_insn {
u_short code;
u_char jt;
u_char jf;
bpf_u_int32 k;
};
/*
* Macros for insn array initializers.
*/
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
#if __STDC__ || defined(__cplusplus)
extern int bpf_validate(const struct bpf_insn *, int);
extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
#else
extern int bpf_validate();
extern u_int bpf_filter();
#endif
/*
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
*/
#define BPF_MEMWORDS 16
#ifdef __cplusplus
}
#endif
#endif
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright (c) 1994, 1996
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006/10/04 18:09:22 guy Exp $ (LBL)
*/
#ifndef lib_pcap_namedb_h
#define lib_pcap_namedb_h
#ifdef __cplusplus
extern "C" {
#endif
/*
* As returned by the pcap_next_etherent()
* XXX this stuff doesn't belong in this interface, but this
* library already must do name to address translation, so
* on systems that don't have support for /etc/ethers, we
* export these hooks since they'll
*/
struct pcap_etherent {
u_char addr[6];
char name[122];
};
#ifndef PCAP_ETHERS_FILE
#define PCAP_ETHERS_FILE "/etc/ethers"
#endif
struct pcap_etherent *pcap_next_etherent(FILE *);
u_char *pcap_ether_hostton(const char*);
u_char *pcap_ether_aton(const char *);
bpf_u_int32 **pcap_nametoaddr(const char *);
#ifdef INET6
struct addrinfo *pcap_nametoaddrinfo(const char *);
#endif
bpf_u_int32 pcap_nametonetaddr(const char *);
int pcap_nametoport(const char *, int *, int *);
int pcap_nametoportrange(const char *, int *, int *, int *);
int pcap_nametoproto(const char *);
int pcap_nametoeproto(const char *);
int pcap_nametollc(const char *);
/*
* If a protocol is unknown, PROTO_UNDEF is returned.
* Also, pcap_nametoport() returns the protocol along with the port number.
* If there are ambiguous entried in /etc/services (i.e. domain
* can be either tcp or udp) PROTO_UNDEF is returned.
*/
#define PROTO_UNDEF -1
/* XXX move these to pcap-int.h? */
int __pcap_atodn(const char *, bpf_u_int32 *);
int __pcap_atoin(const char *, bpf_u_int32 *);
u_short __pcap_nametodnaddr(const char *);
#ifdef __cplusplus
}
#endif
#endif
+407
View File
@@ -0,0 +1,407 @@
/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.11 2008-10-06 15:38:39 gianluca Exp $ (LBL)
*/
#ifndef lib_pcap_pcap_h
#define lib_pcap_pcap_h
#if defined(WIN32)
#include <pcap-stdinc.h>
#elif defined(MSDOS)
#include <sys/types.h>
#include <sys/socket.h> /* u_int, u_char etc. */
#else /* UN*X */
#include <sys/types.h>
#include <sys/time.h>
#endif /* WIN32/MSDOS/UN*X */
#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
#include <pcap/bpf.h>
#endif
#include <stdio.h>
#ifdef HAVE_REMOTE
// We have to define the SOCKET here, although it has been defined in sockutils.h
// This is to avoid the distribution of the 'sockutils.h' file around
// (for example in the WinPcap developer's pack)
#ifndef SOCKET
#ifdef WIN32
#define SOCKET unsigned int
#else
#define SOCKET int
#endif
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define PCAP_VERSION_MAJOR 2
#define PCAP_VERSION_MINOR 4
#define PCAP_ERRBUF_SIZE 256
/*
* Compatibility for systems that have a bpf.h that
* predates the bpf typedefs for 64-bit support.
*/
#if BPF_RELEASE - 0 < 199406
typedef int bpf_int32;
typedef u_int bpf_u_int32;
#endif
typedef struct pcap pcap_t;
typedef struct pcap_dumper pcap_dumper_t;
typedef struct pcap_if pcap_if_t;
typedef struct pcap_addr pcap_addr_t;
/*
* The first record in the file contains saved values for some
* of the flags used in the printout phases of tcpdump.
* Many fields here are 32 bit ints so compilers won't insert unwanted
* padding; these files need to be interchangeable across architectures.
*
* Do not change the layout of this structure, in any way (this includes
* changes that only affect the length of fields in this structure).
*
* Also, do not change the interpretation of any of the members of this
* structure, in any way (this includes using values other than
* LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
* field).
*
* Instead:
*
* introduce a new structure for the new format, if the layout
* of the structure changed;
*
* send mail to "tcpdump-workers@lists.tcpdump.org", requesting
* a new magic number for your new capture file format, and, when
* you get the new magic number, put it in "savefile.c";
*
* use that magic number for save files with the changed file
* header;
*
* make the code in "savefile.c" capable of reading files with
* the old file header as well as files with the new file header
* (using the magic number to determine the header format).
*
* Then supply the changes as a patch at
*
* http://sourceforge.net/projects/libpcap/
*
* so that future versions of libpcap and programs that use it (such as
* tcpdump) will be able to read your new capture file format.
*/
struct pcap_file_header {
bpf_u_int32 magic;
u_short version_major;
u_short version_minor;
bpf_int32 thiszone; /* gmt to local correction */
bpf_u_int32 sigfigs; /* accuracy of timestamps */
bpf_u_int32 snaplen; /* max length saved portion of each pkt */
bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
};
/*
* Macros for the value returned by pcap_datalink_ext().
*
* If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro
* gives the FCS length of packets in the capture.
*/
#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000)
#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28)
#define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000)
typedef enum {
PCAP_D_INOUT = 0,
PCAP_D_IN,
PCAP_D_OUT
} pcap_direction_t;
/*
* Generic per-packet information, as supplied by libpcap.
*
* The time stamp can and should be a "struct timeval", regardless of
* whether your system supports 32-bit tv_sec in "struct timeval",
* 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
* and 64-bit applications. The on-disk format of savefiles uses 32-bit
* tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit
* and 64-bit versions of libpcap, even if they're on the same platform,
* should supply the appropriate version of "struct timeval", even if
* that's not what the underlying packet capture mechanism supplies.
*/
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
/*
* As returned by the pcap_stats()
*/
struct pcap_stat {
u_int ps_recv; /* number of packets received */
u_int ps_drop; /* number of packets dropped */
u_int ps_ifdrop; /* drops by interface XXX not yet supported */
#ifdef HAVE_REMOTE
u_int ps_capt; /* number of packets that are received by the application; please get rid off the Win32 ifdef */
u_int ps_sent; /* number of packets sent by the server on the network */
u_int ps_netdrop; /* number of packets lost on the network */
#endif /* HAVE_REMOTE */
};
#ifdef MSDOS
/*
* As returned by the pcap_stats_ex()
*/
struct pcap_stat_ex {
u_long rx_packets; /* total packets received */
u_long tx_packets; /* total packets transmitted */
u_long rx_bytes; /* total bytes received */
u_long tx_bytes; /* total bytes transmitted */
u_long rx_errors; /* bad packets received */
u_long tx_errors; /* packet transmit problems */
u_long rx_dropped; /* no space in Rx buffers */
u_long tx_dropped; /* no space available for Tx */
u_long multicast; /* multicast packets received */
u_long collisions;
/* detailed rx_errors: */
u_long rx_length_errors;
u_long rx_over_errors; /* receiver ring buff overflow */
u_long rx_crc_errors; /* recv'd pkt with crc error */
u_long rx_frame_errors; /* recv'd frame alignment error */
u_long rx_fifo_errors; /* recv'r fifo overrun */
u_long rx_missed_errors; /* recv'r missed packet */
/* detailed tx_errors */
u_long tx_aborted_errors;
u_long tx_carrier_errors;
u_long tx_fifo_errors;
u_long tx_heartbeat_errors;
u_long tx_window_errors;
};
#endif
/*
* Item in a list of interfaces.
*/
struct pcap_if {
struct pcap_if *next;
char *name; /* name to hand to "pcap_open_live()" */
char *description; /* textual description of interface, or NULL */
struct pcap_addr *addresses;
bpf_u_int32 flags; /* PCAP_IF_ interface flags */
};
#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
/*
* Representation of an interface address.
*/
struct pcap_addr {
struct pcap_addr *next;
struct sockaddr *addr; /* address */
struct sockaddr *netmask; /* netmask for that address */
struct sockaddr *broadaddr; /* broadcast address for that address */
struct sockaddr *dstaddr; /* P2P destination address for that address */
};
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
/*
* Error codes for the pcap API.
* These will all be negative, so you can check for the success or
* failure of a call that returns these codes by checking for a
* negative value.
*/
#define PCAP_ERROR -1 /* generic error code */
#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */
#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */
#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */
#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */
#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */
#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */
#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
/*
* Warning codes for the pcap API.
* These will all be positive and non-zero, so they won't look like
* errors.
*/
#define PCAP_WARNING 1 /* generic warning code */
#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */
char *pcap_lookupdev(char *);
int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
pcap_t *pcap_create(const char *, char *);
int pcap_set_snaplen(pcap_t *, int);
int pcap_set_promisc(pcap_t *, int);
int pcap_can_set_rfmon(pcap_t *);
int pcap_set_rfmon(pcap_t *, int);
int pcap_set_timeout(pcap_t *, int);
int pcap_set_buffer_size(pcap_t *, int);
int pcap_activate(pcap_t *);
pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_dead(int, int);
pcap_t *pcap_open_offline(const char *, char *);
#if defined(WIN32)
pcap_t *pcap_hopen_offline(intptr_t, char *);
#if !defined(LIBPCAP_EXPORTS)
#define pcap_fopen_offline(f,b) \
pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
#else /*LIBPCAP_EXPORTS*/
static pcap_t *pcap_fopen_offline(FILE *, char *);
#endif
#else /*WIN32*/
pcap_t *pcap_fopen_offline(FILE *, char *);
#endif /*WIN32*/
void pcap_close(pcap_t *);
int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
const u_char*
pcap_next(pcap_t *, struct pcap_pkthdr *);
int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
void pcap_breakloop(pcap_t *);
int pcap_stats(pcap_t *, struct pcap_stat *);
int pcap_setfilter(pcap_t *, struct bpf_program *);
int pcap_setdirection(pcap_t *, pcap_direction_t);
int pcap_getnonblock(pcap_t *, char *);
int pcap_setnonblock(pcap_t *, int, char *);
int pcap_inject(pcap_t *, const void *, size_t);
int pcap_sendpacket(pcap_t *, const u_char *, int);
const char *pcap_statustostr(int);
const char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
void pcap_perror(pcap_t *, char *);
int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
bpf_u_int32);
int pcap_compile_nopcap(int, int, struct bpf_program *,
const char *, int, bpf_u_int32);
void pcap_freecode(struct bpf_program *);
int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
const u_char *);
int pcap_datalink(pcap_t *);
int pcap_datalink_ext(pcap_t *);
int pcap_list_datalinks(pcap_t *, int **);
int pcap_set_datalink(pcap_t *, int);
void pcap_free_datalinks(int *);
int pcap_datalink_name_to_val(const char *);
const char *pcap_datalink_val_to_name(int);
const char *pcap_datalink_val_to_description(int);
int pcap_snapshot(pcap_t *);
int pcap_is_swapped(pcap_t *);
int pcap_major_version(pcap_t *);
int pcap_minor_version(pcap_t *);
/* XXX */
FILE *pcap_file(pcap_t *);
int pcap_fileno(pcap_t *);
pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
FILE *pcap_dump_file(pcap_dumper_t *);
long pcap_dump_ftell(pcap_dumper_t *);
int pcap_dump_flush(pcap_dumper_t *);
void pcap_dump_close(pcap_dumper_t *);
void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
int pcap_findalldevs(pcap_if_t **, char *);
void pcap_freealldevs(pcap_if_t *);
const char *pcap_lib_version(void);
/* XXX this guy lives in the bpf tree */
u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
int bpf_validate(const struct bpf_insn *f, int len);
char *bpf_image(const struct bpf_insn *, int);
void bpf_dump(const struct bpf_program *, int);
#if defined(WIN32)
/*
* Win32 definitions
*/
int pcap_setbuff(pcap_t *p, int dim);
int pcap_setmode(pcap_t *p, int mode);
int pcap_setmintocopy(pcap_t *p, int size);
#ifdef WPCAP
/* Include file with the wpcap-specific extensions */
#include <Win32-Extensions.h>
#endif /* WPCAP */
#define MODE_CAPT 0
#define MODE_STAT 1
#define MODE_MON 2
#elif defined(MSDOS)
/*
* MS-DOS definitions
*/
int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
u_long pcap_mac_packets (void);
#else /* UN*X */
/*
* UN*X definitions
*/
int pcap_get_selectable_fd(pcap_t *);
#endif /* WIN32/MSDOS/UN*X */
#ifdef HAVE_REMOTE
/* Includes most of the public stuff that is needed for the remote capture */
#include <remote-ext.h>
#endif /* HAVE_REMOTE */
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More