292 lines
12 KiB
C++
292 lines
12 KiB
C++
#ifndef CHIRP_HPP
|
|
#define CHIRP_HPP
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include "link.h"
|
|
|
|
#define ALIGN(v, n) v = v&((n)-1) ? (v&~((n)-1))+(n) : v
|
|
#define FOURCC(a, b, c, d) (((uint32_t)a<<0)|((uint32_t)b<<8)|((uint32_t)c<<16)|((uint32_t)d<<24))
|
|
|
|
#define CRP_RES_OK 0
|
|
#define CRP_RES_ERROR -1
|
|
#define CRP_RES_ERROR_RECV_TIMEOUT LINK_RESULT_ERROR_RECV_TIMEOUT
|
|
#define CRP_RES_ERROR_SEND_TIMEOUT LINK_RESULT_ERROR_SEND_TIMEOUT
|
|
#define CRP_RES_ERROR_CRC -2
|
|
#define CRP_RES_ERROR_PARSE -3
|
|
#define CRP_RES_ERROR_MAX_NAK -4
|
|
#define CRP_RES_ERROR_MEMORY -5
|
|
#define CRP_RES_ERROR_NOT_CONNECTED -6
|
|
|
|
#define CRP_MAX_NAK 3
|
|
#define CRP_RETRIES 3
|
|
#define CRP_HEADER_TIMEOUT 1000
|
|
#define CRP_DATA_TIMEOUT 500
|
|
#define CRP_IDLE_TIMEOUT 500
|
|
#define CRP_SEND_TIMEOUT 1000
|
|
#define CRP_MAX_ARGS 10
|
|
#define CRP_BUFSIZE 0x80
|
|
#define CRP_BUFPAD 8
|
|
#define CRP_PROCTABLE_LEN 0x40
|
|
|
|
#define CRP_START_CODE 0xaaaa5555
|
|
|
|
#define CRP_CALL 0x80
|
|
#define CRP_RESPONSE 0x40
|
|
#define CRP_INTRINSIC 0x20
|
|
#define CRP_DATA 0x10
|
|
#define CRP_XDATA 0x18 // data not associated with no associated procedure)
|
|
#define CRP_CALL_ENUMERATE (CRP_CALL | CRP_INTRINSIC | 0x00)
|
|
#define CRP_CALL_INIT (CRP_CALL | CRP_INTRINSIC | 0x01)
|
|
#define CRP_CALL_ENUMERATE_INFO (CRP_CALL | CRP_INTRINSIC | 0x02)
|
|
|
|
#define CRP_ACK 0x59
|
|
#define CRP_NACK 0x95
|
|
#define CRP_MAX_HEADER_LEN 64
|
|
|
|
#define CRP_ARRAY 0x80 // bit
|
|
#define CRP_FLT 0x10 // bit
|
|
#define CRP_NO_COPY (0x10 | 0x20)
|
|
#define CRP_HINT 0x40 // bit
|
|
#define CRP_NULLTERM_ARRAY (0x20 | CRP_ARRAY) // bits
|
|
#define CRP_INT8 0x01
|
|
#define CRP_UINT8 0x01
|
|
#define CRP_INT16 0x02
|
|
#define CRP_UINT16 0x02
|
|
#define CRP_INT32 0x04
|
|
#define CRP_UINT32 0x04
|
|
#define CRP_FLT32 (CRP_FLT | 0x04)
|
|
#define CRP_FLT64 (CRP_FLT | 0x08)
|
|
#define CRP_STRING (CRP_NULLTERM_ARRAY | CRP_INT8)
|
|
#define CRP_TYPE_HINT 0x64 // type hint identifier
|
|
#define CRP_INTS8 (CRP_INT8 | CRP_ARRAY)
|
|
#define CRP_INTS16 (CRP_INT16 | CRP_ARRAY)
|
|
#define CRP_INTS32 (CRP_INT32 | CRP_ARRAY)
|
|
#define CRP_UINTS8 CRP_INTS8
|
|
#define CRP_UINTS8_NO_COPY (CRP_INTS8 | CRP_NO_COPY)
|
|
#define CRP_UINTS16_NO_COPY (CRP_INTS16 | CRP_NO_COPY)
|
|
#define CRP_UINTS32_NO_COPY (CRP_INTS32 | CRP_NO_COPY)
|
|
#define CRP_UINTS16 CRP_INTS16
|
|
#define CRP_UINTS32 CRP_INTS32
|
|
#define CRP_FLTS32 (CRP_FLT32 | CRP_ARRAY)
|
|
#define CRP_FLTS64 (CRP_FLT64 | CRP_ARRAY)
|
|
#define CRP_HINT8 (CRP_INT8 | CRP_HINT)
|
|
#define CRP_HINT16 (CRP_INT16 | CRP_HINT)
|
|
#define CRP_HINT32 (CRP_INT32 | CRP_HINT)
|
|
#define CRP_HINTS8 (CRP_INT8 | CRP_ARRAY | CRP_HINT)
|
|
#define CRP_HINTS16 (CRP_INT16 | CRP_ARRAY | CRP_HINT)
|
|
#define CRP_HINTS32 (CRP_INT32 | CRP_ARRAY | CRP_HINT)
|
|
#define CRP_HFLTS32 (CRP_FLT32 | CRP_ARRAY | CRP_HINT)
|
|
#define CRP_HFLTS64 (CRP_FLT64 | CRP_ARRAY | CRP_HINT)
|
|
#define CRP_HSTRING (CRP_STRING | CRP_HINT)
|
|
// CRP_HTYPE is for arg lists which are uint8_t arrays
|
|
#define CRP_HTYPE(v) CRP_TYPE_HINT, (uint8_t)(v>>0&0xff), (uint8_t)(v>>8&0xff), (uint8_t)(v>>16&0xff), (uint8_t)(v>>24&0xff)
|
|
|
|
// regular call args
|
|
#define INT8(v) CRP_INT8, v
|
|
#define UINT8(v) CRP_INT8, v
|
|
#define INT16(v) CRP_INT16, v
|
|
#define UINT16(v) CRP_INT16, v
|
|
#define INT32(v) CRP_INT32, v
|
|
#define UINT32(v) CRP_INT32, v
|
|
#define FLT32(v) CRP_FLT32, v
|
|
#define FLT64(v) CRP_FLT64, v
|
|
#define STRING(s) CRP_STRING, s
|
|
#define INTS8(len, a) CRP_INTS8, len, a
|
|
#define UINTS8(len, a) CRP_INTS8, len, a
|
|
#define UINTS8_NO_COPY(len) CRP_UINTS8_NO_COPY, len
|
|
#define UINTS16_NO_COPY(len) CRP_UINTS16_NO_COPY, len
|
|
#define UINTS32_NO_COPY(len) CRP_UINTS32_NO_COPY, len
|
|
#define INTS16(len, a) CRP_INTS16, len, a
|
|
#define UINTS16(len, a) CRP_INTS16, len, a
|
|
#define INTS32(len, a) CRP_INTS32, len, a
|
|
#define UINTS32(len, a) CRP_INTS32, len, a
|
|
#define FLTS32(len, a) CRP_FLTS32, len, a
|
|
#define FLTS64(len, a) CRP_FLTS64, len, a
|
|
|
|
// hint call args
|
|
#define HINT8(v) CRP_HINT8, v
|
|
#define UHINT8(v) CRP_HINT8, v
|
|
#define HINT16(v) CRP_HINT16, v
|
|
#define UHINT16(v) CRP_HINT16, v
|
|
#define HINT32(v) CRP_HINT32, v
|
|
#define UHINT32(v) CRP_HINT32, v
|
|
#define HFLT32(v) CRP_HFLT32, v
|
|
#define HFLT64(v) CRP_HFLT64, v
|
|
#define HSTRING(s) CRP_HSTRING, s
|
|
#define HINTS8(len, a) CRP_HINTS8, len, a
|
|
#define UHINTS8(len, a) CRP_HINTS8, len, a
|
|
#define HINTS16(len, a) CRP_HINTS16, len, a
|
|
#define UHINTS16(len, a) CRP_HINTS16, len, a
|
|
#define HINTS32(len, a) CRP_HINTS32, len, a
|
|
#define UHINTS32(len, a) CRP_HINTS32, len, a
|
|
#define HFLTS32(len, a) CRP_HFLTS32, len, a
|
|
#define HFLTS64(len, a) CRP_HFLTS64, len, a
|
|
#define HTYPE(v) CRP_TYPE_HINT, v
|
|
|
|
#define INT8_IN(v) int8_t & v
|
|
#define UINT8_IN(v) uint8_t & v
|
|
#define INT16_IN(v) int16_t & v
|
|
#define UINT16_IN(v) uint16_t & v
|
|
#define INT32_IN(v) int32_t & v
|
|
#define UINT32_IN(v) uint32_t & v
|
|
#define FLT32_IN(v) float & v
|
|
#define FLT64_IN(v) double & v
|
|
#define STRING_IN(s) const char * s
|
|
#define INTS8_IN(len, a) uint32_t & len, int8_t * a
|
|
#define UINTS8_IN(len, a) uint32_t & len, uint8_t * a
|
|
#define INTS16_IN(len, a) uint32_t & len, int16_t * a
|
|
#define UINTS16_IN(len, a) uint32_t & len, uint16_t * a
|
|
#define INTS32_IN(len, a) uint32_t & len, int32_t * a
|
|
#define UINTS32_IN(len, a) uint32_t & len, uint32_t * a
|
|
#define FLTS32_IN(len, a) uint32_t & len, float * a
|
|
#define FLTS64_IN(len, a) uint32_t & len, double * a
|
|
|
|
#ifndef END
|
|
#ifdef __x86_64__
|
|
#define END (int64_t)0
|
|
#else
|
|
#define END 0
|
|
#endif
|
|
#endif
|
|
#define END_OUT_ARGS END
|
|
#define END_IN_ARGS END
|
|
|
|
// service types
|
|
#define SYNC 0
|
|
#define ASYNC 0x01 // bit
|
|
#define RETURN_ARRAY 0x02 // bit
|
|
#define SYNC_RETURN_ARRAY (SYNC | RETURN_ARRAY)
|
|
|
|
#define CRP_RETURN(chirp, ...) chirp->assemble(0, __VA_ARGS__, END)
|
|
#define CRP_SEND_XDATA(chirp, ...) chirp->assemble(CRP_XDATA, __VA_ARGS__, END)
|
|
#define callSync(...) call(SYNC, __VA_ARGS__, END)
|
|
#define callAsync(...) call(ASYNC, __VA_ARGS__, END)
|
|
#define callSyncArray(...) call(SYNC_RETURN_ARRAY, __VA_ARGS__, END)
|
|
|
|
class Chirp;
|
|
|
|
typedef int16_t ChirpProc; // negative values are invalid
|
|
|
|
typedef uint32_t (*ProcPtr)(Chirp *);
|
|
|
|
struct ProcModule
|
|
{
|
|
char *procName;
|
|
ProcPtr procPtr;
|
|
uint8_t argTypes[CRP_MAX_ARGS];
|
|
char *procInfo;
|
|
};
|
|
|
|
struct ProcTableExtension
|
|
{
|
|
uint8_t argTypes[CRP_MAX_ARGS];
|
|
char *procInfo;
|
|
};
|
|
|
|
struct ProcInfo
|
|
{
|
|
char *procName;
|
|
uint8_t *argTypes;
|
|
char *procInfo;
|
|
};
|
|
|
|
struct ProcTableEntry
|
|
{
|
|
const char *procName;
|
|
ProcPtr procPtr;
|
|
ChirpProc chirpProc;
|
|
const ProcTableExtension *extension;
|
|
};
|
|
|
|
class Chirp
|
|
{
|
|
public:
|
|
Chirp(bool hinterested=false, bool client=false, Link *link=NULL);
|
|
~Chirp();
|
|
|
|
virtual int init(bool connect);
|
|
int setLink(Link *link);
|
|
ChirpProc getProc(const char *procName, ProcPtr callback=0);
|
|
int setProc(const char *procName, ProcPtr proc, ProcTableExtension *extension=NULL);
|
|
int getProcInfo(ChirpProc proc, ProcInfo *info);
|
|
int registerModule(const ProcModule *module);
|
|
void setSendTimeout(uint32_t timeout);
|
|
void setRecvTimeout(uint32_t timeout);
|
|
|
|
int call(uint8_t service, ChirpProc proc, ...);
|
|
int call(uint8_t service, ChirpProc proc, va_list args);
|
|
static uint8_t getType(const void *arg);
|
|
int service(bool all=true);
|
|
int assemble(uint8_t type, ...);
|
|
bool connected();
|
|
|
|
// utility methods
|
|
static int serialize(Chirp *chirp, uint8_t *buf, uint32_t bufSize, ...);
|
|
static int deserialize(uint8_t *buf, uint32_t len, ...);
|
|
static int vserialize(Chirp *chirp, uint8_t *buf, uint32_t bufSize, va_list *args);
|
|
static int vdeserialize(uint8_t *buf, uint32_t len, va_list *args);
|
|
static int deserializeParse(uint8_t *buf, uint32_t len, void *args[]);
|
|
static int loadArgs(va_list *args, void *recvArgs[]);
|
|
static int getArgList(uint8_t *buf, uint32_t len, uint8_t *argList);
|
|
int useBuffer(uint8_t *buf, uint32_t len);
|
|
|
|
static uint16_t calcCrc(uint8_t *buf, uint32_t len);
|
|
|
|
protected:
|
|
int remoteInit(bool connect);
|
|
int recvChirp(uint8_t *type, ChirpProc *proc, void *args[], bool wait=false); // null pointer terminates
|
|
virtual int handleChirp(uint8_t type, ChirpProc proc, const void *args[]); // null pointer terminates
|
|
virtual void handleXdata(const void *data[]) {(void)data;}
|
|
virtual int sendChirp(uint8_t type, ChirpProc proc);
|
|
|
|
uint8_t *m_buf;
|
|
uint8_t *m_bufSave;
|
|
uint32_t m_len;
|
|
uint32_t m_offset;
|
|
uint32_t m_bufSize;
|
|
bool m_errorCorrected;
|
|
bool m_sharedMem;
|
|
bool m_hinformer;
|
|
bool m_hinterested;
|
|
bool m_client;
|
|
uint32_t m_headerLen;
|
|
uint16_t m_headerTimeout;
|
|
uint16_t m_dataTimeout;
|
|
uint16_t m_idleTimeout;
|
|
uint16_t m_sendTimeout;
|
|
|
|
private:
|
|
int sendHeader(uint8_t type, ChirpProc proc);
|
|
int sendFull(uint8_t type, ChirpProc proc);
|
|
int sendData();
|
|
int sendAck(bool ack); // false=nack
|
|
int sendChirpRetry(uint8_t type, ChirpProc proc);
|
|
int recvHeader(uint8_t *type, ChirpProc *proc, bool wait);
|
|
int recvFull(uint8_t *type, ChirpProc *proc, bool wait);
|
|
int recvData();
|
|
int recvAck(bool *ack, uint16_t timeout); // false=nack
|
|
int32_t handleEnumerate(char *procName, ChirpProc *callback);
|
|
int32_t handleInit(uint16_t *blkSize, uint8_t *hintSource);
|
|
int32_t handleEnumerateInfo(ChirpProc *proc);
|
|
int vassemble(va_list *args);
|
|
void restoreBuffer();
|
|
|
|
ChirpProc updateTable(const char *procName, ProcPtr procPtr);
|
|
ChirpProc lookupTable(const char *procName);
|
|
int realloc(uint32_t min=0);
|
|
int reallocTable();
|
|
|
|
Link *m_link;
|
|
ProcTableEntry *m_procTable;
|
|
uint16_t m_procTableSize;
|
|
uint16_t m_blkSize;
|
|
uint8_t m_maxNak;
|
|
uint8_t m_retries;
|
|
bool m_call;
|
|
bool m_connected;
|
|
};
|
|
|
|
#endif // CHIRP_H
|