From 4c6b25b96807b5da63685854acd005795898744d Mon Sep 17 00:00:00 2001
From: James Meyer <james.meyer@operamail.com>
Date: Wed, 23 Jan 2013 17:49:37 -0600
Subject: LinHES-config:  autocard.py and discover_infinitv.py   Modifications
 to allow autocard to detect and setup both pci and usb based infinitv 
 tuners.   This will also setup the network configuration for the ctnX/usbX if
 the interface is found  but not configured.

refs #899
---
 abs/core/LinHES-config/PKGBUILD             |  11 +-
 abs/core/LinHES-config/autocard.py          | 287 ++++++++++++++++++++++------
 abs/core/LinHES-config/discover_infinitv.py |  84 ++++++++
 3 files changed, 316 insertions(+), 66 deletions(-)
 create mode 100755 abs/core/LinHES-config/discover_infinitv.py

diff --git a/abs/core/LinHES-config/PKGBUILD b/abs/core/LinHES-config/PKGBUILD
index 2c4999c..df3bbb6 100755
--- a/abs/core/LinHES-config/PKGBUILD
+++ b/abs/core/LinHES-config/PKGBUILD
@@ -1,6 +1,6 @@
 pkgname=LinHES-config
 pkgver=2.3
-pkgrel=208
+pkgrel=211
 conflicts=(MythVantage-config MythVantage-config-dev LinHES-config-dev LinHes-config )
 pkgdesc="Install and configure your system"
 depends=('bc' 'libstatgrab'  'mysql-python' 'expect' 'curl' 'dnsutils' 'parted'
@@ -53,7 +53,8 @@ source=(mv_install.py 09_mythvantge_runit_grub
 	config-sudo.rules
 	hdhr.conf blacklist_nouveau.conf  blacklist_pcspkr.conf
 	print_xorg_res.py backend_control.sh
-	plymouth_config.py )
+	plymouth_config.py
+	discover_infinitv.py)
 
 backup=(etc/mythvantage.cfg)
 install=config.install
@@ -107,6 +108,7 @@ build() {
     install -m 0755 systemconfig.py $MVDIR/bin/
     install -m 0755 print_xorg_res.py $MVDIR/bin/
     install -m 0755 plymouth_config.py $MVDIR/bin/
+    install -m 0755 discover_infinitv.py $MVDIR/bin/
     install -m 0755 backend_control.sh $MVDIR/bin/
     install -m 0755 mythvantage.cfg $startdir/pkg/etc/
 
@@ -150,7 +152,7 @@ md5sums=('32fc2b52809231d75a72492b91eeed74'
          'ab2aa42c2947148c2b1cac0ade6d1d55'
          'd429b59d3cfb37b0624c6a4a71a7c2c0'
          'f6a935c35123fdc7c259c01cbc794a64'
-         'cd03c0f179f756665ff7750e234ac02a'
+         'd318046ff657ddec6f701bb9f52e9cce'
          'd3490e93f313bbbcbc6c3693c56b9c17'
          '3d1e4a119f38cff0498bf8a67e94e4b3'
          '71fd2d0d448fc2fcd15415a1beed7109'
@@ -178,4 +180,5 @@ md5sums=('32fc2b52809231d75a72492b91eeed74'
          '3866086e6af5e3528a66eff492f2f4dd'
          'c9279fa095af624ee3d9bc75d3328360'
          '02cf69074d2bbacef05fa3e451af9af3'
-         '85d15efc55074a94c58d44542ea1dd13')
+         '85d15efc55074a94c58d44542ea1dd13'
+         'e410d108ed4778dd898dc68fad4e8828')
diff --git a/abs/core/LinHES-config/autocard.py b/abs/core/LinHES-config/autocard.py
index 8b70465..48b6e06 100644
--- a/abs/core/LinHES-config/autocard.py
+++ b/abs/core/LinHES-config/autocard.py
@@ -1,7 +1,4 @@
 #!/usr/bin/python2
-# import MySQL module
-#jm
-import MySQLdb
 import sys
 import getopt
 import socket
@@ -13,14 +10,9 @@ from string import letters
 from string import digits
 from xml.dom.minidom import parseString
 import errno, fcntl
-import urllib2,urllib
-#from httplib import HTTP
-#from urlparse import urlparse
-#http://code.activestate.com/recipes/576891/
-
-
-
+import urllib2,urllib,json
 
+#http://code.activestate.com/recipes/576891/
 
 class ApplicationLock:
     '''
@@ -89,7 +81,6 @@ class ApplicationLock:
             # lockfile can be erased and everything still works normally.
             pass
 #------- START OF TUNER CLASSES-----------
-
 class v4l_tuners():
     def __init__(self, device):
         self.device = device
@@ -395,7 +386,6 @@ class hdhr_tuners():
 
 
 #-----
-
 class dvb_tuners():
     def __init__(self, device):
         self.device = device
@@ -408,8 +398,6 @@ class dvb_tuners():
         self.udev_rule = self.create_udev_rule()
         #self.staticdevice is set in create_udev_rule
 
-
-
     def find_description(self):
         command = '/usr/bin/dvb-fe-tool  -g -a %s' %self.dvb_number
         results=os.popen(command,'r')
@@ -531,6 +519,7 @@ class dvb_tuners():
             'signal_timeout'  :'1000',
             'channel_timeout' :'12000',
             'diseqcid'        :'NULL',
+            'dvb_on_demand'   :'0',
             'dvb_eitscan'     :'1'
             }
         return values
@@ -563,6 +552,129 @@ class dvb_tuners():
 
     def get_static_device(self):
         return self.staticdevice
+#--
+class infinitv_tuner():
+    def __init__(self, tuner_number,ip):
+        self.tuner_number = tuner_number
+        self.ip = ip
+        self.serial_num = self.find_serial()
+        self.connection = self.find_connection()
+        self.description = self.find_description()
+        self.staticdevice = self.find_static()
+
+    def find_static(self):
+        static="%s-RTP.%s" %(self.ip,self.tuner_number)
+        return static
+
+    def find_connection(self):
+        uri='get_var.json?i=0&s=diag&v=Host_Connection'
+        try:
+            url="http://%s/%s" %(self.ip,uri)
+            req = urllib2.Request(url)
+            r = urllib2.urlopen(req).read()
+            response = r.split()[2].strip('''"''')
+        except:
+            response='unknown'
+        return response
+
+    def find_serial(self):
+        uri='get_var.json?i=0&s=diag&v=Host_Serial_Number'
+        try:
+            url="http://%s/%s" %(self.ip,uri)
+            req = urllib2.Request(url)
+            r = urllib2.urlopen(req).read()
+            response = r.split()[2].strip('''"''')
+        except:
+            response='unknown'
+        return response
+
+    def find_description(self):
+        desc="Ceton InfiniTV %s Tuner %s" %(self.connection,
+                                            self.tuner_number)
+        return desc
+
+    def do_insert(self):
+        try:
+            header = { 'User-Agent' : "autocard" }
+            url="http://127.0.0.1:6544/Capture/AddCaptureCard/"
+            values = self.card_ceton_values()
+            data = urllib.urlencode(values)
+            req = urllib2.Request(url, data, header)
+            self.response = urllib2.urlopen(req)
+        except:
+            print "    **Insert of %s failed" %self.staticdevice
+
+    def card_ceton_values(self):
+        values = {
+            'CardType'     : 'CETON' ,
+            'VideoDevice'  : self.staticdevice,
+            'Defaultinput' : 'Television',
+            'HostName'     : self.localhostname,
+            'dvb_wait_for_seqstart' :'1',
+            'signal_timeout'  :'1000',
+            'channel_timeout' :'3000',
+            'diseqcid'        :'NULL',
+            'dvb_eitscan'     :'1'
+            }
+        return values
+
+    def insert_myth(self,myth_tuner_list):
+        if self.staticdevice in myth_tuner_list:
+            print "    *infinitv %s already in mythtdb" %self.staticdevice
+        else:
+            print "    Inserting Ceton InfinitTV Tuner %s" %self.staticdevice
+            self.do_insert()
+        return
+
+    def write_proxy(self):
+        directory="/etc/ceton_proxy.d"
+        if not os.path.exists(directory):
+            os.makedirs(directory)
+        proxy_file = "%s/%s" %(directory,self.get_proxy_num())
+        try:
+            f = open(proxy_file,'w')
+            line="port=%s\n" %(self.get_proxy_num())
+            f.write(line)
+            line="ip=%s\n" %(self.ip)
+            f.write(line)
+        except:
+            print "    *Problem creating proxy file %s" %proxy_file
+        return
+
+    def get_static_device(self):
+        return self.staticdevice
+
+    def get_tuner_hash(self):
+        return self.staticdevice
+
+    def set_proxy(self,proxy_num):
+        self.proxy_num = 7000 + proxy_num
+        return
+
+    def set_hostname(self,hostname):
+        self.localhostname = hostname
+        return
+
+    def set_tuner_index(self,index):
+        #only used by dvb, but here to be complete
+        self.tuner_index = index
+        return
+    def get_proxy_num(self):
+        return self.proxy_num
+
+    def get_udev_rule(self):
+        return
+
+    def get_card_type(self):
+        return "infinitv"
+
+    def get_description(self):
+        desc = "%s -  %s"  %(self.description,self.ip)
+        return desc
+
+    def get_serial_number(self):
+        return self.serial_num
+#-- end infinitv
 
 #------------------END TUNER CLASSES-----------------------
 
@@ -641,15 +753,83 @@ def gather_dvb(tuner_list):
     except:
          print "no dvb cards found"
     return tuner_list
+
+def gather_ceton(tuner_list):
+    #find and configure ctn network interfaces
+    ceton_network_list = find_ceton_network_list()
+
+    #find all the cards on a network interface
+    for iface in ceton_network_list:
+        #command="cat /tmp/find_ceton.txt"
+        print "Scanning %s network for ceton infinitv" %iface
+        command="/root/discover_infinitv.py %s" %iface
+        results=os.popen(command,'r')
+        lines=results.readlines()
+        #try:
+        if lines[0].strip().split()[0] == "no":
+            print "Ceton not detected"
+        else:
+            for line in lines:
+                #Found InfiniTV. Location URL: http://192.168.200.1/description.xml
+                #cetondevice = line.strip().split()[0]
+                cetonip = line.strip().split("/")[2]
+
+                tuners = [1,2,3,4]
+                for t in tuners:
+                    tuner_list.append(infinitv_tuner(t,cetonip))
+        #except:
+        #    print "Error finding Ceton InfinitTV"
+
+    return tuner_list
+
 #------------------END OF TUNER GATHERING-----------------
+#----linhes specific for networking
+def config_ctn_network(ctn_iface):
+    etcnetdir = "/etc/net/ifaces/%s" %ctn_iface
+    if not os.path.exists(etcnetdir):
+        print "Creating config for interface %s" %ctn_iface
+        os.mkdir(etcnetdir)
+        outline='''
+TYPE=eth
+DISABLED=no
+BOOTPROTO=dhcp
+ONBOOT=yes
+CONFIG_WIRELESS=no
+DHCP_ARGS="-C resolv.conf"
+        '''
+        optionfile="%s/options" %etcnetdir
+        f = open(optionfile, 'w')
+        f.write(outline)
+        f.close()
+        command="/etc/net/scripts/network.init start"
+        os.system(command)
+    else:
+        pass #config is present
+
+
+def find_ceton_network_list():
+    import netifaces
 
+    netinterfaces = netifaces.interfaces()
+    ctnip=[]
+    for i in netinterfaces:
+        if i.startswith("ctn") or i.startswith("usb"):
+            #configure and start ctn network
+            config_ctn_network(i)
+
+            #read ip
+            ctnip.append(netifaces.ifaddresses(i)
+                        [netifaces.AF_INET][0]['addr'])
+    return ctnip
+
+#--end of linhes specific
 
 def gather_tuners():
     tuner_list = []
     tuner_list = gather_hdhr(tuner_list)
     tuner_list = gather_v4l(tuner_list)
     tuner_list = gather_dvb(tuner_list)
-    #tuner_list = gather_ceton(tuner_list)
+    tuner_list = gather_ceton(tuner_list)
     #set the number of times we have seen a specific tuner_hash
     #This will be used by dvb when tuner_hashs conflict
     tuner_count = {}
@@ -660,47 +840,6 @@ def gather_tuners():
         else:
             tuner_count[th] = 1
         i.set_tuner_index(tuner_count[th])
-
-        #if i.get_card_type() == "hdhr":
-            #pass
-            #print "hdhr : %s " %(i.get_dev_node())
-            #print "\t" , i.get_description()
-
-
-        #elif i.get_card_type() == "v4l":
-            #pass
-
-            #print "V4L : %s " %(i.get_dev_node())
-            #print "\t" , i.get_description()
-            ##print "\t" , i.get_udev_probs()
-            #print "\t" , i.get_tuner_hash()
-            ##print "\t" , i.get_udev_rule()
-            ##print "\t" , i.get_full_udev_attribs()
-
-
-        #elif i.get_card_type() == "v4l_hdpvr":
-            #pass
-            #print "hdpvr : %s " %(i.get_dev_node())
-            #print "\t" , i.get_description()
-            ##print "\t" , i.get_udev_probs()
-            #print "\t" , i.get_tuner_hash()
-            ##print "\t" , i.get_udev_rule()
-            ##print "\t" , i.get_full_udev_attribs()
-
-        #elif i.get_card_type() == "dvb":
-            #pass
-            #print "dvb : %s " %(i.get_dev_node())
-            #print "\t" , i.get_description()
-            #print "\t" , i.get_tuner_hash()
-            ##print "\t" , i.get_full_udev_attribs()
-            ##for y in i.get_full_udev_attribs():
-            ##    print y
-            ##print "\t" , i.get_udev_rule()
-
-        #elif i.get_card_type() == "ceton":
-            #print "ceton : %s " %(i.get_dev_node())
-        #else:
-            #print i
     return tuner_list
 
 def trigger_udev():
@@ -712,8 +851,6 @@ def trigger_udev():
     command = '/usr/bin/udevadm trigger'
     results=os.popen(command,'r')
 
-
-
 def write_udev_file(rule_list):
     udevfile = '/etc/udev/rules.d/99-mv-persistent-video.rules'
     try:
@@ -755,7 +892,6 @@ def write_udev_map(tuner_list):
                 f.write("\n")
             elif i.get_card_type() == "v4l_hdpvr":
                 pass
-                #line="hdpvr:%s:/dev/vstatic/%s " %(i.get_description(),i.get_tuner_hash())
                 line="hdpvr:%s: %s " %(i.get_description(),i.get_static_device())
                 f.write(line)
                 f.write("\n")
@@ -763,8 +899,10 @@ def write_udev_map(tuner_list):
                 line="dvb:%s: %s " %(i.get_description(),i.get_static_device())
                 f.write(line)
                 f.write("\n")
-            elif i.get_card_type() == "ceton":
-                line="ceton:%s:/dev/vstatic/%s " %(i.get_description(),i.get_tuner_hash())
+            elif i.get_card_type() == "infinitv":
+                line="infinitv:%s:%s:%s" %(i.get_description(),
+                                           i.get_static_device(),
+                                           i.get_proxy_num())
                 f.write(line)
                 f.write("\n")
             else:
@@ -840,7 +978,8 @@ def usuage():
     insertdb :  This option will insert any detected cards into the MythTV database using the static device generated by udev.
                 This option will also generate udev rules.  Tuners that are already defined will not be readded.
 
-    all  :  The same as using  print udev insertdb
+    write_proxy:  This will write out the config used by the service ceton_proxy
+    all  :  The same as using  print udev insertdb write_proxy
 
 
     EX:
@@ -853,6 +992,7 @@ def main(argv):
     listcards = False
     udev = False
     insertdb = False
+    write_proxy = False
 
     if argv==[] or "help" in argv:
         usuage()
@@ -863,21 +1003,31 @@ def main(argv):
 
     if "udev" in argv:
         udev = True
+        write_proxy = True
 
     if "insertdb" in argv:
         insertdb = True
         udev = True
 
+    if "write_proxy" in argv:
+        write_proxy = True
 
     if "all" in argv:
         udev = True
         insertdb = True
         listcards = True
+        write_proxy = True
 
     tuner_list = gather_tuners()
     rule_list = []
 
+    #setting the proxy port for ceton webpage
+    ceton_proxy = 0
     for i in tuner_list:
+        if i.get_card_type() == "infinitv":
+            ceton_proxy = ceton_proxy + 1
+            i.set_proxy(ceton_proxy)
+
         #setting the hostname for each tuner
         i.set_hostname(localhostname)
         rule_list.append(i.get_udev_rule())
@@ -891,6 +1041,19 @@ def main(argv):
     print("Writing out tuner map")
     write_udev_map(tuner_list)
 
+    restart_proxy=False
+    if write_proxy == True:
+
+        for i in tuner_list:
+            if i.get_card_type() == "infinitv":
+                i.write_proxy()
+                restart_proxy=True
+
+    if restart_proxy == True:
+        print" Restarting ceton proxy"
+        command="sv restart cetonproxy"
+        os.system(command)
+
     if udev == True:
         print("Writing out udev rules")
         write_udev_file(rule_list)
diff --git a/abs/core/LinHES-config/discover_infinitv.py b/abs/core/LinHES-config/discover_infinitv.py
new file mode 100755
index 0000000..5c39c59
--- /dev/null
+++ b/abs/core/LinHES-config/discover_infinitv.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python2
+#   Program to detect Ceton InfiniTV tuners on the network
+#   Program will only listen on a specific interface for a set amount of time.
+#   If during that time it finds a device it will print out the location.
+#   discover_infinitv $ip $timeout
+#   ex:  discover_infinitv 192.168.200.2
+
+import socket
+import thread
+import time,sys
+
+
+class find_the_infiniTV(object):
+
+    def __init__(self,UPNP_GROUP="239.255.255.250", UPNP_PORT=1900, interface_ip='127.0.0.1'):
+        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        sock.bind(('', UPNP_PORT))
+        mreq = socket.inet_aton(UPNP_GROUP)+socket.inet_aton(interface_ip)
+        sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
+        self.sock=sock
+        self.devices = {}
+        self.emit_msearch()
+
+    def emit_msearch(self):
+        msearch_string = 'M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: "ssdp:discover"\r\nMX: 2\r\nST: urn:schemas-upnp-org:device:MediaRenderer:1\r\n\r\n'
+        msearch_encoded_string = msearch_string.encode()
+        self.sock.sendto( msearch_encoded_string,  ('239.255.255.250', 1900 ) )
+
+      # Internally used method to read a notification
+    def _listen_notification(self, data):
+        upnp_header, upnp_body = data.split("\r\n\r\n")
+
+        # Get header by line -- as fragments
+        upnp_hfrags = upnp_header.split("\r\n")
+        upnp_hfrags.pop(0)
+
+        header = {}
+
+        for frag in upnp_hfrags:
+            splitpoint = frag.find(": ")
+            header[frag[:splitpoint]] = frag[splitpoint+2:]
+
+        if("USN" in header):
+            if("CetonFactory" in header["USN"]):
+                if(header["USN"] not in self.devices):
+                    self.devices[header["USN"]] = header["USN"]
+                    print("Found InfiniTV. Location URL: {0}".format(header["LOCATION"]))
+
+
+    def listen(self):
+        import select
+        self.listening = True
+        while self.listening:
+            upnp_data = self.sock.recv(10240).decode('utf-8')
+            #Filter by type (we only care about NOTIFY for now)
+            if(upnp_data[0:6] == "NOTIFY"):
+               self._listen_notification(upnp_data)
+
+    def stop_listen(self):
+        self.listening = False
+        if len(self.devices) == 0:
+            print "No InfiniTV found"
+
+
+if __name__ == "__main__":
+    # Create a default UPnP socket
+    try:
+        interface_ip=sys.argv[1]
+    except:
+        print "detect_infinitv $ip_address"
+        sys.exit(1)
+
+    try:
+        timeout = float(sys.argv[2])
+    except:
+        timeout=5
+    L = find_the_infiniTV(interface_ip=interface_ip)
+    thread.start_new_thread(L.listen, ())
+    time.sleep(timeout)
+    L.stop_listen()
+
+
+
-- 
cgit v0.12

