#ifndef MODULE_DVBAPI_H_ #define MODULE_DVBAPI_H_ #ifdef HAVE_DVBAPI #include #define TYPE_ECM 1 #define TYPE_EMM 2 #define TYPE_SDT 3 #define TYPE_PAT 4 #define TYPE_PMT 5 #define TYPE_CAT 6 // api #define DVBAPI_3 0 #define DVBAPI_1 1 #define STAPI 2 #define COOLAPI 3 #ifdef __CYGWIN__ #define TMPDIR "./" #define STANDBY_FILE "./.pauseoscam" #define ECMINFO_FILE "./ecm.info" #else #define TMPDIR "/tmp/" #define STANDBY_FILE "/tmp/.pauseoscam" #define ECMINFO_FILE "/tmp/ecm.info" #endif #define BOX_COUNT 7 #define BOXTYPE_DREAMBOX 1 #define BOXTYPE_DUCKBOX 2 #define BOXTYPE_UFS910 3 #define BOXTYPE_DBOX2 4 #define BOXTYPE_IPBOX 5 #define BOXTYPE_IPBOX_PMT 6 #define BOXTYPE_DM7000 7 #define BOXTYPE_QBOXHD 8 #define BOXTYPE_COOLSTREAM 9 #define BOXTYPE_NEUMO 10 #define BOXTYPE_PC 11 #define BOXTYPE_PC_NODMX 12 #define BOXTYPE_SAMYGO 13 #define BOXTYPES 13 #define DMXMD5HASHSIZE 16 // use MD5() // we store the results of remove_streampid_from_list() // and update_streampid_list() in one variable, so make sure // the return values do not collide // remove_streampid_from_list() #define NO_STREAMPID_LISTED 0x00 #define REMOVED_STREAMPID_INDEX 0x01 #define REMOVED_STREAMPID_LASTINDEX 0x02 #define REMOVED_DECODING_STREAMPID_INDEX 0x03 // update_streampid_list(): #define FOUND_STREAMPID_INDEX 0x10 #define ADDED_STREAMPID_INDEX 0x11 #define FIRST_STREAMPID_INDEX 0x12 // remove_streampid_from_list() and update_streampid_list() #define INVALID_STREAMPID_INDEX 0x20 #define INDEX_DISABLE_ALL 0xEFFFFFFD // used for remove_streampid_from_list(), dvbapi_set_pid() #define INDEX_INVALID 0xEFFFFFFF #define DUMMY_FD 0xFFFF //----------------------------------------------------------------------------- // constants used in socket communication //----------------------------------------------------------------------------- #define DVBAPI_PROTOCOL_VERSION 3 #define DVBAPI_MAX_PACKET_SIZE 262 // maximum possible packet size #define DVBAPI_CA_GET_DESCR_INFO 0x80086F83 #define DVBAPI_CA_SET_DESCR 0x40106F86 #define DVBAPI_CA_SET_PID 0x40086F87 #define DVBAPI_CA_SET_DESCR_MODE 0x400C6F88 #define DVBAPI_CA_SET_DESCR_DATA 0x40186F89 //#define DVBAPI_DMX_START 0x00006F29 // in case we ever need this #define DVBAPI_DMX_STOP 0x00006F2A #define DVBAPI_DMX_SET_FILTER 0x403C6F2B #define DVBAPI_AOT_CA 0x9F803000 #define DVBAPI_AOT_CA_PMT 0x9F803200 // least significant byte is length (ignored) #define DVBAPI_AOT_CA_STOP 0x9F803F04 #define DVBAPI_FILTER_DATA 0xFFFF0000 #define DVBAPI_CLIENT_INFO 0xFFFF0001 #define DVBAPI_SERVER_INFO 0xFFFF0002 #define DVBAPI_ECM_INFO 0xFFFF0003 #define DVBAPI_INDEX_DISABLE 0xFFFFFFFF // only used for ca_pid_t //----------------------------------------------------------------------------- // CA PMT defined values according to EN 50221 // https://www.dvb.org/resources/public/standards/En50221.V1.pdf // https://www.dvb.org/resources/public/standards/R206-001.V1.pdf //----------------------------------------------------------------------------- // ca_pmt_list_management: This parameter is used to indicate whether the user has selected a single program or several // programs. The following values can be used: #define CA_PMT_LIST_MORE 0x00 // The CA PMT object is neither the first one, nor the last one of the list. #define CA_PMT_LIST_FIRST 0x01 // The CA PMT object is the first one of a new list of more than one CA PMT object. // All previously selected programs are being replaced by the programs of the new list. #define CA_PMT_LIST_LAST 0x02 // The CA PMT object is the last of the list. #define CA_PMT_LIST_ONLY 0x03 // The list is made of a single CA PMT object. #define CA_PMT_LIST_ADD 0x04 // The CA PMT has to be added to an existing list, that is, a new program has been seleced // by the user, but all previously selected programs remain selected. #define CA_PMT_LIST_UPDATE 0x05 // The CA PMT of a program already in the list is sent again because the version_number or // the current_next_indicator has changed. // ca_pmt_cmd_id: This parameter indicates what response is required from the application to a CA PMT object. It can // take the following values: #define CA_PMT_CMD_OK_DESCRAMBLING 0x01 // The host does not expect answer to the CA PMT and the application can start // descrambling the program or start an MMI dialogue immediately. #define CA_PMT_CMD_OK_MMI 0x02 // The application can start an MMI dialogue, but shall not start descrambling // before reception of a new CA PMT object with "ca_pmt_cmd_id" set to // "ok_descrambling". In this case the host shall quarantee that an MMI session // can be opened by the CA application. #define CA_PMT_CMD_QUERY 0x03 // The host expects to receive a CA PMT reply. In this case, the applicaiton is // not allowed to start descrambling or MMI dialogue before reception of a new // CA PMT object with "ca_pmt_cmd_id" set to "ok_descrambling or "ok_mmi". #define CA_PMT_CMD_NOT_SELECTED 0x04 // It indicates to the CA application that the host no longer requires that CA // application to attempt to descramble the service. The CA application shall // close any MMI dialogue it has opened. //---------------- // ca descriptors //---------------- #define CA 0x09 #define ENIGMA_NAMESPACE 0x81 #define DEMUX_CA_MASK_ADAPTER 0x82 // deprecated - applications should use descriptors ADAPTER_DEVICE, DEMUX_DEVICE and CA_DEVICE instead #define ADAPTER_DEVICE 0x83 #define PMT_PID 0x84 #define SERVICE_TYPE_MASK 0x85 // not used by OSCam #define DEMUX_DEVICE 0x86 #define CA_DEVICE 0x87 //----------------------------------------------------------------------------- // api used for internal device communication //----------------------------------------------------------------------------- #define DMX_FILTER_SIZE 16 // The following is part of the linux dvb api (v1), // but modifed to overcome some bugs in specific devices typedef struct dmxFilter { uint8_t filter[DMX_FILTER_SIZE]; uint8_t mask[DMX_FILTER_SIZE]; } dmxFilter_t; struct dmxSctFilterParams { uint16_t pid; dmxFilter_t filter; uint32_t timeout; uint32_t flags; #define DMX_CHECK_CRC 1 #define DMX_ONESHOT 2 #define DMX_IMMEDIATE_START 4 }; #define DMX_START1 _IOW('o', 41, int) #define DMX_STOP1 _IOW('o', 42, int) #define DMX_SET_FILTER1 _IOW('o', 43, struct dmxSctFilterParams *) // The following is part of the linux dvb api // https://www.kernel.org/doc/html/latest/media/uapi/dvb/demux.html // https://github.com/torvalds/linux/blob/master/include/uapi/linux/dvb/dmx.h typedef struct dmx_filter { uint8_t filter[DMX_FILTER_SIZE]; uint8_t mask[DMX_FILTER_SIZE]; uint8_t mode[DMX_FILTER_SIZE]; } dmx_filter_t; struct dmx_sct_filter_params { uint16_t pid; dmx_filter_t filter; uint32_t timeout; uint32_t flags; #define DMX_CHECK_CRC 1 #define DMX_ONESHOT 2 #define DMX_IMMEDIATE_START 4 }; #define DMX_START _IO('o', 41) #define DMX_STOP _IO('o', 42) #define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params) // The following is part of the linux dvb api // https://www.kernel.org/doc/html/latest/media/uapi/dvb/ca.html // https://github.com/torvalds/linux/blob/master/include/uapi/linux/dvb/ca.h typedef struct ca_descr_info { uint32_t num; uint32_t type; /* bitmask: 1 == ECD, 2 == NDS, 4 == DDS */ } ca_descr_info_t; typedef struct ca_descr { uint32_t index; uint32_t parity; /* 0 == even, 1 == odd */ uint8_t cw[8]; } ca_descr_t; // ca_pid has been removed from the api, but we still use it typedef struct ca_pid { uint32_t pid; int32_t index; /* -1 == disable */ } ca_pid_t; enum ca_descr_algo { CA_ALGO_DVBCSA, CA_ALGO_DES, CA_ALGO_AES128, }; enum ca_descr_cipher_mode { CA_MODE_ECB, CA_MODE_CBC, }; // Structs "ca_descr_mode" and "ca_descr_data" and respective ioctl // commands are part of a custom api /* * struct ca_descr_mode - Used to select a crypto algorithm and mode * for a key slot. * * @index: Key slot allocated for a PID or service. * See CA_SET_PID and struct ca_pid. * @algo: Algorithm to select for @index. * @cipher_mode: Cipher mode to use with @algo. */ typedef struct ca_descr_mode { uint32_t index; enum ca_descr_algo algo; enum ca_descr_cipher_mode cipher_mode; } ca_descr_mode_t; /* * struct ca_descr_data - Used to write Keys and IVs to a descrambler. * * @index: Key slot allocated for a PID or service. * See CA_SET_PID and struct ca_pid. * @parity: Indicates even or odd parity for control words. * @data_type: Key or IV. * @length: Size of @data array; depends on selected algorithm and * key or block size. * @data: Pointer to variable @length key or initialization vector data. */ enum ca_descr_data_type { CA_DATA_IV, CA_DATA_KEY, }; enum ca_descr_parity { CA_PARITY_EVEN, CA_PARITY_ODD, }; typedef struct ca_descr_data { uint32_t index; enum ca_descr_parity parity; enum ca_descr_data_type data_type; uint32_t length; uint8_t *data; } ca_descr_data_t; #define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t) #define CA_SET_DESCR _IOW('o', 134, ca_descr_t) #define CA_SET_PID _IOW('o', 135, ca_pid_t) #define CA_SET_DESCR_MODE _IOW('o', 136, ca_descr_mode_t) #define CA_SET_DESCR_DATA _IOW('o', 137, ca_descr_data_t) //----------------------------------------------------------------------------- // OSCam defined structures //----------------------------------------------------------------------------- struct box_devices { char *path; char *ca_device; char *demux_device; char *cam_socket_path; int8_t api; }; typedef struct filter_s { uint32_t fd; // filter handle int32_t pidindex; int32_t pid; uint16_t caid; uint32_t provid; uint16_t type; int32_t count; uint8_t filter[16]; uint8_t mask[16]; uint8_t lastecmd5[CS_ECMSTORESIZE]; // last requested ecm md5 int32_t lastresult; uint8_t prevecmd5[CS_ECMSTORESIZE]; // previous requested ecm md5 int32_t prevresult; #if defined(WITH_STAPI) || defined(WITH_STAPI5) int32_t NumSlots; uint32_t SlotHandle[10]; uint32_t BufferHandle[10]; #endif #ifdef WITH_EMU uint32_t cadata; #endif } FILTERTYPE; #ifdef WITH_EXTENDED_CW #define MAX_STREAM_INDICES 32 // In practice, 5 is the maximum ever used #else #define MAX_STREAM_INDICES 1 #endif #define CA_MAX 32 // Max ca devices supported by oscam - limited by sizeof(ca_mask) of struct demux_s (32 bits) #define INDEX_MAX 64 // Max descramblers per ca device - limited by sizeof(activeindexers) of struct s_streampid (64 bits) #define INDEX_MAX_LOCAL 16 // Max total descramblers to use for enigma2 and other STBs when dvbapi_get_descrambler_info() fails #define INDEX_MAX_NET 64 // Max total descramblers to use for PC (VDR, Tvheadend, etc) typedef struct s_ecmpid { uint16_t CAID; uint32_t PROVID; // provider uint16_t ECM_PID; uint32_t CHID; uint16_t EMM_PID; uint32_t VPID; // video pid uint8_t irdeto_maxindex; // max irdeto indices always fresh fetched from current ecm uint8_t irdeto_curindex; // current irdeto index we want to handle uint8_t irdeto_cycle; // temp var that holds the irdeto index we started with to detect if we cycled trough all indices int8_t checked; int8_t status; uint8_t tries; uint8_t table; int8_t useMultipleIndices; // whether or not to use multiple indices for this ecm pid uint32_t index[MAX_STREAM_INDICES]; // ca indices used for this ecm pid (index[0] holds ca index for STREAMmpids[0] and so on) uint32_t streams; // bit mask of STREAMpids enabled for this ECMpid uint32_t cadata; #ifdef WITH_EMU int16_t pvu_counter; #endif } ECMPIDTYPE; typedef struct s_emmpid { uint16_t CAID; uint32_t PROVID; uint16_t PID; uint8_t type; uint32_t cadata; } EMMPIDTYPE; enum stream_type { STREAM_UNDEFINED, STREAM_VIDEO, STREAM_AUDIO, STREAM_SUBTITLE }; #define MAX_DEMUX 32 // Max number of demuxes supported by OSCam - each channel/service occupies one demux #define MAX_ECM_PIDS 24 // Max number of ECM pids per demux #define MAX_EMM_PIDS 24 // Max number of EMM pids per demux #define MAX_STREAM_PIDS 32 // Max number of pids other than ECM and EMM (e.g. audio, video, subtitle, etc) per demux (hardware descramblers might have a capacity of 30 pids) #define MAX_FILTER 64 #define MAX_ASSOC_FD MAX_DEMUX #define PTINUM 10 #define SLOTNUM 20 typedef struct demux_s { int8_t demux_index; // ID of the (hardware) demux device carrying this program - we get this via CA PMT int8_t adapter_index; // ID of the adapter device carrying this program - we get this via CA PMT uint32_t ca_mask; // Bit mask of ca devices used for descrambling this program - we get this via CA PMT int32_t socket_fd; // Connection identifier through which we received the CA PMT object uint16_t client_proto_version; FILTERTYPE demux_fd[MAX_FILTER]; int8_t ECMpidcount; // Count of ECM pids in this program ECMPIDTYPE ECMpids[MAX_ECM_PIDS]; int8_t EMMpidcount; // Count of EMM pids in this program EMMPIDTYPE EMMpids[MAX_EMM_PIDS]; struct timeb emmstart; // last time emm cat was started uint16_t max_emm_filter; int8_t STREAMpidcount; uint16_t STREAMpids[MAX_STREAM_PIDS]; enum stream_type STREAMpidsType[MAX_STREAM_PIDS]; // type (audio, video, subtitle, etc) of the corresponding stream pid int16_t pidindex; // ECMpid used for descrambling - holds index of the ECMpids[] array int16_t curindex; int8_t max_status; uint16_t program_number; // also called service id (srvid) uint16_t onid; // original network id uint16_t tsid; // transport stream id uint16_t pmtpid; // PMT pid for the program_number uint32_t ens; // enigma namespace uint8_t last_cw[MAX_STREAM_INDICES][2][16]; // even/odd pairs of 16 byte CWs used for descrambling on the last crypto period int8_t emm_filter; int8_t sdt_filter; uint8_t hexserial[8]; struct s_reader *rdr; char pmt_file[30]; time_t pmt_time; bool stop_descrambling; // Program is marked to stop descrambling (not selected in the new CA PMT list) bool running; // Descrambling is currently running for this program uint8_t old_ecmfiltercount; // previous ecm filter count uint8_t old_emmfiltercount; // previous emm filter count pthread_mutex_t answerlock; // request mode 1 avoid race #ifdef WITH_STAPI uint32_t DescramblerHandle[PTINUM]; int32_t desc_pidcount; uint32_t slot_assc[PTINUM][SLOTNUM]; #endif #ifdef WITH_STAPI5 uint32_t dev_index; #endif int8_t decodingtries; // -1 = first run struct timeb decstart; struct timeb decend; uint32_t msgid; } DEMUXTYPE; typedef struct s_streampid { uint16_t streampid; // pid of this stream uint8_t cadevice; // CA device used for descramlbing uint32_t caindex; // index (slot) of the CA device used uint64_t activeindexers; // bitmask indexers if streampid enabled for index, bit is set bool use_des; // whether to use DES for descrambling this streampid } STREAMPIDTYPE; struct s_dvbapi_priority { char type; // can be 'p', 'i', 'm', 'd', 's', 'l', 'j', 'a' or 'x' uint16_t caid; uint32_t provid; uint16_t srvid; uint32_t chid; uint16_t ecmpid; uint32_t cadata; uint16_t mapcaid; uint32_t mapprovid; uint16_t mapecmpid; int16_t delay; int8_t force; int8_t pidx; #if defined(WITH_STAPI) || defined(WITH_STAPI5) char devname[30]; char pmtfile[30]; int8_t disablefilter; #endif struct s_dvbapi_priority *next; }; //----------------------------------------------------------------------------- // function declarations //----------------------------------------------------------------------------- void dvbapi_stop_descrambling(int32_t demux_id, uint32_t msgid); void dvbapi_stop_all_descrambling(uint32_t msgid); void dvbapi_process_input(int32_t demux_id, int32_t filter_num, uint8_t *buffer, int32_t len, uint32_t msgid); int32_t dvbapi_open_device(int32_t, int32_t, int); int32_t dvbapi_stop_filternum(int32_t demux_id, int32_t num, uint32_t msgid); int32_t dvbapi_stop_filter(int32_t demux_id, int32_t type, uint32_t msgid); struct s_dvbapi_priority *dvbapi_check_prio_match(int32_t demux_id, int32_t pidindex, char type); void dvbapi_send_dcw(struct s_client *client, ECM_REQUEST *er); void dvbapi_write_cw(int32_t demux_id, int32_t pid, int32_t stream_id, uint8_t *cw, uint8_t cw_length, uint8_t *iv, uint8_t iv_length, enum ca_descr_algo algo, enum ca_descr_cipher_mode cipher_mode, uint32_t msgid); int32_t dvbapi_parse_capmt(const uint8_t *buffer, uint32_t length, int32_t connfd, char *pmtfile, uint16_t client_proto_version, uint32_t msgid); void request_cw(struct s_client *client, ECM_REQUEST *er, int32_t demux_id, uint8_t delayed_ecm_check); void dvbapi_try_next_caid(int32_t demux_id, int8_t checked, uint32_t msgid); void dvbapi_read_priority(void); int32_t dvbapi_set_section_filter(int32_t demux_id, ECM_REQUEST *er, int32_t n); int32_t dvbapi_activate_section_filter(int32_t demux_id, int32_t num, int32_t fd, int32_t pid, uint8_t *filter, uint8_t *mask, uint32_t msgid); int32_t dvbapi_check_ecm_delayed_delivery(int32_t demux_id, ECM_REQUEST *er); int32_t dvbapi_get_filternum(int32_t demux_id, ECM_REQUEST *er, int32_t type); uint32_t dvbapi_ca_set_pid(int32_t demux_id, int32_t pid, int32_t stream_id, bool use_des, uint32_t msgid); void dvbapi_set_pid(int32_t demux_id, int32_t num, uint32_t idx, bool enable, bool use_des, uint32_t msgid); int8_t update_streampid_list(uint8_t cadevice, uint16_t pid, uint32_t idx, bool use_des); int8_t remove_streampid_from_list(uint8_t cadevice, uint16_t pid, uint32_t idx); void disable_unused_streampids(int16_t demux_id); uint32_t is_ca_used(uint8_t cadevice, int32_t pid); uint32_t count_active_indexers(void); uint16_t dvbapi_get_client_proto_version(void); const char *dvbapi_get_client_name(void); void rotate_emmfilter(int32_t demux_id); int32_t filtermatch(uint8_t *buffer, int32_t filter_num, int32_t demux_id, int32_t len); void delayer(ECM_REQUEST *er, uint32_t delay); void check_add_emmpid(int32_t demux_id, uint8_t *filter, int32_t l, int32_t emmtype); void *dvbapi_start_handler(struct s_client *cl, uint8_t *mbuf, int32_t module_idx, void *(*_main_func)(void *)); uint32_t dvbapi_get_desc_index(int32_t demux_id, int32_t pid, int32_t stream_id); void dvbapi_write_ecminfo_file(struct s_client *client, ECM_REQUEST *er, uint8_t *lastcw0, uint8_t *lastcw1, uint8_t cw_length); #if defined(WITH_AZBOX) || defined(WITH_MCA) #define USE_OPENXCAS 1 extern int32_t openxcas_provid; extern uint16_t openxcas_sid, openxcas_caid, openxcas_ecm_pid; static inline void openxcas_set_caid(uint16_t _caid) { openxcas_caid = _caid; } static inline void openxcas_set_ecm_pid(uint16_t _pid) { openxcas_ecm_pid = _pid; } static inline void openxcas_set_sid(uint16_t _sid) { openxcas_sid = _sid; } static inline void openxcas_set_provid(uint32_t _provid) { openxcas_provid = _provid; } #else #define USE_OPENXCAS 0 static inline void openxcas_set_caid(uint16_t UNUSED(_caid)) { } static inline void openxcas_set_ecm_pid(uint16_t UNUSED(_pid)) { } static inline void openxcas_set_sid(uint16_t UNUSED(_sid)) { } static inline void openxcas_set_provid(uint32_t UNUSED(_provid)) { } #endif bool is_dvbapi_usr(char *usr); static inline bool module_dvbapi_enabled(void) { return cfg.dvbapi_enabled; } #else static inline void dvbapi_stop_all_descrambling(uint32_t UNUSED(msgid)) { } static inline void dvbapi_read_priority(void) { } static inline bool is_dvbapi_usr(char *UNUSED(usr)) { return 0; } static inline bool module_dvbapi_enabled(void) { return 0; } #endif // WITH_DVBAPI #endif // MODULE_DVBAPI_H_