12 #include <linux/dvb/ca.h>
14 #include <netinet/in.h>
17 #include <sys/ioctl.h>
34 #define dbgprotocol(a...) do { if (DebugProtocol) fprintf(stderr, a); } while (0)
38 #define SIZE_INDICATOR 0x80
40 static const uint8_t *
GetLength(
const uint8_t *Data,
int &Length)
47 int l = Length & ~SIZE_INDICATOR;
49 for (
int i = 0; i < l; i++)
50 Length = (Length << 8) | *Data++;
55 static uint8_t *
SetLength(uint8_t *Data,
int Length)
63 int n =
sizeof(Length);
64 for (
int i = n - 1; i >= 0; i--) {
65 int b = (Length >> (8 * i)) & 0xFF;
81 while (Length > 0 && (*Data ==
' ' || *Data == 0x05 || *Data == 0x96 || *Data == 0x97)) {
85 char *s =
MALLOC(
char, Length + 1);
86 strncpy(s, (
char *)Data, Length);
93 static char *
GetString(
int &Length,
const uint8_t **Data)
98 if (Length > 0 && Data && *Data) {
102 Length -= d - *Data + l;
169 length = (int(Data[6] & 0x03) << 8) | Data[7];
171 int v = (Data[10] & 0x3E) >> 1;
173 if (Data[11] == 0 && Data[12] == 0) {
176 memcpy(
buffer, Data + 13, n);
186 dsyslog(
"multi table CAT section - unhandled!");
195 memcpy(
bufp, Data + 4, n);
204 esyslog(
"ERROR: buffer overflow in cCaPidReceiver::Receive()");
213 AttachedDevice->
Detach(
this);
215 for (
int i = 0; i <
length - 4; i++) {
217 int CaId = int(p[i + 2] << 8) | p[i + 3];
218 int EmmPid = int(((p[i + 4] & 0x1F) << 8)) | p[i + 5];
221 case 0x01:
for (
int j = i + 7; j < p[i + 1] + 2; j += 4) {
222 EmmPid = (int(p[j] & 0x0F) << 8) | p[j + 1];
227 i += p[i + 1] + 2 - 1;
245 #define UNSCRAMBLE_TIME 5 // seconds of receiving purely unscrambled data before considering the smart card "activated"
246 #define TS_PACKET_FACTOR 1024 // only process every TS_PACKET_FACTORth packet to keep the load down
276 time_t Now = time(NULL);
289 #define MAX_TPDU_SIZE 2048
290 #define MAX_TPDU_DATA (MAX_TPDU_SIZE - 4)
292 #define DATA_INDICATOR 0x80
296 #define T_CREATE_TC 0x82
297 #define T_CTC_REPLY 0x83
298 #define T_DELETE_TC 0x84
299 #define T_DTC_REPLY 0x85
300 #define T_REQUEST_TC 0x86
301 #define T_NEW_TC 0x87
302 #define T_TC_ERROR 0x88
303 #define T_DATA_LAST 0xA0
304 #define T_DATA_MORE 0xA1
310 const uint8_t *
GetData(
const uint8_t *
Data,
int &Length);
323 void Dump(
int SlotNumber,
bool Outgoing);
326 cTPDU::cTPDU(uint8_t Slot, uint8_t Tcid, uint8_t Tag,
int Length,
const uint8_t *Data)
352 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)", Tag, Length, Slot, Tcid);
361 memcpy(p, Data, Length);
365 esyslog(
"ERROR: invalid data length for TPDU tag 0x%02X: %d (%d/%d)", Tag, Length, Slot, Tcid);
368 esyslog(
"ERROR: unknown TPDU tag: 0x%02X (%d/%d)", Tag, Slot, Tcid);
376 fprintf(stderr,
" %d: %s ", SlotNumber, Outgoing ?
"-->" :
"<--");
378 fprintf(stderr,
"%02X ",
buffer[i]);
379 fprintf(stderr,
"%s\n",
size >= MAX_DUMP ?
"..." :
"");
381 fprintf(stderr,
" ");
383 fprintf(stderr,
"%2c ", isprint(
buffer[i]) ?
buffer[i] :
'.');
384 fprintf(stderr,
"%s\n",
size >= MAX_DUMP ?
"..." :
"");
410 #define MAX_SESSIONS_PER_TC 16
424 void SendTPDU(uint8_t Tag,
int Length = 0,
const uint8_t *Data = NULL);
425 void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0,
int Status = -1);
442 void SendData(
int Length,
const uint8_t *Data);
451 #define ST_SESSION_NUMBER 0x90
452 #define ST_OPEN_SESSION_REQUEST 0x91
453 #define ST_OPEN_SESSION_RESPONSE 0x92
454 #define ST_CREATE_SESSION 0x93
455 #define ST_CREATE_SESSION_RESPONSE 0x94
456 #define ST_CLOSE_SESSION_REQUEST 0x95
457 #define ST_CLOSE_SESSION_RESPONSE 0x96
462 #define SS_NOT_ALLOCATED 0xF0
466 #define RI_RESOURCE_MANAGER 0x00010041
467 #define RI_APPLICATION_INFORMATION 0x00020041
468 #define RI_CONDITIONAL_ACCESS_SUPPORT 0x00030041
469 #define RI_HOST_CONTROL 0x00200041
470 #define RI_DATE_TIME 0x00240041
471 #define RI_MMI 0x00400041
475 #define AOT_NONE 0x000000
476 #define AOT_PROFILE_ENQ 0x9F8010
477 #define AOT_PROFILE 0x9F8011
478 #define AOT_PROFILE_CHANGE 0x9F8012
479 #define AOT_APPLICATION_INFO_ENQ 0x9F8020
480 #define AOT_APPLICATION_INFO 0x9F8021
481 #define AOT_ENTER_MENU 0x9F8022
482 #define AOT_CA_INFO_ENQ 0x9F8030
483 #define AOT_CA_INFO 0x9F8031
484 #define AOT_CA_PMT 0x9F8032
485 #define AOT_CA_PMT_REPLY 0x9F8033
486 #define AOT_TUNE 0x9F8400
487 #define AOT_REPLACE 0x9F8401
488 #define AOT_CLEAR_REPLACE 0x9F8402
489 #define AOT_ASK_RELEASE 0x9F8403
490 #define AOT_DATE_TIME_ENQ 0x9F8440
491 #define AOT_DATE_TIME 0x9F8441
492 #define AOT_CLOSE_MMI 0x9F8800
493 #define AOT_DISPLAY_CONTROL 0x9F8801
494 #define AOT_DISPLAY_REPLY 0x9F8802
495 #define AOT_TEXT_LAST 0x9F8803
496 #define AOT_TEXT_MORE 0x9F8804
497 #define AOT_KEYPAD_CONTROL 0x9F8805
498 #define AOT_KEYPRESS 0x9F8806
499 #define AOT_ENQ 0x9F8807
500 #define AOT_ANSW 0x9F8808
501 #define AOT_MENU_LAST 0x9F8809
502 #define AOT_MENU_MORE 0x9F880A
503 #define AOT_MENU_ANSW 0x9F880B
504 #define AOT_LIST_LAST 0x9F880C
505 #define AOT_LIST_MORE 0x9F880D
506 #define AOT_SUBTITLE_SEGMENT_LAST 0x9F880E
507 #define AOT_SUBTITLE_SEGMENT_MORE 0x9F880F
508 #define AOT_DISPLAY_MESSAGE 0x9F8810
509 #define AOT_SCENE_END_MARK 0x9F8811
510 #define AOT_SCENE_DONE 0x9F8812
511 #define AOT_SCENE_CONTROL 0x9F8813
512 #define AOT_SUBTITLE_DOWNLOAD_LAST 0x9F8814
513 #define AOT_SUBTITLE_DOWNLOAD_MORE 0x9F8815
514 #define AOT_FLUSH_DOWNLOAD 0x9F8816
515 #define AOT_DOWNLOAD_REPLY 0x9F8817
516 #define AOT_COMMS_CMD 0x9F8C00
517 #define AOT_CONNECTION_DESCRIPTOR 0x9F8C01
518 #define AOT_COMMS_REPLY 0x9F8C02
519 #define AOT_COMMS_SEND_LAST 0x9F8C03
520 #define AOT_COMMS_SEND_MORE 0x9F8C04
521 #define AOT_COMMS_RCV_LAST 0x9F8C05
522 #define AOT_COMMS_RCV_MORE 0x9F8C06
530 int GetTag(
int &Length,
const uint8_t **Data);
531 const uint8_t *
GetData(
const uint8_t *Data,
int &Length);
532 void SendData(
int Tag,
int Length = 0,
const uint8_t *Data = NULL);
540 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
559 if (Length >= 3 && Data && *Data) {
561 for (
int i = 0; i < 3; i++)
562 t = (t << 8) | *(*Data)++;
572 return Length ? Data : NULL;
577 uint8_t buffer[2048];
583 *p++ = (Tag >> 16) & 0xFF;
584 *p++ = (Tag >> 8) & 0xFF;
587 if (p - buffer + Length <
int(
sizeof(buffer))) {
589 memcpy(p, Data, Length);
594 esyslog(
"ERROR: CAM %d: data length (%d) exceeds buffer size",
Tc()->CamSlot()->SlotNumber(), Length);
608 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
621 int Tag =
GetTag(Length, &Data);
640 const uint8_t *d =
GetData(Data, l);
642 esyslog(
"ERROR: CAM %d: resource manager: unexpected data",
Tc()->CamSlot()->SlotNumber());
648 esyslog(
"ERROR: CAM %d: resource manager: unexpected tag %06X in state %d",
Tc()->CamSlot()->SlotNumber(), Tag,
state);
652 default:
esyslog(
"ERROR: CAM %d: resource manager: unknown tag %06X",
Tc()->CamSlot()->SlotNumber(), Tag);
655 else if (
state == 0) {
674 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
695 int Tag =
GetTag(Length, &Data);
700 const uint8_t *d =
GetData(Data, l);
701 if ((l -= 1) < 0)
break;
703 if ((l -= 2) < 0)
break;
706 if ((l -= 2) < 0)
break;
715 default:
esyslog(
"ERROR: CAM %d: application information: unknown tag %06X",
Tc()->CamSlot()->SlotNumber(), Tag);
718 else if (
state == 0) {
737 #define MAXCASYSTEMIDS 64
741 #define CPLM_MORE 0x00
742 #define CPLM_FIRST 0x01
743 #define CPLM_LAST 0x02
744 #define CPLM_ONLY 0x03
745 #define CPLM_ADD 0x04
746 #define CPLM_UPDATE 0x05
750 #define CPCI_OK_DESCRAMBLING 0x01
751 #define CPCI_OK_MMI 0x02
752 #define CPCI_QUERY 0x03
753 #define CPCI_NOT_SELECTED 0x04
768 cCiCaPmt(uint8_t
CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds);
772 void AddPid(
int Pid, uint8_t StreamType);
775 cCiCaPmt::cCiCaPmt(uint8_t CmdId,
int Source,
int Transponder,
int ProgramNumber,
const int *CaSystemIds)
783 for (; CaSystemIds[i]; i++)
787 uint8_t caDescriptors[512];
808 uint8_t caDescriptors[512];
831 capmt[esInfoLengthPos + 1] = l & 0xFF;
835 esyslog(
"ERROR: buffer overflow in CA descriptor");
839 esyslog(
"ERROR: adding CA descriptor without Pid!");
846 #define CAEI_POSSIBLE 0x01
847 #define CAEI_POSSIBLE_COND_PURCHASE 0x02
848 #define CAEI_POSSIBLE_COND_TECHNICAL 0x03
849 #define CAEI_NOT_POSSIBLE_ENTITLEMENT 0x71
850 #define CAEI_NOT_POSSIBLE_TECHNICAL 0x73
852 #define CA_ENABLE_FLAG 0x80
854 #define CA_ENABLE(x) (((x) & CA_ENABLE_FLAG) ? (x) & ~CA_ENABLE_FLAG : 0)
856 #define QUERY_WAIT_TIME 1000 // ms to wait before sending a query
857 #define QUERY_REPLY_TIMEOUT 2000 // ms to wait for a reply to a query
868 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
889 int Tag =
GetTag(Length, &Data);
896 const uint8_t *d =
GetData(Data, l);
898 uint16_t
id = ((uint16_t)(*d) << 8) | *(d + 1);
906 esyslog(
"ERROR: CAM %d: too many CA system IDs!",
Tc()->CamSlot()->SlotNumber());
916 dsyslog(
"CAM %d: system ids:%s",
Tc()->CamSlot()->SlotNumber(), *Ids ? *Ids :
" none");
922 dsyslog(
"CAM %d: replies to QUERY - multi channel decryption possible",
Tc()->CamSlot()->SlotNumber());
927 const uint8_t *d =
GetData(Data, l);
929 uint16_t pnr = ((uint16_t)(*d) << 8) | *(d + 1);
938 if (l % 3 == 0 && l > 1) {
944 uint16_t len = ((uint16_t)(*d) << 8) | *(d + 1);
950 unsigned char caepl = *d;
958 uint16_t pid = ((uint16_t)(*d) << 8) | *(d + 1);
959 unsigned char caees = *(d + 2);
974 default:
esyslog(
"ERROR: CAM %d: conditional access support: unknown tag %06X",
Tc()->CamSlot()->SlotNumber(), Tag);
977 else if (
state == 0) {
989 dsyslog(
"CAM %d: doesn't reply to QUERY - only a single channel can be decrypted",
Tc()->CamSlot()->SlotNumber());
996 if (CaPmt &&
state >= 2) {
1012 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1025 time_t t = time(NULL);
1028 if (gmtime_r(&t, &tm_gmt) && localtime_r(&t, &tm_loc)) {
1029 int Y = tm_gmt.tm_year;
1030 int M = tm_gmt.tm_mon + 1;
1031 int D = tm_gmt.tm_mday;
1032 int L = (M == 1 || M == 2) ? 1 : 0;
1033 int MJD = 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
1034 #define DEC2BCD(d) uint8_t(((d / 10) << 4) + (d % 10))
1036 struct tTime { uint16_t mjd; uint8_t h, m, s;
short offset; };
1038 tTime T = { mjd : htons(MJD), h :
DEC2BCD(tm_gmt.tm_hour), m :
DEC2BCD(tm_gmt.tm_min), s :
DEC2BCD(tm_gmt.tm_sec), offset : short(htons(tm_loc.tm_gmtoff / 60)) };
1051 int Tag =
GetTag(Length, &Data);
1056 const uint8_t *d =
GetData(Data, l);
1064 default:
esyslog(
"ERROR: CAM %d: date time: unknown tag %06X",
Tc()->CamSlot()->SlotNumber(), Tag);
1077 #define DCC_SET_MMI_MODE 0x01
1078 #define DCC_DISPLAY_CHARACTER_TABLE_LIST 0x02
1079 #define DCC_INPUT_CHARACTER_TABLE_LIST 0x03
1080 #define DCC_OVERLAY_GRAPHICS_CHARACTERISTICS 0x04
1081 #define DCC_FULL_SCREEN_GRAPHICS_CHARACTERISTICS 0x05
1085 #define MM_HIGH_LEVEL 0x01
1086 #define MM_LOW_LEVEL_OVERLAY_GRAPHICS 0x02
1087 #define MM_LOW_LEVEL_FULL_SCREEN_GRAPHICS 0x03
1091 #define DRI_MMI_MODE_ACK 0x01
1092 #define DRI_LIST_DISPLAY_CHARACTER_TABLES 0x02
1093 #define DRI_LIST_INPUT_CHARACTER_TABLES 0x03
1094 #define DRI_LIST_GRAPHIC_OVERLAY_CHARACTERISTICS 0x04
1095 #define DRI_LIST_FULL_SCREEN_GRAPHIC_CHARACTERISTICS 0x05
1096 #define DRI_UNKNOWN_DISPLAY_CONTROL_CMD 0xF0
1097 #define DRI_UNKNOWN_MMI_MODE 0xF1
1098 #define DRI_UNKNOWN_CHARACTER_TABLE 0xF2
1102 #define EF_BLIND 0x01
1106 #define AI_CANCEL 0x00
1107 #define AI_ANSWER 0x01
1111 char *
GetText(
int &Length,
const uint8_t **Data);
1117 virtual void Process(
int Length = 0,
const uint8_t *Data = NULL);
1153 int Tag =
GetTag(Length, Data);
1160 esyslog(
"ERROR: CAM %d: MMI: unexpected text tag: %06X",
Tc()->CamSlot()->SlotNumber(), Tag);
1167 int Tag =
GetTag(Length, &Data);
1172 const uint8_t *d =
GetData(Data, l);
1177 struct tDisplayReply { uint8_t id; uint8_t mode; };
1183 default:
esyslog(
"ERROR: CAM %d: MMI: unsupported display control command %02X",
Tc()->CamSlot()->SlotNumber(), *d);
1194 const uint8_t *d =
GetData(Data, l);
1219 const uint8_t *d =
GetData(Data, l);
1221 uint8_t blind = *d++;
1236 const uint8_t *d =
GetData(Data, l);
1242 dbgprotocol(
"Slot %d: <== Close MMI (%d) id = %02X delay = %d\n",
Tc()->CamSlot()->SlotNumber(),
SessionId(),
id, delay);
1245 default:
esyslog(
"ERROR: CAM %d: MMI: unknown tag %06X",
Tc()->CamSlot()->SlotNumber(), Tag);
1281 struct tAnswer { uint8_t id;
char text[256]; };
1285 strncpy(answer.text, Text,
sizeof(answer.text));
1393 #define TC_POLL_TIMEOUT 300 // ms WORKAROUND: TC_POLL_TIMEOUT < 300ms doesn't work with DragonCAM
1394 #define TC_ALIVE_TIMEOUT 2000 // ms after which a transport connection is assumed dead
1419 return cas && cas->
Ready();
1445 uint8_t *p = buffer;
1456 buffer[1] = p - buffer - 2;
1491 if (Length == 6 && *(Data + 1) == 0x04) {
1497 switch (ResourceId) {
1522 if (Session &&
sessions[SessionId] == Session) {
1536 const uint8_t *Data = TPDU->
Data(Length);
1537 if (Data && Length > 1) {
1540 uint16_t SessionId = ntohs(
get_unaligned((uint16_t *)&Data[2]));
1543 Session->
Process(Length - 4, Data + 4);
1595 switch (TPDU->
Tag()) {
1622 esyslog(
"ERROR: unknown TPDU tag: 0x%02X (%s)", TPDU->
Tag(), __FUNCTION__);
1643 esyslog(
"ERROR: unknown state: %d (%s)",
state, __FUNCTION__);
1703 esyslog(
"ERROR: no free CAM slot in CI adapter");
1739 #define MODULE_CHECK_INTERVAL 500 // ms
1740 #define MODULE_RESET_TIMEOUT 2 // s
1779 if (!Query || !Device) {
1830 int n = TPDU->
Tcid();
1870 esyslog(
"ERROR: unknown module status %d (%s)", ms, __FUNCTION__);
1927 dsyslog(
"CAM %d: activating on device %d with channel %d (%s)",
SlotNumber(), d->DeviceNumber() + 1, Channel->Number(), Channel->Name());
2021 if (CaSystemIds && *CaSystemIds) {
2027 for (
int Loop = 1; Loop <= 2; Loop++) {
2030 bool Active =
false;
2034 CaPmt.
AddPid(q->pid, q->streamType);
2038 if ((Loop == 1) != Active) {
2052 p->modified =
false;
2064 cCiCaPmt CaPmt(CmdId, 0, 0, 0, NULL);
2094 for (
const int *ids = cas->
GetCaSystemIds(); ids && *ids; ids++) {
2095 for (
const int *
id = CaSystemIds; *id;
id++) {
2109 if (p->programNumber == ProgramNumber) {
2127 if (q->pid == Pid) {
2128 if (q->active != Active) {
2139 #define STREAM_TYPE_VIDEO 0x02
2140 #define STREAM_TYPE_AUDIO 0x04
2141 #define STREAM_TYPE_PRIVATE 0x06
2152 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2154 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2156 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2163 #define QUERY_REPLY_WAIT 100 // ms to wait between checks for a reply
2177 for (
const int *Apid = Channel->
Apids(); *Apid; Apid++)
2179 for (
const int *Dpid = Channel->
Dpids(); *Dpid; Dpid++)
2181 for (
const int *Spid = Channel->
Spids(); *Spid; Spid++)
2244 for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
2246 for (
cCamSlot *CamSlot = CamSlots.
First(); CamSlot; CamSlot = CamSlots.
Next(CamSlot)) {
2247 if (!CamSlot->Ready()) {
2260 #define CAM_CHECKED_TIMEOUT 15 // seconds before a CAM that has been checked for a particular channel will be checked again
2333 #define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL 3600 // seconds between cleanups
2361 if (ccr->ChannelID() == ChannelID)
2380 ccr->ClrChecked(CamSlotNumber);
2381 ccr->ClrDecrypt(CamSlotNumber);
2389 return ccr ? ccr->
CamChecked(CamSlotNumber) :
false;
2396 return ccr ? ccr->
CamDecrypt(CamSlotNumber) :
false;
virtual void Process(int Length=0, const uint8_t *Data=NULL)
uint8_t capmt[2048]
XXX is there a specified maximum?
cCiCaProgramData(int ProgramNumber)
#define AOT_DISPLAY_CONTROL
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
virtual void Action(void)
Handles the attached CAM slots in a separate thread.
const int * Dpids(void) const
bool Process(cTPDU *TPDU=NULL)
cCiCaPidData(int Pid, int StreamType)
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
static char * CopyString(int Length, const uint8_t *Data)
virtual ~cCiAdapter()
The derived class must call Cancel(3) in its destructor.
virtual bool HasUserIO(void)
virtual void StartActivation(void)
Puts the CAM in this slot into a mode where an inserted smart card can be activated.
cCamSlot * ItCamSlot(int &Iter)
Iterates over all added CAM slots of this adapter.
cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc)
cList< cCiCaPidData > pidList
virtual void AddPid(int ProgramNumber, int Pid, int StreamType)
Adds the given PID information to the list of PIDs.
virtual void Write(const uint8_t *Buffer, int Length)
Writes Length bytes of the given Buffer.
void Add(cListObject *Object, cListObject *After=NULL)
#define AOT_PROFILE_CHANGE
bool CamChecked(int CamSlotNumber)
int Ca(int Index=0) const
virtual void StartDecrypting(void)
Triggers sending all currently active CA_PMT entries to the CAM, so that it will start decrypting...
int caSystemIds[MAXCASYSTEMIDS+1]
bool TsPayloadStart(const uchar *p)
#define MAX_CONNECTIONS_PER_CAM_SLOT
static char * GetString(int &Length, const uint8_t **Data)
#define MAX_CAM_SLOTS_PER_ADAPTER
#define AOT_APPLICATION_INFO_ENQ
static cString sprintf(const char *fmt,...) __attribute__((format(printf
#define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL
virtual void Append(T Data)
int QueueMessage(eMessageType Type, const char *s, int Seconds=0, int Timeout=0)
Like Message(), but this function may be called from a background thread.
virtual void Process(int Length=0, const uint8_t *Data=NULL)
void SetCamSlot(cCamSlot *CamSlot)
Sets the given CamSlot to be used with this device.
#define dbgprotocol(a...)
virtual void Receive(uchar *Data, int Length)
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
#define ST_CLOSE_SESSION_RESPONSE
virtual void Process(int Length=0, const uint8_t *Data=NULL)
void Detach(cFilter *Filter)
Detaches the given filter from this device.
bool AttachReceiver(cReceiver *Receiver)
Attaches the given receiver to this device.
virtual bool CanActivate(void)
Returns true if there is a CAM in this slot that can be put into activation mode. ...
static bool DumpTPDUDataTransfer
bool AddPids(const int *Pids)
Adds the given zero terminated list of Pids to the list of PIDs of this receiver. ...
uint8_t ListManagement(void)
int GetTag(int &Length, const uint8_t **Data)
#define CPCI_NOT_SELECTED
virtual void Process(int Length=0, const uint8_t *Data=NULL)
#define AOT_APPLICATION_INFO
const int * GetCaSystemIds(void)
#define STREAM_TYPE_VIDEO
friend class cCiTransportConnection
virtual ~cCaPidReceiver()
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
char * GetText(int &Length, const uint8_t **Data)
int SlotIndex(void)
Returns the index of this CAM slot within its CI adapter.
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
#define ST_SESSION_NUMBER
const uint8_t * GetData(const uint8_t *Data, int &Length)
bool CamDecrypt(int CamSlotNumber)
virtual bool HasUserIO(void)
virtual eModuleStatus ModuleStatus(void)
Returns the status of the CAM in this slot.
void AddPid(int Pid, uint8_t StreamType)
cCiSession * sessions[MAX_SESSIONS_PER_TC+1]
virtual void AddChannel(const cChannel *Channel)
Adds all PIDs if the given Channel to the current list of PIDs.
uint32_t ResourceId(void)
void SetListManagement(uint8_t ListManagement)
#define RI_CONDITIONAL_ACCESS_SUPPORT
int TsPid(const uchar *p)
void SendCaPmt(uint8_t CmdId)
virtual bool Reset(int Slot)
Resets the CAM in the given Slot.
cCiTransportConnection * tc[MAX_CONNECTIONS_PER_CAM_SLOT+1]
void CreateConnection(void)
cCaActivationReceiver * caActivationReceiver
void SendTag(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId=0, int Status=-1)
#define MODULE_RESET_TIMEOUT
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
void DelPids(const int *Pids)
Deletes the given zero terminated list of Pids from the list of PIDs of this receiver.
#define ST_CLOSE_SESSION_REQUEST
cCiTransportConnection * tc
T * Next(const T *object) const
cCiSession * GetSessionByResourceId(uint32_t ResourceId)
int caSystemIds[MAXCASYSTEMIDS+1]
cChannelCamRelation(tChannelID ChannelID)
uint32_t ResourceIdToInt(const uint8_t *Data)
void HandleSessions(cTPDU *TPDU)
void Process(cTPDU *TPDU=NULL)
virtual bool HasUserIO(void)
Returns true if there is a pending user interaction, which shall be retrieved via GetMenu() or GetEnq...
void SetDecrypt(tChannelID ChannelID, int CamSlotNumber)
virtual bool CanDecrypt(const cChannel *Channel)
Returns true if there is a CAM in this slot that is able to decrypt the given Channel (or at least cl...
void SendData(int Tag, int Length=0, const uint8_t *Data=NULL)
cListObject * Next(void) const
cCiSession * GetSessionBySessionId(uint16_t SessionId)
virtual cCiMenu * GetMenu(void)
Gets a pending menu, or NULL if there is no menu.
bool SendAnswer(const char *Text)
cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc)
bool TimedOut(void) const
#define ST_OPEN_SESSION_RESPONSE
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
cList< cCiCaProgramData > caProgramList
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
Gets all CA descriptors for a given channel.
#define STREAM_TYPE_AUDIO
cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
bool IsAttached(void)
Returns true if this receiver is (still) attached to a device.
#define ST_OPEN_SESSION_REQUEST
virtual ~cCiTransportConnection()
cCiEnquiry * Enquiry(bool Clear=false)
#define AOT_DISPLAY_REPLY
void ClrChecked(int CamSlotNumber)
cCamSlot(cCiAdapter *CiAdapter, bool WantsTsData=false)
Creates a new CAM slot for the given CiAdapter.
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
virtual int Read(uint8_t *Buffer, int MaxLength)
Reads one chunk of data into the given Buffer, up to MaxLength bytes.
#define MAX_SESSIONS_PER_TC
eModuleStatus lastModuleStatus
#define STREAM_TYPE_PRIVATE
void AddCamSlot(cCamSlot *CamSlot)
Adds the given CamSlot to this CI adapter.
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
cCiTransportConnection * Tc(void)
bool TimedWait(cMutex &Mutex, int TimeoutMs)
void OpenSession(int Length, const uint8_t *Data)
const int * GetCaSystemIds(void)
void SetChecked(int CamSlotNumber)
#define CPCI_OK_DESCRAMBLING
void Dump(int SlotNumber, bool Outgoing)
bool AddPid(int Pid)
Adds the given Pid to the list of PIDs of this receiver.
static uint8_t * SetLength(uint8_t *Data, int Length)
virtual bool Reset(void)
Resets the CAM in this slot.
virtual bool IsDecrypting(void)
Returns true if the CAM in this slot is currently used for decrypting.
bool createConnectionRequested
cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc)
void SendMenuAnswer(uint8_t Selection)
void SendData(int Length, const uint8_t *Data)
int Priority(void) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY), or IDLEPRIORITY if no receiver is currently active.
const char * GetCamName(void)
void DelPid(int Pid)
Deletes the given Pid from the list of PIDs of this receiver.
void ClrDecrypt(tChannelID ChannelID, int CamSlotNumber)
virtual void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active...
cCamSlot * camSlots[MAX_CAM_SLOTS_PER_ADAPTER]
const int * Apids(void) const
virtual cCiEnquiry * GetEnquiry(void)
Gets a pending enquiry, or NULL if there is no enquiry.
cChannelCamRelation * AddEntry(tChannelID ChannelID)
cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc)
#define AOT_DATE_TIME_ENQ
bool WaitForAllCamSlotsReady(int Timeout=0)
Waits until all CAM slots have become ready, or the given Timeout (seconds) has expired.
#define CAM_CHECKED_TIMEOUT
void Del(cListObject *Object, bool DeleteObject=true)
#define RI_RESOURCE_MANAGER
virtual void Process(int Length=0, const uint8_t *Data=NULL)
cChannel * GetByNumber(int Number, int SkipGap=0)
void SendPMT(cCiCaPmt *CaPmt)
void Reply(const char *s)
cCiMenu * Menu(bool Clear=false)
virtual eModuleStatus ModuleStatus(int Slot)
Returns the status of the CAM in the given Slot.
virtual bool HasMMI(void)
Returns 'true' if the CAM in this slot has an active MMI.
virtual ~cCaActivationReceiver()
cCaActivationReceiver(const cChannel *Channel, cCamSlot *CamSlot)
#define MODULE_CHECK_INTERVAL
tChannelID ChannelID(void)
void SetChecked(tChannelID ChannelID, int CamSlotNumber)
virtual const char * GetCamName(void)
Returns the name of the CAM in this slot, or NULL if there is no ready CAM in this slot...
cCiEnquiry * fetchedEnquiry
void ClrDecrypt(int CamSlotNumber)
bool TsIsScrambled(const uchar *p)
cChannelCamRelations ChannelCamRelations
virtual bool Ready(void)
Returns 'true' if the CAM in this slot is ready to decrypt.
void DeleteConnection(void)
cCaPidReceiver * caPidReceiver
virtual void CancelActivation(void)
Cancels a previously started activation (if any).
virtual uchar * Decrypt(uchar *Data, int &Count)
If this is a CAM slot that can be freely assigned to any device, but will not be directly inserted in...
int Priority(void)
Returns the priority of the device this slot is currently assigned to, or IDLEPRIORITY if it is not a...
bool CamChecked(tChannelID ChannelID, int CamSlotNumber)
virtual void StopDecrypting(void)
Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
void ClrChecked(tChannelID ChannelID, int CamSlotNumber)
void AddCaDescriptors(int Length, const uint8_t *Data)
const uint8_t * GetData(const uint8_t *Data, int &Length)
void Reset(int CamSlotNumber)
const int * Spids(void) const
cCiTransportConnection(cCamSlot *CamSlot, uint8_t Tcid)
virtual bool EnterMenu(void)
Requests the CAM in this slot to start its menu.
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
Gets all CA pids for a given channel.
#define ST_CREATE_SESSION_RESPONSE
#define QUERY_REPLY_TIMEOUT
static const uint8_t * GetLength(const uint8_t *Data, int &Length)
bool deleteConnectionRequested
void CloseSession(uint16_t SessionId)
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this adapter to the given Device, if this is possible.
uint8_t buffer[MAX_TPDU_SIZE]
cChannelCamRelation * GetEntry(tChannelID ChannelID)
#define RI_APPLICATION_INFORMATION
bool Assign(cDevice *Device, bool Query=false)
Assigns this CAM slot to the given Device, if this is possible.
virtual void Activate(bool On)
This function is called just before the cReceiver gets attached to (On == true) and right after it ge...
virtual bool IsActivating(void)
Returns true if this CAM slot is currently activating a smart card.
void SendTPDU(uint8_t Tag, int Length=0, const uint8_t *Data=NULL)
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
cChannelCamRelations(void)
void DeleteAllConnections(void)
bool RepliesToQuery(void)
const uint8_t * Data(int &Length)
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
The cDevice class is the base from which actual devices can be derived.
static bool DebugProtocol
virtual void Receive(uchar *Data, int Length)
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc)
cDevice * Device(void)
Returns the device this CAM slot is currently assigned to.
void SetDecrypt(int CamSlotNumber)