summaryrefslogtreecommitdiff
path: root/cesar/maximus/python/lib/proto/fcall.py
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/maximus/python/lib/proto/fcall.py')
-rw-r--r--cesar/maximus/python/lib/proto/fcall.py349
1 files changed, 349 insertions, 0 deletions
diff --git a/cesar/maximus/python/lib/proto/fcall.py b/cesar/maximus/python/lib/proto/fcall.py
new file mode 100644
index 0000000000..8b87c3d07d
--- /dev/null
+++ b/cesar/maximus/python/lib/proto/fcall.py
@@ -0,0 +1,349 @@
+#! usr/bin/env python
+
+#print __name__
+
+SERIAL = 'PYSERIAL'
+#SERIAL = 'USPP'
+
+import sys
+base = '../../../../'
+utils = 'maximus/python/maximus/utils'
+path = __file__[:__file__.find(".py") - len(__name__)] + base + utils
+sys.path.append(path)
+if SERIAL == 'PYSERIAL':
+ serial = 'maximus/python/lib/proto/pyserial'
+elif SERIAL == 'USPP':
+ serial = 'maximus/python/lib/proto/uspp'
+path = __file__[:__file__.find(".py") - len(__name__)] + base + serial
+sys.path.append(path)
+
+from exception import *
+from format import *
+if SERIAL == 'PYSERIAL':
+ import serial
+elif SERIAL == 'USPP':
+ from uspp import *
+
+# Constants from 'maximus/common/types/sci_types.h'
+SCI_MSG_MAGIC = 'MAXI'
+SCI_MSG_VERSION = 0x03
+SCI_MSG_ID_STATION = 0x8000
+SCI_MSG_TYPE_FUNCTION_CALL = 0x02
+SCI_MSG_TYPE_STATION_LOG = 0x06
+SCI_MSG_FLAG_RESP = 0x0001
+SIZE_OF_SCI_MSG_HEADER = 24 # in octets
+
+# Constants from 'maximus/common/types/functioncall_types.h'
+FUNCTION_CALL_VERSION = 0x03
+FUNCTION_CALL_FLAG_FAILED = 0x01
+FUNCTION_CALL_TYPE_REQ = 0x01
+FUNCTION_CALL_TYPE_RSP = 0x02
+SIZE_OF_FUNCTION_CALL_HEADER = 8 # in octets
+
+class Param:
+
+ def __init__(self, name, length, value):
+ self.__name = name
+ self.__length = hton16(length)
+ self.__value = value
+
+ def get_name(self):
+ return self.__name
+
+ def get_value(self):
+ return self.__value
+
+ def get(self):
+ return self.__name + '\0' + self.__length + self.__value
+
+class Fcall:
+ __msg_id = 1
+
+ tty = None
+ for i in range (1, len(sys.argv)):
+ if sys.argv[i] == '-r' or sys.argv[i] == '--rs-232':
+ if i+1 < len(sys.argv):
+ tty = sys.argv[i+1]
+ break
+
+ if SERIAL == 'PYSERIAL':
+ if tty is None:
+ # Open port 0 at "9600,8,N,1", 1s timeout
+ __tty = serial.Serial(0, timeout=1) # open first serial port
+ # Check which port was really used
+ print "Using port:", __tty.portstr
+ else:
+ # Open named port at "9600,8,N,1", 1s timeout
+ __tty = serial.Serial(tty, timeout=1)
+ if not __tty.isOpen():
+ raise Error("Cannot open serial port!")
+ elif SERIAL == 'USPP':
+ if tty is None:
+ tty = '/dev/ttyS0'
+ # Opens RS-232 at 9600 bps and with a read timeout of 1 second
+ __tty = SerialPort(tty, 1000, 9600)
+
+ def __init__(self, name):
+ self.__name = name
+ self.__param_list = []
+ self.__user_cb = None
+
+ def add_param(self, name, value=None):
+ if value is None:
+ value = ''
+ self.__param_list.append(Param(name, len(value), value))
+ return self
+
+ def add_param_bool(self, name, value):
+ self.__param_list.append(Param(name, SIZE_OF_U8, hton8(value)))
+ return self
+
+ def add_param_uchar(self, name, value):
+ self.__param_list.append(Param(name, SIZE_OF_U8, hton8(value)))
+ return self
+
+ def add_param_ushort(self, name, value):
+ self.__param_list.append(Param(name, SIZE_OF_U16, hton16(value)))
+ return self
+
+ def add_param_ulong(self, name, value):
+ self.__param_list.append(Param(name, SIZE_OF_U32, hton32(value)))
+ return self
+
+ def add_param_n_u8(self, name, tuple):
+ value = ''
+ for t in tuple:
+ value += hton8(t)
+ self.__param_list.append(Param(name, SIZE_OF_U8 * len(value), value))
+ return self
+
+ def add_param_n_u16(self, name, tuple):
+ value = ''
+ for t in tuple:
+ value += hton16(t)
+ self.__param_list.append(Param(name, SIZE_OF_U16 * len(value), value))
+ return self
+
+ def add_param_n_u32(self, name, tuple):
+ value = ''
+ for t in tuple:
+ value += hton32(t)
+ self.__param_list.append(Param(name, SIZE_OF_U32 * len(value), value))
+ return self
+
+ def remove_param(self, name):
+ for i in range (0, len(self.__param_list)):
+ if self.__param_list[i].get_name() == name:
+ self.__param_list.pop(i)
+ break
+ return self
+
+ def set_cb(self, user_cb):
+ self.__user_cb = user_cb
+ return self
+
+ def remove_cb(self):
+ self.__user_cb = None
+ return self
+
+ def set_sta(self, sta):
+ return self
+
+ def send_async(self, sta=None):
+ self.__write()
+ self.__read()
+ if self.__user_cb is not None:
+ self.__user_cb(self)
+
+ def send(self, sta=None):
+ self.__write()
+ return self.__read()
+
+ def is_param(self, name):
+ found = False
+ for l in self.__param_list:
+ if l.get_name() == name:
+ found = True
+ return found
+
+ def bind_param(self, name):
+ param = None
+ for l in self.__param_list:
+ if l.get_name() == name:
+ param = l.get_value()
+ break
+ return param
+
+ def bind_param_string(self, name):
+ param = None
+ for l in self.__param_list:
+ if l.get_name() == name:
+ param = l.get_value()
+ if param[len(param)-1] == '\0':
+ param = param[:-1]
+ break
+ return param
+
+ def bind_param_bool(self, name):
+ param = None
+ for l in self.__param_list:
+ if l.get_name() == name:
+ param = ntoh8(l.get_value())
+ break
+ return param
+
+ def bind_param_ushort(self, name):
+ param = None
+ for l in self.__param_list:
+ if l.get_name() == name:
+ param = ntoh16(l.get_value())
+ break
+ return param
+
+ def bind_param_ulong(self, name):
+ param = None
+ for l in self.__param_list:
+ if l.get_name() == name:
+ param = ntoh32(l.get_value())
+ break
+ return param
+
+ def __get(self):
+ if self.__class__.__msg_id < 0x7FFF:
+ self.__class__.__msg_id += 1
+ else:
+ self.__class__.__msg_id = 0x0001
+
+ # FCALL data
+ fcall_data = self.__name + '\0'
+ for l in self.__param_list:
+ fcall_data += l.get()
+
+ # FCALL header
+ # uint8_t version
+ # uint8_t type
+ # uint16_t msg_id
+ # uint8_t param_nb
+ # uint8_t flags
+ # uint16_t reserved
+ fcall_hdr = hton8(FUNCTION_CALL_VERSION)\
+ + hton8(FUNCTION_CALL_TYPE_REQ)\
+ + hton16(self.__class__.__msg_id)\
+ + hton8(len(self.__param_list))\
+ + hton8(0)\
+ + hton16(0)
+
+ # SCI header
+ # uint32_t magic_id
+ # uint8_t version
+ # uint8_t type
+ # uint16_t length
+ # uint16_t station_id
+ # uint16_t msg_id
+ # uint32_t netclock_high
+ # uint32_t netclock_low
+ # uint16_t flags
+ # uint16_t reserved
+ sci_hdr = SCI_MSG_MAGIC\
+ + hton8(SCI_MSG_VERSION)\
+ + hton8(SCI_MSG_TYPE_FUNCTION_CALL)\
+ + hton16(len(fcall_hdr + fcall_data))\
+ + hton16(0)\
+ + hton16(self.__class__.__msg_id)\
+ + hton32(0)\
+ + hton32(0)\
+ + hton16(0)\
+ + hton16(0)
+
+ return sci_hdr + fcall_hdr + fcall_data
+
+ def __write(self):
+ # Writes a string to the RS-232 port
+ self.__class__.__tty.write(self.__get())
+
+ def __read(self):
+ fcall = None
+
+ # SCI header
+ sci_hdr = self.__class__.__tty.read(SIZE_OF_SCI_MSG_HEADER) # read up to 24 bytes (timeout)
+ if sci_hdr[0:4] != SCI_MSG_MAGIC: # uint32_t magic_id
+ print "SCI header:"
+ print "magic id =", hex(ntoh32(sci_hdr[0:4]))
+ print "version =", hex(ntoh8(sci_hdr[4]))
+ print "type =", hex(ntoh8(sci_hdr[5]))
+ print "length =", hex(ntoh16(sci_hdr[6:8]))
+ print "station id =", hex(ntoh16(sci_hdr[8:10]))
+ print "msg id =", hex(ntoh16(sci_hdr[10:12]))
+ print "netclock high =", hex(ntoh32(sci_hdr[12:16]))
+ print "netclock low =", hex(ntoh32(sci_hdr[16:20]))
+ print "flags =", hex(ntoh16(sci_hdr[20:22]))
+ print "reserved =", hex(ntoh16(sci_hdr[22:24]))
+ raise Error("SCI header: bad magic id! (" + sci_hdr[0:4] + ")")
+ if ntoh8(sci_hdr[4]) != SCI_MSG_VERSION: # uint8_t version
+ raise Error("SCI header: bad version! (" + hex(ntoh8(sci_hdr[4])) + ")")
+ if ntoh8(sci_hdr[5]) == SCI_MSG_TYPE_FUNCTION_CALL: # uint8_t type
+ length = ntoh16(sci_hdr[6:8]) # uint16_t length
+
+ # FCALL header
+ fcall_hdr = self.__class__.__tty.read(SIZE_OF_FUNCTION_CALL_HEADER) # read up to 8 bytes (timeout)
+ if ntoh8(fcall_hdr[0]) != FUNCTION_CALL_VERSION: # uint8_t version
+ raise Error("FCALL header: bad version! (" + hex(ntoh8(fcall_hdr[0])) + ")")
+ if ntoh8(fcall_hdr[1]) != FUNCTION_CALL_TYPE_RSP: # uint8_t type
+ raise Error("FCALL header: bad type! (" + hex(ntoh8(fcall_hdr[1])) + ")")
+ ntoh16(fcall_hdr[2:4]) # uint16_t msg_id
+ param_nb = ntoh8(fcall_hdr[4]) # uint8_t param_nb
+ if ntoh8(fcall_hdr[5]) >= FUNCTION_CALL_FLAG_FAILED: # uint8_t flags
+ raise Error("FCALL header: flag failed! (" + hex(ntoh8(fcall_hdr[5])) + ")")
+ length -= SIZE_OF_FUNCTION_CALL_HEADER
+
+ # FCALL data
+ name = self.__read_name()
+ fcall = Fcall(name)
+ length -= len(name) + 1
+ for n in range(0, param_nb):
+ param_name = self.__read_param_name()
+ param_length = self.__read_param_length()
+ param_value = self.__read_param_value(param_length)
+ fcall.__param_list.append(Param(param_name, param_length, param_value))
+ length -= len(param_name) + 1 + SIZE_OF_U16 + param_length
+
+ if length != 0:
+ raise Error("length = " + str(length))
+
+ elif ntoh8(sci_hdr[5]) == SCI_MSG_TYPE_STATION_LOG: # uint8_t type
+ print self.__class__.__tty.readline() # read a '\n' terminated line
+ else:
+ raise Error("SCI header: bad type! (" + hex(ntoh8(sci_hdr[5])) + ")")
+
+ ntoh16(sci_hdr[8:10]) # uint16_t station_id
+ if ntoh16(sci_hdr[10:12]) < SCI_MSG_ID_STATION: # uint16_t msg_id
+ raise Error("SCI header: bad msg id! (" + hex(ntoh16(sci_hdr[10:12])) + ")")
+ ntoh32(sci_hdr[12:16]) # uint32_t netclock_high
+ ntoh32(sci_hdr[16:20]) # uint32_t netclock_low
+ if ntoh16(sci_hdr[20:22]) != SCI_MSG_FLAG_RESP: # uint16_t flags
+ raise Error("SCI header: bad flags! (" + hex(ntoh16(sci_hdr[20:22])) + ")")
+
+ return fcall
+
+ def __read_name(self):
+ name = ''
+ c = self.__class__.__tty.read() # read one byte
+ while c != '\0':
+ name += c
+ c = self.__class__.__tty.read() # read one byte
+ return name
+
+ def __read_param_name(self):
+ return self.__read_name()
+
+ def __read_param_length(self):
+ return ntoh16(self.__class__.__tty.read(2))
+
+ def __read_param_value(self, length):
+ return self.__class__.__tty.read(length)
+
+def create_fcall(name):
+ return Fcall(name)
+
+def create_probe():
+ return Fcall('probe')