SASC
DVBSoftCAM

gbox.c

Go to the documentation of this file.
00001 /* 
00002  * Softcam plugin to VDR (C++) 
00003  * 
00004  * This code is free software; you can redistribute it and/or 
00005  * modify it under the terms of the GNU General Public License 
00006  * as published by the Free Software Foundation; either version 2 
00007  * of the License, or (at your option) any later version. 
00008  * 
00009  * This code is distributed in the hope that it will be useful, 
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
00012  * GNU General Public License for more details. 
00013  * 
00014  * You should have received a copy of the GNU General Public License 
00015  * along with this program; if not, write to the Free Software 
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
00017  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 
00018  *
00019  * This code is based on morfsta's version but has been rewritten nearly
00020  * from scratch.
00021  * 
00022  * To get it working ensure that GBOX is running with no F: { 01 } line,
00023  * and no pmt.tmp file in /var/tmp.
00024  */ 
00025 
00026 #include <stdio.h>
00027 
00028 #include <vdr/pat.h>
00029 
00030 #include "cc.h" 
00031 #include "parse.h"
00032 
00033 // -- cGboxClient ----------------------------------------------------------- 
00034  
00035 class cCardClientGbox : public cCardClient { 
00036 private: 
00037   int GetMsg(int cmd, unsigned char *buff, int len);
00038 public: 
00039   cCardClientGbox(const char *Name); 
00040   virtual bool Init(const char *CfgDir); 
00041   virtual bool Login(void);
00042   virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw);
00043   }; 
00044  
00045 static cCardClientLinkReg<cCardClientGbox> __ncd("gbox");
00046 
00047 cCardClientGbox::cCardClientGbox(const char *Name)
00048 :cCardClient(Name)
00049 {
00050   so.SetRWTimeout(2*1000);
00051   so.SetUDP(true);
00052 }
00053 
00054 bool cCardClientGbox::Init(const char *config) 
00055 { 
00056   cMutexLock lock(this); 
00057   Logout();
00058   int num=0;
00059   if(!ParseStdConfig(config,&num)) return false;
00060   return true;
00061 } 
00062  
00063 bool cCardClientGbox::Login(void) 
00064 { 
00065   Logout();
00066   if(!so.Bind("127.0.0.1",8003)) return false;
00067   return true;
00068 } 
00069 
00070 int cCardClientGbox::GetMsg(int cmd, unsigned char *buff, int len)
00071 {
00072   int n;
00073   do {
00074     n=so.Read(buff,-len);
00075     } while(n>0 && buff[0]!=cmd);
00076   return n;
00077 }
00078 
00079 bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
00080 {
00081   cMutexLock lock(this);
00082   if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false;
00083   so.Flush();
00084 
00085   const int caid=ecm->caId;
00086   const int pid =ecm->ecm_pid;
00087   int n;
00088   const unsigned char *descr=ecm->GetCaDescr(&n);
00089   if(!descr) {
00090     PRINTF(L_CC_GBOX,"no CA descriptor for caid %04x sid %d prov %04x",caid,ecm->prgId,ecm->provId);
00091     return false;
00092     }
00093 
00094   static const unsigned char pmt[] = {
00095     0x87,
00096     0x02,0xb0,0x25,     // tid, sct len
00097     0x17,0x74,          // sid
00098     0xc3,0x00,0x00,     // vers, sctnr
00099     0xff,0xec,          // pcr pid
00100     0xf0,0x00,          // prg info len
00101     0x02, 0xff,0xec, 0xf0,0x00
00102     };
00103   unsigned char buff[512];
00104   if(sizeof(pmt)+n+8>sizeof(buff)) {
00105     PRINTF(L_CC_GBOX,"CA descriptor buffer overflow %d",sizeof(pmt)+n+8);
00106     return false;
00107     }
00108   memcpy(buff,pmt,sizeof(pmt));
00109   buff[4]=ecm->prgId >> 8;
00110   buff[5]=ecm->prgId & 0xFF;
00111   memcpy(&buff[sizeof(pmt)],descr,n);
00112   buff[16]=0xF0 | ((n>>8)&0x0F);
00113   buff[17]=n & 0xFF;
00114   SetSctLen(&buff[1],sizeof(pmt)-4+n+4);
00115   buff[2]=(buff[2]&0x0F)|0xB0;
00116 
00117   if(so.SendTo("127.0.0.1",8004,buff,sizeof(pmt)+n+4)<0) {
00118     PRINTF(L_CC_GBOX,"failed to send PMT data. GBOX running?");
00119     return false;
00120     }
00121 
00122   if((n=GetMsg(0x8a,buff,sizeof(buff)))<0) {
00123     PRINTF(L_CC_GBOX,"failed to get ECM port. GBOX running?");
00124     return false;
00125     }
00126   int pidnum=-1;
00127   if(n>=2) {
00128     for(int i=0 ; i<buff[1]; i++) {
00129       if(WORD(buff,2+i*2,0x1FFF)==pid) {
00130         pidnum=i;
00131         break;
00132         }
00133       }
00134     }
00135   if(pidnum<0) {
00136     PRINTF(L_CC_ECM,"%s: unable to decode for CAID %04X/PID %04X",name,caid,pid);
00137     return false;
00138     }
00139 
00140   n=SCT_LEN(data);
00141   if(n>=256) {
00142     PRINTF(L_CC_ECM,"%s: ECM section too long %d > 255",name,n);
00143     return false;
00144     }
00145   buff[0]=0x88;
00146   buff[1]=(pid>>8)&0x1F;
00147   buff[2]=pid & 0xFF;
00148   buff[3]=n;
00149   memcpy(&buff[4],data,n);
00150   n+=4;
00151   if(so.SendTo("127.0.0.1",8005+pidnum,buff,n)<0) {
00152     PRINTF(L_CC_GBOX,"failed to send ECM data. GBOX running?");
00153     return false;
00154     }
00155 
00156   if(GetMsg(0x89,buff,sizeof(buff))<0) {
00157     PRINTF(L_CC_GBOX,"failed to get CW. GBOX running?");
00158     return false;
00159     }
00160   if(n<17) {
00161     PRINTF(L_CC_GBOX,"bad CW answer from GBOX");
00162     return false;
00163     }
00164   memcpy(cw,&buff[1],16);
00165   return true;
00166 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines