/*
* Messages and basic I/O functions between VBI proxy client & server
*
* Copyright (C) 2003,2004 Tom Zoerner
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* $Id: proxy-msg.h,v 1.9 2004/10/24 18:33:47 tomzo Exp $
*
* $Log: proxy-msg.h,v $
* Revision 1.9 2004/10/24 18:33:47 tomzo
* - cleaned up socket I/O interface functions
* - added defines for norm change events
*
* Revision 1.8 2004/10/04 20:50:24 mschimek
* *** empty log message ***
*
* Revision 1.6 2003/06/07 09:43:08 tomzo
* - added new message types MSG_TYPE_DAEMON_PID_REQ,CNF
* - added new struct VBIPROXY_MSG: holds message header and body structs
*
* Revision 1.5 2003/06/01 19:36:23 tomzo
* Implemented server-side TV channel switching
* - implemented messages MSG_TYPE_CHN_CHANGE_REQ/CNF/REJ; IND is still TODO
* - removed obsolete PROFILE messages: profile is included with CHN_CHANGE_REQ
* Also: added VBI API identifier and device path to CONNECT_CNF (for future use)
*
* Revision 1.4 2003/05/24 12:19:29 tomzo
* - added VBIPROXY_SERVICE_REQ/_CNF/_REJ messages
* - prepared channel change request and profile request
* - renamed MSG_TYPE_DATA_IND into _SLICED_IND in preparation for raw data
*
* Revision 1.3 2003/05/03 12:04:52 tomzo
* - added new macro VBIPROXY_ENDIAN_MISMATCH to replace use of swap32()
* - added declaration for new func vbi_proxy_msg_set_debug_level()
* - fixed copyright headers, added description to file headers
*
*/
#ifndef PROXY_MSG_H
#define PROXY_MSG_H
#include <sys/syslog.h>
/* Public */
/**
* @ingroup Proxy
* @brief Priority levels for channel switching (equivalent to enum v4l2_priority)
*
* These priorities are used to cooperativly resolve conflicts between
* channel requests of multiple capture applications. While a capture
* application with a higher priority has opened a device, channel change
* requests of applications with lower priority will fail with error "EBUSY".
*/
typedef enum
{
/**
* Priority level to be used for non-interactive, background data
* harvesting, i.e. applications which permanently run in the
* background (e.g. teletext cache, EPG data acquisition)
*/
VBI_CHN_PRIO_BACKGROUND = 1,
/**
* Interactive (default): should be used when channels are changed
* on request of the user (e.g. TV viewer, Radio, teletext reader)
*/
VBI_CHN_PRIO_INTERACTIVE = 2,
/**
* Default priority for client which have not (yet) set a priority.
*/
VBI_CHN_PRIO_DEFAULT = VBI_CHN_PRIO_INTERACTIVE,
/**
* Scheduled recording (e.g. PVR): usually only one application
* should run at this level (although this is not enforced by
* the proxy daemon, must be checked by the user or applications)
*/
VBI_CHN_PRIO_RECORD = 3
} VBI_CHN_PRIO;
/**
* @ingroup Proxy
* @brief Sub-priorities for channel scheduling at "background" priority
*
* This enum describes recommended sub-priority levels for channel profiles.
* They're intended for channel switching through a VBI proxy at background
* priority level. The daemon uses this priority to decide which request
* to grant first if there are multiple outstanding requests. To the daemon
* these are just numbers (highest wins) but for successful cooperation
* clients need to use agree on values for similar tasks. Hence the following
* values are recommended:
*/
typedef enum
{
/**
* Minimal priority level. Client will get channel control only
* after all other clients.
*/
VBI_CHN_SUBPRIO_MINIMAL = 0x00,
/**
* After phases "initial" or "check" are completed, clients can use
* this level to continuously check for change marks.
*/
VBI_CHN_SUBPRIO_CHECK = 0x10,
/**
* A change in the data transmission has been detected or a long
* time has passed since the initial reading, so data needs to be
* read newly.
*/
VBI_CHN_SUBPRIO_UPDATE = 0x20,
/**
* Initial reading of data after program start (and long pause since
* last start); once all data is read the client should lower it's
* priority.
*/
VBI_CHN_SUBPRIO_INITIAL = 0x30,
/**
* Scanning for VPS/PDC labels to wait for the start of a recording.
*/
VBI_CHN_SUBPRIO_VPS_PDC = 0x40
} VBI_CHN_SUBPRIO;
/**
* @ingroup Proxy
* @brief Proxy scheduler configuration for background channel switching
*/
typedef struct
{
/**
* boolean: ignore struct unless TRUE
*/
uint8_t is_valid;
/**
* Background prio: VPS/PDC, initial load, update, check, passive
*/
uint8_t sub_prio;
/**
* boolean: interruption allowed
*/
uint8_t allow_suspend;
uint8_t reserved0;
/**
* min. continuous use of that channel
*/
time_t min_duration;
/**
* expected duration of use of that channel
*/
time_t exp_duration;
uint8_t reserved1[16];
} vbi_channel_profile;
/**
* @ingroup Proxy
* @brief General flags sent from clients to daemon during connect
*/
typedef enum
{
/**
* Don't drop connection upon timeouts in socket I/O or message response;
* Intended for debugging, i.e. when remote party runs in a debugger
*/
VBI_PROXY_DAEMON_NO_TIMEOUTS = 1<<0
} VBI_PROXY_DAEMON_FLAGS;
/**
* @ingroup Proxy
* @brief General flags sent from daemon to clients during connect
*/
typedef enum
{
/**
* Don't drop connection upon timeouts in socket I/O or message response
* (e.g. when waiting for connect confirm)
* Intended for debugging, i.e. when remote party runs in a debugger
*/
VBI_PROXY_CLIENT_NO_TIMEOUTS = 1<<0,
/**
* Suppress sending of channel change and similar indications, i.e. limit
* messages to slicer data forward and synchronous messages (i.e. RPC reply).
* Used to make sure that the proxy client socket only becomes readable
* when data is available for applications which are not proxy-aware.
*/
VBI_PROXY_CLIENT_NO_STATUS_IND = 1<<1
} VBI_PROXY_CLIENT_FLAGS;
/**
* @ingroup Proxy
* @brief Channel notification flags
*/
typedef enum
{
/**
* Revoke a previous channel request and return the channel switch
* token to the daemon.
*/
VBI_PROXY_CHN_RELEASE = 1<<0,
/**
* Return the channel token to the daemon without releasing the
* channel; This should always be done when the channel switch has
* been completed to allow faster scheduling in the daemon (i.e. the
* daemon can grant the token to a different client without having
* to reclaim it first.)
*/
VBI_PROXY_CHN_TOKEN = 1<<1,
/**
* Indicate that the channel was changed and VBI buffer queue
* must be flushed; Should be called as fast as possible after
* the channel and/or norm was changed. Note this affects other
* clients' capturing too, so use with care. Other clients will
* be informed about this change by a channel change indication.
*/
VBI_PROXY_CHN_FLUSH = 1<<2,
/**
* Indicate a norm change. The new norm should be supplied in
* the scanning parameter in cae the daemon is not able to
* determine it from the device directly.
*/
VBI_PROXY_CHN_NORM = 1<<3,
/**
* Indicate that the client failed to switch the channel because
* the device was busy. Used to notify the channel scheduler that
* the current time slice cannot be used by the client. If the
* client isn't able to schedule periodic re-attempts it should
* also return the token.
*/
VBI_PROXY_CHN_FAIL = 1<<4,
VBI_PROXY_CHN_NONE = 0
} VBI_PROXY_CHN_FLAGS;
/**
* @ingroup Proxy
* @brief Identification of the VBI device driver type
*/
typedef enum
{
VBI_API_UNKNOWN,
VBI_API_V4L1,
VBI_API_V4L2,
VBI_API_BKTR
} VBI_DRIVER_API_REV;
/**
* @ingroup Proxy
* @brief Proxy protocol version: major, minor and patchlevel
*/
#define VBIPROXY_VERSION 0x00000100
#define VBIPROXY_COMPAT_VERSION 0x00000100
/* Private */
/* ----------------------------------------------------------------------------
** Declaration of message IDs and the common header struct
*/
typedef enum
{
MSG_TYPE_CONNECT_REQ,
MSG_TYPE_CONNECT_CNF,
MSG_TYPE_CONNECT_REJ,
MSG_TYPE_CLOSE_REQ,
MSG_TYPE_SLICED_IND,
MSG_TYPE_SERVICE_REQ,
MSG_TYPE_SERVICE_CNF,
MSG_TYPE_SERVICE_REJ,
MSG_TYPE_CHN_TOKEN_REQ,
MSG_TYPE_CHN_TOKEN_CNF,
MSG_TYPE_CHN_TOKEN_IND,
MSG_TYPE_CHN_NOTIFY_REQ,
MSG_TYPE_CHN_NOTIFY_CNF,
MSG_TYPE_CHN_RECLAIM_REQ,
MSG_TYPE_CHN_RECLAIM_CNF,
MSG_TYPE_CHN_SUSPEND_REQ,
MSG_TYPE_CHN_SUSPEND_CNF,
MSG_TYPE_CHN_SUSPEND_REJ,
MSG_TYPE_CHN_IOCTL_REQ,
MSG_TYPE_CHN_IOCTL_CNF,
MSG_TYPE_CHN_IOCTL_REJ,
MSG_TYPE_CHN_CHANGE_IND,
MSG_TYPE_DAEMON_PID_REQ,
MSG_TYPE_DAEMON_PID_CNF,
MSG_TYPE_COUNT
} VBIPROXY_MSG_TYPE;
typedef struct
{
uint32_t len;
uint32_t type;
} VBIPROXY_MSG_HEADER;
#define VBIPROXY_MAGIC_STR "LIBZVBI VBIPROXY"
#define VBIPROXY_MAGIC_LEN 16
#define VBIPROXY_ENDIAN_MAGIC 0x11223344
#define VBIPROXY_ENDIAN_MISMATCH 0x44332211
#define VBIPROXY_CLIENT_NAME_MAX_LENGTH 64
#define VBIPROXY_DEV_NAME_MAX_LENGTH 128
#define VBIPROXY_ERROR_STR_MAX_LENGTH 128
typedef struct
{
uint8_t protocol_magic[VBIPROXY_MAGIC_LEN];
uint32_t protocol_compat_version;
uint32_t protocol_version;
uint32_t endian_magic;
} VBIPROXY_MAGICS;
typedef struct
{
VBIPROXY_MAGICS magics;
uint8_t client_name[VBIPROXY_CLIENT_NAME_MAX_LENGTH];
int32_t pid;
uint32_t client_flags;
uint32_t scanning;
uint8_t buffer_count;
uint32_t services;
int8_t strict;
uint32_t reserved[32]; /* set to zero */
} VBIPROXY_CONNECT_REQ;
typedef struct
{
VBIPROXY_MAGICS magics;
uint8_t dev_vbi_name[VBIPROXY_DEV_NAME_MAX_LENGTH];
int32_t pid;
uint32_t vbi_api_revision;
uint32_t daemon_flags;
uint32_t services; /* all services, including raw */
vbi_raw_decoder dec; /* VBI format, e.g. VBI line counts */
uint32_t reserved[32]; /* set to zero */
} VBIPROXY_CONNECT_CNF;
typedef struct
{
VBIPROXY_MAGICS magics;
uint8_t errorstr[VBIPROXY_ERROR_STR_MAX_LENGTH];
} VBIPROXY_CONNECT_REJ;
typedef struct
{
double timestamp;
uint32_t sliced_lines;
uint32_t raw_lines;
union
{
vbi_sliced sliced[1];
int8_t raw[1];
} u;
} VBIPROXY_SLICED_IND;
#define VBIPROXY_RAW_LINE_SIZE 2048
#define VBIPROXY_SLICED_IND_SIZE(S,R) ( sizeof(VBIPROXY_SLICED_IND) \
- sizeof(vbi_sliced) \
+ ((S) * sizeof(vbi_sliced)) \
+ ((R) * VBIPROXY_RAW_LINE_SIZE) )
typedef struct
{
uint8_t reset;
uint8_t commit;
int8_t strict;
uint32_t services;
} VBIPROXY_SERVICE_REQ;
typedef struct
{
uint32_t services; /* all services, including raw */
vbi_raw_decoder dec; /* VBI format, e.g. VBI line counts */
} VBIPROXY_SERVICE_CNF;
typedef struct
{
uint8_t errorstr[VBIPROXY_ERROR_STR_MAX_LENGTH];
} VBIPROXY_SERVICE_REJ;
typedef struct
{
uint32_t chn_prio;
vbi_channel_profile chn_profile;
} VBIPROXY_CHN_TOKEN_REQ;
typedef struct
{
vbi_bool token_ind; /* piggy-back TOKEN_IND (bg. prio only) */
vbi_bool permitted; /* change allowed by prio (non-bg prio) */
vbi_bool non_excl; /* there are other clients at the same prio */
} VBIPROXY_CHN_TOKEN_CNF;
typedef struct
{
} VBIPROXY_CHN_TOKEN_IND;
typedef struct
{
VBI_PROXY_CHN_FLAGS notify_flags;
uint32_t scanning; /* new norm after flush; zero if unknown */
uint32_t cause; /* currently always zero */
uint8_t reserved[32];
} VBIPROXY_CHN_NOTIFY_REQ;
typedef struct
{
uint32_t scanning;
uint8_t reserved[32];
} VBIPROXY_CHN_NOTIFY_CNF;
typedef struct
{
vbi_bool enable;
uint32_t cause;
} VBIPROXY_CHN_SUSPEND_REQ;
typedef struct
{
} VBIPROXY_CHN_SUSPEND_CNF;
typedef struct
{
} VBIPROXY_CHN_SUSPEND_REJ;
typedef struct
{
uint32_t request;
uint32_t reserved_0;
uint32_t reserved_1;
uint32_t arg_size;
uint8_t arg_data[0]; /* warning: must have same offset as in CNF message */
} VBIPROXY_CHN_IOCTL_REQ;
#define VBIPROXY_CHN_IOCTL_REQ_SIZE(SIZE) (sizeof(VBIPROXY_CHN_IOCTL_REQ) + (SIZE) - 1)
typedef struct
{
uint32_t reserved_0;
int32_t result;
int32_t errcode;
uint32_t arg_size;
uint8_t arg_data[0];
} VBIPROXY_CHN_IOCTL_CNF;
#define VBIPROXY_CHN_IOCTL_CNF_SIZE(SIZE) (sizeof(VBIPROXY_CHN_IOCTL_CNF) + (SIZE) - 1)
typedef struct
{
} VBIPROXY_CHN_IOCTL_REJ;
typedef struct
{
} VBIPROXY_CHN_RECLAIM_REQ;
typedef struct
{
} VBIPROXY_CHN_RECLAIM_CNF;
typedef struct
{
VBI_PROXY_CHN_FLAGS notify_flags;
uint32_t scanning;
uint8_t reserved[32]; /* always zero */
} VBIPROXY_CHN_CHANGE_IND;
typedef struct
{
VBIPROXY_MAGICS magics;
} VBIPROXY_DAEMON_PID_REQ;
typedef struct
{
VBIPROXY_MAGICS magics;
int32_t pid;
} VBIPROXY_DAEMON_PID_CNF;
typedef union
{
VBIPROXY_CONNECT_REQ connect_req;
VBIPROXY_CONNECT_CNF connect_cnf;
VBIPROXY_CONNECT_REJ connect_rej;
VBIPROXY_SLICED_IND sliced_ind;
VBIPROXY_SERVICE_REQ service_req;
VBIPROXY_SERVICE_CNF service_cnf;
VBIPROXY_SERVICE_REJ service_rej;
VBIPROXY_CHN_TOKEN_REQ chn_token_req;
VBIPROXY_CHN_TOKEN_CNF chn_token_cnf;
VBIPROXY_CHN_TOKEN_IND chn_token_ind;
VBIPROXY_CHN_RECLAIM_REQ chn_reclaim_req;
VBIPROXY_CHN_RECLAIM_CNF chn_reclaim_cnf;
VBIPROXY_CHN_NOTIFY_REQ chn_notify_req;
VBIPROXY_CHN_NOTIFY_CNF chn_notify_cnf;
VBIPROXY_CHN_SUSPEND_REQ chn_suspend_req;
VBIPROXY_CHN_SUSPEND_CNF chn_suspend_cnf;
VBIPROXY_CHN_SUSPEND_REJ chn_suspend_rej;
VBIPROXY_CHN_IOCTL_REQ chn_ioctl_req;
VBIPROXY_CHN_IOCTL_CNF chn_ioctl_cnf;
VBIPROXY_CHN_IOCTL_REJ chn_ioctl_rej;
VBIPROXY_CHN_CHANGE_IND chn_change_ind;
VBIPROXY_DAEMON_PID_REQ daemon_pid_req;
VBIPROXY_DAEMON_PID_CNF daemon_pid_cnf;
} VBIPROXY_MSG_BODY;
typedef struct
{
VBIPROXY_MSG_HEADER head;
VBIPROXY_MSG_BODY body;
} VBIPROXY_MSG;
#define VBIPROXY_MSG_BODY_OFFSET ((long)&(((VBIPROXY_MSG*)NULL)->body))
/* ----------------------------------------------------------------------------
** Declaration of the IO state struct
*/
typedef struct
{
int sock_fd; /* socket file handle or -1 if closed */
time_t lastIoTime; /* timestamp of last i/o (for timeouts) */
uint32_t writeLen; /* number of bytes in write buffer, including header */
uint32_t writeOff; /* number of already written bytes, including header */
VBIPROXY_MSG * pWriteBuf; /* data to be written */
vbi_bool freeWriteBuf; /* TRUE if the buffer shall be freed by the I/O handler */
uint32_t readLen; /* length of incoming message (including itself) */
uint32_t readOff; /* number of already read bytes */
} VBIPROXY_MSG_STATE;
/* ----------------------------------------------------------------------------
** Declaration of the service interface functions
*/
void vbi_proxy_msg_logger( int level, int clnt_fd, int errCode, const char * pText, ... );
void vbi_proxy_msg_set_logging( vbi_bool do_logtty, int sysloglev,
int fileloglev, const char * pLogfileName );
void vbi_proxy_msg_set_debug_level( int level );
const char * vbi_proxy_msg_debug_get_type_str( VBIPROXY_MSG_TYPE type );
vbi_bool vbi_proxy_msg_read_idle( VBIPROXY_MSG_STATE * pIO );
vbi_bool vbi_proxy_msg_write_idle( VBIPROXY_MSG_STATE * pIO );
vbi_bool vbi_proxy_msg_is_idle( VBIPROXY_MSG_STATE * pIO );
vbi_bool vbi_proxy_msg_check_timeout( VBIPROXY_MSG_STATE * pIO, time_t now );
vbi_bool vbi_proxy_msg_handle_write( VBIPROXY_MSG_STATE * pIO, vbi_bool * pBlocked );
void vbi_proxy_msg_close_read( VBIPROXY_MSG_STATE * pIO );
vbi_bool vbi_proxy_msg_handle_read( VBIPROXY_MSG_STATE * pIO,
vbi_bool * pBlocked, vbi_bool closeOnZeroRead,
VBIPROXY_MSG * pReadBuf, int max_read_len );
void vbi_proxy_msg_close_io( VBIPROXY_MSG_STATE * pIO );
void vbi_proxy_msg_fill_magics( VBIPROXY_MAGICS * p_magic );
void vbi_proxy_msg_write( VBIPROXY_MSG_STATE * p_io, VBIPROXY_MSG_TYPE type,
uint32_t msgLen, VBIPROXY_MSG * pMsg, vbi_bool freeBuf );
int vbi_proxy_msg_listen_socket( vbi_bool is_tcp_ip, const char * listen_ip, const char * listen_port );
void vbi_proxy_msg_stop_listen( vbi_bool is_tcp_ip, int sock_fd, char * pSrvPort );
int vbi_proxy_msg_accept_connection( int listen_fd );
char * vbi_proxy_msg_get_socket_name( const char * p_dev_name );
vbi_bool vbi_proxy_msg_check_connect( const char * p_sock_path );
int vbi_proxy_msg_connect_to_server( vbi_bool use_tcp_ip, const char * pSrvHost, const char * pSrvPort, char ** ppErrorText );
vbi_bool vbi_proxy_msg_finish_connect( int sock_fd, char ** ppErrorText );
int vbi_proxy_msg_check_ioctl( VBI_DRIVER_API_REV vbi_api,
int request, void * p_arg, vbi_bool * req_perm );
#endif /* PROXY_MSG_H */
syntax highlighted by Code2HTML, v. 0.9.1